Skip to content

Commit

Permalink
refactor(api): move DELETE organization invitations admin route
Browse files Browse the repository at this point in the history
Co-authored-by: Eric Lim <eric.lim@pix.fr>
  • Loading branch information
bpetetot and er-lim committed Jul 8, 2024
1 parent c883c6e commit 8869598
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 57 deletions.
30 changes: 0 additions & 30 deletions api/lib/application/organizations/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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',
Expand Down
Original file line number Diff line number Diff line change
@@ -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.",
],
},
},
];
2 changes: 2 additions & 0 deletions api/src/team/application/routes.js
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -9,6 +10,7 @@ const register = async function (server) {
...certificationCenterInvitationAdminRoutes,
...prescriberInformationsRoute,
...organizationInvitationRoutes,
...organizationInvitationAdminRoutes,
]);
};

Expand Down
23 changes: 0 additions & 23 deletions api/tests/integration/application/organizations/index_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { OrganizationInvitation } from '../../../../src/team/domain/models/OrganizationInvitation.js';
import { OrganizationInvitation } from '../../../../../src/team/domain/models/OrganizationInvitation.js';
import {
createServer,
databaseBuilder,
expect,
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();

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
});
});
});

0 comments on commit 8869598

Please sign in to comment.