diff --git a/api/lib/application/account-recovery/account-recovery-controller.js b/api/lib/application/account-recovery/account-recovery-controller.js index c0bf80b963c..cf66f617f50 100644 --- a/api/lib/application/account-recovery/account-recovery-controller.js +++ b/api/lib/application/account-recovery/account-recovery-controller.js @@ -1,5 +1,4 @@ import { usecases } from '../../domain/usecases/index.js'; -import { DomainTransaction } from '../../infrastructure/DomainTransaction.js'; import * as studentInformationForAccountRecoverySerializer from '../../infrastructure/serializers/jsonapi/student-information-for-account-recovery-serializer.js'; const sendEmailForAccountRecovery = async function ( @@ -26,25 +25,7 @@ const checkAccountRecoveryDemand = async function ( return dependencies.studentInformationForAccountRecoverySerializer.serializeAccountRecovery(studentInformation); }; -const updateUserAccountFromRecoveryDemand = async function (request, h) { - const temporaryKey = request.payload.data.attributes['temporary-key']; - const password = request.payload.data.attributes.password; - - await DomainTransaction.execute(async (domainTransaction) => { - await usecases.updateUserForAccountRecovery({ - password, - temporaryKey, - domainTransaction, - }); - }); - - return h.response().code(204); -}; - -const accountRecoveryController = { +export const accountRecoveryController = { sendEmailForAccountRecovery, checkAccountRecoveryDemand, - updateUserAccountFromRecoveryDemand, }; - -export { accountRecoveryController }; diff --git a/api/lib/application/account-recovery/index.js b/api/lib/application/account-recovery/index.js index d727b253f5d..0b27488dbc5 100644 --- a/api/lib/application/account-recovery/index.js +++ b/api/lib/application/account-recovery/index.js @@ -1,15 +1,11 @@ import JoiDate from '@joi/date'; import BaseJoi from 'joi'; const Joi = BaseJoi.extend(JoiDate); -import XRegExp from 'xregexp'; const inePattern = new RegExp('^[0-9]{9}[a-zA-Z]{2}$'); const inaPattern = new RegExp('^[0-9]{10}[a-zA-Z]{1}$'); -import { config } from '../../config.js'; import { accountRecoveryController } from './account-recovery-controller.js'; -const { passwordValidationPattern } = config.account; - const register = async function (server) { server.route([ { @@ -57,31 +53,6 @@ const register = async function (server) { tags: ['api', 'account-recovery'], }, }, - { - method: 'PATCH', - path: '/api/account-recovery', - config: { - auth: false, - handler: accountRecoveryController.updateUserAccountFromRecoveryDemand, - validate: { - payload: Joi.object({ - data: { - attributes: { - 'temporary-key': Joi.string().min(32).required(), - password: Joi.string().pattern(XRegExp(passwordValidationPattern)).required(), - }, - }, - }), - options: { - allowUnknown: true, - }, - }, - notes: [ - '- Permet de mettre à jour les informations d’un utilisateur via à une demande de récupération de compte.', - ], - tags: ['api', 'account-recovery'], - }, - }, ]); }; diff --git a/api/lib/domain/models/index.js b/api/lib/domain/models/index.js index b8cfa0021c8..cb25e78387a 100644 --- a/api/lib/domain/models/index.js +++ b/api/lib/domain/models/index.js @@ -18,6 +18,7 @@ import { UserSavedTutorial } from '../../../src/devcomp/domain/models/UserSavedT import { Answer } from '../../../src/evaluation/domain/models/Answer.js'; import { CompetenceEvaluation } from '../../../src/evaluation/domain/models/CompetenceEvaluation.js'; import { Progression } from '../../../src/evaluation/domain/models/Progression.js'; +import { AccountRecoveryDemand } from '../../../src/identity-access-management/domain/models/AccountRecoveryDemand.js'; import { AuthenticationMethod } from '../../../src/identity-access-management/domain/models/AuthenticationMethod.js'; import { User } from '../../../src/identity-access-management/domain/models/User.js'; import { UserLogin } from '../../../src/identity-access-management/domain/models/UserLogin.js'; @@ -45,7 +46,6 @@ import { Examiner } from '../../../src/shared/domain/models/Examiner.js'; import { OrganizationInvitation } from '../../../src/team/domain/models/OrganizationInvitation.js'; import { CampaignParticipant } from './../../../src/prescription/campaign-participation/domain/models/CampaignParticipant.js'; import { CampaignParticipation } from './../../../src/prescription/campaign-participation/domain/models/CampaignParticipation.js'; -import { AccountRecoveryDemand } from './AccountRecoveryDemand.js'; import { AnswerCollectionForScoring } from './AnswerCollectionForScoring.js'; import { Area } from './Area.js'; import { Authentication } from './Authentication.js'; diff --git a/api/lib/domain/usecases/account-recovery/send-email-for-account-recovery.js b/api/lib/domain/usecases/account-recovery/send-email-for-account-recovery.js index 5e5c5ee43a9..c69a44c75a3 100644 --- a/api/lib/domain/usecases/account-recovery/send-email-for-account-recovery.js +++ b/api/lib/domain/usecases/account-recovery/send-email-for-account-recovery.js @@ -1,6 +1,6 @@ import crypto from 'node:crypto'; -import { AccountRecoveryDemand } from '../../models/AccountRecoveryDemand.js'; +import { AccountRecoveryDemand } from '../../../../src/identity-access-management/domain/models/AccountRecoveryDemand.js'; const sendEmailForAccountRecovery = async function ({ studentInformation, diff --git a/api/lib/domain/usecases/index.js b/api/lib/domain/usecases/index.js index f00ccc22b85..e74244d9b86 100644 --- a/api/lib/domain/usecases/index.js +++ b/api/lib/domain/usecases/index.js @@ -50,6 +50,8 @@ import { OidcAuthenticationServiceRegistry } from '../../../src/identity-access- import { pixAuthenticationService } from '../../../src/identity-access-management/domain/services/pix-authentication-service.js'; import { refreshTokenService } from '../../../src/identity-access-management/domain/services/refresh-token-service.js'; import * as resetPasswordService from '../../../src/identity-access-management/domain/services/reset-password.service.js'; +import { scoAccountRecoveryService } from '../../../src/identity-access-management/domain/services/sco-account-recovery.service.js'; +import { accountRecoveryDemandRepository } from '../../../src/identity-access-management/infrastructure/repositories/account-recovery-demand.repository.js'; import * as authenticationMethodRepository from '../../../src/identity-access-management/infrastructure/repositories/authentication-method.repository.js'; import * as oidcProviderRepository from '../../../src/identity-access-management/infrastructure/repositories/oidc-provider-repository.js'; import * as resetPasswordDemandRepository from '../../../src/identity-access-management/infrastructure/repositories/reset-password-demand.repository.js'; @@ -112,7 +114,6 @@ import * as sessionPublicationService from '../../domain/services/session-public import * as verifyCertificateCodeService from '../../domain/services/verify-certificate-code-service.js'; import * as disabledPoleEmploiNotifier from '../../infrastructure/externals/pole-emploi/disabled-pole-emploi-notifier.js'; import * as poleEmploiNotifier from '../../infrastructure/externals/pole-emploi/pole-emploi-notifier.js'; -import * as accountRecoveryDemandRepository from '../../infrastructure/repositories/account-recovery-demand-repository.js'; import * as attachableTargetProfileRepository from '../../infrastructure/repositories/attachable-target-profiles-repository.js'; import * as badgeAcquisitionRepository from '../../infrastructure/repositories/badge-acquisition-repository.js'; import * as badgeForCalculationRepository from '../../infrastructure/repositories/badge-for-calculation-repository.js'; @@ -167,7 +168,6 @@ import * as userEmailRepository from '../../infrastructure/repositories/user-ema import * as userOrganizationsForAdminRepository from '../../infrastructure/repositories/user-organizations-for-admin-repository.js'; import * as writeCsvUtils from '../../infrastructure/utils/csv/write-csv-utils.js'; import * as learningContentConversionService from '../services/learning-content/learning-content-conversion-service.js'; -import * as scoAccountRecoveryService from '../services/sco-account-recovery-service.js'; import * as userReconciliationService from '../services/user-reconciliation-service.js'; import * as organizationCreationValidator from '../validators/organization-creation-validator.js'; import * as organizationValidator from '../validators/organization-with-tags-and-target-profiles-script.js'; diff --git a/api/src/identity-access-management/application/account-recovery/account-recovery.controller.js b/api/src/identity-access-management/application/account-recovery/account-recovery.controller.js new file mode 100644 index 00000000000..c4c01d6450d --- /dev/null +++ b/api/src/identity-access-management/application/account-recovery/account-recovery.controller.js @@ -0,0 +1,19 @@ +import { DomainTransaction } from '../../../shared/domain/DomainTransaction.js'; +import { usecases } from '../../domain/usecases/index.js'; + +const updateUserAccountFromRecoveryDemand = async function (request, h) { + const temporaryKey = request.payload.data.attributes['temporary-key']; + const password = request.payload.data.attributes.password; + + await DomainTransaction.execute(async (domainTransaction) => { + await usecases.updateUserForAccountRecovery({ + password, + temporaryKey, + domainTransaction, + }); + }); + + return h.response().code(204); +}; + +export const accountRecoveryController = { updateUserAccountFromRecoveryDemand }; diff --git a/api/src/identity-access-management/application/account-recovery/account-recovery.route.js b/api/src/identity-access-management/application/account-recovery/account-recovery.route.js new file mode 100644 index 00000000000..13dfb23cfe3 --- /dev/null +++ b/api/src/identity-access-management/application/account-recovery/account-recovery.route.js @@ -0,0 +1,35 @@ +import Joi from 'joi'; +import XRegExp from 'xregexp'; + +import { config } from '../../../shared/config.js'; +import { accountRecoveryController } from './account-recovery.controller.js'; + +const { passwordValidationPattern } = config.account; + +export const accountRecoveryRoutes = [ + { + method: 'PATCH', + path: '/api/account-recovery', + config: { + auth: false, + handler: (request, h) => accountRecoveryController.updateUserAccountFromRecoveryDemand(request, h), + validate: { + payload: Joi.object({ + data: { + attributes: { + 'temporary-key': Joi.string().min(32).required(), + password: Joi.string().pattern(XRegExp(passwordValidationPattern)).required(), + }, + }, + }), + options: { + allowUnknown: true, + }, + }, + notes: [ + '- Permet de mettre à jour les informations d’un utilisateur via à une demande de récupération de compte.', + ], + tags: ['identity-access-management', 'api', 'account-recovery'], + }, + }, +]; diff --git a/api/src/identity-access-management/application/routes.js b/api/src/identity-access-management/application/routes.js index 56053ad8e80..3ec9eb368ee 100644 --- a/api/src/identity-access-management/application/routes.js +++ b/api/src/identity-access-management/application/routes.js @@ -1,3 +1,4 @@ +import { accountRecoveryRoutes } from './account-recovery/account-recovery.route.js'; import { anonymizationAdminRoutes } from './anonymization/anonymization.admin.route.js'; import { oidcProviderAdminRoutes } from './oidc-provider/oidc-provider.admin.route.js'; import { oidcProviderRoutes } from './oidc-provider/oidc-provider.route.js'; @@ -9,6 +10,7 @@ import { userRoutes } from './user/user.route.js'; const register = async function (server) { server.route([ + ...accountRecoveryRoutes, ...anonymizationAdminRoutes, ...oidcProviderAdminRoutes, ...oidcProviderRoutes, diff --git a/api/lib/domain/models/AccountRecoveryDemand.js b/api/src/identity-access-management/domain/models/AccountRecoveryDemand.js similarity index 56% rename from api/lib/domain/models/AccountRecoveryDemand.js rename to api/src/identity-access-management/domain/models/AccountRecoveryDemand.js index 0ff483af371..a8693fe239e 100644 --- a/api/lib/domain/models/AccountRecoveryDemand.js +++ b/api/src/identity-access-management/domain/models/AccountRecoveryDemand.js @@ -1,4 +1,16 @@ -class AccountRecoveryDemand { +export class AccountRecoveryDemand { + /** + * @param {{ + * id: string, + * userId: string, + * organizationLearnerId: string, + * oldEmail: string, + * newEmail: string, + * temporaryKey: string, + * used: boolean, + * createdAt: string|Date, + * }} data + */ constructor({ id, userId, organizationLearnerId, oldEmail, newEmail, temporaryKey, used, createdAt } = {}) { this.id = id; this.organizationLearnerId = organizationLearnerId; @@ -10,5 +22,3 @@ class AccountRecoveryDemand { this.createdAt = createdAt; } } - -export { AccountRecoveryDemand }; diff --git a/api/lib/domain/services/sco-account-recovery-service.js b/api/src/identity-access-management/domain/services/sco-account-recovery.service.js similarity index 94% rename from api/lib/domain/services/sco-account-recovery-service.js rename to api/src/identity-access-management/domain/services/sco-account-recovery.service.js index c0b0af01dab..4f4b81744bc 100644 --- a/api/lib/domain/services/sco-account-recovery-service.js +++ b/api/src/identity-access-management/domain/services/sco-account-recovery.service.js @@ -1,15 +1,14 @@ import lodash from 'lodash'; -import { config } from '../../config.js'; import { AccountRecoveryDemandExpired, MultipleOrganizationLearnersWithDifferentNationalStudentIdError, UserHasAlreadyLeftSCO, UserNotFoundError, -} from '../errors.js'; +} from '../../../../lib/domain/errors.js'; +import { config } from '../../../shared/config.js'; const { uniqBy } = lodash; - const { features } = config; async function retrieveOrganizationLearner({ @@ -67,6 +66,8 @@ async function retrieveAndValidateAccountRecoveryDemand({ return { id, userId, newEmail, organizationLearnerId }; } +export const scoAccountRecoveryService = { retrieveAndValidateAccountRecoveryDemand, retrieveOrganizationLearner }; + function _demandHasExpired(demandCreationDate) { const minutesInADay = 60 * 24; const lifetimeInMinutes = parseInt(features.scoAccountRecoveryKeyLifetimeMinutes) || minutesInADay; @@ -104,5 +105,3 @@ async function _checkIfThereAreMultipleUserForTheSameAccount({ userId, organizat throw new MultipleOrganizationLearnersWithDifferentNationalStudentIdError(); } } - -export { retrieveAndValidateAccountRecoveryDemand, retrieveOrganizationLearner }; diff --git a/api/src/identity-access-management/domain/usecases/index.js b/api/src/identity-access-management/domain/usecases/index.js index 9d08e5bb918..138771f33a4 100644 --- a/api/src/identity-access-management/domain/usecases/index.js +++ b/api/src/identity-access-management/domain/usecases/index.js @@ -15,6 +15,7 @@ import * as adminMemberRepository from '../../../shared/infrastructure/repositor import * as userLoginRepository from '../../../shared/infrastructure/repositories/user-login-repository.js'; import { injectDependencies } from '../../../shared/infrastructure/utils/dependency-injection.js'; import { importNamedExportsFromDirectory } from '../../../shared/infrastructure/utils/import-named-exports-from-directory.js'; +import { accountRecoveryDemandRepository } from '../../infrastructure/repositories/account-recovery-demand.repository.js'; import * as authenticationMethodRepository from '../../infrastructure/repositories/authentication-method.repository.js'; import { oidcProviderRepository } from '../../infrastructure/repositories/oidc-provider-repository.js'; import * as resetPasswordDemandRepository from '../../infrastructure/repositories/reset-password-demand.repository.js'; @@ -24,11 +25,13 @@ import { authenticationSessionService } from '../services/authentication-session import { pixAuthenticationService } from '../services/pix-authentication-service.js'; import { refreshTokenService } from '../services/refresh-token-service.js'; import * as resetPasswordService from '../services/reset-password.service.js'; +import { scoAccountRecoveryService } from '../services/sco-account-recovery.service.js'; import { addOidcProviderValidator } from '../validators/add-oidc-provider.validator.js'; const path = dirname(fileURLToPath(import.meta.url)); const repositories = { + accountRecoveryDemandRepository, adminMemberRepository, authenticationMethodRepository, campaignRepository, @@ -47,6 +50,7 @@ const services = { pixAuthenticationService, refreshTokenService, resetPasswordService, + scoAccountRecoveryService, tokenService, userService, }; diff --git a/api/lib/domain/usecases/account-recovery/update-user-for-account-recovery.js b/api/src/identity-access-management/domain/usecases/update-user-for-account-recovery.usecase.js similarity index 71% rename from api/lib/domain/usecases/account-recovery/update-user-for-account-recovery.js rename to api/src/identity-access-management/domain/usecases/update-user-for-account-recovery.usecase.js index 551dfbedec0..de629fc2aa0 100644 --- a/api/lib/domain/usecases/account-recovery/update-user-for-account-recovery.js +++ b/api/src/identity-access-management/domain/usecases/update-user-for-account-recovery.usecase.js @@ -1,15 +1,28 @@ -import { NON_OIDC_IDENTITY_PROVIDERS } from '../../../../src/identity-access-management/domain/constants/identity-providers.js'; -import { AuthenticationMethod } from '../../../../src/identity-access-management/domain/models/AuthenticationMethod.js'; +import { NON_OIDC_IDENTITY_PROVIDERS } from '../constants/identity-providers.js'; +import { AuthenticationMethod } from '../models/AuthenticationMethod.js'; -const updateUserForAccountRecovery = async function ({ +/** + * @param {{ + * password: string, + * temporaryKey: string, + * accountRecoveryDemandRepository: AccountRecoveryDemandRepository, + * authenticationMethodRepository: AuthenticationMethodRepository, + * userRepository: UserRepository, + * cryptoService: CryptoService, + * scoAccountRecoveryService: ScoAccountRecoveryService, + * domainTransaction: DomainTransaction, + * }} params + * @return {Promise} + */ +export const updateUserForAccountRecovery = async function ({ password, temporaryKey, userRepository, + domainTransaction, authenticationMethodRepository, accountRecoveryDemandRepository, scoAccountRecoveryService, cryptoService, - domainTransaction, }) { const { userId, newEmail } = await scoAccountRecoveryService.retrieveAndValidateAccountRecoveryDemand({ temporaryKey, @@ -60,5 +73,3 @@ const updateUserForAccountRecovery = async function ({ }); await accountRecoveryDemandRepository.markAsBeingUsed(temporaryKey, domainTransaction); }; - -export { updateUserForAccountRecovery }; diff --git a/api/lib/infrastructure/repositories/account-recovery-demand-repository.js b/api/src/identity-access-management/infrastructure/repositories/account-recovery-demand.repository.js similarity index 83% rename from api/lib/infrastructure/repositories/account-recovery-demand-repository.js rename to api/src/identity-access-management/infrastructure/repositories/account-recovery-demand.repository.js index 09befdc4826..aa4edfc971f 100644 --- a/api/lib/infrastructure/repositories/account-recovery-demand-repository.js +++ b/api/src/identity-access-management/infrastructure/repositories/account-recovery-demand.repository.js @@ -1,9 +1,9 @@ import _ from 'lodash'; -import { knex } from '../../../db/knex-database-connection.js'; -import { NotFoundError } from '../../domain/errors.js'; +import { knex } from '../../../../db/knex-database-connection.js'; +import { NotFoundError } from '../../../../lib/domain/errors.js'; +import { DomainTransaction } from '../../../../lib/infrastructure/DomainTransaction.js'; import { AccountRecoveryDemand } from '../../domain/models/AccountRecoveryDemand.js'; -import { DomainTransaction } from '../DomainTransaction.js'; const _toDomain = (accountRecoveryDemandDTO) => { return new AccountRecoveryDemand(accountRecoveryDemandDTO); @@ -50,4 +50,4 @@ const markAsBeingUsed = async function (temporaryKey, { knexTransaction } = Doma return query; }; -export { findByTemporaryKey, findByUserId, markAsBeingUsed, save }; +export const accountRecoveryDemandRepository = { findByTemporaryKey, findByUserId, markAsBeingUsed, save }; diff --git a/api/tests/acceptance/application/account-recovery/account-recovery-route-patch_test.js b/api/tests/identity-access-management/acceptance/application/account-recovery/account-recovery.route.test.js similarity index 91% rename from api/tests/acceptance/application/account-recovery/account-recovery-route-patch_test.js rename to api/tests/identity-access-management/acceptance/application/account-recovery/account-recovery.route.test.js index 6f7442bb155..9eb867b082f 100644 --- a/api/tests/acceptance/application/account-recovery/account-recovery-route-patch_test.js +++ b/api/tests/identity-access-management/acceptance/application/account-recovery/account-recovery.route.test.js @@ -1,9 +1,9 @@ -import { createServer, databaseBuilder, expect, knex } from '../../../test-helper.js'; +import { createServer, databaseBuilder, expect, knex } from '../../../../test-helper.js'; -describe('Acceptance | Route | Account-recovery', function () { +describe('Acceptance | Identity Access Management | Application | Route | account-recovery', function () { describe('PATCH /api/account-recovery', function () { context('when user has pix authentication method', function () { - it("should proceed to the account recover by changing user's password and email", async function () { + it("proceeds to the account recover by changing user's password and email", async function () { // given const server = await createServer(); const userId = databaseBuilder.factory.buildUser.withRawPassword({ @@ -50,7 +50,7 @@ describe('Acceptance | Route | Account-recovery', function () { }); context('when user has no pix authentication method', function () { - it('should proceed to the account recover by create pix authentication method', async function () { + it('proceeds to the account recover by create pix authentication method', async function () { // given const server = await createServer(); const userWithGarAuthenticationMethod = databaseBuilder.factory.buildUser.withoutPixAuthenticationMethod({ diff --git a/api/tests/identity-access-management/integration/domain/usecases/update-user-for-account-recovery.usecase.test.js b/api/tests/identity-access-management/integration/domain/usecases/update-user-for-account-recovery.usecase.test.js new file mode 100644 index 00000000000..5e304d72bdf --- /dev/null +++ b/api/tests/identity-access-management/integration/domain/usecases/update-user-for-account-recovery.usecase.test.js @@ -0,0 +1,56 @@ +import { DomainTransaction } from '../../../../../lib/infrastructure/DomainTransaction.js'; +import { updateUserForAccountRecovery } from '../../../../../src/identity-access-management/domain/usecases/update-user-for-account-recovery.usecase.js'; +import { accountRecoveryDemandRepository } from '../../../../../src/identity-access-management/infrastructure/repositories/account-recovery-demand.repository.js'; +import * as authenticationMethodRepository from '../../../../../src/identity-access-management/infrastructure/repositories/authentication-method.repository.js'; +import * as userRepository from '../../../../../src/identity-access-management/infrastructure/repositories/user.repository.js'; +import { cryptoService } from '../../../../../src/shared/domain/services/crypto-service.js'; +import { catchErr, databaseBuilder, expect, knex } from '../../../../test-helper.js'; + +describe('Integration | Identity Access Management | Domain | UseCase | update-user-for-account-recovery', function () { + context('when domain transaction throw an error', function () { + it('rollbacks update user account', async function () { + // given + const password = 'pix123'; + const user = databaseBuilder.factory.buildUser(); + await databaseBuilder.commit(); + const authenticatedMethod = + databaseBuilder.factory.buildAuthenticationMethod.withPixAsIdentityProviderAndHashedPassword({ + userId: user.id, + }); + await databaseBuilder.commit(); + const accountRecovery = databaseBuilder.factory.buildAccountRecoveryDemand({ userId: user.id }); + await databaseBuilder.commit(); + + // when + await catchErr(async () => { + await DomainTransaction.execute(async (domainTransaction) => { + await updateUserForAccountRecovery({ + password, + temporaryKey: accountRecovery.temporaryKey, + userRepository, + authenticationMethodRepository, + accountRecoveryDemandRepository, + cryptoService, + domainTransaction, + }); + throw new Error('an error occurs within the domain transaction'); + }); + }); + + // then + const userUpdated = await knex('users'); + const accountRecoveryDemand = await knex('account-recovery-demands'); + const authenticationMethod = await knex('authentication-methods'); + + expect(userUpdated).to.have.lengthOf(1); + expect(accountRecoveryDemand).to.have.lengthOf(1); + expect(authenticationMethod).to.have.lengthOf(1); + + expect(userUpdated[0].email).to.equal(user.email); + expect(userUpdated[0].emailConfirmedAt).to.be.null; + expect(userUpdated[0].cgu).to.be.equal(user.cgu); + expect(accountRecoveryDemand[0].used).to.be.false; + expect(authenticationMethod[0].password).to.equal(authenticatedMethod.password); + }); + }); +}); diff --git a/api/tests/integration/infrastructure/repositories/account-recovery-demand-repository_test.js b/api/tests/identity-access-management/integration/infrastructure/repositories/account-recovery-demand.repository.test.js similarity index 62% rename from api/tests/integration/infrastructure/repositories/account-recovery-demand-repository_test.js rename to api/tests/identity-access-management/integration/infrastructure/repositories/account-recovery-demand.repository.test.js index 544d3108822..049e97f11eb 100644 --- a/api/tests/integration/infrastructure/repositories/account-recovery-demand-repository_test.js +++ b/api/tests/identity-access-management/integration/infrastructure/repositories/account-recovery-demand.repository.test.js @@ -1,16 +1,16 @@ import lodash from 'lodash'; -import { NotFoundError } from '../../../../lib/domain/errors.js'; -import { AccountRecoveryDemand } from '../../../../lib/domain/models/AccountRecoveryDemand.js'; -import { DomainTransaction } from '../../../../lib/infrastructure/DomainTransaction.js'; -import * as accountRecoveryDemandRepository from '../../../../lib/infrastructure/repositories/account-recovery-demand-repository.js'; -import { catchErr, databaseBuilder, domainBuilder, expect, knex } from '../../../test-helper.js'; +import { NotFoundError } from '../../../../../lib/domain/errors.js'; +import { DomainTransaction } from '../../../../../lib/infrastructure/DomainTransaction.js'; +import { AccountRecoveryDemand } from '../../../../../src/identity-access-management/domain/models/AccountRecoveryDemand.js'; +import { accountRecoveryDemandRepository } from '../../../../../src/identity-access-management/infrastructure/repositories/account-recovery-demand.repository.js'; +import { catchErr, databaseBuilder, domainBuilder, expect, knex } from '../../../../test-helper.js'; const { omit } = lodash; -describe('Integration | Infrastructure | Repository | account-recovery-demand-repository', function () { +describe('Integration | Identity Access Management | Infrastructure | Repository | account-recovery-demand', function () { describe('#findByTemporaryKey', function () { context('when demand does not exist', function () { - it('should throw a not found error', async function () { + it('throws a not found error', async function () { // when const error = await catchErr(accountRecoveryDemandRepository.findByTemporaryKey)('temporary key not found'); @@ -22,7 +22,7 @@ describe('Integration | Infrastructure | Repository | account-recovery-demand-re context('when demand exists', function () { context('when demand has been used already', function () { - it('should return the account recovery demand', async function () { + it('returns the account recovery demand', async function () { // given const email = 'someMail@example.net'; const temporaryKey = 'someTemporaryKey'; @@ -53,33 +53,35 @@ describe('Integration | Infrastructure | Repository | account-recovery-demand-re }); context('when demand is not used yet', function () { - it('should return the account recovery demand when demand is still valid', async function () { - // given - const email = 'someMail@example.net'; - const temporaryKey = 'someTemporaryKey'; - const { - id: demandId, - userId, - organizationLearnerId, - createdAt, - } = await databaseBuilder.factory.buildAccountRecoveryDemand({ email, temporaryKey, used: false }); - await databaseBuilder.factory.buildAccountRecoveryDemand({ email, used: false }); - await databaseBuilder.commit(); - const expectedAccountRecoveryDemand = { - id: demandId, - userId, - oldEmail: null, - organizationLearnerId, - newEmail: 'philipe@example.net', - temporaryKey: 'someTemporaryKey', - used: false, - createdAt, - }; - // when - const demand = await accountRecoveryDemandRepository.findByTemporaryKey(temporaryKey); - - // then - expect(demand).to.deep.equal(expectedAccountRecoveryDemand); + context('when demand is still valid', function () { + it('returns the account recovery demand', async function () { + // given + const email = 'someMail@example.net'; + const temporaryKey = 'someTemporaryKey'; + const { + id: demandId, + userId, + organizationLearnerId, + createdAt, + } = await databaseBuilder.factory.buildAccountRecoveryDemand({ email, temporaryKey, used: false }); + await databaseBuilder.factory.buildAccountRecoveryDemand({ email, used: false }); + await databaseBuilder.commit(); + const expectedAccountRecoveryDemand = { + id: demandId, + userId, + oldEmail: null, + organizationLearnerId, + newEmail: 'philipe@example.net', + temporaryKey: 'someTemporaryKey', + used: false, + createdAt, + }; + // when + const demand = await accountRecoveryDemandRepository.findByTemporaryKey(temporaryKey); + + // then + expect(demand).to.deep.equal(expectedAccountRecoveryDemand); + }); }); }); }); @@ -87,7 +89,7 @@ describe('Integration | Infrastructure | Repository | account-recovery-demand-re describe('#findByUserId', function () { context('when there is no demand', function () { - it('should return an empty array', async function () { + it('returns an empty array', async function () { //given const userId = 1; @@ -100,7 +102,7 @@ describe('Integration | Infrastructure | Repository | account-recovery-demand-re }); context('when there are several demands for several users', function () { - it('should return only the user ones', async function () { + it('returns only the user ones', async function () { // given databaseBuilder.factory.buildAccountRecoveryDemand(); const expectedUser = databaseBuilder.factory.buildUser(); @@ -131,7 +133,7 @@ describe('Integration | Infrastructure | Repository | account-recovery-demand-re }); describe('#markAsBeingUsed', function () { - it('should mark demand as used', async function () { + it('marks demand as used', async function () { // given const temporaryKey = 'temporaryKey'; databaseBuilder.factory.buildAccountRecoveryDemand({ temporaryKey, used: false }); @@ -145,7 +147,7 @@ describe('Integration | Infrastructure | Repository | account-recovery-demand-re expect(demand.used).to.be.true; }); - it('should change updatedAt', async function () { + it('changes updatedAt', async function () { // given const temporaryKey = 'temporaryKey'; const oldUpdatedAt = new Date('2013-01-01T15:00:00Z'); @@ -161,28 +163,30 @@ describe('Integration | Infrastructure | Repository | account-recovery-demand-re expect(newUpdatedAt).to.be.above(oldUpdatedAt); }); - it('should rollback update if error occurs in transaction', async function () { - // given - const temporaryKey = 'temporaryKey'; - databaseBuilder.factory.buildAccountRecoveryDemand({ temporaryKey, used: false }); - await databaseBuilder.commit(); + context('when an error occurs in transaction', function () { + it('rollbacks update', async function () { + // given + const temporaryKey = 'temporaryKey'; + databaseBuilder.factory.buildAccountRecoveryDemand({ temporaryKey, used: false }); + await databaseBuilder.commit(); - // when - await catchErr(async () => { - await DomainTransaction.execute(async (domainTransaction) => { - await accountRecoveryDemandRepository.markAsBeingUsed(temporaryKey, domainTransaction); - throw new Error('Error occurs in transaction'); + // when + await catchErr(async () => { + await DomainTransaction.execute(async (domainTransaction) => { + await accountRecoveryDemandRepository.markAsBeingUsed(temporaryKey, domainTransaction); + throw new Error('Error occurs in transaction'); + }); }); - }); - // then - const demand = await knex('account-recovery-demands').select('used').where({ temporaryKey }).first(); - expect(demand.used).to.be.false; + // then + const demand = await knex('account-recovery-demands').select('used').where({ temporaryKey }).first(); + expect(demand.used).to.be.false; + }); }); }); describe('#save', function () { - it('should persist the account recovery demand', async function () { + it('persists the account recovery demand', async function () { // given const user = databaseBuilder.factory.buildUser(); const organizationLearnerId = databaseBuilder.factory.buildOrganizationLearner({ userId: user.id }).id; @@ -216,15 +220,17 @@ describe('Integration | Infrastructure | Repository | account-recovery-demand-re expect(result.temporaryKey).to.equal(temporaryKey); }); - it('should throw an error if no row is saved', async function () { - // given - const notValidAccountRecoveryDemand = 123; + context('when no row is saved', function () { + it('throws an error', async function () { + // given + const notValidAccountRecoveryDemand = 123; - // when - const error = await catchErr(accountRecoveryDemandRepository.save)(notValidAccountRecoveryDemand); + // when + const error = await catchErr(accountRecoveryDemandRepository.save)(notValidAccountRecoveryDemand); - // then - expect(error).to.be.instanceOf(Error); + // then + expect(error).to.be.instanceOf(Error); + }); }); }); }); diff --git a/api/tests/identity-access-management/unit/application/account-recovery/account-recovery.controller.test.js b/api/tests/identity-access-management/unit/application/account-recovery/account-recovery.controller.test.js new file mode 100644 index 00000000000..9806b3234aa --- /dev/null +++ b/api/tests/identity-access-management/unit/application/account-recovery/account-recovery.controller.test.js @@ -0,0 +1,45 @@ +import { accountRecoveryController } from '../../../../../src/identity-access-management/application/account-recovery/account-recovery.controller.js'; +import { usecases } from '../../../../../src/identity-access-management/domain/usecases/index.js'; +import { DomainTransaction } from '../../../../../src/shared/domain/DomainTransaction.js'; +import { domainBuilder, expect, hFake, sinon } from '../../../../test-helper.js'; + +describe('Unit | Identity Access Management | Application | Controller | account-recovery', function () { + describe('#updateUserForAccountRecovery', function () { + it('calls updateUserForAccountRecovery usecase and return 204', async function () { + // given + const user = domainBuilder.buildUser({ id: 1 }); + const temporaryKey = 'validTemporaryKey'; + const domainTransaction = Symbol(); + + const request = { + params: { + id: user.id, + }, + payload: { + data: { + attributes: { + password: user.password, + 'temporary-key': temporaryKey, + }, + }, + }, + }; + + sinon.stub(usecases, 'updateUserForAccountRecovery').resolves(); + sinon.stub(DomainTransaction, 'execute').callsFake((lambda) => { + return lambda(domainTransaction); + }); + + // when + const response = await accountRecoveryController.updateUserAccountFromRecoveryDemand(request, hFake); + + // then + expect(usecases.updateUserForAccountRecovery).calledWithMatch({ + password: user.password, + temporaryKey, + domainTransaction, + }); + expect(response.statusCode).to.equal(204); + }); + }); +}); diff --git a/api/tests/unit/domain/services/sco-account-recovery-service_test.js b/api/tests/identity-access-management/unit/domain/services/sco-account-recovery.service.test.js similarity index 93% rename from api/tests/unit/domain/services/sco-account-recovery-service_test.js rename to api/tests/identity-access-management/unit/domain/services/sco-account-recovery.service.test.js index 909fb125f9f..850aa91acd7 100644 --- a/api/tests/unit/domain/services/sco-account-recovery-service_test.js +++ b/api/tests/identity-access-management/unit/domain/services/sco-account-recovery.service.test.js @@ -1,22 +1,19 @@ import dayjs from 'dayjs'; -import { config } from '../../../../lib/config.js'; import { AccountRecoveryDemandExpired, AlreadyRegisteredEmailError, MultipleOrganizationLearnersWithDifferentNationalStudentIdError, UserHasAlreadyLeftSCO, UserNotFoundError, -} from '../../../../lib/domain/errors.js'; -import { - retrieveAndValidateAccountRecoveryDemand, - retrieveOrganizationLearner, -} from '../../../../lib/domain/services/sco-account-recovery-service.js'; -import { catchErr, domainBuilder, expect, sinon } from '../../../test-helper.js'; +} from '../../../../../lib/domain/errors.js'; +import { scoAccountRecoveryService } from '../../../../../src/identity-access-management/domain/services/sco-account-recovery.service.js'; +import { config } from '../../../../../src/shared/config.js'; +import { catchErr, domainBuilder, expect, sinon } from '../../../../test-helper.js'; const { features } = config; -describe('Unit | Service | sco-account-recovery-service', function () { +describe('Unit | Identity Access Management | Domain | Service | sco-account-recovery', function () { describe('#retrieveOrganizationLearner', function () { let organizationLearnerRepository; let userRepository; @@ -54,7 +51,7 @@ describe('Unit | Service | sco-account-recovery-service', function () { .resolves(); // when - const error = await catchErr(retrieveOrganizationLearner)({ + const error = await catchErr(scoAccountRecoveryService.retrieveOrganizationLearner)({ studentInformation, organizationLearnerRepository, userRepository, @@ -87,7 +84,7 @@ describe('Unit | Service | sco-account-recovery-service', function () { .resolves(organizationLearner); // when - const error = await catchErr(retrieveOrganizationLearner)({ + const error = await catchErr(scoAccountRecoveryService.retrieveOrganizationLearner)({ studentInformation, organizationLearnerRepository, userRepository, @@ -168,7 +165,7 @@ describe('Unit | Service | sco-account-recovery-service', function () { userRepository.get.withArgs(expectedUser.id).resolves(expectedUser); // when - const result = await retrieveOrganizationLearner({ + const result = await scoAccountRecoveryService.retrieveOrganizationLearner({ accountRecoveryDemandRepository, studentInformation, organizationLearnerRepository, @@ -252,7 +249,7 @@ describe('Unit | Service | sco-account-recovery-service', function () { accountRecoveryDemandRepository.findByUserId.withArgs(user.id).resolves([accountRecoveryDemand]); // when - const result = await catchErr(retrieveOrganizationLearner)({ + const result = await catchErr(scoAccountRecoveryService.retrieveOrganizationLearner)({ accountRecoveryDemandRepository, studentInformation, organizationLearnerRepository, @@ -318,7 +315,7 @@ describe('Unit | Service | sco-account-recovery-service', function () { userRepository.get.withArgs(expectedUser.id).resolves(expectedUser); // when - const result = await retrieveOrganizationLearner({ + const result = await scoAccountRecoveryService.retrieveOrganizationLearner({ accountRecoveryDemandRepository, studentInformation, organizationLearnerRepository, @@ -370,7 +367,7 @@ describe('Unit | Service | sco-account-recovery-service', function () { .resolves(undefined); // when - const error = await catchErr(retrieveOrganizationLearner)({ + const error = await catchErr(scoAccountRecoveryService.retrieveOrganizationLearner)({ studentInformation, organizationLearnerRepository, userRepository, @@ -445,7 +442,7 @@ describe('Unit | Service | sco-account-recovery-service', function () { }); // when - const error = await catchErr(retrieveOrganizationLearner)({ + const error = await catchErr(scoAccountRecoveryService.retrieveOrganizationLearner)({ accountRecoveryDemandRepository, studentInformation, organizationLearnerRepository, @@ -493,7 +490,7 @@ describe('Unit | Service | sco-account-recovery-service', function () { accountRecoveryDemandRepository.findByUserId.withArgs(userId).resolves([{ used: false }]); // when - const result = await retrieveAndValidateAccountRecoveryDemand({ + const result = await scoAccountRecoveryService.retrieveAndValidateAccountRecoveryDemand({ userRepository, accountRecoveryDemandRepository, }); @@ -510,7 +507,7 @@ describe('Unit | Service | sco-account-recovery-service', function () { userRepository.checkIfEmailIsAvailable.withArgs(newEmail).rejects(new AlreadyRegisteredEmailError()); // when - const error = await catchErr(retrieveAndValidateAccountRecoveryDemand)({ + const error = await catchErr(scoAccountRecoveryService.retrieveAndValidateAccountRecoveryDemand)({ userRepository, accountRecoveryDemandRepository, }); @@ -530,7 +527,7 @@ describe('Unit | Service | sco-account-recovery-service', function () { accountRecoveryDemandRepository.findByUserId.withArgs(userId).resolves([{ used: true }]); // when - const error = await catchErr(retrieveAndValidateAccountRecoveryDemand)({ + const error = await catchErr(scoAccountRecoveryService.retrieveAndValidateAccountRecoveryDemand)({ userRepository, accountRecoveryDemandRepository, }); @@ -553,7 +550,7 @@ describe('Unit | Service | sco-account-recovery-service', function () { accountRecoveryDemandRepository.findByUserId.withArgs(userId).resolves([{ used: false }]); // when - const error = await catchErr(retrieveAndValidateAccountRecoveryDemand)({ + const error = await catchErr(scoAccountRecoveryService.retrieveAndValidateAccountRecoveryDemand)({ userRepository, accountRecoveryDemandRepository, }); @@ -573,7 +570,7 @@ describe('Unit | Service | sco-account-recovery-service', function () { accountRecoveryDemandRepository.findByUserId.withArgs(userId).resolves([{ used: false }]); // when - const error = await catchErr(retrieveAndValidateAccountRecoveryDemand)({ + const error = await catchErr(scoAccountRecoveryService.retrieveAndValidateAccountRecoveryDemand)({ userRepository, accountRecoveryDemandRepository, }); diff --git a/api/tests/unit/domain/usecases/account-recovery/update-user-for-account-recovery_test.js b/api/tests/identity-access-management/unit/domain/usecases/update-user-for-account-recovery.usecase.test.js similarity index 72% rename from api/tests/unit/domain/usecases/account-recovery/update-user-for-account-recovery_test.js rename to api/tests/identity-access-management/unit/domain/usecases/update-user-for-account-recovery.usecase.test.js index 98a9b19ae87..bcea3dcbb6f 100644 --- a/api/tests/unit/domain/usecases/account-recovery/update-user-for-account-recovery_test.js +++ b/api/tests/identity-access-management/unit/domain/usecases/update-user-for-account-recovery.usecase.test.js @@ -1,11 +1,11 @@ -import { updateUserForAccountRecovery } from '../../../../../lib/domain/usecases/account-recovery/update-user-for-account-recovery.js'; import { DomainTransaction } from '../../../../../lib/infrastructure/DomainTransaction.js'; import { NON_OIDC_IDENTITY_PROVIDERS } from '../../../../../src/identity-access-management/domain/constants/identity-providers.js'; import { AuthenticationMethod } from '../../../../../src/identity-access-management/domain/models/AuthenticationMethod.js'; import { User } from '../../../../../src/identity-access-management/domain/models/User.js'; +import { updateUserForAccountRecovery } from '../../../../../src/identity-access-management/domain/usecases/update-user-for-account-recovery.usecase.js'; import { domainBuilder, expect, sinon } from '../../../../test-helper.js'; -describe('Unit | Usecases | update-user-for-account-recovery', function () { +describe('Unit | Identity Access Management | Domain | UseCase | update-user-for-account-recovery', function () { let userRepository, authenticationMethodRepository, cryptoService, @@ -44,7 +44,7 @@ describe('Unit | Usecases | update-user-for-account-recovery', function () { }); context('when user has no Pix authentication method', function () { - it('should add Pix authentication method', async function () { + it('adds Pix authentication method', async function () { // given const password = 'pix123'; const hashedPassword = 'hashedpassword'; @@ -89,7 +89,7 @@ describe('Unit | Usecases | update-user-for-account-recovery', function () { }); context('when user has Pix authentication method', function () { - it('should only update password', async function () { + it('updates only password', async function () { // given const password = 'pix123'; const hashedPassword = 'hashedpassword'; @@ -130,66 +130,68 @@ describe('Unit | Usecases | update-user-for-account-recovery', function () { }); }); - it('should mark account recovery demand as being used when user id updated', async function () { - // given - const temporaryKey = 'temporarykey'; - const password = 'pix123'; - const hashedPassword = 'hashedpassword'; - const newEmail = 'newemail@example.net'; - const emailConfirmedAt = new Date(); - const domainTransaction = Symbol(); + context('when user id updated', function () { + it('marks account recovery demand as being used', async function () { + // given + const temporaryKey = 'temporarykey'; + const password = 'pix123'; + const hashedPassword = 'hashedpassword'; + const newEmail = 'newemail@example.net'; + const emailConfirmedAt = new Date(); + const domainTransaction = Symbol(); - const user = domainBuilder.buildUser({ - id: 1234, - email: null, - username: 'manuella.philippe0702', - }); + const user = domainBuilder.buildUser({ + id: 1234, + email: null, + username: 'manuella.philippe0702', + }); - scoAccountRecoveryService.retrieveAndValidateAccountRecoveryDemand - .withArgs({ - temporaryKey, - accountRecoveryDemandRepository, - userRepository, - }) - .resolves({ userId: user.id, newEmail }); - cryptoService.hashPassword.withArgs(password).resolves(hashedPassword); - authenticationMethodRepository.hasIdentityProviderPIX.withArgs({ userId: user.id }).resolves(true); - const userUpdate = new User({ - ...user, - cgu: true, - email: newEmail, - emailConfirmedAt, - }); - const userAttributes = { cgu: true, email: newEmail, emailConfirmedAt }; + scoAccountRecoveryService.retrieveAndValidateAccountRecoveryDemand + .withArgs({ + temporaryKey, + accountRecoveryDemandRepository, + userRepository, + }) + .resolves({ userId: user.id, newEmail }); + cryptoService.hashPassword.withArgs(password).resolves(hashedPassword); + authenticationMethodRepository.hasIdentityProviderPIX.withArgs({ userId: user.id }).resolves(true); + const userUpdate = new User({ + ...user, + cgu: true, + email: newEmail, + emailConfirmedAt, + }); + const userAttributes = { cgu: true, email: newEmail, emailConfirmedAt }; - userRepository.updateWithEmailConfirmed - .withArgs({ id: user.id, userAttributes, domainTransaction }) - .resolves(userUpdate); + userRepository.updateWithEmailConfirmed + .withArgs({ id: user.id, userAttributes, domainTransaction }) + .resolves(userUpdate); - sinon.stub(DomainTransaction, 'execute').callsFake((lambda) => { - return lambda(domainTransaction); - }); + sinon.stub(DomainTransaction, 'execute').callsFake((lambda) => { + return lambda(domainTransaction); + }); - // when - await updateUserForAccountRecovery({ - password, - temporaryKey, - userRepository, - authenticationMethodRepository, - scoAccountRecoveryService, - cryptoService, - accountRecoveryDemandRepository, - domainTransaction, - }); + // when + await updateUserForAccountRecovery({ + password, + temporaryKey, + userRepository, + authenticationMethodRepository, + scoAccountRecoveryService, + cryptoService, + accountRecoveryDemandRepository, + domainTransaction, + }); - // then - expect(accountRecoveryDemandRepository.markAsBeingUsed).to.have.been.calledWithExactly( - temporaryKey, - domainTransaction, - ); + // then + expect(accountRecoveryDemandRepository.markAsBeingUsed).to.have.been.calledWithExactly( + temporaryKey, + domainTransaction, + ); + }); }); - it('should save last terms of service validated at date', async function () { + it('saves last terms of service validated at date', async function () { // given const temporaryKey = 'temporarykey'; const password = 'pix123'; diff --git a/api/tests/integration/domain/usecases/account-recovery/update-user-for-account-recovery_test.js b/api/tests/integration/domain/usecases/account-recovery/update-user-for-account-recovery_test.js deleted file mode 100644 index 8f4548c0f1c..00000000000 --- a/api/tests/integration/domain/usecases/account-recovery/update-user-for-account-recovery_test.js +++ /dev/null @@ -1,54 +0,0 @@ -import { updateUserForAccountRecovery } from '../../../../../lib/domain/usecases/account-recovery/update-user-for-account-recovery.js'; -import { DomainTransaction } from '../../../../../lib/infrastructure/DomainTransaction.js'; -import * as accountRecoveryDemandRepository from '../../../../../lib/infrastructure/repositories/account-recovery-demand-repository.js'; -import * as authenticationMethodRepository from '../../../../../src/identity-access-management/infrastructure/repositories/authentication-method.repository.js'; -import * as userRepository from '../../../../../src/identity-access-management/infrastructure/repositories/user.repository.js'; -import { cryptoService } from '../../../../../src/shared/domain/services/crypto-service.js'; -import { catchErr, databaseBuilder, expect, knex } from '../../../../test-helper.js'; - -describe('Integration | UseCases | Account-recovery | updateUserForAccountRecovery', function () { - it('should rollback update user account when domain transaction throw an error', async function () { - // given - const password = 'pix123'; - const user = databaseBuilder.factory.buildUser(); - await databaseBuilder.commit(); - const authenticatedMethod = - databaseBuilder.factory.buildAuthenticationMethod.withPixAsIdentityProviderAndHashedPassword({ - userId: user.id, - }); - await databaseBuilder.commit(); - const accountRecovery = databaseBuilder.factory.buildAccountRecoveryDemand({ userId: user.id }); - await databaseBuilder.commit(); - - // when - await catchErr(async () => { - await DomainTransaction.execute(async (domainTransaction) => { - await updateUserForAccountRecovery({ - password, - temporaryKey: accountRecovery.temporaryKey, - userRepository, - authenticationMethodRepository, - accountRecoveryDemandRepository, - cryptoService, - domainTransaction, - }); - throw new Error('an error occurs within the domain transaction'); - }); - }); - - // then - const userUpdated = await knex('users'); - const accountRecoveryDemand = await knex('account-recovery-demands'); - const authenticationMethod = await knex('authentication-methods'); - - expect(userUpdated).to.have.lengthOf(1); - expect(accountRecoveryDemand).to.have.lengthOf(1); - expect(authenticationMethod).to.have.lengthOf(1); - - expect(userUpdated[0].email).to.equal(user.email); - expect(userUpdated[0].emailConfirmedAt).to.be.null; - expect(userUpdated[0].cgu).to.be.equal(user.cgu); - expect(accountRecoveryDemand[0].used).to.be.false; - expect(authenticationMethod[0].password).to.equal(authenticatedMethod.password); - }); -}); diff --git a/api/tests/tooling/domain-builder/factory/build-account-recovery-demand.js b/api/tests/tooling/domain-builder/factory/build-account-recovery-demand.js index 12128c749e4..a1c08716781 100644 --- a/api/tests/tooling/domain-builder/factory/build-account-recovery-demand.js +++ b/api/tests/tooling/domain-builder/factory/build-account-recovery-demand.js @@ -1,4 +1,4 @@ -import { AccountRecoveryDemand } from '../../../../lib/domain/models/AccountRecoveryDemand.js'; +import { AccountRecoveryDemand } from '../../../../src/identity-access-management/domain/models/AccountRecoveryDemand.js'; const buildAccountRecoveryDemand = function ({ userId = 7, diff --git a/api/tests/unit/application/account-recovery/account-recovery-controller_test.js b/api/tests/unit/application/account-recovery/account-recovery-controller_test.js index 0196fa270ab..8a9a327ad4d 100644 --- a/api/tests/unit/application/account-recovery/account-recovery-controller_test.js +++ b/api/tests/unit/application/account-recovery/account-recovery-controller_test.js @@ -1,7 +1,6 @@ import { accountRecoveryController } from '../../../../lib/application/account-recovery/account-recovery-controller.js'; import { usecases } from '../../../../lib/domain/usecases/index.js'; -import { DomainTransaction } from '../../../../lib/infrastructure/DomainTransaction.js'; -import { domainBuilder, expect, hFake, sinon } from '../../../test-helper.js'; +import { expect, hFake, sinon } from '../../../test-helper.js'; describe('Unit | Controller | account-recovery-controller', function () { describe('#sendEmailForAccountRecovery', function () { @@ -83,43 +82,4 @@ describe('Unit | Controller | account-recovery-controller', function () { ).to.have.been.calledWithExactly(studentInformation); }); }); - - describe('#updateUserForAccountRecovery', function () { - it('should call updateUserForAccountRecovery usecase and return 204', async function () { - // given - const user = domainBuilder.buildUser({ id: 1 }); - const temporaryKey = 'validTemporaryKey'; - const domainTransaction = Symbol(); - - const request = { - params: { - id: user.id, - }, - payload: { - data: { - attributes: { - password: user.password, - 'temporary-key': temporaryKey, - }, - }, - }, - }; - - sinon.stub(usecases, 'updateUserForAccountRecovery').resolves(); - sinon.stub(DomainTransaction, 'execute').callsFake((lambda) => { - return lambda(domainTransaction); - }); - - // when - const response = await accountRecoveryController.updateUserAccountFromRecoveryDemand(request, hFake); - - // then - expect(usecases.updateUserForAccountRecovery).calledWithMatch({ - password: user.password, - temporaryKey, - domainTransaction, - }); - expect(response.statusCode).to.equal(204); - }); - }); }); diff --git a/api/tests/unit/domain/usecases/account-recovery/send-email-for-account-recovery_test.js b/api/tests/unit/domain/usecases/account-recovery/send-email-for-account-recovery_test.js index c9cc7610c7e..a90338c8168 100644 --- a/api/tests/unit/domain/usecases/account-recovery/send-email-for-account-recovery_test.js +++ b/api/tests/unit/domain/usecases/account-recovery/send-email-for-account-recovery_test.js @@ -1,6 +1,6 @@ import { AlreadyRegisteredEmailError } from '../../../../../lib/domain/errors.js'; -import { AccountRecoveryDemand } from '../../../../../lib/domain/models/AccountRecoveryDemand.js'; import { sendEmailForAccountRecovery } from '../../../../../lib/domain/usecases/account-recovery/send-email-for-account-recovery.js'; +import { AccountRecoveryDemand } from '../../../../../src/identity-access-management/domain/models/AccountRecoveryDemand.js'; import { catchErr, expect, sinon } from '../../../../test-helper.js'; describe('Unit | UseCase | Account-recovery | account-recovery | send-email-for-account-recovery', function () {