Skip to content

Commit

Permalink
feat(api): create share profile route and controller
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexandre-Monney committed Nov 20, 2024
1 parent 9aaa251 commit d2bad35
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 15 deletions.
65 changes: 50 additions & 15 deletions api/src/profile/application/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,37 @@ import { attestationController } from './attestation-controller.js';
import { profileController } from './profile-controller.js';

const register = async function (server) {
server.route([
const adminRoutes = [
{
method: 'GET',
path: '/api/admin/users/{id}/profile',
config: {
pre: [
{
method: (request, h) =>
securityPreHandlers.hasAtLeastOneAccessOf([
securityPreHandlers.checkAdminMemberHasRoleSuperAdmin,
securityPreHandlers.checkAdminMemberHasRoleCertif,
securityPreHandlers.checkAdminMemberHasRoleSupport,
securityPreHandlers.checkAdminMemberHasRoleMetier,
])(request, h),
},
],
validate: {
params: Joi.object({
id: identifiersType.userId,
}),
},
handler: profileController.getProfileForAdmin,
notes: [
"- Permet à un administrateur de récupérer le nombre total de Pix d'un utilisateur\n et de ses scorecards",
],
tags: ['api', 'user', 'profile'],
},
},
];

const userRoutes = [
{
method: 'GET',
path: '/api/users/{userId}/attestations/{attestationKey}',
Expand Down Expand Up @@ -57,33 +87,38 @@ const register = async function (server) {
},
},
{
method: 'GET',
path: '/api/admin/users/{id}/profile',
method: 'POST',
path: '/api/users/{userId}/profile/share-reward',
config: {
pre: [
{
method: (request, h) =>
securityPreHandlers.hasAtLeastOneAccessOf([
securityPreHandlers.checkAdminMemberHasRoleSuperAdmin,
securityPreHandlers.checkAdminMemberHasRoleCertif,
securityPreHandlers.checkAdminMemberHasRoleSupport,
securityPreHandlers.checkAdminMemberHasRoleMetier,
])(request, h),
method: securityPreHandlers.checkRequestedUserIsAuthenticatedUser,
assign: 'requestedUserIsAuthenticatedUser',
},
],
validate: {
params: Joi.object({
id: identifiersType.userId,
userId: identifiersType.userId,
}),
payload: Joi.object({
data: {
attributes: {
campaignParticipationId: identifiersType.campaignParticipationId,
profileRewardId: identifiersType.profileRewardId,
},
},
}),
},
handler: profileController.getProfileForAdmin,
handler: profileController.shareProfileReward,
notes: [
"- Permet à un administrateur de récupérer le nombre total de Pix d'un utilisateur\n et de ses scorecards",
"- Cette route permet à un utilisateur de partager l'obtention de son attestation avec une organisation\n",
],
tags: ['api', 'user', 'profile'],
tags: ['api', 'user', 'profile', 'reward'],
},
},
]);
];

server.route([...adminRoutes, ...userRoutes]);
};

const name = 'profile-api';
Expand Down
9 changes: 9 additions & 0 deletions api/src/profile/application/profile-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,18 @@ const getProfileForAdmin = function (request, h, dependencies = { profileSeriali
return usecases.getUserProfile({ userId, locale }).then(dependencies.profileSerializer.serialize);
};

const shareProfileReward = async function (request, h) {
const userId = request.params.userId;
const { profileRewardId, campaignParticipationId } = request.payload.data.attributes;

await usecases.shareProfileReward({ userId, profileRewardId, campaignParticipationId });
return h.response().code(201);
};

const profileController = {
getProfile,
getProfileForAdmin,
shareProfileReward,
};

export { profileController };
1 change: 1 addition & 0 deletions api/src/shared/domain/types/identifiers-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const typesPositiveInteger32bits = [
'ownerId',
'passageId',
'placeId',
'profileRewardId',
'schoolingRegistrationId',
'sessionId',
'stageCollectionId',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import {
createServer,
databaseBuilder,
expect,
generateValidRequestAuthorizationHeader,
} from '../../../test-helper.js';

describe('Profile | Acceptance | Application | Share Profile Route ', function () {
let server;

beforeEach(async function () {
server = await createServer();
});

describe('POST /api/users/{userId}/profile/share-reward', function () {
describe('when profile reward exists and is linked to user', function () {
it('should return a success code', async function () {
// given
const userId = databaseBuilder.factory.buildUser().id;
const profileReward = databaseBuilder.factory.buildProfileReward({ userId });
const campaignParticipation = databaseBuilder.factory.buildCampaignParticipation();

await databaseBuilder.commit();
const options = {
method: 'POST',
headers: { authorization: generateValidRequestAuthorizationHeader(userId) },
url: `/api/users/${userId}/profile/share-reward`,
payload: {
data: {
attributes: {
profileRewardId: profileReward.id,
campaignParticipationId: campaignParticipation.id,
},
},
},
};

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

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

describe('when profile reward is not linked to user', function () {
it('should return a 412 code', async function () {
// given
const userId = databaseBuilder.factory.buildUser().id;
const profileReward = databaseBuilder.factory.buildProfileReward();
const campaignParticipation = databaseBuilder.factory.buildCampaignParticipation();

await databaseBuilder.commit();
const options = {
method: 'POST',
headers: { authorization: generateValidRequestAuthorizationHeader(userId) },
url: `/api/users/${userId}/profile/share-reward`,
payload: {
data: {
attributes: {
profileRewardId: profileReward.id,
campaignParticipationId: campaignParticipation.id,
},
},
},
};

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

// then
expect(response.statusCode).to.equal(412);
});
});
});
42 changes: 42 additions & 0 deletions api/tests/profile/unit/application/profile-controller_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,46 @@ describe('Profile | Unit | Controller | profile-controller', function () {
expect(usecases.getUserProfile).to.have.been.calledWithExactly({ userId, locale });
});
});

describe('#shareProfileReward', function () {
beforeEach(function () {
sinon.stub(usecases, 'shareProfileReward').resolves();
});

it('should call the expected usecase', async function () {
// given
const profileRewardId = '11';
const campaignParticipationId = '22';
const userId = '33';

const request = {
auth: {
credentials: {
userId,
},
},
params: {
userId,
},
payload: {
data: {
attributes: {
profileRewardId,
campaignParticipationId,
},
},
},
};

// when
await profileController.shareProfileReward(request, hFake);

// then
expect(usecases.shareProfileReward).to.have.been.calledWithExactly({
userId,
profileRewardId,
campaignParticipationId,
});
});
});
});

0 comments on commit d2bad35

Please sign in to comment.