Updated user manager.

This commit is contained in:
Michael Woods
2025-12-21 21:25:50 -05:00
parent 95311ece46
commit 1cd7242a7b
2 changed files with 15 additions and 7 deletions

View File

@@ -1,10 +1,12 @@
# packetserver/http/auth.py # packetserver/http/auth.py
import ax25
from persistent import Persistent from persistent import Persistent
from argon2 import PasswordHasher from argon2 import PasswordHasher
from argon2.exceptions import VerifyMismatchError from argon2.exceptions import VerifyMismatchError
import time import time
from persistent.mapping import PersistentMapping from persistent.mapping import PersistentMapping
from persistent.list import PersistentList from persistent.list import PersistentList
from packetserver.common.util import is_valid_ax25_callsign
ph = PasswordHasher() ph = PasswordHasher()
@@ -22,6 +24,12 @@ class HttpUser(Persistent):
self.last_login = None self.last_login = None
self.failed_attempts = 0 self.failed_attempts = 0
# Check to make sure we're not storing a SSID
if is_valid_ax25_callsign(self.username):
base = ax25.Address(self.username).call
if base.upper() != self.username:
raise ValueError(f"'{self.username}' is a callsign with an SSID appended. Please use base callsign.")
# New fields # New fields
self._enabled = True # HTTP access enabled by default self._enabled = True # HTTP access enabled by default
# rf_enabled is a @property no direct storage needed # rf_enabled is a @property no direct storage needed
@@ -30,11 +38,11 @@ class HttpUser(Persistent):
# Simple enabled flag (admin can disable HTTP login entirely) # Simple enabled flag (admin can disable HTTP login entirely)
# ------------------------------------------------------------------ # ------------------------------------------------------------------
@property @property
def enabled(self) -> bool: def http_enabled(self) -> bool:
return getattr(self, '_enabled', True) return getattr(self, '_enabled', True)
@enabled.setter @http_enabled.setter
def enabled(self, value: bool): def http_enabled(self, value: bool):
self._enabled = bool(value) self._enabled = bool(value)
self._p_changed = True self._p_changed = True
@@ -57,7 +65,7 @@ class HttpUser(Persistent):
Requires an open ZODB connection (inside a transaction). Requires an open ZODB connection (inside a transaction).
Only allows enabling if the username is a valid AX.25 callsign. Only allows enabling if the username is a valid AX.25 callsign.
""" """
from packetserver.utils import is_valid_ax25_callsign # our validator from packetserver.common.util import is_valid_ax25_callsign # our validator
root = connection.root() root = connection.root()
config = root.setdefault('config', PersistentMapping()) config = root.setdefault('config', PersistentMapping())

View File

@@ -214,14 +214,14 @@ def main():
if not users_mapping: if not users_mapping:
print("No HTTP users configured") print("No HTTP users configured")
else: else:
print(f"{'Callsign':<12} {'Enabled':<8} {'RF Enabled':<11} {'Created':<20} Last Login") print(f"{'Callsign':<12} {'HTTP Enabled':<13} {'RF Enabled':<11} {'Created':<20} Last Login")
print("-" * 70) print("-" * 75)
for user in sorted(users_mapping.values(), key=lambda u: u.username): for user in sorted(users_mapping.values(), key=lambda u: u.username):
created = time.strftime("%Y-%m-%d %H:%M", time.localtime(user.created_at)) created = time.strftime("%Y-%m-%d %H:%M", time.localtime(user.created_at))
last = (time.strftime("%Y-%m-%d %H:%M", time.localtime(user.last_login)) last = (time.strftime("%Y-%m-%d %H:%M", time.localtime(user.last_login))
if user.last_login else "-") if user.last_login else "-")
rf_status = "True" if user.is_rf_enabled(connection) else "False" rf_status = "True" if user.is_rf_enabled(connection) else "False"
print(f"{user.username:<12} {str(user.enabled):<8} {rf_status:<11} {created:<20} {last}") print(f"{user.username:<12} {str(user.http_enabled):<13} {rf_status:<11} {created:<20} {last}")
finally: finally: