diff --git a/src/utils/unique_email_enforcement/__tests__/index.test.ts b/src/utils/unique_email_enforcement/__tests__/index.test.ts index 69915462..41d47541 100644 --- a/src/utils/unique_email_enforcement/__tests__/index.test.ts +++ b/src/utils/unique_email_enforcement/__tests__/index.test.ts @@ -39,7 +39,8 @@ describe("isEmailAlreadyTaken", () => { ({ entries, expected }) => { const result = isEmailAlreadyTaken(mocks.email)({ profileEmails: { - list: generateProfileEmails(entries) + list: generateProfileEmails(entries), + get: jest.fn() } }); expect(result).resolves.toBe(expected); diff --git a/src/utils/unique_email_enforcement/__tests__/storage.test.ts b/src/utils/unique_email_enforcement/__tests__/storage.test.ts index 36a803bb..dc472db3 100644 --- a/src/utils/unique_email_enforcement/__tests__/storage.test.ts +++ b/src/utils/unique_email_enforcement/__tests__/storage.test.ts @@ -1,6 +1,10 @@ import { describe, it, expect, jest } from "@jest/globals"; -import { odata, TableEntityResult } from "@azure/data-tables"; +import { + GetTableEntityResponse, + odata, + TableEntityResult +} from "@azure/data-tables"; import { DataTableProfileEmailsRepository } from "../storage"; import { TableClient } from "@azure/data-tables"; @@ -45,12 +49,47 @@ MockedTableClient.prototype.listEntities.mockReturnValue( new MockPagedAsyncIterableIterator() ); +MockedTableClient.prototype.getEntity.mockImplementation( + >( + partitionKey: string, + rowKey: string + ) => + Promise.resolve(({ + "odata.metadata": "odata.metadata", + etag: "etag", + partitionKey, + rowKey, + timestamp: "2024-01-09T09:41:37.7269414Z" + } as unknown) as GetTableEntityResponse>) +); + const tableClient = new MockedTableClient( "https://test.localhost", "test-table" ); describe("DataTableProfileEmailsRepository", () => { + describe("get", () => { + it.each(["citizen@email.test.pagopa.it", "CITIZEN@EMAIL.TEST.PAGOPA.IT"])( + "normalizes input e-mail addresses", + async email => { + const repo = new DataTableProfileEmailsRepository(tableClient); + const profileEmail = ProfileEmail.decode({ + email, + fiscalCode: "RLDBSV36A78Y792X" + }); + if (E.isRight(profileEmail)) { + await repo.get(profileEmail.right); + expect(tableClient.getEntity).toHaveBeenCalledWith( + "citizen@email.test.pagopa.it", + "RLDBSV36A78Y792X" + ); + } + expect.hasAssertions(); + } + ); + }); + describe("list", () => { it("normalizes input e-mail address", async () => { const repo = new DataTableProfileEmailsRepository(tableClient); diff --git a/src/utils/unique_email_enforcement/index.ts b/src/utils/unique_email_enforcement/index.ts index d88d6b3b..8ac8da22 100644 --- a/src/utils/unique_email_enforcement/index.ts +++ b/src/utils/unique_email_enforcement/index.ts @@ -10,6 +10,7 @@ export const ProfileEmail = t.type({ export type ProfileEmail = t.TypeOf; export interface IProfileEmailReader { + readonly get: (p: ProfileEmail) => Promise; readonly list: (filter: EmailString) => AsyncIterableIterator; } diff --git a/src/utils/unique_email_enforcement/storage.ts b/src/utils/unique_email_enforcement/storage.ts index 3a19505b..021fa76d 100644 --- a/src/utils/unique_email_enforcement/storage.ts +++ b/src/utils/unique_email_enforcement/storage.ts @@ -37,6 +37,26 @@ export class DataTableProfileEmailsRepository implements IProfileEmailReader, IProfileEmailWriter { constructor(private readonly tableClient: TableClient) {} + public async get(p: ProfileEmail): Promise { + try { + const entity = await this.tableClient.getEntity( + p.email.toLowerCase(), + p.fiscalCode + ); + const profileEmail = ProfileEmailToTableEntity.decode(entity); + if (E.isLeft(profileEmail)) { + throw new Error(`can't parse a profile email from the given entity`, { + cause: "parsing" + }); + } + return profileEmail.right; + } catch { + throw new Error( + `unable to get a profile entity from ${this.tableClient.tableName} table` + ); + } + } + // Generates an AsyncIterable public async *list(filter: EmailString): AsyncIterableIterator { const queryOptions = {