feat(api): расширенная админ-панель инстанса (Фаза 7)
Статистика, карточка пользователя и работа с журналом для администратора
инстанса (AGENT.md 3.2, 7.18):
- GET /instance/stats: рост пользователей и сообщений по дням, активность,
размеры базы и файлов, топы серверов по участникам и сообщениям;
- GET /instance/users/{id}: профиль, активные устройства, серверы с ролями,
события безопасности и аудит по пользователю;
- DELETE /instance/users/{id}/sessions/{sid} и POST .../reset-2fa: отзыв
одного устройства и сброс второго фактора со step-up, аудитом и записью
в события безопасности; чужой ключ администратора не сбрасывается;
- журнал инстанса: фильтры по действию, актору, цели, серверу и датам,
пагинация с общим числом, список действий и выгрузка CSV (лимит 5/мин);
- список серверов: поиск по названию, владелец, главный сервер, пагинация;
- миграция 00025: нормализованное название сервера `name_lower` — SQLite
lower() не знает кириллицу, поэтому регистр приводит приложение (как для
текста сообщений), старые записи дополняются backfill'ом при старте.
This commit is contained in:
@@ -97,6 +97,9 @@ type Server struct {
|
||||
hostCPUSampler *sysinfo.Sampler
|
||||
// metricsLimiter — отдельный лимит для ручки метрик (опрос раз в секунду).
|
||||
metricsLimiter *httpx.RateLimiter
|
||||
// auditExportLimiter — выгрузка журнала инстанса: тяжёлый ответ, поэтому
|
||||
// 5 экспортов в минуту на администратора (AGENT.md 7.18, 8.6).
|
||||
auditExportLimiter *httpx.RateLimiter
|
||||
// health — кэш тяжёлых проверок инстанса.
|
||||
health healthCache
|
||||
// presence — время последнего обновления last_seen по пользователю.
|
||||
@@ -153,9 +156,11 @@ func New(cfg config.Config, db *database.DB, logger *slog.Logger, deps Deps) *Se
|
||||
webhookSeen: map[string]time.Time{},
|
||||
// Дашборд опрашивает метрики раз в секунду: 120/мин с запасом.
|
||||
metricsLimiter: httpx.NewRateLimiter(120, 30),
|
||||
sysinfoPaths: sysinfo.DefaultPaths(),
|
||||
voice: voice.NewIssuer(cfg.LiveKitAPIKey, cfg.LiveKitAPISecret, cfg.LiveKitTokenTTL),
|
||||
voiceAdmin: voice.NewAdminClient(voice.NewIssuer(cfg.LiveKitAPIKey, cfg.LiveKitAPISecret, cfg.LiveKitTokenTTL), cfg.LiveKitAPIURL),
|
||||
// Экспорт журнала — редкое и тяжёлое действие: 5 раз в минуту.
|
||||
auditExportLimiter: httpx.NewRateLimiterWindow(5, time.Minute, 5),
|
||||
sysinfoPaths: sysinfo.DefaultPaths(),
|
||||
voice: voice.NewIssuer(cfg.LiveKitAPIKey, cfg.LiveKitAPISecret, cfg.LiveKitTokenTTL),
|
||||
voiceAdmin: voice.NewAdminClient(voice.NewIssuer(cfg.LiveKitAPIKey, cfg.LiveKitAPISecret, cfg.LiveKitTokenTTL), cfg.LiveKitAPIURL),
|
||||
}
|
||||
s.cpuSampler = sysinfo.NewSampler(s.sysinfoPaths)
|
||||
s.hostCPUSampler = sysinfo.NewHostSampler(s.sysinfoPaths)
|
||||
@@ -200,6 +205,7 @@ func New(cfg config.Config, db *database.DB, logger *slog.Logger, deps Deps) *Se
|
||||
s.registerUserRoutes(s.api)
|
||||
s.registerGuildRoutes(s.api)
|
||||
s.registerInstanceRoutes(s.api)
|
||||
s.registerInstanceExportRoutes(apiRouter)
|
||||
s.registerBanRoutes(s.api)
|
||||
s.registerMetricsRoutes(s.api)
|
||||
s.registerMessageRoutes(s.api)
|
||||
|
||||
Reference in New Issue
Block a user