Skip to content

Commit

Permalink
Merge branch 'dev' into 22465-direct-signin-social
Browse files Browse the repository at this point in the history
  • Loading branch information
alfonsograziano authored Oct 22, 2024
2 parents 0bef242 + e1a6882 commit 1ce8002
Show file tree
Hide file tree
Showing 196 changed files with 18,166 additions and 3,968 deletions.
25 changes: 25 additions & 0 deletions apps/integrator-api/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DB_NAME=integrator
POSTGRES_DB_NAME_SHARED=shared

LOGTO_JWK_ENDPOINT=http://localhost:3301/oidc/jwks
LOGTO_OIDC_ENDPOINT=http://localhost:3301/oidc
LOGTO_API_RESOURCE_INDICATOR=http://localhost:8001/

LOGTO_M2M_PROFILE_APP_ID=ddl4llp30risjwcjymqw3
LOGTO_M2M_PROFILE_APP_SECRET=profile_reader_local_secret

INTEGRATOR_URL=http://localhost:3009/

PAYMENTS_SERVICE_URL=http://localhost:8001/
FORMS_SERVICE_URL=https://www.formsie.dev.gov.ie
FORMS_SECRET_API_KEY=forms_secret_key
FORMS_PUBLIC_API_KEY=form_public_key

AWS_REGION=eu-west-1
KMS_ENDPOINT=http://localhost:4566
AWS_ACCESS_KEY_ID=123
AWS_SECRET_ACCESS_KEY=123
19 changes: 19 additions & 0 deletions apps/integrator-api/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"parser": "@typescript-eslint/parser",
"extends": [
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended",
"eslint:recommended"
],
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module"
},
"rules": {
"no-redeclare": "off"
},
"env": {
"browser": true,
"node": true
}
}
6 changes: 6 additions & 0 deletions apps/integrator-api/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules
.env
.tap

e2e/test-results/
results.xml
66 changes: 66 additions & 0 deletions apps/integrator-api/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
FROM base-deps AS deps
WORKDIR /app

COPY ./package*.json /app/
COPY ./apps/integrator-api/package*.json /app/apps/integrator-api/
COPY ./packages/api-auth/package*.json /app/packages/api-auth/
COPY ./packages/logging-wrapper/package*.json /app/packages/logging-wrapper/
COPY ./packages/error-handler/package*.json /app/packages/error-handler/
COPY ./packages/shared-errors/package*.json /app/packages/shared-errors/
COPY ./packages/building-blocks-sdk/ /app/packages/building-blocks-sdk/

RUN npm ci

COPY ./apps/integrator-api/ /app/apps/integrator-api/
COPY ./packages/logging-wrapper/ /app/packages/logging-wrapper/
COPY ./packages/error-handler/ /app/packages/error-handler/
COPY ./packages/api-auth/ /app/packages/api-auth/
COPY ./packages/shared-errors/ /app/packages/shared-errors/

FROM deps AS builder
WORKDIR /app

RUN npm run build --workspace=packages/shared-errors && \
npm run build --workspace=packages/logging-wrapper && \
npm run build --workspace=packages/error-handler && \
npm run build --workspace=packages/api-auth && \
npm run build --workspace=packages/building-blocks-sdk && \
npm run build --workspace=apps/integrator-api

FROM deps AS assembler
COPY --from=builder /app/package*.json /app/

COPY --from=builder /app/apps/integrator-api/dist /app/apps/integrator-api/dist
COPY --from=builder /app/apps/integrator-api/node_modules /app/apps/integrator-api/node_modules
COPY --from=builder /app/apps/integrator-api/package*.json /app/apps/integrator-api/

COPY --from=builder /app/packages/shared-errors/dist /app/packages/shared-errors/dist
COPY --from=builder /app/packages/shared-errors/node_modules /app/packages/shared-errors/node_modules
COPY --from=builder /app/packages/shared-errors/package.json /app/packages/shared-errors/

COPY --from=builder /app/packages/logging-wrapper/dist /app/packages/logging-wrapper/dist
COPY --from=builder /app/packages/logging-wrapper/node_modules /app/packages/logging-wrapper/node_modules
COPY --from=builder /app/packages/logging-wrapper/package.json /app/packages/logging-wrapper/

