Updated database methodology for everything else.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
# packetserver/http/auth.py
|
||||
import ax25
|
||||
import transaction
|
||||
from persistent import Persistent
|
||||
from argon2 import PasswordHasher
|
||||
from argon2.exceptions import VerifyMismatchError
|
||||
@@ -7,7 +8,7 @@ import time
|
||||
from persistent.mapping import PersistentMapping
|
||||
from persistent.list import PersistentList
|
||||
from packetserver.common.util import is_valid_ax25_callsign
|
||||
from .database import get_db, get_transaction
|
||||
from .database import ConnectionDependency
|
||||
|
||||
ph = PasswordHasher()
|
||||
|
||||
@@ -51,17 +52,16 @@ class HttpUser(Persistent):
|
||||
# rf enabled checks..
|
||||
#
|
||||
|
||||
def is_rf_enabled(self) -> bool:
|
||||
def is_rf_enabled(self, conn: ConnectionDependency) -> bool:
|
||||
"""
|
||||
Check if RF gateway is enabled (i.e., callsign NOT in global blacklist).
|
||||
Requires an open ZODB connection.
|
||||
"""
|
||||
with get_transaction() as storage:
|
||||
root = storage.root()
|
||||
blacklist = root.get('config', {}).get('blacklist', [])
|
||||
return self.username not in blacklist
|
||||
root = conn.root()
|
||||
blacklist = root.get('config', {}).get('blacklist', [])
|
||||
return self.username not in blacklist
|
||||
|
||||
def set_rf_enabled(self, connection, allow: bool):
|
||||
def set_rf_enabled(self, conn: ConnectionDependency, allow: bool):
|
||||
"""
|
||||
Enable/disable RF gateway by adding/removing from global blacklist.
|
||||
Requires an open ZODB connection (inside a transaction).
|
||||
@@ -69,26 +69,26 @@ class HttpUser(Persistent):
|
||||
"""
|
||||
from packetserver.common.util import is_valid_ax25_callsign # our validator
|
||||
|
||||
with get_transaction() as storage:
|
||||
root = storage.root()
|
||||
config = root.setdefault('config', PersistentMapping())
|
||||
blacklist = config.setdefault('blacklist', PersistentList())
|
||||
root = conn.root()
|
||||
config = root.setdefault('config', PersistentMapping())
|
||||
blacklist = config.setdefault('blacklist', PersistentList())
|
||||
|
||||
upper_name = self.username
|
||||
upper_name = self.username
|
||||
|
||||
if allow:
|
||||
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)
|
||||
blacklist._p_changed = True
|
||||
else:
|
||||
if upper_name not in blacklist:
|
||||
blacklist.append(upper_name)
|
||||
blacklist._p_changed = True
|
||||
if allow:
|
||||
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)
|
||||
blacklist._p_changed = True
|
||||
else:
|
||||
if upper_name not in blacklist:
|
||||
blacklist.append(upper_name)
|
||||
blacklist._p_changed = True
|
||||
|
||||
config._p_changed = True
|
||||
root._p_changed = True
|
||||
config._p_changed = True
|
||||
root._p_changed = True
|
||||
transaction.commit()
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Password handling (unchanged)
|
||||
|
||||
@@ -10,6 +10,7 @@ from pydantic import BaseModel, Field, validator
|
||||
|
||||
from packetserver.http.dependencies import get_current_http_user
|
||||
from packetserver.http.auth import HttpUser
|
||||
from packetserver.http.database import ConnectionDependency
|
||||
|
||||
|
||||
html_router = APIRouter(tags=["messages-html"])
|
||||
@@ -28,18 +29,17 @@ class MarkRetrievedRequest(BaseModel):
|
||||
|
||||
@router.get("/messages")
|
||||
async def get_messages(
|
||||
conn: ConnectionDependency,
|
||||
current_user: HttpUser = Depends(get_current_http_user),
|
||||
type: str = Query("received", description="received, sent, or all"),
|
||||
limit: Optional[int] = Query(20, le=100, description="Max messages to return (default 20, max 100)"),
|
||||
since: Optional[str] = Query(None, description="ISO UTC timestamp filter (e.g. 2025-12-01T00:00:00Z)")
|
||||
since: Optional[str] = Query(None, description="ISO UTC timestamp filter (e.g. 2025-12-01T00:00:00Z)"),
|
||||
|
||||
):
|
||||
if limit is None or limit < 1:
|
||||
limit = 20
|
||||
|
||||
username = current_user.username
|
||||
|
||||
from packetserver.runners.http_server import get_db_connection
|
||||
conn = get_db_connection()
|
||||
root = conn.root()
|
||||
|
||||
if 'messages' not in root:
|
||||
@@ -81,12 +81,11 @@ async def get_messages(
|
||||
|
||||
@router.get("/messages/{msg_id}")
|
||||
async def get_message(
|
||||
conn: ConnectionDependency,
|
||||
msg_id: str = Path(..., description="UUID of the message (as string)"),
|
||||
mark_retrieved: bool = Query(False, description="If true, mark message as retrieved/read"),
|
||||
current_user: HttpUser = Depends(get_current_http_user)
|
||||
):
|
||||
from packetserver.runners.http_server import get_db_connection
|
||||
conn = get_db_connection()
|
||||
root = conn.root()
|
||||
|
||||
username = current_user.username
|
||||
@@ -127,12 +126,11 @@ async def get_message(
|
||||
|
||||
@router.patch("/messages/{msg_id}")
|
||||
async def mark_message_retrieved(
|
||||
conn: ConnectionDependency,
|
||||
msg_id: str = Path(..., description="Message UUID as string"),
|
||||
payload: MarkRetrievedRequest = None,
|
||||
current_user: HttpUser = Depends(get_current_http_user)
|
||||
):
|
||||
from packetserver.runners.http_server import get_db_connection
|
||||
conn = get_db_connection()
|
||||
root = conn.root()
|
||||
|
||||
username = current_user.username
|
||||
|
||||
@@ -3,16 +3,14 @@ from fastapi import APIRouter, Depends
|
||||
|
||||
from packetserver.http.dependencies import get_current_http_user
|
||||
from packetserver.http.auth import HttpUser
|
||||
from packetserver.http.database import ConnectionDependency
|
||||
|
||||
router = APIRouter(prefix="/api/v1", tags=["auth"])
|
||||
|
||||
|
||||
@router.get("/profile")
|
||||
async def profile(current_user: HttpUser = Depends(get_current_http_user)):
|
||||
async def profile(conn: ConnectionDependency,current_user: HttpUser = Depends(get_current_http_user)):
|
||||
username = current_user.username
|
||||
|
||||
from packetserver.runners.http_server import get_db_connection
|
||||
conn = get_db_connection()
|
||||
root = conn.root()
|
||||
|
||||
# Get main BBS User and safe dict
|
||||
|
||||
@@ -11,6 +11,7 @@ from packetserver.http.dependencies import get_current_http_user
|
||||
from packetserver.http.auth import HttpUser
|
||||
from packetserver.server.messages import Message
|
||||
from packetserver.common.util import is_valid_ax25_callsign
|
||||
from packetserver.http.database import ConnectionDependency
|
||||
|
||||
router = APIRouter(prefix="/api/v1", tags=["messages"])
|
||||
|
||||
@@ -39,11 +40,10 @@ class SendMessageRequest(BaseModel):
|
||||
|
||||
@router.post("/messages")
|
||||
async def send_message(
|
||||
conn: ConnectionDependency,
|
||||
payload: SendMessageRequest,
|
||||
current_user: HttpUser = Depends(get_current_http_user)
|
||||
):
|
||||
from packetserver.runners.http_server import get_db_connection
|
||||
conn = get_db_connection()
|
||||
root = conn.root()
|
||||
|
||||
if not current_user.is_rf_enabled(conn):
|
||||
|
||||
Reference in New Issue
Block a user