-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f756c26
commit c02089d
Showing
7 changed files
with
346 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
back/src/domains/inclusion-connected-users/use-cases/CreateUserForAgency.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { | ||
AgencyRight, | ||
InclusionConnectedUser, | ||
UserCreateParamsForAgency, | ||
errors, | ||
userCreateParamsForAgencySchema, | ||
} from "shared"; | ||
import { createTransactionalUseCase } from "../../core/UseCase"; | ||
import { TimeGateway } from "../../core/time-gateway/ports/TimeGateway"; | ||
import { UuidGenerator } from "../../core/uuid-generator/ports/UuidGenerator"; | ||
import { throwIfNotAdmin } from "../helpers/throwIfIcUserNotBackofficeAdmin"; | ||
|
||
export type CreateUserForAgency = ReturnType<typeof makeCreateUserForAgency>; | ||
|
||
export const makeCreateUserForAgency = createTransactionalUseCase< | ||
UserCreateParamsForAgency, | ||
void, | ||
InclusionConnectedUser, | ||
{ timeGateway: TimeGateway; uuidGenerator: UuidGenerator } | ||
>( | ||
{ | ||
name: "CreateUserForAgency", | ||
inputSchema: userCreateParamsForAgencySchema, | ||
}, | ||
async ({ | ||
inputParams: { agencyId, email, isNotifiedByEmail, roles, userId }, | ||
uow, | ||
currentUser, | ||
deps, | ||
}) => { | ||
throwIfNotAdmin(currentUser); | ||
const agency = await uow.agencyRepository.getById(agencyId); | ||
if (!agency) throw errors.agency.notFound({ agencyId }); | ||
|
||
if (agency.refersToAgencyId && roles.includes("validator")) | ||
throw errors.agency.invalidRoleUpdateForAgencyWithRefersTo({ | ||
agencyId: agency.id, | ||
role: "validator", | ||
}); | ||
|
||
const existingUser = await uow.userRepository.getById(userId); | ||
|
||
if (!existingUser) { | ||
await uow.userRepository.save({ | ||
createdAt: deps.timeGateway.now().toISOString(), | ||
email, | ||
externalId: null, | ||
firstName: "", | ||
id: userId, | ||
lastName: "", | ||
}); | ||
} | ||
|
||
const existingUserAgencyRights = existingUser?.agencyRights ?? []; | ||
const agencyRight: AgencyRight = { | ||
roles, | ||
isNotifiedByEmail: isNotifiedByEmail, | ||
agency, | ||
}; | ||
await uow.userRepository.updateAgencyRights({ | ||
userId: userId, | ||
agencyRights: [...existingUserAgencyRights, agencyRight], | ||
}); | ||
}, | ||
); |
234 changes: 234 additions & 0 deletions
234
back/src/domains/inclusion-connected-users/use-cases/CreateUserForAgency.unit.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,234 @@ | ||
import { | ||
AgencyDtoBuilder, | ||
InclusionConnectedUserBuilder, | ||
errors, | ||
expectPromiseToFailWithError, | ||
expectToEqual, | ||
} from "shared"; | ||
import { InMemoryAgencyRepository } from "../../agency/adapters/InMemoryAgencyRepository"; | ||
import { InMemoryUserRepository } from "../../core/authentication/inclusion-connect/adapters/InMemoryUserRepository"; | ||
import { CustomTimeGateway } from "../../core/time-gateway/adapters/CustomTimeGateway"; | ||
import { TimeGateway } from "../../core/time-gateway/ports/TimeGateway"; | ||
import { InMemoryUowPerformer } from "../../core/unit-of-work/adapters/InMemoryUowPerformer"; | ||
import { createInMemoryUow } from "../../core/unit-of-work/adapters/createInMemoryUow"; | ||
import { TestUuidGenerator } from "../../core/uuid-generator/adapters/UuidGeneratorImplementations"; | ||
import { UuidGenerator } from "../../core/uuid-generator/ports/UuidGenerator"; | ||
import { | ||
CreateUserForAgency, | ||
makeCreateUserForAgency, | ||
} from "./CreateUserForAgency"; | ||
|
||
const backofficeAdminUser = new InclusionConnectedUserBuilder() | ||
.withId("backoffice-admin-id") | ||
.withIsAdmin(true) | ||
.build(); | ||
|
||
const notAdminUser = new InclusionConnectedUserBuilder() | ||
.withId("not-admin-id") | ||
.withIsAdmin(false) | ||
.build(); | ||
|
||
const agency = new AgencyDtoBuilder() | ||
.withCounsellorEmails(["[email protected]"]) | ||
.build(); | ||
|
||
describe("CreateUserForAgency", () => { | ||
let createUserForAgency: CreateUserForAgency; | ||
let uowPerformer: InMemoryUowPerformer; | ||
let userRepository: InMemoryUserRepository; | ||
let agencyRepository: InMemoryAgencyRepository; | ||
let timeGateway: TimeGateway; | ||
let uuidGenerator: UuidGenerator; | ||
|
||
beforeEach(() => { | ||
const uow = createInMemoryUow(); | ||
|
||
userRepository = uow.userRepository; | ||
agencyRepository = uow.agencyRepository; | ||
uowPerformer = new InMemoryUowPerformer(uow); | ||
userRepository.setInclusionConnectedUsers([ | ||
backofficeAdminUser, | ||
notAdminUser, | ||
]); | ||
timeGateway = new CustomTimeGateway(); | ||
uuidGenerator = new TestUuidGenerator(); | ||
createUserForAgency = makeCreateUserForAgency({ | ||
uowPerformer, | ||
deps: { timeGateway, uuidGenerator }, | ||
}); | ||
agencyRepository.setAgencies([agency]); | ||
}); | ||
|
||
it("throws Forbidden if token payload is not backoffice token", async () => { | ||
await expectPromiseToFailWithError( | ||
createUserForAgency.execute( | ||
{ | ||
userId: uuidGenerator.new(), | ||
roles: ["counsellor"], | ||
agencyId: "agency-1", | ||
isNotifiedByEmail: true, | ||
email: "[email protected]", | ||
}, | ||
notAdminUser, | ||
), | ||
errors.user.forbidden({ userId: notAdminUser.id }), | ||
); | ||
}); | ||
|
||
it("throws not found if agency does not exist", async () => { | ||
userRepository.setInclusionConnectedUsers([ | ||
backofficeAdminUser, | ||
{ | ||
...notAdminUser, | ||
agencyRights: [], | ||
dashboards: { | ||
agencies: {}, | ||
establishments: {}, | ||
}, | ||
}, | ||
]); | ||
|
||
const agencyId = "Fake-Agency-Id"; | ||
|
||
await expectPromiseToFailWithError( | ||
createUserForAgency.execute( | ||
{ | ||
userId: uuidGenerator.new(), | ||
roles: ["counsellor"], | ||
agencyId, | ||
isNotifiedByEmail: true, | ||
email: "[email protected]", | ||
}, | ||
backofficeAdminUser, | ||
), | ||
errors.agency.notFound({ | ||
agencyId, | ||
}), | ||
); | ||
}); | ||
|
||
describe("Agency with refers to agency", () => { | ||
const agencyWithRefersTo = new AgencyDtoBuilder() | ||
.withId("agency-with-refers-to") | ||
.withValidatorEmails([]) | ||
.withCounsellorEmails(["[email protected]"]) | ||
.withRefersToAgencyId(agency.id) | ||
.build(); | ||
|
||
it("Throw when user have role validator", async () => { | ||
agencyRepository.insert(agencyWithRefersTo); | ||
|
||
expectPromiseToFailWithError( | ||
createUserForAgency.execute( | ||
{ | ||
userId: uuidGenerator.new(), | ||
agencyId: agencyWithRefersTo.id, | ||
roles: ["validator"], | ||
isNotifiedByEmail: true, | ||
email: "[email protected]", | ||
}, | ||
backofficeAdminUser, | ||
), | ||
errors.agency.invalidRoleUpdateForAgencyWithRefersTo({ | ||
agencyId: agencyWithRefersTo.id, | ||
role: "validator", | ||
}), | ||
); | ||
}); | ||
}); | ||
|
||
it("create new user with its agency rights", async () => { | ||
const newUserId = uuidGenerator.new(); | ||
userRepository.users = []; | ||
|
||
await createUserForAgency.execute( | ||
{ | ||
userId: newUserId, | ||
agencyId: agency.id, | ||
roles: ["counsellor"], | ||
isNotifiedByEmail: false, | ||
email: "[email protected]", | ||
}, | ||
backofficeAdminUser, | ||
); | ||
|
||
expect(userRepository.users.length).toBe(1); | ||
expectToEqual(await userRepository.getById(newUserId), { | ||
createdAt: timeGateway.now().toISOString(), | ||
externalId: null, | ||
firstName: "", | ||
id: newUserId, | ||
email: "[email protected]", | ||
lastName: "", | ||
agencyRights: [ | ||
{ agency, isNotifiedByEmail: false, roles: ["counsellor"] }, | ||
], | ||
dashboards: { | ||
agencies: {}, | ||
establishments: {}, | ||
}, | ||
}); | ||
}); | ||
|
||
it("add agency rights to an existing user", async () => { | ||
const anotherAgency = new AgencyDtoBuilder() | ||
.withId("another-agency-id") | ||
.build(); | ||
await agencyRepository.insert(anotherAgency); | ||
const userId = uuidGenerator.new(); | ||
await userRepository.save({ | ||
id: userId, | ||
email: "[email protected]", | ||
firstName: "John", | ||
lastName: "Doe", | ||
externalId: null, | ||
createdAt: timeGateway.now().toISOString(), | ||
}); | ||
await userRepository.updateAgencyRights({ | ||
userId, | ||
agencyRights: [ | ||
{ | ||
agency, | ||
isNotifiedByEmail: true, | ||
roles: ["validator"], | ||
}, | ||
], | ||
}); | ||
|
||
await createUserForAgency.execute( | ||
{ | ||
userId, | ||
agencyId: anotherAgency.id, | ||
roles: ["counsellor"], | ||
isNotifiedByEmail: false, | ||
email: "[email protected]", | ||
}, | ||
backofficeAdminUser, | ||
); | ||
|
||
expectToEqual(await userRepository.getById(userId), { | ||
createdAt: timeGateway.now().toISOString(), | ||
externalId: null, | ||
firstName: "John", | ||
id: userId, | ||
email: "[email protected]", | ||
lastName: "Doe", | ||
agencyRights: [ | ||
{ | ||
agency, | ||
isNotifiedByEmail: true, | ||
roles: ["validator"], | ||
}, | ||
{ | ||
agency: anotherAgency, | ||
isNotifiedByEmail: false, | ||
roles: ["counsellor"], | ||
}, | ||
], | ||
dashboards: { | ||
agencies: {}, | ||
establishments: {}, | ||
}, | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters