From ecc428f65eb7fceda23b4bc3fac5692de895206f Mon Sep 17 00:00:00 2001 From: npham49 Date: Thu, 31 Oct 2024 10:10:35 -0700 Subject: [PATCH 01/46] fixes for building --- client/src/router.ts | 2 +- client/src/services/interceptors.ts | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/src/router.ts b/client/src/router.ts index 1a70f42..7f5e0ad 100644 --- a/client/src/router.ts +++ b/client/src/router.ts @@ -58,7 +58,7 @@ const router = createRouter({ routes, }); -router.beforeEach(async (to, from, next) => { +router.beforeEach(async (to, _from, next) => { NProgress.start(); let destination = ""; diff --git a/client/src/services/interceptors.ts b/client/src/services/interceptors.ts index e69c32d..23c9a8f 100644 --- a/client/src/services/interceptors.ts +++ b/client/src/services/interceptors.ts @@ -9,11 +9,11 @@ import { useAuthStore } from "../stores/authStore"; // Axios serializes query params and encodes spaces with '+' // Some external APIs may require spaces to be encoded with '%20 instead -const paramRegex = /\+/g; -const paramsSerializer = { - encode: (param: string) => - encodeURIComponent(param).replace(paramRegex, "%20"), -}; +// const paramRegex = /\+/g; +// const paramsSerializer = { +// encode: (param: string) => +// encodeURIComponent(param).replace(paramRegex, "%20"), +// }; /** * @function apiAxios From 0b94d4e90a8265b9372e41af9186fde0c5584fd0 Mon Sep 17 00:00:00 2001 From: npham49 Date: Thu, 31 Oct 2024 10:16:08 -0700 Subject: [PATCH 02/46] moving init to inside renderApp --- client/src/main.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/src/main.ts b/client/src/main.ts index bfc3ba7..cd5818d 100644 --- a/client/src/main.ts +++ b/client/src/main.ts @@ -17,9 +17,8 @@ const pinia = createPinia(); // Use persisted state with Pinia so our store data will persist even after page refresh pinia.use(piniaPluginPersistedstate); -await KeycloakService.CallInit(); - -const renderApp = () => { +const renderApp = async () => { + await KeycloakService.CallInit(); createApp(App) .use(AuthStorePlugin, { pinia }) .use(pinia) From 4bb5da5c3a2cdc5502c38a22558f976bbee1b979 Mon Sep 17 00:00:00 2001 From: npham49 Date: Thu, 31 Oct 2024 10:21:20 -0700 Subject: [PATCH 03/46] adding dockerfile for server --- server/Dockerfile | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 server/Dockerfile diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 0000000..e409143 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,25 @@ +# dockerfile for an image with the admin api, express deployment +FROM node:lts-alpine3.16 +ENV NODE_ENV production + +RUN mkdir -p /usr/src/app + +# Create app directory +WORKDIR /usr/src/app + +# Copy package.json +COPY package*.json ./ +COPY tsconfig.json ./ + +# Copy all files +COPY . . + +# Install dependencies +RUN npm install --omit=dev +RUN npm run build + +# Expose port 8080 +EXPOSE 8080 + +# Run app +CMD [ "node","dist/app.js" ] \ No newline at end of file From 156dae55a2406b3ba3cc24adaf7ba1061bf52635 Mon Sep 17 00:00:00 2001 From: npham49 Date: Thu, 31 Oct 2024 10:29:39 -0700 Subject: [PATCH 04/46] redoing pckage.json for build process --- server/package.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/server/package.json b/server/package.json index 34b119c..375d8b9 100644 --- a/server/package.json +++ b/server/package.json @@ -13,6 +13,10 @@ "license": "ISC", "description": "", "dependencies": { + "@types/cors": "^2.8.17", + "@types/express": "^4.17.21", + "@types/morgan": "^1.9.9", + "@types/multer": "^1.4.12", "@aws-sdk/client-s3": "^3.679.0", "axios": "^1.7.7", "cors": "^2.8.5", @@ -20,19 +24,15 @@ "express": "^4.21.0", "helmet": "^7.1.0", "jose": "^5.9.3", + "@types/xlsx-populate": "git+https://github.com/JanLoebel/types-xlsx-populate.git", "morgan": "^1.10.0", "multer": "^1.4.5-lts.1", - "xlsx-populate": "^1.21.0" + "xlsx-populate": "^1.21.0", + "ts-node": "^10.9.2", + "typescript": "^5.6.2" }, "devDependencies": { - "@types/cors": "^2.8.17", - "@types/express": "^4.17.21", - "@types/morgan": "^1.9.9", - "@types/multer": "^1.4.12", - "@types/xlsx-populate": "git+https://github.com/JanLoebel/types-xlsx-populate.git", "nodemon": "^3.1.6", - "prettier": "^3.3.3", - "ts-node": "^10.9.2", - "typescript": "^5.6.2" + "prettier": "^3.3.3" } } From 4fa98a931aaea9669a08bf82e2c92b077990a9c0 Mon Sep 17 00:00:00 2001 From: npham49 Date: Thu, 31 Oct 2024 11:45:56 -0700 Subject: [PATCH 05/46] switching to nginx --- client/.dockerignore | 2 ++ client/Dockerfile | 43 +++++++++---------------------------------- client/nginx.conf | 30 ++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 34 deletions(-) create mode 100644 client/.dockerignore create mode 100644 client/nginx.conf diff --git a/client/.dockerignore b/client/.dockerignore new file mode 100644 index 0000000..569ce53 --- /dev/null +++ b/client/.dockerignore @@ -0,0 +1,2 @@ +**/node_modules +**/dist \ No newline at end of file diff --git a/client/Dockerfile b/client/Dockerfile index 86a9812..3ae7149 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -1,38 +1,13 @@ -# Stage 1: Build the application -FROM node:lts-alpine AS builder - -# Set the working directory inside the container +FROM node:latest as build-stage WORKDIR /app - -# Copy package.json and package-lock.json to the working directory COPY package*.json ./ - -# Install dependencies -RUN npm ci - -# Copy the rest of the application code to the working directory -COPY . . - -# Build the application +RUN npm install +COPY ./ . RUN npm run build -# Stage 2: Serve the application -FROM node:lts-alpine - -# Install http-server globally to serve static files -RUN npm install -g http-server - -# Set the working directory inside the container -WORKDIR /app - -# Copy the built files from the previous stage -COPY --from=builder /app/dist ./dist - -# Copy index.html to 404 to fix client side routing -COPY --from=builder /app/dist/index.html ./dist/404.html - -# Expose port 5173 to the outside world -EXPOSE 5173 - -# Command to run http-server to serve the built files -CMD ["http-server", "dist", "-p", "5173", "--history-api-fallback"] +FROM nginx as production-stage +COPY nginx.conf /etc/nginx/nginx.conf +RUN mkdir /app +COPY --from=build-stage /app/dist /app +EXPOSE 5173:5173 +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/client/nginx.conf b/client/nginx.conf new file mode 100644 index 0000000..fbf5f93 --- /dev/null +++ b/client/nginx.conf @@ -0,0 +1,30 @@ +user nginx; +worker_processes 1; +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; +events { + worker_connections 1024; +} +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + access_log /var/log/nginx/access.log main; + sendfile on; + keepalive_timeout 65; + server { + listen 5173; + server_name localhost; + location / { + root /app; + index index.html; + try_files $uri $uri/ /index.html; + } + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + } +} \ No newline at end of file From f6cc6ab8e4029b9deb996dc435bc9769e916f1d9 Mon Sep 17 00:00:00 2001 From: npham49 Date: Thu, 31 Oct 2024 11:54:44 -0700 Subject: [PATCH 06/46] switching to unprivilleged image --- client/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/Dockerfile b/client/Dockerfile index 3ae7149..1b42fc5 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -5,7 +5,7 @@ RUN npm install COPY ./ . RUN npm run build -FROM nginx as production-stage +FROM nginx-unprivileged:stable-alpine as production-stage COPY nginx.conf /etc/nginx/nginx.conf RUN mkdir /app COPY --from=build-stage /app/dist /app From 978a60dab2b82df653b36d49713fd32055b35d06 Mon Sep 17 00:00:00 2001 From: npham49 Date: Thu, 31 Oct 2024 11:55:54 -0700 Subject: [PATCH 07/46] switching to unprivilleged image --- client/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/Dockerfile b/client/Dockerfile index 1b42fc5..7deef54 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -5,7 +5,7 @@ RUN npm install COPY ./ . RUN npm run build -FROM nginx-unprivileged:stable-alpine as production-stage +FROM nginxinc/nginx-unprivileged:stable-alpine as production-stage COPY nginx.conf /etc/nginx/nginx.conf RUN mkdir /app COPY --from=build-stage /app/dist /app From c266cba1753f7e5ee6f4ccaf03236e8d7ba1f4f7 Mon Sep 17 00:00:00 2001 From: npham49 Date: Thu, 31 Oct 2024 12:02:21 -0700 Subject: [PATCH 08/46] switching to unprivilleged image --- client/Dockerfile | 6 +++--- client/nginx.conf | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/Dockerfile b/client/Dockerfile index 7deef54..d926708 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -6,8 +6,8 @@ COPY ./ . RUN npm run build FROM nginxinc/nginx-unprivileged:stable-alpine as production-stage -COPY nginx.conf /etc/nginx/nginx.conf -RUN mkdir /app -COPY --from=build-stage /app/dist /app +ENV NODE_ENV production +COPY nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=build-stage /app/dist /usr/share/nginx/html EXPOSE 5173:5173 CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/client/nginx.conf b/client/nginx.conf index fbf5f93..758aec8 100644 --- a/client/nginx.conf +++ b/client/nginx.conf @@ -18,7 +18,7 @@ http { listen 5173; server_name localhost; location / { - root /app; + root /usr/share/nginx/html/; index index.html; try_files $uri $uri/ /index.html; } From 5e7da7f200c148ad9f06953568a65e3afe10bf9f Mon Sep 17 00:00:00 2001 From: npham49 Date: Thu, 31 Oct 2024 12:08:27 -0700 Subject: [PATCH 09/46] updating nginx config file --- client/nginx.conf | 55 +++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/client/nginx.conf b/client/nginx.conf index 758aec8..0f52cde 100644 --- a/client/nginx.conf +++ b/client/nginx.conf @@ -1,30 +1,29 @@ -user nginx; -worker_processes 1; -error_log /var/log/nginx/error.log warn; -pid /var/run/nginx.pid; -events { - worker_connections 1024; -} -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - access_log /var/log/nginx/access.log main; - sendfile on; - keepalive_timeout 65; - server { - listen 5173; - server_name localhost; - location / { - root /usr/share/nginx/html/; - index index.html; - try_files $uri $uri/ /index.html; - } - error_page 500 502 503 504 /50x.html; - location = /50x.html { - root /usr/share/nginx/html; - } +server { + # Enable HTTP Strict Transport Security (HSTS) to force clients to always + # connect via HTTPS (do not use if only testing) + add_header Strict-Transport-Security "max-age=31536000;"; + + # Enable cross-site filter (XSS) and tell browser to block detected attacks + add_header X-XSS-Protection "1; mode=block"; + + # Prevent some browsers from MIME-sniffing a response away from the declared Content-Type + add_header X-Content-Type-Options "nosniff"; + + # Disallow the site to be rendered within a frame (clickjacking protection) + add_header X-Frame-Options "DENY"; + + # Turn off all caddy caching + add_header Cache-Control "no-cache,no-store,must-revalidate"; + add_header Pragma "no-cache"; + listen 5173; + server_name localhost; + location / { + root /usr/share/nginx/html/; + index index.html; + try_files $uri $uri/ /index.html; + } + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; } } \ No newline at end of file From ee4284b5516d13ef351fb05e490acd366883da2a Mon Sep 17 00:00:00 2001 From: npham49 Date: Thu, 31 Oct 2024 12:22:13 -0700 Subject: [PATCH 10/46] removing basepath in vite config --- client/nginx.conf | 6 ++++-- client/vite.config.ts | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/client/nginx.conf b/client/nginx.conf index 0f52cde..b6f4af4 100644 --- a/client/nginx.conf +++ b/client/nginx.conf @@ -19,11 +19,13 @@ server { server_name localhost; location / { root /usr/share/nginx/html/; + include /etc/nginx/mime.types; index index.html; try_files $uri $uri/ /index.html; } error_page 500 502 503 504 /50x.html; - location = /50x.html { - root /usr/share/nginx/html; + location @index { + expires 0; + try_files /index.html =404; } } \ No newline at end of file diff --git a/client/vite.config.ts b/client/vite.config.ts index 70630bd..c90547b 100644 --- a/client/vite.config.ts +++ b/client/vite.config.ts @@ -5,7 +5,6 @@ import path from "node:path"; // https://vitejs.dev/config/ export default defineConfig({ plugins: [vue()], - base: "/app", resolve: { alias: { "@": path.resolve(__dirname, "./src"), From ba9aab86fd7e4af54931bf2f45653126e029fcc0 Mon Sep 17 00:00:00 2001 From: npham49 Date: Thu, 31 Oct 2024 12:49:38 -0700 Subject: [PATCH 11/46] updated to the correct index file --- server/Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/Dockerfile b/server/Dockerfile index e409143..32967ad 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -1,4 +1,3 @@ -# dockerfile for an image with the admin api, express deployment FROM node:lts-alpine3.16 ENV NODE_ENV production @@ -22,4 +21,4 @@ RUN npm run build EXPOSE 8080 # Run app -CMD [ "node","dist/app.js" ] \ No newline at end of file +CMD [ "node","dist/index.js" ] \ No newline at end of file From 3e9fea361432201265d934f60c775ab401284384 Mon Sep 17 00:00:00 2001 From: npham49 Date: Thu, 31 Oct 2024 14:46:14 -0700 Subject: [PATCH 12/46] added fix for bceid users --- server/api/components/rlsService.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/api/components/rlsService.ts b/server/api/components/rlsService.ts index 37764fc..9322090 100644 --- a/server/api/components/rlsService.ts +++ b/server/api/components/rlsService.ts @@ -33,6 +33,7 @@ export const getRLSRole = async (payload: any) => { const roleFormId = env.RLS_ROLE_FORM_ID; const apiKey = env.RLS_API_KEY || ""; try { + const user_guid = payload.idir_user_guid || payload.bceid_user_guid; // TODO: Move to Axios for consistency, currently only fetch works // axios would throw an error saying too many redirects const response = await fetch(`${apiUrl}?extFormId=${roleFormId}`, { @@ -40,7 +41,7 @@ export const getRLSRole = async (payload: any) => { Connection: "keep-alive", apiKey: apiKey, Application: "application/json", - "x-chefs-user-userid": payload.idir_user_guid, + "x-chefs-user-userid": user_guid, }, }) .then((res) => res.json()) From f47209a079e1dc8a738e7c0afea79eae278879d4 Mon Sep 17 00:00:00 2001 From: npham49 Date: Thu, 31 Oct 2024 16:43:14 -0700 Subject: [PATCH 13/46] replaced user GUID in RLS calls --- server/api/components/rlsService.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server/api/components/rlsService.ts b/server/api/components/rlsService.ts index 9322090..a81f602 100644 --- a/server/api/components/rlsService.ts +++ b/server/api/components/rlsService.ts @@ -6,6 +6,8 @@ export const getRLSHealthAuthorityHierarchy = async (payload: any) => { const apiKey = process.env.RLS_API_KEY || ""; try { console.log(payload); + const userGuid = payload.idir_user_guid || payload.bceid_user_guid; + // TODO: Move to Axios for consistency, currently only fetch works // axios would throw an error saying too many redirects const response = await fetch(`${apiUrl}?extFormId=${haFormId}`, { @@ -33,7 +35,7 @@ export const getRLSRole = async (payload: any) => { const roleFormId = env.RLS_ROLE_FORM_ID; const apiKey = env.RLS_API_KEY || ""; try { - const user_guid = payload.idir_user_guid || payload.bceid_user_guid; + const userGuid = payload.idir_user_guid || payload.bceid_user_guid; // TODO: Move to Axios for consistency, currently only fetch works // axios would throw an error saying too many redirects const response = await fetch(`${apiUrl}?extFormId=${roleFormId}`, { @@ -41,7 +43,7 @@ export const getRLSRole = async (payload: any) => { Connection: "keep-alive", apiKey: apiKey, Application: "application/json", - "x-chefs-user-userid": user_guid, + "x-chefs-user-userid": userGuid, }, }) .then((res) => res.json()) From 24610c5855ee470f7b387a21df7d37a2fab80928 Mon Sep 17 00:00:00 2001 From: npham49 Date: Thu, 31 Oct 2024 16:45:34 -0700 Subject: [PATCH 14/46] switched to using env instead of process.env --- server/api/components/rlsService.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/api/components/rlsService.ts b/server/api/components/rlsService.ts index a81f602..872bb56 100644 --- a/server/api/components/rlsService.ts +++ b/server/api/components/rlsService.ts @@ -1,9 +1,9 @@ import env from "../utils/env"; export const getRLSHealthAuthorityHierarchy = async (payload: any) => { - const apiUrl = process.env.RLS_API_URL; - const haFormId = process.env.RLS_HA_FORM_ID; - const apiKey = process.env.RLS_API_KEY || ""; + const apiUrl = env.RLS_API_URL; + const haFormId = env.RLS_HA_FORM_ID; + const apiKey = env.RLS_API_KEY || ""; try { console.log(payload); const userGuid = payload.idir_user_guid || payload.bceid_user_guid; @@ -15,7 +15,7 @@ export const getRLSHealthAuthorityHierarchy = async (payload: any) => { Connection: "keep-alive", apiKey: apiKey, Application: "application/json", - "x-chefs-user-userid": payload.idir_user_guid, + "x-chefs-user-userid": userGuid, }, }) .then((res) => res.json()) From 60c40473ac6a916d57aa8fa3cde313049a9b44e9 Mon Sep 17 00:00:00 2001 From: npham49 Date: Thu, 31 Oct 2024 20:57:29 -0700 Subject: [PATCH 15/46] updated preview logic for templates and added conditional UI elements --- client/index.html | 4 +-- client/src/assets/{images => }/bc_logo.svg | 0 .../src/assets/{images => }/bc_logo_print.svg | 0 .../assets/{images => }/bc_logo_square.svg | 0 client/src/components/Form.vue | 21 ++++++----- client/src/components/ReplaceTemplate.vue | 35 +++++++++++++++++-- client/src/components/bcgov/Header.vue | 4 +-- client/src/services/apiService.ts | 5 +++ server/api/replace-template/controller.ts | 17 ++++----- server/api/utils/s3.ts | 1 - 10 files changed, 60 insertions(+), 27 deletions(-) rename client/src/assets/{images => }/bc_logo.svg (100%) rename client/src/assets/{images => }/bc_logo_print.svg (100%) rename client/src/assets/{images => }/bc_logo_square.svg (100%) diff --git a/client/index.html b/client/index.html index b1e72eb..834e815 100644 --- a/client/index.html +++ b/client/index.html @@ -1,8 +1,8 @@ - + - + MEDIS Data Template Generator diff --git a/client/src/assets/images/bc_logo.svg b/client/src/assets/bc_logo.svg similarity index 100% rename from client/src/assets/images/bc_logo.svg rename to client/src/assets/bc_logo.svg diff --git a/client/src/assets/images/bc_logo_print.svg b/client/src/assets/bc_logo_print.svg similarity index 100% rename from client/src/assets/images/bc_logo_print.svg rename to client/src/assets/bc_logo_print.svg diff --git a/client/src/assets/images/bc_logo_square.svg b/client/src/assets/bc_logo_square.svg similarity index 100% rename from client/src/assets/images/bc_logo_square.svg rename to client/src/assets/bc_logo_square.svg diff --git a/client/src/components/Form.vue b/client/src/components/Form.vue index 62579d1..904e838 100644 --- a/client/src/components/Form.vue +++ b/client/src/components/Form.vue @@ -183,25 +183,26 @@
@@ -219,6 +220,8 @@ import { RLS } from "../utils/types/rls"; import { InitiativeTypes, ReportingPeriods } from "../utils/types"; import { useAuthStore } from "../stores/authStore"; +const environment = import.meta.env.VITE_ENVIRONMENT || "local"; + const authStore = useAuthStore(); // Reactive selections diff --git a/client/src/components/ReplaceTemplate.vue b/client/src/components/ReplaceTemplate.vue index b77420e..f033987 100644 --- a/client/src/components/ReplaceTemplate.vue +++ b/client/src/components/ReplaceTemplate.vue @@ -3,11 +3,33 @@ import { ref } from "vue"; import { useAuthStore } from "../stores/authStore"; import { useMutation } from "@tanstack/vue-query"; import apiService from "../services/apiService"; +import FileSaver from "file-saver"; import { toast } from "vue-sonner"; const store = useAuthStore(); const file = ref(null); +const getTemplateMutation = useMutation({ + mutationFn: () => + apiService.getCurrentFinancialDataTemplate().then((data) => { + FileSaver.saveAs(data.data, `CurrentFinancialTemplate.xlsm`); + toast.success("Template retrieved successfully", { + duration: 5000, + }); + toast.dismiss(); + }), + onError: (error: { message: any }) => { + toast.error(`Failed to retrieve template: ${error.message}`, { + duration: 5000, + }); + console.log(error); + toast.dismiss(); + }, + onMutate: () => { + toast.info("Retrieving template..."); + }, +}); + const mutation = useMutation({ mutationFn: async () => { const formData = new FormData(); @@ -39,10 +61,17 @@ const mutation = useMutation({ diff --git a/client/src/components/bcgov/Header.vue b/client/src/components/bcgov/Header.vue index c39e5f4..837c1df 100644 --- a/client/src/components/bcgov/Header.vue +++ b/client/src/components/bcgov/Header.vue @@ -1,5 +1,5 @@