feat: add notification preferences database & audit support (#14100)

This commit is contained in:
Danny Kopping
2024-08-05 16:18:45 +02:00
committed by GitHub
parent 49a2880abc
commit e164b1e71c
49 changed files with 3229 additions and 368 deletions
+172 -12
View File
@@ -3335,14 +3335,18 @@ SELECT
nm.id,
nm.payload,
nm.method,
nm.attempt_count::int AS attempt_count,
nm.queued_seconds::float AS queued_seconds,
nm.attempt_count::int AS attempt_count,
nm.queued_seconds::float AS queued_seconds,
-- template
nt.id AS template_id,
nt.id AS template_id,
nt.title_template,
nt.body_template
nt.body_template,
-- preferences
(CASE WHEN np.disabled IS NULL THEN false ELSE np.disabled END)::bool AS disabled
FROM acquired nm
JOIN notification_templates nt ON nm.notification_template_id = nt.id
LEFT JOIN notification_preferences AS np
ON (np.user_id = nm.user_id AND np.notification_template_id = nm.notification_template_id)
`
type AcquireNotificationMessagesParams struct {
@@ -3361,6 +3365,7 @@ type AcquireNotificationMessagesRow struct {
TemplateID uuid.UUID `db:"template_id" json:"template_id"`
TitleTemplate string `db:"title_template" json:"title_template"`
BodyTemplate string `db:"body_template" json:"body_template"`
Disabled bool `db:"disabled" json:"disabled"`
}
// Acquires the lease for a given count of notification messages, to enable concurrent dequeuing and subsequent sending.
@@ -3396,6 +3401,7 @@ func (q *sqlQuerier) AcquireNotificationMessages(ctx context.Context, arg Acquir
&i.TemplateID,
&i.TitleTemplate,
&i.BodyTemplate,
&i.Disabled,
); err != nil {
return nil, err
}
@@ -3534,10 +3540,11 @@ func (q *sqlQuerier) EnqueueNotificationMessage(ctx context.Context, arg Enqueue
const fetchNewMessageMetadata = `-- name: FetchNewMessageMetadata :one
SELECT nt.name AS notification_name,
nt.actions AS actions,
nt.method AS custom_method,
u.id AS user_id,
u.email AS user_email,
COALESCE(NULLIF(u.name, ''), NULLIF(u.username, ''))::text AS user_name,
COALESCE(u.username, '') AS user_username
u.username AS user_username
FROM notification_templates nt,
users u
WHERE nt.id = $1
@@ -3550,12 +3557,13 @@ type FetchNewMessageMetadataParams struct {
}
type FetchNewMessageMetadataRow struct {
NotificationName string `db:"notification_name" json:"notification_name"`
Actions []byte `db:"actions" json:"actions"`
UserID uuid.UUID `db:"user_id" json:"user_id"`
UserEmail string `db:"user_email" json:"user_email"`
UserName string `db:"user_name" json:"user_name"`
UserUsername string `db:"user_username" json:"user_username"`
NotificationName string `db:"notification_name" json:"notification_name"`
Actions []byte `db:"actions" json:"actions"`
CustomMethod NullNotificationMethod `db:"custom_method" json:"custom_method"`
UserID uuid.UUID `db:"user_id" json:"user_id"`
UserEmail string `db:"user_email" json:"user_email"`
UserName string `db:"user_name" json:"user_name"`
UserUsername string `db:"user_username" json:"user_username"`
}
// This is used to build up the notification_message's JSON payload.
@@ -3565,6 +3573,7 @@ func (q *sqlQuerier) FetchNewMessageMetadata(ctx context.Context, arg FetchNewMe
err := row.Scan(
&i.NotificationName,
&i.Actions,
&i.CustomMethod,
&i.UserID,
&i.UserEmail,
&i.UserName,
@@ -3574,7 +3583,10 @@ func (q *sqlQuerier) FetchNewMessageMetadata(ctx context.Context, arg FetchNewMe
}
const getNotificationMessagesByStatus = `-- name: GetNotificationMessagesByStatus :many
SELECT id, notification_template_id, user_id, method, status, status_reason, created_by, payload, attempt_count, targets, created_at, updated_at, leased_until, next_retry_after, queued_seconds FROM notification_messages WHERE status = $1 LIMIT $2::int
SELECT id, notification_template_id, user_id, method, status, status_reason, created_by, payload, attempt_count, targets, created_at, updated_at, leased_until, next_retry_after, queued_seconds
FROM notification_messages
WHERE status = $1
LIMIT $2::int
`
type GetNotificationMessagesByStatusParams struct {
@@ -3621,6 +3633,154 @@ func (q *sqlQuerier) GetNotificationMessagesByStatus(ctx context.Context, arg Ge
return items, nil
}
const getNotificationTemplateByID = `-- name: GetNotificationTemplateByID :one
SELECT id, name, title_template, body_template, actions, "group", method, kind
FROM notification_templates
WHERE id = $1::uuid
`
func (q *sqlQuerier) GetNotificationTemplateByID(ctx context.Context, id uuid.UUID) (NotificationTemplate, error) {
row := q.db.QueryRowContext(ctx, getNotificationTemplateByID, id)
var i NotificationTemplate
err := row.Scan(
&i.ID,
&i.Name,
&i.TitleTemplate,
&i.BodyTemplate,
&i.Actions,
&i.Group,
&i.Method,
&i.Kind,
)
return i, err
}
const getNotificationTemplatesByKind = `-- name: GetNotificationTemplatesByKind :many
SELECT id, name, title_template, body_template, actions, "group", method, kind
FROM notification_templates
WHERE kind = $1::notification_template_kind
`
func (q *sqlQuerier) GetNotificationTemplatesByKind(ctx context.Context, kind NotificationTemplateKind) ([]NotificationTemplate, error) {
rows, err := q.db.QueryContext(ctx, getNotificationTemplatesByKind, kind)
if err != nil {
return nil, err
}
defer rows.Close()
var items []NotificationTemplate
for rows.Next() {
var i NotificationTemplate
if err := rows.Scan(
&i.ID,
&i.Name,
&i.TitleTemplate,
&i.BodyTemplate,
&i.Actions,
&i.Group,
&i.Method,
&i.Kind,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getUserNotificationPreferences = `-- name: GetUserNotificationPreferences :many
SELECT user_id, notification_template_id, disabled, created_at, updated_at
FROM notification_preferences
WHERE user_id = $1::uuid
`
func (q *sqlQuerier) GetUserNotificationPreferences(ctx context.Context, userID uuid.UUID) ([]NotificationPreference, error) {
rows, err := q.db.QueryContext(ctx, getUserNotificationPreferences, userID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []NotificationPreference
for rows.Next() {
var i NotificationPreference
if err := rows.Scan(
&i.UserID,
&i.NotificationTemplateID,
&i.Disabled,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const updateNotificationTemplateMethodByID = `-- name: UpdateNotificationTemplateMethodByID :one
UPDATE notification_templates
SET method = $1::notification_method
WHERE id = $2::uuid
RETURNING id, name, title_template, body_template, actions, "group", method, kind
`
type UpdateNotificationTemplateMethodByIDParams struct {
Method NullNotificationMethod `db:"method" json:"method"`
ID uuid.UUID `db:"id" json:"id"`
}
func (q *sqlQuerier) UpdateNotificationTemplateMethodByID(ctx context.Context, arg UpdateNotificationTemplateMethodByIDParams) (NotificationTemplate, error) {
row := q.db.QueryRowContext(ctx, updateNotificationTemplateMethodByID, arg.Method, arg.ID)
var i NotificationTemplate
err := row.Scan(
&i.ID,
&i.Name,
&i.TitleTemplate,
&i.BodyTemplate,
&i.Actions,
&i.Group,
&i.Method,
&i.Kind,
)
return i, err
}
const updateUserNotificationPreferences = `-- name: UpdateUserNotificationPreferences :execrows
INSERT
INTO notification_preferences (user_id, notification_template_id, disabled)
SELECT $1::uuid, new_values.notification_template_id, new_values.disabled
FROM (SELECT UNNEST($2::uuid[]) AS notification_template_id,
UNNEST($3::bool[]) AS disabled) AS new_values
ON CONFLICT (user_id, notification_template_id) DO UPDATE
SET disabled = EXCLUDED.disabled,
updated_at = CURRENT_TIMESTAMP
`
type UpdateUserNotificationPreferencesParams struct {
UserID uuid.UUID `db:"user_id" json:"user_id"`
NotificationTemplateIds []uuid.UUID `db:"notification_template_ids" json:"notification_template_ids"`
Disableds []bool `db:"disableds" json:"disableds"`
}
func (q *sqlQuerier) UpdateUserNotificationPreferences(ctx context.Context, arg UpdateUserNotificationPreferencesParams) (int64, error) {
result, err := q.db.ExecContext(ctx, updateUserNotificationPreferences, arg.UserID, pq.Array(arg.NotificationTemplateIds), pq.Array(arg.Disableds))
if err != nil {
return 0, err
}
return result.RowsAffected()
}
const deleteOAuth2ProviderAppByID = `-- name: DeleteOAuth2ProviderAppByID :exec
DELETE FROM oauth2_provider_apps WHERE id = $1
`