Adding defunct changes. Still testing.

This commit is contained in:
Michael Woods
2025-12-24 19:52:14 -05:00
parent f8685230c4
commit 31ea05e3cb
2 changed files with 45 additions and 75 deletions

View File

@@ -1,91 +1,61 @@
# packetserver/http/routers/bulletins.py from fastapi import APIRouter, Path, Query, Depends, HTTPException, Request, status
from fastapi import APIRouter, Path, Query, Depends, HTTPException, status, Request, APIRouter as PrefixedRouter
from fastapi.responses import HTMLResponse from fastapi.responses import HTMLResponse
from typing import Optional from typing import Optional
from pydantic import BaseModel, Field, constr
from datetime import datetime from datetime import datetime
import transaction import transaction
from pydantic import BaseModel, Field, constr
from persistent.list import PersistentList from persistent.list import PersistentList
from packetserver.http.dependencies import get_current_http_user from ..dependencies import get_current_http_user # relative
from packetserver.http.auth import HttpUser from ..auth import HttpUser
from packetserver.http.server import templates from ..server import templates # relative import - this is now safe
from packetserver.server.bulletin import Bulletin # core class from packetserver.server.bulletin import Bulletin
# Existing API router (keep)
router = APIRouter(prefix="/api/v1", tags=["bulletins"]) router = APIRouter(prefix="/api/v1", tags=["bulletins"])
# ... your existing list_bulletins and get_bulletin routes ...
# New non-prefixed router for HTML pages
html_router = APIRouter(tags=["bulletins-html"]) html_router = APIRouter(tags=["bulletins-html"])
@html_router.get("/bulletins", response_class="HTMLResponse")
async def bulletin_list_page(request: Request, limit: Optional[int] = Query(50, le=100)):
# Local import to avoid circular issues
from .bulletins import list_bulletins as api_list_bulletins
api_resp = await api_list_bulletins(limit=limit, since=None)
bulletins = api_resp["bulletins"]
class CreateBulletinRequest(BaseModel): current_user = None
subject: constr(min_length=1, max_length=100) = Field(..., description="Bulletin subject/title") try:
body: constr(min_length=1) = Field(..., description="Bulletin body text") current_user = await get_current_http_user()(request) # optional call
except:
pass
return templates.TemplateResponse(
"bulletin_list.html",
{"request": request, "bulletins": bulletins, "current_user": current_user.username if current_user else None}
)
@router.get("/bulletins") @html_router.get("/bulletins/{bid}", response_class="HTMLResponse")
async def list_bulletins( async def bulletin_detail_page(request: Request, bid: int):
limit: Optional[int] = Query(20, le=100, description="Max bulletins to return"), from .bulletins import get_bulletin as api_get_bulletin
since: Optional[str] = Query(None, description="ISO UTC timestamp filter") try:
): bulletin = await api_get_bulletin(bid=bid, current_user=None)
from packetserver.runners.http_server import get_db_connection except HTTPException:
conn = get_db_connection() raise HTTPException(status_code=404, detail="Bulletin not found")
root = conn.root()
bulletins_list = root.get('bulletins', []) current_user = None
if not bulletins_list: try:
return {"bulletins": [], "total": 0} current_user = await get_current_http_user()(request)
except:
pass
since_dt = None return templates.TemplateResponse(
if since: "bulletin_detail.html",
try: {"request": request, "bulletin": bulletin, "current_user": current_user.username if current_user else None}
since_dt = datetime.fromisoformat(since.replace("Z", "+00:00")) )
except ValueError:
raise HTTPException(status_code=400, detail="Invalid 'since' format")
filtered = []
for bull in reversed(bulletins_list): # newest first (assuming appended order)
if since_dt and bull.created_at < since_dt:
continue
filtered.append({
"id": bull.id,
"author": bull.author,
"subject": bull.subject,
"body": bull.body,
"created_at": bull.created_at.isoformat() + "Z",
"updated_at": bull.updated_at.isoformat() + "Z",
})
return {
"bulletins": filtered[:limit],
"total": len(filtered)
}
@router.get("/bulletins/{bid}")
async def get_bulletin(
bid: int = Path(..., description="Bulletin ID"),
current_user: HttpUser = Depends(get_current_http_user) # require auth, but public read
):
from packetserver.runners.http_server import get_db_connection
conn = get_db_connection()
root = conn.root()
bulletins_list = root.get('bulletins', [])
for bull in bulletins_list:
if bull.id == bid:
return {
"id": bull.id,
"author": bull.author,
"subject": bull.subject,
"body": bull.body,
"created_at": bull.created_at.isoformat() + "Z",
"updated_at": bull.updated_at.isoformat() + "Z",
}
raise HTTPException(status_code=404, detail="Bulletin not found")
from fastapi import status
from pydantic import BaseModel, Field, constr
# datetime already imported elsewhere, but ensure
class CreateBulletinRequest(BaseModel): class CreateBulletinRequest(BaseModel):
subject: constr(min_length=1, max_length=100) = Field(..., description="Bulletin subject/title") subject: constr(min_length=1, max_length=100) = Field(..., description="Bulletin subject/title")
@@ -104,7 +74,7 @@ async def create_bulletin(
# Ensure the bulletins list and counter exist # Ensure the bulletins list and counter exist
if 'bulletins' not in root: if 'bulletins' not in root:
root['bulletins'] = persistent.list.PersistentList() root['bulletins'] = PersistentList()
new_bulletin = Bulletin( new_bulletin = Bulletin(
author=current_user.username, # uppercase callsign author=current_user.username, # uppercase callsign

View File

@@ -4,7 +4,7 @@ from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from pathlib import Path from pathlib import Path
from .routers import public, profile, messages, send, bulletins from .routers import public, profile, messages, send
from packetserver.http.routers.bulletins import html_router from packetserver.http.routers.bulletins import html_router
BASE_DIR = Path(__file__).parent.resolve() BASE_DIR = Path(__file__).parent.resolve()
@@ -36,7 +36,7 @@ templates.env.filters["timestamp_to_date"] = timestamp_to_date
app.mount("/static", StaticFiles(directory=BASE_DIR / "static"), name="static") app.mount("/static", StaticFiles(directory=BASE_DIR / "static"), name="static")
# Now safe to import dashboard (it needs templates) # Now safe to import dashboard (it needs templates)
from .routers import dashboard # add this line from .routers import dashboard, bulletins
# Include routers # Include routers
app.include_router(public.router) app.include_router(public.router)