Sith/com/api.py

105 lines
3.5 KiB
Python
Raw Normal View History

2025-01-03 01:48:18 +01:00
from pathlib import Path
2025-02-17 13:29:12 +01:00
from typing import Literal
2025-01-03 01:48:18 +01:00
from django.conf import settings
2025-02-20 17:47:51 +01:00
from django.http import Http404, HttpResponse
2025-02-17 13:29:12 +01:00
from ninja import Query
from ninja_extra import ControllerBase, api_controller, paginate, route
from ninja_extra.pagination import PageNumberPaginationExtra
2025-02-20 17:47:51 +01:00
from ninja_extra.permissions import IsAuthenticated
2025-02-17 13:29:12 +01:00
from ninja_extra.schemas import PaginatedResponseSchema
2025-01-04 18:57:31 +01:00
from com.calendar import IcsCalendar
2025-02-17 13:29:12 +01:00
from com.models import News, NewsDate
from com.schemas import NewsDateFilterSchema, NewsDateSchema
2025-01-20 17:03:25 +01:00
from core.auth.api_permissions import HasPerm
2025-01-03 01:48:18 +01:00
from core.views.files import send_raw_file
@api_controller("/calendar")
class CalendarController(ControllerBase):
2025-01-03 01:48:18 +01:00
CACHE_FOLDER: Path = settings.MEDIA_ROOT / "com" / "calendars"
2025-01-05 01:04:11 +01:00
@route.get("/external.ics", url_name="calendar_external")
def calendar_external(self):
"""Return the ICS file of the AE Google Calendar
2025-01-04 18:57:31 +01:00
Because of Google's cors rules, we can't just do a request to google ics
2025-01-20 17:03:25 +01:00
from the frontend. Google is blocking CORS request in its responses headers.
The only way to do it from the frontend is to use Google Calendar API with an API key
This is not especially desirable as your API key is going to be provided to the frontend.
This is why we have this backend based solution.
"""
if (calendar := IcsCalendar.get_external()) is not None:
return send_raw_file(calendar)
raise Http404
2025-01-05 01:04:11 +01:00
@route.get("/internal.ics", url_name="calendar_internal")
def calendar_internal(self):
2025-01-03 13:56:40 +01:00
return send_raw_file(IcsCalendar.get_internal())
2025-01-20 17:03:25 +01:00
2025-02-20 17:47:51 +01:00
@route.get(
"/unmoderated.ics",
permissions=[IsAuthenticated],
url_name="calendar_unmoderated",
)
def calendar_unmoderated(self):
return HttpResponse(
IcsCalendar.get_unmoderated(self.context.request.user),
content_type="text/calendar",
)
2025-01-20 17:03:25 +01:00
@api_controller("/news")
class NewsController(ControllerBase):
@route.patch(
2025-02-17 13:29:12 +01:00
"/{int:news_id}/moderate",
2025-01-20 17:03:25 +01:00
permissions=[HasPerm("com.moderate_news")],
url_name="moderate_news",
)
def moderate_news(self, news_id: int):
news = self.get_object_or_exception(News, id=news_id)
if not news.is_moderated:
news.is_moderated = True
2025-01-23 14:32:10 +01:00
news.moderator = self.context.request.user
2025-01-20 17:03:25 +01:00
news.save()
@route.patch(
"/{int:news_id}/remove",
permissions=[HasPerm("com.moderate_news")],
url_name="remove_news",
)
def remove_news(self, news_id: int):
news = self.get_object_or_exception(News, id=news_id)
if news.is_moderated:
news.is_moderated = False
news.moderator = self.context.request.user
news.save()
2025-01-20 17:03:25 +01:00
@route.delete(
2025-02-17 13:29:12 +01:00
"/{int:news_id}",
2025-01-20 17:03:25 +01:00
permissions=[HasPerm("com.delete_news")],
url_name="delete_news",
)
def delete_news(self, news_id: int):
news = self.get_object_or_exception(News, id=news_id)
news.delete()
2025-02-17 13:29:12 +01:00
@route.get(
"/date",
url_name="fetch_news_dates",
response=PaginatedResponseSchema[NewsDateSchema],
)
@paginate(PageNumberPaginationExtra, page_size=50)
def fetch_news_dates(
self,
filters: Query[NewsDateFilterSchema],
text_format: Literal["md", "html"] = "md",
):
return filters.filter(
NewsDate.objects.viewable_by(self.context.request.user)
.order_by("start_date")
.select_related("news", "news__club")
)