COPY --from=builder /app/packages/error-handler/dist /app/packages/error-handler/dist
COPY --from=builder /app/packages/error-handler/package.json /app/packages/error-handler/

COPY --from=builder /app/packages/api-auth/dist /app/packages/api-auth/dist
COPY --from=builder /app/packages/api-auth/node_modules /app/packages/api-auth/node_modules
COPY --from=builder /app/packages/api-auth/package.json /app/packages/api-auth/

COPY --from=builder /app/packages/building-blocks-sdk/dist /app/packages/building-blocks-sdk/dist
COPY --from=builder /app/packages/building-blocks-sdk/node_modules /app/packages/building-blocks-sdk/node_modules
COPY --from=builder /app/packages/building-blocks-sdk/package.json /app/packages/building-blocks-sdk/

RUN npm prune --omit=dev

FROM deps AS runner

COPY --from=assembler /app /app
WORKDIR /app/apps/integrator-api

ENV NODE_ENV=production
ENV LOG_LEVEL=trace
EXPOSE 8009
CMD [ "npx", "ts-node", "dist/", "index.js" ]
148 changes: 148 additions & 0 deletions apps/integrator-api/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import fastify, { FastifyServerOptions } from "fastify";
import routes from "./src/routes";
import fastifyEnv from "@fastify/env";
import fastifyFormBody from "@fastify/formbody";
import postgres from "@fastify/postgres";
import { TypeBoxTypeProvider } from "@fastify/type-provider-typebox";
import dotenv from "dotenv";
import { envSchema } from "./config";
import fastifySwagger from "@fastify/swagger";
import fastifySwaggerUi from "@fastify/swagger-ui";
import fs from "fs";
import { fileURLToPath } from "url";
import { dirname, join } from "path";
import sensible from "@fastify/sensible";
import schemaValidators from "./src/routes/schemas/validations";
import apiAuthPlugin, { createSignedJWT, getJWKS, verifyJWT } from "api-auth";
import { initializeErrorHandler } from "@ogcio/fastify-error-handler";
import { initializeLoggingHooks } from "@ogcio/fastify-logging-wrapper";
import healthCheck from "./src/routes/healthcheck";
import journey from "./src/plugins/entities/journey/index.js";
import journeyStepConnections from "./src/plugins/entities/journeyStepConnections";
import journeySteps from "./src/plugins/entities/journeySteps";
import run from "./src/plugins/entities/run";
import { keyAlias } from "./src/utils/kms";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

dotenv.config();

export async function build(opts?: FastifyServerOptions) {
const app = fastify(opts).withTypeProvider<TypeBoxTypeProvider>();
initializeLoggingHooks(app);
initializeErrorHandler(app);

app.setValidatorCompiler(({ schema }) => {
return schemaValidators(schema);
});

app.register(fastifyEnv, {
schema: envSchema,
dotenv: true,
});

app.register(apiAuthPlugin, {
jwkEndpoint: process.env.LOGTO_JWK_ENDPOINT as string,
oidcEndpoint: process.env.LOGTO_OIDC_ENDPOINT as string,
currentApiResourceIndicator: process.env
.LOGTO_API_RESOURCE_INDICATOR as string,
});

app.register(fastifyFormBody);

app.register(fastifySwagger, {
openapi: {
info: {
title: "OGCIO Integrator API",
description: "API for OGCIO Integrator Service",
version: "0.1.0",
},
tags: [
{
name: "Integrator",
},
],
},
});

app.register(fastifySwaggerUi, {
routePrefix: "/docs",
logo: {
type: "image/png",
content: Buffer.from(
fs.readFileSync(join(__dirname, "logo.png")).toString("base64"),
"base64",
),
},
});

app.register(postgres, {
host: process.env.POSTGRES_HOST,
port: Number(process.env.POSTGRES_PORT),
user: process.env.POSTGRES_USER,
password: process.env.POSTGRES_PASSWORD,
database: process.env.POSTGRES_DB_NAME,
});

app.register(healthCheck);

app.register(routes, { prefix: "/api/v1" });

app.get("/.well-known/jwks.json", async () => {
return getJWKS(keyAlias);
});

// can be used to test
app.get("/token", async (_, reply) => {
const payload = { amount: 70 };

const jwt = await createSignedJWT(payload, keyAlias, {
audience: "payments-api",
issuer: "integrator-api",
});

return reply.code(200).send({ token: jwt });
});

// Test callback route to test communication between systems
app.get("/callback", async (request, reply) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const { token } = request.query as any;

if (!token) {
return reply.code(400).send({ error: "Token not provided" });
}

// We need to store this somehow in an env variable
const jwksRegistry = {
payments: "http://localhost:8001/.well-known/jwks.json",
};

try {
// How to understand what jwks to use? - Most probably by looking at the step id
const jwksUrl = jwksRegistry.payments;
const payload = await verifyJWT(token, {
jwksUrl,
issuer: "payments-api",
audience: "integrator-api",
});

// Send back the payload if the JWT verification is successful
return reply.code(200).send({ status: "success", payload });
} catch (err) {
return reply
.code(401)
.send({ status: "error", message: "Invalid token" });
}
});

