Feature: Plugin UI, event hooks, DB notifications, web push, webhook retry, games pages, rate limiting, tests
Local Build and Deploy / deploy (push) Successful in 1m5s
Local Build and Deploy / deploy (push) Successful in 1m5s
- Plugin admin UI: enable/disable per plugin with config forms - Event hooks system: HookManager with on/off/emit for plugin events - Database notifications: persistent via WebsiteNotification table + Redis pub/sub - Notification preferences: per-user settings with API endpoints - Web Push API: browser push notification subscription - Webhook retry: 3 attempts with exponential backoff (1s/3s/9s) + delivery logs - Webhook test button + paginated delivery log viewer - Games: rank/challenge/reward admin pages - Games: public frontend leaderboard - Rate limiting: search API (30/min), notification stream dedup - Unit tests: 28 new tests (registry, notifications, webhooks) - Prisma migration 0017: website_notifications, website_notification_preferences, website_webhook_logs
This commit is contained in:
1 parent
8bf48f46e7
commit
83f4585167
30 files changed
+2196
-51
No files matched your search
@@ -0,0 +1,48 @@
|
||||
-- Notifications
|
||||
CREATE TABLE IF NOT EXISTS `website_notifications` (
|
||||
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`user_id` BIGINT UNSIGNED NOT NULL,
|
||||
`type` VARCHAR(50) NOT NULL,
|
||||
`title` VARCHAR(255) NOT NULL,
|
||||
`body` TEXT DEFAULT NULL,
|
||||
`icon` VARCHAR(50) DEFAULT NULL,
|
||||
`link` VARCHAR(500) DEFAULT NULL,
|
||||
`read` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`created_at` TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `idx_user_read` (`user_id`, `read`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Notification preferences
|
||||
CREATE TABLE IF NOT EXISTS `website_notification_preferences` (
|
||||
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`user_id` BIGINT UNSIGNED NOT NULL,
|
||||
`email_enabled` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`push_enabled` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`friend_request` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`messages` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`guild_invite` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`events` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`alerts` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`achievements` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`radio` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_user` (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Webhook delivery logs
|
||||
CREATE TABLE IF NOT EXISTS `website_webhook_logs` (
|
||||
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`webhook_id` VARCHAR(100) NOT NULL,
|
||||
`url` VARCHAR(500) NOT NULL,
|
||||
`event` VARCHAR(100) NOT NULL,
|
||||
`status` INT NOT NULL DEFAULT 0,
|
||||
`response` TEXT DEFAULT NULL,
|
||||
`duration` INT NOT NULL DEFAULT 0,
|
||||
`success` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`created_at` TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `idx_webhook_logs` (`webhook_id`, `created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Migration tracking
|
||||
@@ -2759,3 +2759,50 @@ model WebsitePollVote {
|
||||
@@index([userId])
|
||||
@@map("website_poll_votes")
|
||||
}
|
||||
|
||||
model WebsiteNotification {
|
||||
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
|
||||
userId BigInt @map("user_id") @db.UnsignedBigInt
|
||||
type String @db.VarChar(50)
|
||||
title String @db.VarChar(255)
|
||||
body String? @db.Text
|
||||
icon String? @db.VarChar(50)
|
||||
link String? @db.VarChar(500)
|
||||
read Boolean @default(false)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.Timestamp(0)
|
||||
|
||||
@@index([userId, read])
|
||||
@@map("website_notifications")
|
||||
}
|
||||
|
||||
model WebsiteNotificationPreference {
|
||||
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
|
||||
userId BigInt @map("user_id") @db.UnsignedBigInt
|
||||
emailEnabled Boolean @default(true) @map("email_enabled")
|
||||
pushEnabled Boolean @default(true) @map("push_enabled")
|
||||
friendRequest Boolean @default(true) @map("friend_request")
|
||||
messages Boolean @default(true)
|
||||
guildInvite Boolean @default(true) @map("guild_invite")
|
||||
events Boolean @default(true)
|
||||
alerts Boolean @default(true)
|
||||
achievements Boolean @default(true)
|
||||
radio Boolean @default(true)
|
||||
|
||||
@@unique([userId])
|
||||
@@map("website_notification_preferences")
|
||||
}
|
||||
|
||||
model WebsiteWebhookLog {
|
||||
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
|
||||
webhookId String @map("webhook_id") @db.VarChar(100)
|
||||
url String @db.VarChar(500)
|
||||
event String @db.VarChar(100)
|
||||
status Int @default(0)
|
||||
response String? @db.Text
|
||||
duration Int @default(0)
|
||||
success Boolean @default(false)
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.Timestamp(0)
|
||||
|
||||
@@index([webhookId, createdAt])
|
||||
@@map("website_webhook_logs")
|
||||
}
|
||||
Reference in new issue
Block a user