diff --git a/misc/BreCalApi.yaml b/misc/BreCalApi.yaml index 4bac560..0e4cf5f 100644 --- a/misc/BreCalApi.yaml +++ b/misc/BreCalApi.yaml @@ -658,12 +658,12 @@ paths: - notification operationId: notificationsGet parameters: - - name: shipcall_id + - name: participant_id in: query required: false - description: '**Id of ship call**. *Example: 52*. Id given in ship call list' + description: '**Id of participant**. *Example: 7*. Id of logged in participant.' schema: - $ref: '#/components/schemas/shipcallId' + $ref: '#/components/schemas/participant_id' responses: '200': description: notification list diff --git a/src/server/BreCal/api/notifications.py b/src/server/BreCal/api/notifications.py index c05d52e..7b715d2 100644 --- a/src/server/BreCal/api/notifications.py +++ b/src/server/BreCal/api/notifications.py @@ -14,7 +14,14 @@ def GetNotifications(): try: if 'Authorization' in request.headers: token = request.headers.get('Authorization') - return impl.notifications.GetNotifications(token) + participant_id = None + if 'participant_id' in request.args: + try: + participant_id = int(request.args.get('participant_id')) + except (TypeError, ValueError): + return create_dynamic_exception_response(ex=None, status_code=400, message="participant_id must be an integer") + + return impl.notifications.GetNotifications(token, participant_id=participant_id) else: return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated") diff --git a/src/server/BreCal/impl/login.py b/src/server/BreCal/impl/login.py index f1d7d00..bfc16cd 100644 --- a/src/server/BreCal/impl/login.py +++ b/src/server/BreCal/impl/login.py @@ -39,7 +39,7 @@ def GetUser(options): "notify_whatsapp": data[0].notify_whatsapp, "notify_signal": data[0].notify_signal, "notify_popup": data[0].notify_popup, - "notify_on": model.bitflag_to_list(data[0].notify_event) + "notify_on": model.notification_types_to_names(model.bitflag_to_list(data[0].notify_event)) } token = jwt_handler.generate_jwt(payload=result, lifetime=120) # generate token valid 60 mins result["token"] = token # add token to user data diff --git a/src/server/BreCal/impl/notifications.py b/src/server/BreCal/impl/notifications.py index ea1ecb5..49a2d41 100644 --- a/src/server/BreCal/impl/notifications.py +++ b/src/server/BreCal/impl/notifications.py @@ -6,17 +6,22 @@ from ..schemas import model from .. import local_db from BreCal.database.sql_queries import SQLQuery -def GetNotifications(token): +def GetNotifications(token, participant_id=None): """ - No parameters, gets all entries + Optional filtering by participant_id. Returns delivered (level=2) notifications. """ pooledConnection = None try: pooledConnection = local_db.getPoolConnection() commands = pydapper.using(pooledConnection) - data = commands.query("SELECT id, shipcall_id, participant_id, level, type, message, created, modified FROM notification " + - "WHERE level = 2", model=model.Notification.from_query_row) + query = "SELECT id, shipcall_id, participant_id, level, type, message, created, modified FROM notification WHERE level = 2" + params = {} + if participant_id is not None: + query += " AND participant_id = ?participant_id?" + params["participant_id"] = participant_id + + data = commands.query(query, model=model.Notification.from_query_row, param=params if params else None) except Exception as ex: logging.error(ex) diff --git a/src/server/BreCal/schemas/model.py b/src/server/BreCal/schemas/model.py index 89218d7..dc99e61 100644 --- a/src/server/BreCal/schemas/model.py +++ b/src/server/BreCal/schemas/model.py @@ -5,7 +5,7 @@ from marshmallow_enum import EnumField from enum import IntEnum from marshmallow_dataclass import dataclass -from typing import List +from typing import Iterable, List import json import re @@ -85,19 +85,31 @@ class NotificationType(IntEnum): def _missing_(cls, value): return cls.undefined -def bitflag_to_list(bitflag: int) -> list[NotificationType]: +def bitflag_to_list(bitflag: int | None) -> list[NotificationType]: + """Converts an integer bitflag to a list of NotificationType enums.""" if bitflag is None: return [] - """Converts an integer bitflag to a list of NotificationType enums.""" return [nt for nt in NotificationType if bitflag & (1 << (nt.value - 1))] -def list_to_bitflag(notifications: fields.List) -> int: - """Converts a list of NotificationType enums to an integer bitflag.""" - try: - iter(notifications) - return sum(1 << (nt.value - 1) for nt in notifications) - except TypeError as te: +def list_to_bitflag(notifications: Iterable[NotificationType | str | int] | None) -> int: + """Converts a list of NotificationType enums (or their names/values) to an integer bitflag.""" + if not notifications: return 0 + bitflag = 0 + for nt in notifications: + enum_val = None + if isinstance(nt, NotificationType): + enum_val = nt + elif isinstance(nt, str): + enum_val = NotificationType[nt] + else: + enum_val = NotificationType(nt) + bitflag |= 1 << (enum_val.value - 1) + return bitflag + +def notification_types_to_names(notifications: Iterable[NotificationType]) -> list[str]: + """Render NotificationType values as their names for API responses.""" + return [nt.name for nt in notifications] class ShipcallType(IntEnum): @@ -573,8 +585,7 @@ class User: notify_popup: bool created: datetime modified: datetime - ports: List[NotificationType] = field(default_factory=list) - notify_event: List[NotificationType] = field(default_factory=list) + notify_event: int | None = 0 def __hash__(self): return hash(id)