Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
58e207a
set version to dev again
svenhertle Jul 25, 2022
4291a16
use username field to match users for openid connect login
svenhertle Aug 12, 2022
a5516af
name and email of external users cannot be edited
svenhertle Aug 12, 2022
d5cf3b9
show help text for image upload forms
svenhertle Aug 13, 2022
78d7a2e
show direct error when sending a mail to 0 recipients
svenhertle Aug 13, 2022
2b18e3d
migrate to "path" in urls.py
svenhertle Oct 15, 2022
27ac605
update to django 4.1
svenhertle Oct 15, 2022
d5460ac
fix issue when creating new events caused by django update
svenhertle Oct 15, 2022
3b65611
fix placeholders on statistics page
svenhertle Oct 15, 2022
5c385ff
minor design fixes
svenhertle Oct 16, 2022
218c357
do not show "registration disabled" note when link is used
svenhertle Oct 22, 2022
73edcce
improve latex escaping for badges
svenhertle Oct 22, 2022
442ff4c
update to celery 5
svenhertle Apr 23, 2023
c939433
pylint update
svenhertle Apr 23, 2023
46302fe
update to django 4.2
svenhertle Apr 23, 2023
38c6195
update names of badge objects in django admin
svenhertle Apr 23, 2023
4cfbe22
use python 3.11 for github action
svenhertle Apr 23, 2023
c61cf05
make container.sh macos compatible
svenhertle Jun 16, 2023
bebb073
remove "Helfertool" branding on main pages
svenhertle Sep 8, 2023
bcfbcaf
fix container build
svenhertle Sep 8, 2023
2a61785
update python libs
svenhertle Sep 8, 2023
b63c933
update container to debian bookworm
svenhertle Sep 15, 2023
fbf9e75
session cookie expires on browser close and lang cookie is persistent
svenhertle Sep 16, 2023
7776ba3
update translations
svenhertle Sep 30, 2023
b8c054f
Bump version: 3.1.2 → 3.2.0
svenhertle Sep 30, 2023
8ebe1f1
set version to dev again
svenhertle Sep 30, 2023
000d8ce
Bump version: 3.2.0 → 3.2.1
svenhertle Oct 1, 2023
23f7668
fix uuid handling for validation link
svenhertle Oct 1, 2023
f90d9bd
Bump version: 3.2.0 → 3.2.1
svenhertle Oct 1, 2023
ee61ead
increase upload limit in nginx
svenhertle Oct 7, 2023
5ea8ff7
update pillow version
svenhertle Oct 7, 2023
decb28a
Bump version: 3.2.1 → 3.2.2
svenhertle Oct 7, 2023
ffb52e2
update pillow version
svenhertle Apr 9, 2024
1e92519
Bump version: 3.2.2 → 3.2.3
svenhertle Apr 9, 2024
718883d
update dependencies
svenhertle Feb 15, 2025
9b6c0f5
add config option for oidc scopes
svenhertle Feb 15, 2025
5daac2f
Update django.po
franztv82 Nov 1, 2023
8cb61ea
add single language mode
svenhertle Feb 15, 2025
72f843e
add more shirt sizes
svenhertle Feb 15, 2025
0a8ac91
show note about internal and public events
svenhertle Feb 15, 2025
f7b1cd4
add captchas for newsletter and registraion (optional)
svenhertle Mar 8, 2025
1a4e02f
downgrade pylint due to issues
svenhertle Mar 8, 2025
ed029ca
allow to list all users for users that can add users
svenhertle Mar 9, 2025
7659c73
fix pagination for user list
svenhertle Mar 9, 2025
06967a1
fix pagination for event audit log with filters
svenhertle Mar 9, 2025
33c6d40
update python dependencies
svenhertle Mar 9, 2025
dc8e803
update frontend libraries
svenhertle Mar 9, 2025
4b7123e
update translations
svenhertle Mar 9, 2025
4fae161
update bootstrap colors (for alerts)
svenhertle Mar 14, 2025
cacf95e
update data privacy template
svenhertle Mar 14, 2025
78587e5
enable extended result storage for celery
svenhertle Mar 16, 2025
58f317a
fix oidc auth by importing josepy module manually
svenhertle Mar 16, 2025
8d8ab79
improve ldap settings to allow search for users
svenhertle Mar 16, 2025
88e1fda
Bump version: 3.2.3 → 3.3.0
svenhertle Mar 16, 2025
4d8e193
security update for django-select2
svenhertle Jun 3, 2025
e1bdd24
Bump version: 3.3.0 → 3.3.1
svenhertle Jun 3, 2025
27beeb5
set version to dev again
svenhertle Oct 7, 2025
fb3f6d5
add config option for openid connect claim for username
svenhertle Oct 7, 2025
01348d0
support openid connect rp-initiated logout
svenhertle Oct 7, 2025
561fdba
improve performance on index page (fixed slow permission checks)
svenhertle Oct 12, 2025
6827166
remove taskName from log entries
svenhertle Dec 23, 2025
24f944b
automated archiving reminders for events
svenhertle Dec 23, 2025
fbf2587
fix deadline calculation for archiving reminders
svenhertle Dec 25, 2025
9e89c29
add support for matrix id
domrim Dec 18, 2025
c7da149
set default for ask_mxid, ask_phone, ask_shirt and ask_nutrition to f…
svenhertle Dec 27, 2025
f9cd737
Modifies redirects
N0W0RK Jul 8, 2025
7db394e
add more redirects to specific shifts/jobs
svenhertle Dec 27, 2025
006cdba
update contributors
svenhertle Dec 27, 2025
eff45c9
update python dependencies
svenhertle Dec 27, 2025
8565921
update js/css dependencies
svenhertle Dec 27, 2025
06f0788
use debian 13 in container
svenhertle Dec 28, 2025
539008b
replace ckeditor with proseeditor
svenhertle Jan 12, 2026
7f3eb8a
remove corona contact tracing feature
svenhertle Jan 13, 2026
5ea2420
year++
svenhertle Jan 13, 2026
6796b21
add password reset
svenhertle Jan 25, 2026
2d7243d
add new users without setting the password directly
svenhertle Jan 25, 2026
7c4643f
add translation
svenhertle Jan 25, 2026
1ca2680
enforce additional uuid to validation link
svenhertle Jan 25, 2026
857bf76
set DEFAULT_FROM_EMAIL setting
svenhertle Jan 25, 2026
0ce1d3a
security fix: check if helper belongs to event
svenhertle Jan 30, 2026
4dda9ff
add timeout for badge build
svenhertle Jan 30, 2026
54c38ba
Verify that job/mail belongs to event in some views
svenhertle Jan 31, 2026
14ce4fb
show warning about debug mode and weak secret key on status page
svenhertle Feb 1, 2026
19ba925
properly escape og:description meta property
svenhertle Feb 2, 2026
c353f16
prose editor: disable open in new window for links
svenhertle Feb 2, 2026
ccd1d94
fix crash when adding new gift set
svenhertle Feb 2, 2026
2a478f4
add translations
svenhertle Feb 2, 2026
3c5e478
Bump version: 3.3.1 → 4.0.0
svenhertle Feb 2, 2026
651a6d4
set version to dev again
svenhertle Feb 2, 2026
1de8b59
set captcha default values in settings.py to default of helfertool.yaml
svenhertle Feb 2, 2026
fa99a32
fix bug: ask_mxid was set to True for existing events due to wrong mi…
svenhertle Feb 3, 2026
6364eb9
Bump version: 4.0.0 → 4.0.1
svenhertle Feb 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 3.1.2
current_version = 4.0.1
commit = True
tag = True

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/check-codestyle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ jobs:
steps:
- uses: actions/checkout@v2

