Skip to content

Commit

Permalink
Bruke common server i opplæringspenger
Browse files Browse the repository at this point in the history
  • Loading branch information
frodehansen2 committed Oct 5, 2024
1 parent a7b617b commit 2895ce2
Show file tree
Hide file tree
Showing 35 changed files with 288 additions and 499 deletions.
19 changes: 12 additions & 7 deletions apps/opplaringspenger-soknad/.env.example
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
API_URL=http://localhost:8089
APPSTATUS_DATASET=staging
APPSTATUS_PROJECT_ID=ryujtq87
DEKORATOR_URL=https://www.nav.no/dekoratoren/?simple=true&chatbot=false&logoutUrl=https://www.nav.no/familie/sykdom-i-familien/soknad/opplaringspenger/oauth2/logout
FRONTEND_API_PATH=http://localhost:8089/familie/sykdom-i-familien/soknad/opplaringspenger
LOGIN_URL=http://localhost:8081/auth-mock/cookie?subject=mockSubject&redirect_location=http://localhost:8080

APP_VERSION=dev
NODE_ENV=development
PUBLIC_PATH=/familie/sykdom-i-familien/soknad/opplaringspenger
SKIP_ORGNUM_VALIDATION=true
GITHUB_REF_NAME=branch-name

SIF_PUBLIC_APPSTATUS_DATASET=staging
SIF_PUBLIC_APPSTATUS_PROJECT_ID=ryujtq87
SIF_PUBLIC_DEKORATOR_URL=https://www.nav.no/dekoratoren/?simple=true&chatbot=false&logoutUrl=https://www.nav.no/familie/sykdom-i-familien/soknad/opplaringspenger/oauth2/logout
SIF_PUBLIC_LOGIN_URL=http://localhost:8081/auth-mock/cookie?subject=mockSubject&redirect_location=http://localhost:8080

K9_BRUKERDIALOG_PROSESSERING_FRONTEND_PATH=/familie/sykdom-i-familien/soknad/opplaringspenger/api
K9_BRUKERDIALOG_PROSESSERING_API_SCOPE=dev-gcp:dusseldorf:k9-brukerdialog-prosessering
K9_BRUKERDIALOG_PROSESSERING_API_URL=http://k9-brukerdialog-prosessering
8 changes: 1 addition & 7 deletions apps/opplaringspenger-soknad/.storybook/preview-head.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
<script>
window.appSettings = {
DEKORATOR_URL: 'https://www.nav.no/dekoratoren/?simple=true&chatbot=false',
LOGIN_URL: 'http://localhost:8089/login',
API_URL: 'http://localhost:8089',
PUBLIC_PATH: '/familie/sykdom-i-familien/soknad/{SIF_SOKNAD_TEMPLATE}',
APPSTATUS_PROJECT_ID: 'ryujtq87',
APPSTATUS_DATASET: 'staging',
APP_VERSION: 'dev',
K9_BRUKERDIALOG_PROSESSERING_FRONTEND_PATH: '/familie/sykdom-i-familien/soknad/opplaringspenger/api/k9-brukerdialog',
};
</script>
96 changes: 70 additions & 26 deletions apps/opplaringspenger-soknad/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,35 +1,79 @@

FROM node:18-alpine AS base
RUN apk update && apk add git
RUN apk add --no-cache libc6-compat
FROM node:20.12-alpine AS base

ENV APP="opplaringspenger-soknad"
ENV SERVER="server"
ENV SCOPE=@navikt/opplaringspenger-soknad

