"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var RoleSyncService_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.RoleSyncService = void 0; const common_1 = require("@nestjs/common"); const prisma_service_1 = require("../../shared/prisma.service"); const event_bus_service_1 = require("../../core/event-bus/event-bus.service"); const group_hash_service_1 = require("./group-hash.service"); const authorization_service_1 = require("../authorization/authorization.service"); let RoleSyncService = RoleSyncService_1 = class RoleSyncService { prisma; groupHash; permissionCache; events; logger = new common_1.Logger(RoleSyncService_1.name); constructor(prisma, groupHash, permissionCache, events) { this.prisma = prisma; this.groupHash = groupHash; this.permissionCache = permissionCache; this.events = events; } computeGroupHash(groups) { return this.groupHash.compute(groups || []); } async mapGroupsToRoleIds(groups) { if (!groups || groups.length === 0) return []; const mappings = await this.prisma.authGroupRoleMapping.findMany({ where: { authGroup: { in: groups } } }); const roleIds = mappings.map((m) => m.roleId); return Array.from(new Set(roleIds)); } async syncUserRolesFromAuthentik(userId, groups) { const groupHash = this.computeGroupHash(groups || []); const user = await this.prisma.user.findUnique({ where: { id: userId } }); if (!user) throw new Error('User not found'); if (user.lastGroupHash === groupHash) { this.logger.debug('Group hash unchanged, skipping sync'); return { skipped: true }; } const roleIds = await this.mapGroupsToRoleIds(groups || []); const previousRoleRows = await this.prisma.userRole.findMany({ where: { userId, source: 'AUTHENTIK' }, select: { roleId: true } }); const previousRoles = previousRoleRows.map((r) => r.roleId); await this.prisma.$transaction(async (tx) => { await tx.userRole.deleteMany({ where: { userId: userId, source: 'AUTHENTIK' } }); if (roleIds.length > 0) { const createData = roleIds.map((rid) => ({ userId, roleId: rid, source: 'AUTHENTIK' })); await tx.userRole.createMany({ data: createData, skipDuplicates: true }); } await tx.user.update({ where: { id: userId }, data: { lastGroupHash: groupHash } }); }); // Invalidate permission cache through abstraction try { await this.permissionCache.invalidate(userId); } catch (e) { this.logger.error('Failed to invalidate permission cache', e); } // Publish event for audit and other subscribers this.events.publish({ id: require('crypto').randomUUID(), timestamp: new Date().toISOString(), type: 'RolesSynchronized', payload: { userId, groups, assignedRoleIds: roleIds, previousRoles }, }); return { skipped: false, assignedRoleIds: roleIds }; } }; exports.RoleSyncService = RoleSyncService; exports.RoleSyncService = RoleSyncService = RoleSyncService_1 = __decorate([ (0, common_1.Injectable)(), __param(2, (0, common_1.Inject)(authorization_service_1.PERMISSION_CACHE)), __metadata("design:paramtypes", [prisma_service_1.PrismaService, group_hash_service_1.GroupHashService, Object, event_bus_service_1.EventBus]) ], RoleSyncService); //# sourceMappingURL=role-sync.service.js.map