Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TECH] Migration de la route /api/admin/sessions/publish-in-batch (PIX-15768). #10842

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading