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