import json import sqlite3 import time from datetime import datetime import config_utils import factory def _fmt_ts(ts, now): try: dt = datetime.fromtimestamp(int(ts)) ago = config_utils.relative_time(int(ts), now) return f'{dt.strftime("%Y-%m-%d %H:%M")} ({ago} ago)' except Exception: return '-' _LEVEL_INT_TO_STR = {0: 'nothing', 1: 'viewer', 2: 'administrator', 3: 'manager'} def _active_sessions_table(): try: con = sqlite3.connect(config_utils.ACCOUNTS_DB, timeout=5) con.row_factory = sqlite3.Row rows = con.execute( '''SELECT s.session_id, a.email, a.access_level, s.session_started_ts, s.last_seen_ts FROM sessions s JOIN accounts a ON a.account_id = s.account_id ORDER BY s.last_seen_ts DESC''' ).fetchall() con.close() except Exception: rows = [] if not rows: return '

No active sessions.

' now = int(time.time()) trs = '' for row in rows: sid = row['session_id'] email = row['email'] access_level = _LEVEL_INT_TO_STR.get(row['access_level'], 'viewer') started_ts = row['session_started_ts'] last_seen = row['last_seen_ts'] online = (now - int(last_seen)) < 300 ago = config_utils.relative_time(int(last_seen), now) tip = factory.e(f'Last seen {ago} ago') badge_cls = 'badge-enabled' if online else 'badge-disabled' badge_lbl = 'Online' if online else 'Offline' badge = ( f'' f'{badge_lbl}' f'' ) btn = ( f'
' f'' f'' f'
' ) trs += ( f'' f'{factory.e(email)}' f'{factory.e(access_level)}' f'{badge}' f'{_fmt_ts(started_ts, now)}' f'{btn}' f'' ) return ( '' '' '' '' '' '' '' + trs + '
EmailAccess LevelStatusLogged In
' ) def collect_tokens(cfg): tokens = config_utils.collect_layout_tokens(cfg) tokens['ACCOUNT_LEVEL_OPTIONS'] = json.dumps([ {'value': 'viewer', 'label': 'Viewer (read-only access to live data)'}, {'value': 'administrator', 'label': 'Administrator (can modify configuration)'}, {'value': 'manager', 'label': 'Manager (full access including account management)'}, ]) tokens['ACTIVE_SESSIONS_TABLE'] = _active_sessions_table() content = factory.load_json(f'{factory.PAGES_DIR}/accountmanage/content.json') for table_item in factory.iter_table_items(content.get('items', [])): ds = table_item.get('datasource', '') tokens[factory.table_token_key(ds)] = factory.build_table(table_item, tokens, config_utils.load_datasource(ds)) return tokens