Changes grok suggested.

This commit is contained in:
Michael Woods
2025-12-21 21:10:11 -05:00
parent 2b4c8b56ba
commit b671e49e69
4 changed files with 30 additions and 41 deletions

View File

@@ -38,61 +38,47 @@ class HttpUser(Persistent):
self._enabled = bool(value)
self._p_changed = True
# ------------------------------------------------------------------
# rf_enabled property tied directly to the main server's blacklist
# ------------------------------------------------------------------
@property
def rf_enabled(self) -> bool:
"""
True if the callsign is NOT in the global blacklist.
This allows HTTP users to act as RF gateways only if explicitly allowed.
"""
from ZODB import DB # deferred import to avoid circular issues
# We'll get the db from the transaction in most contexts
# But for safety, we'll reach into the current connection's root
import transaction
try:
root = transaction.get().db().root()
blacklist = root.get('config', {}).get('blacklist', [])
return self.username not in blacklist
except Exception:
# If we're outside a transaction (e.g. during tests), default safe
return False
#
# rf enabled checks..
#
@rf_enabled.setter
def rf_enabled(self, allow: bool):
def is_rf_enabled(self, connection) -> bool:
"""
Enable/disable RF gateway capability by adding/removing from the global blacklist.
Check if RF gateway is enabled (i.e., callsign NOT in global blacklist).
Requires an open ZODB connection.
"""
root = connection.root()
blacklist = root.get('config', {}).get('blacklist', [])
return self.username not in blacklist
def set_rf_enabled(self, connection, allow: bool):
"""
Enable/disable RF gateway by adding/removing from global blacklist.
Requires an open ZODB connection (inside a transaction).
Only allows enabling if the username is a valid AX.25 callsign.
"""
import transaction
from packetserver.common.util import is_valid_ax25_callsign # assuming you have this helper
from packetserver.utils import is_valid_ax25_callsign # our validator
root = transaction.get().db().root()
root = connection.root()
config = root.setdefault('config', PersistentMapping())
blacklist = config.setdefault('blacklist', PersistentList())
upper_name = self.username
if allow:
# Trying to enable RF access
if not is_valid_ax25_callsign(upper_name):
raise ValueError(f"{upper_name} is not a valid AX.25 callsign cannot enable RF access")
if upper_name in blacklist:
blacklist.remove(upper_name)
config['blacklist'] = blacklist
self._p_changed = True
blacklist._p_changed = True
else:
# Disable RF access
if upper_name not in blacklist:
blacklist.append(upper_name)
config['blacklist'] = blacklist
self._p_changed = True
blacklist._p_changed = True
# Ensure changes are marked
root._p_changed = True
config._p_changed = True
root._p_changed = True
# Caller should commit the transaction
# ------------------------------------------------------------------
# Password handling (unchanged)

View File

@@ -19,11 +19,12 @@ async def profile(current_user: HttpUser = Depends(get_current_http_user)):
main_users = root.get('users', {})
bbs_user = main_users.get(username)
safe_profile = bbs_user.to_safe_dict() if bbs_user else {}
rf_enabled = current_user.is_rf_enabled(conn)
return {
**safe_profile,
"http_enabled": current_user.enabled,
"rf_enabled": current_user.rf_enabled,
"rf_enabled": rf_enabled,
"http_created_at": current_user.created_at,
"http_last_login": current_user.last_login,
}

View File

@@ -2,6 +2,8 @@
from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel, Field, validator
from typing import List
from persistent.list import PersistentList
from persistent.mapping import PersistentMapping
from datetime import datetime
import uuid
@@ -32,7 +34,9 @@ async def send_message(
payload: SendMessageRequest,
current_user: HttpUser = Depends(get_current_http_user)
):
if not current_user.rf_enabled:
from packetserver.runners.http_server import get_db_connection
conn = get_db_connection()
if not current_user.is_rf_enabled(conn):
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="RF gateway access required to send messages"
@@ -54,8 +58,6 @@ async def send_message(
msg_from=username,
msg_to=to_tuple,
text=payload.text,
subject=payload.subject, # if Message supports it; otherwise drop
sent_at=datetime.utcnow(),
attachments=() # empty for now
)

View File

@@ -193,7 +193,7 @@ def main():
print(f"Error: User {callsign} not found")
sys.exit(1)
try:
user.rf_enabled = True
user.set_rf_enabled(connection, True)
transaction.commit()
print(f"RF gateway enabled for {callsign}")
except ValueError as e:
@@ -206,7 +206,7 @@ def main():
if not user:
print(f"Error: User {callsign} not found")
sys.exit(1)
user.rf_enabled = False
user.set_rf_enabled(connection, False)
transaction.commit()
print(f"RF gateway disabled for {callsign}")