Skip to content

Commit

Permalink
IMN-563: consumerServiceV2 in client-readmodel-writer (#566)
Browse files Browse the repository at this point in the history
  • Loading branch information
AsterITA authored Jun 21, 2024
1 parent 260dc06 commit 593d207
Show file tree
Hide file tree
Showing 8 changed files with 333 additions and 27 deletions.
9 changes: 7 additions & 2 deletions packages/authorization-updater/test/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import {
writeInReadmodel,
} from "pagopa-interop-commons-test";
import { inject, afterEach } from "vitest";
import { Client, EService, toReadModelEService } from "pagopa-interop-models";
import {
Client,
EService,
toReadModelClient,
toReadModelEService,
} from "pagopa-interop-models";
import { readModelServiceBuilder } from "../src/readModelService.js";

export const { cleanup, readModelRepository } = setupTestContainersVitest(
Expand All @@ -22,5 +27,5 @@ export const addOneEService = async (eservice: EService): Promise<void> => {
};

export const addOneClient = async (client: Client): Promise<void> => {
await writeInReadmodel(client, clients);
await writeInReadmodel(toReadModelClient(client), clients);
};
39 changes: 34 additions & 5 deletions packages/client-readmodel-writer/src/clientConsumerServiceV2.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,51 @@
import { ClientCollection } from "pagopa-interop-commons";
import { AuthorizationEventEnvelopeV2 } from "pagopa-interop-models";
import {
AuthorizationEventEnvelopeV2,
fromClientV2,
toReadModelClient,
} from "pagopa-interop-models";
import { match } from "ts-pattern";

export async function handleMessageV2(
message: AuthorizationEventEnvelopeV2,
_clients: ClientCollection
clients: ClientCollection
): Promise<void> {
match(message)
const client = message.data.client;

await match(message)
.with(
{ type: "ClientAdded" },
{ type: "ClientDeleted" },
{ type: "ClientKeyAdded" },
{ type: "ClientKeyDeleted" },
{ type: "ClientUserAdded" },
{ type: "ClientUserDeleted" },
{ type: "ClientPurposeAdded" },
{ type: "ClientPurposeRemoved" },
() => Promise.resolve
async (message) => {
await clients.updateOne(
{
"data.id": message.stream_id,
"metadata.version": { $lt: message.version },
},
{
$set: {
data: client
? toReadModelClient(fromClientV2(client))
: undefined,
metadata: {
version: message.version,
},
},
},
{ upsert: true }
);
}
)
.with({ type: "ClientDeleted" }, async (message) => {
await clients.deleteOne({
"data.id": message.stream_id,
"metadata.version": { $lt: message.version },
});
})
.exhaustive();
}

This file was deleted.

253 changes: 253 additions & 0 deletions packages/client-readmodel-writer/test/consumerServiceV2.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
import {
getMockClient,
getMockKey,
writeInReadmodel,
} from "pagopa-interop-commons-test/index.js";
import {
AuthorizationEventEnvelopeV2,
Client,
ClientAddedV2,
ClientKeyAddedV2,
ClientKeyDeletedV2,
ClientPurposeAddedV2,
ClientPurposeRemovedV2,
ClientUserAddedV2,
ClientUserDeletedV2,
Key,
PurposeId,
UserId,
generateId,
toClientV2,
toReadModelClient,
} from "pagopa-interop-models";
import { describe, expect, it } from "vitest";
import { handleMessageV2 } from "../src/clientConsumerServiceV2.js";
import { clients } from "./utils.js";

describe("Events V2", async () => {
const mockClient = getMockClient();
const mockMessage: AuthorizationEventEnvelopeV2 = {
event_version: 2,
stream_id: mockClient.id,
version: 1,
sequence_num: 1,
log_date: new Date(),
type: "ClientAdded",
data: {},
};

it("ClientAdded", async () => {
const payload: ClientAddedV2 = {
client: toClientV2(mockClient),
};

const message: AuthorizationEventEnvelopeV2 = {
...mockMessage,
type: "ClientAdded",
data: payload,
};

await handleMessageV2(message, clients);

const retrievedClient = await clients.findOne({
"data.id": mockClient.id,
});

expect(retrievedClient?.data).toEqual(toReadModelClient(mockClient));

expect(retrievedClient?.metadata).toEqual({
version: 1,
});
});

it("ClientKeyAdded", async () => {
await writeInReadmodel(toReadModelClient(mockClient), clients, 1);

const key: Key = getMockKey();
const updatedClient: Client = {
...mockClient,
keys: [key],
};
const payload: ClientKeyAddedV2 = {
client: toClientV2(updatedClient),
kid: key.kid,
};

const message: AuthorizationEventEnvelopeV2 = {
...mockMessage,
type: "ClientKeyAdded",
data: payload,
version: 2,
};

await handleMessageV2(message, clients);

const retrievedClient = await clients.findOne({
"data.id": mockClient.id,
});

expect(retrievedClient?.data).toEqual(toReadModelClient(updatedClient));
expect(retrievedClient?.metadata).toEqual({
version: 2,
});
});

it("ClientKeyDeleted", async () => {
const key: Key = getMockKey();
const client: Client = {
...mockClient,
keys: [key],
};
await writeInReadmodel(toReadModelClient(client), clients, 1);

const updatedClient = mockClient;

const payload: ClientKeyDeletedV2 = {
client: toClientV2(updatedClient),
kid: key.kid,
};

const message: AuthorizationEventEnvelopeV2 = {
...mockMessage,
type: "ClientKeyDeleted",
data: payload,
version: 2,
};

await handleMessageV2(message, clients);

const retrievedClient = await clients.findOne({
"data.id": client.id,
});

expect(retrievedClient?.data.keys).toHaveLength(0);
});

it("ClientUserAdded", async () => {
await writeInReadmodel(toReadModelClient(mockClient), clients, 1);

const userId: UserId = generateId<UserId>();
const updatedClient: Client = {
...mockClient,
users: [userId],
};

const payload: ClientUserAddedV2 = {
client: toClientV2(updatedClient),
userId,
};

const message: AuthorizationEventEnvelopeV2 = {
...mockMessage,
type: "ClientUserAdded",
data: payload,
version: 2,
};

await handleMessageV2(message, clients);

const retrievedClient = await clients.findOne({
"data.id": updatedClient.id,
});

expect(retrievedClient?.data).toEqual(toReadModelClient(updatedClient));
expect(retrievedClient?.metadata).toEqual({
version: 2,
});
});

it("ClientUserDeleted", async () => {
const userId: UserId = generateId<UserId>();
const client: Client = {
...mockClient,
users: [userId],
};
await writeInReadmodel(toReadModelClient(client), clients, 1);

const updatedClient = mockClient;

const payload: ClientUserDeletedV2 = {
client: toClientV2(updatedClient),
userId,
};

const message: AuthorizationEventEnvelopeV2 = {
...mockMessage,
type: "ClientUserDeleted",
data: payload,
version: 2,
};

await handleMessageV2(message, clients);

const retrievedClient = await clients.findOne({
"data.id": client.id,
});

expect(retrievedClient?.data.users).toHaveLength(0);
});

it("ClientPurposeAdded", async () => {
await writeInReadmodel(toReadModelClient(mockClient), clients, 1);

const purposeId: PurposeId = generateId<PurposeId>();
const updatedClient: Client = {
...mockClient,
purposes: [purposeId],
};

const payload: ClientPurposeAddedV2 = {
client: toClientV2(updatedClient),
purposeId,
};

const message: AuthorizationEventEnvelopeV2 = {
...mockMessage,
type: "ClientPurposeAdded",
data: payload,
version: 2,
};

await handleMessageV2(message, clients);

const retrievedClient = await clients.findOne({
"data.id": updatedClient.id,
});

expect(retrievedClient?.data).toEqual(toReadModelClient(updatedClient));
expect(retrievedClient?.metadata).toEqual({
version: 2,
});
});

it("ClientPurposeRemoved", async () => {
const purposeId: PurposeId = generateId<PurposeId>();
const client: Client = {
...mockClient,
purposes: [purposeId],
};
await writeInReadmodel(toReadModelClient(client), clients, 1);

const updatedClient = mockClient;

const payload: ClientPurposeRemovedV2 = {
client: toClientV2(updatedClient),
purposeId,
};

const message: AuthorizationEventEnvelopeV2 = {
...mockMessage,
type: "ClientPurposeRemoved",
data: payload,
version: 2,
};

await handleMessageV2(message, clients);

const retrievedClient = await clients.findOne({
"data.id": client.id,
});

expect(retrievedClient?.data.purposes).toHaveLength(0);
});
});
8 changes: 4 additions & 4 deletions packages/commons/src/repositories/ReadModelRepository.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {
AgreementReadModel,
AttributeReadmodel,
Client,
ClientReadModel,
EServiceReadModel,
Key,
KeyReadModel,
PurposeReadModel,
Tenant,
genericInternalError,
Expand Down Expand Up @@ -36,8 +36,8 @@ export type AgreementCollection = GenericCollection<AgreementReadModel>;
export type TenantCollection = GenericCollection<Tenant>;
export type AttributeCollection = GenericCollection<AttributeReadmodel>;
export type PurposeCollection = GenericCollection<PurposeReadModel>;
export type ClientCollection = GenericCollection<Client>;
export type KeyCollection = GenericCollection<Key>;
export type ClientCollection = GenericCollection<ClientReadModel>;
export type KeyCollection = GenericCollection<KeyReadModel>;

export type Collections =
| EServiceCollection
Expand Down
17 changes: 17 additions & 0 deletions packages/models/src/authorization/authorizationReadModelAdapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {
ClientReadModel,
KeyReadModel,
} from "../read-models/authorizationReadModel.js";
import { Client } from "./client.js";
import { Key } from "./key.js";

export const toReadModelKey = (key: Key): KeyReadModel => ({
...key,
createdAt: key.createdAt.toISOString(),
});

export const toReadModelClient = (client: Client): ClientReadModel => ({
...client,
createdAt: client.createdAt.toISOString(),
keys: client.keys.map(toReadModelKey),
});
Loading

0 comments on commit 593d207

Please sign in to comment.