Skip to content

Commit

Permalink
refactor(orga): rename password reset route and function
Browse files Browse the repository at this point in the history
to batch username password generation
  • Loading branch information
er-lim committed Sep 25, 2024
1 parent f78a9cd commit f77b6ec
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 20 deletions.
37 changes: 37 additions & 0 deletions api/lib/application/sco-organization-learners/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,43 @@ const register = async function (server) {
tags: ['api', 'sco-organization-learners'],
},
},
{
method: 'POST',
path: '/api/sco-organization-learners/batch-username-password-generate',
config: {
pre: [
{
method: securityPreHandlers.checkUserBelongsToScoOrganizationAndManagesStudents,
assign: 'belongsToScoOrganizationAndManageStudents',
},
],
handler: scoOrganizationLearnerController.batchGenerateOrganizationLearnersUsernameWithTemporaryPassword,
validate: {
options: {
allowUnknown: true,
},
payload: Joi.object({
data: {
attributes: {
'organization-id': identifiersType.campaignId,
'organization-learners-id': Joi.array().items(identifiersType.organizationLearnerId),
},
},
}),
failAction: (request, h) => {
return sendJsonApiError(
new BadRequestError('The server could not understand the request due to invalid syntax.'),
h,
);
},
},
notes: [
"- Réinitialise, avec un mot de passe à usage unique, les mots de passe des élèves dont les identifiants sont passés en paramètre et qui ont un identifiant comme méthode d'authentification\n" +
"- La demande de modification du mot de passe doit être effectuée par un membre de l'organisation à laquelle appartiennent les élèves.",
],
tags: ['api', 'sco-organization-learners'],
},
},
{
method: 'POST',
path: '/api/sco-organization-learners/password-reset',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ describe('Acceptance | Controller | sco-organization-learners', function () {
});
});

