Skip to content

Commit

Permalink
refactor(api): move publish in batch route to src
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandrecoin committed Dec 17, 2024
1 parent 022f259 commit f967542
Show file tree
Hide file tree
Showing 14 changed files with 288 additions and 296 deletions.
32 changes: 0 additions & 32 deletions api/lib/application/sessions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,38 +37,6 @@ const register = async function (server) {
],
},
},
{
method: 'POST',
path: '/api/admin/sessions/publish-in-batch',
config: {
validate: {
payload: Joi.object({
data: {
attributes: {
ids: Joi.array().items(identifiersType.sessionId),
},
},
}),
},
pre: [
{
method: (request, h) =>
securityPreHandlers.hasAtLeastOneAccessOf([
securityPreHandlers.checkAdminMemberHasRoleSuperAdmin,
securityPreHandlers.checkAdminMemberHasRoleCertif,
securityPreHandlers.checkAdminMemberHasRoleSupport,
])(request, h),
assign: 'hasAuthorizationToAccessAdminScope',
},
],
handler: sessionController.publishInBatch,
notes: [
"- **Cette route est restreinte aux utilisateurs authentifiés ayant les droits d'accès**\n" +
"- Permet de publier plusieurs sessions sans problème d'un coup",
],
tags: ['api', 'session', 'publication'],
},
},
]);
};

Expand Down
34 changes: 0 additions & 34 deletions api/lib/application/sessions/session-controller.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import * as juryCertificationSummaryRepository from '../../../src/certification/session-management/infrastructure/repositories/jury-certification-summary-repository.js';
import { SessionPublicationBatchError } from '../../../src/shared/application/http-errors.js';
import { logger } from '../../../src/shared/infrastructure/utils/logger.js';
import { usecases } from '../../domain/usecases/index.js';
import * as juryCertificationSummarySerializer from '../../infrastructure/serializers/jsonapi/jury-certification-summary-serializer.js';

