From 21a661f4ad2f206eaa54458ae5129bb2ad115915 Mon Sep 17 00:00:00 2001 From: armanddidierjean <95971503+armanddidierjean@users.noreply.github.com> Date: Sat, 28 Jun 2025 20:16:47 +0200 Subject: [PATCH] Admin endpoint to send notification to group --- .../notification/endpoints_notification.py | 45 ++++++++++++++----- app/core/notification/schemas_notification.py | 6 +++ app/utils/communication/notifications.py | 23 ++++++++++ tests/test_notification.py | 45 +++++++++++++++++++ 4 files changed, 109 insertions(+), 10 deletions(-) diff --git a/app/core/notification/endpoints_notification.py b/app/core/notification/endpoints_notification.py index bd2bac34f4..da62c96920 100644 --- a/app/core/notification/endpoints_notification.py +++ b/app/core/notification/endpoints_notification.py @@ -244,9 +244,34 @@ async def get_topic_identifier( @router.post( "/notification/send", - status_code=201, + status_code=204, ) async def send_notification( + notification_request: schemas_notification.GroupNotificationRequest, + user: models_users.CoreUser = Depends(is_user_in(GroupType.admin)), + notification_tool: NotificationTool = Depends(get_notification_tool), +): + """ + Send a notification to a group. + + **Only admins can use this endpoint** + """ + message = schemas_notification.Message( + title=notification_request.title, + content=notification_request.content, + action_module="", + ) + await notification_tool.send_notification_to_group( + group_id=notification_request.group_id, + message=message, + ) + + +@router.post( + "/notification/test/send", + status_code=201, +) +async def send_test_notification( user: models_users.CoreUser = Depends(is_user_in(GroupType.admin)), notification_tool: NotificationTool = Depends(get_notification_tool), ): @@ -267,10 +292,10 @@ async def send_notification( @router.post( - "/notification/send/future", - status_code=201, + "/notification/test/send/future", + status_code=204, ) -async def send_future_notification( +async def send_test_future_notification( user: models_users.CoreUser = Depends(is_user_in(GroupType.admin)), notification_tool: NotificationTool = Depends(get_notification_tool), scheduler: Scheduler = Depends(get_scheduler), @@ -295,10 +320,10 @@ async def send_future_notification( @router.post( - "/notification/send/topic", - status_code=201, + "/notification/test/send/topic", + status_code=204, ) -async def send_notification_topic( +async def send_test_notification_topic( user: models_users.CoreUser = Depends(is_user_in(GroupType.admin)), notification_tool: NotificationTool = Depends(get_notification_tool), ): @@ -319,10 +344,10 @@ async def send_notification_topic( @router.post( - "/notification/send/topic/future", - status_code=201, + "/notification/test/send/topic/future", + status_code=204, ) -async def send_future_notification_topic( +async def send_test_future_notification_topic( user: models_users.CoreUser = Depends(is_user_in(GroupType.admin)), notification_tool: NotificationTool = Depends(get_notification_tool), scheduler: Scheduler = Depends(get_scheduler), diff --git a/app/core/notification/schemas_notification.py b/app/core/notification/schemas_notification.py index 8714643552..aeed256f58 100644 --- a/app/core/notification/schemas_notification.py +++ b/app/core/notification/schemas_notification.py @@ -11,3 +11,9 @@ class Message(BaseModel): class FirebaseDevice(BaseModel): user_id: str = Field(description="The Hyperion user id") firebase_device_token: str = Field("Firebase device token") + + +class GroupNotificationRequest(BaseModel): + group_id: str + title: str + content: str diff --git a/app/utils/communication/notifications.py b/app/utils/communication/notifications.py index 057669e2dc..8edc9f0ce4 100644 --- a/app/utils/communication/notifications.py +++ b/app/utils/communication/notifications.py @@ -9,6 +9,7 @@ from app.core.notification import cruds_notification, models_notification from app.core.notification.notification_types import CustomTopic from app.core.notification.schemas_notification import Message +from app.core.users import cruds_users from app.core.utils.config import Settings from app.types.scheduler import Scheduler @@ -327,6 +328,28 @@ def __init__( self.db = db # self.scheduler = scheduler + async def send_notification_to_group( + self, + group_id: str, + message: Message, + scheduler: Scheduler | None = None, + defer_date: datetime | None = None, + job_id: str | None = None, + ): + users = await cruds_users.get_users( + included_groups=[group_id], + db=self.db, + ) + user_ids = [user.id for user in users] + + await self.send_notification_to_users( + user_ids=user_ids, + message=message, + scheduler=scheduler, + defer_date=defer_date, + job_id=job_id, + ) + async def send_notification_to_users( self, user_ids: list[str], diff --git a/tests/test_notification.py b/tests/test_notification.py index a7e7c4fff7..a7461ef948 100644 --- a/tests/test_notification.py +++ b/tests/test_notification.py @@ -156,3 +156,48 @@ def test_get_topic_identifier(client: TestClient) -> None: ) assert response.status_code == 200 assert response.json() == [TOPIC_2] + + +def test_send_notification_to_group(client: TestClient) -> None: + response = client.post( + "/notification/send", + json={ + "title": "Test Notification", + "content": "This is a test notification.", + "group_id": GroupType.admin.value, + }, + headers={ + "Authorization": f"Bearer {admin_user_token}", + }, + ) + assert response.status_code == 204 + + +def test_send_test_future_notification(client: TestClient) -> None: + response = client.post( + "/notification/test/send/future", + headers={ + "Authorization": f"Bearer {admin_user_token}", + }, + ) + assert response.status_code == 204 + + +def test_send_test_notification_topic(client: TestClient) -> None: + response = client.post( + "/notification/test/send/topic", + headers={ + "Authorization": f"Bearer {admin_user_token}", + }, + ) + assert response.status_code == 204 + + +def test_send_test_future_notification_topic(client: TestClient) -> None: + response = client.post( + "/notification/test/send/topic/future", + headers={ + "Authorization": f"Bearer {admin_user_token}", + }, + ) + assert response.status_code == 204