diff --git a/package-lock.json b/package-lock.json index f9fe00e..260e7df 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "soul-cli", - "version": "0.7.1", + "version": "0.7.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "soul-cli", - "version": "0.7.1", + "version": "0.7.2", "license": "MIT", "dependencies": { "bcrypt": "^5.1.1", diff --git a/package.json b/package.json index 5e2d55f..a916db2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "soul-cli", - "version": "0.7.1", + "version": "0.7.2", "description": "A SQLite REST and Realtime server", "main": "src/server.js", "bin": { diff --git a/src/commands.js b/src/commands.js index b798a30..99993e2 100644 --- a/src/commands.js +++ b/src/commands.js @@ -7,8 +7,7 @@ const runCLICommands = () => { // if the updatesuperuser command is passed from the CLI execute the updatesuperuser function if (argv._.includes('updatesuperuser')) { const { id, password, is_superuser } = argv; - - if (!password && !is_superuser) { + if (!password && is_superuser === undefined) { console.log( 'Please provide either the --password or --is_superuser flag when using the updateuser command.', ); diff --git a/src/controllers/auth/tables.js b/src/controllers/auth/tables.js index 0dbdab0..3de0019 100644 --- a/src/controllers/auth/tables.js +++ b/src/controllers/auth/tables.js @@ -76,10 +76,10 @@ const createDefaultTables = async () => { permissions.push({ role_id: roleId, table_name: table.name, - create: 'false', - read: 'true', - update: 'false', - delete: 'false', + create: 0, + read: 1, + update: 0, + delete: 0, }); } diff --git a/src/controllers/auth/token.js b/src/controllers/auth/token.js index cd0e74f..a66894c 100644 --- a/src/controllers/auth/token.js +++ b/src/controllers/auth/token.js @@ -55,7 +55,7 @@ const obtainAccessToken = async (req, res) => { */ } - let permissions, roleIds; + let roleIds; // if the user is not a superuser get the role and its permission from the DB if (!toBoolean(user.is_superuser)) { @@ -64,7 +64,6 @@ const obtainAccessToken = async (req, res) => { res, }); - permissions = roleData.permissions; roleIds = roleData.roleIds; } @@ -73,7 +72,6 @@ const obtainAccessToken = async (req, res) => { userId: user.id, isSuperuser: user.is_superuser, roleIds, - permissions, }; // generate an access token @@ -151,7 +149,7 @@ const refreshAccessToken = async (req, res) => { */ } - let permissions, roleIds; + let roleIds; const user = users[0]; // if the user is not a superuser get the role and its permission from the DB @@ -161,7 +159,6 @@ const refreshAccessToken = async (req, res) => { res, }); - permissions = roleData.permissions; roleIds = roleData.roleIds; } @@ -170,7 +167,6 @@ const refreshAccessToken = async (req, res) => { userId: user.id, isSuperuser: user.is_superuser, roleIds, - permissions, }; // generate an access token diff --git a/src/controllers/auth/user.js b/src/controllers/auth/user.js index c7eccbc..b0d891a 100644 --- a/src/controllers/auth/user.js +++ b/src/controllers/auth/user.js @@ -25,7 +25,7 @@ const updateSuperuser = async (fields) => { try { // find the user by using the id field - const users = authService.getRoleByUserId({ id }); + const users = authService.getUsersById({ userId: id }); // abort if the id is invalid if (users.length === 0) { diff --git a/src/controllers/rows.js b/src/controllers/rows.js index 7d31c26..4a1acb7 100644 --- a/src/controllers/rows.js +++ b/src/controllers/rows.js @@ -657,7 +657,7 @@ const updateRowInTableByPK = async (req, res, next) => { if (typeof value === 'string') { value = `'${value}'`; } - return `${key} = ${value}`; + return `'${key}' = ${value}`; }) .join(', '); diff --git a/src/middlewares/api.js b/src/middlewares/api.js index 4b47a9a..7ff2bc1 100644 --- a/src/middlewares/api.js +++ b/src/middlewares/api.js @@ -6,9 +6,16 @@ const { responseMessages, } = require('../constants/'); const { removeFields } = require('../utils'); +const { customValidator } = require('../middlewares/validation'); +const schema = require('../schemas/auth'); const { httpVerbs } = apiConstants; -const { reservedTableNames, USERS_TABLE, tableFields } = dbConstants; +const { + reservedTableNames, + USERS_TABLE, + ROLES_PERMISSIONS_TABLE, + tableFields, +} = dbConstants; const { errorMessage } = responseMessages; const processRowRequest = async (req, res, next) => { @@ -39,6 +46,21 @@ const processRowRequest = async (req, res, next) => { ); } + // Validate fields for the _roles_permission API on POST and PUT requests + if ( + resource === ROLES_PERMISSIONS_TABLE && + (method === httpVerbs.POST || method === httpVerbs.PUT) + ) { + const validation = customValidator(schema.updateRolePermissions)(req); + + if (validation.errorStatus) { + return res.status(400).json({ + message: validation.message, + error: validation.details, + }); + } + } + next(); }; diff --git a/src/middlewares/auth.js b/src/middlewares/auth.js index ec74577..e93a8d5 100644 --- a/src/middlewares/auth.js +++ b/src/middlewares/auth.js @@ -1,6 +1,7 @@ const config = require('../config'); const { decodeToken, toBoolean } = require('../utils/index'); const { apiConstants, responseMessages } = require('../constants'); +const { authService } = require('../services'); const { errorMessage } = responseMessages; @@ -42,12 +43,16 @@ const hasAccess = async (req, res, next) => { .send({ message: errorMessage.NOT_AUTHORIZED_ERROR }); } - // if the user is not a super user, check the users permission on the resource - const permissions = payload.permissions.filter((row) => { - return row.table_name === tableName; + // if the user is not a super user, fetch the permission of the user from the DB + const rolePermissions = authService.getPermissionByRoleIds({ + roleIds: payload.roleIds, }); - if (permissions.length <= 0) { + const resourcePermission = rolePermissions.filter( + (row) => row.table_name === tableName, + ); + + if (resourcePermission.length <= 0) { return res .status(403) .send({ message: errorMessage.PERMISSION_NOT_DEFINED_ERROR }); @@ -56,7 +61,7 @@ const hasAccess = async (req, res, next) => { // If the user has permission on the table in at least in one of the roles then allow access on the table let hasPermission = false; - permissions.some((resource) => { + resourcePermission.some((resource) => { const httpMethod = apiConstants.httpMethodDefinitions[verb].toLowerCase(); diff --git a/src/middlewares/validation.js b/src/middlewares/validation.js index c8bcd69..7229a9c 100644 --- a/src/middlewares/validation.js +++ b/src/middlewares/validation.js @@ -19,6 +19,24 @@ const validator = (schema) => (req, res, next) => { } }; +const customValidator = (schema) => (req) => { + const response = { errorStatus: false, message: '', error: '' }; + + const { body, params, query, cookies } = req; + const data = { body, params, query, cookies }; + + const { error } = schema.validate(data); + + if (error) { + response.errorStatus = true; + response.message = error.message; + response.error = error.details; + } + + return response; +}; + module.exports = { validator, + customValidator, }; diff --git a/src/schemas/auth.js b/src/schemas/auth.js index 369edf2..7f37a3d 100644 --- a/src/schemas/auth.js +++ b/src/schemas/auth.js @@ -59,9 +59,30 @@ const registerUser = Joi.object({ }).required(), }); +const updateRolePermissions = Joi.object({ + query: Joi.object({}).required(), + params: Joi.object({ name: Joi.string(), pks: Joi.string() }).required(), + body: Joi.object({ + fields: Joi.object({ + role_id: Joi.number().required(), + table_name: Joi.string().required(), + create: Joi.number().valid(0, 1).required(), + read: Joi.number().valid(0, 1).required(), + update: Joi.number().valid(0, 1).required(), + delete: Joi.number().valid(0, 1).required(), + }).required(), + }).required(), + + cookies: Joi.object({ + accessToken: Joi.string().required(), + refreshToken: Joi.string().optional(), + }).required(), +}); + module.exports = { obtainAccessToken, refreshAccessToken, changePassword, registerUser, + updateRolePermissions, };