-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into 245-unify-terminology
- Loading branch information
Showing
47 changed files
with
3,574 additions
and
641 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -74,7 +74,7 @@ python manage.py migrate --settings=config.settings.local | |
|
||
# (optional) install example data | ||
python manage.py loaddata --settings=config.settings.local e2e_tests/database/test_database.json | ||
cp -r e2e_tests/database/test_database_uploads cpmonitor/images/uploads | ||
cp -r e2e_tests/database/test_database_uploads/. cpmonitor/images/uploads | ||
|
||
# install css and javascript libraries | ||
yarn install | ||
|
@@ -119,7 +119,7 @@ pytest --ignore e2e_tests/test_deployed.py | |
rm db/db.sqlite3 | ||
poetry run python manage.py migrate --settings=config.settings.local | ||
poetry run python manage.py loaddata --settings=config.settings.local e2e_tests/database/test_database.json | ||
cp -r e2e_tests/database/test_database_uploads cpmonitor/images/uploads | ||
cp -r e2e_tests/database/test_database_uploads/. cpmonitor/images/uploads | ||
docker compose up -d --build | ||
docker compose -f docker/reverseproxy/docker-compose.yml up -d --build | ||
pytest e2e_tests/test_deployed.py | ||
|
@@ -142,11 +142,17 @@ pytest --headed <path-to-e2e-test> | |
From a local database filled with suitable data, generate a fixture named `example_fixture` with | ||
|
||
```shell | ||
python -Xutf8 manage.py dumpdata cpmonitor -e contenttypes -e admin.logentry -e sessions --indent 2 --settings=config.settings.local > cpmonitor/fixtures/example_fixture.json | ||
python -Xutf8 manage.py dumpdata -e contenttypes -e auth.Permission -e admin.LogEntry -e sessions --indent 2 --settings=config.settings.local > cpmonitor/fixtures/example_fixture.json | ||
``` | ||
|
||
(The `-Xutf8` and `--indent 2` options ensure consistent and readable output on all platforms.) | ||
|
||
The arguments `-e contenttypes -e auth.Permission -e admin.LogEntry -e sessions` exclude tables which are pre-filled | ||
by django or during usage by django and whose content may change depending on the models in the project. If they are | ||
included, everything works fine at first, since loaddata will silently accept data already there. However, as soon as | ||
the data to load clashes with existing content, it will fail. `-e admin.LogEntry` excludes references to content types | ||
which may otherwise be inconsistent.`-e sessions` excludes unneeded data which otherwise would clog the JSON file. | ||
|
||
This fixture may be loaded in a test with. (Similar in a pytest fixture.) | ||
|
||
```python | ||
|
@@ -241,7 +247,7 @@ Afterwards the test database has to be updated as well. Use the dumpdata command | |
currently running database: | ||
|
||
```shell | ||
python -Xutf8 manage.py dumpdata -e contenttypes -e admin.logentry -e sessions --indent 2 --settings=config.settings.local > e2e_tests/database/test_database.json | ||
python -Xutf8 manage.py dumpdata -e contenttypes -e auth.Permission -e admin.LogEntry -e sessions --indent 2 --settings=config.settings.local > e2e_tests/database/test_database.json | ||
``` | ||
|
||
Cheat-sheet to make sure the correct data is dumped: | ||
|
@@ -251,10 +257,10 @@ git checkout right-before-model-change | |
rm db/db.sqlite3 | ||
python manage.py migrate --settings=config.settings.local | ||
python manage.py loaddata --settings=config.settings.local e2e_tests/database/test_database.json | ||
cp -r e2e_tests/database/test_database_uploads cpmonitor/images/uploads | ||
cp -r e2e_tests/database/test_database_uploads/. cpmonitor/images/uploads | ||
git checkout after-model-change-including-migration | ||
python manage.py migrate --settings=config.settings.local | ||
python -Xutf8 manage.py dumpdata -e contenttypes -e admin.logentry -e sessions --indent 2 --settings=config.settings.local > e2e_tests/database/test_database.json | ||
python -Xutf8 manage.py dumpdata -e contenttypes -e auth.Permission -e admin.LogEntry -e sessions --indent 2 --settings=config.settings.local > e2e_tests/database/test_database.json | ||
# Only if additional images were uploaded: | ||
cp -r cpmonitor/images/uploads e2e_tests/database/test_database_uploads | ||
``` | ||
|
@@ -371,7 +377,7 @@ Possibly migrate, test the data, and check that the size is reasonable. Then mak | |
|
||
```sh | ||
SNAPSHOT_NAME=prod_database_$(date -u +"%FT%H%M%SZ") | ||
python -Xutf8 manage.py dumpdata -e contenttypes -e admin.logentry -e sessions --indent 2 --settings=config.settings.local > e2e_tests/database/${SNAPSHOT_NAME}.json | ||
python -Xutf8 manage.py dumpdata -e contenttypes -e auth.Permission -e admin.LogEntry -e sessions --indent 2 --settings=config.settings.local > e2e_tests/database/${SNAPSHOT_NAME}.json | ||
cp -r cpmonitor/images/uploads e2e_tests/database/${SNAPSHOT_NAME}_uploads | ||
echo "Some useful information, e.g. the migration state of the snapshot" > e2e_tests/database/${SNAPSHOT_NAME}.README | ||
du -hs e2e_tests/database/${SNAPSHOT_NAME}* | ||
|
@@ -415,7 +421,7 @@ docker compose up -d | |
``` | ||
5. Copy the images, the compose files, the certificate renewal cron job and the reverse proxy settings to the server: | ||
```sh | ||
scp -C cpmonitor.tar klimaschutzmonitor-dbeaver.tar docker-compose.yml crontab renew-cert.sh docker/reverseproxy/ [email protected]:/tmp/ | ||
scp -C cpmonitor.tar klimaschutzmonitor-dbeaver.tar docker-compose.yml crontab reload-cert.sh docker/reverseproxy/ [email protected]:/tmp/ | ||
``` | ||
6. Login to the server: | ||
```sh | ||
|
@@ -465,8 +471,8 @@ docker compose up -d | |
11. Install certificate renewal cron job: | ||
```sh | ||
crontab /tmp/crontab | ||
cp /tmp/renew-cert.sh /home/monitoring/ | ||
chmod +x /home/monitoring/renew-cert.sh | ||
cp /tmp/reload-cert.sh /home/monitoring/ | ||
chmod +x /home/monitoring/reload-cert.sh | ||
``` | ||
### Database Client | ||
|
@@ -478,13 +484,16 @@ the environment) and the credentials can be found in the .env.local file. For te | |
configured in the respective .env files on the server. | ||
### TLS Certificate and Renewal | ||
#### Overview | ||
We currently use a single TLS certificate for both monitoring.localzero.org and monitoring-test.localzero.org. The certificate is issued by letsencrypt.org and requesting and renewal is performed using [acme.sh](https://github.com/acmesh-official/acme.sh), which runs in a container. This solution allows us to have almost all necessary code and config in the repo instead of only on the server. | ||
#### Initial Issuance | ||
The initial certificate was issued using the following command: | ||
```sh | ||
docker exec acme-sh --issue -d monitoring-test.localzero.net -d monitoring.localzero.net --standalone --server https://acme-v02.api.letsencrypt.org/directory --fullchain-file /acme.sh/fullchain.cer --key-file /acme.sh/ssl-cert.key | ||
``` | ||
#### Renewal | ||
Renewal is performed automatically by acme.sh's internal cron job, which... | ||
- checks if a renewal is necessary, and if so: | ||
- requests a new certificate from letsencrypt, | ||
|
@@ -495,6 +504,26 @@ A reload of the nginx config is independently triggered every four hours by our | |
```sh | ||
crontab -l | ||
``` | ||
This job runs [a script](renew-cert.sh) which applies the latest certificate that acme.sh has produced. This means there can be some delay between renewal and application of the certificate, but since acme.sh performs renewal a few days before expiry, there should be enough time for nginx to reload the certificate. | ||
This job runs [a script](reload-cert.sh) which applies the latest certificate that acme.sh has produced. This means there can be some delay between renewal and application of the certificate, but since acme.sh performs renewal a few days before expiry, there should be enough time for nginx to reload the certificate. | ||
|
||
#### acme-sh Configuration and Debugging | ||
|
||
The configuration used by acme-sh's cronjob (not our nginx reload cronjob!), e.g. renewal interval, can be changed in `reverseproxy/ssl_certificates/monitoring-test.localzero.net_ecc/`` on the server. | ||
The following commands might be executed on the server to debug and test the acme-sh configuration: | ||
```shell | ||
# view certificate creation date and next renew date | ||
docker exec acme-sh --list | ||
# tell acme-sh to run its cronjob now, using letsencrypt's test environment (to bypass rate limiting) | ||
docker exec acme-sh --cron --staging | ||
|
||
# tell acme-sh to run its cronjob now, using letsencrypt's PROD environment (affected by rate limiting - 5 certs every couple weeks...) | ||
docker exec acme-sh --cron | ||
|
||
# force a renewal via letsencrypt's PROD environment, even if renewal time hasn't been reached yet | ||
docker exec acme-sh --cron --force | ||
``` | ||
#### TLS Certificates and Running Locally | ||
When running locally, we instead use a [certificate created for localhost](ssl_certificates_localhost). Since ownership of localhost cannot be certified, this is a single self-signed certificate instead of a full chain signed by a CA like on the server, and an exception must be added to your browser to trust it. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
from allauth.account.adapter import DefaultAccountAdapter | ||
from invitations.app_settings import app_settings | ||
|
||
from .models import AccessRight, City, get_invitation | ||
|
||
|
||
class AllauthInvitationsAdapter(DefaultAccountAdapter): | ||
def is_open_for_signup(self, request): | ||
""" | ||
Overwrites django-invitations. | ||
Checks that there exists an invitation instead of email. | ||
""" | ||
if get_invitation(request): | ||
return True | ||
elif app_settings.INVITATION_ONLY: | ||
return False | ||
else: | ||
return True | ||
|
||
def save_user(self, request, user, form, commit=True): | ||
""" | ||
Overwrites django-allauth. | ||
Check there is an invitation and set the appropriate access rights. | ||
Swallow the user object already created, if not. | ||
Otherwise, set access rights according to invitation. | ||
""" | ||
invitation = get_invitation(request) | ||
if not invitation: | ||
self.add_error( | ||
None, | ||
"Die Registrierung ist nur möglich über einen gültigen Einladungslink.", | ||
) | ||
return | ||
|
||
user.is_staff = True | ||
user = super().save_user(request, user, form, commit) | ||
|
||
city: City = invitation.city | ||
if invitation.access_right == AccessRight.CITY_EDITOR: | ||
city.city_editors.add(user) | ||
city.save() | ||
elif invitation.access_right == AccessRight.CITY_ADMIN: | ||
city.city_admins.add(user) | ||
city.save() | ||
|
||
return user |
Oops, something went wrong.