Skip to content

Commit 1efac3a

Browse files
authored
ALLOWEDFLARE_EMAIL_DOMAIN (#5)
Account for the possibility of different top level domains between private stuff and public-facing stuff like email addresses. Put a 3-second timeout on the certificates request, just in case. Bump the Ruff version to pick up astral-sh/ruff#9734 and update some other tooling. Also prepare for running more linters with Ruff and replacing `black` with [The Ruff Formatter](https://docs.astral.sh/ruff/formatter/).
1 parent a9f374e commit 1efac3a

File tree

6 files changed

+93
-41
lines changed

6 files changed

+93
-41
lines changed

.pre-commit-config.yaml

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@ default_language_version:
44
repos:
55
# Autoformatters
66
- repo: https://github.com/astral-sh/ruff-pre-commit
7-
rev: v0.0.270
7+
rev: v0.3.0
88
hooks:
99
- id: ruff
1010
args:
1111
- --fix
1212
- repo: https://github.com/pre-commit/pre-commit-hooks
13-
rev: v4.4.0
13+
rev: v4.5.0
1414
hooks:
1515
- id: double-quote-string-fixer
1616
- id: end-of-file-fixer
1717
- repo: https://github.com/psf/black
18-
rev: 23.10.1
18+
rev: 23.12.1
1919
hooks:
2020
- id: black
2121
- repo: https://github.com/jazzband/pip-tools
@@ -46,7 +46,7 @@ repos:
4646
- id: validate-pyproject
4747

4848
- repo: https://github.com/adrienverge/yamllint.git
49-
rev: v1.32.0
49+
rev: v1.33.0
5050
hooks:
5151
- id: yamllint
5252

demodj/settings.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
"""
2-
Django settings for the Demo DJ project.
1+
"""Django settings for the Demo DJ project.
32
43
Generated by 'django-admin startproject' using Django 4.2.1.
54
@@ -11,8 +10,8 @@
1110
"""
1211

1312
from ast import literal_eval
14-
from pathlib import Path
1513
from os import getenv
14+
from pathlib import Path
1615

1716
BASE_DIR = Path(__file__).resolve().parent.parent
1817

@@ -41,6 +40,7 @@
4140
'django.contrib.sessions',
4241
'django.contrib.messages',
4342
'django.contrib.staticfiles',
43+
'django_extensions',
4444
]
4545

4646
MIDDLEWARE = [

django_allowedflare/__init__.py

+12-9
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,36 @@
11
import logging
2-
from datetime import datetime, timedelta, timezone as datetime_timezone
2+
from datetime import datetime, timedelta
3+
from datetime import timezone as datetime_timezone
34
from typing import Any
45

6+
import requests
57
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
8+
from django.conf import settings
69
from django.contrib.auth.backends import ModelBackend
710
from django.contrib.auth.models import User
811
from django.http import HttpRequest
912
from django.utils import timezone as django_utils_timezone
10-
from django.conf import settings
13+
from jwt import InvalidSignatureError, decode
1114
from jwt.algorithms import RSAAlgorithm
12-
from jwt import decode, InvalidSignatureError
13-
import requests
14-
1515

1616
cache_updated = datetime.fromtimestamp(0, tz=datetime_timezone.utc)
1717
cached_keys: list[RSAPublicKey] = []
1818
logger = logging.getLogger(__name__)
1919

2020

2121
def clean_username(username: str) -> str:
22-
return username.removesuffix(f'@{settings.ALLOWEDFLARE_PRIVATE_DOMAIN}')
22+
suffix = getattr(settings, 'ALLOWEDFLARE_EMAIL_DOMAIN', settings.ALLOWEDFLARE_PRIVATE_DOMAIN)
23+
return username.removesuffix(f'@{suffix}')
2324

2425

2526
def fetch_or_reuse_keys() -> list[RSAPublicKey]:
26-
global cache_updated, cached_keys
27+
global cache_updated, cached_keys # noqa: PLW0603
2728
now = django_utils_timezone.now()
2829
# As of June 2023, signing keys are documented as rotated every 6 weeks
2930
if cache_updated + timedelta(days=1) < now:
30-
response = requests.get(f'{settings.ALLOWEDFLARE_ACCESS_URL}/cdn-cgi/access/certs').json()
31+
response = requests.get(
32+
f'{settings.ALLOWEDFLARE_ACCESS_URL}/cdn-cgi/access/certs', timeout=3
33+
).json()
3134
if response.get('keys'):
3235
decoded_keys = [RSAAlgorithm.from_jwk(key) for key in response['keys']]
3336
cached_keys = [key for key in decoded_keys if isinstance(key, RSAPublicKey)]
@@ -50,7 +53,7 @@ def decode_token(cf_authorization: str) -> dict:
5053

5154

5255
def defaults_for_user(token: dict) -> dict:
53-
return getattr(settings, 'ALLOWEDFLARE_DEFAULTS_FOR_USER', lambda token: {'is_staff': True})(
56+
return getattr(settings, 'ALLOWEDFLARE_DEFAULTS_FOR_USER', lambda _token: {'is_staff': True})(
5457
token
5558
)
5659

includes.sh

+58-21
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
# shellcheck shell=bash
22

3-
case $(uname -s) in
3+
OS=$(uname -s)
4+
5+
case $OS in
46
Darwin)
57
export BASH_SILENCE_DEPRECATION_WARNING=1
68

7-
if ! [[ -x $(command -v brew) ]]; then
8-
[[ -d /opt/homebrew/bin ]] && export PATH="/opt/homebrew/bin:$PATH"
9-
[[ -x $(command -v brew) ]] || echo ERROR: homebrew missing
10-
fi
9+
if ! [[ -x $(command -v brew) ]]; then
10+
[[ -d /opt/homebrew/bin ]] && export PATH="/opt/homebrew/bin:$PATH"
11+
[[ -x $(command -v brew) ]] || echo ERROR: homebrew missing
12+
fi
13+
14+
;;
1115
esac
1216

1317
if ! [[ -x $(command -v nvm) ]]; then
@@ -17,21 +21,21 @@ if ! [[ -x $(command -v nvm) ]]; then
1721
fi
1822

1923
# F: no-op for single page, R: color, X: keep text when exiting, i: case insensitive searching
20-
LESS="-FRXi"
24+
LESS='-FRXi'
2125
export LESS
2226

2327
# Aliases only work in interactive shells
2428
alias jq='jq --color-output'
2529
alias ls='ls --color=auto'
2630

2731
pathver() {
28-
: Print path and version
32+
: 'Print path and version'
2933
(type "$1" && "$1" --version) |
30-
sed -Ee N -e 's,^[^/(]*,,' -e 's,\((.+)\),\1,' -e 's/\n/ /'
34+
sed -Ee N -e 's,^[^/(]*,,' -e 's,\((.+)\),\1,' -e "s/\n($1 )?/ /i"
3135
}
3236

3337
a() {
34-
: Activate virtual environment after changing directory
38+
: 'Activate virtual environment after changing directory'
3539

3640
if [[ $1 ]]; then
3741
directory=~/code/$1
@@ -46,9 +50,9 @@ a() {
4650

4751
cd "$directory" || return 1
4852

49-
# TODO pyenv-virtualenv wants `. deactivate`
50-
# TODO conda wants `conda deactivate`
53+
[[ $(command -v conda) ]] && conda deactivate
5154
[[ $(command -v deactivate) ]] && deactivate
55+
# TODO pyenv-virtualenv wants `. deactivate`
5256

5357
if [[ -f .venv/bin/activate ]]; then
5458
# shellcheck disable=SC1091
@@ -57,47 +61,80 @@ a() {
5761
elif [[ -d conda ]]; then
5862
# shellcheck disable=SC1091
5963
source "$HOME/miniconda3/etc/profile.d/conda.sh"
60-
conda activate "$(basename "$directory")"
64+
conda activate "$(basename "$PWD")"
6165
pathver python
6266
fi
6367

6468
if [[ -f .nvmrc ]]; then
65-
nvm install && nvm use
69+
nvm install &>/dev/null && nvm use &>/dev/null
6670
pathver node
6771
fi
72+
73+
export PS1='\w$ '
6874
}
6975

7076
devready() {
71-
: DEVelopment READYness check
77+
: 'DEVelopment READYness check'
7278
[[ $(git config --global user.name) ]] || echo ERROR: git user.name missing
7379
[[ $(git config --global user.email) ]] || echo ERROR: git user.email missing
7480
[[ $(git config --global pull.rebase) == true ]] || echo WARNING: git pull.rebase != true
75-
[[ $(git config --global rebase.autosquash) == true ]] || echo WARNING: git rebase.autosquash != true
76-
[[ $(git config --global push.default) == current ]] || echo WARNING: git push.default != current
81+
[[ $(git config --global rebase.autosquash) == true ]] ||
82+
echo WARNING: git rebase.autosquash != true
83+
[[ $(git config --global push.default) == current ]] ||
84+
echo WARNING: git push.default != current
85+
[[ -f ~/.config/git/ignore ]] || echo WARNING: global git ignore file absent
86+
if [[ $OS == Darwin ]]; then
87+
grep --fixed-strings --no-messages --quiet '.DS_Store' ~/.config/git/ignore ||
88+
echo WARNING: .DS_Store files not globally git ignored
89+
[[ $(defaults read NSGlobalDomain ApplePressAndHoldEnabled) == '0' ]] ||
90+
echo WARNING: MacOS press and hold enabled
91+
[[ $(defaults read NSGlobalDomain NSAutomaticPeriodSubstitutionEnabled) == '0' ]] ||
92+
echo WARNING: MacOS period substitution enabled
93+
[[ $(defaults read NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled) == '0' ]] ||
94+
echo WARNING: MacOS quote substitution enabled
95+
fi
96+
}
97+
98+
forceready() {
99+
: 'FORCE system to be READY for development, clobbering current settings'
100+
[[ -n $INSH_NAME ]] || git config --global user.name "$INSH_NAME"
101+
[[ -n $INSH_EMAIL ]] || git config --global user.email "$INSH_EMAIL"
102+
git config --global pull.rebase true
103+
git config --global rebase.autosquash true
104+
git config --global push.default current
105+
[[ -d ~/.config/git ]] || mkdir -p ~/.config/git
106+
107+
if [[ $OS == Darwin ]]; then
108+
[[ -f ~/.config/git/ignore ]] || curl -so ~/.config/git/ignore \
109+
https://raw.githubusercontent.com/github/gitignore/master/Global/macOS.gitignore
110+
defaults write NSGlobalDomain ApplePressAndHoldEnabled -bool false
111+
defaults write NSGlobalDomain NSAutomaticPeriodSubstitutionEnabled -bool false
112+
defaults write NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool false
113+
fi
77114
}
78115

79116
pc() {
80-
: run Pre-Commit on modified files
117+
: 'run Pre-Commit on modified files'
81118
pre-commit run "$@"
82119
}
83120

84121
pca() {
85-
: run Pre-Commit on All files
122+
: 'run Pre-Commit on All files'
86123
pre-commit run --all-files "$@"
87124
}
88125

89126
pcam() {
90-
: run Pre-Commit on All files including Manual stage hooks
127+
: 'run Pre-Commit on All files including Manual stage hooks'
91128
pre-commit run --all-files --hook-stage manual "$@"
92129
}
93130

94131
pcm() {
95-
: run Pre-Commit on modified files including Manual stage hooks
132+
: 'run Pre-Commit on modified files including Manual stage hooks'
96133
pre-commit run --hook-stage manual "$@"
97134
}
98135

99136
resourcerun() {
100-
: RE-SOURCE this file and RUN the specified function with tracing enabled
137+
: 'RE-SOURCE this file and RUN the specified function with tracing enabled'
101138
# shellcheck source=includes.sh
102139
source "${BASH_SOURCE[0]}"
103140
set -x

manage.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
import default
66

77

8-
def main():
8+
def main() -> None:
99
"""Run administrative tasks."""
1010
try:
1111
from django.core.management import execute_from_command_line
12-
from django.core.management.commands.runserver import Command as runserver
12+
from django.core.management.commands.runserver import Command
1313

14-
runserver.default_addr = '0.0.0.0'
15-
runserver.default_port = '8001' # Should match docker-compose.yml
14+
Command.default_addr = '0.0.0.0' # noqa: S104
15+
Command.default_port = '8001' # Should match docker-compose.yml
1616
except ImportError as exc:
1717
raise ImportError(
1818
"Couldn't import Django. Are you sure it's installed and "

pyproject.toml

+12
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,24 @@ line-length = 100
2727
skip-magic-trailing-comma = true
2828
skip-string-normalization = true
2929

30+
[tool.ruff.format]
31+
quote-style = 'single'
32+
skip-magic-trailing-comma = true
33+
34+
[tool.ruff.lint.flake8-quotes]
35+
inline-quotes = 'single'
36+
3037
[tool.django-stubs]
3138
django_settings_module = 'demodj.settings'
3239

3340
[tool.ruff]
3441
line-length = 100
3542

43+
[tool.ruff.lint]
44+
ignore = [
45+
'EM101', # Allow exceptions to use string literals because keeping code as simple as possible is more important than keeping tracebacks as simple as possible.
46+
]
47+
3648
[tool.mypy]
3749
plugins = ['mypy_django_plugin.main']
3850

0 commit comments

Comments
 (0)