feat(notifications): add per-tenant notification preferences
This commit is contained in:
@@ -201,32 +201,34 @@ export default async function communicationRoutes(server: FastifyInstance) {
|
||||
.from(communicationRoomMembers).where(eq(communicationRoomMembers.roomId, room.id))
|
||||
const memberIds = new Set(memberRows.map((member) => member.userId))
|
||||
const normalizedText = message.body.toLowerCase()
|
||||
const recipients = users.filter((user) => {
|
||||
if (user.userId === senderId || !memberIds.has(user.userId)) return false
|
||||
if (room.type === "direct") return true
|
||||
const recipients = users.filter((user) => user.userId !== senderId && memberIds.has(user.userId))
|
||||
const isMentioned = (user: ChatUser) => {
|
||||
const aliases = [displayName(user), user.fullName, user.firstName, user.email]
|
||||
.filter(Boolean).map((value) => String(value).toLowerCase())
|
||||
return aliases.some((alias) => normalizedText.includes(`@${alias}`))
|
||||
})
|
||||
}
|
||||
if (!recipients.length) return
|
||||
const senderName = sender ? displayName(sender) : "FEDEO"
|
||||
await notifications.trigger({
|
||||
tenantId,
|
||||
userIds: recipients.map((recipient) => recipient.userId),
|
||||
eventType: "communication.message.new",
|
||||
title: room.type === "direct" ? `Neue Direktnachricht von ${senderName}` : `${senderName} hat dich erwähnt`,
|
||||
message: message.body.length > 160 ? `${message.body.slice(0, 157)}...` : message.body,
|
||||
payload: {
|
||||
link: `/communication/chat?room=${encodeURIComponent(room.key)}`,
|
||||
roomKey: room.key,
|
||||
roomName: room.name,
|
||||
roomType: room.type,
|
||||
messageId: message.id,
|
||||
mentioned: room.type !== "direct",
|
||||
direct: room.type === "direct",
|
||||
},
|
||||
channels: ["inapp", "push"],
|
||||
})
|
||||
for (const eventType of ["communication.message.direct", "communication.message.mentioned", "communication.message.room"]) {
|
||||
const targets = recipients.filter((user) => (room.type === "direct" ? "communication.message.direct" : isMentioned(user) ? "communication.message.mentioned" : "communication.message.room") === eventType)
|
||||
if (!targets.length) continue
|
||||
await notifications.trigger({
|
||||
tenantId,
|
||||
userIds: targets.map((recipient) => recipient.userId),
|
||||
eventType,
|
||||
title: room.type === "direct" ? `Neue Direktnachricht von ${senderName}` : eventType === "communication.message.mentioned" ? `${senderName} hat dich erwähnt` : `Neue Nachricht in ${room.name}`,
|
||||
message: message.body.length > 160 ? `${message.body.slice(0, 157)}...` : message.body,
|
||||
payload: {
|
||||
link: `/communication/chat?room=${encodeURIComponent(room.key)}`,
|
||||
roomKey: room.key,
|
||||
roomName: room.name,
|
||||
roomType: room.type,
|
||||
messageId: message.id,
|
||||
mentioned: eventType === "communication.message.mentioned",
|
||||
direct: room.type === "direct",
|
||||
},
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
server.log.error({ err }, "Chat-Benachrichtigung konnte nicht ausgelöst werden")
|
||||
}
|
||||
@@ -307,6 +309,14 @@ export default async function communicationRoutes(server: FastifyInstance) {
|
||||
return room
|
||||
})
|
||||
if (!created) return reply.code(409).send({ error: "Dieser Raumschlüssel ist bereits vergeben" })
|
||||
const recipients = userIds.filter((id) => id !== req.user.user_id)
|
||||
if (recipients.length) {
|
||||
try {
|
||||
await notifications.trigger({ tenantId, userIds: recipients, eventType: "communication.room.invited",
|
||||
title: "Neuer Chatraum", message: `Du wurdest dem Raum „${created.name}“ hinzugefügt.`,
|
||||
payload: { link: `/communication/chat?room=${encodeURIComponent(created.key)}` } })
|
||||
} catch (err) { server.log.error({ err }, "Raum-Benachrichtigung fehlgeschlagen") }
|
||||
}
|
||||
return { ...roomToApi(created), alreadyExisted: false }
|
||||
})
|
||||
|
||||
|
||||
@@ -23,6 +23,12 @@ const requireTenant = (tenantId: number | null) => {
|
||||
export default async function notificationsRoutes(server: FastifyInstance) {
|
||||
const svc = new NotificationService(server, getUserDirectory)
|
||||
|
||||
server.get("/notifications/preferences", async (req) =>
|
||||
svc.preferences(requireTenant(req.user.tenant_id), req.user.user_id))
|
||||
|
||||
server.put("/notifications/preferences", async (req) =>
|
||||
svc.savePreferences(requireTenant(req.user.tenant_id), req.user.user_id, req.body))
|
||||
|
||||
server.get("/notifications", async (req) => {
|
||||
const limit = Number((req.query as { limit?: string })?.limit || 50)
|
||||
return await svc.listForUser(requireTenant(req.user.tenant_id), req.user.user_id, limit)
|
||||
|
||||
Reference in New Issue
Block a user