Files
drone-detector/server/tests/middleware/rbac.test.js
2025-09-14 21:07:43 +02:00

213 lines
8.2 KiB
JavaScript

const { describe, it, beforeEach, afterEach, before, after } = require('mocha');
const { expect } = require('chai');
const sinon = require('sinon');
const { checkPermission, requirePermission } = 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);
});
});
});
});