describe('POST /api/sco-organization-learners/password-reset', function () {
describe('POST /api/sco-organization-learners/batch-username-password-generate', function () {
context('when successfully update organization learners passwords', function () {
it('returns an HTTP status code 200 with generated CSV file', async function () {
// given
Expand Down Expand Up @@ -631,7 +631,7 @@ describe('Acceptance | Controller | sco-organization-learners', function () {
// when
const { headers, payload, statusCode } = await server.inject({
method: 'POST',
url: '/api/sco-organization-learners/password-reset',
url: '/api/sco-organization-learners/batch-username-password-generate',
headers: { authorization: generateValidRequestAuthorizationHeader(userId) },
payload: {
data: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ describe('Integration | Application | sco-organization-learners | sco-organizati
// when
const response = await httpTestServer.request(
'POST',
'/api/sco-organization-learners/password-reset',
'/api/sco-organization-learners/batch-username-password-generate',
payload,
auth,
);
Expand Down
10 changes: 8 additions & 2 deletions orga/app/adapters/sco-organization-participant.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ export default class ScoOrganizationParticipantAdapter extends ApplicationAdapte
return `${this.host}/${this.namespace}/organizations/${organizationId}/sco-participants`;
}

async resetOrganizationLearnersPassword({ fetch, fileSaver, organizationId, organizationLearnersIds, token }) {
const url = `${this.host}/${this.namespace}/sco-organization-learners/password-reset`;
async generateOrganizationLearnersUsernamePassword({
fetch,
fileSaver,
organizationId,
organizationLearnersIds,
token,
}) {
const url = `${this.host}/${this.namespace}/sco-organization-learners/batch-username-password-generate`;
const payload = JSON.stringify(
{
data: {
Expand Down
4 changes: 2 additions & 2 deletions orga/app/components/sco-organization-participant/list.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@
@showModal={{this.showResetPasswordModal}}
@totalSelectedStudents={{selectedStudents.length}}
@totalAffectedStudents={{this.affectedStudents.length}}
@onTriggerAction={{fn this.resetPasswordForStudents this.affectedStudents reset}}
@onTriggerAction={{fn this.generateUsernamePasswordForStudents this.affectedStudents reset}}
@onCloseModal={{this.closeResetPasswordModal}}
/>
<ScoOrganizationParticipant::GenerateUsernamePasswordModal
@showModal={{this.showGenerateUsernamePasswordModal}}
@totalAffectedStudents={{this.affectedStudents.length}}
@onTriggerAction={{fn this.resetPasswordForStudents this.affectedStudents reset}}
@onTriggerAction={{fn this.generateUsernamePasswordForStudents this.affectedStudents reset}}
@onCloseModal={{this.closeGenerateUsernamePasswordModal}}
/>
</InElement>
Expand Down
4 changes: 2 additions & 2 deletions orga/app/components/sco-organization-participant/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,10 @@ export default class ScoList extends Component {
}

@action
async resetPasswordForStudents(affectedStudents, resetSelectedStudents) {
async generateUsernamePasswordForStudents(affectedStudents, resetSelectedStudents) {
const affectedStudentsIds = affectedStudents.map((affectedStudents) => affectedStudents.id);
try {
await this.store.adapterFor('sco-organization-participant').resetOrganizationLearnersPassword({
await this.store.adapterFor('sco-organization-participant').generateOrganizationLearnersUsernamePassword({
fetch,
fileSaver: this.fileSaver,
organizationId: this.currentUser.organization.id,
Expand Down
2 changes: 1 addition & 1 deletion orga/mirage/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ function routes() {
});
});

this.post('/sco-organization-learners/password-reset', () => {
this.post('/sco-organization-learners/batch-username-password-generate', () => {
const headers = {
'Content-Type': 'text/csv;charset=utf-8',
'Content-Disposition': 'attachment; filename=content.csv',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1420,7 +1420,9 @@ module('Integration | Component | ScoOrganizationParticipant::List', function (h
test('closes dialog', async function (assert) {
// given
const store = this.owner.lookup('service:store');
sinon.stub(store, 'adapterFor').returns({ resetOrganizationLearnersPassword: sinon.stub().resolves() });
sinon
.stub(store, 'adapterFor')
.returns({ generateOrganizationLearnersUsernamePassword: sinon.stub().resolves() });

const students = [
{ id: '1', firstName: 'Spider', lastName: 'Man', authenticationMethods: ['mediacentre'] },
Expand Down Expand Up @@ -1470,7 +1472,9 @@ module('Integration | Component | ScoOrganizationParticipant::List', function (h
test('displays a successful notification', async function (assert) {
// given
const store = this.owner.lookup('service:store');
sinon.stub(store, 'adapterFor').returns({ resetOrganizationLearnersPassword: sinon.stub().resolves() });
sinon
.stub(store, 'adapterFor')
.returns({ generateOrganizationLearnersUsernamePassword: sinon.stub().resolves() });
notificationsStub = this.owner.lookup('service:notifications');
sinon.stub(notificationsStub, 'sendSuccess');

Expand Down Expand Up @@ -1525,7 +1529,7 @@ module('Integration | Component | ScoOrganizationParticipant::List', function (h
// given
const store = this.owner.lookup('service:store');
sinon.stub(store, 'adapterFor').returns({
resetOrganizationLearnersPassword: sinon
generateOrganizationLearnersUsernamePassword: sinon
.stub()
.rejects([{ code: 'USER_DOES_NOT_BELONG_TO_ORGANIZATION' }]),
});
Expand Down Expand Up @@ -1586,7 +1590,7 @@ module('Integration | Component | ScoOrganizationParticipant::List', function (h
// given
const store = this.owner.lookup('service:store');
sinon.stub(store, 'adapterFor').returns({
resetOrganizationLearnersPassword: sinon
generateOrganizationLearnersUsernamePassword: sinon
.stub()
.rejects([{ code: 'ORGANIZATION_LEARNER_DOES_NOT_BELONG_TO_ORGANIZATION' }]),
});
Expand Down Expand Up @@ -1649,7 +1653,7 @@ module('Integration | Component | ScoOrganizationParticipant::List', function (h
// given
const store = this.owner.lookup('service:store');
sinon.stub(store, 'adapterFor').returns({
resetOrganizationLearnersPassword: sinon.stub().rejects([
generateOrganizationLearnersUsernamePassword: sinon.stub().rejects([
{
code: 'ORGANIZATION_LEARNER_WITHOUT_USERNAME',
},
Expand Down Expand Up @@ -1712,7 +1716,7 @@ module('Integration | Component | ScoOrganizationParticipant::List', function (h
// given
const store = this.owner.lookup('service:store');
sinon.stub(store, 'adapterFor').returns({
resetOrganizationLearnersPassword: sinon.stub().rejects([{ status: 500 }]),
generateOrganizationLearnersUsernamePassword: sinon.stub().rejects([{ status: 500 }]),
});
notificationsStub = this.owner.lookup('service:notifications');
sinon.stub(notificationsStub, 'sendError');
Expand Down
8 changes: 4 additions & 4 deletions orga/tests/unit/adapters/sco-organization-participant-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ module('Unit | Adapters | sco-organization-participant', function (hooks) {
});
});

module('#resetOrganizationLearnersPassword', function () {
test('resets organization learners password and saves a CSV file', async function (assert) {
module('#generateOrganizationLearnersUsernamePassword', function () {
test('generates organization learners username with password and saves a CSV file', async function (assert) {
// given
const fetch = sinon.stub().resolves();
const fileSaver = { save: sinon.stub().resolves() };
Expand All @@ -36,7 +36,7 @@ module('Unit | Adapters | sco-organization-participant', function (hooks) {
adapter.namespace = 'api';

// when
await adapter.resetOrganizationLearnersPassword({
await adapter.generateOrganizationLearnersUsernamePassword({
fetch,
fileSaver,
organizationId,
Expand All @@ -45,7 +45,7 @@ module('Unit | Adapters | sco-organization-participant', function (hooks) {
});

// then
const expectedUrl = `${adapter.host}/${adapter.namespace}/sco-organization-learners/password-reset`;
const expectedUrl = `${adapter.host}/${adapter.namespace}/sco-organization-learners/batch-username-password-generate`;
const expectedOptions = {
method: 'POST',
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
Expand Down

0 comments on commit f77b6ec

Please sign in to comment.