Notification endpoint now filters for participant_id and fixed parsing of event type enumeration array

This commit is contained in:
Daniel Schick 2025-12-09 12:21:11 +01:00
parent 18f6d53998
commit f68e9ee218
5 changed files with 43 additions and 20 deletions

View File

@ -658,12 +658,12 @@ paths:
- notification - notification
operationId: notificationsGet operationId: notificationsGet
parameters: parameters:
- name: shipcall_id - name: participant_id
in: query in: query
required: false 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: schema:
$ref: '#/components/schemas/shipcallId' $ref: '#/components/schemas/participant_id'
responses: responses:
'200': '200':
description: notification list description: notification list

View File

@ -14,7 +14,14 @@ def GetNotifications():
try: try:
if 'Authorization' in request.headers: if 'Authorization' in request.headers:
token = request.headers.get('Authorization') 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: else:
return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated") return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated")

View File

@ -39,7 +39,7 @@ def GetUser(options):
"notify_whatsapp": data[0].notify_whatsapp, "notify_whatsapp": data[0].notify_whatsapp,
"notify_signal": data[0].notify_signal, "notify_signal": data[0].notify_signal,
"notify_popup": data[0].notify_popup, "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 token = jwt_handler.generate_jwt(payload=result, lifetime=120) # generate token valid 60 mins
result["token"] = token # add token to user data result["token"] = token # add token to user data

View File

@ -6,17 +6,22 @@ from ..schemas import model
from .. import local_db from .. import local_db
from BreCal.database.sql_queries import SQLQuery 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 pooledConnection = None
try: try:
pooledConnection = local_db.getPoolConnection() pooledConnection = local_db.getPoolConnection()
commands = pydapper.using(pooledConnection) commands = pydapper.using(pooledConnection)
data = commands.query("SELECT id, shipcall_id, participant_id, level, type, message, created, modified FROM notification " + query = "SELECT id, shipcall_id, participant_id, level, type, message, created, modified FROM notification WHERE level = 2"
"WHERE level = 2", model=model.Notification.from_query_row) 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: except Exception as ex:
logging.error(ex) logging.error(ex)

View File

@ -5,7 +5,7 @@ from marshmallow_enum import EnumField
from enum import IntEnum from enum import IntEnum
from marshmallow_dataclass import dataclass from marshmallow_dataclass import dataclass
from typing import List from typing import Iterable, List
import json import json
import re import re
@ -85,19 +85,31 @@ class NotificationType(IntEnum):
def _missing_(cls, value): def _missing_(cls, value):
return cls.undefined 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: if bitflag is None:
return [] return []
"""Converts an integer bitflag to a list of NotificationType enums."""
return [nt for nt in NotificationType if bitflag & (1 << (nt.value - 1))] return [nt for nt in NotificationType if bitflag & (1 << (nt.value - 1))]
def list_to_bitflag(notifications: fields.List) -> int: def list_to_bitflag(notifications: Iterable[NotificationType | str | int] | None) -> int:
"""Converts a list of NotificationType enums to an integer bitflag.""" """Converts a list of NotificationType enums (or their names/values) to an integer bitflag."""
try: if not notifications:
iter(notifications)
return sum(1 << (nt.value - 1) for nt in notifications)
except TypeError as te:
return 0 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): class ShipcallType(IntEnum):
@ -573,8 +585,7 @@ class User:
notify_popup: bool notify_popup: bool
created: datetime created: datetime
modified: datetime modified: datetime
ports: List[NotificationType] = field(default_factory=list) notify_event: int | None = 0
notify_event: List[NotificationType] = field(default_factory=list)
def __hash__(self): def __hash__(self):
return hash(id) return hash(id)