Skip to main content

User Management

1. Summary

Goal: Полноценная админ-панель для управления пользователями goLoot — поиск, просмотр, модерация, управление балансами.

User Value: Администратор получает полный контроль над пользователями: от просмотра детальной статистики до управления банами и валютами.


2. Business Logic

Capabilities

Таблица пользователей:

  • Пагинация: 10/25/50/100 записей
  • Поиск: по имени, username, Telegram ID
  • Сортировка: дата регистрации, уровень, scrap, xp
  • Фильтры: level (min/max), premium, banned, active, lastActivityDays

StatCards метрики:

  • Всего пользователей
  • Доступны для рассылки
  • Premium пользователи
  • Активные за 7 дней
  • Новые за 24ч
  • Забаненные

Services

СервисМетодыОписание
UserCRUDServicegetAllUsers, getUserDetailed, getUserStats, deleteUserОсновной CRUD + статистика для StatCards
UserActionsServicebanUser, unbanUser, addScrap, removeScrap, addXP, removeXP, addStreakPoints, removeStreakPointsАдминистративные действия
UserInventoryStatsServicegetUserInventory, getWithdrawalsИнвентарь и выводы
UserActivityStatsServicegetCasesList, getSpinsList, getCaseHistory, getSpinHistory, getAllQuests, getAllAchievementsСправочники и история активности
UserCraftStatsServicegetCraftHistory, getSalvageHistoryИстория крафта и salvage
UserRewardsStatsServicegetPromoCodeRedemptions, getRaffleHistory, getSeasonRewards, getAdminGrants, getBuffHistoryНаграды и баффы
UserSearchServicedelegates to UserCRUDServiceОбратная совместимость

Constants

Backend константы
// backend/src/common/constants/admin-users.constants.ts

ADMIN_USERS_CONSTANTS = {
pagination: {
defaultLimit: 10,
maxLimit: 100
},
filters: {
levelMin: 1,
levelMax: 100,
lastActivityDays: [1, 7, 30, 90]
}
}

CURRENCY_LIMITS = {
min: 1,
max: 1_000_000
}

Protection

ДействиеRate LimitAuthValidation
list usersadminApiLimiter (50/min)adminAdminUsersListQueryValidation
get statsadminApiLimiteradmin
get detailsadminApiLimiteradminUserIdParamValidation
ban useradminApiLimiteradminBanUserBodyValidation
unban useradminApiLimiteradminUserIdParamValidation
delete useradminApiLimiteradminDeleteUserBodyValidation
manage currencyadminApiLimiteradminUpdateCurrencyBodyValidation
get inventoryadminApiLimiteradminUserInventoryQueryValidation
get historiesadminApiLimiteradmin*HistoryQueryValidation

Edge Cases

СитуацияПоведение
Пользователь не найденHTTP 404, Prisma error handling
Невалидный amountHTTP 400, валидация 1..1,000,000
Убавление > балансаПроверка текущего баланса перед операцией
Бан уже забаненногоОбновляется причина и дата
Удаление (soft delete)deletedAt + isActive = false. Скрывается из списка админки, но продолжает иметь доступ к TMA (auth middleware не проверяет deletedAt)

3. ADR (Architectural Decisions)

Почему UserSearchService делегирует к UserCRUDService?

Проблема: Дублирование логики поиска в двух сервисах.

Решение: UserSearchService стал wrapper, делегирующий все вызовы к UserCRUDService.

Последствия:

  • DRY — единая точка логики
  • Обратная совместимость — старые импорты продолжают работать
  • Проще тестирование

Почему adminId = username?

Проблема: Нужно логировать кто выполнил действие, но JWT payload содержит username, не id.

Решение: Использовать request.user.username как adminId в логах.

Последствия:

  • bannedBy хранит username админа
  • При переименовании админа — старые логи не обновятся

Три уровня управления доступом

УровеньПоляБлокирует доступ к TMA?Удаляет данные?
БанisBanned = trueДа — auth middleware проверяетНет
Soft DeletedeletedAt, isActive = falseНет — auth middleware не проверяет deletedAtНет
Full Reset (/stop)Удаление связанных записейНет (аккаунт остаётся)Да (инвентарь, квесты, история)
Известное ограничение

Soft delete через админку не блокирует доступ пользователя к TMA. Auth middleware (telegram-auth.middleware.ts) проверяет только isBanned, но не deletedAt. Soft-deleted пользователь продолжает пользоваться приложением как обычно.