RUN apk fix \
&& apk add --no-cache --update libc6-compat tini \
&& rm -rf /var/cache/apk/*

RUN yarn global add turbo

#########################################
# PREPARE DEPS FOR BUILD
#########################################

FROM base AS prepare
WORKDIR /app
COPY ["package.json", ".yarnrc.yml", "yarn.lock", "turbo.json", "./"]
COPY [".yarn/releases/*", ".yarn/releases/"]
COPY packages packages
COPY apps apps
ARG SERVER
COPY ${SERVER} ${SERVER}
RUN find apps \! -name "package.json" -mindepth 2 -maxdepth 2 -print | xargs rm -rf
RUN find packages \! -name "package.json" -mindepth 2 -maxdepth 2 -print | xargs rm -rf
RUN find ${SERVER} \! -name "package.json" -mindepth 2 -maxdepth 2 -print | xargs rm -rf

ENV SCOPE=@navikt/opplaringspenger-soknad
#########################################
# BUILDER IMAGE - INSTALL PACKAGES AND COPY SOURCE
#########################################

FROM base AS turbo-builder
FROM prepare AS installer
COPY --from=prepare /app ./
RUN --mount=type=secret,id=PACKAGES_AUTH_TOKEN \
PACKAGES_AUTH_TOKEN=$(cat /run/secrets/PACKAGES_AUTH_TOKEN) yarn
COPY . .
RUN yarn
RUN yarn turbo run build --filter=${SCOPE}

FROM base AS ws-installer
RUN apk update && apk add git
RUN apk add --no-cache libc6-compat
WORKDIR /app-ws
COPY . .
RUN yarn workspaces focus ${SCOPE} --production

FROM gcr.io/distroless/nodejs18-debian11:nonroot
WORKDIR /apps/opplaringspenger-soknad
COPY --from=ws-installer /app-ws/node_modules ./node_modules/
COPY --from=turbo-builder /app/apps/opplaringspenger-soknad/server.cjs .
COPY --from=turbo-builder /app/apps/opplaringspenger-soknad/tokenx.cjs .
COPY --from=turbo-builder /app/apps/opplaringspenger-soknad/package.json .
COPY --from=turbo-builder /app/apps/opplaringspenger-soknad/src/build/decorator.cjs ./src/build/decorator.cjs
COPY --from=turbo-builder /app/apps/opplaringspenger-soknad/src/build/AppSettings.cjs ./src/build/AppSettings.cjs
COPY --from=turbo-builder /app/apps/opplaringspenger-soknad/dist ./dist

EXPOSE 8080
CMD ["server.cjs"]
#########################################
# BUILD SERVER
#########################################

FROM installer AS server-build
ARG SERVER
WORKDIR /app/${SERVER}
RUN --mount=type=secret,id=PACKAGES_AUTH_TOKEN \
PACKAGES_AUTH_TOKEN=$(cat /run/secrets/PACKAGES_AUTH_TOKEN) yarn build


#########################################
# Client
#########################################

FROM installer AS client-build
WORKDIR /app
RUN --mount=type=secret,id=PACKAGES_AUTH_TOKEN \
PACKAGES_AUTH_TOKEN=$(cat /run/secrets/PACKAGES_AUTH_TOKEN) yarn turbo run build --filter=${SCOPE}
RUN mv /app/apps/${APP}/dist /public


#########################################
# Server
#########################################
FROM base AS server
ARG SERVER
WORKDIR /app
COPY --from=server-build /app/${SERVER}/dist ./
ENTRYPOINT ["/sbin/tini", "--"]

#########################################
# App
#########################################
FROM server

COPY --from=client-build /public ./public

CMD ["node", "index.js"]

108 changes: 108 additions & 0 deletions apps/opplaringspenger-soknad/dev-server.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
const { createProxyMiddleware, fixRequestBody } = require('http-proxy-middleware');
const getAppSettings = require('./mock/AppSettings.cjs');
const { injectDecoratorServerSide } = require('@navikt/nav-dekoratoren-moduler/ssr/index.js');
const express = require('express');
const server = express();
server.use(express.json());
const path = require('path');
const mustacheExpress = require('mustache-express');
const compression = require('compression');

server.disable('x-powered-by');

server.use(compression());

require('dotenv').config();
server.set('views', `${__dirname}`);
server.set('view engine', 'mustache');
server.engine('html', mustacheExpress());

server.use((req, res, next) => {
res.removeHeader('X-Powered-By');
res.set('X-Frame-Options', 'SAMEORIGIN');
res.set('X-XSS-Protection', '1; mode=block');
res.set('X-Content-Type-Options', 'nosniff');
res.set('Referrer-Policy', 'no-referrer');
res.set('Feature-Policy', "geolocation 'none'; microphone 'none'; camera 'none'");
next();
});

async function injectDecorator(filePath) {
return injectDecoratorServerSide({
env: 'dev',
filePath,
params: {
enforceLogin: false,
simple: true,
},
});
}

const startServer = async () => {
server.get('/health/isAlive', (req, res) => res.sendStatus(200));
server.get('/health/isReady', (req, res) => res.sendStatus(200));

const indexHtmlPath = path.resolve(__dirname, 'index.html');

const htmlWithDecoratorInjected = await injectDecorator(indexHtmlPath);

const renderedHtml = htmlWithDecoratorInjected.replaceAll(
'{{{APP_SETTINGS}}}',
JSON.stringify({
APP_VERSION: `${process.env.APP_VERSION}`,
PUBLIC_PATH: `${process.env.PUBLIC_PATH}`,
...getAppSettings(),
}),
);

server.use(
`${process.env.PUBLIC_PATH}/api/k9-brukerdialog`,
// limiter,
createProxyMiddleware({
target: 'http://localhost:8089/',
changeOrigin: true,
logger: console,
on: {
proxyReq: fixRequestBody,
},
}),
);

const fs = require('fs');
fs.writeFileSync(path.resolve(__dirname, 'index-decorated.html'), renderedHtml);

const vite = await require('vite').createServer({
root: __dirname,
server: {
middlewareMode: true,
port: 8080,
open: './index-decorated.html',
},
});

server.get(/^\/(?!.*dist).*$/, (req, res, next) => {
const ROOT_DIR = path.resolve(__dirname);
const fullPath = path.resolve(ROOT_DIR, decodeURIComponent(req.path.substring(1)));

if (!fullPath.startsWith(ROOT_DIR)) {
res.status(403).send('Forbidden');
return;
}

const fileExists = fs.existsSync(fullPath);

if ((!fileExists && !req.url.startsWith('/@')) || req.url === '/') {
req.url = '/index-decorated.html';
}
next();
});

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
a file system access
, but is not rate-limited.

server.use(vite.middlewares);

const port = process.env.PORT || 8080;
server.listen(port, () => {
console.log(`App listening on port: ${port}`);
});
};

startServer();
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const decoratorParams = new URLSearchParams({

const getDecorator = (appSettings) =>
new Promise((resolve, reject) => {
fetch(`${process.env.DEKORATOR_URL}`, decoratorParams)
fetch(`${process.env.SIF_PUBLIC_DEKORATOR_URL}`, decoratorParams)
.then((response) => response.text())
.then((html) => {
if (html) {
Expand Down
105 changes: 0 additions & 105 deletions apps/opplaringspenger-soknad/e2e/server/mock-decorator.html

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ const express = require('express');
const server = express();
const path = require('path');
const mustacheExpress = require('mustache-express');
const getAppSettings = require('./src/build/AppSettings.cjs');
const getDecorator = require('./src/build/decorator.cjs');
const getAppSettings = require('../../mock/AppSettings.cjs');
const getDecorator = require('./decorator.cjs');
const compression = require('compression');

require('dotenv').config();
Expand All @@ -13,7 +13,7 @@ server.use(express.json());
server.disable('x-powered-by');
server.use(compression());

server.set('views', path.resolve(`${__dirname}/dist`));
server.set('views', path.resolve(`${__dirname}/../../dist`));

server.set('view engine', 'mustache');
server.engine('html', mustacheExpress());
Expand Down Expand Up @@ -43,7 +43,7 @@ const startServer = async (html) => {
console.log(process.env.PUBLIC_PATH);
server.get(`${process.env.PUBLIC_PATH}/health/isAlive`, (_req, res) => res.sendStatus(200));
server.get(`${process.env.PUBLIC_PATH}/health/isReady`, (_req, res) => res.sendStatus(200));
server.use(`${process.env.PUBLIC_PATH}/assets`, express.static(path.resolve(__dirname, 'dist/assets')));
server.use(`${process.env.PUBLIC_PATH}/assets`, express.static(path.resolve(__dirname, '../../dist/assets')));

server.get(/^\/(?!.*api)(?!.*dist).*$/, (req, res) => {
res.send(html);
Expand Down
Loading

0 comments on commit 2895ce2

Please sign in to comment.