diff --git a/packages/backend/src/models/__snapshots__/permission.test.js.snap b/packages/backend/src/models/__snapshots__/permission.test.js.snap new file mode 100644 index 00000000..4b861e39 --- /dev/null +++ b/packages/backend/src/models/__snapshots__/permission.test.js.snap @@ -0,0 +1,42 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Permission model > jsonSchema should have correct validations 1`] = ` +{ + "properties": { + "action": { + "minLength": 1, + "type": "string", + }, + "conditions": { + "items": { + "type": "string", + }, + "type": "array", + }, + "createdAt": { + "type": "string", + }, + "id": { + "format": "uuid", + "type": "string", + }, + "roleId": { + "format": "uuid", + "type": "string", + }, + "subject": { + "minLength": 1, + "type": "string", + }, + "updatedAt": { + "type": "string", + }, + }, + "required": [ + "roleId", + "action", + "subject", + ], + "type": "object", +} +`; diff --git a/packages/backend/src/models/permission.test.js b/packages/backend/src/models/permission.test.js new file mode 100644 index 00000000..c53b8218 --- /dev/null +++ b/packages/backend/src/models/permission.test.js @@ -0,0 +1,95 @@ +import { describe, it, expect } from 'vitest'; +import Permission from './permission'; +import permissionCatalog from '../helpers/permission-catalog.ee.js'; + +describe('Permission model', () => { + it('tableName should return correct name', () => { + expect(Permission.tableName).toBe('permissions'); + }); + + it('jsonSchema should have correct validations', () => { + expect(Permission.jsonSchema).toMatchSnapshot(); + }); + + it('filter should return only valid permissions based on permission catalog', () => { + const permissions = [ + { action: 'read', subject: 'Flow', conditions: ['isCreator'] }, + { action: 'delete', subject: 'Connection', conditions: [] }, + { action: 'publish', subject: 'Flow', conditions: ['isCreator'] }, + { action: 'update', subject: 'Execution', conditions: [] }, // Invalid subject + { action: 'read', subject: 'Execution', conditions: ['invalid'] }, // Invalid condition + { action: 'invalid', subject: 'Execution', conditions: [] }, // Invalid action + ]; + + const result = Permission.filter(permissions); + + expect(result).toStrictEqual([ + { action: 'read', subject: 'Flow', conditions: ['isCreator'] }, + { action: 'delete', subject: 'Connection', conditions: [] }, + { action: 'publish', subject: 'Flow', conditions: ['isCreator'] }, + ]); + }); + + describe('findAction', () => { + it('should return action from permission catalog', () => { + const action = Permission.findAction('create'); + expect(action.key).toStrictEqual('create'); + }); + + it('should return undefined for invalid actions', () => { + const invalidAction = Permission.findAction('invalidAction'); + expect(invalidAction).toBeUndefined(); + }); + }); + + describe('isSubjectValid', () => { + it('should return true for valid subjects', () => { + const validAction = permissionCatalog.actions.find( + (action) => action.key === 'create' + ); + + const validSubject = Permission.isSubjectValid('Connection', validAction); + expect(validSubject).toBe(true); + }); + + it('should return false for invalid subjects', () => { + const validAction = permissionCatalog.actions.find( + (action) => action.key === 'create' + ); + + const invalidSubject = Permission.isSubjectValid( + 'Execution', + validAction + ); + + expect(invalidSubject).toBe(false); + }); + }); + + describe('areConditionsValid', () => { + it('should return true for valid conditions', () => { + const validConditions = Permission.areConditionsValid(['isCreator']); + expect(validConditions).toBe(true); + }); + + it('should return false for invalid conditions', () => { + const invalidConditions = Permission.areConditionsValid([ + 'invalidCondition', + ]); + + expect(invalidConditions).toBe(false); + }); + }); + + describe('isConditionValid', () => { + it('should return true for valid conditions', () => { + const validCondition = Permission.isConditionValid('isCreator'); + expect(validCondition).toBe(true); + }); + + it('should return false for invalid conditions', () => { + const invalidCondition = Permission.isConditionValid('invalidCondition'); + expect(invalidCondition).toBe(false); + }); + }); +}); diff --git a/packages/backend/src/models/role.js b/packages/backend/src/models/role.js index 6760c321..dec80c5b 100644 --- a/packages/backend/src/models/role.js +++ b/packages/backend/src/models/role.js @@ -63,14 +63,14 @@ class Role extends Base { await this.$relatedQuery('permissions', trx).delete(); if (permissions?.length) { - const sanitizedPermissions = Permission.sanitize(permissions).map( + const validPermissions = Permission.filter(permissions).map( (permission) => ({ ...permission, roleId: this.id, }) ); - await Permission.query().insert(sanitizedPermissions); + await Permission.query().insert(validPermissions); } await this.$query(trx).patch({