Если нужно заблокировать доступ — используй Бан, а не удаление.

Почему soft delete?

Проблема: Полное удаление пользователя потеряет данные для аналитики.

Решение: Soft delete через deletedAt + isActive = false.

Что делает:

  • Устанавливает deletedAt = now() и isActive = false
  • Скрывает пользователя из списка в админке
  • Данные сохраняются для аналитики
  • Можно восстановить при необходимости

Чего НЕ делает:

  • Не блокирует доступ к TMA (auth middleware не проверяет deletedAt)
  • Не удаляет данные пользователя
  • Не отвязывает Steam аккаунт

Почему UserGameStatsService разделён на 4 сервиса?

Проблема: UserGameStatsService вырос до 1,408 строк и 19 методов — God Object антипаттерн.

Решение: Разделение по доменам:

  • UserInventoryStatsService — инвентарь, выводы
  • UserActivityStatsService — кейсы, спины, квесты, достижения
  • UserCraftStatsService — крафт, salvage
  • UserRewardsStatsService — промокоды, розыгрыши, награды, баффы

Последствия:

  • Каждый сервис ≤500 строк
  • Чёткая ответственность по домену
  • Проще тестировать (19 unit-тестов для критичных методов)
  • API остаётся неизменным — рефакторинг прозрачен для фронтенда

4. Architecture

Services Overview

Key Components

КомпонентПутьОписание
UserCRUDServicebackend/src/domains/admin/services/user-crud.service.tsCRUD операции + статистика
UserActionsServicebackend/src/domains/admin/services/user-actions.service.tsБан, валюты
UserInventoryStatsServicebackend/src/domains/admin/services/user-stats/user-inventory-stats.service.tsИнвентарь, выводы
UserActivityStatsServicebackend/src/domains/admin/services/user-stats/user-activity-stats.service.tsКейсы, спины, квесты, достижения
UserCraftStatsServicebackend/src/domains/admin/services/user-stats/user-craft-stats.service.tsКрафт, salvage
UserRewardsStatsServicebackend/src/domains/admin/services/user-stats/user-rewards-stats.service.tsПромокоды, розыгрыши, награды, баффы
UserSearchServicebackend/src/domains/admin/services/user-search.service.tsWrapper для совместимости
Routesbackend/src/domains/admin/routes/admin-users.routes.ts15+ API endpoints
Validation Schemasbackend/src/common/schemas/admin-users-validation.schemas.tsJSON Schema валидация
Typesbackend/src/common/types/admin-users.types.tsTypeScript типы
Constantsbackend/src/common/constants/admin-users.constants.tsЛимиты, фильтры
Ban Middlewarebackend/src/common/middleware/ban-check.middleware.tsПроверка бана

Frontend Components

КомпонентПутьОписание
Users.tsxadmin/src/pages/Users.tsxГлавная страница
UsersTableadmin/src/components/users/UsersTable.tsxТаблица с пагинацией
UserDetailsModaladmin/src/components/users/UserDetailsModal.tsxДетальная карточка
BanUserModaladmin/src/components/users/modals/BanUserModal.tsxМодалка бана
UnbanConfirmModaladmin/src/components/users/modals/UnbanConfirmModal.tsxПодтверждение разбана
DeleteUserModaladmin/src/components/users/modals/DeleteUserModal.tsxУдаление с подтверждением
ManageCurrencyModaladmin/src/components/users/modals/ManageCurrencyModal.tsxУправление валютами

5. Database Schema

Ban & Delete Fields on User

ПолеТипОписание
isBannedBooleanФлаг бана (default: false). Проверяется auth middleware
bannedAtDateTime?Когда забанен
banReasonString?Причина бана (max 500 chars)
bannedByString?Username админа
deletedAtDateTime?Когда удалён (soft delete). Не проверяется auth middleware
isActiveBooleanФлаг активности (default: true). Устанавливается в false при soft delete

Indexes

@@index([isBanned])
@@index([bannedAt])
МодельИспользование
UserОсновные данные + ban fields
UserInventoryИнвентарь пользователя
CaseOpeningИстория кейсов
SpinResultИстория спинов
UserQuestКвесты
UserAchievementДостижения
WithdrawalИстория выводов
ReferralРеферальные связи

6. API Endpoints

Admin API (15 endpoints)

МетодЭндпоинтОписание
GET/admin/usersСписок с фильтрами и пагинацией
GET/admin/users/statsСтатистика для StatCards
GET/admin/users/:userIdДетальная информация
GET/admin/users/searchПоиск (legacy)
Request/Response Examples

