From 85f78103cf5d22ff6833bc4cc25221a877ea525d Mon Sep 17 00:00:00 2001 From: "Md. Ashikul Alam" Date: Mon, 21 Oct 2024 17:53:22 +0600 Subject: [PATCH] chore: update permission of scopes in backend routes --- packages/client/src/tests/util.tsx | 10 - .../inExternalValidationTab.test.tsx | 2 +- packages/commons/src/scopes.ts | 5 +- packages/config/src/config/routes.ts | 98 +------ .../certificate/certificateHandler.test.ts | 251 ------------------ .../certificate/certificateHandler.ts | 142 ---------- packages/gateway/src/config/routes.ts | 7 +- packages/gateway/src/utils/testUtils.ts | 39 --- packages/metrics/src/config/routes.ts | 7 +- packages/notification/src/config/routes.ts | 67 +++-- packages/search/src/config/routes.ts | 73 ++--- .../registration/assignment/handler.ts | 3 +- .../search/src/features/search/handler.ts | 3 +- packages/search/src/test/utils.ts | 53 +--- packages/user-mgnt/src/config/routes.ts | 190 ++++++------- packages/workflow/test/mocks/user.ts | 2 +- 16 files changed, 198 insertions(+), 754 deletions(-) delete mode 100644 packages/config/src/handlers/certificate/certificateHandler.test.ts delete mode 100644 packages/config/src/handlers/certificate/certificateHandler.ts diff --git a/packages/client/src/tests/util.tsx b/packages/client/src/tests/util.tsx index 7acc8f234e2..16012dd13a2 100644 --- a/packages/client/src/tests/util.tsx +++ b/packages/client/src/tests/util.tsx @@ -170,16 +170,6 @@ export const ACTION_STATUS_MAP = { SUBMISSION_STATUS.READY_TO_REQUEST_CORRECTION } as const -export const validateScopeToken = jwt.sign( - { scope: ['validate'] }, - readFileSync('./test/cert.key'), - { - algorithm: 'RS256', - issuer: 'opencrvs:auth-service', - audience: 'opencrvs:gateway-user' - } -) - export function flushPromises() { return new Promise((resolve) => setImmediate(resolve)) } diff --git a/packages/client/src/views/OfficeHome/inExternalValidation/inExternalValidationTab.test.tsx b/packages/client/src/views/OfficeHome/inExternalValidation/inExternalValidationTab.test.tsx index 337807939df..8ebebb6de43 100644 --- a/packages/client/src/views/OfficeHome/inExternalValidation/inExternalValidationTab.test.tsx +++ b/packages/client/src/views/OfficeHome/inExternalValidation/inExternalValidationTab.test.tsx @@ -30,7 +30,7 @@ const EVENT_CREATION_TIME = 1583322631424 // Wed Mar 04 2020 13:50:31 GMT+0200 ( const SEND_FOR_VALIDATION_TIME = 1582912800000 // Fri Feb 28 2020 20:00:00 GMT+0200 (Eastern European Standard Time) const registerScopeToken = jwt.sign( - { scope: ['register'] }, + { scope: ['record.register'] }, readFileSync('./test/cert.key'), { algorithm: 'RS256', diff --git a/packages/commons/src/scopes.ts b/packages/commons/src/scopes.ts index 9279747ce01..8cb7d4e600e 100644 --- a/packages/commons/src/scopes.ts +++ b/packages/commons/src/scopes.ts @@ -105,7 +105,10 @@ export const scopes = [ 'user.create', 'user.create:my-jurisdiction', 'user.update:my-office', - 'user.update' + 'user.update', + + // config + 'config.update-all' ] as const export type Scope = (typeof scopes)[number] diff --git a/packages/config/src/config/routes.ts b/packages/config/src/config/routes.ts index 2fb26a97195..794addc8273 100644 --- a/packages/config/src/config/routes.ts +++ b/packages/config/src/config/routes.ts @@ -8,15 +8,6 @@ * * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ -import { - createCertificateHandler, - getActiveCertificatesHandler, - getCertificateHandler, - requestActiveCertificate, - requestNewCertificate, - updateCertificate, - updateCertificateHandler -} from '@config/handlers/certificate/certificateHandler' import configHandler, { getLoginConfigHandler } from '@config/handlers/application/applicationConfigHandler' @@ -73,13 +64,14 @@ export default function getRoutes(): ServerRoute[] { options: { auth: { scope: [ - RouteScope.NATLSYSADMIN, - RouteScope.DECLARE, - RouteScope.REGISTER, - RouteScope.CERTIFY, - RouteScope.PERFORMANCE, - RouteScope.SYSADMIN, - RouteScope.VALIDATE + 'config.update-all', + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.certify', + 'performance.read', + 'record.submit-for-approval' ] }, tags: ['api'], @@ -114,76 +106,6 @@ export default function getRoutes(): ServerRoute[] { description: 'Retrieve forms' } }, - { - method: 'POST', - path: '/getCertificate', - handler: getCertificateHandler, - options: { - tags: ['api'], - description: 'Retrieves certificate', - auth: { - scope: [ - RouteScope.NATLSYSADMIN, - RouteScope.REGISTER, - RouteScope.CERTIFY, - RouteScope.VALIDATE - ] - }, - validate: { - payload: requestActiveCertificate - } - } - }, - { - method: 'GET', - path: '/getActiveCertificates', - handler: getActiveCertificatesHandler, - options: { - tags: ['api'], - description: 'Retrieves active certificates for birth and death', - auth: { - scope: [ - RouteScope.NATLSYSADMIN, - RouteScope.DECLARE, - RouteScope.REGISTER, - RouteScope.CERTIFY, - RouteScope.PERFORMANCE, - RouteScope.SYSADMIN, - RouteScope.VALIDATE - ] - } - } - }, - { - method: 'POST', - path: '/createCertificate', - handler: createCertificateHandler, - options: { - tags: ['api'], - description: 'Creates a new Certificate', - auth: { - scope: [RouteScope.NATLSYSADMIN] - }, - validate: { - payload: requestNewCertificate - } - } - }, - { - method: 'POST', - path: '/updateCertificate', - handler: updateCertificateHandler, - options: { - tags: ['api'], - description: 'Updates an existing Certificate', - auth: { - scope: [RouteScope.NATLSYSADMIN] - }, - validate: { - payload: updateCertificate - } - } - }, { method: 'GET', path: '/dashboardQueries', @@ -214,7 +136,7 @@ export default function getRoutes(): ServerRoute[] { options: { tags: ['api'], auth: { - scope: ['natlsysadmin'] + scope: ['config.update-all'] }, description: 'Create a location', validate: { @@ -242,7 +164,7 @@ export default function getRoutes(): ServerRoute[] { options: { tags: ['api'], auth: { - scope: ['natlsysadmin'] + scope: ['config.update-all'] }, description: 'Update a location or facility', validate: { diff --git a/packages/config/src/handlers/certificate/certificateHandler.test.ts b/packages/config/src/handlers/certificate/certificateHandler.test.ts deleted file mode 100644 index cca060e6609..00000000000 --- a/packages/config/src/handlers/certificate/certificateHandler.test.ts +++ /dev/null @@ -1,251 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - * - * OpenCRVS is also distributed under the terms of the Civil Registration - * & Healthcare Disclaimer located at http://opencrvs.org/license. - * - * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. - */ -import { createServer } from '@config/server' -import Certificate, { ICertificateModel } from '@config/models/certificate' -import * as fetchMock from 'jest-fetch-mock' -import * as mockingoose from 'mockingoose' -import * as jwt from 'jsonwebtoken' -import { readFileSync } from 'fs' - -export enum Event { - BIRTH = 'birth', - DEATH = 'death', - MARRIAGE = 'marriage' -} -export enum Status { - ACTIVE = 'ACTIVE', - INACTIVE = 'INACTIVE' -} - -const token = jwt.sign( - { scope: ['natlsysadmin'] }, - readFileSync('./test/cert.key'), - { - algorithm: 'RS256', - issuer: 'opencrvs:auth-service', - audience: 'opencrvs:config-user' - } -) - -const fetch = fetchMock as fetchMock.FetchMock - -const mockCertificate = { - svgCode: 'ocrvs/1234-6789.svg', - svgFilename: 'ocrvs.svg', - user: 'dde0846b-4b0f-4732-80e7-b0f06444fef5', - event: 'birth', - status: 'ACTIVE' -} as unknown as ICertificateModel - -describe('createCertificate handler', () => { - let server: any - const svgCode = 'ocrvs/1234-6789.svg' - - beforeEach(async () => { - mockingoose.resetAll() - server = await createServer() - fetch.resetMocks() - }) - - it('creates and saves new certificate using mongoose', async () => { - mockingoose(Certificate).toReturn(mockCertificate, 'save') - - const res = await server.server.inject({ - method: 'POST', - url: '/createCertificate', - payload: { - svgCode: svgCode, - svgFilename: 'sample_doc.jpeg', - user: 'dde0846b-4b0f-4732-80e7-b0f06444fef5', - event: 'birth', - status: 'ACTIVE' - }, - headers: { - Authorization: `Bearer ${token}` - } - }) - expect(res.statusCode).toBe(201) - }) - - it('returns error when tries to saves invalid svg code using mongoose', async () => { - mockingoose(Certificate).toReturn(mockCertificate, 'save') - - const res = await server.server.inject({ - method: 'POST', - url: '/createCertificate', - payload: { - svgCode: 1123, - svgFilename: 'sample_doc.jpeg', - user: 'dde0846b-4b0f-4732-80e7-b0f06444fef5', - event: 'birth', - status: 'ACTIVE' - }, - headers: { - Authorization: `Bearer ${token}` - } - }) - expect(res.statusCode).toBe(400) - }) -}) - -describe('getCertificate handler', () => { - let server: any - - beforeEach(async () => { - mockingoose.resetAll() - server = await createServer() - fetch.resetMocks() - }) - - it('get active certificate for birth using mongoose', async () => { - mockingoose(Certificate).toReturn(mockCertificate, 'findOne') - - const res = await server.server.inject({ - method: 'POST', - url: '/getCertificate', - payload: { - status: 'ACTIVE', - event: 'birth' - }, - headers: { - Authorization: `Bearer ${token}` - } - }) - expect(res.statusCode).toBe(200) - }) - - it('get active certificate for marriage using mongoose', async () => { - mockingoose(Certificate).toReturn(mockCertificate, 'findOne') - - const res = await server.server.inject({ - method: 'POST', - url: '/getCertificate', - payload: { - status: 'ACTIVE', - event: 'marriage' - }, - headers: { - Authorization: `Bearer ${token}` - } - }) - expect(res.statusCode).toBe(200) - }) - - it('return no result found for active death certificate', async () => { - mockingoose(Certificate).toReturn(null, 'findOne') - - const res = await server.server.inject({ - method: 'POST', - url: '/getCertificate', - payload: { - status: 'ACTIVE', - event: 'death' - }, - headers: { - Authorization: `Bearer ${token}` - } - }) - - expect(res.statusCode).toBe(404) - }) -}) - -describe('getActiveCertificates handler', () => { - let server: any - - beforeEach(async () => { - mockingoose.resetAll() - server = await createServer() - fetch.resetMocks() - }) - - it('get active certificate for birth and death using mongoose', async () => { - mockingoose(Certificate).toReturn(mockCertificate, 'find') - - const res = await server.server.inject({ - method: 'GET', - url: '/getActiveCertificates', - headers: { - Authorization: `Bearer ${token}` - } - }) - expect(res.statusCode).toBe(200) - }) -}) - -describe('updateCertificate handler', () => { - let server: any - - beforeEach(async () => { - mockingoose.resetAll() - server = await createServer() - fetch.resetMocks() - }) - - it('update certificate to inactive using mongoose', async () => { - mockCertificate.id = '61c4664e663fc6af203b63b8' - mockingoose(Certificate).toReturn(mockCertificate, 'findOne') - mockingoose(Certificate).toReturn(mockCertificate, 'update') - - const res = await server.server.inject({ - method: 'POST', - url: '/updateCertificate', - payload: { - id: '61c4664e663fc6af203b63b8', - status: 'INACTIVE' - }, - headers: { - Authorization: `${token}` - } - }) - expect(res.statusCode).toBe(201) - }) - - it('return error when tries to save invalid data', async () => { - mockingoose(Certificate).toReturn(null, 'findOne') - mockingoose(Certificate).toReturn({}, 'update') - - const res = await server.server.inject({ - method: 'POST', - url: '/getCertificate', - payload: { - id: '61c4664e663fc6af203b63b8', - svgFilename: 1234 - }, - headers: { - Authorization: `${token}` - } - }) - - expect(res.statusCode).toBe(400) - }) -}) - -describe('deleteCertificate handler', () => { - let server: any - - beforeEach(async () => { - mockingoose.resetAll() - server = await createServer() - fetch.resetMocks() - }) - - it('return error when there is no param', async () => { - mockingoose(Certificate).toReturn({}, 'findOneAndRemove') - - const res = await server.server.inject({ - method: 'DELETE', - url: '/certificate' - }) - - expect(res.statusCode).toBe(404) - }) -}) diff --git a/packages/config/src/handlers/certificate/certificateHandler.ts b/packages/config/src/handlers/certificate/certificateHandler.ts deleted file mode 100644 index 44a0d840794..00000000000 --- a/packages/config/src/handlers/certificate/certificateHandler.ts +++ /dev/null @@ -1,142 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - * - * OpenCRVS is also distributed under the terms of the Civil Registration - * & Healthcare Disclaimer located at http://opencrvs.org/license. - * - * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. - */ -import * as Hapi from '@hapi/hapi' -import Certificate, { - ICertificateModel, - Status, - Event -} from '@config/models/certificate' // IDeclarationConfigurationModel -import { logger } from '@opencrvs/commons' -import * as Joi from 'joi' -import { badRequest, notFound } from '@hapi/boom' -import { verifyToken } from '@config/utils/verifyToken' -import { RouteScope } from '@config/config/routes' -import { pipe } from 'fp-ts/lib/function' - -interface IActivePayload { - status: Status - event: Event -} - -export async function getCertificateHandler( - request: Hapi.Request, - h: Hapi.ResponseToolkit -) { - const { status, event } = request.payload as IActivePayload - const certificate: ICertificateModel | null = await Certificate.findOne({ - status: status, - event: event - }) - - if (!certificate) { - throw notFound() - } - return certificate -} - -export async function getActiveCertificatesHandler( - request: Hapi.Request, - h: Hapi.ResponseToolkit -) { - const token = request.headers.authorization.replace('Bearer ', '') - const decodedOrError = pipe(token, verifyToken) - if (decodedOrError._tag === 'Left') { - return [] - } - const { scope } = decodedOrError.right - - if ( - scope && - (scope.includes(RouteScope.CERTIFY) || - scope.includes(RouteScope.VALIDATE) || - scope.includes(RouteScope.NATLSYSADMIN)) - ) { - const activeCertificates = await Certificate.find({ - status: Status.ACTIVE, - event: { $in: [Event.BIRTH, Event.DEATH, Event.MARRIAGE] } - }).lean() - return activeCertificates - } - return [] -} - -export async function createCertificateHandler( - request: Hapi.Request, - h: Hapi.ResponseToolkit -) { - const newCertificate = request.payload as ICertificateModel - // save new certificate - let certificateResponse - try { - certificateResponse = await Certificate.create(newCertificate) - } catch (err) { - logger.error(err) - // return 400 if there is a validation error when saving to mongo - return h.response().code(400) - } - return h.response(certificateResponse).code(201) -} - -export async function updateCertificateHandler( - request: Hapi.Request, - h: Hapi.ResponseToolkit -) { - try { - const certificate = request.payload as ICertificateModel - const existingCertificate: ICertificateModel | null = - await Certificate.findOne({ _id: certificate.id }) - if (!existingCertificate) { - throw badRequest(`No certificate found by given id: ${certificate.id}`) - } - // Update existing certificate's fields - existingCertificate.svgCode = certificate.svgCode - existingCertificate.svgFilename = certificate.svgFilename - existingCertificate.svgDateUpdated = Date.now() - existingCertificate.user = certificate.user - existingCertificate.event = certificate.event - existingCertificate.status = certificate.status - await Certificate.update( - { _id: existingCertificate._id }, - existingCertificate - ) - return h.response(existingCertificate).code(201) - } catch (err) { - logger.error(err) - // return 400 if there is a validation error when saving to mongo - return h.response().code(400) - } -} - -export const requestActiveCertificate = Joi.object({ - status: Joi.string().required(), - event: Joi.string().required() -}) - -export const requestNewCertificate = Joi.object({ - svgCode: Joi.string(), - svgFilename: Joi.string(), - svgDateUpdated: Joi.number(), - svgDateCreated: Joi.number(), - user: Joi.string(), - event: Joi.string(), - status: Joi.string() -}) - -export const updateCertificate = Joi.object({ - id: Joi.string().required(), - svgCode: Joi.string(), - svgFilename: Joi.string(), - svgDateUpdated: Joi.number(), - svgDateCreated: Joi.number(), - user: Joi.string(), - event: Joi.string(), - status: Joi.string() -}) diff --git a/packages/gateway/src/config/routes.ts b/packages/gateway/src/config/routes.ts index 10d82963c9c..bdafc017c44 100644 --- a/packages/gateway/src/config/routes.ts +++ b/packages/gateway/src/config/routes.ts @@ -47,7 +47,12 @@ export const getRoutes = () => { tags: ['api'], description: 'Create a health notification', auth: { - scope: ['declare', 'notification-api'] + scope: [ + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'notification-api' + ] }, validate: { payload: fhirBundleSchema, diff --git a/packages/gateway/src/utils/testUtils.ts b/packages/gateway/src/utils/testUtils.ts index 476fd6a36f3..77d288d50f6 100644 --- a/packages/gateway/src/utils/testUtils.ts +++ b/packages/gateway/src/utils/testUtils.ts @@ -1778,45 +1778,6 @@ export const mockTaskForError = { } } -export const mockUserDetails = { - _id: '5d027bc403b93b17526323f6', - name: [ - { - use: 'en', - given: ['Sakib Al'], - family: 'Hasan' - } - ], - username: 'sakibal.hasan', - mobile: '+8801711111111', - email: 'test@test.org', - identifiers: [], - passwordHash: - 'b8be6cae5215c93784b1b9e2c06384910f754b1d66c077f1f8fdc98fbd92e6c17a0fdc790b30225986cadb9553e87a47b1d2eb7bd986f96f0da7873e1b2ddf9c', - salt: '12345', - scope: ['register'], - role: 'Field Agent', - status: 'active', - practitionerId: '2d11389d-f58e-4d47-a562-b934f1b85936', - primaryOfficeId: '79776844-b606-40e9-8358-7d82147f702a', - securityQuestionAnswers: [ - { - questionKey: 'BIRTH_TOWN', - answerHash: '$2a$10$uHhZhgHqgOdt7CZdkKCysO/sVyYHwbEhB5q5TPE.fN9O1kiz0OxVG' - }, - { - questionKey: 'MOTHER_NICK_NAME', - answerHash: '$2a$10$uHhZhgHqgOdt7CZdkKCysO/sVyYHwbEhB5q5TPE.fN9O1kiz0OxVG' - }, - { - questionKey: 'FAVORITE_MOVIE', - answerHash: '$2a$10$uHhZhgHqgOdt7CZdkKCysO/sVyYHwbEhB5q5TPE.fN9O1kiz0OxVG' - } - ], - creationDate: 1559054406433, - auditHistory: [] -} - export const mockFhirLocation = { resourceType: 'Location', identifier: [ diff --git a/packages/metrics/src/config/routes.ts b/packages/metrics/src/config/routes.ts index c243eb679ba..2ce1758eba3 100644 --- a/packages/metrics/src/config/routes.ts +++ b/packages/metrics/src/config/routes.ts @@ -78,9 +78,6 @@ import { import { PRODUCTION, QA_ENV } from '@metrics/constants' import * as Hapi from '@hapi/hapi' -const enum RouteScope { - NATLSYSADMIN = 'natlsysadmin' -} export enum EventType { BIRTH = 'birth', DEATH = 'death', @@ -717,7 +714,7 @@ export const getRoutes = () => { handler: metricsDeleteMeasurementHandler, options: { auth: { - scope: [RouteScope.NATLSYSADMIN] + scope: ['config.update-all'] }, tags: ['api'] } @@ -729,7 +726,7 @@ export const getRoutes = () => { handler: deletePerformanceHandler, options: { auth: { - scope: [RouteScope.NATLSYSADMIN] + scope: ['config.update-all'] }, tags: ['api'] } diff --git a/packages/notification/src/config/routes.ts b/packages/notification/src/config/routes.ts index 9bf78f9cae8..ad433666de3 100644 --- a/packages/notification/src/config/routes.ts +++ b/packages/notification/src/config/routes.ts @@ -64,15 +64,6 @@ import { deathSentForUpdatesNotification } from '@notification/features/sentForUpdates/handler' -const enum RouteScope { - DECLARE = 'declare', - VALIDATE = 'validate', - REGISTER = 'register', - CERTIFY = 'certify', - SYSADMIN = 'sysadmin', - NATIONAL_SYSTEM_ADMIN = 'natlsysadmin' -} - const recordValidation: RouteOptionsValidate = { payload: Joi.object() } @@ -226,10 +217,12 @@ export default function getRoutes(): ServerRoute[] { description: 'Sends an sms to a user for birth in-progress entry', auth: { scope: [ - RouteScope.DECLARE, - RouteScope.VALIDATE, - RouteScope.REGISTER, - RouteScope.CERTIFY + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.certify', + 'record.submit-for-approval' ] }, validate: { @@ -247,10 +240,12 @@ export default function getRoutes(): ServerRoute[] { 'Sends an sms or email to a user for birth declaration entry', auth: { scope: [ - RouteScope.DECLARE, - RouteScope.VALIDATE, - RouteScope.REGISTER, - RouteScope.CERTIFY + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.certify', + 'record.submit-for-approval' ] }, validate: { @@ -267,7 +262,7 @@ export default function getRoutes(): ServerRoute[] { description: 'Sends an sms or email to a user for birth registration entry', auth: { - scope: [RouteScope.REGISTER] + scope: ['record.register'] }, validate: { payload: registrationNotificationSchema @@ -283,7 +278,7 @@ export default function getRoutes(): ServerRoute[] { description: 'Sends an sms or email to a user for birth declaration rejection entry', auth: { - scope: [RouteScope.VALIDATE, RouteScope.REGISTER] + scope: ['record.submit-for-approval', 'record.register'] }, validate: { payload: rejectionNotificationSchema @@ -300,10 +295,12 @@ export default function getRoutes(): ServerRoute[] { 'Sends an sms or email to a user for death in-progress entry', auth: { scope: [ - RouteScope.DECLARE, - RouteScope.VALIDATE, - RouteScope.REGISTER, - RouteScope.CERTIFY + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.certify', + 'record.submit-for-approval' ] }, validate: { @@ -321,10 +318,12 @@ export default function getRoutes(): ServerRoute[] { 'Sends an sms or email to a user for death declaration entry', auth: { scope: [ - RouteScope.DECLARE, - RouteScope.VALIDATE, - RouteScope.REGISTER, - RouteScope.CERTIFY + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.certify', + 'record.submit-for-approval' ] }, validate: { @@ -340,7 +339,7 @@ export default function getRoutes(): ServerRoute[] { tags: ['api'], description: 'Sends an sms to a user for death registration entry', auth: { - scope: [RouteScope.REGISTER] + scope: ['record.register'] }, validate: { payload: registrationNotificationSchema @@ -356,7 +355,7 @@ export default function getRoutes(): ServerRoute[] { description: 'Sends an sms to a user for death declaration rejection entry', auth: { - scope: [RouteScope.VALIDATE, RouteScope.REGISTER] + scope: ['record.submit-for-approval', 'record.register'] }, validate: { payload: rejectionNotificationSchema @@ -371,7 +370,7 @@ export default function getRoutes(): ServerRoute[] { tags: ['api'], description: 'Sends an sms to a user with credentials', auth: { - scope: [RouteScope.SYSADMIN] + scope: ['config.update-all'] }, validate: { payload: userCredentialsNotificationSchema @@ -386,7 +385,7 @@ export default function getRoutes(): ServerRoute[] { tags: ['api'], description: 'Sends an sms to a user with credentials', auth: { - scope: [RouteScope.REGISTER] + scope: ['record.register'] }, validate: { payload: sendCorrectionRejectedNotificationInput @@ -401,7 +400,7 @@ export default function getRoutes(): ServerRoute[] { tags: ['api'], description: 'Sends an sms to a user with credentials', auth: { - scope: [RouteScope.REGISTER] + scope: ['record.register'] }, validate: { payload: sendCorrectionApprovedNotificationInput @@ -416,7 +415,7 @@ export default function getRoutes(): ServerRoute[] { tags: ['api'], description: 'Sends an sms to a user with new temporary password', auth: { - scope: [RouteScope.SYSADMIN] + scope: ['config.update-all'] }, validate: { payload: userPasswordResetNotificationSchema @@ -454,7 +453,7 @@ export default function getRoutes(): ServerRoute[] { options: { tags: ['api'], auth: { - scope: [RouteScope.NATIONAL_SYSTEM_ADMIN] + scope: ['config.update-all'] }, description: 'Sends emails to all users given in payload', validate: { diff --git a/packages/search/src/config/routes.ts b/packages/search/src/config/routes.ts index a92c882b64c..a740dfe9f09 100644 --- a/packages/search/src/config/routes.ts +++ b/packages/search/src/config/routes.ts @@ -31,17 +31,6 @@ import { reindexStatusHandler } from '@search/features/reindex/handler' -export const enum RouteScope { - DECLARE = 'declare', - VALIDATE = 'validate', - REGISTER = 'register', - SYSADMIN = 'sysadmin', - CERTIFY = 'certify', - NATLSYSADMIN = 'natlsysadmin', - PERFORMANCE = 'performance', - RECORD_SEARCH = 'recordsearch' -} - export const getRoutes = () => { const client = getOrCreateClient() const routes = [ @@ -93,7 +82,13 @@ export const getRoutes = () => { config: { tags: ['api'], auth: { - scope: [RouteScope.DECLARE, RouteScope.VALIDATE, RouteScope.REGISTER] + scope: [ + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.submit-for-approval' + ] }, description: 'Handles searching declaration assignment' } @@ -184,10 +179,12 @@ export const getRoutes = () => { tags: ['api'], auth: { scope: [ - RouteScope.DECLARE, - RouteScope.VALIDATE, - RouteScope.REGISTER, - RouteScope.SYSADMIN + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.submit-for-approval', + 'config.update-all' ] }, description: 'Returns all the documents in the index' @@ -201,11 +198,13 @@ export const getRoutes = () => { tags: ['api'], auth: { scope: [ - RouteScope.DECLARE, - RouteScope.VALIDATE, - RouteScope.REGISTER, - RouteScope.SYSADMIN, - RouteScope.PERFORMANCE + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'performance.read', + 'record.submit-for-approval', + 'config.update-all' ] }, validate: { @@ -226,11 +225,13 @@ export const getRoutes = () => { tags: ['api'], auth: { scope: [ - RouteScope.RECORD_SEARCH, - RouteScope.DECLARE, - RouteScope.VALIDATE, - RouteScope.REGISTER, - RouteScope.SYSADMIN + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.submit-for-approval', + 'config.update-all', + 'recordsearch' ] }, description: @@ -245,10 +246,12 @@ export const getRoutes = () => { tags: ['api'], auth: { scope: [ - RouteScope.DECLARE, - RouteScope.VALIDATE, - RouteScope.REGISTER, - RouteScope.SYSADMIN + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.submit-for-approval', + 'config.update-all' ] }, description: 'Handles searching from declarations' @@ -262,10 +265,12 @@ export const getRoutes = () => { tags: ['api'], auth: { scope: [ - RouteScope.DECLARE, - RouteScope.VALIDATE, - RouteScope.REGISTER, - RouteScope.SYSADMIN + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.submit-for-approval', + 'config.update-all' ] }, description: 'Handle searching from death declarations' diff --git a/packages/search/src/features/registration/assignment/handler.ts b/packages/search/src/features/registration/assignment/handler.ts index 5172aa4eb46..cfa28e83088 100644 --- a/packages/search/src/features/registration/assignment/handler.ts +++ b/packages/search/src/features/registration/assignment/handler.ts @@ -16,7 +16,6 @@ import { logger } from '@opencrvs/commons' import { internal } from '@hapi/boom' import * as Hapi from '@hapi/hapi' import { getTokenPayload } from '@search/utils/authUtils' -import { RouteScope } from '@search/config/routes' export async function assignEventHandler( request: Hapi.Request, @@ -24,7 +23,7 @@ export async function assignEventHandler( ) { try { const tokenPayload = getTokenPayload(request.headers.authorization) - if (tokenPayload.scope.includes(RouteScope.RECORD_SEARCH)) { + if (tokenPayload.scope.includes('recordsearch')) { return h.response().code(200) } diff --git a/packages/search/src/features/search/handler.ts b/packages/search/src/features/search/handler.ts index fa0e830fd88..aa602374bca 100644 --- a/packages/search/src/features/search/handler.ts +++ b/packages/search/src/features/search/handler.ts @@ -22,7 +22,6 @@ import { import { searchByCompositionId } from '@search/elasticsearch/dbhelper' import { OPENCRVS_INDEX_NAME } from '@search/constants' import { getTokenPayload } from '@search/utils/authUtils' -import { RouteScope } from '@search/config/routes' import { searchForDeathDuplicates, searchForBirthDuplicates @@ -207,7 +206,7 @@ export async function advancedRecordSearch( try { let isExternalSearch = false const tokenPayload = getTokenPayload(request.headers.authorization) - if (tokenPayload.scope.includes(RouteScope.RECORD_SEARCH)) { + if (tokenPayload.scope.includes('recordsearch')) { isExternalSearch = true } const result = await advancedSearch( diff --git a/packages/search/src/test/utils.ts b/packages/search/src/test/utils.ts index be37a594664..46103b33725 100644 --- a/packages/search/src/test/utils.ts +++ b/packages/search/src/test/utils.ts @@ -4556,59 +4556,8 @@ export const mockMinimalMarriageFhirBundle = { ] } -export const dummyUser = { - _id: '5d027bc403b93b17526323f6', - name: [ - { - use: 'en', - given: ['Sakib Al'], - family: 'Hasan' - } - ], - username: 'sakibal.hasan', - mobile: '+8801711111111', - email: 'test@test.org', - identifiers: [], - passwordHash: - 'b8be6cae5215c93784b1b9e2c06384910f754b1d66c077f1f8fdc98fbd92e6c17a0fdc790b30225986cadb9553e87a47b1d2eb7bd986f96f0da7873e1b2ddf9c', - salt: '12345', - scope: ['register'], - role: { - label: { - id: 'userRole.fieldAgent', - defaultMessage: 'Field Agent', - description: 'Name for user role Field Agent', - __typename: 'I18nMessage' - }, - __typename: 'UserRole' - }, - status: 'active', - avatar: { - type: 'image/jpg', - data: 'data:image/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAACCAYAAABllJ3tAAAABHNCSVQICAgIfAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAAXSURBVAiZY1RWVv7PgAcw4ZNkYGBgAABYyAFsic1CfAAAAABJRU5ErkJggg==' - }, - practitionerId: 'dcba7022-f0ff-4822-b5d9-cb90d0e7b8de', - primaryOfficeId: '79776844-b606-40e9-8358-7d82147f702a', - securityQuestionAnswers: [ - { - questionKey: 'BIRTH_TOWN', - answerHash: '$2a$10$uHhZhgHqgOdt7CZdkKCysO/sVyYHwbEhB5q5TPE.fN9O1kiz0OxVG' - }, - { - questionKey: 'MOTHER_NICK_NAME', - answerHash: '$2a$10$uHhZhgHqgOdt7CZdkKCysO/sVyYHwbEhB5q5TPE.fN9O1kiz0OxVG' - }, - { - questionKey: 'FAVORITE_MOVIE', - answerHash: '$2a$10$uHhZhgHqgOdt7CZdkKCysO/sVyYHwbEhB5q5TPE.fN9O1kiz0OxVG' - } - ], - creationDate: 1559054406433, - auditHistory: [] -} - export const mockUserModelResponse = { - scope: ['register', 'performance', 'certify', 'demo'], + scope: ['record.register', 'performance.read', 'record.certify', 'demo'], status: 'active', _id: '5ddfdfec61f7c0d1aafe1961', name: [ diff --git a/packages/user-mgnt/src/config/routes.ts b/packages/user-mgnt/src/config/routes.ts index 654f1d6a4ea..a4756f2bc67 100644 --- a/packages/user-mgnt/src/config/routes.ts +++ b/packages/user-mgnt/src/config/routes.ts @@ -97,18 +97,6 @@ import changeEmailHandler, { import { getAllSystemsHandler } from '@user-mgnt/features/getAllSystems/handler' import * as mongoose from 'mongoose' -const enum RouteScope { - DECLARE = 'declare', - REGISTER = 'register', - CERTIFY = 'certify', - PERFORMANCE = 'performance', - SYSADMIN = 'sysadmin', - NATLSYSADMIN = 'natlsysadmin', - VALIDATE = 'validate', - RECORDSEARCH = 'recordsearch', - VERIFY = 'verify' -} - export const getRoutes = () => { return [ // add ping route by default for health check @@ -215,12 +203,14 @@ export const getRoutes = () => { description: 'Changes password for logged-in user', auth: { scope: [ - RouteScope.DECLARE, - RouteScope.REGISTER, - RouteScope.CERTIFY, - RouteScope.PERFORMANCE, - RouteScope.SYSADMIN, - RouteScope.VALIDATE + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.certify', + 'performance.read', + 'config.update-all', + 'record.submit-for-approval' ] }, validate: { @@ -240,12 +230,14 @@ export const getRoutes = () => { description: 'Changes password for logged-in user', auth: { scope: [ - RouteScope.DECLARE, - RouteScope.REGISTER, - RouteScope.CERTIFY, - RouteScope.PERFORMANCE, - RouteScope.SYSADMIN, - RouteScope.VALIDATE + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.certify', + 'performance.read', + 'config.update-all', + 'record.submit-for-approval' ] }, validate: { @@ -265,12 +257,14 @@ export const getRoutes = () => { description: 'Changes email for logged-in user', auth: { scope: [ - RouteScope.DECLARE, - RouteScope.REGISTER, - RouteScope.CERTIFY, - RouteScope.PERFORMANCE, - RouteScope.SYSADMIN, - RouteScope.VALIDATE + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.certify', + 'performance.read', + 'config.update-all', + 'record.submit-for-approval' ] }, validate: { @@ -290,12 +284,14 @@ export const getRoutes = () => { description: 'Changes avatar for logged-in user', auth: { scope: [ - RouteScope.DECLARE, - RouteScope.REGISTER, - RouteScope.CERTIFY, - RouteScope.PERFORMANCE, - RouteScope.SYSADMIN, - RouteScope.VALIDATE + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.certify', + 'performance.read', + 'config.update-all', + 'record.submit-for-approval' ] }, validate: { @@ -315,12 +311,14 @@ export const getRoutes = () => { description: 'Retrieves a user mobile number', auth: { scope: [ - RouteScope.DECLARE, - RouteScope.REGISTER, - RouteScope.CERTIFY, - RouteScope.PERFORMANCE, - RouteScope.SYSADMIN, - RouteScope.VALIDATE + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.certify', + 'performance.read', + 'config.update-all', + 'record.submit-for-approval' ] }, validate: { @@ -338,12 +336,14 @@ export const getRoutes = () => { options: { auth: { scope: [ - RouteScope.DECLARE, - RouteScope.REGISTER, - RouteScope.CERTIFY, - RouteScope.PERFORMANCE, - RouteScope.SYSADMIN, - RouteScope.VALIDATE + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.certify', + 'performance.read', + 'config.update-all', + 'record.submit-for-approval' ] }, validate: { @@ -361,14 +361,16 @@ export const getRoutes = () => { description: 'Retrieves a user', auth: { scope: [ - RouteScope.DECLARE, - RouteScope.REGISTER, - RouteScope.CERTIFY, - RouteScope.PERFORMANCE, - RouteScope.SYSADMIN, - RouteScope.VALIDATE, - RouteScope.VERIFY, - RouteScope.RECORDSEARCH + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.certify', + 'performance.read', + 'config.update-all', + 'record.submit-for-approval', + 'record.registration-verify-certified-copies', + 'recordsearch' ] }, validate: { @@ -384,7 +386,7 @@ export const getRoutes = () => { tags: ['api'], description: 'Creates a new user', auth: { - scope: [RouteScope.SYSADMIN] + scope: ['config.update-all'] } } }, @@ -396,7 +398,7 @@ export const getRoutes = () => { tags: ['api'], description: 'Updates an existing user', auth: { - scope: [RouteScope.SYSADMIN] + scope: ['config.update-all'] } } }, @@ -409,12 +411,14 @@ export const getRoutes = () => { description: 'Activate an existing pending user', auth: { scope: [ - RouteScope.DECLARE, - RouteScope.REGISTER, - RouteScope.CERTIFY, - RouteScope.PERFORMANCE, - RouteScope.SYSADMIN, - RouteScope.VALIDATE + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.certify', + 'performance.read', + 'config.update-all', + 'record.submit-for-approval' ] }, validate: { @@ -447,7 +451,7 @@ export const getRoutes = () => { handler: userAuditHandler, options: { auth: { - scope: [RouteScope.SYSADMIN] + scope: ['config.update-all'] }, validate: { payload: userAuditSchema @@ -462,12 +466,14 @@ export const getRoutes = () => { options: { auth: { scope: [ - RouteScope.DECLARE, - RouteScope.REGISTER, - RouteScope.CERTIFY, - RouteScope.PERFORMANCE, - RouteScope.SYSADMIN, - RouteScope.VALIDATE + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.certify', + 'performance.read', + 'config.update-all', + 'record.submit-for-approval' ] }, validate: { @@ -483,12 +489,14 @@ export const getRoutes = () => { options: { auth: { scope: [ - RouteScope.DECLARE, - RouteScope.REGISTER, - RouteScope.CERTIFY, - RouteScope.PERFORMANCE, - RouteScope.SYSADMIN, - RouteScope.VALIDATE + 'record.declare-birth', + 'record.declare-death', + 'record.declare-marriage', + 'record.register', + 'record.certify', + 'performance.read', + 'config.update-all', + 'record.submit-for-approval' ] }, validate: { @@ -503,7 +511,7 @@ export const getRoutes = () => { handler: resendInviteHandler, options: { auth: { - scope: [RouteScope.SYSADMIN] + scope: ['config.update-all'] }, validate: { payload: resendInviteRequestSchema @@ -518,7 +526,7 @@ export const getRoutes = () => { handler: usernameReminderHandler, options: { auth: { - scope: [RouteScope.SYSADMIN] + scope: ['config.update-all'] }, validate: { payload: usernameReminderRequestSchema @@ -533,7 +541,7 @@ export const getRoutes = () => { handler: resetPasswordInviteHandler, options: { auth: { - scope: [RouteScope.SYSADMIN] + scope: ['config.update-all'] }, validate: { payload: resetPasswordRequestSchema @@ -550,7 +558,7 @@ export const getRoutes = () => { tags: ['api'], description: 'Creates a new system client', auth: { - scope: [RouteScope.NATLSYSADMIN] + scope: ['config.update-all'] }, validate: { payload: reqRegisterSystemSchema @@ -568,7 +576,7 @@ export const getRoutes = () => { tags: ['api'], description: 'Update system permissions', auth: { - scope: [RouteScope.SYSADMIN] + scope: ['config.update-all'] }, validate: { payload: reqUpdateSystemSchema @@ -583,7 +591,7 @@ export const getRoutes = () => { tags: ['api'], description: 'Deactivates a new system client', auth: { - scope: [RouteScope.NATLSYSADMIN] + scope: ['config.update-all'] }, validate: { payload: clientIdSchema @@ -601,7 +609,7 @@ export const getRoutes = () => { tags: ['api'], description: 'Reactivates a new system client', auth: { - scope: [RouteScope.NATLSYSADMIN] + scope: ['config.update-all'] }, validate: { payload: clientIdSchema @@ -664,11 +672,11 @@ export const getRoutes = () => { description: 'Gets count of users group by office ids', auth: { scope: [ - RouteScope.REGISTER, - RouteScope.CERTIFY, - RouteScope.PERFORMANCE, - RouteScope.SYSADMIN, - RouteScope.VALIDATE + 'record.register', + 'record.certify', + 'performance.read', + 'config.update-all', + 'record.submit-for-approval' ] }, validate: { @@ -687,7 +695,7 @@ export const getRoutes = () => { description: 'Refresh client secret ', notes: 'Refresh client secret', auth: { - scope: [RouteScope.NATLSYSADMIN] + scope: ['config.update-all'] }, validate: { payload: systemSecretRequestSchema @@ -706,7 +714,7 @@ export const getRoutes = () => { description: 'Delete system ', notes: 'This is responsible for system deletion', auth: { - scope: [RouteScope.NATLSYSADMIN] + scope: ['config.update-all'] }, validate: { payload: clientIdSchema diff --git a/packages/workflow/test/mocks/user.ts b/packages/workflow/test/mocks/user.ts index 9713711fb7c..29640eccd58 100644 --- a/packages/workflow/test/mocks/user.ts +++ b/packages/workflow/test/mocks/user.ts @@ -72,7 +72,7 @@ export const registrar = { role: '66619330a6a4a835aa689ddb', practitionerId: '648c914d-de38-4c24-bdc9-ce8ee8cacd4c', primaryOfficeId: '435e5301-063d-4f22-958e-24176cfb4e54', - scope: ['register', 'performance', 'certify', 'demo'], + scope: ['record.register', 'performance.read', 'record.certify', 'demo'], status: 'active', securityQuestionAnswers: [], creationDate: 1717670705858,