Skip to content

Commit

Permalink
🚚 api: move generate-results-download-link to results certification c…
Browse files Browse the repository at this point in the history
…ontext

Co-authored-by: Steph0 <[email protected]>
Co-authored-by: GUL <[email protected]>
Co-authored-by: Alexandre Coin <[email protected]>
  • Loading branch information
4 people committed Dec 4, 2024
1 parent 1cd5be7 commit 771a05b
Show file tree
Hide file tree
Showing 18 changed files with 193 additions and 171 deletions.
31 changes: 0 additions & 31 deletions api/lib/application/sessions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,37 +37,6 @@ const register = async function (server) {
],
},
},
{
method: 'GET',
path: '/api/admin/sessions/{id}/generate-results-download-link',
config: {
validate: {
params: Joi.object({
id: identifiersType.sessionId,
}),
query: Joi.object({
lang: Joi.string().optional().valid('fr', 'en'),
}),
},
pre: [
{
method: (request, h) =>
securityPreHandlers.hasAtLeastOneAccessOf([
securityPreHandlers.checkAdminMemberHasRoleSuperAdmin,
securityPreHandlers.checkAdminMemberHasRoleCertif,
securityPreHandlers.checkAdminMemberHasRoleSupport,
])(request, h),
assign: 'hasAuthorizationToAccessAdminScope',
},
],
handler: sessionController.generateSessionResultsDownloadLink,
tags: ['api', 'sessions'],
notes: [
"Cette route est restreinte aux utilisateurs ayant les droits d'accès",
"Elle permet de générer un lien permettant de télécharger tous les résultats de certification d'une session",
],
},
},
{
method: 'PATCH',
path: '/api/admin/sessions/{id}/publish',
Expand Down
10 changes: 0 additions & 10 deletions api/lib/application/sessions/session-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import * as juryCertificationSummaryRepository from '../../../src/certification/
import * as sessionManagementSerializer from '../../../src/certification/session-management/infrastructure/serializers/session-serializer.js';
import { SessionPublicationBatchError } from '../../../src/shared/application/http-errors.js';
import { logger } from '../../../src/shared/infrastructure/utils/logger.js';
import * as sessionResultsLinkService from '../../domain/services/session-results-link-service.js';
import { usecases } from '../../domain/usecases/index.js';
import * as juryCertificationSummarySerializer from '../../infrastructure/serializers/jsonapi/jury-certification-summary-serializer.js';

Expand All @@ -25,14 +24,6 @@ const getJuryCertificationSummaries = async function (
return dependencies.juryCertificationSummarySerializer.serialize(juryCertificationSummaries, pagination);
};

const generateSessionResultsDownloadLink = async function (request, h, dependencies = { sessionResultsLinkService }) {
const sessionId = request.params.id;
const i18n = request.i18n;
const sessionResultsLink = dependencies.sessionResultsLinkService.generateResultsLink({ sessionId, i18n });

return h.response({ sessionResultsLink });
};

const publish = async function (request, h, dependencies = { sessionManagementSerializer }) {
const sessionId = request.params.id;
const i18n = request.i18n;
Expand Down Expand Up @@ -74,7 +65,6 @@ const flagResultsAsSentToPrescriber = async function (request, h, dependencies =

const sessionController = {
getJuryCertificationSummaries,
generateSessionResultsDownloadLink,
publish,
publishInBatch,
unpublish,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import dayjs from 'dayjs';

import { tokenService } from '../../../shared/domain/services/token-service.js';
import * as sessionResultsLinkService from '../domain/services/session-results-link-service.js';
import { usecases } from '../domain/usecases/index.js';
import * as certifiedProfileRepository from '../infrastructure/repositories/certified-profile-repository.js';
import * as certifiedProfileSerializer from '../infrastructure/serializers/certified-profile-serializer.js';
Expand Down Expand Up @@ -102,12 +103,21 @@ const getCertifiedProfile = async function (
return dependencies.certifiedProfileSerializer.serialize(certifiedProfile);
};

const generateSessionResultsDownloadLink = async function (request, h, dependencies = { sessionResultsLinkService }) {
const sessionId = request.params.sessionId;
const i18n = request.i18n;
const sessionResultsLink = dependencies.sessionResultsLinkService.generateResultsLink({ sessionId, i18n });

return h.response({ sessionResultsLink });
};

const certificationResultsController = {
getCleaCertifiedCandidateDataCsv,
getSessionResultsByRecipientEmail,
getSessionResultsToDownload,
postSessionResultsToDownload,
getCertifiedProfile,
generateSessionResultsDownloadLink,
};

export { certificationResultsController };
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,37 @@ const register = async function (server) {
],
},
},
{
method: 'GET',
path: '/api/admin/sessions/{sessionId}/generate-results-download-link',
config: {
validate: {
params: Joi.object({
sessionId: identifiersType.sessionId,
}),
query: Joi.object({
lang: Joi.string().optional().valid(LOCALE.FRENCH_SPOKEN, LOCALE.ENGLISH_SPOKEN),
}),
},
pre: [
{
method: (request, h) =>
securityPreHandlers.hasAtLeastOneAccessOf([
securityPreHandlers.checkAdminMemberHasRoleSuperAdmin,
securityPreHandlers.checkAdminMemberHasRoleCertif,
securityPreHandlers.checkAdminMemberHasRoleSupport,
])(request, h),
assign: 'hasAuthorizationToAccessAdminScope',
},
],
handler: certificationResultsController.generateSessionResultsDownloadLink,
tags: ['api', 'sessions', 'results'],
notes: [
"Cette route est restreinte aux utilisateurs ayant les droits d'accès",
"Elle permet de générer un lien permettant de télécharger tous les résultats de certification d'une session",
],
},
},
]);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { config } from '../../../src/shared/config.js';
import { tokenService } from '../../../src/shared/domain/services/token-service.js';
import { config } from '../../../../shared/config.js';
import { tokenService } from '../../../../shared/domain/services/token-service.js';