GET /admin/users

Query params:
- page: number (default 1)
- limit: number (default 10, max 100)
- sortBy: 'createdAt' | 'level' | 'scrap' | 'xp'
- sortOrder: 'asc' | 'desc'
- search: string (name, username, telegramId)
- levelMin, levelMax: number
- isPremium, isBanned, isActive: boolean
- lastActivityDays: number

POST /admin/users/:userId/ban

{
"reason": "Нарушение правил платформы"
}

POST /admin/users/:userId/scrap

{
"amount": 1000,
"reason": "Компенсация за баг"
}
// amount > 0 = добавить
// amount < 0 = убрать

7. Admin Guide

Доступ к панели пользователей

  1. Войти в Admin Panel
  2. Выбрать в меню раздел "Пользователи"

Просмотр списка

  • Статистика отображается в StatCards над таблицей
  • Поиск по имени, нику или Telegram ID
  • Сортировка по колонкам таблицы
  • Пагинация внизу таблицы

Детальная информация

  1. Нажать на строку пользователя
  2. Откроется модальное окно с секциями

Управление валютами

  1. Открыть детали пользователя
  2. Нажать кнопку "Scrap" / "XP" / "SP"
  3. Выбрать операцию: добавить или убрать
  4. Указать сумму (1 - 1,000,000) и причину
  5. Подтвердить

Бан пользователя

  1. Открыть детали пользователя
  2. Нажать "Забанить"
  3. Указать причину (обязательно, max 500 символов)
  4. Подтвердить
Важно

Забаненный пользователь не сможет войти в TMA и получать уведомления от бота.

Разбан

  1. Открыть детали забаненного пользователя
  2. Нажать "Разбанить"
  3. Подтвердить

Удаление пользователя

  1. Открыть детали пользователя
  2. Нажать "Удалить"
  3. Поставить галочку подтверждения
  4. Подтвердить
Soft delete — не блокирует доступ

Удаление устанавливает deletedAt и isActive = false. Пользователь скрывается из списка админки, данные сохраняются для аналитики.

Важно: Пользователь продолжит иметь доступ к TMA после soft delete. Для блокировки доступа используй Бан.


8. Dashboard & Analytics

Админ-панель включает дашборд с ключевыми метриками платформы.

Dashboard Stats

МетрикаОписаниеСервис
Sent WithdrawalsВыводы, ожидающие принятия (статус SENT)DashboardStatsService
Active Season UsersПользователи с активностью в текущем сезонеDashboardStatsService
Total Withdrawn (RUB)Сумма всех выведенных скиновDashboardStatsService
Scrap in CirculationОбщий баланс Scrap у всех пользователейDashboardStatsService

Charts & Analytics

КомпонентОписаниеСервис
User AnalyticsDAU, MAU, retention, когортыUserAnalyticsService
UTM AnalyticsКонверсии по источникам трафикаUniversalChartService
Revenue ChartsГрафики экономикиUnifiedChartEngineService

Key Components

КомпонентПутьОписание
DashboardStatsServicebackend/src/domains/admin/services/dashboard-stats.service.tsКлючевые метрики
UserAnalyticsServicebackend/src/domains/admin/services/user-analytics.service.tsАналитика пользователей
UnifiedChartEngineServicebackend/src/domains/admin/services/unified-chart-engine.service.tsУниверсальный движок графиков
Admin Analytics Routesbackend/src/domains/admin/routes/admin-analytics.routes.tsAPI эндпоинты
Admin Charts Routesbackend/src/domains/admin/routes/admin-charts.routes.tsAPI графиков

API Endpoints

МетодЭндпоинтОписание
GET/admin/analytics/dashboardМетрики дашборда
GET/admin/analytics/bannersАналитика баннеров
GET/admin/analytics/banners/metricsМетрики баннеров
GET/admin/analytics/pushАналитика push-уведомлений
GET/admin/analytics/referralsСтатистика рефералов
GET/admin/analytics/referrals/adminДетальная статистика рефералов
GET/admin/analytics/export/referralsЭкспорт рефералов
GET/admin/analytics/users/registrationСтатистика регистраций
GET/admin/analytics/bot-blocksБлокировки бота
GET/admin/charts/*Универсальные графики (UTM, revenue, etc.)

  • Profile — профиль пользователя (User API)
  • Settings — настройки пользователя
  • Feedback — тикеты пользователей
  • UTM Tracking — источники трафика
  • Security Matrix — обзор защит