Skip to content

Commit

Permalink
[TECH] Migrer la route `GET /api/users/{userId}/campaigns/{campaignId…
Browse files Browse the repository at this point in the history
…}/campaign-participations` vers son BC (PIX-15278)

 #10532
  • Loading branch information
pix-service-auto-merge authored Nov 15, 2024
2 parents 9600a14 + 5677282 commit 04f8fd6
Show file tree
Hide file tree
Showing 14 changed files with 161 additions and 262 deletions.
25 changes: 0 additions & 25 deletions api/lib/application/users/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,31 +192,6 @@ const register = async function (server) {
tags: ['api'],
},
},
{
method: 'GET',
path: '/api/users/{userId}/campaigns/{campaignId}/campaign-participations',
config: {
validate: {
params: Joi.object({
userId: identifiersType.userId,
campaignId: identifiersType.campaignId,
}),
},
pre: [
{
method: securityPreHandlers.checkRequestedUserIsAuthenticatedUser,
assign: 'requestedUserIsAuthenticatedUser',
},
],
handler: userController.getUserCampaignParticipationToCampaign,
notes: [
'- **Cette route est restreinte aux utilisateurs authentifiés**\n' +
'- Récupération de la dernière participation d’un utilisateur (**userId**) à une campagne donnée (**campaignId**)\n' +
'- L’id demandé doit correspondre à celui de l’utilisateur authentifié',
],
tags: ['api', 'user', 'campaign', 'campaign-participations'],
},
},
{
method: 'GET',
path: '/api/users/{id}/trainings',
Expand Down
14 changes: 0 additions & 14 deletions api/lib/application/users/user-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,6 @@ const resetScorecard = function (request, h, dependencies = { scorecardSerialize
.then(dependencies.scorecardSerializer.serialize);
};

const getUserCampaignParticipationToCampaign = function (
request,
h,
dependencies = { campaignParticipationSerializer },
) {
const authenticatedUserId = request.auth.credentials.userId;
const campaignId = request.params.campaignId;

return usecases
.getUserCampaignParticipationToCampaign({ userId: authenticatedUserId, campaignId })
.then((campaignParticipation) => dependencies.campaignParticipationSerializer.serialize(campaignParticipation));
};

const removeAuthenticationMethod = async function (request, h) {
const userId = request.params.id;
const authenticationMethodType = request.payload.data.attributes.type;
Expand Down Expand Up @@ -146,7 +133,6 @@ const userController = {
findPaginatedUserRecommendedTrainings,
findUserOrganizationsForAdmin,
getCampaignParticipations,
getUserCampaignParticipationToCampaign,
reassignAuthenticationMethods,
rememberUserHasSeenAssessmentInstructions,
rememberUserHasSeenChallengeTooltip,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,6 @@ const findLatestOngoingByUserId = async function (userId) {
});
};

const findOneByCampaignIdAndUserId = async function ({ campaignId, userId }) {
const campaignParticipation = await knex('campaign-participations')
.where({ userId, isImproved: false, campaignId })
.first();
if (!campaignParticipation) return null;
const assessments = await knex('assessments').where({ campaignParticipationId: campaignParticipation.id });
return new CampaignParticipation({
...campaignParticipation,
assessments: assessments.map((assessment) => new Assessment(assessment)),
});
};

const isRetrying = async function ({ campaignParticipationId }) {
const { id: campaignId, userId } = await knex('campaigns')
.select('campaigns.id', 'userId')
Expand All @@ -105,7 +93,6 @@ const isRetrying = async function ({ campaignParticipationId }) {

export {
findLatestOngoingByUserId,
findOneByCampaignIdAndUserId,
get,
getCodeOfLastParticipationToProfilesCollectionCampaignForUser,
hasAssessmentParticipations,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,24 @@ import * as campaignAnalysisSerializer from '../infrastructure/serializers/jsona
import * as campaignAssessmentParticipationResultSerializer from '../infrastructure/serializers/jsonapi/campaign-assessment-participation-result-serializer.js';
import * as campaignAssessmentParticipationSerializer from '../infrastructure/serializers/jsonapi/campaign-assessment-participation-serializer.js';
import * as campaignParticipationOverviewSerializer from '../infrastructure/serializers/jsonapi/campaign-participation-overview-serializer.js';
import * as campaignParticipationSerializer from '../infrastructure/serializers/jsonapi/campaign-participation-serializer.js';
import * as campaignProfileSerializer from '../infrastructure/serializers/jsonapi/campaign-profile-serializer.js';
import * as participantResultSerializer from '../infrastructure/serializers/jsonapi/participant-result-serializer.js';
import * as participationForCampaignManagementSerializer from '../infrastructure/serializers/jsonapi/participation-for-campaign-management-serializer.js';

const getUserCampaignParticipationToCampaign = function (
request,
h,
dependencies = { campaignParticipationSerializer },
) {
const authenticatedUserId = request.auth.credentials.userId;
const campaignId = request.params.campaignId;

return usecases
.getUserCampaignParticipationToCampaign({ userId: authenticatedUserId, campaignId })
.then((campaignParticipation) => dependencies.campaignParticipationSerializer.serialize(campaignParticipation));
};

const findPaginatedParticipationsForCampaignManagement = async function (request) {
const { campaignId } = request.params;
const { page } = request.query;
Expand Down Expand Up @@ -161,17 +175,18 @@ const getUserCampaignAssessmentResult = async function (
};

const campaignParticipationController = {
deleteCampaignParticipationForAdmin,
deleteParticipation,
findPaginatedParticipationsForCampaignManagement,
getUserCampaignAssessmentResult,
getAnalysis,
getCampaignProfile,
getCampaignAssessmentParticipation,
getCampaignParticipationsForOrganizationLearner,
deleteParticipation,
getCampaignAssessmentParticipationResult,
updateParticipantExternalId,
deleteCampaignParticipationForAdmin,
getCampaignParticipationOverviews,
getCampaignParticipationsForOrganizationLearner,
getCampaignProfile,
getUserCampaignAssessmentResult,
getUserCampaignParticipationToCampaign,
updateParticipantExternalId,
};

export { campaignParticipationController };
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,31 @@ const register = async function (server) {
tags: ['api'],
},
},
{
method: 'GET',
path: '/api/users/{userId}/campaigns/{campaignId}/campaign-participations',
config: {
validate: {
params: Joi.object({
userId: identifiersType.userId,
campaignId: identifiersType.campaignId,
}),
},
pre: [
{
method: securityPreHandlers.checkRequestedUserIsAuthenticatedUser,
assign: 'requestedUserIsAuthenticatedUser',
},
],
handler: campaignParticipationController.getUserCampaignParticipationToCampaign,
notes: [
'- **Cette route est restreinte aux utilisateurs authentifiés**\n' +
'- Récupération de la dernière participation d’un utilisateur (**userId**) à une campagne donnée (**campaignId**)\n' +
'- L’id demandé doit correspondre à celui de l’utilisateur authentifié',
],
tags: ['api', 'user', 'campaign', 'campaign-participations'],
},
},
]);
};

Expand Down

This file was deleted.

50 changes: 1 addition & 49 deletions api/tests/integration/application/users/user-controller_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,16 @@ import * as moduleUnderTest from '../../../../lib/application/users/index.js';
import { usecases } from '../../../../lib/domain/usecases/index.js';
import { securityPreHandlers } from '../../../../src/shared/application/security-pre-handlers.js';
import { UserNotAuthorizedToRemoveAuthenticationMethod } from '../../../../src/shared/domain/errors.js';
import { domainBuilder, expect, HttpTestServer, sinon } from '../../../test-helper.js';
import { expect, HttpTestServer, sinon } from '../../../test-helper.js';

describe('Integration | Application | Users | user-controller', function () {
let sandbox;
let httpTestServer;

beforeEach(async function () {
sandbox = sinon.createSandbox();
sandbox.stub(securityPreHandlers, 'checkRequestedUserIsAuthenticatedUser');
sandbox.stub(securityPreHandlers, 'hasAtLeastOneAccessOf');

sandbox.stub(usecases, 'getUserCampaignParticipationToCampaign');
sandbox.stub(usecases, 'removeAuthenticationMethod');

httpTestServer = new HttpTestServer();
Expand All @@ -24,52 +22,6 @@ describe('Integration | Application | Users | user-controller', function () {
sandbox.restore();
});

describe('#getUserCampaignParticipationToCampaign', function () {
const auth = { credentials: {}, strategy: {} };

context('Success cases', function () {
let campaignParticipation;

beforeEach(function () {
campaignParticipation = domainBuilder.buildCampaignParticipation();
securityPreHandlers.checkRequestedUserIsAuthenticatedUser.returns(true);
auth.credentials.userId = '1234';
});

it('should return an HTTP response with status code 200', async function () {
// given
usecases.getUserCampaignParticipationToCampaign.resolves(campaignParticipation);

// when
const response = await httpTestServer.request(
'GET',
'/api/users/1234/campaigns/5678/campaign-participations',
null,
auth,
);

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

context('Error cases', function () {
beforeEach(function () {
securityPreHandlers.checkRequestedUserIsAuthenticatedUser.callsFake((request, h) => {
return Promise.resolve(h.response().code(403).takeover());
});
});

it('should return a 403 HTTP response', async function () {
// when
const response = await httpTestServer.request('GET', '/api/users/1234/campaigns/5678/campaign-participations');

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

describe('#removeAuthenticationMethod', function () {
const method = 'POST';
const url = '/api/admin/users/1/remove-authentication';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -848,4 +848,32 @@ describe('Acceptance | API | Campaign Participations', function () {
expect(participationIds).to.deep.equals([sharableCampaignParticipation.id, startedCampaignParticipation.id]);
});
});

describe('GET /users/{userId}/campaigns/{campaignId}/campaign-participations', function () {
let options;

beforeEach(function () {
databaseBuilder.factory.buildCampaignParticipation({
userId,
campaignId,
status: 'SHARED',
});

options = {
method: 'GET',
url: `/api/users/${userId}/campaigns/${campaignId}/campaign-participations`,
headers: { authorization: generateValidRequestAuthorizationHeader(userId) },
};

return databaseBuilder.commit();
});

it('should return campaign participation with 200 HTTP status code', async function () {
// when
const response = await server.inject(options);

// then
expect(response.statusCode).to.equal(200);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,24 @@ describe('Integration | Application | Route | campaignParticipationRouter', func
sandbox.restore();
});

describe('#getUserCampaignParticipationToCampaign', function () {
context('When Authenticated user mismatch requested user', function () {
beforeEach(function () {
securityPreHandlers.checkRequestedUserIsAuthenticatedUser.callsFake((request, h) => {
return Promise.resolve(h.response().code(403).takeover());
});
});

it('should return a 403 HTTP response', async function () {
// when
const response = await httpTestServer.request('GET', '/api/users/1234/campaigns/5678/campaign-participations');

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

describe('#getUserCampaignAssessmentResult', function () {
context('Error cases', function () {
it('should not called controller when user not authenticated', async function () {
Expand Down
Loading

0 comments on commit 04f8fd6

Please sign in to comment.