diff --git a/api/lib/application/organizations/index.js b/api/lib/application/organizations/index.js index b0a7b41e37a..9d714a6a40d 100644 --- a/api/lib/application/organizations/index.js +++ b/api/lib/application/organizations/index.js @@ -4,7 +4,6 @@ const Joi = BaseJoi.extend(JoiDate); import { securityPreHandlers } from '../../../src/shared/application/security-pre-handlers.js'; import { identifiersType } from '../../../src/shared/domain/types/identifiers-type.js'; -import { organizationInvitationController } from '../../../src/team/application/organization-invitations/organization-invitation.controller.js'; import { BadRequestError, PayloadTooLargeError, sendJsonApiError } from '../http-errors.js'; import { organizationController } from './organization-controller.js'; @@ -170,35 +169,6 @@ const register = async function (server) { ], }, }, - { - method: 'DELETE', - path: '/api/admin/organizations/{id}/invitations/{organizationInvitationId}', - config: { - pre: [ - { - method: (request, h) => - securityPreHandlers.hasAtLeastOneAccessOf([ - securityPreHandlers.checkAdminMemberHasRoleSuperAdmin, - securityPreHandlers.checkAdminMemberHasRoleSupport, - securityPreHandlers.checkAdminMemberHasRoleMetier, - ])(request, h), - assign: 'hasAuthorizationToAccessAdminScope', - }, - ], - validate: { - params: Joi.object({ - id: identifiersType.organizationId, - organizationInvitationId: identifiersType.organizationInvitationId, - }), - }, - handler: organizationInvitationController.cancelOrganizationInvitation, - tags: ['api', 'admin', 'invitations', 'cancel'], - notes: [ - "- **Cette route est restreinte aux utilisateurs authentifiés ayant les droits d'accès**\n" + - "- Elle permet d'annuler une invitation envoyée mais non acceptée encore.", - ], - }, - }, { method: 'POST', path: '/api/admin/organizations/{id}/invitations', diff --git a/api/src/team/application/organization-invitations/organization-invitation.admin.route.js b/api/src/team/application/organization-invitations/organization-invitation.admin.route.js new file mode 100644 index 00000000000..88d51345b05 --- /dev/null +++ b/api/src/team/application/organization-invitations/organization-invitation.admin.route.js @@ -0,0 +1,37 @@ +import Joi from 'joi'; + +import { securityPreHandlers } from '../../../shared/application/security-pre-handlers.js'; +import { identifiersType } from '../../../shared/domain/types/identifiers-type.js'; +import { organizationInvitationController } from './organization-invitation.controller.js'; + +export const organizationInvitationAdminRoutes = [ + { + method: 'DELETE', + path: '/api/admin/organizations/{id}/invitations/{organizationInvitationId}', + config: { + pre: [ + { + method: (request, h) => + securityPreHandlers.hasAtLeastOneAccessOf([ + securityPreHandlers.checkAdminMemberHasRoleSuperAdmin, + securityPreHandlers.checkAdminMemberHasRoleSupport, + securityPreHandlers.checkAdminMemberHasRoleMetier, + ])(request, h), + assign: 'hasAuthorizationToAccessAdminScope', + }, + ], + validate: { + params: Joi.object({ + id: identifiersType.organizationId, + organizationInvitationId: identifiersType.organizationInvitationId, + }), + }, + handler: (request, h) => organizationInvitationController.cancelOrganizationInvitation(request, h), + tags: ['team', 'api', 'admin', 'invitations', 'cancel'], + notes: [ + "- **Cette route est restreinte aux utilisateurs authentifiés ayant les droits d'accès**\n" + + "- Elle permet d'annuler une invitation envoyée mais non acceptée encore.", + ], + }, + }, +]; diff --git a/api/src/team/application/routes.js b/api/src/team/application/routes.js index a3b58001e21..a3144fb0e89 100644 --- a/api/src/team/application/routes.js +++ b/api/src/team/application/routes.js @@ -1,5 +1,6 @@ import { certificationCenterInvitationAdminRoutes } from './certification-center-invitation/certification-center-invitation.admin.route.js'; import { certificationCenterInvitationRoutes } from './certification-center-invitation/certification-center-invitation.route.js'; +import { organizationInvitationAdminRoutes } from './organization-invitations/organization-invitation.admin.route.js'; import { organizationInvitationRoutes } from './organization-invitations/organization-invitation.route.js'; import { prescriberInformationsRoute } from './prescriber-informations.route.js'; @@ -9,6 +10,7 @@ const register = async function (server) { ...certificationCenterInvitationAdminRoutes, ...prescriberInformationsRoute, ...organizationInvitationRoutes, + ...organizationInvitationAdminRoutes, ]); }; diff --git a/api/tests/integration/application/organizations/index_test.js b/api/tests/integration/application/organizations/index_test.js index 68df9f41ce4..7845dd4cb4b 100644 --- a/api/tests/integration/application/organizations/index_test.js +++ b/api/tests/integration/application/organizations/index_test.js @@ -105,29 +105,6 @@ describe('Integration | Application | Organizations | Routes', function () { }); }); - describe('DELETE /api/admin/organizations/:organizationId/invitations/:organizationInvitationId', function () { - it('should return an HTTP status code 204', async function () { - // given - const method = 'DELETE'; - const url = '/api/admin/organizations/1/invitations/1'; - - sinon.stub(securityPreHandlers, 'hasAtLeastOneAccessOf').returns(() => true); - sinon - .stub(organizationController, 'cancelOrganizationInvitation') - .returns((request, h) => h.response().code(204)); - - const httpTestServer = new HttpTestServer(); - await httpTestServer.register(moduleUnderTest); - - // when - const { statusCode } = await httpTestServer.request(method, url); - - // then - expect(statusCode).to.equal(204); - expect(organizationController.cancelOrganizationInvitation).to.have.been.calledOnce; - }); - }); - describe('POST /api/organizations/:id/invitations', function () { it('should call the organization controller to send invitations', async function () { // given diff --git a/api/tests/acceptance/application/organizations/cancel-organization-invitation-delete_test.js b/api/tests/team/acceptance/application/organization-invitations/organization-invitation.admin.route.test.js similarity index 78% rename from api/tests/acceptance/application/organizations/cancel-organization-invitation-delete_test.js rename to api/tests/team/acceptance/application/organization-invitations/organization-invitation.admin.route.test.js index c4b2124f85f..b622ca7005b 100644 --- a/api/tests/acceptance/application/organizations/cancel-organization-invitation-delete_test.js +++ b/api/tests/team/acceptance/application/organization-invitations/organization-invitation.admin.route.test.js @@ -1,4 +1,4 @@ -import { OrganizationInvitation } from '../../../../src/team/domain/models/OrganizationInvitation.js'; +import { OrganizationInvitation } from '../../../../../src/team/domain/models/OrganizationInvitation.js'; import { createServer, databaseBuilder, @@ -6,11 +6,11 @@ import { generateValidRequestAuthorizationHeader, insertOrganizationUserWithRoleAdmin, insertUserWithRoleSuperAdmin, -} from '../../../test-helper.js'; +} from '../../../../../tests/test-helper.js'; -describe('Acceptance | Route | Organizations', function () { +describe('Acceptance | Team | Route | Admin | organization-invitation', function () { describe('DELETE /api/admin/organizations/{organizationId}/invitations/{invitationId}', function () { - it('should return 204 HTTP status code', async function () { + it('returns 204 HTTP status code', async function () { // given const server = await createServer(); diff --git a/api/tests/team/integration/application/organization-invitation/organization-invitation.admin.route.test.js b/api/tests/team/integration/application/organization-invitation/organization-invitation.admin.route.test.js new file mode 100644 index 00000000000..2d7703deab0 --- /dev/null +++ b/api/tests/team/integration/application/organization-invitation/organization-invitation.admin.route.test.js @@ -0,0 +1,29 @@ +import { securityPreHandlers } from '../../../../../src/shared/application/security-pre-handlers.js'; +import { organizationInvitationController } from '../../../../../src/team/application/organization-invitations/organization-invitation.controller.js'; +import { teamRoutes } from '../../../../../src/team/application/routes.js'; +import { expect, HttpTestServer, sinon } from '../../../../test-helper.js'; + +describe('Integration | Team | Application | Route | Admin | organization-invitations', function () { + describe('DELETE /api/admin/organizations/:organizationId/invitations/:organizationInvitationId', function () { + it('returns an HTTP status code 204', async function () { + // given + const method = 'DELETE'; + const url = '/api/admin/organizations/1/invitations/1'; + + sinon.stub(securityPreHandlers, 'hasAtLeastOneAccessOf').returns(() => true); + sinon + .stub(organizationInvitationController, 'cancelOrganizationInvitation') + .returns((request, h) => h.response().code(204)); + + const httpTestServer = new HttpTestServer(); + await httpTestServer.register(teamRoutes[0]); + + // when + const { statusCode } = await httpTestServer.request(method, url); + + // then + expect(statusCode).to.equal(204); + expect(organizationInvitationController.cancelOrganizationInvitation).to.have.been.calledOnce; + }); + }); +});