const generateResultsLink = function ({ sessionId, i18n }) {
const daysBeforeExpiration = 30;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
databaseBuilder,
expect,
generateValidRequestAuthorizationHeader,
insertUserWithRoleSuperAdmin,
} from '../../../../test-helper.js';

describe('Certification | Results | Acceptance | Application | Routes | certification results', function () {
Expand Down Expand Up @@ -267,4 +268,71 @@ describe('Certification | Results | Acceptance | Application | Routes | certific
});
});
});

describe('GET /api/admin/sessions/{sessionId}/generate-results-download-link', function () {
context('when user is Super Admin', function () {
it('should return a 200 status code response', async function () {
// given
const sessionId = 121;
const options = {
method: 'GET',
url: `/api/admin/sessions/${sessionId}/generate-results-download-link`,
payload: {},
};
const server = await createServer();
await insertUserWithRoleSuperAdmin();
databaseBuilder.factory.buildSession({ id: 121 });
await databaseBuilder.commit();

// when
options.headers = { authorization: generateValidRequestAuthorizationHeader() };
const response = await server.inject(options);

// then
expect(response.statusCode).to.equal(200);
});
});

context('when user is not SuperAdmin', function () {
it('should return 403 HTTP status code', async function () {
// given
const sessionId = 121;
const options = {
method: 'GET',
url: `/api/admin/sessions/${sessionId}/generate-results-download-link`,
payload: {},
};
const server = await createServer();
await insertUserWithRoleSuperAdmin();

// when
options.headers = { authorization: generateValidRequestAuthorizationHeader(1111) };
const response = await server.inject(options);

// then
expect(response.statusCode).to.equal(403);
});
});

context('when user is not connected', function () {
it('should return 401 HTTP status code if user is not authenticated', async function () {
// given
const sessionId = 121;
const options = {
method: 'GET',
url: `/api/admin/sessions/${sessionId}/generate-results-download-link`,
payload: {},
};
const server = await createServer();
await insertUserWithRoleSuperAdmin();

// when
options.headers = {};
const response = await server.inject(options);

// then
expect(response.statusCode).to.equal(401);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,32 @@ describe('Certification | Results | Unit | Application | Certification Results R
});
});
});

describe('GET /api/admin/sessions/{sessionId}/generate-results-download-link', function () {
it('return forbidden access if user has METIER role', async function () {
// given
sinon
.stub(securityPreHandlers, 'hasAtLeastOneAccessOf')
.withArgs([
securityPreHandlers.checkAdminMemberHasRoleSuperAdmin,
securityPreHandlers.checkAdminMemberHasRoleCertif,
securityPreHandlers.checkAdminMemberHasRoleSupport,
])
.callsFake(
() => (request, h) =>
h
.response({ errors: new Error('forbidden') })
.code(403)
.takeover(),
);
const httpTestServer = new HttpTestServer();
await httpTestServer.register(moduleUnderTest);

// when
const response = await httpTestServer.request('GET', '/api/admin/sessions/1/generate-results-download-link');

// then
expect(response.statusCode).to.equal(403);
});
});
});
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as sessionResultsLinkService from '../../../../lib/domain/services/session-results-link-service.js';
import { tokenService } from '../../../../src/shared/domain/services/token-service.js';
import { getI18n } from '../../../../src/shared/infrastructure/i18n/i18n.js';
import { expect, sinon } from '../../../test-helper.js';
import * as sessionResultsLinkService from '../../../../../../src/certification/results/domain/services/session-results-link-service.js';
import { tokenService } from '../../../../../../src/shared/domain/services/token-service.js';
import { getI18n } from '../../../../../../src/shared/infrastructure/i18n/i18n.js';
import { expect, sinon } from '../../../../../test-helper.js';

