Adding defunct changes. Still testing.
This commit is contained in:
@@ -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")
|
|
||||||
body: constr(min_length=1) = Field(..., description="Bulletin body text")
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/bulletins")
|
|
||||||
async def list_bulletins(
|
|
||||||
limit: Optional[int] = Query(20, le=100, description="Max bulletins to return"),
|
|
||||||
since: Optional[str] = Query(None, description="ISO UTC timestamp filter")
|
|
||||||
):
|
|
||||||
from packetserver.runners.http_server import get_db_connection
|
|
||||||
conn = get_db_connection()
|
|
||||||
root = conn.root()
|
|
||||||
|
|
||||||
bulletins_list = root.get('bulletins', [])
|
|
||||||
if not bulletins_list:
|
|
||||||
return {"bulletins": [], "total": 0}
|
|
||||||
|
|
||||||
since_dt = None
|
|
||||||
if since:
|
|
||||||
try:
|
try:
|
||||||
since_dt = datetime.fromisoformat(since.replace("Z", "+00:00"))
|
current_user = await get_current_http_user()(request) # optional call
|
||||||
except ValueError:
|
except:
|
||||||
raise HTTPException(status_code=400, detail="Invalid 'since' format")
|
pass
|
||||||
|
|
||||||
filtered = []
|
return templates.TemplateResponse(
|
||||||
for bull in reversed(bulletins_list): # newest first (assuming appended order)
|
"bulletin_list.html",
|
||||||
if since_dt and bull.created_at < since_dt:
|
{"request": request, "bulletins": bulletins, "current_user": current_user.username if current_user else None}
|
||||||
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",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@html_router.get("/bulletins/{bid}", response_class="HTMLResponse")
|
||||||
|
async def bulletin_detail_page(request: Request, bid: int):
|
||||||
|
from .bulletins import get_bulletin as api_get_bulletin
|
||||||
|
try:
|
||||||
|
bulletin = await api_get_bulletin(bid=bid, current_user=None)
|
||||||
|
except HTTPException:
|
||||||
raise HTTPException(status_code=404, detail="Bulletin not found")
|
raise HTTPException(status_code=404, detail="Bulletin not found")
|
||||||
|
|
||||||
from fastapi import status
|
current_user = None
|
||||||
from pydantic import BaseModel, Field, constr
|
try:
|
||||||
# datetime already imported elsewhere, but ensure
|
current_user = await get_current_http_user()(request)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return templates.TemplateResponse(
|
||||||
|
"bulletin_detail.html",
|
||||||
|
{"request": request, "bulletin": bulletin, "current_user": current_user.username if current_user else None}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user