from fastapi import APIRouter, Depends, HTTPException from .. import database as db from ..config import CAMPAIGN_SETTINGS, merge_campaign_settings_with_env from .auth import require_user, require_admin router = APIRouter(prefix="/api/campaigns", tags=["campaigns"]) @router.get("") def list_campaigns(user: dict = Depends(require_user)): return db.get_user_campaigns(user["id"]) @router.post("") def create_campaign(body: dict, user: dict = Depends(require_user)): name = body.get("name", "").strip() if not name: raise HTTPException(400, "Name is required") desc = body.get("description", "").strip() return db.create_campaign(name, desc, user["id"]) @router.get("/{campaign_id}") def get_campaign(campaign_id: str, user: dict = Depends(require_user)): if not db.can_access_campaign(user["id"], campaign_id): raise HTTPException(404, "Campaign not found") return db.get_campaign(campaign_id) @router.put("/{campaign_id}") def update_campaign(campaign_id: str, body: dict, user: dict = Depends(require_user)): if not db.can_access_campaign(user["id"], campaign_id): raise HTTPException(404, "Campaign not found") updated = db.update_campaign( campaign_id, name=body.get("name"), description=body.get("description"), ) return updated @router.delete("/{campaign_id}") def delete_campaign(campaign_id: str, user: dict = Depends(require_user)): campaign = db.get_campaign(campaign_id) if not campaign: raise HTTPException(404, "Campaign not found") if campaign.get("created_by") != user["id"] and not user.get("is_admin"): raise HTTPException(403, "Only the campaign owner can delete it") db.delete_campaign(campaign_id) return {"ok": True} # ── Campaign settings ──────────────────────────────────────────────────── @router.get("/{campaign_id}/settings") def get_campaign_settings(campaign_id: str, user: dict = Depends(require_user)): if not db.can_access_campaign(user["id"], campaign_id): raise HTTPException(404, "Campaign not found") raw = db.get_campaign_settings(campaign_id) return merge_campaign_settings_with_env(raw) @router.post("/{campaign_id}/settings") def update_campaign_settings(campaign_id: str, body: dict, user: dict = Depends(require_user)): if not db.can_access_campaign(user["id"], campaign_id): raise HTTPException(404, "Campaign not found") clean = {k: str(v) for k, v in body.items() if k in CAMPAIGN_SETTINGS} db.update_campaign_settings(campaign_id, clean) raw = db.get_campaign_settings(campaign_id) return merge_campaign_settings_with_env(raw) # ── Sharing ─────────────────────────────────────────────────────────────── @router.get("/{campaign_id}/shares") def list_shares(campaign_id: str, user: dict = Depends(require_user)): campaign = db.get_campaign(campaign_id) if not campaign: raise HTTPException(404, "Campaign not found") if campaign.get("created_by") != user["id"] and not user.get("is_admin"): raise HTTPException(403, "Only the campaign owner can manage sharing") return db.get_campaign_shares(campaign_id) @router.post("/{campaign_id}/shares") def add_share(campaign_id: str, body: dict, user: dict = Depends(require_user)): campaign = db.get_campaign(campaign_id) if not campaign: raise HTTPException(404, "Campaign not found") if campaign.get("created_by") != user["id"] and not user.get("is_admin"): raise HTTPException(403, "Only the campaign owner can manage sharing") target_username = body.get("username", "").strip() if not target_username: raise HTTPException(400, "username is required") target = db.get_user_by_username(target_username) if not target: raise HTTPException(404, "User not found") if target["id"] == campaign["created_by"]: raise HTTPException(400, "Cannot share campaign with its owner") role = body.get("role", "editor") db.share_campaign(campaign_id, target["id"], role) return {"ok": True} @router.delete("/{campaign_id}/shares") def remove_share(campaign_id: str, body: dict, user: dict = Depends(require_user)): campaign = db.get_campaign(campaign_id) if not campaign: raise HTTPException(404, "Campaign not found") if campaign.get("created_by") != user["id"] and not user.get("is_admin"): raise HTTPException(403, "Only the campaign owner can manage sharing") target_username = body.get("username", "").strip() if not target_username: raise HTTPException(400, "username is required") target = db.get_user_by_username(target_username) if not target: raise HTTPException(404, "User not found") db.unshare_campaign(campaign_id, target["id"]) return {"ok": True}