diff --git a/ticdesk/settings.py b/ticdesk/settings.py index 1e1876a3f1f1f6ba698cbfd020bcfd30ab1d03a0..eafd942c987a3d4144ef306ae3941669c6975920 100644 --- a/ticdesk/settings.py +++ b/ticdesk/settings.py @@ -103,8 +103,8 @@ MIDDLEWARE = [ ] CRON_CLASSES = [ - 'ticdesk_account.cron.CleanGroups', - 'ticdesk_account.cron.CleanPersons', +# 'ticdesk_account.cron.CleanGroups', +# 'ticdesk_account.cron.CleanPersons', 'ticdesk_account.cron.BirthdayMails', 'django_cron.cron.FailedRunsNotificationCronJob' ] @@ -140,7 +140,7 @@ DATABASES = { 'default': { 'CONN_MAX_AGE': 0, 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'HOST': 'db.teckids.org', + 'HOST': 'db-vip.teckids.org', 'NAME': 'ticdesk', 'PASSWORD': POSTGRES_PASSWORD, 'PORT': '5432', diff --git a/ticdesk/templates/ticdesk/base.html b/ticdesk/templates/ticdesk/base.html index e05587127efca6ad9c4cb3bef40231f5172d6a25..ee20e7184bb294c6a62305e9ffe452df315b0825 100644 --- a/ticdesk/templates/ticdesk/base.html +++ b/ticdesk/templates/ticdesk/base.html @@ -14,7 +14,7 @@ <nav class="navbar navbar-light bg-light navbar-expand-md"> {% get_current_language as LANGUAGE_CODE %} <a class="navbar-brand" href="{% url "index" %}"><img - src="https://www.teckids.org/static/logo_{{ LANGUAGE_CODE }}.png" alt="Teckids-Logo" id="logo" /></a> + src="https://www.teckids.org/images/logo.png" alt="Teckids-Logo" id="logo" /></a> <button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar-main"> {% fa 'fa-align-justify' %} diff --git a/ticdesk_account/forms.py b/ticdesk_account/forms.py index 86b737f2520ea0edc42a347791681e47a36362e1..47f885782cfcd6b8499ce578ef6f6334a478e59b 100644 --- a/ticdesk_account/forms.py +++ b/ticdesk_account/forms.py @@ -119,9 +119,9 @@ class RegisterFormBase(forms.Form): # Additional fields accept_tos = forms.BooleanField(label=_('Ich habe die Nutzungsbedingungen gelesen und stimme ihnen zu.'), help_text=_( - 'Bitte lies die <a href="https://www.teckids.org/kleingedrucktes/nutzungsbedingungen/">Nutzungsbedingungen</a> aufmerksam durch!')) + 'Bitte lies die <a href="https://www.teckids.org/pages/nutzungsbedingungen_datenschutz.html">Nutzungsbedingungen</a> aufmerksam durch!')) accept_data = forms.BooleanField(label=_('Ich habe die Hinweise zur Verarbeitung meiner Daten gelesen und stimme diesen zu.'), help_text=_( - 'Ich bin mit der in den <a href="https://www.teckids.org/kleingedrucktes/nutzungsbedingungen/">Nutzungsbedingungen</a> erklärten Verarbeitung meiner Daten einverstanden und alle angegebenen Daten sind richtig. Falls ich jünger als 16 Jahre bin, sind meine Eltern hiermit ebenfalls einverstanden und ich kann dies, auf Anfrage, nachweisen (z.B. durch Herstellung eines Kontakts zu meinen Eltern).')) + 'Ich bin mit der in den <a href="https://www.teckids.org/pages/nutzungsbedingungen_datenschutz.html">Nutzungsbedingungen</a> erklärten Verarbeitung meiner Daten einverstanden und alle angegebenen Daten sind richtig. Falls ich jünger als 16 Jahre bin, sind meine Eltern hiermit ebenfalls einverstanden und ich kann dies, auf Anfrage, nachweisen (z.B. durch Herstellung eines Kontakts zu meinen Eltern).')) def clean(self): # Ensure both passwords are identical diff --git a/ticdesk_account/locale/en/LC_MESSAGES/django.po b/ticdesk_account/locale/en/LC_MESSAGES/django.po index 1b39de05101b21feeba08c840cb4a4215141542d..7e0b41f9a55c74847d466f119b79c06ff07c92fe 100644 --- a/ticdesk_account/locale/en/LC_MESSAGES/django.po +++ b/ticdesk_account/locale/en/LC_MESSAGES/django.po @@ -209,7 +209,7 @@ msgid "Diese E-Mail-Adresse ist bereits belegt!" msgstr "This mail address is already taken!" #: models.py:147 -msgid "Allgemeine Teams" +msgid "Allegemeine Teams" msgstr "" #: models.py:149 diff --git a/ticdesk_account/models.py b/ticdesk_account/models.py index 19e8c0302afa2cbb1cf45be7ef82f2554e4f9c51..6a807bd7c467a1771c18c7f8a0413a63f0ce1621 100644 --- a/ticdesk_account/models.py +++ b/ticdesk_account/models.py @@ -5,7 +5,9 @@ import os import pytz from random import shuffle import string +from time import sleep +import django.db from django.conf import settings from django.contrib.staticfiles import finders from django.core.exceptions import ObjectDoesNotExist @@ -204,7 +206,7 @@ class TeckidsGroup(ldapdb.models.Model, TeckidsLdapMixin): @property def group_type(self): if self.cn.startswith('team-'): - return ('team', _('Allgemeine Teams')) + return ('team', _('Allegemeine Teams')) elif self.cn.startswith('thema-'): return ('topic', _('Thementeams')) elif self.cn.startswith('news-'): @@ -226,7 +228,7 @@ class TeckidsPerson(ldapdb.models.Model, TeckidsLdapMixin): base_dn = 'ou=People,dc=teckids,dc=org' object_classes = ['inetOrgPerson', 'organizationalPerson', 'teckidsPerson', - 'posixAccount', 'shadowAccount', 'inetLocalMailRecipient'] + 'posixAccount', 'shadowAccount', 'inetLocalMailRecipient', 'krb5KDCEntry', 'krb5Principal'] # Name cn = CharField(db_column='cn', max_length=200, @@ -313,11 +315,20 @@ class TeckidsPerson(ldapdb.models.Model, TeckidsLdapMixin): members_share_info = BooleanField( db_column='teckidsMembersShareInfo', default=False) + krb_princ_name = CharField(db_column="krb5PrincipalName") + + krb_princ_version = IntegerField(db_column="krb5KeyVersionNumber", default=1) + + krb_kdc_flags = IntegerField(db_column="krb5KDCFlags", default=126) + def clean(self): # Set default cn if not given if not self.cn: self.cn = "%s %s" % (self.given_name, self.sn) + if not self.krb_princ_name: + self.krb_princ_name = f"{self.uid}@TECKIDS.ORG" + # Set default home directory if not given if not self.home_directory: self.home_directory = "/home/%s" % self.uid @@ -328,8 +339,8 @@ class TeckidsPerson(ldapdb.models.Model, TeckidsLdapMixin): '-uid_number')[0].uid_number + 1 # Activate SASL passthrough if principal exists - if TeckidsKrbPrinc.objects.filter(princ_name='%s@TECKIDS.ORG' % self.uid): - self.set_sasl_passthrough() +# if TeckidsKrbPrinc.objects.filter(princ_name='%s@TECKIDS.ORG' % self.uid): +# self.set_sasl_passthrough() # Update coordinates if postal address is given and changed since last save if self.home_postal_address and (self.uid not in address_cache or @@ -411,32 +422,40 @@ class TeckidsPerson(ldapdb.models.Model, TeckidsLdapMixin): # Generate temporary password # We set the real password later by changing the temporary password to the correct one # through Kerberos, as to leverage passwd's password complexity checking. - temp_password = list(string.ascii_letters) - shuffle(temp_password) - temp_password = ''.join(temp_password) +# temp_password = list(string.ascii_letters) +# shuffle(temp_password) +# temp_password = ''.join(temp_password) # Set the password in LDAP - person.user_password = ssha(temp_password) - person.save() +# person.user_password = ssha(temp_password) +# person.save() # Do PAM authentication for the new user # On ticdesk.teckids.org, this will trigger pam_migrate to create the Kerberos principal - p_conv = pam() - res = p_conv.authenticate( - '%s%s' % (uid, settings.TICDESK_USER_INITIAL_SUFFIX), temp_password, service='ticdesk') - if res: +# res = False +# for tries in range(6): +# p_conv = pam() +# res = p_conv.authenticate( +# '%s%s' % (uid, settings.TICDESK_USER_INITIAL_SUFFIX), temp_password, service='ticdesk') +# if res: +# break +# else: +# sleep(5) + res = django.db.connections.all()[1].client.connection.connection.passwd_s(person.dn, oldpw=None, newpw=password) + person.user_password = "{SASL}%s@TECKIDS.ORG" % person.uid + if not res: # Now set the real password - res = change_kerberos_password(uid, temp_password, password) +# res = change_kerberos_password(uid, temp_password, password) - if not res[0]: +# if not res[0]: # passwd failed - remove the new user to not confuse systems! - person.delete() - return res - else: +# person.delete() +# return res +# else: # PAM failed - remove the new user to not confuse systems! person.delete() return (False, _('Anlegen des Benutzers fehlgeschlagen. Bitte versuche es später erneut!')) - +# # Save again, which will activate SASL passthrough in clean() person.save() @@ -444,10 +463,10 @@ class TeckidsPerson(ldapdb.models.Model, TeckidsLdapMixin): def delete(self): # Look for Kerberos principal with asme name and delete if existing - principals = TeckidsKrbPrinc.objects.filter( - princ_name='%s@TECKIDS.ORG' % self.uid) - if principals.count() > 0: - principals.delete() +# principals = TeckidsKrbPrinc.objects.filter( +# princ_name='%s@TECKIDS.ORG' % self.uid) +# if principals.count() > 0: +# principals.delete() return super(TeckidsPerson, self).delete() @@ -499,13 +518,14 @@ class TeckidsPerson(ldapdb.models.Model, TeckidsLdapMixin): return self._get_objects('guardians', TeckidsParent) -class TeckidsKrbPrinc(ldapdb.models.Model): - class Meta: - managed = False - app_label = 'ticdesk_account' - - base_dn = 'ou=KerberosPrincipals,dc=teckids,dc=org' - object_classes = ['account', 'krb5Principal', 'krb5KDCEntry'] - - # Only need the principal name as all we do is validating existence - princ_name = CharField(db_column='krb5PrincipalName', max_length=100) +#class TeckidsKrbPrinc(ldapdb.models.Model): +# class Meta: +# managed = False +# app_label = 'ticdesk_account' +# +# base_dn = 'ou=KerberosPrincipals,dc=teckids,dc=org' +# object_classes = ['account', 'krb5Principal', 'krb5KDCEntry'] +# +# # Only need the principal name as all we do is validating existence +# princ_name = CharField(db_column='krb5PrincipalName', max_length=100) +# diff --git a/ticdesk_account/util.py b/ticdesk_account/util.py index ba14be1a130757ed6331fbd021dca40b0edd17e4..8113ba79f6c79cefe7ec9b08341114156db797b7 100644 --- a/ticdesk_account/util.py +++ b/ticdesk_account/util.py @@ -12,7 +12,6 @@ import requests def change_kerberos_password(uid, old_password, new_password): # Trigger PAM once to ensure password is correct ret = pam().authenticate(uid, old_password, service='ticdesk') - if ret: # Do expect conversation with passwd as logged-in user child = pexpect.spawn('su -c passwd %s' % uid) @@ -44,13 +43,8 @@ def change_kerberos_password(uid, old_password, new_password): elif ret == 3: return (False, _('Das Passwort enthält nicht genug verschiedene Zeichen.')) - # Try new password - ret = pam().authenticate(uid, new_password, service='ticdesk') - if ret: - return (True, None) - return (False, - _('Unerwarteter Fehler beim Ändern des Passworts. Bitte versuche es in ein paar Minuten noch einmal.')) + return (True, None) return (False, _('Das angegebene alte Passwort ist falsch!')) diff --git a/ticdesk_account/views.py b/ticdesk_account/views.py index a8c9617dce82b42688b5ca0d62aaad3f0a84139e..89fd28b2e834599c2800248d5a517a4ba1371374 100644 --- a/ticdesk_account/views.py +++ b/ticdesk_account/views.py @@ -1,3 +1,4 @@ +import django.db from datetime import datetime from django.conf import settings from django.contrib import auth @@ -64,15 +65,16 @@ def change_password(request): if request.method == 'POST': chpw_form = ChPwForm(request.POST) if chpw_form.is_valid(): - ret = change_kerberos_password( - request.user.username, - chpw_form.cleaned_data['password_old'], - chpw_form.cleaned_data['password_new']) + dn = TeckidsPerson.objects.get(uid=request.user.username).dn + ret = django.db.connections.all()[1].client.connection.connection.passwd_s( + dn, + oldpw=chpw_form.cleaned_data['password_old'], + newpw=chpw_form.cleaned_data['password_new']) - if ret[0]: + if ret: context['success'] = True else: - context['error'] = ret[1] + context['error'] = ret context['chpw_form'] = chpw_form return render(request, 'ticdesk_account/change_password.html', context) diff --git a/ticdesk_org/templates/ticdesk_org/corona.tex b/ticdesk_org/templates/ticdesk_org/corona.tex new file mode 100644 index 0000000000000000000000000000000000000000..d1d58574d8c5b3d5963e28d9be8c842c459fde63 --- /dev/null +++ b/ticdesk_org/templates/ticdesk_org/corona.tex @@ -0,0 +1,32 @@ +{% load i18n latex_helpers %} +{% autoescape off %} +\documentclass{teckidsproto} + +\usepackage{tabu} +\usepackage{longtable} +\geometry{landscape,left=.5cm,right=.5cm} + +\usepackage[export]{adjustbox} + +\keineseitenzahlenbeginn +\begin{document} + \teckidshead{ {{ group.display_name }} \dash {% blocktrans %}Corona{% endblocktrans %}} + + \begin{longtabu} to \linewidth {|l|l|l|l|X[l]|X[l]|} +\hline\rowfont\bfseries Nachname & Vorname & Adresse & Telefon & Ankunft & Abfahrt \\\hline +\endhead +{% for person in persons|dictsort:"sn" %} + \nohyphens{{ person.sn|embrace }} & + \nohyphens{{ person.given_name|embrace }} & + \nohyphens{{ person.home_postal_address|embrace }} & + {% if person.is_member %} + \nohyphens{{ person.mobile|embrace }} & + {% else %} + \nohyphens{{ person.guardians_parents.0.mobile|embrace }} & + {% endif %} + & + \\\hline +{% endfor %} + \end{longtabu} +\end{document} +{% endautoescape %} diff --git a/ticdesk_org/templates/ticdesk_org/persons.html b/ticdesk_org/templates/ticdesk_org/persons.html index 98c6ae733ab6b78897c8ecf500cdfe0495d1f803..28022ba09bdd687e2ca032f0178c066f2def0116 100644 --- a/ticdesk_org/templates/ticdesk_org/persons.html +++ b/ticdesk_org/templates/ticdesk_org/persons.html @@ -25,11 +25,13 @@ <a href="{% url 'org:persons_by_group' group.cn %}?format=pdf&template=list_attendance">{% blocktrans %}Anwesenheitsliste{% endblocktrans %}</a> · <a href="{% url 'org:persons_by_group' group.cn %}?format=pdf&template=list_attendance_sig">{% blocktrans %}Unterschriftenliste{% endblocktrans %}</a> + · + <a href="{% url 'org:persons_by_group' group.cn %}?format=pdf&template=corona">{% blocktrans %}Corona{% endblocktrans %}</a> ) </p> <p> - {% blocktrans %}Kontankt{% endblocktrans %} + {% blocktrans %}Kontakt{% endblocktrans %} <a href="{% url 'org:group_contact_by_group' group.cn %}">Gruppenkommunikation</a> </p> diff --git a/ticdesk_org/views.py b/ticdesk_org/views.py index 819a08d47ea9b94fe81e9936a8f98bd769500c89..926b1898cdcfa22736d68559bb99ae480fa3a253 100644 --- a/ticdesk_org/views.py +++ b/ticdesk_org/views.py @@ -488,7 +488,7 @@ def edit_user(request, uid): 'setting_birthday_mail_days'] # Editable only for board if request.FILES and 'jpeg_photo' in request.FILES: - with Image.open(request.FILE['jpeg_photo']) as image: + with Image.open(request.FILES['jpeg_photo']) as image: resized_image = resizeimage.resize_width( image, 300, validate=False) img_bytes = BytesIO()