-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(identite): extract markDomainAsVerified function
- Loading branch information
1 parent
6ccd601
commit a28284b
Showing
62 changed files
with
985 additions
and
355 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
--- | ||
"@gouvfr-lasuite/proconnect.core": minor | ||
--- | ||
|
||
♻️ Prélevement de la fonction getEmailDomain | ||
|
||
Permet l'extraction du domain d'un email. | ||
|
||
```ts | ||
import { getEmailDomain } from "@gouvfr-lasuite/proconnect.core/services/email"; | ||
|
||
getEmailDomain("[email protected]"); // darkangels.world | ||
``` |
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,5 @@ | ||
--- | ||
"@gouvfr-lasuite/proconnect.identite": minor | ||
--- | ||
|
||
♻️ Prélevement d'un partie du buisness proconnect identité |
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,29 @@ | ||
// | ||
|
||
import { assert } from "chai"; | ||
import { getEmailDomain } from "./get-email-domain.js"; | ||
|
||
// | ||
|
||
describe(getEmailDomain.name, () => { | ||
const data = [ | ||
{ | ||
email: "[email protected]", | ||
domain: "beta.gouv.fr", | ||
}, | ||
{ | ||
email: "[email protected]", | ||
domain: "notaires.fr", | ||
}, | ||
{ | ||
email: "[email protected]", | ||
domain: "subdomain.domain.org", | ||
}, | ||
]; | ||
|
||
data.forEach(({ email, domain }) => { | ||
it("should return email domain", () => { | ||
assert.equal(getEmailDomain(email), domain); | ||
}); | ||
}); | ||
}); |
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,20 @@ | ||
// | ||
|
||
import { parse_host } from "tld-extract"; | ||
|
||
// | ||
|
||
/** | ||
* Get the domain of an email address | ||
* @example | ||
* getEmailDomain("[email protected]") // darkangels.world | ||
* @param email - the email address | ||
* @returns the domain of the email address | ||
*/ | ||
export function getEmailDomain(email: string) { | ||
const parts = email.split("@"); | ||
const host = parts[parts.length - 1]; | ||
const { sub, domain } = parse_host(host, { allowDotlessTLD: true }); | ||
|
||
return [sub, domain].filter(Boolean).join("."); | ||
} |
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 |
---|---|---|
@@ -1,3 +1,4 @@ | ||
// | ||
|
||
export * from "./isAFreeDomain.js"; | ||
export * from "./get-email-domain.js"; | ||
export * from "./is-a-free-domain.js"; |
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
File renamed without changes.
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 |
---|---|---|
@@ -1,5 +1,12 @@ | ||
// | ||
|
||
declare module "tld-extract" { | ||
function parse_host(domain: string, { allowDotlessTLD: boolean }): boolean; | ||
function parse_host( | ||
domain: string, | ||
{ allowDotlessTLD: boolean }, | ||
): { | ||
tld: string; | ||
domain: string; | ||
sub: string; | ||
}; | ||
} |
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
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion
2
...src/organization/get-organization-info.ts → ...ers/organization/get-organization-info.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
2 changes: 1 addition & 1 deletion
2
packages/identite/src/organization/index.ts → ...entite/src/managers/organization/index.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 |
---|---|---|
@@ -1,4 +1,4 @@ | ||
// | ||
|
||
export * from "./get-organization-info.js"; | ||
export * from "./upsert.js"; | ||
export * from "./mark-domain-as-verified.js"; |
115 changes: 115 additions & 0 deletions
115
packages/identite/src/managers/organization/mark-domain-as-verified.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,115 @@ | ||
import { | ||
type AddDomainHandler, | ||
type FindEmailDomainsByOrganizationIdHandler, | ||
} from "#src/repositories/email-domain"; | ||
import type { | ||
FindByIdHandler, | ||
GetUsersByOrganizationHandler, | ||
} from "#src/repositories/organization"; | ||
import type { UpdateUserOrganizationLinkHandler } from "#src/repositories/user"; | ||
import type { | ||
BaseUserOrganizationLink, | ||
EmailDomain, | ||
Organization, | ||
User, | ||
UserOrganizationLink, | ||
} from "#src/types"; | ||
import * as chai from "chai"; | ||
import chaiAsPromised from "chai-as-promised"; | ||
import { mock } from "node:test"; | ||
import { markDomainAsVerifiedFactory } from "./mark-domain-as-verified.js"; | ||
// | ||
|
||
chai.use(chaiAsPromised); | ||
const assert = chai.assert; | ||
|
||
describe(markDomainAsVerifiedFactory.name, () => { | ||
it("should update organization members", async () => { | ||
const addDomain = mock.fn<AddDomainHandler>(() => | ||
Promise.resolve({} as any), | ||
); | ||
|
||
const updateUserOrganizationLink = | ||
mock.fn<UpdateUserOrganizationLinkHandler>(() => | ||
Promise.resolve({} as any), | ||
); | ||
const markDomainAsVerified = markDomainAsVerifiedFactory({ | ||
addDomain, | ||
findEmailDomainsByOrganizationId: | ||
mock.fn<FindEmailDomainsByOrganizationIdHandler>(), | ||
findOrganizationById: mock.fn<FindByIdHandler>(() => | ||
Promise.resolve({ id: 42 } as Organization), | ||
), | ||
getUsers: mock.fn<GetUsersByOrganizationHandler>(() => | ||
Promise.resolve([ | ||
{ | ||
id: 42, | ||
email: "[email protected]", | ||
verification_type: null, | ||
} as User & BaseUserOrganizationLink, | ||
]), | ||
), | ||
updateUserOrganizationLink, | ||
}); | ||
|
||
await markDomainAsVerified({ | ||
domain: "darkangels.world", | ||
domain_verification_type: "verified", | ||
organization_id: 42, | ||
}); | ||
|
||
assert.deepEqual(updateUserOrganizationLink.mock.callCount(), 1); | ||
{ | ||
const [call] = updateUserOrganizationLink.mock.calls; | ||
assert.deepEqual(call.arguments, [ | ||
42, | ||
42, | ||
{ verification_type: "domain" }, | ||
]); | ||
} | ||
|
||
assert.deepEqual(addDomain.mock.callCount(), 1); | ||
{ | ||
const [call] = addDomain.mock.calls; | ||
assert.deepEqual(call.arguments, [ | ||
{ | ||
domain: "darkangels.world", | ||
organization_id: 42, | ||
verification_type: "verified", | ||
}, | ||
]); | ||
} | ||
}); | ||
|
||
it("should add domain if organization if missing", async () => { | ||
const logs = [] as unknown[]; | ||
const updateUserOrganizationLink: UpdateUserOrganizationLinkHandler = ( | ||
...args | ||
) => { | ||
logs.push(args); | ||
return Promise.resolve({} as UserOrganizationLink); | ||
}; | ||
const markDomainAsVerified = markDomainAsVerifiedFactory({ | ||
addDomain: () => Promise.resolve({} as EmailDomain), | ||
findEmailDomainsByOrganizationId: () => Promise.resolve([]), | ||
findOrganizationById: () => Promise.resolve({ id: 42 } as Organization), | ||
getUsers: () => | ||
Promise.resolve([ | ||
{ | ||
id: 42, | ||
email: "[email protected]", | ||
verification_type: null, | ||
} as User & BaseUserOrganizationLink, | ||
]), | ||
updateUserOrganizationLink, | ||
}); | ||
|
||
await markDomainAsVerified({ | ||
domain: "darkangels.world", | ||
domain_verification_type: "verified", | ||
organization_id: 42, | ||
}); | ||
|
||
assert.deepEqual(logs, [[42, 42, { verification_type: "domain" }]]); | ||
}); | ||
}); |
84 changes: 84 additions & 0 deletions
84
packages/identite/src/managers/organization/mark-domain-as-verified.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,84 @@ | ||
// | ||
|
||
import type { GetUsersByOrganizationHandler } from "#src/repositories/organization"; | ||
import type { UpdateUserOrganizationLinkHandler } from "#src/repositories/user"; | ||
import { getEmailDomain } from "@gouvfr-lasuite/proconnect.core/services/email"; | ||
import type { | ||
AddDomainHandler, | ||
FindEmailDomainsByOrganizationIdHandler, | ||
} from "@gouvfr-lasuite/proconnect.identite/repositories/email-domain"; | ||
import type { FindByIdHandler } from "@gouvfr-lasuite/proconnect.identite/repositories/organization"; | ||
import type { EmailDomain } from "@gouvfr-lasuite/proconnect.identite/types"; | ||
import { InseeNotFoundError } from "@gouvfr-lasuite/proconnect.insee/errors"; | ||
import { isEmpty, some } from "lodash-es"; | ||
|
||
// | ||
|
||
type FactoryDependencies = { | ||
addDomain: AddDomainHandler; | ||
findEmailDomainsByOrganizationId: FindEmailDomainsByOrganizationIdHandler; | ||
findOrganizationById: FindByIdHandler; | ||
getUsers: GetUsersByOrganizationHandler; | ||
updateUserOrganizationLink: UpdateUserOrganizationLinkHandler; | ||
}; | ||
|
||
export function markDomainAsVerifiedFactory({ | ||
addDomain, | ||
findEmailDomainsByOrganizationId, | ||
findOrganizationById, | ||
getUsers, | ||
updateUserOrganizationLink, | ||
}: FactoryDependencies) { | ||
return async function markDomainAsVerified({ | ||
organization_id, | ||
domain, | ||
domain_verification_type, | ||
}: { | ||
organization_id: number; | ||
domain: string; | ||
domain_verification_type: EmailDomain["verification_type"]; | ||
}) { | ||
const organization = await findOrganizationById(organization_id); | ||
if (isEmpty(organization)) { | ||
throw new InseeNotFoundError(); | ||
} | ||
const emailDomains = | ||
await findEmailDomainsByOrganizationId(organization_id); | ||
|
||
if ( | ||
!some(emailDomains, { | ||
domain, | ||
verification_type: domain_verification_type, | ||
}) | ||
) { | ||
await addDomain({ | ||
organization_id, | ||
domain, | ||
verification_type: domain_verification_type, | ||
}); | ||
} | ||
const usersInOrganization = await getUsers(organization_id); | ||
|
||
await Promise.all( | ||
usersInOrganization.map( | ||
({ id, email, verification_type: link_verification_type }) => { | ||
const userDomain = getEmailDomain(email); | ||
if ( | ||
userDomain === domain && | ||
[ | ||
null, | ||
"no_verification_means_available", | ||
"no_verification_means_for_entreprise_unipersonnelle", | ||
].includes(link_verification_type) | ||
) { | ||
return updateUserOrganizationLink(organization_id, id, { | ||
verification_type: "domain", | ||
}); | ||
} | ||
|
||
return null; | ||
}, | ||
), | ||
); | ||
}; | ||
} |
35 changes: 35 additions & 0 deletions
35
packages/identite/src/repositories/email-domain/add-domain.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,35 @@ | ||
// | ||
|
||
import { emptyDatabase, migrate, pg } from "#testing"; | ||
import { expect } from "chai"; | ||
import { before, describe, it } from "mocha"; | ||
import { addDomainFactory } from "./add-domain.js"; | ||
|
||
// | ||
|
||
const addDomain = addDomainFactory({ pg: pg as any }); | ||
|
||
describe(addDomainFactory.name, () => { | ||
before(migrate); | ||
beforeEach(emptyDatabase); | ||
|
||
it("should add domain", async () => { | ||
await pg.sql` | ||
INSERT INTO organizations | ||
(id, siret, created_at, updated_at) | ||
VALUES | ||
(1, '66204244933106', '4444-04-04', '4444-04-04') | ||
; | ||
`; | ||
|
||
const emailDomain = await addDomain({ | ||
domain: "darkangels.world", | ||
organization_id: 1, | ||
verification_type: "verified", | ||
}); | ||
|
||
expect(emailDomain.domain).to.equal("darkangels.world"); | ||
expect(emailDomain.verification_type).to.equal("verified"); | ||
expect(emailDomain.created_at).to.deep.equal(emailDomain.updated_at); | ||
}); | ||
}); |
Oops, something went wrong.