diff --git a/.dockerignore b/.dockerignore index 762eda321de6fcd05a277ab12e97c5ce01e648ba..db7b4285480598fe3ca884c25206a38768bb873f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,4 @@ node_modules .git dist +.idea diff --git a/.gitignore b/.gitignore index b0b76d98da60c6d4518fd5dd1d5bb5d81a5a340d..dec6fc796b98fc1450aa486afe8c5fa909925761 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,5 @@ coverage *.sln *.sw? .env + +public/env.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 100c79d301182c25db37e69771a52fb03ca3bda0..e8cf31a6b094281a12945d0c8ca77146773e18c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ ### General * Improved UI when browsing a non-existing bucket or a bucket without permissions for * Improved UI when not browsing a bucket +* Load environment variables dynamically instead of injecting them into the build process. +You can now restart the docker container with new env variables without rebuilding it. +The browser cache for this file is disabled to immediately see the changes #27 ### Fixes * Show correct number of visible objects when searching for objects #28 ### Internal diff --git a/DEVELOPING.md b/DEVELOPING.md index 7cb00f0d03b4c94c2513395f613143cecab6f909..7563ec6856fa012b1e0a6aa6f29cc0c08d30add4 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -7,11 +7,12 @@ npm install ``` ## Environment Setup -Create the file `.env` with the following (or similar) content. See the [README](README.md) for details on these -environment variables. -``` -VITE_API_BASE_URL=http://localhost:9999/api -VITE_S3_URL=http://localhost:9998 +This has to be done only once. Export the environment variables with the appropriate values and use the `envsubst` command +to populate the template and create the file the `public/env.js` +```shell +export API_BASE_URL=http://localhost:9999/api +export S3_URL=http://localhost:9998 +envsubst < src/assets/env.template.js > public/env.js ``` ## Backend Setup Clone the [repository](https://gitlab.ub.uni-bielefeld.de/denbi/object-storage-access) for the backend and set up the diff --git a/Dockerfile b/Dockerfile index 3b4ab9dc348033051ecc250c25cc4d17d5f6c94c..eb4c7fb260bd3b9743d04d5eac727a20f19110f6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,7 @@ RUN npm run build-only FROM nginx:stable-alpine as production-stage HEALTHCHECK --interval=35s --timeout=4s CMD curl -f http://localhost || exit 1 COPY --from=build-stage /app/dist /usr/share/nginx/html +COPY --from=build-stage /app/src/assets/env.template.js /tmp COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80 -CMD ["nginx", "-g", "daemon off;"] +CMD ["/bin/sh", "-c", "envsubst < /tmp/env.template.js > /usr/share/nginx/html/env.js && exec nginx -g 'daemon off;'"] diff --git a/README.md b/README.md index c563b1bd93f21f66050cd92ce2b9b2bed7949cd4..b2410f2ed314fe2dbbdb97f373999e9fdb8dbfdf 100644 --- a/README.md +++ b/README.md @@ -7,13 +7,14 @@ backend https://gitlab.ub.uni-bielefeld.de/denbi/object-storage-access ## Environment Variables -These needs to be present when bundling the JavaScript files. -This needs to be considered when building docker images. +The docker container replaces them in the `env.template.js` file and moves that file to the same location as the `index.html`. +When accessing the website, these variables will be loaded dynamically into the application. -| Variable | Default | Value | Description | -|---------------------|---------------------------|-----------|----------------------------------------| -| `VITE_API_BASE_URL` | http://localhost:9999/api | HTTP URL | Base URL for the API as backend | -| `VITE_S3_URL` | unset | HTTP URL | URL of the S3 storage to interact with | + +| Variable | Default | Value | Description | +|-----------------|---------|-----------|----------------------------------------| +| `API_BASE_URL` | unset | HTTP URL | Base URL for the API as backend | +| `S3_URL` | unset | HTTP URL | URL of the S3 storage to interact with | ## Getting started diff --git a/index.html b/index.html index 87d4c4bbfbf28d649522ab90fe2b7412cb0af47d..0aa6bdd0bc4e0120526b53463a27e8ceaf379794 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,7 @@ <link rel="icon" href="/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>S3 Proxy</title> + <script src="/env.js"></script> </head> <body> <div id="app"></div> diff --git a/nginx.conf b/nginx.conf index 1424297eef187edb0899678349378b38859a80d3..eca71fafffaa1157d81bd2dd6bed4fef96f96c31 100644 --- a/nginx.conf +++ b/nginx.conf @@ -7,6 +7,11 @@ server { root /usr/share/nginx/html; index index.html index.htm; try_files $uri $uri/ /index.html; + # Disable cache for env.js + location ~ env\.js { + add_header Cache-Control 'no-store'; + expires off; + } } diff --git a/src/App.vue b/src/App.vue index 41975a90f162301e85b125c5f6179969cba510a9..52a20b0ac5a0df6077a6687fd39c792053cab4c9 100644 --- a/src/App.vue +++ b/src/App.vue @@ -5,16 +5,14 @@ import { useCookies } from "vue3-cookies"; import { useAuthStore } from "@/stores/auth"; import { useRouter } from "vue-router"; import { OpenAPI } from "@/client"; +import { environment } from "@/environment"; const { cookies } = useCookies(); const store = useAuthStore(); const router = useRouter(); onBeforeMount(() => { - OpenAPI.BASE = - import.meta.env.VITE_API_BASE_URL != null - ? import.meta.env.VITE_API_BASE_URL - : "http://localhost:9999/api"; + OpenAPI.BASE = environment.API_BASE_URL; store.setToken(cookies.get("bearer")); router.beforeEach(async (to) => { // make sure the user is authenticated diff --git a/src/assets/env.template.js b/src/assets/env.template.js new file mode 100644 index 0000000000000000000000000000000000000000..2e722b9c2872f738a688d2bc2566484fadfc4103 --- /dev/null +++ b/src/assets/env.template.js @@ -0,0 +1,7 @@ +(function (window) { + window["env"] = window["env"] || {}; + + // Environment variables + window["env"]["apiUrl"] = "${API_BASE_URL}"; + window["env"]["s3Url"] = "${S3_URL}"; +})(this); diff --git a/src/components/BucketView.vue b/src/components/BucketView.vue index aeff991f8f77eba0be2e755fcbcb84f1d16ddd22..d83664eca24feef730642edfb75670b5c6f07b55 100644 --- a/src/components/BucketView.vue +++ b/src/components/BucketView.vue @@ -29,6 +29,7 @@ import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; import { awsAuthMiddlewareOptions } from "@aws-sdk/middleware-signing"; import { useAuthStore } from "@/stores/auth"; import { useBucketStore } from "@/stores/buckets"; +import { environment } from "@/environment"; const authStore = useAuthStore(); const bucketRepository = useBucketStore(); @@ -37,7 +38,7 @@ const middleware = [ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore (next) => async (args) => { - args.request.headers["host"] = import.meta.env.VITE_S3_URL.split("://")[1]; + args.request.headers["host"] = environment.S3_URL.split("://")[1]; return await next(args); }, { @@ -48,7 +49,7 @@ const middleware = [ let client = new S3Client({ region: "us-east-1", - endpoint: import.meta.env.VITE_S3_URL, + endpoint: environment.S3_URL, forcePathStyle: true, credentials: { accessKeyId: authStore.s3key?.access_key ?? "", @@ -67,7 +68,7 @@ authStore.$onAction(({ name, args }) => { } else { client = new S3Client({ region: "us-east-1", - endpoint: import.meta.env.VITE_S3_URL, + endpoint: environment.S3_URL, forcePathStyle: true, credentials: { accessKeyId: args[0].access_key, diff --git a/src/environment.ts b/src/environment.ts new file mode 100644 index 0000000000000000000000000000000000000000..0b261862ef36606075ac7434da45a769d0828693 --- /dev/null +++ b/src/environment.ts @@ -0,0 +1,12 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +// @ts-ignore +const windowEnv: Record<string, string> = window["env"]; +export const environment: env = { + S3_URL: windowEnv["s3Url"], + API_BASE_URL: windowEnv["apiUrl"], +}; + +type env = { + S3_URL: string; + API_BASE_URL: string; +};