Skip to content

Commit

Permalink
Apply updates from ds-etna-frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
ahosgood committed Jul 31, 2024
1 parent 9999c9a commit 7f5d04c
Show file tree
Hide file tree
Showing 29 changed files with 1,493 additions and 1,401 deletions.
4 changes: 2 additions & 2 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ docker-compose.yml
Dockerfile
README.md
node_modules
tmp
.babelrc.json
.eslintrc.js
.flake8
.gitignore
.stylelintrc
.prettierignore
stylelint.config.mjs
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ module.exports = {
sourceType: "module",
},
rules: {},
ignorePatterns: ["webpack.config.js", "*.min.js", "tmp/*"],
ignorePatterns: ["webpack.config.js", "*.min.js"],
};
2 changes: 1 addition & 1 deletion .flake8
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[flake8]
ignore = E203, E266, E501, W503, F403, F401
exclude = venv*,__pycache__,node_modules,migrations,tmp
exclude = venv*,__pycache__,node_modules,migrations
max-line-length = 80
max-complexity = 12
select = B,C,E,F,W,T4,B9
2 changes: 1 addition & 1 deletion .github/actions/python-tests/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ runs:
virtualenvs-in-project: true
virtualenvs-path: .venv
- name: Install Poetry dependencies
run: poetry install --no-interaction --no-root
run: poetry install --no-interaction --no-root --with dev
shell: bash
- name: Run Python tests
run: poetry run python -m pytest
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/branch-cleanup.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
name: Delete container image
name: Clean up feature branch

on:
delete:

