1
0

chore: snapshot notifications hardening and css/docs alignment

This commit is contained in:
2026-03-20 00:05:03 +01:00
parent fb6e30a062
commit 60c27e50cb
41 changed files with 1862 additions and 254 deletions

View File

@@ -338,6 +338,9 @@ CREATE TABLE IF NOT EXISTS `user_notifications` (
`body` VARCHAR(500) NULL,
`link` VARCHAR(500) NULL,
`data` JSON NULL,
`dedupe_fingerprint` CHAR(64) NULL,
`dedupe_bucket` INT UNSIGNED NULL,
`dedupe_until` DATETIME NULL DEFAULT NULL,
`is_read` TINYINT(1) NOT NULL DEFAULT 0,
`read_at` DATETIME NULL DEFAULT NULL,
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
@@ -346,6 +349,7 @@ CREATE TABLE IF NOT EXISTS `user_notifications` (
KEY `idx_un_recipient_created` (`recipient_user_id`, `created` DESC),
KEY `idx_un_tenant_created` (`tenant_id`, `created` DESC),
KEY `idx_un_cleanup` (`is_read`, `read_at`),
UNIQUE KEY `uniq_un_dedupe_bucket` (`recipient_user_id`, `dedupe_fingerprint`, `dedupe_bucket`),
CONSTRAINT `fk_un_recipient` FOREIGN KEY (`recipient_user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_un_tenant` FOREIGN KEY (`tenant_id`) REFERENCES `tenants` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
@@ -1048,7 +1052,8 @@ VALUES
('system_audit.purge', 'Can purge system audit logs', 1, 1),
('api_tokens.manage', 'Can manage user API tokens', 1, 1),
('stats.view', 'Can view statistics', 1, 1),
('roles.assign_all', 'Can assign all roles (bypass assignable-roles check)', 1, 1)
('roles.assign_all', 'Can assign all roles (bypass assignable-roles check)', 1, 1),
('notifications.view', 'Can view and manage own notifications', 1, 1)
ON DUPLICATE KEY UPDATE
`description` = VALUES(`description`),
`active` = VALUES(`active`),
@@ -1154,6 +1159,14 @@ JOIN permissions p ON p.`key` IN (
WHERE r.description IN ('Admin', 'Administrator') OR r.id = 1
ON DUPLICATE KEY UPDATE role_id = role_id;
-- Notifications are user-scoped and should be visible to all active roles by default.
INSERT INTO `role_permissions` (`role_id`, `permission_id`, `created`)
SELECT r.id, p.id, NOW()
FROM roles r
JOIN permissions p ON p.`key` = 'notifications.view'
WHERE r.active = 1
ON DUPLICATE KEY UPDATE role_id = role_id;
INSERT INTO `role_permissions` (`role_id`, `permission_id`, `created`)
SELECT r.id, p.id, NOW()
FROM roles r
@@ -1277,3 +1290,63 @@ VALUES
('remember_token_lifetime_days', '30', 'setting.remember_token_lifetime_days')
ON DUPLICATE KEY UPDATE
`key` = `key`;
-- =============================================
-- Seed: sample notifications for demo user
-- =============================================
INSERT INTO `user_notifications` (
`recipient_user_id`, `tenant_id`, `type`, `title`, `body`, `link`, `data`, `is_read`, `read_at`, `created`
)
SELECT
u.id,
(SELECT t.id FROM tenants t ORDER BY t.id LIMIT 1),
n.type, n.title, n.body, n.link, n.data, n.is_read, n.read_at, n.created
FROM users u
CROSS JOIN (
SELECT 'user.created' AS type,
'Neuer Benutzer: Max Mustermann' AS title,
NULL AS body,
'admin/users/edit/00000000-0000-0000-0000-000000000001' AS link,
'{"user_id":99}' AS data,
0 AS is_read,
NULL AS read_at,
DATE_SUB(NOW(), INTERVAL 5 MINUTE) AS created
UNION ALL
SELECT 'user.created',
'Neuer Benutzer: Erika Musterfrau',
NULL,
'admin/users/edit/00000000-0000-0000-0000-000000000002',
'{"user_id":98}',
0,
NULL,
DATE_SUB(NOW(), INTERVAL 30 MINUTE)
UNION ALL
SELECT 'user.deleted',
'Benutzer geloescht: Karl Schmidt',
NULL,
NULL,
'{"user_id":97}',
0,
NULL,
DATE_SUB(NOW(), INTERVAL 2 HOUR)
UNION ALL
SELECT 'system',
'Systemwartung abgeschlossen',
'Alle Dienste laufen wieder normal.',
NULL,
NULL,
1,
DATE_SUB(NOW(), INTERVAL 3 HOUR),
DATE_SUB(NOW(), INTERVAL 4 HOUR)
UNION ALL
SELECT 'user.created',
'Neuer Benutzer: Anna Weber',
NULL,
'admin/users/edit/00000000-0000-0000-0000-000000000003',
'{"user_id":96}',
1,
DATE_SUB(NOW(), INTERVAL 1 DAY),
DATE_SUB(NOW(), INTERVAL 2 DAY)
) n
WHERE u.email = 'demo@user.com'
AND NOT EXISTS (SELECT 1 FROM user_notifications un WHERE un.recipient_user_id = u.id);