"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const testing_1 = require("@nestjs/testing"); const typeorm_1 = require("@nestjs/typeorm"); const common_1 = require("@nestjs/common"); const rbac_service_1 = require("../services/rbac.service"); const entities_1 = require("../entities"); describe('RbacService', () => { let service; let roleRepository; let permissionRepository; let userRoleRepository; let rolePermissionRepository; const mockRole = { id: 'role-123', tenant_id: 'tenant-123', name: 'Admin', code: 'admin', description: 'Administrator role', is_system: false, is_active: true, metadata: null, created_at: new Date('2026-01-01'), updated_at: new Date('2026-01-01'), }; const mockSystemRole = { ...mockRole, id: 'role-system', code: 'owner', name: 'Owner', is_system: true, }; const mockPermission = { id: 'perm-123', code: 'users:read', name: 'Read Users', description: 'Can read user data', category: 'users', is_sensitive: false, requires_owner: false, created_at: new Date('2026-01-01'), }; const mockUserRole = { id: 'ur-123', user_id: 'user-123', role_id: 'role-123', tenant_id: 'tenant-123', assigned_by: 'admin-123', created_at: new Date('2026-01-01'), }; const mockRolePermission = { id: 'rp-123', role_id: 'role-123', permission_id: 'perm-123', created_at: new Date('2026-01-01'), }; beforeEach(async () => { const module = await testing_1.Test.createTestingModule({ providers: [ rbac_service_1.RbacService, { provide: (0, typeorm_1.getRepositoryToken)(entities_1.Role), useValue: { findOne: jest.fn(), find: jest.fn(), save: jest.fn(), create: jest.fn(), delete: jest.fn(), count: jest.fn(), }, }, { provide: (0, typeorm_1.getRepositoryToken)(entities_1.Permission), useValue: { findOne: jest.fn(), find: jest.fn(), save: jest.fn(), }, }, { provide: (0, typeorm_1.getRepositoryToken)(entities_1.UserRole), useValue: { findOne: jest.fn(), find: jest.fn(), save: jest.fn(), create: jest.fn(), delete: jest.fn(), count: jest.fn(), }, }, { provide: (0, typeorm_1.getRepositoryToken)(entities_1.RolePermission), useValue: { findOne: jest.fn(), find: jest.fn(), save: jest.fn(), delete: jest.fn(), }, }, ], }).compile(); service = module.get(rbac_service_1.RbacService); roleRepository = module.get((0, typeorm_1.getRepositoryToken)(entities_1.Role)); permissionRepository = module.get((0, typeorm_1.getRepositoryToken)(entities_1.Permission)); userRoleRepository = module.get((0, typeorm_1.getRepositoryToken)(entities_1.UserRole)); rolePermissionRepository = module.get((0, typeorm_1.getRepositoryToken)(entities_1.RolePermission)); }); afterEach(() => { jest.clearAllMocks(); }); describe('createRole', () => { const createDto = { name: 'Manager', code: 'manager', description: 'Manager role', permissions: ['users:read'], }; it('should create a new role', async () => { const createdRole = { ...mockRole, ...createDto, id: 'new-role-123' }; roleRepository.findOne .mockResolvedValueOnce(null) .mockResolvedValueOnce(createdRole); roleRepository.create.mockReturnValue(createdRole); roleRepository.save.mockResolvedValue(createdRole); permissionRepository.find.mockResolvedValue([mockPermission]); rolePermissionRepository.delete.mockResolvedValue({ affected: 0, raw: {} }); rolePermissionRepository.save.mockResolvedValue([mockRolePermission]); const result = await service.createRole(createDto, 'tenant-123'); expect(result.name).toBe('Manager'); expect(roleRepository.create).toHaveBeenCalled(); expect(roleRepository.save).toHaveBeenCalled(); }); it('should throw ConflictException if role code exists', async () => { roleRepository.findOne.mockResolvedValue(mockRole); await expect(service.createRole(createDto, 'tenant-123')).rejects.toThrow(common_1.ConflictException); }); }); describe('updateRole', () => { const updateDto = { name: 'Updated Admin', description: 'Updated description' }; it('should update a role', async () => { const roleCopy = { ...mockRole }; roleRepository.findOne.mockResolvedValue(roleCopy); roleRepository.save.mockResolvedValue({ ...roleCopy, ...updateDto }); const result = await service.updateRole('role-123', updateDto, 'tenant-123'); expect(result.name).toBe('Updated Admin'); expect(roleRepository.save).toHaveBeenCalled(); }); it('should throw NotFoundException if role not found', async () => { roleRepository.findOne.mockResolvedValue(null); await expect(service.updateRole('non-existent', updateDto, 'tenant-123')).rejects.toThrow(common_1.NotFoundException); }); it('should throw ForbiddenException for system role', async () => { roleRepository.findOne.mockResolvedValue(mockSystemRole); await expect(service.updateRole('role-system', updateDto, 'tenant-123')).rejects.toThrow(common_1.ForbiddenException); }); }); describe('deleteRole', () => { it('should delete a role', async () => { roleRepository.findOne.mockResolvedValue(mockRole); userRoleRepository.count.mockResolvedValue(0); rolePermissionRepository.delete.mockResolvedValue({ affected: 1, raw: {} }); roleRepository.delete.mockResolvedValue({ affected: 1, raw: {} }); await service.deleteRole('role-123', 'tenant-123'); expect(roleRepository.delete).toHaveBeenCalledWith({ id: 'role-123' }); }); it('should throw NotFoundException if role not found', async () => { roleRepository.findOne.mockResolvedValue(null); await expect(service.deleteRole('non-existent', 'tenant-123')).rejects.toThrow(common_1.NotFoundException); }); it('should throw ForbiddenException for system role', async () => { roleRepository.findOne.mockResolvedValue(mockSystemRole); await expect(service.deleteRole('role-system', 'tenant-123')).rejects.toThrow(common_1.ForbiddenException); }); it('should throw ConflictException if role is assigned to users', async () => { roleRepository.findOne.mockResolvedValue(mockRole); userRoleRepository.count.mockResolvedValue(5); await expect(service.deleteRole('role-123', 'tenant-123')).rejects.toThrow(common_1.ConflictException); }); }); describe('findAllRoles', () => { it('should return all active roles for tenant', async () => { roleRepository.find.mockResolvedValue([mockRole]); const result = await service.findAllRoles('tenant-123'); expect(result).toEqual([mockRole]); expect(roleRepository.find).toHaveBeenCalledWith({ where: { tenant_id: 'tenant-123', is_active: true }, order: { is_system: 'DESC', name: 'ASC' }, }); }); }); describe('findRoleById', () => { it('should return a role by id', async () => { roleRepository.findOne.mockResolvedValue(mockRole); const result = await service.findRoleById('role-123', 'tenant-123'); expect(result).toEqual(mockRole); }); it('should throw NotFoundException if role not found', async () => { roleRepository.findOne.mockResolvedValue(null); await expect(service.findRoleById('non-existent', 'tenant-123')).rejects.toThrow(common_1.NotFoundException); }); }); describe('findAllPermissions', () => { it('should return all permissions', async () => { permissionRepository.find.mockResolvedValue([mockPermission]); const result = await service.findAllPermissions(); expect(result).toEqual([mockPermission]); expect(permissionRepository.find).toHaveBeenCalledWith({ order: { category: 'ASC', code: 'ASC' }, }); }); }); describe('assignRoleToUser', () => { const assignDto = { userId: 'user-123', roleId: 'role-123' }; it('should assign a role to a user', async () => { roleRepository.findOne.mockResolvedValue(mockRole); userRoleRepository.findOne.mockResolvedValue(null); userRoleRepository.create.mockReturnValue(mockUserRole); userRoleRepository.save.mockResolvedValue(mockUserRole); const result = await service.assignRoleToUser(assignDto, 'tenant-123', 'admin-123'); expect(result).toEqual(mockUserRole); expect(userRoleRepository.save).toHaveBeenCalled(); }); it('should throw ConflictException if role already assigned', async () => { roleRepository.findOne.mockResolvedValue(mockRole); userRoleRepository.findOne.mockResolvedValue(mockUserRole); await expect(service.assignRoleToUser(assignDto, 'tenant-123', 'admin-123')).rejects.toThrow(common_1.ConflictException); }); it('should throw NotFoundException if role not found', async () => { roleRepository.findOne.mockResolvedValue(null); await expect(service.assignRoleToUser(assignDto, 'tenant-123', 'admin-123')).rejects.toThrow(common_1.NotFoundException); }); }); describe('removeRoleFromUser', () => { it('should remove a role from a user', async () => { userRoleRepository.delete.mockResolvedValue({ affected: 1, raw: {} }); await service.removeRoleFromUser('user-123', 'role-123', 'tenant-123'); expect(userRoleRepository.delete).toHaveBeenCalledWith({ user_id: 'user-123', role_id: 'role-123', tenant_id: 'tenant-123', }); }); it('should throw NotFoundException if assignment not found', async () => { userRoleRepository.delete.mockResolvedValue({ affected: 0, raw: {} }); await expect(service.removeRoleFromUser('user-123', 'role-123', 'tenant-123')).rejects.toThrow(common_1.NotFoundException); }); }); describe('getUserRoles', () => { it('should return all roles for a user', async () => { userRoleRepository.find.mockResolvedValue([mockUserRole]); roleRepository.find.mockResolvedValue([mockRole]); const result = await service.getUserRoles('user-123', 'tenant-123'); expect(result).toEqual([mockRole]); }); it('should return empty array if user has no roles', async () => { userRoleRepository.find.mockResolvedValue([]); const result = await service.getUserRoles('user-123', 'tenant-123'); expect(result).toEqual([]); }); }); describe('getUserPermissions', () => { it('should return all permissions for a user', async () => { userRoleRepository.find.mockResolvedValue([mockUserRole]); roleRepository.find.mockResolvedValue([mockRole]); rolePermissionRepository.find.mockResolvedValue([mockRolePermission]); permissionRepository.find.mockResolvedValue([mockPermission]); const result = await service.getUserPermissions('user-123', 'tenant-123'); expect(result).toEqual([mockPermission]); }); it('should return empty array if user has no roles', async () => { userRoleRepository.find.mockResolvedValue([]); const result = await service.getUserPermissions('user-123', 'tenant-123'); expect(result).toEqual([]); }); }); describe('userHasPermission', () => { it('should return true if user has permission', async () => { userRoleRepository.find.mockResolvedValue([mockUserRole]); roleRepository.find.mockResolvedValue([mockRole]); rolePermissionRepository.find.mockResolvedValue([mockRolePermission]); permissionRepository.find.mockResolvedValue([mockPermission]); const result = await service.userHasPermission('user-123', 'tenant-123', 'users:read'); expect(result).toBe(true); }); it('should return false if user lacks permission', async () => { userRoleRepository.find.mockResolvedValue([mockUserRole]); roleRepository.find.mockResolvedValue([mockRole]); rolePermissionRepository.find.mockResolvedValue([mockRolePermission]); permissionRepository.find.mockResolvedValue([mockPermission]); const result = await service.userHasPermission('user-123', 'tenant-123', 'users:delete'); expect(result).toBe(false); }); }); describe('userHasRole', () => { it('should return true if user has role', async () => { userRoleRepository.find.mockResolvedValue([mockUserRole]); roleRepository.find.mockResolvedValue([mockRole]); const result = await service.userHasRole('user-123', 'tenant-123', 'admin'); expect(result).toBe(true); }); it('should return false if user lacks role', async () => { userRoleRepository.find.mockResolvedValue([]); const result = await service.userHasRole('user-123', 'tenant-123', 'admin'); expect(result).toBe(false); }); }); }); //# sourceMappingURL=rbac.service.spec.js.map