Coverage for src/cstlcore/newsletter/router.py: 35%
48 statements
« prev ^ index » next coverage.py v7.9.1, created at 2026-02-19 12:46 +0000
« prev ^ index » next coverage.py v7.9.1, created at 2026-02-19 12:46 +0000
1from fastapi import APIRouter, BackgroundTasks, Depends
2from sqlmodel import Session, select, func
4from cstlcore.database.dependencies import get_session
5from cstlcore.newsletter.models import (
6 NewsletterForm,
7 NewsletterSubscribed,
8 NewsletterSubscribedCreate,
9)
10from cstlcore.newsletter.services import send_email_newsletter, verify_unsubscribe_token
11from cstlcore.settings import settings
13router = APIRouter()
16@router.post("/newsletter/send")
17async def send_newsletter(
18 newsletter_form: NewsletterForm,
19 background_tasks: BackgroundTasks,
20 session: Session = Depends(get_session),
21):
22 # Verify admin token
23 if (
24 not newsletter_form.admin_token
25 or newsletter_form.admin_token != settings.newsletter.admin_token
26 ):
27 return {"message": "Invalid admin token."}
29 # Get all subscribed emails from the newsletter subscription table
30 subscriptions = session.exec(select(NewsletterSubscribed)).all()
31 if not subscriptions:
32 return {"message": "No one is subscribed to the newsletter."}
34 # Add the email sending task to background tasks
35 background_tasks.add_task(
36 send_email_newsletter,
37 [sub.email for sub in subscriptions],
38 newsletter_form.title,
39 newsletter_form.content,
40 f"{settings.services.current}/newsletter/unsubscribe",
41 )
43 return {
44 "message": f"Newsletter queued for {len(subscriptions)} members. Emails will be sent in the background."
45 }
48@router.get("/newsletter/unsubscribe")
49async def unsubscribe_newsletter(token: str, session: Session = Depends(get_session)):
50 email_member = verify_unsubscribe_token(token)
51 if not email_member:
52 return {"message": "Invalid or expired token."}
54 # Remove the newsletter subscription
55 subscription = session.exec(
56 select(NewsletterSubscribed).where(NewsletterSubscribed.email == email_member)
57 ).first()
58 if subscription:
59 session.delete(subscription)
60 session.commit()
62 return {"ok": True}
65@router.post("/newsletter/subscribe")
66async def subscribe_newsletter(
67 subscription: NewsletterSubscribedCreate,
68 session: Session = Depends(get_session),
69):
70 # Check if email is already subscribed
71 existing_subscription = session.exec(
72 select(NewsletterSubscribed).where(
73 NewsletterSubscribed.email == subscription.email
74 )
75 ).first()
77 if existing_subscription:
78 return {"message": "Email is already subscribed to the newsletter."}
80 # Create new subscription
81 new_subscription = NewsletterSubscribed(email=subscription.email)
82 session.add(new_subscription)
83 session.commit()
84 session.refresh(new_subscription)
86 return {"ok": True}
89@router.get("/newsletter/subscribers/count")
90async def get_subscribers_count(
91 admin_token: str,
92 session: Session = Depends(get_session),
93):
94 # Verify admin token
95 if not admin_token or admin_token != settings.newsletter.admin_token:
96 return {"message": "Invalid admin token."}
98 count = session.exec(select(func.count()).select_from(NewsletterSubscribed)).one()
99 return {"count": count}
102@router.get("/newsletter/subscribers")
103async def get_subscribers_list(
104 admin_token: str,
105 session: Session = Depends(get_session),
106):
107 # Verify admin token
108 if not admin_token or admin_token != settings.newsletter.admin_token:
109 return {"message": "Invalid admin token."}
111 subscriptions = session.exec(select(NewsletterSubscribed)).all()
112 return {"subscribers": [sub.email for sub in subscriptions], "count": len(subscriptions)}