const getJuryCertificationSummaries = async function (
Expand All @@ -23,39 +20,8 @@ const getJuryCertificationSummaries = async function (
return dependencies.juryCertificationSummarySerializer.serialize(juryCertificationSummaries, pagination);
};

const publishInBatch = async function (request, h) {
const sessionIds = request.payload.data.attributes.ids;
const i18n = request.i18n;

const result = await usecases.publishSessionsInBatch({
sessionIds,
i18n,
});
if (result.hasPublicationErrors()) {
_logSessionBatchPublicationErrors(result);
throw new SessionPublicationBatchError(result.batchId);
}
return h.response().code(204);
};

const sessionController = {
getJuryCertificationSummaries,
publishInBatch,
};

export { sessionController };

function _logSessionBatchPublicationErrors(result) {
logger.warn(`One or more error occurred when publishing session in batch ${result.batchId}`);

const sessionAndError = result.publicationErrors;
for (const sessionId in sessionAndError) {
logger.warn(
{
batchId: result.batchId,
sessionId,
},
sessionAndError[sessionId].message,
);
}
}
3 changes: 0 additions & 3 deletions api/lib/domain/usecases/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import * as certificationEvaluationCandidateRepository from '../../../src/certif
import * as flashAlgorithmService from '../../../src/certification/flash-certification/domain/services/algorithm-methods/flash.js';
import * as sessionPublicationService from '../../../src/certification/session-management/domain/services/session-publication-service.js';
import * as certificationOfficerRepository from '../../../src/certification/session-management/infrastructure/repositories/certification-officer-repository.js';
import * as sessionManagementCertificationRepository from '../../../src/certification/session-management/infrastructure/repositories/certification-repository.js';
import * as finalizedSessionRepository from '../../../src/certification/session-management/infrastructure/repositories/finalized-session-repository.js';
import * as juryCertificationRepository from '../../../src/certification/session-management/infrastructure/repositories/jury-certification-repository.js';
import * as juryCertificationSummaryRepository from '../../../src/certification/session-management/infrastructure/repositories/jury-certification-summary-repository.js';
Expand Down Expand Up @@ -188,7 +187,6 @@ function requirePoleEmploiNotifier() {
* @typedef {certificationChallengesService} CertificationChallengesService
* @typedef {verifyCertificateCodeService} VerifyCertificateCodeService
* @typedef {assessmentRepository} AssessmentRepository
* @typedef {sessionManagementCertificationRepository} SessionManagementCertificationRepository
*/
const dependencies = {
accountRecoveryDemandRepository,
Expand Down Expand Up @@ -298,7 +296,6 @@ const dependencies = {
scoringCertificationService,
sessionCodeService,
sessionEnrolmentRepository,
sessionManagementCertificationRepository,
sessionPublicationService,
sessionRepository,
sessionSummaryRepository,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { SessionPublicationBatchError } from '../../../shared/application/http-errors.js';
import { logger } from '../../../shared/infrastructure/utils/logger.js';
import { usecases } from '../domain/usecases/index.js';
import * as sessionManagementSerializer from '../infrastructure/serializers/session-serializer.js';

Expand All @@ -18,7 +20,38 @@ const unpublish = async function (request, h, dependencies = { sessionManagement
return dependencies.sessionManagementSerializer.serialize({ session });
};

const publishInBatch = async function (request, h) {
const sessionIds = request.payload.data.attributes.ids;
const i18n = request.i18n;

const result = await usecases.publishSessionsInBatch({
sessionIds,
i18n,
});
if (result.hasPublicationErrors()) {
_logSessionBatchPublicationErrors(result);
throw new SessionPublicationBatchError(result.batchId);
}
return h.response().code(204);
};

export const sessionPublicationController = {
publish,
unpublish,
publishInBatch,
};

function _logSessionBatchPublicationErrors(result) {
logger.warn(`One or more error occurred when publishing session in batch ${result.batchId}`);

const sessionAndError = result.publicationErrors;
for (const sessionId in sessionAndError) {
logger.warn(
{
batchId: result.batchId,
sessionId,
},
sessionAndError[sessionId].message,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,38 @@ const register = async function (server) {
tags: ['api', 'session', 'publication'],
},
},
{
method: 'POST',
path: '/api/admin/sessions/publish-in-batch',
config: {
validate: {
payload: Joi.object({
data: {
attributes: {
ids: Joi.array().items(identifiersType.sessionId),
},
},
}),
},
pre: [
{
method: (request, h) =>
securityPreHandlers.hasAtLeastOneAccessOf([
securityPreHandlers.checkAdminMemberHasRoleSuperAdmin,
securityPreHandlers.checkAdminMemberHasRoleCertif,
securityPreHandlers.checkAdminMemberHasRoleSupport,
])(request, h),
assign: 'hasAuthorizationToAccessAdminScope',
},
],
handler: sessionPublicationController.publishInBatch,
notes: [
"- **Cette route est restreinte aux utilisateurs authentifiés ayant les droits d'accès**\n" +
"- Permet de publier plusieurs sessions sans problème d'un coup",
],
tags: ['api', 'session', 'publication'],
},
},
]);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { randomUUID } from 'node:crypto';

import { SessionPublicationBatchResult } from '../../../src/shared/domain/models/index.js';
import { SessionPublicationBatchResult } from '../models/SessionPublicationBatchResult.js';

const publishSessionsInBatch = async function ({
i18n,
sessionIds,
publishedAt = new Date(),
batchId = randomUUID(),
certificationCenterRepository,
sessionManagementCertificationRepository,
certificationRepository,
finalizedSessionRepository,
sessionRepository,
sharedSessionRepository,
Expand All @@ -20,7 +20,7 @@ const publishSessionsInBatch = async function ({
const session = await sessionPublicationService.publishSession({
sessionId,
publishedAt,
certificationRepository: sessionManagementCertificationRepository,
certificationRepository,
finalizedSessionRepository,
sharedSessionRepository,
sessionRepository,
Expand Down
2 changes: 0 additions & 2 deletions api/src/shared/domain/models/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ import { ScoringSimulation } from './ScoringSimulation.js';
import { ScoringSimulationContext } from './ScoringSimulationContext.js';
import { ScoringSimulationDataset } from './ScoringSimulationDataset.js';
import { ScoringSimulationResult } from './ScoringSimulationResult.js';
import { SessionPublicationBatchResult } from './SessionPublicationBatchResult.js';
import { Skill } from './Skill.js';
import { Solution } from './Solution.js';
import { Student } from './Student.js';
Expand Down Expand Up @@ -199,7 +198,6 @@ export {
ScoringSimulationContext,
ScoringSimulationDataset,
ScoringSimulationResult,
SessionPublicationBatchResult,
ShareableCertificate,
Skill,
Solution,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
databaseBuilder,
expect,
generateValidRequestAuthorizationHeader,
} from '../../../test-helper.js';
} from '../../../../test-helper.js';

describe('POST /api/admin/sessions/publish-in-batch', function () {
let server;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { sessionPublicationController } from '../../../../../src/certification/session-management/application/session-publication-controller.js';
import { SessionPublicationBatchResult } from '../../../../../src/certification/session-management/domain/models/SessionPublicationBatchResult.js';
import { usecases } from '../../../../../src/certification/session-management/domain/usecases/index.js';
import { SessionPublicationBatchError } from '../../../../../src/shared/application/http-errors.js';
import { getI18n } from '../../../../../src/shared/infrastructure/i18n/i18n.js';
import { expect, hFake, sinon } from '../../../../test-helper.js';
import { logger } from '../../../../../src/shared/infrastructure/utils/logger.js';
import { catchErr, expect, hFake, sinon } from '../../../../test-helper.js';

describe('Certification | Session-management | Unit | Application | Controller | Session Publication', function () {
describe('#publish', function () {
Expand Down Expand Up @@ -75,4 +78,106 @@ describe('Certification | Session-management | Unit | Application | Controller |
expect(response).to.equal(serializedSession);
});
});

describe('#publishInBatch', function () {
it('returns 204 when no error occurred', async function () {
// given
const i18n = getI18n();

const request = {
i18n,
payload: {
data: {
attributes: {
ids: ['sessionId1', 'sessionId2'],
},
},
},
};
sinon
.stub(usecases, 'publishSessionsInBatch')
.withArgs({
sessionIds: ['sessionId1', 'sessionId2'],
i18n,
})
.resolves(new SessionPublicationBatchResult('batchId'));

// when
const response = await sessionPublicationController.publishInBatch(request, hFake);

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

it('logs errors when errors occur', async function () {
// given
const i18n = getI18n();
const result = new SessionPublicationBatchResult('batchId');
result.addPublicationError('sessionId1', new Error('an error'));
result.addPublicationError('sessionId2', new Error('another error'));

const request = {
i18n,
payload: {
data: {
attributes: {
ids: ['sessionId1', 'sessionId2'],
},
},
},
};
sinon.stub(usecases, 'publishSessionsInBatch').resolves(result);
sinon.stub(logger, 'warn');

// when
await catchErr(sessionPublicationController.publishInBatch)(request, hFake);

// then
expect(logger.warn).to.have.been.calledWithExactly(
'One or more error occurred when publishing session in batch batchId',
);

expect(logger.warn).to.have.been.calledWithExactly(
{
batchId: 'batchId',
sessionId: 'sessionId1',
},
'an error',
);

expect(logger.warn).to.have.been.calledWithExactly(
{
batchId: 'batchId',
sessionId: 'sessionId2',
},
'another error',
);
});

it('returns the serialized batch id', async function () {
// given
const i18n = getI18n();
const result = new SessionPublicationBatchResult('batchId');
result.addPublicationError('sessionId1', new Error('an error'));

const request = {
i18n,
payload: {
data: {
attributes: {
ids: ['sessionId1', 'sessionId2'],
},
},
},
};
sinon.stub(usecases, 'publishSessionsInBatch').resolves(result);
sinon.stub(logger, 'warn');

// when
const error = await catchErr(sessionPublicationController.publishInBatch)(request, hFake);

// then
expect(error).to.be.an.instanceof(SessionPublicationBatchError);
});
});
});
Loading

0 comments on commit f967542

Please sign in to comment.