Skip to content

Commit

Permalink
IMN-616 BFF Tools router (#976)
Browse files Browse the repository at this point in the history
Co-authored-by: Stefano Hu <[email protected]>
Co-authored-by: Roberto Taglioni <[email protected]>
Co-authored-by: Carmine Porricelli <[email protected]>
  • Loading branch information
4 people authored Oct 11, 2024
1 parent 96aa64e commit f517ccf
Show file tree
Hide file tree
Showing 11 changed files with 546 additions and 21 deletions.
3 changes: 3 additions & 0 deletions packages/backend-for-frontend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ COPY ./packages/commons/package.json /app/packages/commons/package.json
COPY ./packages/models/package.json /app/packages/models/package.json
COPY ./packages/api-clients/package.json /app/packages/api-clients/package.json
COPY ./packages/agreement-lifecycle/package.json /app/packages/agreement-lifecycle/package.json
COPY ./packages/client-assertion-validation/package.json /app/packages/client-assertion-validation/package.json

RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile

Expand All @@ -22,6 +23,7 @@ COPY ./packages/commons /app/packages/commons
COPY ./packages/models /app/packages/models
COPY ./packages/api-clients /app/packages/api-clients
COPY ./packages/agreement-lifecycle /app/packages/agreement-lifecycle
COPY ./packages/client-assertion-validation /app/packages/client-assertion-validation

RUN pnpm build && \
rm -rf /app/node_modules/.modules.yaml && \
Expand All @@ -34,6 +36,7 @@ RUN pnpm build && \
packages/models \
packages/api-clients \
packages/agreement-lifecycle \
packages/client-assertion-validation \
packages/backend-for-frontend/dist && \
find /out -exec touch -h --date=@0 {} \;

Expand Down
1 change: 1 addition & 0 deletions packages/backend-for-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"adm-zip": "0.5.15",
"mime": "4.0.4",
"pagopa-interop-agreement-lifecycle": "workspace:*",
"pagopa-interop-client-assertion-validation": "workspace:*",
"pagopa-interop-api-clients": "workspace:*",
"pagopa-interop-commons": "workspace:*",
"pagopa-interop-models": "workspace:*",
Expand Down
2 changes: 1 addition & 1 deletion packages/backend-for-frontend/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ app.use(
agreementRouter(zodiosCtx, clients, fileManager),
selfcareRouter(clients, zodiosCtx),
supportRouter(zodiosCtx, clients, redisRateLimiter),
toolRouter(zodiosCtx),
toolRouter(zodiosCtx, clients),
tenantRouter(zodiosCtx, clients),
clientRouter(zodiosCtx, clients),
privacyNoticeRouter(zodiosCtx),
Expand Down
4 changes: 4 additions & 0 deletions packages/backend-for-frontend/src/clients/clientsProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export type AuthorizationProcessClient = {
typeof authorizationApi.createProducerKeychainApiClient
>;
user: ReturnType<typeof authorizationApi.createUserApiClient>;
token: ReturnType<typeof authorizationApi.createTokenGenerationApiClient>;
};

export type SelfcareV2Client = {
Expand Down Expand Up @@ -81,6 +82,9 @@ export function getInteropBeClients(): PagoPAInteropBeClients {
config.authorizationUrl
),
user: authorizationApi.createUserApiClient(config.authorizationUrl),
token: authorizationApi.createTokenGenerationApiClient(
config.authorizationUrl
),
},
selfcareV2Client: {
institution: selfcareV2InstitutionClientBuilder(config),
Expand Down
65 changes: 65 additions & 0 deletions packages/backend-for-frontend/src/model/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ export const errorCodes = {
privacyNoticeNotFoundInConfiguration: "0033",
privacyNoticeNotFound: "0034",
privacyNoticeVersionIsNotTheLatest: "0035",
missingActivePurposeVersion: "0036",
activeAgreementByEserviceAndConsumerNotFound: "0037",
purposeIdNotFoundInClientAssertion: "0038",
clientAssertionPublicKeyNotFound: "0049",
organizationNotAllowed: "0040",
cannotGetKeyWithClient: "0041",
};

export type ErrorCodes = keyof typeof errorCodes;
Expand Down Expand Up @@ -352,3 +358,62 @@ export function invalidZipStructure(description: string): ApiError<ErrorCodes> {
title: "Invalid zip structure",
});
}

export function missingActivePurposeVersion(
purposeId: string
): ApiError<ErrorCodes> {
return new ApiError({
detail: `There is no active version for purpose ${purposeId}`,
code: "missingActivePurposeVersion",
title: "Missing active purpose version",
});
}

export function activeAgreementByEserviceAndConsumerNotFound(
eserviceId: string,
consumerId: string
): ApiError<ErrorCodes> {
return new ApiError({
detail: `Active agreement for Eservice ${eserviceId} and consumer ${consumerId} not found`,
code: "activeAgreementByEserviceAndConsumerNotFound",
title: "Active agreement not found",
});
}

export function purposeIdNotFoundInClientAssertion(): ApiError<ErrorCodes> {
return new ApiError({
detail: `PurposeId not found in client assertion`,
code: "purposeIdNotFoundInClientAssertion",
title: "PurposeId not found in client assertion",
});
}

export function clientAssertionPublicKeyNotFound(
kid: string,
clientId: string
): ApiError<ErrorCodes> {
return new ApiError({
detail: `Public key with kid ${kid} not found for client ${clientId}`,
code: "clientAssertionPublicKeyNotFound",
title: "Client assertion public key not found",
});
}

export function organizationNotAllowed(clientId: string): ApiError<ErrorCodes> {
return new ApiError({
detail: `Organization not allowed for client ${clientId}`,
code: "organizationNotAllowed",
title: "Organization not allowed",
});
}

export function cannotGetKeyWithClient(
clientId: string,
keyId: string
): ApiError<ErrorCodes> {
return new ApiError({
detail: `Cannot get key with client ${clientId} and key ${keyId}`,
code: "cannotGetKeyWithClient",
title: "Cannot get key with client",
});
}
39 changes: 34 additions & 5 deletions packages/backend-for-frontend/src/routers/toolRouter.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,51 @@
import { ZodiosEndpointDefinitions } from "@zodios/core";
import { ZodiosRouter } from "@zodios/express";
import { bffApi } from "pagopa-interop-api-clients";
import {
ExpressContext,
ZodiosContext,
zodiosValidationErrorToApiProblem,
} from "pagopa-interop-commons";
import { bffApi } from "pagopa-interop-api-clients";
import { toolsServiceBuilder } from "../services/toolService.js";
import { fromBffAppContext } from "../utilities/context.js";
import { toolsErrorMapper } from "../utilities/errorMappers.js";
import { PagoPAInteropBeClients } from "../clients/clientsProvider.js";
import { makeApiProblem } from "../model/errors.js";

const toolRouter = (
ctx: ZodiosContext
ctx: ZodiosContext,
clients: PagoPAInteropBeClients
): ZodiosRouter<ZodiosEndpointDefinitions, ExpressContext> => {
const toolRouter = ctx.router(bffApi.toolsApi.api, {
validationErrorHandler: zodiosValidationErrorToApiProblem,
});

toolRouter.post("/tools/validateTokenGeneration", async (_req, res) =>
res.status(501).send()
);
const toolsService = toolsServiceBuilder(clients);

toolRouter.post("/tools/validateTokenGeneration", async (req, res) => {
const ctx = fromBffAppContext(req.ctx, req.headers);

try {
const result = await toolsService.validateTokenGeneration(
req.body.client_id,
req.body.client_assertion,
req.body.client_assertion_type,
req.body.grant_type,
ctx
);
return res
.status(200)
.send(bffApi.TokenGenerationValidationResult.parse(result));
} catch (error) {
const errorRes = makeApiProblem(
error,
toolsErrorMapper,
ctx.logger,
"Error validating token generation request"
);
return res.status(errorRes.status).send(errorRes);
}
});

return toolRouter;
};
Expand Down
Loading

0 comments on commit f517ccf

Please sign in to comment.