141 lines
7.1 KiB
TypeScript
141 lines
7.1 KiB
TypeScript
import { Injectable, OnModuleInit } from '@nestjs/common';
|
||
import { PrismaService } from '../infra/prisma.service';
|
||
import { DEFAULT_USER_ROLE_SLUG } from './rbac.constants';
|
||
import { RbacService } from './rbac.service';
|
||
|
||
const PERMISSIONS = [
|
||
{ slug: 'admin.access', name: 'Доступ к админ-панели', description: 'Позволяет открывать раздел администрирования' },
|
||
{ slug: 'oauth.view', name: 'Просмотр OAuth-приложений', description: 'Просмотр списка OAuth2-клиентов' },
|
||
{ slug: 'oauth.view.all', name: 'Просмотр всех OAuth-приложений', description: 'Просмотр OAuth2-клиентов, созданных другими пользователями' },
|
||
{ slug: 'oauth.manage', name: 'Управление своими OAuth-приложениями', description: 'Создание и редактирование собственных OAuth2-клиентов' },
|
||
{ slug: 'oauth.manage.all', name: 'Управление всеми OAuth-приложениями', description: 'Создание и редактирование любых OAuth2-клиентов' },
|
||
{ slug: 'users.view', name: 'Просмотр пользователей', description: 'Чтение списка пользователей без изменений' },
|
||
{ slug: 'users.view.all', name: 'Просмотр всех пользователей', description: 'Просмотр полного списка пользователей системы' },
|
||
{ slug: 'users.manage', name: 'Управление пользователями', description: 'Редактирование, блокировка и сброс паролей' },
|
||
{ slug: 'users.manage.all', name: 'Полное управление пользователями', description: 'Расширенное управление всеми пользователями' },
|
||
{ slug: 'users.verify', name: 'Верификация пользователей', description: 'Выдача и снятие верификации, выбор значка' },
|
||
{ slug: 'users.read', name: 'Просмотр пользователей (устар.)', description: 'Устаревшее право, заменено на users.view' },
|
||
{ slug: 'settings.manage', name: 'Управление настройками', description: 'Изменение глобальных SystemSetting' },
|
||
{ slug: 'rbac.manage', name: 'Управление ролями и правами', description: 'Назначение ролей, прав пользователям и редактирование ролей' },
|
||
{ slug: 'documents.view_others', name: 'Просмотр документов пользователей', description: 'Просмотр документов и фото других пользователей' },
|
||
{ slug: 'bots.manage.all', name: 'Управление всеми ботами', description: 'Просмотр, блокировка и администрирование всех Telegram-ботов' }
|
||
] as const;
|
||
|
||
const ROLES = [
|
||
{
|
||
slug: DEFAULT_USER_ROLE_SLUG,
|
||
name: 'Пользователь',
|
||
description: 'Стандартная роль всех пользователей системы',
|
||
permissions: [] as string[],
|
||
isSystem: true,
|
||
isDefault: true
|
||
},
|
||
{
|
||
slug: 'bot',
|
||
name: 'Бот',
|
||
description: 'Системная учётная запись Telegram-бота',
|
||
permissions: [] as string[],
|
||
isSystem: true,
|
||
isDefault: false
|
||
},
|
||
{
|
||
slug: 'admin',
|
||
name: 'Администратор',
|
||
description: 'Полный доступ к админ-панели',
|
||
permissions: ['admin.access', 'oauth.manage.all', 'oauth.view.all', 'users.manage.all', 'users.view.all', 'users.verify', 'settings.manage', 'rbac.manage', 'bots.manage.all'],
|
||
isSystem: false,
|
||
isDefault: false
|
||
},
|
||
{
|
||
slug: 'moderator',
|
||
name: 'Модератор',
|
||
description: 'Просмотр пользователей и базовый доступ к админке',
|
||
permissions: ['admin.access', 'users.view', 'users.view.all'],
|
||
isSystem: false,
|
||
isDefault: false
|
||
},
|
||
{
|
||
slug: 'manager',
|
||
name: 'Менеджер',
|
||
description: 'Управление OAuth-приложениями',
|
||
permissions: ['admin.access', 'oauth.manage', 'oauth.view'],
|
||
isSystem: false,
|
||
isDefault: false
|
||
}
|
||
] as const;
|
||
|
||
const OAUTH_SCOPES = [
|
||
{ slug: 'openid', name: 'OpenID', description: 'Базовая идентификация OpenID Connect' },
|
||
{ slug: 'profile', name: 'Профиль', description: 'Имя, логин и аватар пользователя' },
|
||
{ slug: 'email', name: 'Email', description: 'Основная и резервная почта' },
|
||
{ slug: 'phone', name: 'Телефон', description: 'Основной и резервный телефон' },
|
||
{ slug: 'address', name: 'Адреса', description: 'Адреса пользователя' },
|
||
{ slug: 'documents', name: 'Документы', description: 'Документы пользователя' }
|
||
] as const;
|
||
|
||
@Injectable()
|
||
export class AdminSeedService implements OnModuleInit {
|
||
constructor(
|
||
private readonly prisma: PrismaService,
|
||
private readonly rbac: RbacService
|
||
) {}
|
||
|
||
async onModuleInit() {
|
||
for (const permission of PERMISSIONS) {
|
||
await this.rbac.upsertPermission(permission);
|
||
}
|
||
|
||
for (const scope of OAUTH_SCOPES) {
|
||
await this.prisma.oAuthScope.upsert({
|
||
where: { slug: scope.slug },
|
||
create: scope,
|
||
update: { name: scope.name, description: scope.description }
|
||
});
|
||
}
|
||
|
||
for (const role of ROLES) {
|
||
const existing = await this.prisma.role.findUnique({ where: { slug: role.slug } });
|
||
const roleRecord =
|
||
existing ??
|
||
(await this.prisma.role.create({
|
||
data: {
|
||
slug: role.slug,
|
||
name: role.name,
|
||
description: role.description,
|
||
isSystem: role.isSystem,
|
||
isDefault: role.isDefault
|
||
}
|
||
}));
|
||
|
||
await this.prisma.role.update({
|
||
where: { id: roleRecord.id },
|
||
data: {
|
||
name: role.name,
|
||
description: role.description,
|
||
isSystem: role.isSystem,
|
||
isDefault: role.isDefault
|
||
}
|
||
});
|
||
|
||
for (const slug of role.permissions) {
|
||
const permission = await this.prisma.permission.findUnique({ where: { slug } });
|
||
if (!permission) continue;
|
||
await this.prisma.rolePermission.upsert({
|
||
where: { roleId_permissionId: { roleId: roleRecord.id, permissionId: permission.id } },
|
||
create: { roleId: roleRecord.id, permissionId: permission.id },
|
||
update: {}
|
||
});
|
||
}
|
||
}
|
||
|
||
const users = await this.prisma.user.findMany({ where: { deletedAt: null }, select: { id: true, isSystemAccount: true, linkedBotId: true } });
|
||
for (const user of users) {
|
||
if (user.linkedBotId || user.isSystemAccount) {
|
||
await this.rbac.ensureBotUserRole(user.id);
|
||
} else {
|
||
await this.rbac.ensureDefaultUserRole(user.id);
|
||
}
|
||
}
|
||
}
|
||
}
|