app.register(sensible);

app.register(journey);
app.register(journeyStepConnections);
app.register(journeySteps);
app.register(run);

return app;
}
79 changes: 79 additions & 0 deletions apps/integrator-api/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
export const envSchema = {
type: "object",
required: [
"POSTGRES_USER",
"POSTGRES_PASSWORD",
"POSTGRES_HOST",
"POSTGRES_PORT",
"POSTGRES_DB_NAME",
"POSTGRES_DB_NAME_SHARED",
"LOGTO_JWK_ENDPOINT",
"LOGTO_OIDC_ENDPOINT",
"LOGTO_API_RESOURCE_INDICATOR",
"LOGTO_M2M_PROFILE_APP_ID",
"LOGTO_M2M_PROFILE_APP_SECRET",
"PAYMENTS_SERVICE_URL",
"FORMS_SERVICE_URL",
"FORMS_SECRET_API_KEY",
"FORMS_PUBLIC_API_KEY",
"AWS_REGION",
"KMS_ENDPOINT",
"INTEGRATOR_URL",
],
properties: {
POSTGRES_USER: {
type: "string",
},
POSTGRES_PASSWORD: {
type: "string",
},
POSTGRES_HOST: {
type: "string",
},
POSTGRES_PORT: {
type: "string",
},
POSTGRES_DB_NAME: {
type: "string",
},
POSTGRES_DB_NAME_SHARED: {
type: "string",
},
LOGTO_JWK_ENDPOINT: {
type: "string",
},
LOGTO_OIDC_ENDPOINT: {
type: "string",
},
LOGTO_API_RESOURCE_INDICATOR: {
type: "string",
},
LOGTO_M2M_PROFILE_APP_ID: {
type: "string",
},
LOGTO_M2M_PROFILE_APP_SECRET: {
type: "string",
},
PAYMENTS_SERVICE_URL: {
type: "string",
},
FORMS_SERVICE_URL: {
type: "string",
},
FORMS_SECRET_API_KEY: {
type: "string",
},
FORMS_PUBLIC_API_KEY: {
type: "string",
},
AWS_REGION: {
type: "string",
},
KMS_ENDPOINT: {
type: "string",
},
INTEGRATOR_URL: {
type: "string",
},
},
};
36 changes: 36 additions & 0 deletions apps/integrator-api/e2e/Healthcheck.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
meta {
name: Healthcheck
type: http
seq: 1
}

get {
url: {{baseUrl}}/health
body: none
auth: none
}

assert {
res.status: eq 200
res.body.status: eq 'ok'
}

script:pre-request {
//Placeholder for any setup before making the request
}

script:post-response {
//Placeholder for any post response logic
}

tests {
// Allows for more complex tests on the response beyond the basic inbuilt assert library
test("res.status should be 200", function() {
const data = res.getBody();
expect(res.getStatus()).to.equal(200);
});
test("res.body should be correct", function() {
const data = res.getBody();
expect(data.status).to.equal('ok');
});
}
9 changes: 9 additions & 0 deletions apps/integrator-api/e2e/bruno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"version": "1",
"name": "integrator-api",
"type": "collection",
"ignore": [
"node_modules",
".git"
]
}
Loading

0 comments on commit 1ce8002

Please sign in to comment.