96 lines
3.5 KiB
Python
96 lines
3.5 KiB
Python
import json
|
|
import sqlite3
|
|
import time
|
|
import datetime
|
|
|
|
from config_utils import collect_layout_tokens, CREDENTIALS_DB
|
|
from factory import load_json, build_table, table_token_key, iter_table_items, PAGES_DIR
|
|
import settings as settings
|
|
|
|
PRO_LICENSE = settings.is_pro()
|
|
|
|
USER_TYPE_LABELS = {0: 'Captive Portal', 1: '802.1X'}
|
|
HASH_TYPE_LABELS = {0: 'Cleartext', 1: 'NT-Password', 2: 'Bcrypt'}
|
|
|
|
|
|
def _load_credentials():
|
|
try:
|
|
conn = sqlite3.connect(CREDENTIALS_DB)
|
|
conn.row_factory = sqlite3.Row
|
|
conn.execute("""
|
|
CREATE TABLE IF NOT EXISTS credentials (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
username TEXT NOT NULL UNIQUE COLLATE NOCASE,
|
|
password TEXT NOT NULL,
|
|
description TEXT NOT NULL DEFAULT '',
|
|
user_type INTEGER NOT NULL,
|
|
hash_type INTEGER NOT NULL,
|
|
vlan TEXT NOT NULL DEFAULT '',
|
|
enabled INTEGER NOT NULL DEFAULT 1,
|
|
date_set INTEGER NOT NULL,
|
|
valid_for INTEGER DEFAULT NULL
|
|
)
|
|
""")
|
|
conn.execute("""
|
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
ip TEXT NOT NULL,
|
|
credential_id INTEGER REFERENCES credentials(id) ON DELETE CASCADE,
|
|
started_at INTEGER NOT NULL,
|
|
expires_at INTEGER,
|
|
mac TEXT NOT NULL DEFAULT ''
|
|
)
|
|
""")
|
|
conn.commit()
|
|
rows = conn.execute("SELECT * FROM credentials ORDER BY id").fetchall()
|
|
conn.close()
|
|
return rows
|
|
except Exception:
|
|
return []
|
|
|
|
|
|
def _format_expiry(date_set, valid_for):
|
|
if valid_for is None:
|
|
return 'Never'
|
|
expires_ts = date_set + valid_for
|
|
now = int(time.time())
|
|
if expires_ts <= now:
|
|
return 'Expired'
|
|
dt = datetime.datetime.fromtimestamp(expires_ts)
|
|
return dt.strftime('%Y-%m-%d %H:%M')
|
|
|
|
|
|
def collect_tokens(cfg):
|
|
tokens = collect_layout_tokens(cfg)
|
|
|
|
tokens['PRO_NOTE'] = (
|
|
'' if PRO_LICENSE else
|
|
'<div class="info-bar info-bar-info">'
|
|
'<span>Client Credentials is a Routlin Pro feature. '
|
|
'Credentials can be viewed but not added or edited without a Pro license.</span></div>'
|
|
)
|
|
tokens['ADD_CREDENTIAL_DISABLED'] = '' if PRO_LICENSE else 'true'
|
|
|
|
vlans = [v for v in cfg.get('vlans', []) if not v.get('is_vpn')]
|
|
tokens['VLAN_OPTIONS'] = json.dumps(
|
|
[{'value': '', 'label': '— Select VLAN —'}] +
|
|
[{'value': v['name'], 'label': f"{v['name']} (VLAN {v['vlan_id']})"} for v in vlans]
|
|
)
|
|
|
|
raw_rows = _load_credentials()
|
|
display_rows = []
|
|
for row in raw_rows:
|
|
r = dict(row)
|
|
r.pop('password', None)
|
|
r['user_type_label'] = USER_TYPE_LABELS.get(r.get('user_type'), str(r.get('user_type', '')))
|
|
r['hash_type_label'] = HASH_TYPE_LABELS.get(r.get('hash_type'), str(r.get('hash_type', '')))
|
|
r['expires_label'] = _format_expiry(r.get('date_set', 0), r.get('valid_for'))
|
|
display_rows.append(r)
|
|
|
|
content = load_json(f'{PAGES_DIR}/clientcredentials/content.json')
|
|
for table_item in iter_table_items(content.get('items', [])):
|
|
ds = table_item.get('datasource', '')
|
|
data = display_rows if ds == 'sqlite:client_credentials' else []
|
|
tokens[table_token_key(ds)] = build_table(table_item, tokens, data)
|
|
|
|
return tokens
|