jobs:
delete:
if: github.event.ref_type == 'branch' && github.event.ref != 'main'
if: github.event.ref_type == 'branch' && startsWith(github.event.ref, 'feature/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Get tag from deleted branch
id: version-tag
run: echo "VERSION=$(echo "${{ github.event.ref }}" | sed -e 's,/,-,g')" >> "$GITHUB_OUTPUT"
- name: Debug
run: echo "Delete container image ${{ steps.version-tag.outputs.VERSION }}"
run: echo "Clean up Docker image example-flask-application:${{ steps.version-tag.outputs.VERSION }}"
- name: Delete image
if: ${{ steps.version-tag.outputs.VERSION }}
uses: bots-house/ghcr-delete-image-action@v1.1.0
Expand Down
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ __pycache__
/app/static/*.css
/app/static/*.css.map
/app/static/*.min.js
/app/static/*.min.js.map
/tmp
/app/static/*.min.js.map
3 changes: 1 addition & 2 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
**/*.html
tmp/**/*
**/*.html
18 changes: 0 additions & 18 deletions .stylelintrc

This file was deleted.

45 changes: 24 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,36 @@ cp -r node_modules/@nationalarchives/frontend/nationalarchives/assets/* app/stat

In addition to the [base Docker image variables](https://github.com/nationalarchives/docker/blob/main/docker/tna-python/README.md#environment-variables), this application has support for:

| Variable | Purpose | Default |
| ----------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------- |
| `CONFIG` | The configuration to use | `config.Production` |
| `DEBUG` | If true, allow debugging[^1] | `False` |
| `COOKIE_DOMAIN` | The domain to save cookie preferences against | _none_ |
| `CSP_IMG_SRC` | A comma separated list of CSP rules for `img-src` | `'self'` |
| `CSP_SCRIPT_SRC` | A comma separated list of CSP rules for `script-src` | `'self'` |
| `CSP_SCRIPT_SRC_ELEM` | A comma separated list of CSP rules for `script-src-elem` | `'self'` |
| `CSP_STYLE_SRC` | A comma separated list of CSP rules for `style-src` | `'self'` |
| `CSP_FONT_SRC` | A comma separated list of CSP rules for `font-src` | `'self'` |
| `CSP_CONNECT_SRC` | A comma separated list of CSP rules for `connect-src` | `'self'` |
| `CSP_MEDIA_SRC` | A comma separated list of CSP rules for `media-src` | `'self'` |
| `CSP_WORKER_SRC` | A comma separated list of CSP rules for `worker-src` | `'self'` |
| `CSP_FRAME_SRC` | A comma separated list of CSP rules for `frame-src` | `'self'` |
| `FRAME_DOMAIN_ALLOW` | A domain from which to allow frame embedding (used in CMS previews) | _none_ |
| `FORCE_HTTPS` | Redirect requests to HTTPS as part of the CSP | _none_ |
| `CACHE_TYPE` | https://flask-caching.readthedocs.io/en/latest/#configuring-flask-caching | _none_ |
| `CACHE_DEFAULT_TIMEOUT` | The number of seconds to cache pages for | production: `300`, staging: `60`, develop: `0`, test: `0` |
| `CACHE_DIR` | Directory for storing cached responses | `/tmp` |
| `CACHE_HEADER_DURATION` | The time to return in the `Cache-Control` header | production: `604800`, staging/develop/test: `1` |
| Variable | Purpose | Default |
| -------------------------------- | --------------------------------------------------------------------------- | --------------------------------------------------------- |
| `CONFIG` | The configuration to use | `config.Production` |
| `DEBUG` | If true, allow debugging[^1] | `False` |
| `COOKIE_DOMAIN` | The domain to save cookie preferences against | _none_ |
| `CSP_IMG_SRC` | A comma separated list of CSP rules for `img-src` | `'self'` |
| `CSP_SCRIPT_SRC` | A comma separated list of CSP rules for `script-src` | `'self'` |
| `CSP_SCRIPT_SRC_ELEM` | A comma separated list of CSP rules for `script-src-elem` | `'self'` |
| `CSP_STYLE_SRC` | A comma separated list of CSP rules for `style-src` | `'self'` |
| `CSP_STYLE_SRC_ELEM` | A comma separated list of CSP rules for `style-src-elem` | `'self'` |
| `CSP_FONT_SRC` | A comma separated list of CSP rules for `font-src` | `'self'` |
| `CSP_CONNECT_SRC` | A comma separated list of CSP rules for `connect-src` | `'self'` |
| `CSP_MEDIA_SRC` | A comma separated list of CSP rules for `media-src` | `'self'` |
| `CSP_WORKER_SRC` | A comma separated list of CSP rules for `worker-src` | `'self'` |
| `CSP_FRAME_SRC` | A comma separated list of CSP rules for `frame-src` | `'self'` |
| `CSP_FEATURE_FULLSCREEN` | A comma separated list of rules for the `fullscreen` feature policy | `'self'` |
| `CSP_FEATURE_PICTURE_IN_PICTURE` | A comma separated list of rules for the `picture-in-picture` feature policy | `'self'` |
| `FORCE_HTTPS` | Redirect requests to HTTPS as part of the CSP | _none_ |
| `CACHE_TYPE` | https://flask-caching.readthedocs.io/en/latest/#configuring-flask-caching | _none_ |
| `CACHE_DEFAULT_TIMEOUT` | The number of seconds to cache pages for | production: `300`, staging: `60`, develop: `0`, test: `0` |
| `CACHE_DIR` | Directory for storing cached responses when using `FileSystemCache` | `/tmp` |
| `CACHE_HEADER_DURATION` | The time to return in the `Cache-Control` header | production: `604800`, staging/develop/test: `1` |
| `GA4_ID` | The Google Analytics 4 ID | _none_ |

[^1] [Debugging in Flask](https://flask.palletsprojects.com/en/2.3.x/debugging/)

## Running tests

```sh
poetry run python -m pytest
docker compose exec dev poetry run python -m pytest
```

## Format and debug code
Expand Down
63 changes: 27 additions & 36 deletions app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import logging

from app.lib import cache
from app.lib.context_processor import (
cookie_preference,
merge_dict,
merge_dict_if,
now_iso_8601,
)
from app.lib.cache import cache
from app.lib.context_processor import cookie_preference, now_iso_8601
from app.lib.template_filters import slugify
from flask import Flask
from flask_talisman import Talisman
Expand All @@ -24,10 +19,10 @@ def create_app(config_class):
cache.init_app(
app,
config={
"CACHE_TYPE": app.config["CACHE_TYPE"],
"CACHE_DEFAULT_TIMEOUT": app.config["CACHE_DEFAULT_TIMEOUT"],
"CACHE_IGNORE_ERRORS": app.config["CACHE_IGNORE_ERRORS"],
"CACHE_DIR": app.config["CACHE_DIR"],
"CACHE_TYPE": app.config.get("CACHE_TYPE"),
"CACHE_DEFAULT_TIMEOUT": app.config.get("CACHE_DEFAULT_TIMEOUT"),
"CACHE_IGNORE_ERRORS": app.config.get("CACHE_IGNORE_ERRORS"),
"CACHE_DIR": app.config.get("CACHE_DIR"),
},
)

Expand All @@ -40,72 +35,70 @@ def create_app(config_class):
"base-uri": csp_none,
"object-src": csp_none,
**(
{"img-src": app.config["CSP_IMG_SRC"]}
if app.config["CSP_IMG_SRC"] != csp_self
{"img-src": app.config.get("CSP_IMG_SRC")}
if app.config.get("CSP_IMG_SRC") != csp_self
else {}
),
**(
{"script-src": app.config["CSP_SCRIPT_SRC"]}
if app.config["CSP_SCRIPT_SRC"] != csp_self
{"script-src": app.config.get("CSP_SCRIPT_SRC")}
if app.config.get("CSP_SCRIPT_SRC") != csp_self
else {}
),
**(
{"script-src-elem": app.config["CSP_SCRIPT_SRC_ELEM"]}
if app.config["CSP_SCRIPT_SRC_ELEM"] != csp_self
{"script-src-elem": app.config.get("CSP_SCRIPT_SRC_ELEM")}
if app.config.get("CSP_SCRIPT_SRC_ELEM") != csp_self
else {}
),
**(
{"style-src": app.config["CSP_STYLE_SRC"]}
if app.config["CSP_STYLE_SRC"] != csp_self
{"style-src": app.config.get("CSP_STYLE_SRC")}
if app.config.get("CSP_STYLE_SRC") != csp_self
else {}
),
**(
{"font-src": app.config["CSP_FONT_SRC"]}
if app.config["CSP_FONT_SRC"] != csp_self
{"font-src": app.config.get("CSP_FONT_SRC")}
if app.config.get("CSP_FONT_SRC") != csp_self
else {}
),
**(
{"connect-src": app.config["CSP_CONNECT_SRC"]}
if app.config["CSP_CONNECT_SRC"] != csp_self
{"connect-src": app.config.get("CSP_CONNECT_SRC")}
if app.config.get("CSP_CONNECT_SRC") != csp_self
else {}
),
**(
{"media-src": app.config["CSP_MEDIA_SRC"]}
if app.config["CSP_MEDIA_SRC"] != csp_self
{"media-src": app.config.get("CSP_MEDIA_SRC")}
if app.config.get("CSP_MEDIA_SRC") != csp_self
else {}
),
**(
{"worker-src": app.config["CSP_WORKER_SRC"]}
if app.config["CSP_WORKER_SRC"] != csp_self
{"worker-src": app.config.get("CSP_WORKER_SRC")}
if app.config.get("CSP_WORKER_SRC") != csp_self
else {}
),
**(
{"frame-src": app.config["CSP_FRAME_SRC"]}
if app.config["CSP_FRAME_SRC"] != csp_self
{"frame-src": app.config.get("CSP_FRAME_SRC")}
if app.config.get("CSP_FRAME_SRC") != csp_self
else {}
),
},
# content_security_policy_nonce_in=["script-src", "style-src"],
feature_policy={
"camera": csp_none,
"fullscreen": csp_self,
"fullscreen": app.config.get("CSP_FEATURE_FULLSCREEN") or csp_self,
"geolocation": csp_none,
"microphone": csp_none,
"screen-wake-lock": csp_none,
},
force_https=app.config["FORCE_HTTPS"],
frame_options="ALLOW-FROM",
frame_options_allow_from=app.config["FRAME_DOMAIN_ALLOW"],
)

@app.after_request
def apply_extra_headers(response):
response.headers["X-Permitted-Cross-Domain-Policies"] = "none"
response.headers["Cross-Origin-Embedder-Policy"] = "credentialless"
response.headers["Cross-Origin-Embedder-Policy"] = "unsafe-none"
response.headers["Cross-Origin-Opener-Policy"] = "same-origin"
response.headers["Cross-Origin-Resource-Policy"] = "same-origin"
response.headers["Cache-Control"] = (
f"public, max-age={app.config['CACHE_HEADER_DURATION']}"
f"public, max-age={app.config.get('CACHE_HEADER_DURATION')}"
)
return response

Expand All @@ -123,8 +116,6 @@ def apply_extra_headers(response):
@app.context_processor
def context_processor():
return dict(
merge_dict=merge_dict,
merge_dict_if=merge_dict_if,
cookie_preference=cookie_preference,
now_iso_8601=now_iso_8601,
app_config=app.config,
Expand Down
3 changes: 0 additions & 3 deletions app/lib/__init__.py

This file was deleted.

8 changes: 0 additions & 8 deletions app/lib/context_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,6 @@
from flask import request


def merge_dict(dict, new_data):
return dict | new_data


def merge_dict_if(dict, new_data, condition):
return dict | new_data if condition else dict


def now_iso_8601():
now = datetime.now()
now_date = now.strftime("%Y-%m-%dT%H:%M:%SZ")
Expand Down
3 changes: 2 additions & 1 deletion app/main/routes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from app.lib import cache, cache_key_prefix
from app.lib.cache import cache
from app.lib.cache_key_prefix import cache_key_prefix
from app.main import bp
from flask import render_template

Expand Down
5 changes: 0 additions & 5 deletions app/site/__init__.py

This file was deleted.

Loading

0 comments on commit 7f5d04c

Please sign in to comment.