238 lines
7.4 KiB
Python
238 lines
7.4 KiB
Python
from fastapi import APIRouter, Depends, File, Form, HTTPException, UploadFile
|
|
from sqlalchemy.orm import Session, joinedload
|
|
|
|
from app.auth import get_current_admin
|
|
from app.database import get_db
|
|
from app.models import AdminUser, EventEdition, MediaAsset, PlatformLink
|
|
from app.schemas import (
|
|
EventEditionCreate,
|
|
EventEditionAdmin,
|
|
EventEditionUpdate,
|
|
MediaReorderItem,
|
|
PlatformLinkCreate,
|
|
PlatformLinkPublic,
|
|
PlatformLinkUpdate,
|
|
)
|
|
from app.services.editions import edition_to_admin, edition_to_public
|
|
from app.services.media import public_url_for_path, save_image
|
|
|
|
router = APIRouter(prefix="/api/admin", tags=["admin"])
|
|
|
|
|
|
@router.get("/me")
|
|
def me(admin: AdminUser = Depends(get_current_admin)):
|
|
return {"email": admin.email, "role": admin.role.value}
|
|
|
|
|
|
# --- Platform links ---
|
|
|
|
|
|
@router.get("/links", response_model=list[PlatformLinkPublic])
|
|
def list_links(db: Session = Depends(get_db), _: AdminUser = Depends(get_current_admin)):
|
|
rows = db.query(PlatformLink).order_by(PlatformLink.sort_order, PlatformLink.id).all()
|
|
return [PlatformLinkPublic.model_validate(r) for r in rows]
|
|
|
|
|
|
@router.post("/links", response_model=PlatformLinkPublic)
|
|
def create_link(
|
|
body: PlatformLinkCreate,
|
|
db: Session = Depends(get_db),
|
|
_: AdminUser = Depends(get_current_admin),
|
|
):
|
|
row = PlatformLink(**body.model_dump())
|
|
db.add(row)
|
|
db.commit()
|
|
db.refresh(row)
|
|
return PlatformLinkPublic.model_validate(row)
|
|
|
|
|
|
@router.patch("/links/{link_id}", response_model=PlatformLinkPublic)
|
|
def update_link(
|
|
link_id: int,
|
|
body: PlatformLinkUpdate,
|
|
db: Session = Depends(get_db),
|
|
_: AdminUser = Depends(get_current_admin),
|
|
):
|
|
row = db.query(PlatformLink).filter(PlatformLink.id == link_id).first()
|
|
if not row:
|
|
raise HTTPException(status_code=404, detail="Link not found")
|
|
for k, v in body.model_dump(exclude_unset=True).items():
|
|
setattr(row, k, v)
|
|
db.commit()
|
|
db.refresh(row)
|
|
return PlatformLinkPublic.model_validate(row)
|
|
|
|
|
|
@router.delete("/links/{link_id}")
|
|
def delete_link(link_id: int, db: Session = Depends(get_db), _: AdminUser = Depends(get_current_admin)):
|
|
row = db.query(PlatformLink).filter(PlatformLink.id == link_id).first()
|
|
if not row:
|
|
raise HTTPException(status_code=404, detail="Link not found")
|
|
db.delete(row)
|
|
db.commit()
|
|
return {"ok": True}
|
|
|
|
|
|
# --- Editions ---
|
|
|
|
|
|
@router.get("/editions", response_model=list[EventEditionAdmin])
|
|
def admin_list_editions(db: Session = Depends(get_db), _: AdminUser = Depends(get_current_admin)):
|
|
editions = (
|
|
db.query(EventEdition)
|
|
.options(joinedload(EventEdition.media))
|
|
.order_by(EventEdition.id.desc())
|
|
.all()
|
|
)
|
|
return [edition_to_admin(e) for e in editions]
|
|
|
|
|
|
@router.post("/editions", response_model=EventEditionAdmin)
|
|
def create_edition(
|
|
body: EventEditionCreate,
|
|
db: Session = Depends(get_db),
|
|
_: AdminUser = Depends(get_current_admin),
|
|
):
|
|
if db.query(EventEdition).filter(EventEdition.slug == body.slug).first():
|
|
raise HTTPException(status_code=400, detail="Slug already exists")
|
|
edition = EventEdition(city="Bengaluru", **body.model_dump())
|
|
db.add(edition)
|
|
db.commit()
|
|
db.refresh(edition)
|
|
edition = (
|
|
db.query(EventEdition)
|
|
.options(joinedload(EventEdition.media))
|
|
.filter(EventEdition.id == edition.id)
|
|
.one()
|
|
)
|
|
return edition_to_admin(edition)
|
|
|
|
|
|
@router.patch("/editions/{edition_id}", response_model=EventEditionAdmin)
|
|
def update_edition(
|
|
edition_id: int,
|
|
body: EventEditionUpdate,
|
|
db: Session = Depends(get_db),
|
|
_: AdminUser = Depends(get_current_admin),
|
|
):
|
|
edition = db.query(EventEdition).filter(EventEdition.id == edition_id).first()
|
|
if not edition:
|
|
raise HTTPException(status_code=404, detail="Edition not found")
|
|
data = body.model_dump(exclude_unset=True)
|
|
if "slug" in data and data["slug"] != edition.slug:
|
|
if db.query(EventEdition).filter(EventEdition.slug == data["slug"]).first():
|
|
raise HTTPException(status_code=400, detail="Slug already exists")
|
|
for k, v in data.items():
|
|
setattr(edition, k, v)
|
|
db.commit()
|
|
edition = (
|
|
db.query(EventEdition)
|
|
.options(joinedload(EventEdition.media))
|
|
.filter(EventEdition.id == edition_id)
|
|
.one()
|
|
)
|
|
return edition_to_admin(edition)
|
|
|
|
|
|
@router.post("/editions/{edition_id}/cover")
|
|
async def upload_cover(
|
|
edition_id: int,
|
|
file: UploadFile = File(...),
|
|
db: Session = Depends(get_db),
|
|
_: AdminUser = Depends(get_current_admin),
|
|
):
|
|
edition = db.query(EventEdition).filter(EventEdition.id == edition_id).first()
|
|
if not edition:
|
|
raise HTTPException(status_code=404, detail="Edition not found")
|
|
try:
|
|
path = save_image(file)
|
|
except ValueError as e:
|
|
raise HTTPException(status_code=400, detail=str(e))
|
|
edition.cover_image_path = path
|
|
db.commit()
|
|
return {"cover_image_url": public_url_for_path(path)}
|
|
|
|
|
|
@router.post("/editions/{edition_id}/media")
|
|
async def upload_media(
|
|
edition_id: int,
|
|
file: UploadFile = File(...),
|
|
caption: str | None = Form(default=None),
|
|
sort_order: int = Form(default=0),
|
|
db: Session = Depends(get_db),
|
|
_: AdminUser = Depends(get_current_admin),
|
|
):
|
|
edition = db.query(EventEdition).filter(EventEdition.id == edition_id).first()
|
|
if not edition:
|
|
raise HTTPException(status_code=404, detail="Edition not found")
|
|
try:
|
|
path = save_image(file)
|
|
except ValueError as e:
|
|
raise HTTPException(status_code=400, detail=str(e))
|
|
asset = MediaAsset(
|
|
edition_id=edition_id,
|
|
file_path=path,
|
|
caption=caption,
|
|
sort_order=sort_order,
|
|
is_published=True,
|
|
)
|
|
db.add(asset)
|
|
db.commit()
|
|
db.refresh(asset)
|
|
return {
|
|
"id": asset.id,
|
|
"url": public_url_for_path(path),
|
|
"caption": asset.caption,
|
|
"sort_order": asset.sort_order,
|
|
}
|
|
|
|
|
|
@router.patch("/media/{media_id}")
|
|
def update_media(
|
|
media_id: int,
|
|
caption: str | None = Form(default=None),
|
|
sort_order: int | None = Form(default=None),
|
|
is_published: bool | None = Form(default=None),
|
|
db: Session = Depends(get_db),
|
|
_: AdminUser = Depends(get_current_admin),
|
|
):
|
|
asset = db.query(MediaAsset).filter(MediaAsset.id == media_id).first()
|
|
if not asset:
|
|
raise HTTPException(status_code=404, detail="Media not found")
|
|
if caption is not None:
|
|
asset.caption = caption
|
|
if sort_order is not None:
|
|
asset.sort_order = sort_order
|
|
if is_published is not None:
|
|
asset.is_published = is_published
|
|
db.commit()
|
|
return {"ok": True}
|
|
|
|
|
|
@router.post("/editions/{edition_id}/media/reorder")
|
|
def reorder_media(
|
|
edition_id: int,
|
|
items: list[MediaReorderItem],
|
|
db: Session = Depends(get_db),
|
|
_: AdminUser = Depends(get_current_admin),
|
|
):
|
|
for item in items:
|
|
asset = (
|
|
db.query(MediaAsset)
|
|
.filter(MediaAsset.id == item.id, MediaAsset.edition_id == edition_id)
|
|
.first()
|
|
)
|
|
if asset:
|
|
asset.sort_order = item.sort_order
|
|
db.commit()
|
|
return {"ok": True}
|
|
|
|
|
|
@router.delete("/media/{media_id}")
|
|
def delete_media(media_id: int, db: Session = Depends(get_db), _: AdminUser = Depends(get_current_admin)):
|
|
asset = db.query(MediaAsset).filter(MediaAsset.id == media_id).first()
|
|
if not asset:
|
|
raise HTTPException(status_code=404, detail="Media not found")
|
|
db.delete(asset)
|
|
db.commit()
|
|
return {"ok": True}
|