describe('Unit | Domain | Service | Session Results Link Service', function () {
describe('Certification | Results | Unit | Domain | Service | Session Results Link Service', function () {
describe('#generateResultsLink', function () {
it('should return a valid download link', function () {
// given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createAccountCreationEmail } from '../../../../../src/identity-access-m
import { InvalidOrAlreadyUsedEmailError } from '../../../../../src/identity-access-management/domain/errors.js';
import { User } from '../../../../../src/identity-access-management/domain/models/User.js';
import { createUser } from '../../../../../src/identity-access-management/domain/usecases/create-user.usecase.js';
import { config } from '../../../../../src/shared/config.js';
import { DomainTransaction } from '../../../../../src/shared/domain/DomainTransaction.js';
import { EntityValidationError } from '../../../../../src/shared/domain/errors.js';
import { urlBuilder } from '../../../../../src/shared/infrastructure/utils/url-builder.js';
Expand Down Expand Up @@ -442,7 +443,7 @@ describe('Unit | Identity Access Management | Domain | UseCase | create-user', f
firstName: user.firstName,
locale: localeFromHeader,
token,
redirectionUrl: `https://app.pix.fr/campagnes/${campaignCode}`,
redirectionUrl: `${config.domain.pixApp + config.domain.tldFr}/campagnes/${campaignCode}`,
});

// when
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { validateUserAccountEmail } from '../../../../../src/identity-access-management/domain/usecases/validate-user-account-email.usecase.js';
import { config } from '../../../../../src/shared/config.js';
import { monitoringTools } from '../../../../../src/shared/infrastructure/monitoring-tools.js';
import { domainBuilder, expect, sinon } from '../../../../test-helper.js';

Expand All @@ -7,9 +8,11 @@ describe('Unit | Identity Access Management | Domain | UseCase | validate-user-a
let clock, now;

const token = '00000000-0000-0000-0000-000000000000';
const defaultRedirectionUrl = 'https://app.pix.fr/connexion';
let defaultRedirectionUrl;

beforeEach(function () {
defaultRedirectionUrl = `${config.domain.pixApp + config.domain.tldFr}/connexion`;

emailValidationDemandRepository = {
get: sinon.stub(),
remove: sinon.stub(),
Expand Down
Loading

0 comments on commit 771a05b

Please sign in to comment.