Skip to content

Commit e735f5c

Browse files
committed
Make time dropdowns user configurable via an environmental config file path supplied as a build arg to Docker
1 parent 19e9b1d commit e735f5c

20 files changed

+563
-615
lines changed

.env.production.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ REACT_SENTRY_DSN=https://<key>@sentry.io/<project>
1212
CLOUDFLARE_TEAM_DOMAIN=<CLOUDFLARE_ACCESS_TEAM_DOMAIN>
1313
CLOUDFLARE_APPLICATION_AUDIENCE=<CLOUFLARE_ACCESS_AUDIENCE_TAG>
1414
SECRET_KEY=<YOUR_SECRET_KEY>
15-
OIDC_CLIENT_SECRETS=<YOUR_CLIENT_SECRETS>
15+
OIDC_CLIENT_SECRETS=<YOUR_CLIENT_SECRETS>

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,3 +497,9 @@ $RECYCLE.BIN/
497497
*.lnk
498498

499499
# End of https://www.toptal.com/developers/gitignore/api/macos,windows,visualstudiocode,jetbrains+all,node,python,flask
500+
501+
config.production.json
502+
config.staging.json
503+
config.development.json
504+
config.test.json
505+
config.overrides.json

Dockerfile

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,17 @@ ARG PUSH_SENTRY_RELEASE="false"
66
FROM node:22-alpine AS build-step
77
ARG SENTRY_RELEASE=""
88
WORKDIR /app
9-
ENV PATH /app/node_modules/.bin:$PATH
9+
ENV PATH=/app/node_modules/.bin:$PATH
1010
COPY craco.config.js package.json package-lock.json tsconfig.json tsconfig.paths.json .env.production* ./
1111
COPY ./src ./src
1212
COPY ./public ./public
13+
ARG ACCESS_FILE_CONFIG_PATH="src/config/config.empty.json"
14+
COPY $ACCESS_FILE_CONFIG_PATH /app/config.overrides.json
15+
1316
RUN npm install
1417
RUN touch .env.production
15-
ENV REACT_APP_SENTRY_RELEASE $SENTRY_RELEASE
16-
ENV REACT_APP_API_SERVER_URL ""
18+
ENV REACT_APP_SENTRY_RELEASE=$SENTRY_RELEASE
19+
ENV REACT_APP_API_SERVER_URL=""
1720
RUN npm run build
1821

1922
# Optional build step #2: upload the source maps by pushing a release to sentry
@@ -48,9 +51,9 @@ COPY --from=sentry /app/sentry ./sentry
4851
# Choose whether to include the sentry release push build step or not
4952
FROM ${PUSH_SENTRY_RELEASE}
5053

51-
ENV FLASK_ENV production
52-
ENV FLASK_APP api.app:create_app
53-
ENV SENTRY_RELEASE $SENTRY_RELEASE
54+
ENV FLASK_ENV=production
55+
ENV FLASK_APP=api.app:create_app
56+
ENV SENTRY_RELEASE=$SENTRY_RELEASE
5457

