Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • hub/hub
  • cyroxx/hub
  • myigel/hub
  • thomasdotwtf/hub
4 results
Select Git revision
Show changes
Commits on Source (244)
......@@ -10,3 +10,9 @@ src/hub/.settings.secret
# local media files
src/media/
.tools/
.vscode/
.venv*/
**/*_cache
......@@ -13,5 +13,5 @@ trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.py]
[*.py, *.toml]
indent_size = 4
......@@ -83,15 +83,6 @@ db.sqlite3-journal
profile_default/
ipython_config.py
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
.pdm-python
# Environments
.env
.venv
......
......@@ -29,10 +29,14 @@ workflow:
# Use build cache to speed up CI
default:
cache:
- key:
files:
- uv.lock
paths:
- $UV_CACHE_DIR
- key: "python-default"
paths:
- .cache/pip
- .cache/pdm
- key:
files:
- src/plainui/yarn.lock
......@@ -68,6 +72,7 @@ default:
POSTGRES_USER: ci
SSO_SECRET_GENERATE: "True"
STORAGE_TYPE: local
UV_CACHE_DIR: .uv-cache
# Kaniko build setup
.build:
......@@ -111,6 +116,8 @@ default:
"ci": true
}
EOF
after_script:
- uv cache prune --ci
# Crane setup
.crane:
......@@ -122,29 +129,32 @@ default:
before_script:
- '[ -n "$DOCKER_CONFIG" ] || export DOCKER_CONFIG=$HOME/.docker'
- crane auth login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
meta_build:
stage: prepare
extends: .build
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
UV_CACHE_DIR: .uv-cache
script:
- /kaniko/executor
$KANIKO_ARGS
$KANIKO_CACHE_ARGS
--dockerfile $CI_PROJECT_DIR/Dockerfile
--target base
--destination $CI_REGISTRY_IMAGE/build_image:bi-$CI_PIPELINE_ID
--target meta
--destination $CI_REGISTRY_IMAGE/meta_image:mi-$CI_PIPELINE_ID
rules:
- when: always
.test:
extends:
- .django_runner_settings
image: $CI_REGISTRY_IMAGE/build_image:bi-$CI_PIPELINE_ID
image: $CI_REGISTRY_IMAGE/meta_image:mi-$CI_PIPELINE_ID
variables:
PDM_CACHE_DIR: .cache/pdm
UV_CACHE_DIR: .uv-cache
needs:
- meta_build
after_script:
- uv cache prune --ci
app_version:
stage: test
......@@ -155,8 +165,8 @@ app_version:
DATABASE_URL: "postgis://ci:runner@db_server/migrations"
script:
- python3 -V
- pdm sync -d --no-editable -G dev
- pdm app_version
- uv sync
- uv run task app_version
allow_failure: true
rules:
- when: always
......@@ -166,8 +176,7 @@ lint:
extends: .test
script:
- python3 -V
- pdm sync -d --no-editable -G dev
- pdm run lint
- tox -e py-lint,html-lint
allow_failure: true
rules:
- when: always
......@@ -177,8 +186,7 @@ format:
extends: .test
script:
- python3 -V
- pdm sync -d --no-editable -G dev
- pdm run format
- tox -e py-format,html-format
- git diff --exit-code -- . ':!src/version.json'
allow_failure: true
rules:
......@@ -191,11 +199,11 @@ format_prettier:
before_script:
- apk add --no-cache git
- corepack enable
- 'echo "cacheFolder: \".yarn/cache/\"" > .yarnrc.yml'
- 'echo "cacheFolder: \".yarn/cache/\"" >> .yarnrc.yml'
- yarn install --immutable
script:
- yarn format
- git diff --exit-code -- . ':!src/version.json'
- git diff --exit-code -- . ':!src/version.json' ':!.yarnrc.yml'
allow_failure: true
rules:
- when: always
......@@ -209,8 +217,8 @@ migration_check:
DATABASE_URL: "postgis://ci:runner@db_server/migrations"
script:
- python3 -V
- pdm sync -d --no-editable -G dev
- pdm run check-migrations
- uv run task manage makemigrations --check
- uv run task manage makemigrations --dry-run
translations_check:
stage: test
......@@ -222,8 +230,8 @@ translations_check:
allow_failure: true
script:
- python3 -V
- pdm install --no-editable --prod
- pdm manage makemessages
- uv sync
- uv run task manage makemessages
- git diff --exit-code -- . ':!src/version.json'
requirements_export:
......@@ -231,16 +239,16 @@ requirements_export:
extends: .test
script:
- python3 -V
- pdm lock --check
- pdm export --no-hashes -o requirements.txt --prod
- pdm export --no-hashes -o requirements.dev.txt --de
- uv lock --check
- uv export --frozen -o=requirements.dev.txt --no-hashes --all-groups
- uv export --frozen -o=requirements.txt --no-hashes --no-dev
- git diff --exit-code -- . ':!src/version.json'
rules:
- changes:
- requirements.txt
- requirements.dev.txt
- project.toml
- pdm.lock
- uv.lock
django-tests:
stage: test
......@@ -256,16 +264,18 @@ django-tests:
DATABASE_URL: "postgis://ci:runner@db_server/self_test"
script:
- python3 -V
- pdm sync -d --no-editable -G dev
- pdm run test
- pdm run coverage xml -i
- pdm run coverage report
- tox -e django-test
- tox -e coverage-report
coverage: '/(?i)total(?:\s+\d+){4}\s+(\d+)%/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: .tools/coverage/coverage.xml
path: .tools/coverage/report.xml
paths:
- .tools/coverage/html_report/
expire_in: 1 week
expose_as: "HTML Coverage Report"
build_nginx:
stage: build
......@@ -515,7 +525,7 @@ cleanup-ci-images:
- crane delete $CI_REGISTRY_IMAGE/ci/hub:ci-${CI_PIPELINE_ID}
- crane delete $CI_REGISTRY_IMAGE/ci/nginx:ci-${CI_PIPELINE_ID}
- crane delete $CI_REGISTRY_IMAGE/ci/hub:ci-${CI_PIPELINE_ID}-test
- crane delete $CI_REGISTRY_IMAGE/build_image:bi-$CI_PIPELINE_ID
- crane delete $CI_REGISTRY_IMAGE/meta_image:mi-$CI_PIPELINE_ID
needs:
- job: publish-production
optional: true
......
......@@ -9,7 +9,7 @@ repos:
- id: check-merge-conflict
- id: check-ast
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.0
rev: v0.9.7
hooks:
- id: ruff
args: [--fix]
......@@ -18,37 +18,40 @@ repos:
rev: v1.0.0
hooks:
- id: check-json5
- repo: https://github.com/pdm-project/pdm
rev: 2.20.1
hooks:
- name: check production requirements
id: pdm-export
args: ["-o", "requirements.txt", "--without-hashes", "--prod"]
files: ^pdm.lock$
- repo: https://github.com/pdm-project/pdm
rev: 2.20.1
hooks:
- name: check development requirements
id: pdm-export
args: ["-o", "requirements.dev.txt", "--without-hashes", "--dev"]
files: ^pdm.lock$
- repo: https://github.com/pdm-project/pdm
rev: 2.20.1
hooks:
- id: pdm-lock-check
- repo: https://github.com/djlint/djLint
rev: v1.36.2
rev: v1.36.4
hooks:
- id: djlint-reformat-django
- id: djlint-reformat-jinja
- id: djlint-django
- id: djlint-jinja
- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.6.2
hooks:
- id: uv-lock
- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.6.2
hooks:
- name: uv-export-prod
id: uv-export
args:
- --frozen
- -o=requirements.txt
- --no-hashes
- --no-dev
- name: uv-export-dev
id: uv-export
args:
- --frozen
- -o=requirements.dev.txt
- --no-hashes
- --all-groups
- repo: local
hooks:
- name: Check for uncreated migrations.
id: migrations-check
language: system
entry: sh -c "pdm manage makemigrations --check --dry-run"
entry: sh -c "uv run task manage makemigrations --check --dry-run"
files: "models/.*.py$"
types:
- python
......
**/*.html
**/*.j2
.yarn
.yarnrc.yml
.venv*
static.dist/
**/vendor/**/*
......
......@@ -2,8 +2,6 @@ activitypub
Andi
ASGI
backoffice
bigbluebutton
BIGBLUEBUTTON
blocktranslate
clonbares
CLUBFRIENDS
......
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
yarnPath: .yarn/releases/yarn-4.6.0.cjs
......@@ -50,11 +50,10 @@ Um eine andere Demo Datei zu laden kann die Umgebungsvariable `DJANGO_LOAD_FIXTU
- Linux: Pakete `python3`, `postgresql` und `gettext`
- Mac: `brew install python3 postgresql gettext` bzw. https://postgresapp.com/
- Windows: [latest stable Python 3 release](https://www.python.org/downloads/windows/) und [PostgreSQL Installer](https://www.postgresql.org/download/windows/) und [gettext binaries](https://mlocati.github.io/articles/gettext-iconv-windows.html)
- Python Paketmanager: `pdm`:
Kann mit OS Installationsmitteln, mit `pip install pdm` oder `pipx install pdm` installiert werden.
- Python Paketmanager: `uv`:
Kann mit OS Installationsmitteln, mit `pip install uv` oder `pipx install uv` installiert werden. (Siehe die [Offizielle Dokumentation](https://docs.astral.sh/uv/getting-started/installation/))
1. Klone dieses Repository an beliebigen Ort.
1. Erstelle die virtuelle Umgebung mit `pdm info`
1. Installiere die python dependencies mit `pdm install`
1. Installiere die python dependencies mit `uv sync`
1. (falls nicht bereits vorhanden) lege einen PostgreSQL-User an (`createuser -P hub_app`) sowie eine Datenbank (`createdb -O hub_app hub`) - unter Linux ggf. via `sudo -u postgres`
1. Konfiguriere deine Instanz mittels:
- Umgebungsvariablen (z.B. direnv, oder env Datei)
......@@ -84,18 +83,17 @@ DATABASES = {
}
```
8. Lege die Datenbanktabellen an: `pdm manage migrate`
9. Richte einen Admin-Nutzer (für die Anwendung) ein: `pdm manage createsuperuser`
10. optional: Import von Demo-Daten: `pdm manage.py loaddata .src/core/fixtures/rc3_2021.json`
8. Lege die Datenbanktabellen an: `uv run task manage migrate`
9. Richte einen Admin-Nutzer (für die Anwendung) ein: `uv run task manage createsuperuser`
10. optional: Import von Demo-Daten: `uv run task.py loaddata .src/core/fixtures/rc3_2021.json`
11. optional: Für deinen Adminuser via [Admin-Seite](http://localhost:8000/c3admin/) einen `ConferenceMember` anlegen um den User für das Frontend freizuschalten
## Nutzung
1. Aktiviere das virtual env `pdm venv activate`
2. Wende ggf. vorhandene DB-Migrations an (wenn du gerade aus dem Git geupdatet hast): `pdm manage migrate`
3. Stelle sicher dass alle Translations aktuell sind: `pdm manage compilemessages`
4. Lasse alle staticfiles einsammeln: `pdm manage collectstatic --noinput`
5. Starte den Dev-Server: `pdm manage runserver`
2. Wende ggf. vorhandene DB-Migrations an (wenn du gerade aus dem Git geupdatet hast): `uv run task manage migrate`
3. Stelle sicher dass alle Translations aktuell sind: `uv run task manage compilemessages`
4. Lasse alle staticfiles einsammeln: `uv run task manage collectstatic --noinput`
5. Starte den Dev-Server: `uv run task manage runserver`
6. Besuche die lokale Instanz: [Admin-Seite](http://localhost:8000/c3admin/), [API](http://localhost:8000/api/) und [plainui-Frontend](http://localhost:8000/)
## PlainUI Development Tipps
......@@ -136,26 +134,26 @@ Wiederverwendbare Elemente können als Komponenten integriert werden. Dafür gib
### Abhängigkeitsverwaltung
Zur Verwaltung der verwendeten python Abhängigkeiten wir der [Paketmanager PDM](https://pdm-project.org/en/latest/) verwendet.
Zur Verwaltung der verwendeten python Abhängigkeiten wir der [Paketmanager UV](https://docs.astral.sh/uv/) verwendet.
Mittels diesem werden die `requirements.txt` und die `requirements.dev.txt` erzeugt.
#### Installation der aktuellen Abhängigkeiten
Um die aktuellen python Abhängigkeiten zu installieren kann das Kommando `pdm install` verwendet werden.
Mit dem Kommando `pdm sync --clean` kann sichergestellt werden, dass genau die Versionen aus dem pdm lock file installiert werden.
Um die aktuellen python Abhängigkeiten zu installieren kann das Kommando `uv sync` verwendet werden.
Mit dem Kommando `ur sync --frozen` kann sichergestellt werden, dass genau die Versionen aus dem uv lock file installiert werden.
_Achtung_: **Nicht in der Lock Datei enthaltene python Pakete werden deinstalliert!**
#### Hinzufügen von neuen Abhängigkeiten
Um neue Abhängigkeiten hinzuzufügen kann das Kommando `pdm add` verwendet werden. Mit dem Parameter `--dev` kann eine Abhängigkeit als Entwicklungs-Abhängigkeit deklariert werden. Diese wird dann in den Produktivinstanzen nicht installiert.
Um neue Abhängigkeiten hinzuzufügen kann das Kommando `uv add` verwendet werden. Mit dem Parameter `--dev` kann eine Abhängigkeit als Entwicklungs-Abhängigkeit deklariert werden. Diese wird dann in den Produktivinstanzen nicht installiert.
Anschließend müssen die `requirements.txt` und `requirements.dev.txt` angepasst werden.
Wenn `pre-commit` verwendet wird, passiert dies automatisch beim commit.
Alternativ können die folgenden Kommandos verwendet werden
```bash
pdm export --no-hashes -o requirements.txt --prod
pdm export --no-hashes -o requirements.dev.txt --dev
uv export --format requirements-txt --no-hashes -o requirements.txt --no-dev
uv export --format requirements-txt --no-hashes -o requirements.dev.txt --all-groups
```
### Debugging DJANGO
......@@ -177,9 +175,9 @@ oder:
### Übersetzungen extrahieren & compilieren
- `pdm manage makemessages`
- `uv run task manage makemessages`
- Die Übersetzungsdateien in `<app>/locale/<sprache>/LC_MESSAGES/django.po` wurden um alle neuen Übersetzungsstrings erweitert. Bearbeiten und jeweils bei `msgstr` die Übersetzungen einfügen!
- `pdm manage compilemessages`
- `uv run task manage compilemessages`
- Zum Ausprobieren müsst ihr django neu starten um die neuen Übersetzungsdateien zu laden
### Übersetzungen definineren
......@@ -189,7 +187,7 @@ oder:
### Static Files einsammeln lassen
- `pdm manage collectstatic`
- `uv run task manage collectstatic`
- ohne dies brechen u.a. Unittests mit Fehlern wie "Missing staticfiles manifest entry" ab
### Tests
......@@ -216,8 +214,8 @@ self.assertEqual(translation, "NoTIcket_trans")
Um die Tests ausführen zu können muss der Datenbanknutzer das Recht haben neue Datenbaken anzulegen.
Dafür mit `psql postgres` die Datenbankkonsole starten. Dort `ALTER USER hub_app CREATEDB;` ausführen (ggf. `hub_app` durch den gewählten Nutzernamen ersetzen). Am Ende mit `Strg-D` Konsole wieder schließen.
Um die Django Tests auszuführen kann das Kommando `pdm test` verwendet werden. \
Um nur die Tests einer App auszuführen stattdessen `pdm test -- <app>.tests` ausführen. \
Um die Django Tests auszuführen kann das Kommando `uv run tox -e django-test` verwendet werden. \
Um nur die Tests einer App auszuführen stattdessen `uv run tox -e django-test -- <app>.tests` ausführen. \
Hilfreiche Argumente sind `-v 2` um die ausgeführten Tests anzuzeigen, `--failfast` um nach dem ersten Fehler abzubrechen, und `--keepdb` um nicht jedes mal die Migrationen durchführen zu müssen. \
Für weitere Infos zu dem Befehl ist https://docs.djangoproject.com/en/3.1/ref/django-admin/#django-admin-test hilfreich.
......@@ -244,7 +242,7 @@ Dieses hat die folgenden Kommandos:
- `ruff check`: Diess Kommando checkt auf häufige Fehler in python code und hat auch teilweise Möglichkeiten diese zu beheben
- `ruff format`: Dieses Kommando re-formatiert alle python dateien nach einem voregebenen Code-Style
### djLink
### djLint
**Leider ist es nicht möglich djLint so zu konfigurieren, dass es automatisch die richtigen Profile verwendet.**
**Wenn eine Integration in einen Editor gewünscht ist, muss dies berücksichtigt werden!**
......
ARG REGISTRY=""
FROM ${REGISTRY}python:3.13-bookworm AS base
COPY --from=ghcr.io/astral-sh/uv:0.5.21 /uv /uvx /bin/
ENV DEBIAN_FRONTEND=noninteractive
ENV PDM_CHECK_UPDATE=false
# Set up uv environment
ENV UV_LINK_MODE=copy UV_COMPILE_BYTECODE=1 UV_TOOL_BIN_DIR=/opt/uv-bin/
RUN echo 'APT::Install-Recommends "false";' > /etc/apt/apt.conf.d/99-unattended-minimal && \
echo 'APT::Install-Suggests "false";' >> /etc/apt/apt.conf.d/99-unattended-minimal && \
......@@ -10,7 +12,6 @@ RUN echo 'APT::Install-Recommends "false";' > /etc/apt/apt.conf.d/99-unattended-
RUN --mount=target=/var/lib/apt/lists/,type=cache,sharing=locked \
--mount=target=/var/cache/apt/archives/,type=cache,sharing=locked \
--mount=target=/root/.cache/pip,type=cache,sharing=locked \
# Prevent apt cache cleaning
rm -f /etc/apt/apt.conf.d/docker-clean && \
apt-get update && \
......@@ -21,12 +22,16 @@ RUN --mount=target=/var/lib/apt/lists/,type=cache,sharing=locked \
dpkg-reconfigure locales && \
locale-gen C.UTF-8 && \
/usr/sbin/update-locale LANG=C.UTF-8 && \
pip install -U pdm && \
# Fix caching issue with kaniko see: https://github.com/GoogleContainerTools/kaniko/issues/3246
mkdir -p /app/plainui
# Add path for future pdm location
ENV PATH="/install/.venv/bin:$PATH"
# Add path for future uv location
ENV PATH="/install/.venv/bin:/opt/uv-bin:$PATH"
######################################### [meta] #############################
FROM base AS meta
RUN uv tool install tox --with tox-uv
######################################### [build] #############################
......@@ -38,25 +43,24 @@ RUN --mount=target=/var/lib/apt/lists/,type=cache,sharing=locked \
--mount=target=/var/cache/apt/archives/,type=cache,sharing=locked \
apt-get update && \
apt-get install \
build-essential \
yarnpkg && \
/usr/bin/yarnpkg global bin corepack enable &&\
build-essential && \
mkdir /install
WORKDIR /install
COPY pyproject.toml pdm.lock README.md /install/
RUN --mount=target=/root/.cache/pdm,type=cache,sharing=locked \
pdm install --check --prod --no-editable
COPY pyproject.toml uv.lock README.md /install/
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-install-project --no-editable
######################################### [build-dev] #########################
FROM build AS build-dev
WORKDIR /install
RUN --mount=target=/root/.cache/pdm,type=cache,sharing=locked \
pdm install --check --dev --no-editable
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-install-project --no-editable
######################################### [node-build] ########################
FROM ${REGISTRY}node:20-alpine AS node-base
RUN mkdir -p /app/plainui/
......@@ -68,16 +72,6 @@ RUN corepack enable && \
/usr/local/bin/yarnpkg set version stable && \
/usr/local/bin/yarnpkg install
######################################### [nginx-forwarder] ###################
FROM ${REGISTRY}nginx:1-alpine-slim AS nginx-forwarder
ENV APP_SOCKET="/run/hub/app.sock"
ENV SCRIPT_NAME=""
COPY deployment/docker/index.html deployment/docker/error_*.html /www/default/
COPY deployment/docker/nginx.conf /etc/nginx/templates/default.conf.template
######################################### [webworker-base] ####################
FROM base AS webworker-base
......@@ -96,7 +90,6 @@ COPY deployment/docker/app.sh /usr/local/bin/app
COPY deployment/docker/check_django.sh /usr/local/bin/hub_healthcheck
COPY deployment/docker/check_psql.py /usr/local/bin/postgres_healthcheck
COPY --from=build /install/.venv /install/.venv
ENV PATH="/install/.venv/bin:$PATH"
RUN install -d -m 0755 -o appuser -g appuser /app/hub /data /app/media /run/hub && \
......@@ -133,7 +126,12 @@ RUN export DJANGO_SETTINGS_MODULE='hub.settings.build' && \
######################################### [nginx] #############################
FROM nginx-forwarder AS nginx
FROM ${REGISTRY}nginx:1-alpine-slim AS nginx
ENV APP_SOCKET="/run/hub/app.sock"
ENV SCRIPT_NAME=""
COPY deployment/docker/index.html deployment/docker/error_*.html /www/default/
COPY deployment/docker/nginx.conf /etc/nginx/templates/default.conf.template
COPY --from=build-static /app/static.dist /www/static
......@@ -141,6 +139,7 @@ COPY --from=build-static /app/static.dist /www/static
FROM webworker-base AS webworker
COPY --from=build /install/.venv /install/.venv
COPY --from=build-static --chown=appuser /app /app
USER appuser
......
......@@ -39,9 +39,18 @@ Prodinstanz: <https://api.events.ccc.de/congress/2024/>
| Kategorie | Endpunkt | GET | POST | PUT | DEL | Beschreibung |
| ---------- | ---------------------------------------- | --- | ---- | --- | --- | ----------------------------------------------------- |
| Auth | `/auth/get-token` | | x | | | Ausstellen eines API-Tokens |
| Persönlich | `/me` | x | | x | | eigenes Profil / Settings |
| Persönlich | `/me/friends` | x | | x | x | Liste der Buddies |
| Persönlich | `/me/badges` | x | | | | Liste aller Badges/Achievements |
| Persönlich | `/me/events` | x | | | | Favorisierte Events |
| Persönlich | `/me/events/<uuid>/` | | | x | x | Events (ent-)favorisieren |
| Persönlich | `/me/friends` | x | | x | x | Liste der Buddies |
| Persönlich | `/me/received-messages/` | x | | | | Übersicht empfangener PN |
| Persönlich | `/me/received-messages/<uuid>` | x | | | | Details einer empfangenen PN |
| Persönlich | `/me/send-message` | | x | | | Send a new PN |
| Persönlich | `/me/sent-messages/` | x | | | | Übersicht gesendeter PN |
| Persönlich | `/me/sent-messages/<uuid>` | x | | | | Details einer gesendeten PN |
| Persönlich | `/me/delete-message/<uuid>` | x | | | | PN löschen |
| Konferenz | `/` | x | | | | Metadaten des Konferenz |
| Konferenz | `/tags` | x | | | | Liste aller Tags auf der Konferenz |
| Konferenz | `/tracks` | x | x | | | Liste der Tracks |
......@@ -64,6 +73,20 @@ Prodinstanz: <https://api.events.ccc.de/congress/2024/>
Per POST werden neue Einträge angelegt, per PUT bestehende verändert.
Details zu den einzelnen Endpunkten folgen in Kürze™.
### API-Beispiel mit cURL
Zuerst einen Token generieren:
```bash
curl https://{API_URL}/api/auth/get-token -H "Content-Type: application/json" -X POST --data '{"username": "{USERNAME}", "password": "{PASSWORD}"}'
```
Mit diesem Token können dann Endpunkte aufgerufen werden die eine Authentifizierung erfordern:
```bash
curl https://{API_URL}/api/me -H "Content-Type: application/json" -H "Authorization: Token {API_TOKEN}"
```
## Development
see [Development.md](./Development.md)
......@@ -45,6 +45,8 @@ if [ ! -e "$HOME/$ADMIN_CREATED" -a -n "$DJANGO_CREATE_ADMIN_PASSWORD" ]; then
touch $HOME/$ADMIN_CREATED
fi
touch $HOME/PREPARATION_DONE
if [ "$1" == "webworker" -o "$STARTMODE" == "webworker" ]; then
# start gunicorn (might be called indirectly via supervisor when started with 'all')
gunicorn_params=()
......@@ -75,12 +77,7 @@ if [ "$1" == "shell" -o "$1" == "createsuperuser" -o "$1" == "test" ]; then
fi
if [ "$1" == "housekeeping" ]; then
interval="${HOUSEKEEPING_SLEEP_SECONDS:-300}"
if [ "$interval" -gt 0 ]; then
python3 $APP_HOME/manage.py housekeeping --forever --forever-delay="$interval"
else
python3 $APP_HOME/manage.py housekeeping
fi
python3 $APP_HOME/manage.py housekeeping --forever
fi
cat <<EOD
......
......@@ -21,7 +21,7 @@ TOKEN = env('API_TOKEN')
PER_PAGE = 100
DELETE_ALL = datetime.now(tz=UTC) - timedelta(weeks=env('THRESHOLD_ALL'))
DELETE_FAILED = datetime.now(tz=UTC) - timedelta(weeks=env('THRESHOLD_FAILED'))
BASE_URL = f'{env('CI_API_V4_URL')}/projects/{env("CI_PROJECT_ID")}'
BASE_URL = f'{env("CI_API_V4_URL")}/projects/{env("CI_PROJECT_ID")}'
if TOKEN is None:
raise ValueError('API_TOKEN is required')
......
{
"name": "hub",
"packageManager": "yarn@4.5.0",
"packageManager": "yarn@4.6.0",
"devDependencies": {
"@cspell/dict-de-de": "^4.0.3",
"@cspell/dict-python": "^4.2.12",
......
This diff is collapsed.
......@@ -2,9 +2,7 @@
name = "hub"
dynamic = ["version"]
description = "Management tool for chaos events."
authors = [
{name = "Roang", email = "lucas@brandstaetter.tech"},
]
authors = [{ name = "Hub Team", email = "hub@cccv.de" }]
dependencies = [
"babel~=2.16",
"bleach~=6.1",
......@@ -39,69 +37,58 @@ dependencies = [
"segno~=1.6.1",
"sentry-sdk>=2.17.0,<3",
"tzdata~=2024.2",
"pdm>=2.11.2",
"psycopg[binary,pool]>=3.2.3",
"gunicorn>=23.0.0",
"pydantic>=2.9.2",
"django-rich>=1.13.0",
"django-csp>=3.8",
"rules>=3.5",
"django-ical>=1.9.2",
"django-stubs-ext>=5.1.2",
"ipython>=8.31.0",
"django-extensions>=3.2.3",
]
requires-python = "==3.13.*"
readme = "README.md"
license = { text = "MIT" }
[project.optional-dependencies]
watchfiles = [
"django-watchfiles>=1.0.0",
]
[tool.pdm]
distribution = false
[tool.pdm.version]
source = "scm"
write_to = "version.txt"
[tool.pdm.dev-dependencies]
lint = [
"ruff>=0.1.11",
"djlint>=1.35.4",
]
local = [
"debugpy>=1.8.0",
"icecream>=2.1.3",
]
[dependency-groups]
dev = [
"tox>=4.11.4",
"coverage>=7.4.0",
"tox-pdm>=0.7.2",
"pre-commit>=3.6.0",
"docutils>=0.21.2",
"pre-commit>=3.6.0",
"tblib>=3.0.0",
"tox-uv>=1.19.0",
"tox>=4.11.4",
"taskipy>=1.14.1",
]
lint = ["ruff>=0.1.11", "djlint>=1.35.4"]
local = ["debugpy>=1.8.0", "icecream>=2.1.3"]
typing = [
"django-stubs[mypy-compatible]>=5.1.1",
]
static-analysis = [
"pylint>=3.3.1",
"pylint-django>=2.6.1",
"pyright>=1.1.392.post0",
"djangorestframework-stubs[compatible-mypy]>=1.4.0",
"django-stubs>=5.1.2",
]
static-analysis = ["pylint>=3.3.1", "pylint-django>=2.6.1"]
watchfiles = ["django-watchfiles>=1.0.0"]
[tool.pdm.scripts]
# Generic scripts
whoami = { shell = "echo `{pdm} -V` was called as '{pdm} -V'" }
# uv currently has no task runner, use taskipy instead.
# Ref: https://github.com/astral-sh/uv/issues/5903
[tool.taskipy.tasks]
# Application version
app_version = "./src/manage.py appversion"
# Django scripts
start = "./src/manage.py runserver"
shell = "./src/manage.py shell"
manage = "./src/manage.py"
start = { cmd = "./src/manage.py runserver", cwd = "." }
shell = { cmd = "./src/manage.py shell_plus", cwd = "." }
manage = { cmd = "./src/manage.py", cwd = "." }
compilemessages = { cmd = "./manage.py compilemessages", cwd = "./src" }
# TOX scripts
all = "tox"
check-migrations = "tox -e migrations"
coverage-report = "tox -e coverage-report"
style-check = {composite = ["format", "lint"]}
format = {composite = ["py-format", "html-format"]}
lint = {composite = ["py-lint", "html-lint"]}
style-check = "task format && task lint"
format = "tox -e py-format,html-format"
lint = "tox -e py-lint,html-lint"
py-format = "tox -e py-format"
py-lint = "tox -e py-lint"
html-format = "tox -e html-format"
......@@ -112,15 +99,20 @@ live-test = "tox -e live-test"
[tool.coverage.run]
data_file = ".tools/coverage/coverage"
dynamic_context = "test_function"
omit =[
"*/migrations/*"]
omit = ["*/migrations/*"]
branch = true
[tool.coverage.report]
show_missing = true
exclude_also = [
"def __repr__",
"if settings.DEBUG",
"if TYPE_CHECKING:",
"raise NotImplementedError",
]
[tool.coverage.xml]
output = ".tools/coverage/coverage.xml"
output = ".tools/coverage/report.xml"
[tool.coverage.html]
directory = ".tools/coverage/html_report"
......@@ -130,10 +122,187 @@ indent = 2
ignore = "H006,H013,H021,H022,H030,H031"
linter_output_format = "{filename}:{line}: {code} {message} {match}"
preserve_blank_lines = true
extend_exclude=".tools"
# We neeed to override the default settings for the GitLab CI
# Ref: https://github.com/djlint/djLint/issues/1028
exclude = ".venv"
extend_exclude = "__pypackages__,_build,.bzr,.direnv,.eggs,.git,.git-rewrite,.hg,.ipynb_checkpoints,.mypy_cache,.nox,.pants.d,.pytest_cache,.pytype,.ruff_cache,.svn,.tox,.venv,.vscode,buck-out,dist,node_modules,venv,.tools"
[tool.mypy]
plugins = ["mypy_django_plugin.main"]
[tool.django-stubs]
django_settings_module = "hub.settings.base"
[tool.tox]
requires = ["tox>=4"]
env_list = [
"py-lint",
"py-format",
"html-lint",
"html-format",
"django-test",
"coverage-repor",
]
work_dir = ".tools/tox"
[tool.tox.env_run_base]
runner = "uv-venv-lock-runner"
skip_install = true
[tool.tox.env.hub.set_env]
ALLOWED_HOSTS = { replace = "env", name = "ALLOWED_HOSTS" }
DATABASE_URL = { replace = "env", name = "DATABASE_URL" }
DJANGO_DEBUG = "I_KNOW_WHAT_I_AM_DOING"
DJANGO_SETTINGS_MODULE = "hub.settings.test"
DISABLE_REQUEST_LOGGING = "True"
SERVE_API = "True"
SERVE_BACKOFFICE = "True"
SERVE_FRONTEND = "True"
SSO_SECRET_GENERATE = "True"
STORAGE_TYPE = "local"
USE_PLAIN_STATICFILES = "True"
METRICS_SERVER_IPS = "127.0.0.1,localhost"
[tool.tox.env.py-lint]
uv_sync_flags = ["--only-group=lint"]
commands = [["ruff", "check", "."]]
[tool.tox.env.py-format]
uv_sync_flags = ["--only-group=lint"]
commands = [["ruff", "format", ".", "--diff"]]
[tool.tox.env.html-lint]
uv_sync_flags = ["--only-group=lint"]
commands = [
[
"djlint",
"--profile",
"jinja",
"-e",
"j2",
"--lint",
".",
],
[
"djlint",
"--profile",
"django",
"-e",
"html",
"--lint",
".",
],
]
[tool.tox.env.html-format]
uv_sync_flags = ["--only-group=lint"]
commands = [
[
"djlint",
"--profile",
"jinja",
"-e",
"j2",
"--reformat",
".",
],
[
"djlint",
"--profile",
"django",
"-e",
"html",
"--reformat",
".",
],
]
[tool.tox.env.django-test]
set_env = [
{ replace = "ref", of = [
"tool",
"tox",
"env",
"hub",
"set_env",
] },
{ PYTHONWARNINGS = "always" },
]
allowlist_externals = ["coverage"]
extras = ["dev"]
commands = [
[
"coverage",
"run",
"--concurrency=multiprocessing",
"{toxinidir}/src/manage.py",
"test",
"-v",
"2",
"--parallel=8",
'src',
{ replace = "posargs", extend = true },
],
[
"coverage",
"combine",
],
]
[tool.tox.env.django-test-single]
set_env = [
{ replace = "ref", of = [
"tool",
"tox",
"env",
"hub",
"set_env",
] },
{ PYTHONWARNINGS = "always" },
]
extras = ["dev"]
change_dir = "{toxinidir}/src"
allowlist_externals = ["coverage"]
commands = [
[
"coverage",
"run",
"./manage.py",
"test",
"-v",
"2",
{ replace = "posargs", extend = true },
],
]
[tool.tox.env.live-test]
groups = "dev"
change_dir = "{toxinidir}"
commands = [["python", "-m", "unittest", "{posargs}"]]
[tool.tox.env.live-test.set_env]
PYTHONWARNINGS = "always"
SERVE_API = "yes"
[tool.tox.env.coverage-report]
deps = ["coverage"]
commands = [["coverage", "report"], ["coverage", "xml"], ["coverage", "html"]]
[tool.pyright]
include = ["src"]
exclude = [
"**/node_modules",
"**/dist",
"**/build",
"**/.venv",
"**/.vscode",
"**/.tools",
]
venvPath = "."
venv = ".venv"
verboseOutput = true
reportMissingTypeArgument = "information"
reportPrivateUsage = "information"
typeCheckingMode = "standard" # "off", "basic", "standard", "strict"
# This file is @generated by PDM.
# Please do not edit it manually.
# This file was autogenerated by uv via the following command:
# uv export --frozen -o=requirements.dev.txt --no-hashes --all-groups
annotated-types==0.7.0
anyio==4.6.2.post1
anyio==4.8.0
asgiref==3.8.1
astroid==3.3.5
asttokens==2.4.1
babel==2.16.0
beautifulsoup4==4.12.3
astroid==3.3.8
asttokens==3.0.0
babel==2.17.0
beautifulsoup4==4.13.3
bleach==6.2.0
blinker==1.9.0
boto3==1.35.71
botocore==1.35.71
cachetools==5.5.0
certifi==2024.8.30
cffi==1.17.1; platform_python_implementation != "PyPy"
boto3==1.36.26
botocore==1.36.26
cachetools==5.5.2
certifi==2025.1.31
cffi==1.17.1 ; platform_python_implementation != 'PyPy'
cfgv==3.4.0
chardet==5.2.0
charset-normalizer==3.4.0
click==8.1.7
charset-normalizer==3.4.1
click==8.1.8
colorama==0.4.6
coverage==7.6.8
cryptography==43.0.3
cssbeautifier==1.15.1
debugpy==1.8.9
coverage==7.6.12
cryptography==44.0.1
cssbeautifier==1.15.3
debugpy==1.8.12
decorator==5.2.0
defusedxml==0.7.1
dep-logic==0.4.9
dill==0.3.9; python_version >= "3.11"
dill==0.3.9
distlib==0.3.9
django==5.1.3
django==5.1.6
django-bootstrap5==24.3
django-cors-headers==4.6.0
django-cors-headers==4.7.0
django-csp==3.8
django-debug-toolbar==4.4.6
django-environ==0.11.2
django-modeltranslation==0.19.11
django-extensions==3.2.3
django-ical==1.9.2
django-modeltranslation==0.19.12
django-oauth-toolkit==3.0.1
django-ratelimit==4.1.0
django-recurrence==1.11.1
django-redis==5.4.0
django-rich==1.13.0
django-storages==1.14.4
django-stubs-ext==5.1.1
django-stubs[mypy-compatible]==5.1.1
django-rich==1.14.0
django-storages==1.14.5
django-stubs==5.1.3
django-stubs-ext==5.1.3
django-timezone-field==7.0
django-watchfiles==1.1.0
django-widget-tweaks==1.5.0
djangorestframework==3.15.2
djlint==1.36.2
djangorestframework-stubs==3.15.3
djlint==1.36.4
docutils==0.21.2
editorconfig==0.12.4
editorconfig==0.17.0
et-xmlfile==2.0.0
executing==2.1.0
filelock==3.16.1
findpython==0.6.2
executing==2.2.0
filelock==3.17.0
freezegun==1.5.1
gunicorn==23.0.0
h11==0.14.0
hishel==0.0.33
httpcore==1.0.7
httpx[socks]==0.27.2
icecream==2.1.3
identify==2.6.2
icalendar==6.1.1
icecream==2.1.4
identify==2.6.7
idna==3.10
installer==0.7.0
isort==5.13.2
jinja2==3.1.4
ipython==8.32.0
isort==6.0.0
jedi==0.19.2
jinja2==3.1.5
jmespath==1.0.1
jsbeautifier==1.15.1
json5==0.9.28
jsbeautifier==1.15.3
json5==0.10.0
jwcrypto==1.5.6
lxml==5.3.0
lxml==5.3.1
markdown-it-py==3.0.0
markdownify==0.13.1
markupsafe==3.0.2
matplotlib-inline==0.1.7
mccabe==0.7.0
mdurl==0.1.2
mistletoe==1.4.0
msgpack==1.1.0
mslex==1.3.0 ; sys_platform == 'win32'
mypy==1.15.0
mypy-extensions==1.0.0
nodeenv==1.9.1
numpy==2.1.3; python_version >= "3.12"
numpy==2.2.3
oauthlib==3.2.2
odfpy==1.4.1
openpyxl==3.1.5
ordered-set==4.1.0
packaging==24.2
pandas==2.2.3
parso==0.8.4
pathspec==0.12.1
pbs-installer==2024.10.16
pdm==2.21.0
pexpect==4.9.0 ; sys_platform != 'emscripten' and sys_platform != 'win32'
pillow==10.4.0
platformdirs==4.3.6
pluggy==1.5.0
pre-commit==4.0.1
psycopg-binary==3.2.3; implementation_name != "pypy"
psycopg-pool==3.2.4
psycopg[binary,pool]==3.2.3
pycparser==2.22; platform_python_implementation != "PyPy"
pydantic==2.10.2
pydantic-core==2.27.1
pygments==2.18.0
pre-commit==4.1.0
prompt-toolkit==3.0.50
psutil==6.1.1
psycopg==3.2.4
psycopg-binary==3.2.4 ; implementation_name != 'pypy'
psycopg-pool==3.2.5
ptyprocess==0.7.0 ; sys_platform != 'emscripten' and sys_platform != 'win32'
pure-eval==0.2.3
pycparser==2.22 ; platform_python_implementation != 'PyPy'
pydantic==2.10.6
pydantic-core==2.27.2
pygments==2.19.1
pyjwt==2.9.0
pylint==3.3.1
pylint==3.3.4
pylint-django==2.6.1
pylint-plugin-utils==0.8.2
pyproject-api==1.8.0
pyproject-hooks==1.2.0
pyproject-api==1.9.0
pyright==1.1.394
python-dateutil==2.9.0.post0
python-dotenv==1.0.1
pytz==2024.2
pytz==2025.1
pyyaml==6.0.2
redis==5.2.0
redis==5.2.1
regex==2024.11.6
requests==2.32.3
requests-file==2.1.0
resolvelib==1.1.0
rich==13.9.4
ruff==0.8.0
ruff==0.9.7
rules==3.5
s3transfer==0.10.4
s3transfer==0.11.2
segno==1.6.1
sentry-sdk==2.19.0
shellingham==1.5.4
six==1.16.0
sentry-sdk==2.22.0
six==1.17.0
sniffio==1.3.1
socksio==1.0.0
soupsieve==2.6
sqlparse==0.5.2
sqlparse==0.5.3
stack-data==0.6.3
taskipy==1.14.1
tblib==3.0.0
tomli==2.2.1
tomlkit==0.13.2
tox==4.23.2
tox-pdm==0.7.2
tox==4.24.1
tox-uv==1.25.0
tqdm==4.67.1
truststore==0.10.0; python_version >= "3.10"
types-pyyaml==6.0.12.20240917
traitlets==5.14.3
types-pyyaml==6.0.12.20241230
types-requests==2.32.0.20241016
typing-extensions==4.12.2
tzdata==2024.2
unearth==0.17.2
urllib3==2.2.3
virtualenv==20.27.1
urllib3==2.3.0
uv==0.6.2
virtualenv==20.29.2
watchfiles==1.0.4
wcwidth==0.2.13
webencodings==0.5.1
# This file is @generated by PDM.
# Please do not edit it manually.
# This file was autogenerated by uv via the following command:
# uv export --frozen -o=requirements.txt --no-hashes --no-dev
annotated-types==0.7.0
anyio==4.6.2.post1
asgiref==3.8.1
babel==2.16.0
beautifulsoup4==4.12.3
asttokens==3.0.0
babel==2.17.0
beautifulsoup4==4.13.3
bleach==6.2.0
blinker==1.9.0
boto3==1.35.71
botocore==1.35.71
certifi==2024.8.30
cffi==1.17.1; platform_python_implementation != "PyPy"
charset-normalizer==3.4.0
cryptography==43.0.3
boto3==1.36.26
botocore==1.36.26
certifi==2025.1.31
cffi==1.17.1 ; platform_python_implementation != 'PyPy'
charset-normalizer==3.4.1
colorama==0.4.6 ; sys_platform == 'win32'
cryptography==44.0.1
decorator==5.2.0
defusedxml==0.7.1
dep-logic==0.4.9
distlib==0.3.9
django==5.1.3
django==5.1.6
django-bootstrap5==24.3
django-cors-headers==4.6.0
django-cors-headers==4.7.0
django-csp==3.8
django-debug-toolbar==4.4.6
django-environ==0.11.2
django-modeltranslation==0.19.11
django-extensions==3.2.3
django-ical==1.9.2
django-modeltranslation==0.19.12
django-oauth-toolkit==3.0.1
django-ratelimit==4.1.0
django-recurrence==1.11.1
django-redis==5.4.0
django-rich==1.13.0
django-storages==1.14.4
django-rich==1.14.0
django-storages==1.14.5
django-stubs-ext==5.1.3
django-timezone-field==7.0
django-widget-tweaks==1.5.0
djangorestframework==3.15.2
et-xmlfile==2.0.0
filelock==3.16.1
findpython==0.6.2
executing==2.2.0
freezegun==1.5.1
gunicorn==23.0.0
h11==0.14.0
hishel==0.0.33
httpcore==1.0.7
httpx[socks]==0.27.2
icalendar==6.1.1
idna==3.10
installer==0.7.0
jinja2==3.1.4
ipython==8.32.0
jedi==0.19.2
jinja2==3.1.5
jmespath==1.0.1
jwcrypto==1.5.6
lxml==5.3.0
lxml==5.3.1
markdown-it-py==3.0.0
markdownify==0.13.1
markupsafe==3.0.2
matplotlib-inline==0.1.7
mdurl==0.1.2
mistletoe==1.4.0
msgpack==1.1.0
numpy==2.1.3; python_version >= "3.12"
numpy==2.2.3
oauthlib==3.2.2
odfpy==1.4.1
openpyxl==3.1.5
ordered-set==4.1.0
packaging==24.2
pandas==2.2.3
pbs-installer==2024.10.16
pdm==2.21.0
parso==0.8.4
pexpect==4.9.0 ; sys_platform != 'emscripten' and sys_platform != 'win32'
pillow==10.4.0
platformdirs==4.3.6
psycopg-binary==3.2.3; implementation_name != "pypy"
psycopg-pool==3.2.4
psycopg[binary,pool]==3.2.3
pycparser==2.22; platform_python_implementation != "PyPy"
pydantic==2.10.2
pydantic-core==2.27.1
pygments==2.18.0
prompt-toolkit==3.0.50
psycopg==3.2.4
psycopg-binary==3.2.4 ; implementation_name != 'pypy'
psycopg-pool==3.2.5
ptyprocess==0.7.0 ; sys_platform != 'emscripten' and sys_platform != 'win32'
pure-eval==0.2.3
pycparser==2.22 ; platform_python_implementation != 'PyPy'
pydantic==2.10.6
pydantic-core==2.27.2
pygments==2.19.1
pyjwt==2.9.0
pyproject-hooks==1.2.0
python-dateutil==2.9.0.post0
python-dotenv==1.0.1
pytz==2024.2
redis==5.2.0
pytz==2025.1
redis==5.2.1
requests==2.32.3
requests-file==2.1.0
resolvelib==1.1.0
rich==13.9.4
rules==3.5
s3transfer==0.10.4
s3transfer==0.11.2
segno==1.6.1
sentry-sdk==2.19.0
shellingham==1.5.4
six==1.16.0
sniffio==1.3.1
socksio==1.0.0
sentry-sdk==2.22.0
six==1.17.0
soupsieve==2.6
sqlparse==0.5.2
tomlkit==0.13.2
truststore==0.10.0; python_version >= "3.10"
sqlparse==0.5.3
stack-data==0.6.3
traitlets==5.14.3
typing-extensions==4.12.2
tzdata==2024.2
unearth==0.17.2
urllib3==2.2.3
virtualenv==20.27.1
urllib3==2.3.0
wcwidth==0.2.13
webencodings==0.5.1
from typing import Optional
from django_ical.views import ICalFeed
from django.utils.text import slugify
from core.models import (
Conference,
Event,
)
class EventICalFeed(ICalFeed):
"""
EventICalFeed serializes Events to an iCal response.
"""
def __init__(self, events: list[Event], name: Optional[str] = None, conference: Optional[Conference] = None):
super().__init__()
self.name = name
self.conference = conference
self.events = events
def product_id(self) -> str:
issuer = self.conference.name if self.conference else 'Hub'
product = self.name if self.name else 'iCal export'
return f'-//{issuer}//{product}'
def title(self) -> str:
if self.name:
return self.name
return 'Hub iCal export'
def items(self) -> list[Event]:
return self.events
def item_title(self, item) -> str:
return item.name
def item_description(self, item) -> str:
return item.description
def item_start_datetime(self, item):
return item.schedule_start
def item_end_datetime(self, item):
return item.schedule_end
def item_location(self, item) -> str:
if item.room:
return item.room.name
if item.location:
return item.location
return ''
def item_guid(self, item) -> str:
return item.pk
def item_categories(self, item) -> list[str]:
categories = []
if item.recording == Event.Recording.YES:
categories.append('recorded')
elif item.recording == Event.Recording.NO:
categories.append('not recorded')
if item.kind == Event.Kind.OFFICIAL or item.assembly.is_official:
categories.append('official')
if item.track:
categories.append(item.track.name)
return categories
def file_name(self) -> str:
return slugify(self.title()) + '.ics'