- name: Set up Python 3.9
- name: Set up Python 3.13
uses: actions/setup-python@v2
with:
python-version: 3.9
python-version: 3.13

- name: Install dependencies via apt
run: |
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ Session.vim
# PyCharm
.idea

# macOS
.DS_Store

# python/django
*.pyc
*.pyo
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.2.0
rev: v4.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- repo: https://github.com/psf/black
rev: 22.3.0
rev: 23.7.0
hooks:
- id: black
- repo: local
Expand Down
3 changes: 3 additions & 0 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
Konrad Gößmann
Dominik Rimpf
franztv82
Johannes Walcher
Johannes Ostner
Sebastian Faul
Expand Down
15 changes: 8 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM debian:bullseye
FROM debian:trixie

ARG CONTAINER_VERSION="unknown"

Expand All @@ -9,14 +9,15 @@ ENV HELFERTOOL_CONFIG_FILE="/config/helfertool.yaml"
RUN apt-get update && apt-get full-upgrade -y && \
apt-get install --no-install-recommends -y \
supervisor nginx rsyslog pwgen curl \
python3 python3-pip python3-dev uwsgi uwsgi-plugin-python3 \
build-essential libldap2-dev libsasl2-dev libmariadb-dev libmagic1 \
python3 python3-venv python3-dev uwsgi uwsgi-plugin-python3 \
build-essential pkg-config ldap-utils libldap2-dev libsasl2-dev libmariadb-dev libpq-dev libmagic1 \
texlive-latex-extra texlive-plain-generic texlive-fonts-recommended texlive-lang-german && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /usr/share/doc/* && \
# add user, some directories and set file permissions
useradd --shell /bin/bash --home-dir /helfertool --create-home helfertool --uid 10001 && \
mkdir -p /config /data /log /helfertool/run && \
chmod 0755 /helfertool/ && \
chmod -R 0777 /helfertool/run && \
# nginx always writes to /var/log/nginx/error.log before reading the config
# so we redirect it to a writable location
Expand All @@ -34,13 +35,13 @@ COPY deployment/container/healthcheck.sh /usr/local/bin/healthcheck
RUN echo $CONTAINER_VERSION > /helfertool/container_version && \
# install python libs
cd /helfertool/src/ && \
pip3 install -U pip && \
pip3 install -r requirements.txt -r requirements_prod.txt && \
python3 -m venv /helfertool/venv/ && \
/helfertool/venv/bin/pip install wheel -r requirements.txt -r requirements_prod.txt && \
rm -rf /root/.cache/pip/ && \
# generate compressed CSS/JS files
HELFERTOOL_CONFIG_FILE=/dev/null python3 manage.py compress --force && \
HELFERTOOL_CONFIG_FILE=/dev/null /helfertool/venv/bin/python manage.py compress --force && \
# copy static files
HELFERTOOL_CONFIG_FILE=/dev/null python3 manage.py collectstatic --noinput && \
HELFERTOOL_CONFIG_FILE=/dev/null /helfertool/venv/bin/python manage.py collectstatic --noinput && \
chmod -R go+rX /helfertool/static && \
# fix permissions
chmod +x /usr/local/bin/helfertool /usr/local/bin/healthcheck
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Please feel free to create issues here in Github!

# License

Copyright (C) 2015-2022 Sven Hertle and contributors
Copyright (C) 2015-2026 Sven Hertle and contributors

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
Expand Down
2 changes: 2 additions & 0 deletions deployment/container/etc/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ http {
uwsgi_pass django;
include /etc/nginx/uwsgi_params;

client_max_body_size 50M;

# CSP is set here, not in django
add_header Content-Security-Policy "default-src 'none'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; form-action 'self'";
}
Expand Down
4 changes: 2 additions & 2 deletions deployment/container/etc/supervisord.conf
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ stderr_logfile_backups=2
priority=10

[program:celery]
command=celery -A helfertool worker -c %(ENV_HELFERTOOL_TASK_WORKERS)s --pidfile=/helfertool/run/celery.pid
command=/helfertool/venv/bin/celery -A helfertool worker -c %(ENV_HELFERTOOL_TASK_WORKERS)s --pidfile=/helfertool/run/celery.pid
directory=/helfertool/src
autostart=true
autorestart=true
Expand All @@ -53,7 +53,7 @@ stderr_logfile_backups=2
priority=20

[program:celerybeat]
command=celery -A helfertool beat --schedule=/data/tmp/celerybeat-schedule --pidfile=/helfertool/run/celerybeat.pid
command=/helfertool/venv/bin/celery -A helfertool beat --schedule=/data/tmp/celerybeat-schedule --pidfile=/helfertool/run/celerybeat.pid
directory=/helfertool/src
autostart=true
autorestart=true
Expand Down
3 changes: 2 additions & 1 deletion deployment/container/etc/uwsgi.conf
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
[uwsgi]
plugin = python39
plugin = python313

chdir = /helfertool/src
venv = /helfertool/venv
wsgi-file = /helfertool/src/helfertool/wsgi.py

socket = /helfertool/run/uwsgi.sock
Expand Down
2 changes: 1 addition & 1 deletion deployment/container/healthcheck.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ die () {

# check webserver (with a host header that is allowed)
cd /helfertool/src
host="$(python3 manage.py shell -c "from django.conf import settings ; print(settings.ALLOWED_HOSTS[0] if settings.ALLOWED_HOSTS else '')")"
host="$(/helfertool/venv/bin/python manage.py shell -c "from django.conf import settings ; print(settings.ALLOWED_HOSTS[0] if settings.ALLOWED_HOSTS else '')")"
curl --fail --silent --output /dev/null -H "Host: $host" http://localhost:8000 || die "Error on HTTP query"

# check supervisord
Expand Down
8 changes: 4 additions & 4 deletions deployment/container/helfertool.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ mkdir -p /data/media /data/tmp /helfertool/run/tmp
# command: init
if [ "$1" = "init" ] ; then
# initialise database with default settings
python3 manage.py loaddata toolsettings
/helfertool/venv/bin/python manage.py loaddata toolsettings

# command: reload
elif [ "$1" = "reload" ] ; then
Expand All @@ -54,7 +54,7 @@ elif [ "$1" = "postrotate" ] ; then
# command: manage
elif [ "$1" = "manage" ] ; then
shift
python3 manage.py $@
/helfertool/venv/bin/python manage.py $@

# command: run
elif [ "$1" = "run" ] ; then
Expand Down Expand Up @@ -82,8 +82,8 @@ elif [ "$1" = "run" ] ; then
sed "s/will_be_replaced/$(pwgen 40 1)/g" /helfertool/etc/supervisord.conf > /helfertool/run/supervisord.conf

# run migrations and go
python3 manage.py migrate --noinput
python3 manage.py createcachetable
/helfertool/venv/bin/python manage.py migrate --noinput
/helfertool/venv/bin/python manage.py createcachetable
exec supervisord --nodaemon --configuration /helfertool/run/supervisord.conf

# help message
Expand Down
4 changes: 3 additions & 1 deletion scripts/container.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@ set -u
# command: build
if [ "$action" = "build" ] ; then
# build without cache and with updated base image
container_version="$(date --utc --iso-8601=seconds)"
container_version="$(date -u -Iseconds)"
podman build --no-cache --pull \
--arch=amd64 \
--build-arg CONTAINER_VERSION="$container_version" \
--format docker \
-t "$container_name:$container_tag" .
Expand All @@ -73,6 +74,7 @@ if [ "$action" = "build" ] ; then
elif [ "$action" = "fastbuild" ] ; then
# build with cache, as fast as possible
podman build \
--arch=amd64 \
--build-arg CONTAINER_VERSION="fastbuild" \
--format docker \
-t "$container_name:$container_tag" .
Expand Down
1 change: 1 addition & 0 deletions src/account/forms/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .account import CreateUserForm, EditUserForm, DeleteUserForm, MergeUserForm
from .agreement import AgreementForm, UserAgreementForm
from .delete import DeleteForm
from .password_reset import CustomPasswordResetForm, CustomSetPasswordForm
40 changes: 37 additions & 3 deletions src/account/forms/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import Group
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from django.views.decorators.debug import sensitive_variables

from django_select2.forms import Select2Widget

Expand All @@ -15,6 +16,7 @@

from ..templatetags.globalpermissions import has_adduser_group, has_addevent_group, has_sendnews_group

import secrets
import logging

logger = logging.getLogger("helfertool.account")
Expand Down Expand Up @@ -88,18 +90,44 @@ class Meta:
),
}

no_password = forms.BooleanField(
label=_("Do not set password now"),
help_text=_("The user is notified via email and can set the password (via the password reset)"),
required=False,
)

def __init__(self, *args, **kwargs):
super(CreateUserForm, self).__init__(*args, **kwargs)

# compared to the django default, we need some data
for f in ("email", "first_name", "last_name"):
self.fields[f].required = True

# if no_password is set, the password is not required, see clean() for more validation
for f in ("password1", "password2"):
self.fields[f].required = False

self.fields["no_password"].widget.attrs["onChange"] = "handle_password()"

@sensitive_variables("password")
def clean(self):
# add LOCAL_USER_CHAR to the beginning
char = settings.LOCAL_USER_CHAR
if char and not self.cleaned_data.get("username").startswith(char):
self.cleaned_data["username"] = char + self.cleaned_data.get("username")

# if no_password is set, set a randomly generated password
# otherwise, check if password is set
if self.cleaned_data["no_password"]:
password = secrets.token_urlsafe(100)
self.cleaned_data["password1"] = password
self.cleaned_data["password2"] = password
else:
if not self.cleaned_data["password1"]:
self.add_error("password1", _("Password is required"))
if not self.cleaned_data["password2"]:
self.add_error("password2", _("Password is required"))

return super(CreateUserForm, self).clean()


Expand All @@ -113,9 +141,15 @@ def __init__(self, *args, **kwargs):

super(EditUserForm, self).__init__(*args, **kwargs)

# set required fields
# set attributes for name/email fields
# if user is local, the fields are required
# if users is from external idp, the fields cannot be changed
for f in ("first_name", "last_name", "email"):
self.fields[f].required = True
if self.instance.has_usable_password():
self.fields[f].required = True
else:
self.fields[f].help_text = _("Managed by external identity provider")
self.fields[f].disabled = True

# adjust labels of active and superuser flags
self._active_initial = self.instance.is_active
Expand Down
11 changes: 1 addition & 10 deletions src/account/forms/agreement.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
from django import forms
from django.conf import settings
from django.utils.translation import ugettext_lazy as _

from ckeditor.widgets import CKEditorWidget
from django.utils.translation import gettext_lazy as _

from helfertool.forms import DatePicker

Expand All @@ -20,13 +18,6 @@ class Meta:
"end": DatePicker,
}

# According to the documentation django-modeltranslations copies the
# widget from the original field.
# But when setting BLEACH_DEFAULT_WIDGET this does not happen.
# Therefore set it manually...
for lang, name in settings.LANGUAGES:
widgets["text_{}".format(lang)] = CKEditorWidget()

def __init__(self, *args, **kwargs):
super(AgreementForm, self).__init__(*args, **kwargs)

Expand Down
75 changes: 75 additions & 0 deletions src/account/forms/password_reset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from django.conf import settings
from django.contrib.auth.forms import PasswordResetForm, SetPasswordForm
from django.core.mail import EmailMessage
from django.template.loader import get_template

from axes.helpers import get_client_ip_address

from captcha.fields import CaptchaField
from helfertool.forms import CustomCaptchaTextInput

import logging

logger = logging.getLogger("helfertool.account")


class CustomPasswordResetForm(PasswordResetForm):
def __init__(self, *args, **kwargs):
super(CustomPasswordResetForm, self).__init__(*args, **kwargs)

if not settings.CAPTCHAS_PASSWORD_RESET:
self.fields.pop("captcha")

def save(self, *args, **kwargs):
super(CustomPasswordResetForm, self).save(*args, **kwargs)

# log password reset attempt
email = self.cleaned_data["email"]
ip_address = get_client_ip_address(kwargs.get("request"))
logger.info(
"password resetattempt",
extra={
"email": email,
"ip": ip_address,
},
)

captcha = CaptchaField(widget=CustomCaptchaTextInput)


class CustomSetPasswordForm(SetPasswordForm):
def save(self, commit=True):
user = super(CustomSetPasswordForm, self).save(commit)

# log password reset
logger.info(
"password reset",
extra={
"changed_user": user.username,
},
)

# sent confirmation mail to user
context = {
"firstname": user.first_name,
"page_title": settings.PAGE_TITLE,
"contact_mail": settings.CONTACT_MAIL,
}
subject_template = get_template("account/password_reset/completed_mail_subject.txt")
subject = subject_template.render(context).strip()

text_template = get_template("account/password_reset/completed_mail.txt")
text = text_template.render(context)

# sent it and handle errors
mail = EmailMessage(
subject,
text,
settings.EMAIL_SENDER_ADDRESS,
[user.email], # to
reply_to=[settings.EMAIL_SENDER_ADDRESS],
)

mail.send(fail_silently=True)

return user
Binary file modified src/account/locale/de/LC_MESSAGES/django.mo
Binary file not shown.
Loading