747 lines
20 KiB
TypeScript
747 lines
20 KiB
TypeScript
import { AdminUser } from '../entities/AdminUser';
|
|
import { AuthorizationService } from './AuthorizationService';
|
|
|
|
describe('AuthorizationService', () => {
|
|
describe('TDD - Test First', () => {
|
|
describe('canListUsers', () => {
|
|
it('should allow owner to list users', () => {
|
|
// Arrange
|
|
const owner = AdminUser.create({
|
|
id: 'owner-1',
|
|
email: 'owner@example.com',
|
|
displayName: 'Owner',
|
|
roles: ['owner'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canList = AuthorizationService.canListUsers(owner);
|
|
|
|
// Assert
|
|
expect(canList).toBe(true);
|
|
});
|
|
|
|
it('should allow admin to list users', () => {
|
|
// Arrange
|
|
const admin = AdminUser.create({
|
|
id: 'admin-1',
|
|
email: 'admin@example.com',
|
|
displayName: 'Admin',
|
|
roles: ['admin'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canList = AuthorizationService.canListUsers(admin);
|
|
|
|
// Assert
|
|
expect(canList).toBe(true);
|
|
});
|
|
|
|
it('should deny regular user from listing users', () => {
|
|
// Arrange
|
|
const user = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canList = AuthorizationService.canListUsers(user);
|
|
|
|
// Assert
|
|
expect(canList).toBe(false);
|
|
});
|
|
|
|
it('should deny suspended admin from listing users', () => {
|
|
// Arrange
|
|
const suspendedAdmin = AdminUser.create({
|
|
id: 'admin-1',
|
|
email: 'admin@example.com',
|
|
displayName: 'Admin',
|
|
roles: ['admin'],
|
|
status: 'suspended',
|
|
});
|
|
|
|
// Act
|
|
const canList = AuthorizationService.canListUsers(suspendedAdmin);
|
|
|
|
// Assert
|
|
expect(canList).toBe(false);
|
|
});
|
|
|
|
it('should allow owner with multiple roles to list users', () => {
|
|
// Arrange
|
|
const owner = AdminUser.create({
|
|
id: 'owner-1',
|
|
email: 'owner@example.com',
|
|
displayName: 'Owner',
|
|
roles: ['owner'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canList = AuthorizationService.canListUsers(owner);
|
|
|
|
// Assert
|
|
expect(canList).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('canPerformAction with manage', () => {
|
|
it('should allow owner to manage any user', () => {
|
|
// Arrange
|
|
const owner = AdminUser.create({
|
|
id: 'owner-1',
|
|
email: 'owner@example.com',
|
|
displayName: 'Owner',
|
|
roles: ['owner'],
|
|
status: 'active',
|
|
});
|
|
|
|
const targetUser = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canManage = AuthorizationService.canPerformAction(owner, 'manage', targetUser);
|
|
|
|
// Assert
|
|
expect(canManage).toBe(true);
|
|
});
|
|
|
|
it('should allow admin to manage non-admin users', () => {
|
|
// Arrange
|
|
const admin = AdminUser.create({
|
|
id: 'admin-1',
|
|
email: 'admin@example.com',
|
|
displayName: 'Admin',
|
|
roles: ['admin'],
|
|
status: 'active',
|
|
});
|
|
|
|
const targetUser = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canManage = AuthorizationService.canPerformAction(admin, 'manage', targetUser);
|
|
|
|
// Assert
|
|
expect(canManage).toBe(true);
|
|
});
|
|
|
|
it('should deny admin from managing other admins', () => {
|
|
// Arrange
|
|
const admin1 = AdminUser.create({
|
|
id: 'admin-1',
|
|
email: 'admin1@example.com',
|
|
displayName: 'Admin 1',
|
|
roles: ['admin'],
|
|
status: 'active',
|
|
});
|
|
|
|
const admin2 = AdminUser.create({
|
|
id: 'admin-2',
|
|
email: 'admin2@example.com',
|
|
displayName: 'Admin 2',
|
|
roles: ['admin'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canManage = AuthorizationService.canPerformAction(admin1, 'manage', admin2);
|
|
|
|
// Assert
|
|
expect(canManage).toBe(false);
|
|
});
|
|
|
|
it('should deny regular user from managing anyone', () => {
|
|
// Arrange
|
|
const user = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
const targetUser = AdminUser.create({
|
|
id: 'user-2',
|
|
email: 'user2@example.com',
|
|
displayName: 'User 2',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canManage = AuthorizationService.canPerformAction(user, 'manage', targetUser);
|
|
|
|
// Assert
|
|
expect(canManage).toBe(false);
|
|
});
|
|
|
|
it('should allow admin to manage suspended users', () => {
|
|
// Arrange
|
|
const admin = AdminUser.create({
|
|
id: 'admin-1',
|
|
email: 'admin@example.com',
|
|
displayName: 'Admin',
|
|
roles: ['admin'],
|
|
status: 'active',
|
|
});
|
|
|
|
const suspendedUser = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'suspended',
|
|
});
|
|
|
|
// Act
|
|
const canManage = AuthorizationService.canPerformAction(admin, 'manage', suspendedUser);
|
|
|
|
// Assert
|
|
expect(canManage).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('canPerformAction with modify_roles', () => {
|
|
it('should allow owner to modify roles', () => {
|
|
// Arrange
|
|
const owner = AdminUser.create({
|
|
id: 'owner-1',
|
|
email: 'owner@example.com',
|
|
displayName: 'Owner',
|
|
roles: ['owner'],
|
|
status: 'active',
|
|
});
|
|
|
|
const targetUser = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canModify = AuthorizationService.canPerformAction(owner, 'modify_roles', targetUser);
|
|
|
|
// Assert
|
|
expect(canModify).toBe(true);
|
|
});
|
|
|
|
it('should deny admin from modifying roles', () => {
|
|
// Arrange
|
|
const admin = AdminUser.create({
|
|
id: 'admin-1',
|
|
email: 'admin@example.com',
|
|
displayName: 'Admin',
|
|
roles: ['admin'],
|
|
status: 'active',
|
|
});
|
|
|
|
const targetUser = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canModify = AuthorizationService.canPerformAction(admin, 'modify_roles', targetUser);
|
|
|
|
// Assert
|
|
expect(canModify).toBe(false);
|
|
});
|
|
|
|
it('should deny regular user from modifying roles', () => {
|
|
// Arrange
|
|
const user = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
const targetUser = AdminUser.create({
|
|
id: 'user-2',
|
|
email: 'user2@example.com',
|
|
displayName: 'User 2',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canModify = AuthorizationService.canPerformAction(user, 'modify_roles', targetUser);
|
|
|
|
// Assert
|
|
expect(canModify).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('canPerformAction with change_status', () => {
|
|
it('should allow owner to change any status', () => {
|
|
// Arrange
|
|
const owner = AdminUser.create({
|
|
id: 'owner-1',
|
|
email: 'owner@example.com',
|
|
displayName: 'Owner',
|
|
roles: ['owner'],
|
|
status: 'active',
|
|
});
|
|
|
|
const targetUser = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canChange = AuthorizationService.canPerformAction(owner, 'change_status', targetUser);
|
|
|
|
// Assert
|
|
expect(canChange).toBe(true);
|
|
});
|
|
|
|
it('should allow admin to change non-admin status', () => {
|
|
// Arrange
|
|
const admin = AdminUser.create({
|
|
id: 'admin-1',
|
|
email: 'admin@example.com',
|
|
displayName: 'Admin',
|
|
roles: ['admin'],
|
|
status: 'active',
|
|
});
|
|
|
|
const targetUser = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canChange = AuthorizationService.canPerformAction(admin, 'change_status', targetUser);
|
|
|
|
// Assert
|
|
expect(canChange).toBe(true);
|
|
});
|
|
|
|
it('should deny admin from changing admin status', () => {
|
|
// Arrange
|
|
const admin1 = AdminUser.create({
|
|
id: 'admin-1',
|
|
email: 'admin1@example.com',
|
|
displayName: 'Admin 1',
|
|
roles: ['admin'],
|
|
status: 'active',
|
|
});
|
|
|
|
const admin2 = AdminUser.create({
|
|
id: 'admin-2',
|
|
email: 'admin2@example.com',
|
|
displayName: 'Admin 2',
|
|
roles: ['admin'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canChange = AuthorizationService.canPerformAction(admin1, 'change_status', admin2);
|
|
|
|
// Assert
|
|
expect(canChange).toBe(false);
|
|
});
|
|
|
|
it('should deny regular user from changing status', () => {
|
|
// Arrange
|
|
const user = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
const targetUser = AdminUser.create({
|
|
id: 'user-2',
|
|
email: 'user2@example.com',
|
|
displayName: 'User 2',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canChange = AuthorizationService.canPerformAction(user, 'change_status', targetUser);
|
|
|
|
// Assert
|
|
expect(canChange).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('canPerformAction with delete', () => {
|
|
it('should allow owner to delete any user', () => {
|
|
// Arrange
|
|
const owner = AdminUser.create({
|
|
id: 'owner-1',
|
|
email: 'owner@example.com',
|
|
displayName: 'Owner',
|
|
roles: ['owner'],
|
|
status: 'active',
|
|
});
|
|
|
|
const targetUser = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canDelete = AuthorizationService.canPerformAction(owner, 'delete', targetUser);
|
|
|
|
// Assert
|
|
expect(canDelete).toBe(true);
|
|
});
|
|
|
|
it('should allow admin to delete non-admin users', () => {
|
|
// Arrange
|
|
const admin = AdminUser.create({
|
|
id: 'admin-1',
|
|
email: 'admin@example.com',
|
|
displayName: 'Admin',
|
|
roles: ['admin'],
|
|
status: 'active',
|
|
});
|
|
|
|
const targetUser = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canDelete = AuthorizationService.canPerformAction(admin, 'delete', targetUser);
|
|
|
|
// Assert
|
|
expect(canDelete).toBe(true);
|
|
});
|
|
|
|
it('should deny admin from deleting other admins', () => {
|
|
// Arrange
|
|
const admin1 = AdminUser.create({
|
|
id: 'admin-1',
|
|
email: 'admin1@example.com',
|
|
displayName: 'Admin 1',
|
|
roles: ['admin'],
|
|
status: 'active',
|
|
});
|
|
|
|
const admin2 = AdminUser.create({
|
|
id: 'admin-2',
|
|
email: 'admin2@example.com',
|
|
displayName: 'Admin 2',
|
|
roles: ['admin'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canDelete = AuthorizationService.canPerformAction(admin1, 'delete', admin2);
|
|
|
|
// Assert
|
|
expect(canDelete).toBe(false);
|
|
});
|
|
|
|
it('should deny regular user from deleting anyone', () => {
|
|
// Arrange
|
|
const user = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
const targetUser = AdminUser.create({
|
|
id: 'user-2',
|
|
email: 'user2@example.com',
|
|
displayName: 'User 2',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const canDelete = AuthorizationService.canPerformAction(user, 'delete', targetUser);
|
|
|
|
// Assert
|
|
expect(canDelete).toBe(false);
|
|
});
|
|
|
|
it('should allow owner to delete suspended users', () => {
|
|
// Arrange
|
|
const owner = AdminUser.create({
|
|
id: 'owner-1',
|
|
email: 'owner@example.com',
|
|
displayName: 'Owner',
|
|
roles: ['owner'],
|
|
status: 'active',
|
|
});
|
|
|
|
const suspendedUser = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'suspended',
|
|
});
|
|
|
|
// Act
|
|
const canDelete = AuthorizationService.canPerformAction(owner, 'delete', suspendedUser);
|
|
|
|
// Assert
|
|
expect(canDelete).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('getPermissions', () => {
|
|
it('should return correct permissions for owner', () => {
|
|
// Arrange
|
|
const owner = AdminUser.create({
|
|
id: 'owner-1',
|
|
email: 'owner@example.com',
|
|
displayName: 'Owner',
|
|
roles: ['owner'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const permissions = AuthorizationService.getPermissions(owner);
|
|
|
|
// Assert
|
|
expect(permissions).toContain('users.view');
|
|
expect(permissions).toContain('users.list');
|
|
expect(permissions).toContain('users.manage');
|
|
expect(permissions).toContain('users.roles.modify');
|
|
expect(permissions).toContain('users.status.change');
|
|
expect(permissions).toContain('users.create');
|
|
expect(permissions).toContain('users.delete');
|
|
expect(permissions).toContain('users.export');
|
|
});
|
|
|
|
it('should return correct permissions for admin', () => {
|
|
// Arrange
|
|
const admin = AdminUser.create({
|
|
id: 'admin-1',
|
|
email: 'admin@example.com',
|
|
displayName: 'Admin',
|
|
roles: ['admin'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const permissions = AuthorizationService.getPermissions(admin);
|
|
|
|
// Assert
|
|
expect(permissions).toContain('users.view');
|
|
expect(permissions).toContain('users.list');
|
|
expect(permissions).toContain('users.manage');
|
|
expect(permissions).toContain('users.status.change');
|
|
expect(permissions).toContain('users.create');
|
|
expect(permissions).toContain('users.delete');
|
|
expect(permissions).not.toContain('users.roles.modify');
|
|
expect(permissions).not.toContain('users.export');
|
|
});
|
|
|
|
it('should return empty permissions for regular user', () => {
|
|
// Arrange
|
|
const user = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const permissions = AuthorizationService.getPermissions(user);
|
|
|
|
// Assert
|
|
expect(permissions).toEqual([]);
|
|
});
|
|
|
|
it('should return empty permissions for suspended admin', () => {
|
|
// Arrange
|
|
const suspendedAdmin = AdminUser.create({
|
|
id: 'admin-1',
|
|
email: 'admin@example.com',
|
|
displayName: 'Admin',
|
|
roles: ['admin'],
|
|
status: 'suspended',
|
|
});
|
|
|
|
// Act
|
|
const permissions = AuthorizationService.getPermissions(suspendedAdmin);
|
|
|
|
// Assert
|
|
expect(permissions).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('hasPermission', () => {
|
|
it('should return true for owner with users.view permission', () => {
|
|
// Arrange
|
|
const owner = AdminUser.create({
|
|
id: 'owner-1',
|
|
email: 'owner@example.com',
|
|
displayName: 'Owner',
|
|
roles: ['owner'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const hasPermission = AuthorizationService.hasPermission(owner, 'users.view');
|
|
|
|
// Assert
|
|
expect(hasPermission).toBe(true);
|
|
});
|
|
|
|
it('should return false for admin with users.roles.modify permission', () => {
|
|
// Arrange
|
|
const admin = AdminUser.create({
|
|
id: 'admin-1',
|
|
email: 'admin@example.com',
|
|
displayName: 'Admin',
|
|
roles: ['admin'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const hasPermission = AuthorizationService.hasPermission(admin, 'users.roles.modify');
|
|
|
|
// Assert
|
|
expect(hasPermission).toBe(false);
|
|
});
|
|
|
|
it('should return false for regular user with any permission', () => {
|
|
// Arrange
|
|
const user = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act
|
|
const hasPermission = AuthorizationService.hasPermission(user, 'users.view');
|
|
|
|
// Assert
|
|
expect(hasPermission).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('enforce', () => {
|
|
it('should not throw for authorized action', () => {
|
|
// Arrange
|
|
const owner = AdminUser.create({
|
|
id: 'owner-1',
|
|
email: 'owner@example.com',
|
|
displayName: 'Owner',
|
|
roles: ['owner'],
|
|
status: 'active',
|
|
});
|
|
|
|
const targetUser = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act & Assert - Should not throw
|
|
expect(() => {
|
|
AuthorizationService.enforce(owner, 'manage', targetUser);
|
|
}).not.toThrow();
|
|
});
|
|
|
|
it('should throw for unauthorized action', () => {
|
|
// Arrange
|
|
const user = AdminUser.create({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
displayName: 'User',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
const targetUser = AdminUser.create({
|
|
id: 'user-2',
|
|
email: 'user2@example.com',
|
|
displayName: 'User 2',
|
|
roles: ['user'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act & Assert - Should throw
|
|
expect(() => {
|
|
AuthorizationService.enforce(user, 'manage', targetUser);
|
|
}).toThrow();
|
|
});
|
|
});
|
|
|
|
describe('enforcePermission', () => {
|
|
it('should not throw for authorized permission', () => {
|
|
// Arrange
|
|
const owner = AdminUser.create({
|
|
id: 'owner-1',
|
|
email: 'owner@example.com',
|
|
displayName: 'Owner',
|
|
roles: ['owner'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act & Assert - Should not throw
|
|
expect(() => {
|
|
AuthorizationService.enforcePermission(owner, 'users.view');
|
|
}).not.toThrow();
|
|
});
|
|
|
|
it('should throw for unauthorized permission', () => {
|
|
// Arrange
|
|
const admin = AdminUser.create({
|
|
id: 'admin-1',
|
|
email: 'admin@example.com',
|
|
displayName: 'Admin',
|
|
roles: ['admin'],
|
|
status: 'active',
|
|
});
|
|
|
|
// Act & Assert - Should throw
|
|
expect(() => {
|
|
AuthorizationService.enforcePermission(admin, 'users.roles.modify');
|
|
}).toThrow();
|
|
});
|
|
});
|
|
});
|
|
}); |