Initial project setup

This commit is contained in:
Gowtham M 2026-06-17 12:54:24 +05:30
commit 69588c1889
4 changed files with 36 additions and 13 deletions

View File

@ -363,12 +363,10 @@ components:
module_id: { type: integer, example: 1 } module_id: { type: integer, example: 1 }
actions: actions:
type: object type: object
required: [view, create, edit, delete, approve, export] required: [view, edit, approve, export]
properties: properties:
view: { type: boolean, example: true } view: { type: boolean, example: true }
create: { type: boolean, example: true } edit: { type: boolean, example: true, description: 'Add & edit (grants create + edit)' }
edit: { type: boolean, example: true }
delete: { type: boolean, example: false }
approve: { type: boolean, example: false } approve: { type: boolean, example: false }
export: { type: boolean, example: true } export: { type: boolean, example: true }
@ -1619,7 +1617,7 @@ paths:
schema: { type: string } schema: { type: string }
get: get:
tags: [Roles] tags: [Roles]
summary: Permission matrix for role (modules x actions checkboxes) summary: Permission matrix for role (modules x view/edit/approve/export; edit = add + edit)
responses: responses:
"200": "200":
description: Matrix fetched description: Matrix fetched

View File

@ -23,7 +23,7 @@ router.get(
controller.list controller.list
); );
router.get('/:id', authorize('ROLES', 'view'), controller.getOne); router.get('/:id', authorize('ROLES', 'view'), controller.getOne);
router.post('/', authorize('ROLES', 'create'), validate(createRoleSchema), controller.create); router.post('/', authorize('ROLES', 'edit'), validate(createRoleSchema), controller.create);
router.put('/:id', authorize('ROLES', 'edit'), validate(updateRoleSchema), controller.update); router.put('/:id', authorize('ROLES', 'edit'), validate(updateRoleSchema), controller.update);
router.put( router.put(
'/:id/permissions', '/:id/permissions',
@ -38,6 +38,6 @@ router.put(
validate(permissionMatrixSchema), validate(permissionMatrixSchema),
controller.savePermissionMatrix controller.savePermissionMatrix
); );
router.delete('/:id', authorize('ROLES', 'delete'), controller.remove); router.delete('/:id', authorize('ROLES', 'edit'), controller.remove);
module.exports = router; module.exports = router;

View File

@ -3,7 +3,8 @@ const ApiError = require('../../utils/ApiError');
const auditLog = require('../../utils/auditLog'); const auditLog = require('../../utils/auditLog');
const { getPagination } = require('../../utils/pagination'); const { getPagination } = require('../../utils/pagination');
const PERMISSION_ACTIONS = ['view', 'create', 'edit', 'delete', 'approve', 'export']; const MATRIX_ACTIONS = ['view', 'edit', 'approve', 'export'];
const MERGED_EDIT_ACTIONS = ['create', 'edit'];
const permissionSelect = { const permissionSelect = {
permissions: { permissions: {
@ -293,7 +294,19 @@ const getPermissionMatrix = async (id) => {
const matrix = modules.map((mod) => { const matrix = modules.map((mod) => {
const permissions = {}; const permissions = {};
for (const action of PERMISSION_ACTIONS) { for (const action of MATRIX_ACTIONS) {
if (action === 'edit') {
const createPerm = mod.permissions.find((p) => p.action === 'create');
const editPerm = mod.permissions.find((p) => p.action === 'edit');
const merged = [createPerm, editPerm].filter(Boolean);
permissions.edit = {
permission_id: editPerm?.id ?? createPerm?.id ?? null,
permission_ids: merged.map((p) => p.id),
granted: merged.some((p) => granted.has(p.id.toString())),
};
continue;
}
const perm = mod.permissions.find((p) => p.action === action); const perm = mod.permissions.find((p) => p.action === action);
permissions[action] = { permissions[action] = {
permission_id: perm?.id ?? null, permission_id: perm?.id ?? null,
@ -310,7 +323,7 @@ const getPermissionMatrix = async (id) => {
return { return {
role: { id: role.id, name: role.name }, role: { id: role.id, name: role.name },
actions: PERMISSION_ACTIONS, actions: MATRIX_ACTIONS,
modules: matrix, modules: matrix,
}; };
}; };
@ -327,8 +340,22 @@ const savePermissionMatrix = async (id, matrix, userId, requestId) => {
const permissionIds = []; const permissionIds = [];
for (const row of matrix) { for (const row of matrix) {
for (const action of PERMISSION_ACTIONS) { for (const action of MATRIX_ACTIONS) {
if (!row.actions?.[action]) continue; if (!row.actions?.[action]) continue;
if (action === 'edit') {
for (const dbAction of MERGED_EDIT_ACTIONS) {
const perm = catalog.find(
(p) => p.module_id.toString() === String(row.module_id) && p.action === dbAction
);
if (!perm) {
throw new ApiError(422, `Permission not found for module ${row.module_id}:${dbAction}`);
}
permissionIds.push(perm.id);
}
continue;
}
const perm = catalog.find( const perm = catalog.find(
(p) => p.module_id.toString() === String(row.module_id) && p.action === action (p) => p.module_id.toString() === String(row.module_id) && p.action === action
); );

View File

@ -23,9 +23,7 @@ const permissionMatrixSchema = Joi.object({
module_id: Joi.number().integer().positive().required(), module_id: Joi.number().integer().positive().required(),
actions: Joi.object({ actions: Joi.object({
view: Joi.boolean().required(), view: Joi.boolean().required(),
create: Joi.boolean().required(),
edit: Joi.boolean().required(), edit: Joi.boolean().required(),
delete: Joi.boolean().required(),
approve: Joi.boolean().required(), approve: Joi.boolean().required(),
export: Joi.boolean().required(), export: Joi.boolean().required(),
}).required(), }).required(),