Trying to fix profile dashboard timestamps.
This commit is contained in:
@@ -17,6 +17,18 @@ app = FastAPI(
|
|||||||
# Define templates EARLY (before importing dashboard)
|
# Define templates EARLY (before importing dashboard)
|
||||||
templates = Jinja2Templates(directory=BASE_DIR / "templates")
|
templates = Jinja2Templates(directory=BASE_DIR / "templates")
|
||||||
|
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
|
@templates.env.filters.register
|
||||||
|
def timestamp_to_date(ts):
|
||||||
|
if ts is None:
|
||||||
|
return "Never"
|
||||||
|
try:
|
||||||
|
dt = datetime.fromtimestamp(float(ts), tz=timezone.utc)
|
||||||
|
return dt.strftime("%Y-%m-%d %H:%M:%S UTC")
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
return "Invalid"
|
||||||
|
|
||||||
# Static files
|
# Static files
|
||||||
app.mount("/static", StaticFiles(directory=BASE_DIR / "static"), name="static")
|
app.mount("/static", StaticFiles(directory=BASE_DIR / "static"), name="static")
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,8 @@
|
|||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr><th>HTTP Enabled</th><td>{% if profile.http_enabled %}<span class="text-success">Yes</span>{% else %}<span class="text-danger">No</span>{% endif %}</td></tr>
|
<tr><th>HTTP Enabled</th><td>{% if profile.http_enabled %}<span class="text-success">Yes</span>{% else %}<span class="text-danger">No</span>{% endif %}</td></tr>
|
||||||
<tr><th>RF Gateway Enabled</th><td>{% if profile.rf_enabled %}<span class="text-success">Yes</span>{% else %}<span class="text-warning">No (blacklisted)</span>{% endif %}</td></tr>
|
<tr><th>RF Gateway Enabled</th><td>{% if profile.rf_enabled %}<span class="text-success">Yes</span>{% else %}<span class="text-warning">No (blacklisted)</span>{% endif %}</td></tr>
|
||||||
<tr><th>HTTP Account Created</th><td>{{ profile.http_created_at }}</td></tr>
|
<tr><th>HTTP Account Created</th><td>{{ profile.http_created_at | timestamp_to_date }}</td></tr>
|
||||||
<tr><th>Last HTTP Login</th><td>{{ profile.http_last_login or "Never" }}</td></tr>
|
<tr><th>Last HTTP Login</th><td>{{ profile.http_last_login | timestamp_to_date or "Never" }}</td></tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -91,6 +91,11 @@ def main():
|
|||||||
p_dump = subparsers.add_parser("dump", help="Dump JSON details of the BBS user (incl. UUID and hidden flag)")
|
p_dump = subparsers.add_parser("dump", help="Dump JSON details of the BBS user (incl. UUID and hidden flag)")
|
||||||
p_dump.add_argument("callsign", help="Callsign to dump")
|
p_dump.add_argument("callsign", help="Callsign to dump")
|
||||||
|
|
||||||
|
# sync missing
|
||||||
|
p_sync = subparsers.add_parser("sync-missing", help="Add missing HttpUser objects for existing BBS users")
|
||||||
|
p_sync.add_argument("--dry-run", action="store_true", help="Show what would be done without changes")
|
||||||
|
p_sync.add_argument("--enable", action="store_true", help="Set http_enabled=True for new users (default False)")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# Open the database
|
# Open the database
|
||||||
@@ -264,6 +269,44 @@ def main():
|
|||||||
|
|
||||||
print(json.dumps(dump_data, indent=4))
|
print(json.dumps(dump_data, indent=4))
|
||||||
|
|
||||||
|
elif args.command == "sync-missing":
|
||||||
|
import secrets
|
||||||
|
import string
|
||||||
|
|
||||||
|
def generate_password(length=20):
|
||||||
|
alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
|
||||||
|
return ''.join(secrets.choice(alphabet) for _ in range(length))
|
||||||
|
|
||||||
|
bbs_users = root.get('users', {})
|
||||||
|
http_users = get_or_create_http_users(root)
|
||||||
|
|
||||||
|
missing = [call for call in bbs_users if call not in http_users and call != "SYSTEM"]
|
||||||
|
if not missing:
|
||||||
|
print("No missing HTTP users—all BBS users have HttpUser objects")
|
||||||
|
else:
|
||||||
|
print(f"Found {len(missing)} BBS users without HTTP accounts:")
|
||||||
|
for call in sorted(missing):
|
||||||
|
print(f" - {call}")
|
||||||
|
|
||||||
|
if args.dry_run:
|
||||||
|
print("\n--dry-run: No changes made")
|
||||||
|
else:
|
||||||
|
confirm_msg = f"Create {len(missing)} new HttpUser objects (http_enabled={'True' if args.enable else 'False'})?"
|
||||||
|
if not confirm(confirm_msg):
|
||||||
|
print("Aborted")
|
||||||
|
else:
|
||||||
|
created_count = 0
|
||||||
|
for call in missing:
|
||||||
|
password = generate_password() # strong random, not printed
|
||||||
|
new_http = HttpUser(call, password)
|
||||||
|
new_http.http_enabled = args.enable
|
||||||
|
http_users[call] = new_http
|
||||||
|
created_count += 1
|
||||||
|
|
||||||
|
transaction.commit()
|
||||||
|
print(f"\nSync complete: {created_count} HTTP users added (passwords random & hidden)")
|
||||||
|
print("Use 'set-password <call>' to set a known password before enabling login")
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
connection.close()
|
connection.close()
|
||||||
db.close()
|
db.close()
|
||||||
|
|||||||
Reference in New Issue
Block a user