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

- 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:
openhands committed 2026-07-18 14:04:41 +02:00
1 parent 8bf48f46e7
commit 83f4585167
30 files changed
+2196 -51

No files matched your search

+47
View File
@@ -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")
}