const { describe, it, beforeEach, afterEach, before, after } = require('mocha'); const { expect } = require('chai'); const sinon = require('sinon'); const { hasPermission, checkPermission, requirePermission, requirePermissions } = require('../../middleware/rbac'); const { setupTestEnvironment, teardownTestEnvironment, cleanDatabase, mockRequest, mockResponse, mockNext, createTestUser, createTestTenant } = require('../setup'); describe('RBAC Middleware', () => { let models, sequelize; before(async () => { ({ models, sequelize } = await setupTestEnvironment()); }); after(async () => { await teardownTestEnvironment(); }); beforeEach(async () => { await cleanDatabase(); }); describe('checkPermission', () => { it('should allow admin to access any resource', () => { const result = checkPermission('admin', 'devices', 'read'); expect(result).to.be.true; }); it('should allow user_admin to manage users', () => { const result = checkPermission('user_admin', 'users', 'create'); expect(result).to.be.true; }); it('should deny user_admin from managing devices', () => { const result = checkPermission('user_admin', 'devices', 'create'); expect(result).to.be.false; }); it('should allow security_admin to manage security features', () => { expect(checkPermission('security_admin', 'alerts', 'create')).to.be.true; expect(checkPermission('security_admin', 'ip_restrictions', 'read')).to.be.true; expect(checkPermission('security_admin', 'audit_logs', 'read')).to.be.true; }); it('should deny security_admin from managing users', () => { const result = checkPermission('security_admin', 'users', 'create'); expect(result).to.be.false; }); it('should allow branding_admin to manage branding', () => { expect(checkPermission('branding_admin', 'branding', 'update')).to.be.true; expect(checkPermission('branding_admin', 'ui_customization', 'create')).to.be.true; }); it('should deny branding_admin from managing devices', () => { const result = checkPermission('branding_admin', 'devices', 'delete'); expect(result).to.be.false; }); it('should allow operator to read and create detections', () => { expect(checkPermission('operator', 'devices', 'read')).to.be.true; expect(checkPermission('operator', 'detections', 'read')).to.be.true; expect(checkPermission('operator', 'detections', 'create')).to.be.true; }); it('should deny operator from deleting devices', () => { const result = checkPermission('operator', 'devices', 'delete'); expect(result).to.be.false; }); it('should allow viewer to read only', () => { expect(checkPermission('viewer', 'devices', 'read')).to.be.true; expect(checkPermission('viewer', 'detections', 'read')).to.be.true; expect(checkPermission('viewer', 'dashboard', 'read')).to.be.true; }); it('should deny viewer from creating or updating', () => { expect(checkPermission('viewer', 'devices', 'create')).to.be.false; expect(checkPermission('viewer', 'devices', 'update')).to.be.false; expect(checkPermission('viewer', 'detections', 'create')).to.be.false; }); it('should deny unknown role', () => { const result = checkPermission('unknown_role', 'devices', 'read'); expect(result).to.be.false; }); it('should handle case-insensitive roles', () => { const result = checkPermission('ADMIN', 'devices', 'read'); expect(result).to.be.true; }); it('should handle undefined role', () => { const result = checkPermission(undefined, 'devices', 'read'); expect(result).to.be.false; }); }); describe('requirePermission middleware', () => { it('should allow request with valid permission', async () => { const req = mockRequest({ user: { role: 'admin' } }); const res = mockResponse(); const next = mockNext(); const middleware = requirePermission('devices', 'read'); middleware(req, res, next); expect(next.errors).to.have.length(0); }); it('should deny request without permission', async () => { const req = mockRequest({ user: { role: 'viewer' } }); const res = mockResponse(); const next = mockNext(); const middleware = requirePermission('devices', 'delete'); middleware(req, res, next); expect(res.statusCode).to.equal(403); expect(res.data).to.deep.equal({ success: false, message: 'Insufficient permissions' }); }); it('should deny request without user', async () => { const req = mockRequest({}); const res = mockResponse(); const next = mockNext(); const middleware = requirePermission('devices', 'read'); middleware(req, res, next); expect(res.statusCode).to.equal(401); expect(res.data).to.deep.equal({ success: false, message: 'User not authenticated' }); }); it('should deny request without user role', async () => { const req = mockRequest({ user: { username: 'test' } }); const res = mockResponse(); const next = mockNext(); const middleware = requirePermission('devices', 'read'); middleware(req, res, next); expect(res.statusCode).to.equal(403); expect(res.data).to.deep.equal({ success: false, message: 'Insufficient permissions' }); }); }); describe('Role-specific permission tests', () => { const testCases = [ // Admin tests { role: 'admin', resource: 'devices', action: 'create', expected: true }, { role: 'admin', resource: 'users', action: 'delete', expected: true }, { role: 'admin', resource: 'tenants', action: 'update', expected: true }, // User Admin tests { role: 'user_admin', resource: 'users', action: 'create', expected: true }, { role: 'user_admin', resource: 'users', action: 'update', expected: true }, { role: 'user_admin', resource: 'users', action: 'delete', expected: true }, { role: 'user_admin', resource: 'roles', action: 'read', expected: true }, { role: 'user_admin', resource: 'devices', action: 'create', expected: false }, // Security Admin tests { role: 'security_admin', resource: 'alerts', action: 'create', expected: true }, { role: 'security_admin', resource: 'ip_restrictions', action: 'update', expected: true }, { role: 'security_admin', resource: 'audit_logs', action: 'read', expected: true }, { role: 'security_admin', resource: 'users', action: 'create', expected: false }, // Branding Admin tests { role: 'branding_admin', resource: 'branding', action: 'update', expected: true }, { role: 'branding_admin', resource: 'ui_customization', action: 'create', expected: true }, { role: 'branding_admin', resource: 'logo', action: 'upload', expected: true }, { role: 'branding_admin', resource: 'devices', action: 'create', expected: false }, // Operator tests { role: 'operator', resource: 'devices', action: 'read', expected: true }, { role: 'operator', resource: 'devices', action: 'update', expected: true }, { role: 'operator', resource: 'detections', action: 'read', expected: true }, { role: 'operator', resource: 'detections', action: 'create', expected: true }, { role: 'operator', resource: 'devices', action: 'delete', expected: false }, { role: 'operator', resource: 'users', action: 'create', expected: false }, // Viewer tests { role: 'viewer', resource: 'devices', action: 'read', expected: true }, { role: 'viewer', resource: 'detections', action: 'read', expected: true }, { role: 'viewer', resource: 'dashboard', action: 'read', expected: true }, { role: 'viewer', resource: 'devices', action: 'create', expected: false }, { role: 'viewer', resource: 'devices', action: 'update', expected: false }, { role: 'viewer', resource: 'users', action: 'read', expected: false } ]; testCases.forEach(({ role, resource, action, expected }) => { it(`should ${expected ? 'allow' : 'deny'} ${role} to ${action} ${resource}`, () => { const result = checkPermission(role, resource, action); expect(result).to.equal(expected); }); }); }); });