5558
EXPOSE 3000
5659

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,29 @@ If you are using Cloudflare Access, ensure that you configure `CLOUDFLARE_TEAM_D
248248

249249
Else, if you are using a generic OIDC identity provider (such as Okta), then you should configure `SECRET_KEY` and `OIDC_CLIENT_SECRETS`. `CLOUDFLARE_TEAM_DOMAIN` and `CLOUDFLARE_APPLICATION_AUDIENCE` do not need to be set and can be removed from your env file. Make sure to also mount your `client-secrets.json` file to the container if you don't have it inline.
250250

251+
### Access application configuration overrides
252+
253+
The default config for the application is at `src/config/config.default.json`.
254+
255+
If you want to override those values, create your own config file containing JSON that overrides values in the default config.
256+
257+
- `ACCESS_TIME_LABELS`: _Optional._ Specifies the time access labels to use for dropdowns on the front end. Contains a JSON object of the format `{"NUM_SECONDS": "LABEL"}`. **Example:** `{"86400": "1 day", "604800": "1 week", "2592000": "1 month"}`.
258+
- `DEFAULT_ACCESS_TIME`: _Optional._ Specifies the default time access label to use for dropdowns on the front end. Contains a string with a number of seconds corresponding to a key in the access time labels, e.g. `"86400"`.
259+
260+
To use your custom config file, edit `docker-compose.yml` to add a build arg `ACCESS_FILE_CONFIG_PATH` with a local path to your config override file:
261+
262+
```yaml
263+
services:
264+
discord-access:
265+
build:
266+
context: .
267+
dockerfile: Dockerfile
268+
args:
269+
ACCESS_FILE_CONFIG_PATH: 'path/to/config.production.json'
270+
```
271+
272+
If `ACCESS_FILE_CONFIG_PATH` is not set as a build arg when building the Docker image, then the default config will be used.
273+
251274
#### Database Setup
252275

253276
After `docker compose up --build`, you can run the following commands to setup the database:

craco.config.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,48 @@
11
const CracoAlias = require('react-app-alias');
2+
const fs = require('fs');
3+
const path = require('path');
4+
const webpack = require('webpack');
5+
6+
function load_access_config() {
7+
// Load the default config
8+
const defaultConfigPath = path.resolve(__dirname, 'src/config/config.default.json');
9+
const accessConfig = JSON.parse(fs.readFileSync(defaultConfigPath, 'utf8'));
10+
11+
// Dockerfile copies the file at build arg ACCESS_FILE_CONFIG_PATH to config.overrides.json
12+
const dockerConfigOverrideFile = 'config.overrides.json';
13+
const overrideConfigPath = fs.existsSync(path.resolve(__dirname, dockerConfigOverrideFile))
14+
? path.resolve(__dirname, dockerConfigOverrideFile)
15+
: null;
16+
17+
// Load override config, if present
18+
if (overrideConfigPath) {
19+
try {
20+
const overrideConfig = JSON.parse(fs.readFileSync(overrideConfigPath, 'utf8'));
21+
22+
// Merge override config with default config
23+
Object.assign(accessConfig, overrideConfig);
24+
} catch (err) {
25+
console.error(`Failed to load override config from ${overrideConfigPath}: ${err}`);
26+
process.exit(1); // Exit with an error status
27+
}
28+
}
29+
30+
// Sanity check for ACCESS_TIME_LABELS
31+
if (accessConfig.ACCESS_TIME_LABELS && typeof accessConfig.ACCESS_TIME_LABELS !== 'object') {
32+
throw new Error('ACCESS_TIME_LABELS must be a dictionary');
33+
}
34+
35+
// Sanity check for DEFAULT_ACCESS_TIME
36+
if (accessConfig.DEFAULT_ACCESS_TIME) {
37+
const defaultAccessTime = parseInt(accessConfig.DEFAULT_ACCESS_TIME, 10);
38+
if (isNaN(defaultAccessTime) || !accessConfig.ACCESS_TIME_LABELS.hasOwnProperty(defaultAccessTime)) {
39+
throw new Error('DEFAULT_ACCESS_TIME must be a valid key in ACCESS_TIME_LABELS');
40+
}
41+
}
42+
return accessConfig;
43+
}
44+
45+
const accessConfig = load_access_config();
246

347
module.exports = {
448
plugins: [
@@ -15,5 +59,11 @@ module.exports = {
1559
alias: {
1660
'@mui/styled-engine': '@mui/styled-engine-sc',
1761
},
62+
plugins: [
63+
/* defined in src/globals.d.ts, which is included in tsconfig.json */
64+
new webpack.DefinePlugin({
65+
ACCESS_CONFIG: JSON.stringify(accessConfig),
66+
}),
67+
],
1868
},
1969
};

docker-compose.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
services:
22
discord-access:
3-
build: .
3+
build:
4+
context: .
5+
dockerfile: Dockerfile
6+
# args:
7+
# ACCESS_FILE_CONFIG_PATH: 'src/config/config.empty.json'
48
container_name: discord-access
59
env_file:
610
- .env.production

0 commit comments

Comments
 (0)