feat(notifications): add per-tenant notification preferences
This commit is contained in:
@@ -111,6 +111,42 @@ export class NotificationService {
|
||||
}
|
||||
}
|
||||
|
||||
async preferences(tenantId: number, userId: string) {
|
||||
const events = await this.server.db.select().from(notificationsEventTypes)
|
||||
.where(eq(notificationsEventTypes.isActive, true))
|
||||
const rows = []
|
||||
for (const event of events.filter((event) => event.category !== "system")) {
|
||||
const channels = this.normalizeChannels(event.allowedChannels).filter((channel) => channel === "email" || channel === "push")
|
||||
const enabled = await this.resolveEnabledChannels({ tenantId, userId, eventType: event.eventKey, channels })
|
||||
rows.push({ eventKey: event.eventKey, displayName: event.displayName, description: event.description,
|
||||
channels: Object.fromEntries(channels.map((channel) => [channel, enabled.includes(channel)])) })
|
||||
}
|
||||
return { tenantId, events: rows }
|
||||
}
|
||||
|
||||
async savePreferences(tenantId: number, userId: string, input: unknown) {
|
||||
const invalid = () => Object.assign(new Error("Ungültige Benachrichtigungseinstellungen"), { statusCode: 400 })
|
||||
if (!Array.isArray(input) || input.length > 200) throw invalid()
|
||||
const available = await this.preferences(tenantId, userId)
|
||||
const seen = new Set<string>()
|
||||
const values = input.map((value) => {
|
||||
if (!value || typeof value !== "object") throw invalid()
|
||||
const { eventType, channel, enabled } = value
|
||||
if (typeof eventType !== "string" || (channel !== "email" && channel !== "push")) throw invalid()
|
||||
const event = available.events.find((event) => event.eventKey === eventType)
|
||||
const key = `${eventType}:${channel}`
|
||||
if (!event || !Object.prototype.hasOwnProperty.call(event.channels, channel) || typeof enabled !== "boolean" || seen.has(key)) throw invalid()
|
||||
seen.add(key)
|
||||
return { tenantId, userId, eventType: String(eventType), channel: channel as NotificationChannel, enabled }
|
||||
})
|
||||
await this.server.db.transaction(async (tx) => {
|
||||
for (const value of values) await tx.insert(notificationsPreferences).values(value)
|
||||
.onConflictDoUpdate({ target: [notificationsPreferences.tenantId, notificationsPreferences.userId,
|
||||
notificationsPreferences.eventType, notificationsPreferences.channel], set: { enabled: value.enabled } })
|
||||
})
|
||||
return await this.preferences(tenantId, userId)
|
||||
}
|
||||
|
||||
async listForUser(tenantId: number, userId: string, limit = 50) {
|
||||
return await this.server.db
|
||||
.select()
|
||||
@@ -259,7 +295,7 @@ export class NotificationService {
|
||||
const defaultPref = defaults.find((pref) => pref.channel === channel)
|
||||
if (defaultPref) return defaultPref.enabled
|
||||
|
||||
return true
|
||||
return channel !== "email" && input.eventType !== "communication.message.room" && input.eventType !== "communication.room.invited"
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user