This commit is contained in:
@@ -11,6 +11,7 @@ disable=missing-docstring,
|
||||
missing-class-docstring,
|
||||
missing-function-docstring,
|
||||
consider-using-f-string,
|
||||
duplicate-code,
|
||||
|
||||
[BASIC]
|
||||
|
||||
@@ -22,8 +23,11 @@ good-names=_,
|
||||
i,
|
||||
j,
|
||||
k,
|
||||
n,
|
||||
r,
|
||||
s,
|
||||
t,
|
||||
pk,
|
||||
|
||||
[FORMAT]
|
||||
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
import argparse
|
||||
import coverage
|
||||
import datetime
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
import coverage
|
||||
from selenium import webdriver
|
||||
from selenium.common.exceptions import WebDriverException
|
||||
|
||||
|
||||
class Command(object):
|
||||
class Command: # pylint: disable=too-few-public-methods
|
||||
default_browser = 'firefox'
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -1 +1 @@
|
||||
default_app_config = 'dav_auth.apps.AppConfig'
|
||||
default_app_config = 'dav_auth.apps.AppConfig' # pylint: disable=invalid-name
|
||||
|
||||
@@ -8,5 +8,5 @@ DEFAULT_SETTINGS = (
|
||||
|
||||
class AppConfig(_AppConfig):
|
||||
name = 'dav_auth'
|
||||
verbose_name = u'DAV Benutzerverwaltung'
|
||||
verbose_name = 'DAV Benutzerverwaltung'
|
||||
default_settings = DEFAULT_SETTINGS
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
from dav_base.emails import AbstractMail
|
||||
|
||||
|
||||
class PasswordSetEmail(AbstractMail):
|
||||
_subject = u'Zugangsdaten'
|
||||
class PasswordSetEmail(AbstractMail): # pylint: disable=too-few-public-methods
|
||||
_subject = 'Zugangsdaten'
|
||||
_template_name = 'dav_auth/emails/password_set.txt'
|
||||
|
||||
def __init__(self, user, password):
|
||||
@@ -11,12 +11,12 @@ class PasswordSetEmail(AbstractMail):
|
||||
self._password = password
|
||||
|
||||
def _get_recipients(self):
|
||||
r = u'"{fullname}" <{email}>'.format(fullname=self._user.get_full_name(),
|
||||
r = '"{fullname}" <{email}>'.format(fullname=self._user.get_full_name(),
|
||||
email=self._user.email)
|
||||
return [r]
|
||||
|
||||
def _get_context_data(self, extra_context=None):
|
||||
context = super(PasswordSetEmail, self)._get_context_data(extra_context=extra_context)
|
||||
context = super()._get_context_data(extra_context=extra_context)
|
||||
context.update({
|
||||
'fullname': self._user.get_full_name(),
|
||||
'username': self._user.username,
|
||||
|
||||
@@ -9,13 +9,13 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class LoginForm(auth_forms.AuthenticationForm):
|
||||
username = auth_forms.UsernameField(
|
||||
label=_(u'E-Mail-Adresse'),
|
||||
label=_('E-Mail-Adresse'),
|
||||
widget=forms.TextInput(attrs={'autofocus': True}),
|
||||
)
|
||||
|
||||
error_messages = {
|
||||
'invalid_login': _(u'Benutzername oder Passwort falsch.'),
|
||||
'inactive': _("This account is inactive."),
|
||||
'invalid_login': _('Benutzername oder Passwort falsch.'),
|
||||
'inactive': _('This account is inactive.'),
|
||||
}
|
||||
|
||||
def clean_username(self):
|
||||
@@ -24,18 +24,18 @@ class LoginForm(auth_forms.AuthenticationForm):
|
||||
|
||||
|
||||
class SetPasswordForm(forms.Form):
|
||||
new_password = forms.CharField(label=_(u'Neues Passwort'),
|
||||
new_password = forms.CharField(label=_('Neues Passwort'),
|
||||
widget=forms.PasswordInput)
|
||||
new_password_repeat = forms.CharField(label=_(u'Neues Passwort wiederholen'),
|
||||
new_password_repeat = forms.CharField(label=_('Neues Passwort wiederholen'),
|
||||
widget=forms.PasswordInput)
|
||||
send_password_mail = forms.BooleanField(required=False,
|
||||
initial=False,
|
||||
label=_(u'Neues Passwort per E-Mail zusenden'),
|
||||
label=_('Neues Passwort per E-Mail zusenden'),
|
||||
)
|
||||
|
||||
def __init__(self, user, *args, **kwargs):
|
||||
self.user = user
|
||||
super(SetPasswordForm, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def clean_new_password(self):
|
||||
password = self.cleaned_data.get('new_password')
|
||||
@@ -48,7 +48,7 @@ class SetPasswordForm(forms.Form):
|
||||
if password1 and password2:
|
||||
if password1 != password2:
|
||||
raise forms.ValidationError(
|
||||
ugettext(u'Passwörter stimmen nicht überein'),
|
||||
ugettext('Passwörter stimmen nicht überein'),
|
||||
code='password_mismatch',
|
||||
)
|
||||
return password2
|
||||
@@ -63,7 +63,7 @@ class SetPasswordForm(forms.Form):
|
||||
|
||||
class CreateAndSendPasswordForm(forms.Form):
|
||||
username = auth_forms.UsernameField(
|
||||
label=_(u'E-Mail-Adresse'),
|
||||
label=_('E-Mail-Adresse'),
|
||||
widget=forms.TextInput(attrs={'autofocus': True}),
|
||||
)
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@ from ..emails import PasswordSetEmail
|
||||
|
||||
|
||||
TEST_USERNAME = 'user'
|
||||
TEST_PASSWORD = u'me||ön 21ABll'
|
||||
TEST_PASSWORD = 'me||ön 21ABll'
|
||||
TEST_EMAIL = 'root@localhost'
|
||||
|
||||
PASSWORD_EMAIL_TEMPLATE = u"""Hallo {fullname},
|
||||
PASSWORD_EMAIL_TEMPLATE = """Hallo {fullname},
|
||||
|
||||
Benutzername: {username}
|
||||
Passwort: {password}
|
||||
@@ -23,7 +23,7 @@ URL: {base_url}/
|
||||
|
||||
class EmailTestCase(EmailTestMixin, TestCase):
|
||||
def setUp(self):
|
||||
super(EmailTestCase, self).setUp()
|
||||
super().setUp()
|
||||
model = get_user_model()
|
||||
self.user = model.objects.create_user(username=TEST_USERNAME, password=TEST_PASSWORD, email=TEST_EMAIL)
|
||||
|
||||
@@ -38,7 +38,7 @@ class EmailTestCase(EmailTestMixin, TestCase):
|
||||
|
||||
self.assertSender(mail)
|
||||
self.assertRecipients(mail, [self.user])
|
||||
self.assertSubject(mail, u'Zugangsdaten')
|
||||
self.assertSubject(mail, 'Zugangsdaten')
|
||||
|
||||
expected_body = PASSWORD_EMAIL_TEMPLATE.format(
|
||||
fullname=self.user.get_full_name(),
|
||||
|
||||
@@ -9,7 +9,7 @@ from dav_base.tests.generic import FormDataSet, FormsTestCase
|
||||
from ..forms import LoginForm, SetPasswordForm, CreateAndSendPasswordForm
|
||||
|
||||
TEST_USERNAME = 'root@localhost'
|
||||
TEST_PASSWORD = u'me||ön 21ABll'
|
||||
TEST_PASSWORD = 'me||ön 21ABll'
|
||||
TEST_EMAIL = TEST_USERNAME
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@ class LoginFormTestCase(FormsTestCase):
|
||||
|
||||
def test_labels(self):
|
||||
form = self.form_class()
|
||||
self.assertEqual(form.fields['username'].label, ugettext(u'E-Mail-Adresse'))
|
||||
self.assertEqual(form.fields['password'].label, ugettext(u'Password'))
|
||||
self.assertEqual(form.fields['username'].label, ugettext('E-Mail-Adresse'))
|
||||
self.assertEqual(form.fields['password'].label, ugettext('Password'))
|
||||
|
||||
def test_required(self):
|
||||
form = self.form_class()
|
||||
@@ -38,28 +38,28 @@ class LoginFormTestCase(FormsTestCase):
|
||||
FormDataSet({'username': '', 'password': self.test_password},
|
||||
expected_errors=[('username', 'required')]),
|
||||
]
|
||||
super(LoginFormTestCase, self).test_invalid_data(data_sets=data_sets)
|
||||
super().test_invalid_data(data_sets=data_sets)
|
||||
|
||||
def test_password_empty(self):
|
||||
data_sets = [
|
||||
FormDataSet({'username': self.test_username, 'password': ''},
|
||||
expected_errors=[('password', 'required')]),
|
||||
]
|
||||
super(LoginFormTestCase, self).test_invalid_data(data_sets=data_sets)
|
||||
super().test_invalid_data(data_sets=data_sets)
|
||||
|
||||
def test_invalid_username(self):
|
||||
data_sets = [
|
||||
FormDataSet({'username': self.test_username[::-1], 'password': self.test_password},
|
||||
expected_errors=[('__all__', 'invalid_login')]),
|
||||
]
|
||||
super(LoginFormTestCase, self).test_invalid_data(data_sets=data_sets)
|
||||
super().test_invalid_data(data_sets=data_sets)
|
||||
|
||||
def test_invalid_password(self):
|
||||
data_sets = [
|
||||
FormDataSet({'username': self.test_username, 'password': self.test_password[::-1]},
|
||||
expected_errors=[('__all__', 'invalid_login')]),
|
||||
]
|
||||
super(LoginFormTestCase, self).test_invalid_data(data_sets=data_sets)
|
||||
super().test_invalid_data(data_sets=data_sets)
|
||||
|
||||
def test_inactive_user(self):
|
||||
self.user.is_active = False
|
||||
@@ -68,13 +68,13 @@ class LoginFormTestCase(FormsTestCase):
|
||||
FormDataSet({'username': self.test_username, 'password': self.test_password},
|
||||
expected_errors=[('__all__', 'invalid_login')]),
|
||||
]
|
||||
super(LoginFormTestCase, self).test_invalid_data(data_sets=data_sets)
|
||||
super().test_invalid_data(data_sets=data_sets)
|
||||
|
||||
def test_valid_credentials(self):
|
||||
data_sets = [
|
||||
FormDataSet({'username': self.test_username, 'password': self.test_password}),
|
||||
]
|
||||
super(LoginFormTestCase, self).test_valid_data(data_sets=data_sets)
|
||||
super().test_valid_data(data_sets=data_sets)
|
||||
|
||||
|
||||
class SetPasswordFormTestCase(FormsTestCase):
|
||||
@@ -98,56 +98,56 @@ class SetPasswordFormTestCase(FormsTestCase):
|
||||
FormDataSet({'new_password': 'mellonAB12+-', 'new_password_repeat': 'mellonAB13+-'},
|
||||
[('new_password_repeat', 'password_mismatch')]),
|
||||
]
|
||||
super(SetPasswordFormTestCase, self).test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
|
||||
super().test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
|
||||
|
||||
def test_empty(self):
|
||||
data_sets = [
|
||||
FormDataSet({'new_password': '', 'new_password_repeat': ''},
|
||||
[('new_password', 'required')]),
|
||||
]
|
||||
super(SetPasswordFormTestCase, self).test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
|
||||
super().test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
|
||||
|
||||
def test_too_short(self):
|
||||
data_sets = [
|
||||
FormDataSet({'new_password': 'mellon', 'new_password_repeat': 'mellon'},
|
||||
[('new_password', 'password_too_short')]),
|
||||
]
|
||||
super(SetPasswordFormTestCase, self).test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
|
||||
super().test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
|
||||
|
||||
def test_entirely_numeric(self):
|
||||
data_sets = [
|
||||
FormDataSet({'new_password': '1357924680', 'new_password_repeat': '1357924680'},
|
||||
[('new_password', 'password_entirely_numeric')]),
|
||||
]
|
||||
super(SetPasswordFormTestCase, self).test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
|
||||
super().test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
|
||||
|
||||
def test_too_similar(self):
|
||||
data_sets = [
|
||||
FormDataSet({'new_password': self.test_username, 'new_password_repeat': self.test_username},
|
||||
[('new_password', 'password_too_similar')]),
|
||||
]
|
||||
super(SetPasswordFormTestCase, self).test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
|
||||
super().test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
|
||||
|
||||
def test_too_common(self):
|
||||
data_sets = [
|
||||
FormDataSet({'new_password': 'password', 'new_password_repeat': 'password'},
|
||||
[('new_password', 'password_too_common')]),
|
||||
]
|
||||
super(SetPasswordFormTestCase, self).test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
|
||||
super().test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
|
||||
|
||||
def test_valid(self):
|
||||
data_sets = [
|
||||
FormDataSet({'new_password': 'mellonAB12+-', 'new_password_repeat': 'mellonAB12+-'}),
|
||||
FormDataSet({'new_password': 'mellonAB12+-', 'new_password_repeat': 'mellonAB12+-',
|
||||
'send_password_mail': True}),
|
||||
FormDataSet({'new_password': u'"ä§ MellonAB12+-', 'new_password_repeat': u'"ä§ MellonAB12+-'}),
|
||||
FormDataSet({'new_password': '"ä§ MellonAB12+-', 'new_password_repeat': '"ä§ MellonAB12+-'}),
|
||||
FormDataSet({'new_password': 'mellon12' * 128, 'new_password_repeat': 'mellon12' * 128}),
|
||||
]
|
||||
super(SetPasswordFormTestCase, self).test_valid_data(data_sets=data_sets, form_kwargs={'user': self.user})
|
||||
super().test_valid_data(data_sets=data_sets, form_kwargs={'user': self.user})
|
||||
|
||||
def test_save(self):
|
||||
new_passwords = [
|
||||
u'"ä§ Mellon12'
|
||||
'"ä§ Mellon12'
|
||||
'mellon12' * 128,
|
||||
]
|
||||
|
||||
@@ -162,7 +162,7 @@ class SetPasswordFormTestCase(FormsTestCase):
|
||||
@skip('Function is implemented in SetPasswordView instead of SetPasswordForm')
|
||||
def test_save_with_mail(self): # pragma: no cover
|
||||
new_passwords = [
|
||||
u'"ä§ Mellon12'
|
||||
'"ä§ Mellon12'
|
||||
'mellon12' * 128,
|
||||
]
|
||||
|
||||
@@ -193,7 +193,7 @@ class CreateAndSendPasswordFormTestCase(FormsTestCase):
|
||||
|
||||
def test_labels(self):
|
||||
form = self.form_class()
|
||||
self.assertEqual(form.fields['username'].label, ugettext(u'E-Mail-Adresse'))
|
||||
self.assertEqual(form.fields['username'].label, ugettext('E-Mail-Adresse'))
|
||||
|
||||
def test_required(self):
|
||||
form = self.form_class()
|
||||
|
||||
@@ -9,7 +9,7 @@ from selenium.webdriver.common.keys import Keys
|
||||
from dav_base.tests.generic import ScreenshotTestCase
|
||||
|
||||
TEST_USERNAME = 'root@localhost'
|
||||
TEST_PASSWORD = u'me||ön 21ABll'
|
||||
TEST_PASSWORD = 'me||ön 21ABll'
|
||||
TEST_EMAIL = TEST_USERNAME
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ class TestCase(ScreenshotTestCase):
|
||||
screenshot_prefix = 'dav_auth-'
|
||||
|
||||
def setUp(self):
|
||||
super(TestCase, self).setUp()
|
||||
super().setUp()
|
||||
# Need a test user
|
||||
self.test_username = TEST_USERNAME
|
||||
self.test_password = TEST_PASSWORD
|
||||
@@ -105,7 +105,7 @@ class TestCase(ScreenshotTestCase):
|
||||
|
||||
# Click on 'set password' -> save set password page
|
||||
user_menu = c.find_element_by_css_selector('#login-widget ul')
|
||||
link = user_menu.find_element_by_partial_link_text(ugettext(u'Passwort ändern'))
|
||||
link = user_menu.find_element_by_partial_link_text(ugettext('Passwort ändern'))
|
||||
link.click()
|
||||
password_field = self.wait_on_presence(c, (By.ID, 'id_new_password'))
|
||||
self.save_screenshot('empty_set_password_form', sequence=sequence_name)
|
||||
@@ -189,7 +189,7 @@ class TestCase(ScreenshotTestCase):
|
||||
dropdown_button = self.wait_on_presence(c, (By.ID, 'user_dropdown_button'))
|
||||
dropdown_button.click()
|
||||
user_menu = c.find_element_by_css_selector('#login-widget ul')
|
||||
link = user_menu.find_element_by_partial_link_text(ugettext(u'Logout'))
|
||||
link = user_menu.find_element_by_partial_link_text(ugettext('Logout'))
|
||||
link.click()
|
||||
self.wait_until_stale(c, user_menu)
|
||||
self.save_screenshot('logout_succeed', sequence=sequence_name)
|
||||
@@ -200,7 +200,7 @@ class TestCase(ScreenshotTestCase):
|
||||
self.wait_on_presence(c, (By.ID, 'id_username'))
|
||||
|
||||
# Locate password recreate link, click it -> save password recreate form
|
||||
link = c.find_element_by_partial_link_text(ugettext(u'Passwort vergessen'))
|
||||
link = c.find_element_by_partial_link_text(ugettext('Passwort vergessen'))
|
||||
link.click()
|
||||
username_field = self.wait_on_presence(c, (By.ID, 'id_username'))
|
||||
self.save_screenshot('empty_recreate_password_form', sequence=sequence_name)
|
||||
@@ -212,7 +212,7 @@ class TestCase(ScreenshotTestCase):
|
||||
self.save_screenshot('recreate_password_invalid_user', sequence=sequence_name)
|
||||
|
||||
# Locate password recreate link, click it
|
||||
link = c.find_element_by_partial_link_text(ugettext(u'Passwort vergessen'))
|
||||
link = c.find_element_by_partial_link_text(ugettext('Passwort vergessen'))
|
||||
link.click()
|
||||
username_field = self.wait_on_presence(c, (By.ID, 'id_username'))
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class TemplatesTestCase(SimpleTestCase):
|
||||
@tag('browser')
|
||||
class TestCase(SeleniumAuthMixin, SeleniumTestCase):
|
||||
def setUp(self):
|
||||
super(TestCase, self).setUp()
|
||||
super().setUp()
|
||||
# Need a test user
|
||||
self.test_username = TEST_USERNAME
|
||||
self.test_password = TEST_PASSWORD
|
||||
|
||||
@@ -8,19 +8,19 @@ from ..validators import PasswordScoreValidator, CustomWordlistPasswordValidator
|
||||
class PasswordScoreValidatorTestCase(SimpleTestCase):
|
||||
def test_too_little_score(self):
|
||||
passwords = [
|
||||
u'', # score = 0
|
||||
u'abcdefghijklmnopq', # score = 17
|
||||
u'Abcdefghijklmnop', # score = 16 + 1
|
||||
u'ABcdefghijklmno', # score = 15 + 2
|
||||
u'AB1defghijklmn', # score = 14 + 2 + 1
|
||||
u'AB12efghijklm', # score = 13 + 2 + 2
|
||||
u'AB12+fghijkl', # score = 12 + 2 + 2 + 1
|
||||
u'AB12+-ghijk', # score = 11 + 2 + 2 + 2
|
||||
u'AB12+-*hij', # score = 10 + 2 + 2 + 3
|
||||
u'AB12+-*hi/', # score = 10 + 2 + 2 + 3
|
||||
u'AB12+-*hi3', # score = 10 + 2 + 2 + 3
|
||||
u'AB12+-*hiC', # score = 10 + 2 + 2 + 3
|
||||
u'abcbbbgbbjklmnopqr', # score = 17
|
||||
'', # score = 0
|
||||
'abcdefghijklmnopq', # score = 17
|
||||
'Abcdefghijklmnop', # score = 16 + 1
|
||||
'ABcdefghijklmno', # score = 15 + 2
|
||||
'AB1defghijklmn', # score = 14 + 2 + 1
|
||||
'AB12efghijklm', # score = 13 + 2 + 2
|
||||
'AB12+fghijkl', # score = 12 + 2 + 2 + 1
|
||||
'AB12+-ghijk', # score = 11 + 2 + 2 + 2
|
||||
'AB12+-*hij', # score = 10 + 2 + 2 + 3
|
||||
'AB12+-*hi/', # score = 10 + 2 + 2 + 3
|
||||
'AB12+-*hi3', # score = 10 + 2 + 2 + 3
|
||||
'AB12+-*hiC', # score = 10 + 2 + 2 + 3
|
||||
'abcbbbgbbjklmnopqr', # score = 17
|
||||
]
|
||||
|
||||
validator = PasswordScoreValidator(min_classes=0)
|
||||
@@ -31,19 +31,19 @@ class PasswordScoreValidatorTestCase(SimpleTestCase):
|
||||
except ValidationError as e:
|
||||
self.assertEqual('too_little_score', e.code)
|
||||
else:
|
||||
self.fail(u'%s: no validation error was raised' % password)
|
||||
self.fail('%s: no validation error was raised' % password)
|
||||
|
||||
def test_too_few_classes(self):
|
||||
passwords = [
|
||||
u'', # classes = 0
|
||||
u'abcdefgh', # classes = 1
|
||||
u'abcdef+-', # classes = 2
|
||||
u'abcd12gh', # classes = 2
|
||||
u'abcd12-+', # classes = 3
|
||||
u'abCDefgh', # classes = 2
|
||||
u'abCDef+-', # classes = 3
|
||||
u'abCD12gh', # classes = 3
|
||||
u'ABCD12-+', # classes = 3
|
||||
'', # classes = 0
|
||||
'abcdefgh', # classes = 1
|
||||
'abcdef+-', # classes = 2
|
||||
'abcd12gh', # classes = 2
|
||||
'abcd12-+', # classes = 3
|
||||
'abCDefgh', # classes = 2
|
||||
'abCDef+-', # classes = 3
|
||||
'abCD12gh', # classes = 3
|
||||
'ABCD12-+', # classes = 3
|
||||
]
|
||||
|
||||
validator = PasswordScoreValidator(min_score=0, min_classes=4)
|
||||
@@ -54,20 +54,20 @@ class PasswordScoreValidatorTestCase(SimpleTestCase):
|
||||
except ValidationError as e:
|
||||
self.assertEqual('too_few_classes', e.code)
|
||||
else:
|
||||
self.fail(u'%s: no validation error was raised' % password)
|
||||
self.fail('%s: no validation error was raised' % password)
|
||||
|
||||
def test_valid(self):
|
||||
passwords = [
|
||||
u'Abcdefghijklmnopq',
|
||||
u'ABcdefghijklmnop',
|
||||
u'AB1defghijklmno',
|
||||
u'AB12efghijklmn',
|
||||
u'AB12+fghijklm',
|
||||
u'AB12+-ghijkl',
|
||||
u'AB12+-*hijk',
|
||||
u'ab1defghijklmnopq',
|
||||
u'abcd+fghijklmnopq',
|
||||
u'AB1CDEFGHIJKLMNOPQ',
|
||||
'Abcdefghijklmnopq',
|
||||
'ABcdefghijklmnop',
|
||||
'AB1defghijklmno',
|
||||
'AB12efghijklmn',
|
||||
'AB12+fghijklm',
|
||||
'AB12+-ghijkl',
|
||||
'AB12+-*hijk',
|
||||
'ab1defghijklmnopq',
|
||||
'abcd+fghijklmnopq',
|
||||
'AB1CDEFGHIJKLMNOPQ',
|
||||
]
|
||||
|
||||
validator = PasswordScoreValidator()
|
||||
@@ -82,23 +82,23 @@ class PasswordScoreValidatorTestCase(SimpleTestCase):
|
||||
class CustomWordlistPasswordValidatorTestCase(SimpleTestCase):
|
||||
def test_invalid(self):
|
||||
invalid_passwords = [
|
||||
(u'passwort', [
|
||||
u'Das Passwort darf nicht die Zeichenfolge \'passwort\' enthalten.',
|
||||
('passwort', [
|
||||
'Das Passwort darf nicht die Zeichenfolge \'passwort\' enthalten.',
|
||||
]),
|
||||
(u'abcdDaVefgh', [
|
||||
u'Das Passwort darf nicht die Zeichenfolge \'dav\' enthalten.',
|
||||
('abcdDaVefgh', [
|
||||
'Das Passwort darf nicht die Zeichenfolge \'dav\' enthalten.',
|
||||
]),
|
||||
(u'abcdsektIonefgh', [
|
||||
u'Das Passwort darf nicht die Zeichenfolge \'sektion\' enthalten.',
|
||||
('abcdsektIonefgh', [
|
||||
'Das Passwort darf nicht die Zeichenfolge \'sektion\' enthalten.',
|
||||
]),
|
||||
(u'alpen12verein34KArlsruhE berge', [
|
||||
u'Das Passwort darf nicht die Zeichenfolge \'karlsruhe\' enthalten.',
|
||||
u'Das Passwort darf nicht die Zeichenfolge \'berge\' enthalten.',
|
||||
('alpen12verein34KArlsruhE berge', [
|
||||
'Das Passwort darf nicht die Zeichenfolge \'karlsruhe\' enthalten.',
|
||||
'Das Passwort darf nicht die Zeichenfolge \'berge\' enthalten.',
|
||||
]),
|
||||
(u'heinzel@alpenverein-karlsruhe.de', [
|
||||
u'Das Passwort darf nicht die Zeichenfolge \'heinzel\' enthalten.',
|
||||
u'Das Passwort darf nicht die Zeichenfolge \'alpenverein\' enthalten.',
|
||||
u'Das Passwort darf nicht die Zeichenfolge \'karlsruhe\' enthalten.',
|
||||
('heinzel@alpenverein-karlsruhe.de', [
|
||||
'Das Passwort darf nicht die Zeichenfolge \'heinzel\' enthalten.',
|
||||
'Das Passwort darf nicht die Zeichenfolge \'alpenverein\' enthalten.',
|
||||
'Das Passwort darf nicht die Zeichenfolge \'karlsruhe\' enthalten.',
|
||||
]),
|
||||
]
|
||||
|
||||
@@ -114,13 +114,13 @@ class CustomWordlistPasswordValidatorTestCase(SimpleTestCase):
|
||||
for error in errors:
|
||||
self.assertIn(error, expected_errors)
|
||||
else:
|
||||
self.fail(u'%s: no validation error was raised' % password)
|
||||
self.fail('%s: no validation error was raised' % password)
|
||||
|
||||
def test_valid(self):
|
||||
passwords = [
|
||||
u'',
|
||||
u'password',
|
||||
u'münchen',
|
||||
'',
|
||||
'password',
|
||||
'münchen',
|
||||
]
|
||||
|
||||
validator = CustomWordlistPasswordValidator()
|
||||
@@ -134,72 +134,72 @@ class CustomWordlistPasswordValidatorTestCase(SimpleTestCase):
|
||||
|
||||
class CharacterClassPasswordValidatorTestCase(SimpleTestCase):
|
||||
def setUp(self):
|
||||
super(CharacterClassPasswordValidatorTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.validator = CharacterClassPasswordValidator()
|
||||
|
||||
def test_invalid(self):
|
||||
invalid_passwords = [
|
||||
(u'', [
|
||||
u'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.',
|
||||
u'Das Passwort muss mindestens 2 Großbuchstaben enthalten.',
|
||||
u'Das Passwort muss mindestens 2 Ziffern enthalten.',
|
||||
u'Das Passwort muss mindestens 2 Sonderzeichen enthalten.',
|
||||
('', [
|
||||
'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.',
|
||||
'Das Passwort muss mindestens 2 Großbuchstaben enthalten.',
|
||||
'Das Passwort muss mindestens 2 Ziffern enthalten.',
|
||||
'Das Passwort muss mindestens 2 Sonderzeichen enthalten.',
|
||||
]),
|
||||
(u'A+-', [
|
||||
u'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.',
|
||||
u'Das Passwort muss mindestens 2 Großbuchstaben enthalten.',
|
||||
u'Das Passwort muss mindestens 2 Ziffern enthalten.',
|
||||
('A+-', [
|
||||
'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.',
|
||||
'Das Passwort muss mindestens 2 Großbuchstaben enthalten.',
|
||||
'Das Passwort muss mindestens 2 Ziffern enthalten.',
|
||||
]),
|
||||
(u'1234567890*', [
|
||||
u'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.',
|
||||
u'Das Passwort muss mindestens 2 Großbuchstaben enthalten.',
|
||||
u'Das Passwort muss mindestens 2 Sonderzeichen enthalten.',
|
||||
('1234567890*', [
|
||||
'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.',
|
||||
'Das Passwort muss mindestens 2 Großbuchstaben enthalten.',
|
||||
'Das Passwort muss mindestens 2 Sonderzeichen enthalten.',
|
||||
]),
|
||||
(u'34*/()', [
|
||||
u'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.',
|
||||
u'Das Passwort muss mindestens 2 Großbuchstaben enthalten.',
|
||||
('34*/()', [
|
||||
'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.',
|
||||
'Das Passwort muss mindestens 2 Großbuchstaben enthalten.',
|
||||
]),
|
||||
(u'AA', [
|
||||
u'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.',
|
||||
u'Das Passwort muss mindestens 2 Ziffern enthalten.',
|
||||
u'Das Passwort muss mindestens 2 Sonderzeichen enthalten.',
|
||||
('AA', [
|
||||
'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.',
|
||||
'Das Passwort muss mindestens 2 Ziffern enthalten.',
|
||||
'Das Passwort muss mindestens 2 Sonderzeichen enthalten.',
|
||||
]),
|
||||
(u'CD0.,', [
|
||||
u'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.',
|
||||
u'Das Passwort muss mindestens 2 Ziffern enthalten.',
|
||||
('CD0.,', [
|
||||
'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.',
|
||||
'Das Passwort muss mindestens 2 Ziffern enthalten.',
|
||||
]),
|
||||
(u'EF56', [
|
||||
u'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.',
|
||||
u'Das Passwort muss mindestens 2 Sonderzeichen enthalten.',
|
||||
('EF56', [
|
||||
'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.',
|
||||
'Das Passwort muss mindestens 2 Sonderzeichen enthalten.',
|
||||
]),
|
||||
(u'8GH?!8', [
|
||||
u'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.',
|
||||
('8GH?!8', [
|
||||
'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.',
|
||||
]),
|
||||
(u'bbX', [
|
||||
u'Das Passwort muss mindestens 2 Großbuchstaben enthalten.',
|
||||
u'Das Passwort muss mindestens 2 Ziffern enthalten.',
|
||||
u'Das Passwort muss mindestens 2 Sonderzeichen enthalten.',
|
||||
('bbX', [
|
||||
'Das Passwort muss mindestens 2 Großbuchstaben enthalten.',
|
||||
'Das Passwort muss mindestens 2 Ziffern enthalten.',
|
||||
'Das Passwort muss mindestens 2 Sonderzeichen enthalten.',
|
||||
]),
|
||||
(u'$cd%', [
|
||||
u'Das Passwort muss mindestens 2 Großbuchstaben enthalten.',
|
||||
u'Das Passwort muss mindestens 2 Ziffern enthalten.',
|
||||
('$cd%', [
|
||||
'Das Passwort muss mindestens 2 Großbuchstaben enthalten.',
|
||||
'Das Passwort muss mindestens 2 Ziffern enthalten.',
|
||||
]),
|
||||
(u'ef90', [
|
||||
u'Das Passwort muss mindestens 2 Großbuchstaben enthalten.',
|
||||
u'Das Passwort muss mindestens 2 Sonderzeichen enthalten.',
|
||||
('ef90', [
|
||||
'Das Passwort muss mindestens 2 Großbuchstaben enthalten.',
|
||||
'Das Passwort muss mindestens 2 Sonderzeichen enthalten.',
|
||||
]),
|
||||
(u'1g=h3~', [
|
||||
u'Das Passwort muss mindestens 2 Großbuchstaben enthalten.',
|
||||
('1g=h3~', [
|
||||
'Das Passwort muss mindestens 2 Großbuchstaben enthalten.',
|
||||
]),
|
||||
(u'Gi&jH', [
|
||||
u'Das Passwort muss mindestens 2 Ziffern enthalten.',
|
||||
u'Das Passwort muss mindestens 2 Sonderzeichen enthalten.',
|
||||
('Gi&jH', [
|
||||
'Das Passwort muss mindestens 2 Ziffern enthalten.',
|
||||
'Das Passwort muss mindestens 2 Sonderzeichen enthalten.',
|
||||
]),
|
||||
(u'IkK:i;', [
|
||||
u'Das Passwort muss mindestens 2 Ziffern enthalten.',
|
||||
('IkK:i;', [
|
||||
'Das Passwort muss mindestens 2 Ziffern enthalten.',
|
||||
]),
|
||||
(u'mKn4L8', [
|
||||
u'Das Passwort muss mindestens 2 Sonderzeichen enthalten.',
|
||||
('mKn4L8', [
|
||||
'Das Passwort muss mindestens 2 Sonderzeichen enthalten.',
|
||||
]),
|
||||
]
|
||||
|
||||
@@ -215,10 +215,10 @@ class CharacterClassPasswordValidatorTestCase(SimpleTestCase):
|
||||
for error in errors:
|
||||
self.assertIn(error, expected_errors)
|
||||
else:
|
||||
self.fail(u'%s: no validation error was raised' % password)
|
||||
self.fail('%s: no validation error was raised' % password)
|
||||
|
||||
def test_valid(self):
|
||||
valid_passwords = [u'abCD12+-']
|
||||
valid_passwords = ['abCD12+-']
|
||||
validator = self.validator
|
||||
for password in valid_passwords:
|
||||
try:
|
||||
|
||||
@@ -10,7 +10,7 @@ from django.urls import reverse
|
||||
from ..forms import LoginForm, SetPasswordForm, CreateAndSendPasswordForm
|
||||
|
||||
TEST_USERNAME = 'root@localhost'
|
||||
TEST_PASSWORD = u'me||ön 21ABll'
|
||||
TEST_PASSWORD = 'me||ön 21ABll'
|
||||
TEST_EMAIL = TEST_USERNAME
|
||||
|
||||
|
||||
@@ -30,12 +30,12 @@ class ViewsTestCase(TestCase):
|
||||
cls.recreate_password_url = reverse('dav_auth:recreate_password')
|
||||
|
||||
# Some messages
|
||||
cls.wrong_credentials_message = ugettext(u'Benutzername oder Passwort falsch.')
|
||||
cls.logout_message = ugettext(u'Benutzer abgemeldet.')
|
||||
cls.set_password_message = ugettext(u'Passwort gespeichert.')
|
||||
cls.wrong_credentials_message = ugettext('Benutzername oder Passwort falsch.')
|
||||
cls.logout_message = ugettext('Benutzer abgemeldet.')
|
||||
cls.set_password_message = ugettext('Passwort gespeichert.')
|
||||
|
||||
def setUp(self):
|
||||
super(ViewsTestCase, self).setUp()
|
||||
super().setUp()
|
||||
# Need a test user
|
||||
self.test_username = TEST_USERNAME
|
||||
self.test_password = TEST_PASSWORD
|
||||
@@ -74,7 +74,7 @@ class ViewsTestCase(TestCase):
|
||||
|
||||
def test_integrated_login_succeed(self):
|
||||
username = self.user.username
|
||||
message = ugettext(u'Benutzer angemeldet: %(username)s') % {'username': username}
|
||||
message = ugettext('Benutzer angemeldet: %(username)s') % {'username': username}
|
||||
|
||||
response = self.client.post(self.login_url, {'username': username, 'password': self.test_password})
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@@ -166,7 +166,7 @@ class ViewsTestCase(TestCase):
|
||||
'send_password_mail': True})
|
||||
self.assertEqual(len(django_mail.outbox), 1)
|
||||
mail = django_mail.outbox[0]
|
||||
recipient = u'"%s" <%s>' % (self.user.get_full_name(), self.user.email)
|
||||
recipient = '"%s" <%s>' % (self.user.get_full_name(), self.user.email)
|
||||
recipients = mail.recipients()
|
||||
self.assertIn(recipient, recipients)
|
||||
self.assertEqual(len(recipients), 1)
|
||||
@@ -202,7 +202,7 @@ class ViewsTestCase(TestCase):
|
||||
|
||||
self.assertEqual(len(django_mail.outbox), 1)
|
||||
mail = django_mail.outbox[0]
|
||||
recipient = u'"%s" <%s>' % (self.user.get_full_name(), self.user.email)
|
||||
recipient = '"%s" <%s>' % (self.user.get_full_name(), self.user.email)
|
||||
recipients = mail.recipients()
|
||||
self.assertIn(recipient, recipients)
|
||||
self.assertEqual(len(recipients), 1)
|
||||
|
||||
@@ -56,67 +56,67 @@ class PasswordScoreValidator:
|
||||
score, used_classes = self._get_score(password, user=user)
|
||||
|
||||
if used_classes < self.min_classes:
|
||||
raise ValidationError(_(u'Das Passwort muss Zeichen aus mindestens %(min_classes)d'
|
||||
u' verschiedenen Arten von Zeichen bestehen'
|
||||
u' (d.h. Kleinbuchstaben, Großbuchstaben, Ziffern und Sonderzeichen).'),
|
||||
raise ValidationError(_('Das Passwort muss Zeichen aus mindestens %(min_classes)d'
|
||||
' verschiedenen Arten von Zeichen bestehen'
|
||||
' (d.h. Kleinbuchstaben, Großbuchstaben, Ziffern und Sonderzeichen).'),
|
||||
code='too_few_classes',
|
||||
params={'min_classes': self.min_classes})
|
||||
|
||||
if score < self.min_score:
|
||||
raise ValidationError(_(u'Dieses Passwort ist zu einfach. Benutze mehr Zeichen'
|
||||
u' und gegebenenfalls auch Großbuchstaben, Ziffern und Sonderzeichen.'),
|
||||
raise ValidationError(_('Dieses Passwort ist zu einfach. Benutze mehr Zeichen'
|
||||
' und gegebenenfalls auch Großbuchstaben, Ziffern und Sonderzeichen.'),
|
||||
code='too_little_score')
|
||||
|
||||
return score
|
||||
|
||||
def get_help_text(self):
|
||||
text = u'%s\n%s' % (
|
||||
_(u'The password must get a minimum score of %d points.') % self.min_score,
|
||||
_(u'For each character the score is increased by 1 point.'),
|
||||
text = '%s\n%s' % (
|
||||
_('The password must get a minimum score of %d points.') % self.min_score,
|
||||
_('For each character the score is increased by 1 point.'),
|
||||
)
|
||||
if self.lcredit > 0:
|
||||
text += '\n'
|
||||
text += _(u'The first %d lower characters increase the score by 1 point each.') % self.lcredit
|
||||
text += _('The first %d lower characters increase the score by 1 point each.') % self.lcredit
|
||||
if self.ucredit > 0:
|
||||
text += '\n'
|
||||
text += _(u'The first %d upper characters increase the score by 1 point each.') % self.ucredit
|
||||
text += _('The first %d upper characters increase the score by 1 point each.') % self.ucredit
|
||||
if self.dcredit > 0:
|
||||
text += '\n'
|
||||
text += _(u'The first %d digits increase the score by 1 point each.') % self.dcredit
|
||||
text += _('The first %d digits increase the score by 1 point each.') % self.dcredit
|
||||
if self.ocredit > 0:
|
||||
text += '\n'
|
||||
text += _(u'The first %d non alpha numeric characters'
|
||||
u' increase the score by 1 point each.') % self.ocredit
|
||||
text += _('The first %d non alpha numeric characters'
|
||||
' increase the score by 1 point each.') % self.ocredit
|
||||
if self.max_repeat > 0:
|
||||
text += '\n'
|
||||
text += _(u'If a particular character is used more than %d times,'
|
||||
u' it will not increase the score anymore.') % self.max_repeat
|
||||
text += _('If a particular character is used more than %d times,'
|
||||
' it will not increase the score anymore.') % self.max_repeat
|
||||
if self.min_classes > 0:
|
||||
text += '\n'
|
||||
text += _(u'Also the password must contain characters from %d different character classes'
|
||||
u' (i.e. lower, upper, digits, others).') % self.min_classes
|
||||
text += _('Also the password must contain characters from %d different character classes'
|
||||
' (i.e. lower, upper, digits, others).') % self.min_classes
|
||||
return text
|
||||
|
||||
|
||||
class CustomWordlistPasswordValidator:
|
||||
context = 'the Sektion Karlsruhe'
|
||||
words = (
|
||||
u'dav',
|
||||
u'berge',
|
||||
u'sektion',
|
||||
u'karlsruhe',
|
||||
u'alpenverein',
|
||||
u'heinzel',
|
||||
u'passwort',
|
||||
'dav',
|
||||
'berge',
|
||||
'sektion',
|
||||
'karlsruhe',
|
||||
'alpenverein',
|
||||
'heinzel',
|
||||
'passwort',
|
||||
)
|
||||
|
||||
def validate(self, password, user=None):
|
||||
def validate(self, password, user=None): # pylint: disable=unused-argument
|
||||
errors = []
|
||||
|
||||
lower_pw = password.lower()
|
||||
for word in self.words:
|
||||
if word in lower_pw:
|
||||
error = ValidationError(_(u'Das Passwort darf nicht die Zeichenfolge \'%(word)s\' enthalten.'),
|
||||
error = ValidationError(_('Das Passwort darf nicht die Zeichenfolge \'%(word)s\' enthalten.'),
|
||||
code='forbidden_word',
|
||||
params={'word': word})
|
||||
errors.append(error)
|
||||
@@ -125,10 +125,10 @@ class CustomWordlistPasswordValidator:
|
||||
raise ValidationError(errors)
|
||||
|
||||
def get_help_text(self):
|
||||
text = _(u'The password must not contain some specific words,'
|
||||
u' that are common in context with %(context)s.') % {'context': self.context}
|
||||
text += u'\n'
|
||||
text += _(u'All words are matched case insensitive.')
|
||||
text = _('The password must not contain some specific words,'
|
||||
' that are common in context with %(context)s.') % {'context': self.context}
|
||||
text += '\n'
|
||||
text += _('All words are matched case insensitive.')
|
||||
return text
|
||||
|
||||
|
||||
@@ -163,26 +163,26 @@ class CharacterClassPasswordValidator:
|
||||
self.minimum_digits = minimum_digits
|
||||
self.minimum_others = minimum_others
|
||||
|
||||
def validate(self, password, user=None):
|
||||
def validate(self, password, user=None): # pylint: disable=unused-argument
|
||||
errors = []
|
||||
if not self._is_enough_lower(password):
|
||||
error = ValidationError(_(u'Das Passwort muss mindestens %(min_lower)d Kleinbuchstaben enthalten.'),
|
||||
error = ValidationError(_('Das Passwort muss mindestens %(min_lower)d Kleinbuchstaben enthalten.'),
|
||||
code='too_few_lower_characters',
|
||||
params={'min_lower': self.minimum_lower})
|
||||
errors.append(error)
|
||||
if not self._is_enough_upper(password):
|
||||
error = ValidationError(_(u'Das Passwort muss mindestens %(min_upper)d Großbuchstaben enthalten.'),
|
||||
error = ValidationError(_('Das Passwort muss mindestens %(min_upper)d Großbuchstaben enthalten.'),
|
||||
code='too_few_upper_characters',
|
||||
params={'min_upper': self.minimum_upper})
|
||||
errors.append(error)
|
||||
if not self._is_enough_digits(password):
|
||||
error = ValidationError(_(u'Das Passwort muss mindestens %(min_digits)d Ziffern enthalten.'),
|
||||
error = ValidationError(_('Das Passwort muss mindestens %(min_digits)d Ziffern enthalten.'),
|
||||
code='too_few_digits',
|
||||
params={'min_digits': self.minimum_digits})
|
||||
errors.append(error)
|
||||
if not self._is_enough_others(password):
|
||||
error = ValidationError(_(u'Das Passwort muss mindestens %(min_others)d'
|
||||
u' Sonderzeichen enthalten.'),
|
||||
error = ValidationError(_('Das Passwort muss mindestens %(min_others)d'
|
||||
' Sonderzeichen enthalten.'),
|
||||
code='too_few_other_characters',
|
||||
params={'min_others': self.minimum_others})
|
||||
errors.append(error)
|
||||
@@ -191,7 +191,7 @@ class CharacterClassPasswordValidator:
|
||||
raise ValidationError(errors)
|
||||
|
||||
def get_help_text(self):
|
||||
text = u'%s %s %s %s' % (
|
||||
text = '%s %s %s %s' % (
|
||||
_('The password must contain at least %d characters from a-z.') % self.minimum_lower,
|
||||
_('The password must contain at least %d characters from A-Z.') % self.minimum_upper,
|
||||
_('The password must contain at least %d digits from 0-9.') % self.minimum_digits,
|
||||
|
||||
@@ -24,39 +24,39 @@ class LoginView(auth_views.LoginView):
|
||||
template_name = 'dav_auth/forms/login.html'
|
||||
|
||||
def get_redirect_url(self):
|
||||
url = super(LoginView, self).get_redirect_url()
|
||||
url = super().get_redirect_url()
|
||||
if not url and app_config.settings.login_redirect_url:
|
||||
url = resolve_url(app_config.settings.login_redirect_url)
|
||||
return url
|
||||
|
||||
def form_valid(self, form):
|
||||
r = super(LoginView, self).form_valid(form)
|
||||
messages.success(self.request, _(u'Benutzer angemeldet: %(username)s') % {'username': form.get_user()})
|
||||
r = super().form_valid(form)
|
||||
messages.success(self.request, _('Benutzer angemeldet: %(username)s') % {'username': form.get_user()})
|
||||
try:
|
||||
validate_password(form.cleaned_data['password'])
|
||||
except ValidationError as e:
|
||||
logger.warning(u'Weak password (%d): %s', self.request.user.pk, e)
|
||||
message = u'<br />\n<p>\n'
|
||||
message += u'Dein Passwort entspricht nicht mehr den aktuellen Passwortrichtlinien.<br />\n'
|
||||
message += u'Bitte hilf uns die Daten deiner Teilnehmer zu schützen und ändere dein Passwort.<br />\n'
|
||||
message += u'</p>\n'
|
||||
message += u'<p>\n'
|
||||
message += u'<a href="%(href)s">Passwort ändern</a>\n' % {'href': reverse('dav_auth:set_password')}
|
||||
message += u'</p>\n<br />\n'
|
||||
logger.warning('Weak password (%d): %s', self.request.user.pk, e)
|
||||
message = '<br />\n<p>\n'
|
||||
message += 'Dein Passwort entspricht nicht mehr den aktuellen Passwortrichtlinien.<br />\n'
|
||||
message += 'Bitte hilf uns die Daten deiner Teilnehmer zu schützen und ändere dein Passwort.<br />\n'
|
||||
message += '</p>\n'
|
||||
message += '<p>\n'
|
||||
message += '<a href="%(href)s">Passwort ändern</a>\n' % {'href': reverse('dav_auth:set_password')}
|
||||
message += '</p>\n<br />\n'
|
||||
messages.warning(self.request, mark_safe(message))
|
||||
return r
|
||||
|
||||
|
||||
class LogoutView(auth_views.LogoutView):
|
||||
def get_next_page(self):
|
||||
url = super(LogoutView, self).get_next_page()
|
||||
url = super().get_next_page()
|
||||
if not url and app_config.settings.logout_redirect_url:
|
||||
url = resolve_url(app_config.settings.logout_redirect_url)
|
||||
return url
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
r = super(LogoutView, self).dispatch(request, *args, **kwargs)
|
||||
messages.success(self.request, _(u'Benutzer abgemeldet.'))
|
||||
r = super().dispatch(request, *args, **kwargs)
|
||||
messages.success(self.request, _('Benutzer abgemeldet.'))
|
||||
return r
|
||||
|
||||
|
||||
@@ -68,8 +68,8 @@ class SetPasswordView(auth_views.PasswordChangeView):
|
||||
return resolve_url(app_config.settings.login_redirect_url)
|
||||
|
||||
def form_valid(self, form):
|
||||
r = super(SetPasswordView, self).form_valid(form)
|
||||
messages.success(self.request, _(u'Passwort gespeichert.'))
|
||||
r = super().form_valid(form)
|
||||
messages.success(self.request, _('Passwort gespeichert.'))
|
||||
if form.cleaned_data.get('send_password_mail', False):
|
||||
email = emails.PasswordSetEmail(self.request.user, form.cleaned_data['new_password'])
|
||||
email.send()
|
||||
@@ -91,14 +91,14 @@ class CreateAndSendPasswordView(generic.FormView):
|
||||
user.save()
|
||||
email = emails.PasswordSetEmail(user, random_password)
|
||||
email.send()
|
||||
messages.success(self.request, _(u'Neues Passwort versendet.'))
|
||||
messages.success(self.request, _('Neues Passwort versendet.'))
|
||||
logger.info('Password recreated for user \'%s\'', username)
|
||||
except user_model.DoesNotExist:
|
||||
logger.warning('Password recreated for unknown user \'%s\'', username)
|
||||
|
||||
return super(CreateAndSendPasswordView, self).form_valid(form)
|
||||
return super().form_valid(form)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if request.user.is_authenticated:
|
||||
return HttpResponseRedirect(reverse('dav_auth:set_password'))
|
||||
return super(CreateAndSendPasswordView, self).get(request, *args, **kwargs)
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
@@ -1 +1 @@
|
||||
default_app_config = 'dav_base.apps.AppConfig'
|
||||
default_app_config = 'dav_base.apps.AppConfig' # pylint: disable=invalid-name
|
||||
|
||||
@@ -9,5 +9,5 @@ DEFAULT_SETTINGS = (
|
||||
|
||||
class AppConfig(_AppConfig):
|
||||
name = 'dav_base'
|
||||
verbose_name = u'DAV Base App'
|
||||
verbose_name = 'DAV Base App'
|
||||
default_settings = DEFAULT_SETTINGS
|
||||
|
||||
@@ -7,7 +7,7 @@ from django.core.exceptions import ImproperlyConfigured
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DefaultSetting(object):
|
||||
class DefaultSetting: # pylint: disable=too-few-public-methods
|
||||
def __init__(self, name, value, key_name=None, validator=None):
|
||||
self.name = name
|
||||
self.value = value
|
||||
@@ -27,7 +27,7 @@ class DefaultSetting(object):
|
||||
raise ImproperlyConfigured('Does not match /{re}/'.format(re=self.validator))
|
||||
|
||||
|
||||
class AppSettings(object):
|
||||
class AppSettings: # pylint: disable=too-few-public-methods
|
||||
def __init__(self, app_name, defaults):
|
||||
settings_name = 'main.settings-' + app_name
|
||||
|
||||
@@ -45,7 +45,7 @@ class AppSettings(object):
|
||||
msg = 'Invalid value of {key} in {module}: {cause}'.format(key=default.key_name,
|
||||
module=settings_name,
|
||||
cause=e)
|
||||
raise ImproperlyConfigured(msg)
|
||||
raise ImproperlyConfigured(msg) from e
|
||||
setattr(self, default.name, value)
|
||||
elif isinstance(default.value, ImproperlyConfigured):
|
||||
raise default.value
|
||||
@@ -59,13 +59,13 @@ class AppSettings(object):
|
||||
msg = '{key} must be defined in {module}'.format(key=default.key_name,
|
||||
module=settings_name)
|
||||
raise default.value(msg)
|
||||
else:
|
||||
setattr(self, default.name, default.value)
|
||||
|
||||
setattr(self, default.name, default.value)
|
||||
|
||||
|
||||
class AppConfig(_AppConfig):
|
||||
default_settings = ()
|
||||
|
||||
def __init__(self, app_name, app_module):
|
||||
super(AppConfig, self).__init__(app_name, app_module)
|
||||
super().__init__(app_name, app_module)
|
||||
self.settings = AppSettings(app_name, self.default_settings)
|
||||
|
||||
@@ -13,7 +13,7 @@ class ModuleConfigError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ModuleMeta(object):
|
||||
class ModuleMeta:
|
||||
_json_file = 'module.json'
|
||||
_root_url_name = 'root'
|
||||
|
||||
@@ -73,7 +73,7 @@ class ModuleMeta(object):
|
||||
return d
|
||||
|
||||
|
||||
class ModuleConfig(object):
|
||||
class ModuleConfig:
|
||||
_lazy_load = True
|
||||
|
||||
def __init__(self, config_file_path=None, django_base_dir=None):
|
||||
@@ -83,7 +83,7 @@ class ModuleConfig(object):
|
||||
config_file_path = os.path.join(django_base_dir, DJANGO_MAIN_MODULE, MODULE_CONFIG_FILE_NAME)
|
||||
self._config_file_path = config_file_path
|
||||
|
||||
self._modules = dict()
|
||||
self._modules = {}
|
||||
|
||||
self._loaded = False
|
||||
if not self._lazy_load:
|
||||
@@ -96,13 +96,13 @@ class ModuleConfig(object):
|
||||
def _load(self):
|
||||
path = self._config_file_path
|
||||
|
||||
self._modules = dict()
|
||||
self._modules = {}
|
||||
|
||||
if os.path.exists(path):
|
||||
with open(path, 'r') as f:
|
||||
with open(path, 'r', encoding='ascii') as f:
|
||||
data = json.load(f)
|
||||
else:
|
||||
data = dict()
|
||||
data = {}
|
||||
|
||||
if 'modules' in data:
|
||||
for meta_dict in data['modules']:
|
||||
@@ -131,5 +131,5 @@ class ModuleConfig(object):
|
||||
for meta_obj in self._modules.values():
|
||||
data['modules'].append(meta_obj.dump_as_dict())
|
||||
|
||||
with open(path, 'w') as f:
|
||||
with open(path, 'w', encoding='ascii') as f:
|
||||
json.dump(data, f, indent=4)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import argparse
|
||||
import os
|
||||
import pkg_resources
|
||||
import posix
|
||||
import sys
|
||||
import pkg_resources
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
from dav_base.config.modules import DJANGO_MAIN_MODULE, ModuleConfig
|
||||
@@ -10,7 +10,7 @@ from dav_base.config.modules import DJANGO_MAIN_MODULE, ModuleConfig
|
||||
VERSION = '0.1'
|
||||
|
||||
|
||||
class AdminCommand(object):
|
||||
class AdminCommand: # pylint: disable=too-few-public-methods
|
||||
def _setup_argparser(self):
|
||||
kwargs = {
|
||||
'description': 'Tool to manage the DAV django project installation.',
|
||||
@@ -60,7 +60,7 @@ class AdminCommand(object):
|
||||
def _subcmd_setup(self, cmd_args):
|
||||
django_main_module = DJANGO_MAIN_MODULE
|
||||
django_base_dir = cmd_args.path
|
||||
|
||||
|
||||
sys.stdout.write('Setup installation in \'{path}\'...\n'.format(path=django_base_dir))
|
||||
|
||||
if os.path.exists(django_base_dir):
|
||||
|
||||
@@ -9,8 +9,8 @@ app_config = apps.get_containing_app_config(__package__)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AbstractMail(object):
|
||||
_subject = u''
|
||||
class AbstractMail: # pylint: disable=too-few-public-methods
|
||||
_subject = ''
|
||||
_template_name = None
|
||||
|
||||
def _get_sender(self):
|
||||
@@ -20,7 +20,7 @@ class AbstractMail(object):
|
||||
if subject_fmt is None:
|
||||
subject_fmt = self._subject
|
||||
if app_config.settings.email_subject_prefix:
|
||||
subject_fmt = u'%s %s' % (app_config.settings.email_subject_prefix, subject_fmt)
|
||||
subject_fmt = '%s %s' % (app_config.settings.email_subject_prefix, subject_fmt)
|
||||
subject = subject_fmt.format(**kwargs)
|
||||
return subject
|
||||
|
||||
@@ -57,7 +57,7 @@ class AbstractMail(object):
|
||||
|
||||
email = EmailMessage(subject=subject, body=body, from_email=sender, to=recipients, reply_to=reply_to)
|
||||
if fail_silently:
|
||||
logger.info(u'Fake sending %s to %s', self.__class__.__name__, recipients)
|
||||
logger.info('Fake sending %s to %s', self.__class__.__name__, recipients)
|
||||
else:
|
||||
logger.info(u'Send %s to %s', self.__class__.__name__, recipients)
|
||||
logger.info('Send %s to %s', self.__class__.__name__, recipients)
|
||||
email.send(fail_silently=fail_silently)
|
||||
|
||||
@@ -7,7 +7,7 @@ register = template.Library()
|
||||
def do_include_if_exist(parser, token):
|
||||
"""
|
||||
Used to include a template, that maybe does not exist.
|
||||
|
||||
|
||||
include_if_exist support an optional keyword 'default', which must be followed by the name of a default template.
|
||||
The default template will be included, if the first template does not exist.
|
||||
If also the default template does not exist, the behaviour is the same as for the original (builtin) include tag.
|
||||
@@ -36,7 +36,7 @@ def do_include_if_exist(parser, token):
|
||||
except IndexError:
|
||||
raise template.TemplateSyntaxError("'default' keyword in %r tag requires another arguments:"
|
||||
" the name of the default template" % bits[0])
|
||||
|
||||
|
||||
try:
|
||||
include_node = template.loader_tags.do_include(parser, token)
|
||||
except template.TemplateDoesNotExist:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import datetime
|
||||
import os
|
||||
from urllib.parse import quote
|
||||
from django.apps import apps
|
||||
from django.contrib.auth.models import AbstractUser
|
||||
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
|
||||
@@ -9,11 +10,10 @@ from django.test import SimpleTestCase, TestCase, tag
|
||||
from django.urls import reverse
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from six.moves.urllib.parse import quote
|
||||
from selenium.webdriver.support import expected_conditions as ExpectedConditions
|
||||
|
||||
|
||||
class AppSetting(object):
|
||||
class AppSetting: # pylint: disable=too-few-public-methods
|
||||
def __init__(self, name, of=None):
|
||||
self.name = name
|
||||
self.of = of
|
||||
@@ -24,7 +24,7 @@ class AppsTestCase(SimpleTestCase):
|
||||
settings = ()
|
||||
|
||||
def setUp(self):
|
||||
super(AppsTestCase, self).setUp()
|
||||
super().setUp()
|
||||
if self.app_config:
|
||||
self.configured_settings = self.app_config.settings
|
||||
else:
|
||||
@@ -41,7 +41,7 @@ class AppsTestCase(SimpleTestCase):
|
||||
self.assertIsInstance(value, of)
|
||||
|
||||
|
||||
class EmailTestMixin(object):
|
||||
class EmailTestMixin:
|
||||
email_sender = 'Automatic Software Test <root@localhost>'
|
||||
email_base_url = 'http://localhost'
|
||||
email_subject_prefix = '[Test]'
|
||||
@@ -55,29 +55,29 @@ class EmailTestMixin(object):
|
||||
|
||||
return mails
|
||||
|
||||
def assertSender(self, mail):
|
||||
def assertSender(self, mail): # pylint: disable=invalid-name
|
||||
self.assertEqual(mail.from_email, self.email_sender)
|
||||
|
||||
def assertReplyTo(self, mail, addresses):
|
||||
def assertReplyTo(self, mail, addresses): # pylint: disable=invalid-name
|
||||
self.assertEqual(len(mail.reply_to), len(addresses))
|
||||
for expected_address in addresses:
|
||||
if isinstance(expected_address, AbstractUser):
|
||||
expected_address = u'"%s" <%s>' % (expected_address.get_full_name(), expected_address.email)
|
||||
expected_address = '"%s" <%s>' % (expected_address.get_full_name(), expected_address.email)
|
||||
self.assertIn(expected_address, mail.reply_to)
|
||||
|
||||
def assertRecipients(self, mail, recipients):
|
||||
def assertRecipients(self, mail, recipients): # pylint: disable=invalid-name
|
||||
self.assertEqual(len(mail.recipients()), len(recipients))
|
||||
for expected_recipient in recipients:
|
||||
if isinstance(expected_recipient, AbstractUser):
|
||||
expected_recipient = u'"%s" <%s>' % (expected_recipient.get_full_name(), expected_recipient.email)
|
||||
expected_recipient = '"%s" <%s>' % (expected_recipient.get_full_name(), expected_recipient.email)
|
||||
recipients = mail.recipients()
|
||||
self.assertIn(expected_recipient, recipients)
|
||||
|
||||
def assertSubject(self, mail, subject):
|
||||
expected_subject = u'{} {}'.format(self.email_subject_prefix, subject)
|
||||
def assertSubject(self, mail, subject): # pylint: disable=invalid-name
|
||||
expected_subject = '{} {}'.format(self.email_subject_prefix, subject)
|
||||
self.assertEqual(mail.subject, expected_subject)
|
||||
|
||||
def assertBody(self, mail, body):
|
||||
def assertBody(self, mail, body): # pylint: disable=invalid-name
|
||||
expected_lines = body.splitlines()
|
||||
lines = mail.body.splitlines()
|
||||
i = 0
|
||||
@@ -93,14 +93,14 @@ class EmailTestMixin(object):
|
||||
self.fail('line %d: %s' % (i, e))
|
||||
self.assertEqual(mail.body, body)
|
||||
|
||||
def setUp(self):
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
app_config = apps.get_app_config('dav_base')
|
||||
app_config.settings.email_sender = self.email_sender
|
||||
app_config.settings.email_base_url = self.email_base_url
|
||||
app_config.settings.email_subject_prefix = self.email_subject_prefix
|
||||
|
||||
|
||||
class FormDataSet(object):
|
||||
class FormDataSet: # pylint: disable=too-few-public-methods
|
||||
def __init__(self, data, expected_errors=None, form_kwargs=None):
|
||||
self.data = data
|
||||
self.expected_errors = expected_errors
|
||||
@@ -116,44 +116,46 @@ class FormsTestCase(TestCase):
|
||||
if form_class is None:
|
||||
form_class = self.form_class
|
||||
if form_class is None:
|
||||
return True
|
||||
return
|
||||
|
||||
if data_sets is None:
|
||||
data_sets = self.valid_data_sets
|
||||
|
||||
given_form_kwargs = form_kwargs
|
||||
for data_set in data_sets:
|
||||
fk = {}
|
||||
if form_kwargs is not None:
|
||||
fk.update(form_kwargs)
|
||||
form_kwargs = {}
|
||||
if given_form_kwargs is not None:
|
||||
form_kwargs.update(given_form_kwargs)
|
||||
if data_set.form_kwargs is not None:
|
||||
fk.update(data_set.form_kwargs)
|
||||
fk['data'] = data_set.data
|
||||
form = form_class(**fk)
|
||||
form_kwargs.update(data_set.form_kwargs)
|
||||
form_kwargs['data'] = data_set.data
|
||||
form = form_class(**form_kwargs)
|
||||
if not form.is_valid():
|
||||
errors = []
|
||||
for key in form.errors.as_data():
|
||||
for ve in form.errors[key].as_data():
|
||||
errors.append(u'%s (%s)' % (ve.code, ve.message))
|
||||
self.fail(u'Invalid form data \'%s\': %s' % (data_set.data, errors))
|
||||
for e in form.errors[key].as_data():
|
||||
errors.append('%s (%s)' % (e.code, e.message))
|
||||
self.fail('Invalid form data \'%s\': %s' % (data_set.data, errors))
|
||||
|
||||
def test_invalid_data(self, form_class=None, data_sets=None, form_kwargs=None):
|
||||
if form_class is None:
|
||||
form_class = self.form_class
|
||||
if form_class is None:
|
||||
return True
|
||||
return
|
||||
|
||||
if data_sets is None:
|
||||
data_sets = self.invalid_data_sets
|
||||
|
||||
given_form_kwargs = form_kwargs
|
||||
for data_set in data_sets:
|
||||
fk = {}
|
||||
if form_kwargs is not None:
|
||||
fk.update(form_kwargs)
|
||||
form_kwargs = {}
|
||||
if given_form_kwargs is not None:
|
||||
form_kwargs.update(given_form_kwargs)
|
||||
if data_set.form_kwargs is not None:
|
||||
fk.update(data_set.form_kwargs)
|
||||
fk['data'] = data_set.data
|
||||
form_kwargs.update(data_set.form_kwargs)
|
||||
form_kwargs['data'] = data_set.data
|
||||
|
||||
form = form_class(**fk)
|
||||
form = form_class(**form_kwargs)
|
||||
|
||||
if form.is_valid():
|
||||
self.fail('Valid form data: \'%s\'' % data_set.data)
|
||||
@@ -164,7 +166,7 @@ class FormsTestCase(TestCase):
|
||||
self.assertIn(code, error_codes)
|
||||
|
||||
|
||||
class Url(object):
|
||||
class Url: # pylint: disable=too-few-public-methods
|
||||
def __init__(self, location, name=None, func=None, **kwargs):
|
||||
self.location = location
|
||||
self.name = name
|
||||
@@ -210,15 +212,15 @@ class UrlsTestCase(TestCase):
|
||||
'Getting url named \'{}\' resolve to wrong function'.format(url.name))
|
||||
|
||||
|
||||
class ValidatorTestMixin(object):
|
||||
def assertValid(self, validator, data):
|
||||
class ValidatorTestMixin:
|
||||
def assertValid(self, validator, data): # pylint: disable=invalid-name
|
||||
for val in data:
|
||||
try:
|
||||
validator(val)
|
||||
except ValidationError as e: # pragma: no cover
|
||||
self.fail('%s: %s' % (val, e))
|
||||
|
||||
def assertInvalid(self, validator, data):
|
||||
def assertInvalid(self, validator, data): # pylint: disable=invalid-name
|
||||
for val in data:
|
||||
try:
|
||||
validator(val)
|
||||
@@ -234,7 +236,7 @@ class SeleniumTestCase(StaticLiveServerTestCase):
|
||||
window_height = 768
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SeleniumTestCase, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
self._driver = None
|
||||
self._driver_options = webdriver.FirefoxOptions()
|
||||
self.quit_selenium = None
|
||||
@@ -254,7 +256,7 @@ class SeleniumTestCase(StaticLiveServerTestCase):
|
||||
def tearDown(self):
|
||||
if self.quit_selenium:
|
||||
self.selenium.quit()
|
||||
super(SeleniumTestCase, self).tearDown()
|
||||
super().tearDown()
|
||||
|
||||
def complete_url(self, location):
|
||||
base_url = self.live_server_url
|
||||
@@ -264,8 +266,8 @@ class SeleniumTestCase(StaticLiveServerTestCase):
|
||||
return self.selenium.get(self.complete_url(location))
|
||||
|
||||
def wait_on(self, driver, ec_name, ec_argument, timeout=30):
|
||||
ec = getattr(EC, ec_name)
|
||||
return WebDriverWait(driver, timeout).until(ec(ec_argument))
|
||||
expected_condition = getattr(ExpectedConditions, ec_name)
|
||||
return WebDriverWait(driver, timeout).until(expected_condition(ec_argument))
|
||||
|
||||
def wait_on_presence(self, driver, locator, timeout=30):
|
||||
ec_name = 'presence_of_element_located'
|
||||
@@ -281,7 +283,7 @@ class ScreenshotTestCase(SeleniumTestCase):
|
||||
locations = ()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ScreenshotTestCase, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
screenshot_base_dir = os.path.join('tmp', 'test-screenshots')
|
||||
self.screenshot_path = screenshot_base_dir
|
||||
self.screenshot_sequences = {}
|
||||
@@ -298,7 +300,7 @@ class ScreenshotTestCase(SeleniumTestCase):
|
||||
else:
|
||||
self.screenshot_sequences[sequence] = 1
|
||||
n = self.screenshot_sequences[sequence]
|
||||
sequence = u'%s-%04d-' % (sequence, n)
|
||||
sequence = '%s-%04d-' % (sequence, n)
|
||||
if title is None:
|
||||
location = self.selenium.current_url
|
||||
if location.startswith(self.live_server_url):
|
||||
@@ -308,7 +310,7 @@ class ScreenshotTestCase(SeleniumTestCase):
|
||||
location = 'root'
|
||||
title = location
|
||||
|
||||
base_name = u'{timestamp}-{prefix}{sequence}{title}.png'.format(
|
||||
base_name = '{timestamp}-{prefix}{sequence}{title}.png'.format(
|
||||
timestamp=datetime.datetime.now().strftime('%Y%m%d-%H%M%S.%f'),
|
||||
prefix=self.screenshot_prefix,
|
||||
sequence=sequence,
|
||||
|
||||
@@ -48,8 +48,8 @@ class DefaultSettingTestCase(SimpleTestCase):
|
||||
|
||||
re_validator = r'[a-z]'
|
||||
|
||||
valid_values = u'aocd'
|
||||
invalid_values = u'Aö1.'
|
||||
valid_values = 'aocd'
|
||||
invalid_values = 'Aö1.'
|
||||
|
||||
setting = DefaultSetting(name, None, validator=re_validator)
|
||||
for val in valid_values:
|
||||
@@ -89,7 +89,7 @@ class AppSettingsTestCase(SimpleTestCase):
|
||||
DefaultSetting('no_test_setting', ImproperlyConfigured),
|
||||
)
|
||||
with self.assertRaisesRegex(ImproperlyConfigured, 'NO_TEST_SETTING must be defined in main.settings-dav_base'):
|
||||
app_settings = AppSettings(self.app_name, default_settings)
|
||||
_ = AppSettings(self.app_name, default_settings)
|
||||
|
||||
def test_improperlyconfigured_by_instance(self):
|
||||
"""Test if mandatory but unset setting raise correct exception"""
|
||||
@@ -97,17 +97,17 @@ class AppSettingsTestCase(SimpleTestCase):
|
||||
DefaultSetting('no_test_setting', ImproperlyConfigured('Some Error Message')),
|
||||
)
|
||||
with self.assertRaisesRegex(ImproperlyConfigured, 'Some Error Message'):
|
||||
app_settings = AppSettings(self.app_name, default_settings)
|
||||
_ = AppSettings(self.app_name, default_settings)
|
||||
|
||||
def test_improperlyconfigured_by_func(self):
|
||||
"""Test if invalid setting raise correct exception"""
|
||||
def validator(value):
|
||||
def validator(value): # pylint: disable=unused-argument
|
||||
return False
|
||||
default_settings = (
|
||||
DefaultSetting('test_setting', 1, validator=validator),
|
||||
)
|
||||
with self.assertRaises(ImproperlyConfigured):
|
||||
app_settings = AppSettings(self.app_name, default_settings)
|
||||
_ = AppSettings(self.app_name, default_settings)
|
||||
|
||||
def test_improperlyconfigured_by_regex(self):
|
||||
"""Test if invalid setting raise correct exception"""
|
||||
@@ -115,7 +115,7 @@ class AppSettingsTestCase(SimpleTestCase):
|
||||
DefaultSetting('test_setting', 1, validator=r'^[01]$'),
|
||||
)
|
||||
with self.assertRaises(ImproperlyConfigured):
|
||||
app_settings = AppSettings(self.app_name, default_settings)
|
||||
_ = AppSettings(self.app_name, default_settings)
|
||||
|
||||
def test_settings_from_file(self):
|
||||
"""Test if value from settings file eliminate exception"""
|
||||
@@ -145,7 +145,7 @@ class AppSettingsTestCase(SimpleTestCase):
|
||||
class AppConfigTestCase(SimpleTestCase):
|
||||
def test_init(self):
|
||||
app_name = 'dav_base'
|
||||
import dav_base as app_module
|
||||
import dav_base as app_module # pylint: disable=import-outside-toplevel
|
||||
|
||||
test_default_settings = (
|
||||
DefaultSetting('test_setting', ImproperlyConfigured),
|
||||
@@ -154,7 +154,7 @@ class AppConfigTestCase(SimpleTestCase):
|
||||
|
||||
class TestAppConfig(AppConfig):
|
||||
name = 'not_dav_base'
|
||||
verbose_name = u'DAV Base App'
|
||||
verbose_name = 'DAV Base App'
|
||||
default_settings = test_default_settings
|
||||
|
||||
app_config = TestAppConfig(app_name, app_module)
|
||||
|
||||
@@ -10,7 +10,7 @@ MAIL_TEMPLATE = 'dav_base/tests/mail.txt'
|
||||
|
||||
class TestCase(EmailTestMixin, SimpleTestCase):
|
||||
def test_no_template_configured(self):
|
||||
class ConcreteMail(AbstractMail):
|
||||
class ConcreteMail(AbstractMail): # pylint: disable=abstract-method disable=too-few-public-methods
|
||||
pass
|
||||
|
||||
email = ConcreteMail()
|
||||
@@ -18,7 +18,7 @@ class TestCase(EmailTestMixin, SimpleTestCase):
|
||||
email.send()
|
||||
|
||||
def test_no_get_recipients_implemented(self):
|
||||
class ConcreteMail(AbstractMail):
|
||||
class ConcreteMail(AbstractMail): # pylint: disable=abstract-method disable=too-few-public-methods
|
||||
_template_name = MAIL_TEMPLATE
|
||||
|
||||
email = ConcreteMail()
|
||||
@@ -28,7 +28,7 @@ class TestCase(EmailTestMixin, SimpleTestCase):
|
||||
def test_send(self):
|
||||
recipient = 'root@localhost'
|
||||
|
||||
class ConcreteMail(AbstractMail):
|
||||
class ConcreteMail(AbstractMail): # pylint: disable=too-few-public-methods
|
||||
_template_name = MAIL_TEMPLATE
|
||||
|
||||
def _get_recipients(self):
|
||||
@@ -42,5 +42,5 @@ class TestCase(EmailTestMixin, SimpleTestCase):
|
||||
|
||||
self.assertSender(mail)
|
||||
self.assertRecipients(mail, [recipient])
|
||||
self.assertSubject(mail, u'')
|
||||
self.assertSubject(mail, '')
|
||||
self.assertBody(mail, 'MAILBODY')
|
||||
|
||||
@@ -5,7 +5,7 @@ from django.test import SimpleTestCase
|
||||
|
||||
class TemplatesTestCase(SimpleTestCase):
|
||||
def setUp(self):
|
||||
super(TemplatesTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.response_from_root_view = self.client.get('/')
|
||||
|
||||
def test_template_usage(self):
|
||||
|
||||
@@ -10,4 +10,4 @@ DAVNumberValidator = RegexValidator(r'^'
|
||||
r'(\*[0-9]{4}\*[0-9]{4})?'
|
||||
r'([* ][0-9]{8})?'
|
||||
r'$',
|
||||
_(u'Ungültiges Format.'))
|
||||
_('Ungültiges Format.'))
|
||||
|
||||
@@ -7,7 +7,7 @@ class RootView(generic.TemplateView):
|
||||
template_name = 'dav_base/root.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
c = super(RootView, self).get_context_data(**kwargs)
|
||||
c = super().get_context_data(**kwargs)
|
||||
root_urls = []
|
||||
for module_meta_obj in settings.MODULE_CONFIG.modules.values():
|
||||
root_url_name = 'root'
|
||||
|
||||
@@ -1 +1 @@
|
||||
default_app_config = 'dav_event_office.apps.AppConfig'
|
||||
default_app_config = 'dav_event_office.apps.AppConfig' # pylint: disable=invalid-name
|
||||
|
||||
@@ -5,5 +5,5 @@ DEFAULT_SETTINGS = ()
|
||||
|
||||
class AppConfig(_AppConfig):
|
||||
name = 'dav_event_office'
|
||||
verbose_name = u'DAV Touren- & Kursreferat'
|
||||
verbose_name = 'DAV Touren- & Kursreferat'
|
||||
default_settings = DEFAULT_SETTINGS
|
||||
|
||||
@@ -24,7 +24,7 @@ class EventListView(_EventListView):
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not DefaultWorkflow.has_global_permission(request.user, 'payment'):
|
||||
raise PermissionDenied('payment')
|
||||
return super(EventListView, self).dispatch(request, *args, **kwargs)
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
||||
class EventDetailView(_EventRegistrationsView):
|
||||
@@ -34,7 +34,7 @@ class EventDetailView(_EventRegistrationsView):
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not DefaultWorkflow.has_global_permission(request.user, 'payment'):
|
||||
raise PermissionDenied('payment')
|
||||
return super(EventDetailView, self).dispatch(request, *args, **kwargs)
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
||||
class ParticipantListView(generic.ListView):
|
||||
@@ -66,4 +66,4 @@ class ParticipantListView(generic.ListView):
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not DefaultWorkflow.has_global_permission(request.user, 'payment'):
|
||||
raise PermissionDenied('payment')
|
||||
return super(ParticipantListView, self).dispatch(request, *args, **kwargs)
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
@@ -1 +1 @@
|
||||
default_app_config = 'dav_events.apps.AppConfig'
|
||||
default_app_config = 'dav_events.apps.AppConfig' # pylint: disable=invalid-name
|
||||
|
||||
@@ -16,17 +16,17 @@ DEFAULT_SETTINGS = (
|
||||
DefaultSetting('groups_publisher_facebook', []),
|
||||
DefaultSetting('groups_office', []),
|
||||
DefaultSetting('forms_development_init', False),
|
||||
DefaultSetting('form_initials', dict()),
|
||||
DefaultSetting('form_initials', {}),
|
||||
DefaultSetting('matrix_config', ImproperlyConfigured),
|
||||
DefaultSetting('publish_before_begin_days', 10),
|
||||
DefaultSetting('publish_before_deadline_days', 7),
|
||||
DefaultSetting('publish_issues', list()),
|
||||
DefaultSetting('publish_issues', []),
|
||||
)
|
||||
|
||||
|
||||
class AppConfig(_AppConfig):
|
||||
name = 'dav_events'
|
||||
verbose_name = u'DAV Touren & Kurse'
|
||||
verbose_name = 'DAV Touren & Kurse'
|
||||
default_settings = DEFAULT_SETTINGS
|
||||
|
||||
def ready(self):
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import datetime
|
||||
import logging
|
||||
import pytz
|
||||
import re
|
||||
import pytz
|
||||
from six import string_types
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Iso8601Serializer(object):
|
||||
class Iso8601Serializer:
|
||||
marker = 'ISO8601'
|
||||
separator = ':'
|
||||
|
||||
|
||||
@@ -5,4 +5,4 @@ from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
class RegistrationResponseForm(forms.Form):
|
||||
apply_reduced_fee = forms.BooleanField(required=False,
|
||||
label=_(u'Reduzierte Teilnahmegebühr'))
|
||||
label=_('Reduzierte Teilnahmegebühr'))
|
||||
|
||||
@@ -1 +1 @@
|
||||
from .trashed_participant import TrashedParticipant
|
||||
from .trashed_participant import TrashedParticipant
|
||||
|
||||
@@ -14,9 +14,9 @@ register = template.Library()
|
||||
|
||||
@register.simple_tag
|
||||
def render_event_status(event, show_void=True):
|
||||
label_html = u'<span class="label label-{context}">{label}</span> '
|
||||
label_html = '<span class="label label-{context}">{label}</span> '
|
||||
|
||||
html = u''
|
||||
html = ''
|
||||
|
||||
status_list = event.workflow.get_status_list()
|
||||
if show_void and len(status_list) < 1:
|
||||
@@ -39,29 +39,29 @@ def render_event_status(event, show_void=True):
|
||||
|
||||
@register.simple_tag
|
||||
def render_event_changelog(event):
|
||||
change_templ = u'<li class="list-group-item">\n' \
|
||||
u'\t<p class="list-group-item-heading">' \
|
||||
u'<span class="glyphicon glyphicon-{icon}"></span>' \
|
||||
u' {timestamp}' \
|
||||
u' - ' \
|
||||
u' {user}</p>\n' \
|
||||
u'\t{content}\n' \
|
||||
u'</li>\n'
|
||||
update_sub_templ = u'<li class="list-group-item">\n' \
|
||||
u'\t{field}:{separator1}\n' \
|
||||
u'\t<span style="background-color: #ffe0e0;">{refer}</span>\n' \
|
||||
u'\t{separator2}\n' \
|
||||
u'\t<span style="background-color: #e0ffe0;">{current}</span>\n' \
|
||||
u'</li>\n'
|
||||
raise_flag_templ = u'<span class="text-success glyphicon glyphicon-plus"></span>' \
|
||||
u' <span class="label label-{bcontext}">{label}</span>' \
|
||||
u' <span class="text-success glyphicon glyphicon-plus"></span>'
|
||||
lower_flag_templ = u'<span class="text-danger glyphicon glyphicon-minus"></span>' \
|
||||
u' <del><span class="label label-{bcontext}">{label}</span></del>' \
|
||||
u' <span class="text-danger glyphicon glyphicon-minus"></span>'
|
||||
change_templ = '<li class="list-group-item">\n' \
|
||||
'\t<p class="list-group-item-heading">' \
|
||||
'<span class="glyphicon glyphicon-{icon}"></span>' \
|
||||
' {timestamp}' \
|
||||
' - ' \
|
||||
' {user}</p>\n' \
|
||||
'\t{content}\n' \
|
||||
'</li>\n'
|
||||
update_sub_templ = '<li class="list-group-item">\n' \
|
||||
'\t{field}:{separator1}\n' \
|
||||
'\t<span style="background-color: #ffe0e0;">{refer}</span>\n' \
|
||||
'\t{separator2}\n' \
|
||||
'\t<span style="background-color: #e0ffe0;">{current}</span>\n' \
|
||||
'</li>\n'
|
||||
raise_flag_templ = '<span class="text-success glyphicon glyphicon-plus"></span>' \
|
||||
' <span class="label label-{bcontext}">{label}</span>' \
|
||||
' <span class="text-success glyphicon glyphicon-plus"></span>'
|
||||
lower_flag_templ = '<span class="text-danger glyphicon glyphicon-minus"></span>' \
|
||||
' <del><span class="label label-{bcontext}">{label}</span></del>' \
|
||||
' <span class="text-danger glyphicon glyphicon-minus"></span>'
|
||||
|
||||
if event.changes.exists():
|
||||
html = u'<ul class="list-group">\n'
|
||||
html = '<ul class="list-group">\n'
|
||||
|
||||
for change in event.changes.all():
|
||||
|
||||
@@ -70,8 +70,8 @@ def render_event_changelog(event):
|
||||
username = change.user
|
||||
|
||||
if change.operation == EventChange.UPDATE:
|
||||
icon = u'pencil'
|
||||
content_html = u'<ul class="list-group">'
|
||||
icon = 'pencil'
|
||||
content_html = '<ul class="list-group">'
|
||||
subchanges = json.loads(change.content)
|
||||
for subchange in subchanges:
|
||||
field_label = event._meta.get_field(subchange['field']).verbose_name
|
||||
@@ -80,33 +80,33 @@ def render_event_changelog(event):
|
||||
except TypeError:
|
||||
is_long_strings = False
|
||||
if is_long_strings:
|
||||
separator1 = u'<br />'
|
||||
separator2 = u'<br />'
|
||||
separator1 = '<br />'
|
||||
separator2 = '<br />'
|
||||
else:
|
||||
separator1 = u' '
|
||||
separator2 = u' -> '
|
||||
separator1 = ' '
|
||||
separator2 = ' -> '
|
||||
content_html += format_html(update_sub_templ,
|
||||
field=field_label,
|
||||
separator1=mark_safe(separator1),
|
||||
refer=subchange['refer'],
|
||||
separator2=mark_safe(separator2),
|
||||
current=subchange['current'])
|
||||
content_html += u'</ul>'
|
||||
content_html += '</ul>'
|
||||
elif change.operation == EventChange.RAISE_FLAG:
|
||||
icon = u'flag'
|
||||
icon = 'flag'
|
||||
status = get_or_create_event_status(change.content)
|
||||
content_html = format_html(raise_flag_templ,
|
||||
bcontext=status.bootstrap_context or u'default',
|
||||
bcontext=status.bootstrap_context or 'default',
|
||||
label=status.label)
|
||||
elif change.operation == EventChange.LOWER_FLAG:
|
||||
icon = u'flag'
|
||||
icon = 'flag'
|
||||
status = get_or_create_event_status(change.content)
|
||||
content_html = format_html(lower_flag_templ,
|
||||
bcontext=status.bootstrap_context or u'default',
|
||||
bcontext=status.bootstrap_context or 'default',
|
||||
label=status.label)
|
||||
else:
|
||||
icon = u'question-sign'
|
||||
content_html = format_html(u'{content}', content=change.content)
|
||||
icon = 'question-sign'
|
||||
content_html = format_html('{content}', content=change.content)
|
||||
|
||||
html += format_html(change_templ,
|
||||
icon=icon,
|
||||
@@ -114,7 +114,7 @@ def render_event_changelog(event):
|
||||
user=username,
|
||||
content=mark_safe(content_html))
|
||||
|
||||
html += u'</ul>\n'
|
||||
html += '</ul>\n'
|
||||
else:
|
||||
html = _(u'Keine Einträge')
|
||||
html = _('Keine Einträge')
|
||||
return mark_safe(html)
|
||||
|
||||
@@ -6,13 +6,12 @@ import os
|
||||
from django.apps import apps
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import Group
|
||||
from django.db import models
|
||||
|
||||
from ..models.event import Event
|
||||
from ..models.eventstatus import EventStatus
|
||||
|
||||
|
||||
class RoleMixin(object):
|
||||
class RoleMixin:
|
||||
def create_user_for_role(self, role_name, password, first_name, last_name):
|
||||
group = Group(name=role_name)
|
||||
group.save()
|
||||
@@ -31,7 +30,7 @@ class RoleMixin(object):
|
||||
return user
|
||||
|
||||
|
||||
class EventMixin(object):
|
||||
class EventMixin:
|
||||
def get_status_label(self, status_code):
|
||||
return EventStatus.objects.get(code=status_code).label
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import sys
|
||||
import datetime
|
||||
from unittest import TestCase
|
||||
|
||||
@@ -10,7 +9,7 @@ class Iso8601SerializerTestCase(TestCase):
|
||||
date = start_date
|
||||
while date <= end_date:
|
||||
text = '%04d-%02d-%02d' % (date.year, date.month, date.day)
|
||||
yield (date, text)
|
||||
yield date, text
|
||||
date += datetime.timedelta(step)
|
||||
|
||||
def _gen_times(self, step_hours=1, step_minutes=1, step_seconds=1):
|
||||
@@ -50,7 +49,7 @@ class Iso8601SerializerTestCase(TestCase):
|
||||
'2019-03-01',
|
||||
)
|
||||
for value in invalid_values:
|
||||
emsg = ('Expected datetime.datetime, datetime.date or datetime.time,'
|
||||
emsg = ('Expected datetime.datetime, datetime.date or datetime.time,'
|
||||
' not {}'.format(value.__class__.__name__))
|
||||
with self.assertRaisesRegexp(ValueError, emsg):
|
||||
Iso8601Serializer.serialize(value)
|
||||
|
||||
@@ -83,7 +83,7 @@ Ausschreibung:
|
||||
==============
|
||||
{event_text}"""
|
||||
|
||||
EVENT_ACCEPTED_EMAIL_TEMPLATE=u"""Hallo {recipient_first_name},
|
||||
EVENT_ACCEPTED_EMAIL_TEMPLATE = """Hallo {recipient_first_name},
|
||||
|
||||
deine Veranstaltung wurde von {editor_full_name} freigegeben.
|
||||
Die Redaktion wurde informiert, um deine Veranstaltung zu veröffentlichen.
|
||||
|
||||
@@ -158,4 +158,3 @@ class EventsTestCase(EventMixin, TestCase):
|
||||
def test_event_create_view(self):
|
||||
for data in self.gen_create_event_input():
|
||||
self.create_event_by_view(data)
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ class OneClickActionRunView(generic.DetailView):
|
||||
login(self.request, user)
|
||||
logger.info('Logged in via OneClickAction: %s', user.username)
|
||||
messages.success(self.request,
|
||||
_(u'Benutzer angemeldet: %(username)s') % {'username': user.username})
|
||||
_('Benutzer angemeldet: %(username)s') % {'username': user.username})
|
||||
|
||||
if 'location' in result:
|
||||
return HttpResponseRedirect(result['location'])
|
||||
|
||||
@@ -1 +1 @@
|
||||
default_app_config = 'dav_registration.apps.AppConfig'
|
||||
default_app_config = 'dav_registration.apps.AppConfig' # pylint: disable=invalid-name
|
||||
|
||||
@@ -9,7 +9,7 @@ DEFAULT_SETTINGS = (
|
||||
|
||||
class AppConfig(_AppConfig):
|
||||
name = 'dav_registration'
|
||||
verbose_name = u'DAV Kurs-Anmeldungen'
|
||||
verbose_name = 'DAV Kurs-Anmeldungen'
|
||||
default_settings = DEFAULT_SETTINGS
|
||||
|
||||
def ready(self):
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
from dav_base.emails import AbstractMail
|
||||
|
||||
|
||||
class AbstractRegistrationMail(AbstractMail):
|
||||
class AbstractRegistrationMail(AbstractMail): # pylint: disable=too-few-public-methods
|
||||
def __init__(self, recipient, registration):
|
||||
self._recipient = recipient
|
||||
self._registration = registration
|
||||
@@ -13,45 +13,45 @@ class AbstractRegistrationMail(AbstractMail):
|
||||
subject_fmt = self._subject
|
||||
|
||||
if self._event.number:
|
||||
subject_fmt = u'%s: %s' % (self._event.number, subject_fmt)
|
||||
subject_fmt = '%s: %s' % (self._event.number, subject_fmt)
|
||||
|
||||
return super(AbstractRegistrationMail, self)._get_subject(subject_fmt=subject_fmt, **kwargs)
|
||||
return super()._get_subject(subject_fmt=subject_fmt, **kwargs)
|
||||
|
||||
def _get_recipients(self):
|
||||
if hasattr(self._recipient, 'get_full_name') and hasattr(self._recipient, 'email'):
|
||||
r = u'"{fullname}" <{email}>'.format(fullname=self._recipient.get_full_name(),
|
||||
email=self._recipient.email)
|
||||
r = '"{fullname}" <{email}>'.format(fullname=self._recipient.get_full_name(),
|
||||
email=self._recipient.email)
|
||||
else:
|
||||
r = self._recipient
|
||||
return [r]
|
||||
|
||||
def _get_context_data(self, extra_context=None):
|
||||
context = super(AbstractRegistrationMail, self)._get_context_data(extra_context=extra_context)
|
||||
context = super()._get_context_data(extra_context=extra_context)
|
||||
context['recipient'] = self._recipient
|
||||
context['registration'] = self._registration
|
||||
context['event'] = self._event
|
||||
return context
|
||||
|
||||
|
||||
class InformTrainerRegistrationMail(AbstractRegistrationMail):
|
||||
_subject = u'Anmeldung {full_name}'
|
||||
class InformTrainerRegistrationMail(AbstractRegistrationMail): # pylint: disable=too-few-public-methods
|
||||
_subject = 'Anmeldung {full_name}'
|
||||
_template_name = 'dav_registration/emails/inform_trainer.txt'
|
||||
|
||||
def _get_subject(self, subject_fmt=None, **kwargs):
|
||||
kwargs['full_name'] = self._registration.get_full_name()
|
||||
return super(InformTrainerRegistrationMail, self)._get_subject(subject_fmt=subject_fmt, **kwargs)
|
||||
return super()._get_subject(subject_fmt=subject_fmt, **kwargs)
|
||||
|
||||
def _get_reply_to(self):
|
||||
s = u'"{fullname}" <{email}>'.format(fullname=self._registration.get_full_name(),
|
||||
email=self._registration.email_address)
|
||||
return [s]
|
||||
reply_to = '"{fullname}" <{email}>'.format(fullname=self._registration.get_full_name(),
|
||||
email=self._registration.email_address)
|
||||
return [reply_to]
|
||||
|
||||
|
||||
class InformSelfRegistrationMail(AbstractRegistrationMail):
|
||||
_subject = u'Deine Anmeldung'
|
||||
class InformSelfRegistrationMail(AbstractRegistrationMail): # pylint: disable=too-few-public-methods
|
||||
_subject = 'Deine Anmeldung'
|
||||
_template_name = 'dav_registration/emails/inform_self.txt'
|
||||
|
||||
def _get_reply_to(self):
|
||||
s = u'"{fullname}" <{email}>'.format(fullname=self._event.owner.get_full_name(),
|
||||
email=self._event.owner.email)
|
||||
return [s]
|
||||
reply_to = '"{fullname}" <{email}>'.format(fullname=self._event.owner.get_full_name(),
|
||||
email=self._event.owner.email)
|
||||
return [reply_to]
|
||||
|
||||
@@ -11,13 +11,13 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class RegistrationForm(forms.ModelForm):
|
||||
not_dav_member = forms.BooleanField(required=False,
|
||||
label=_(u'Ich bin noch kein DAV Mitglied.'),
|
||||
help_text=u'%s<br />\n%s' % (
|
||||
_(u'Wenn du noch kein DAV Mitglied bist,'
|
||||
u' oder deine Aufnahme noch in Arbeit ist,'
|
||||
u' kreuze dieses Feld hier an.'),
|
||||
_(u'Spätestens zu Veranstaltungsbeginn muss'
|
||||
u' jedoch eine Mitgliedschaft bestehen.')
|
||||
label=_('Ich bin noch kein DAV Mitglied.'),
|
||||
help_text='%s<br />\n%s' % (
|
||||
_('Wenn du noch kein DAV Mitglied bist,'
|
||||
' oder deine Aufnahme noch in Arbeit ist,'
|
||||
' kreuze dieses Feld hier an.'),
|
||||
_('Spätestens zu Veranstaltungsbeginn muss'
|
||||
' jedoch eine Mitgliedschaft bestehen.')
|
||||
))
|
||||
|
||||
class Meta:
|
||||
@@ -30,7 +30,7 @@ class RegistrationForm(forms.ModelForm):
|
||||
'note': forms.Textarea(attrs={'rows': 5}),
|
||||
}
|
||||
labels = {
|
||||
'apply_reduced_fee': _(u'Ich bin noch keine 25 Jahre alt oder besitze einen "Karlsruher Pass".'),
|
||||
'apply_reduced_fee': _('Ich bin noch keine 25 Jahre alt oder besitze einen "Karlsruher Pass".'),
|
||||
}
|
||||
|
||||
def clean_year_of_birth(self):
|
||||
@@ -40,16 +40,16 @@ class RegistrationForm(forms.ModelForm):
|
||||
val = self.cleaned_data.get('year_of_birth')
|
||||
if val > year_now:
|
||||
raise forms.ValidationError(
|
||||
ugettext(u'Dein Geburtsjahr liegt in der Zukunft?'
|
||||
u' Das finden wir gut,'
|
||||
u' aber bitte melde dich besser mal per E-Mail bei uns.'),
|
||||
ugettext('Dein Geburtsjahr liegt in der Zukunft?'
|
||||
' Das finden wir gut,'
|
||||
' aber bitte melde dich besser mal per E-Mail bei uns.'),
|
||||
code='to_young',
|
||||
)
|
||||
elif val < (year_now - max_age):
|
||||
raise forms.ValidationError(
|
||||
ugettext(u'Du bist schon über %(max_age)d Jahre alt?'
|
||||
u' Das finden wir gut,'
|
||||
u' aber bitte melde dich besser mal per E-Mail bei uns.'),
|
||||
ugettext('Du bist schon über %(max_age)d Jahre alt?'
|
||||
' Das finden wir gut,'
|
||||
' aber bitte melde dich besser mal per E-Mail bei uns.'),
|
||||
params={'max_age': max_age},
|
||||
code='to_old',
|
||||
)
|
||||
@@ -63,8 +63,8 @@ class RegistrationForm(forms.ModelForm):
|
||||
need_experience = False
|
||||
if need_experience:
|
||||
raise forms.ValidationError(
|
||||
ugettext(u'Die Tourenleiter*innen brauchen ein paar Angaben,'
|
||||
u' was du bereits kannst oder wie fit du bist.'),
|
||||
ugettext('Die Tourenleiter*innen brauchen ein paar Angaben,'
|
||||
' was du bereits kannst oder wie fit du bist.'),
|
||||
code='need_experience',
|
||||
)
|
||||
return val
|
||||
@@ -73,18 +73,18 @@ class RegistrationForm(forms.ModelForm):
|
||||
val = self.cleaned_data.get('privacy_policy_accepted')
|
||||
if not val and self.instance.privacy_policy:
|
||||
raise forms.ValidationError(
|
||||
ugettext(u'Wir müssen deine Daten leider speichern können,'
|
||||
u' damit wir wissen, dass du teilnehmen möchtest.'),
|
||||
ugettext('Wir müssen deine Daten leider speichern können,'
|
||||
' damit wir wissen, dass du teilnehmen möchtest.'),
|
||||
code='privacy_policy_not_accepted',
|
||||
)
|
||||
return val
|
||||
|
||||
def clean(self):
|
||||
super(RegistrationForm, self).clean()
|
||||
super().clean()
|
||||
dav_member = self.cleaned_data.get('dav_member')
|
||||
dav_number = self.cleaned_data.get('dav_number')
|
||||
if dav_member and not dav_number:
|
||||
error_msg = ugettext(u'Wenn du DAV Mitglied bist, brauchen wir deine Mitgliedsnummer.')
|
||||
error_msg = ugettext('Wenn du DAV Mitglied bist, brauchen wir deine Mitgliedsnummer.')
|
||||
self.add_error('not_dav_member', error_msg)
|
||||
raise forms.ValidationError(error_msg, code='dav_number_missing')
|
||||
return self.cleaned_data
|
||||
|
||||
@@ -182,7 +182,7 @@ Anmerkung:
|
||||
self.purge_at = self.__class__.calc_purge_at(self.event)
|
||||
|
||||
self.full_clean()
|
||||
super(Registration, self).save(**kwargs)
|
||||
super().save(**kwargs)
|
||||
|
||||
if creating:
|
||||
status = RegistrationStatus(registration=self)
|
||||
@@ -238,7 +238,7 @@ class RegistrationStatus(models.Model):
|
||||
|
||||
def save(self, **kwargs):
|
||||
self.full_clean()
|
||||
super(RegistrationStatus, self).save(**kwargs)
|
||||
super().save(**kwargs)
|
||||
|
||||
def set_accepted(self):
|
||||
self.accepted = True
|
||||
|
||||
@@ -5,7 +5,7 @@ from . import emails
|
||||
registration_created = Signal(providing_args=['registration'])
|
||||
|
||||
|
||||
def send_emails_on_registration(sender, **kwargs):
|
||||
def send_emails_on_registration(sender, **kwargs): # pylint: disable=unused-argument
|
||||
registration = kwargs.get('registration')
|
||||
|
||||
# Inform the event owner (trainer)
|
||||
@@ -14,7 +14,7 @@ def send_emails_on_registration(sender, **kwargs):
|
||||
email.send()
|
||||
|
||||
# Inform the potential participant
|
||||
recipient = u'"{fullname}" <{email}>'.format(fullname=registration.get_full_name(),
|
||||
email=registration.email_address)
|
||||
recipient = '"{fullname}" <{email}>'.format(fullname=registration.get_full_name(),
|
||||
email=registration.email_address)
|
||||
email = emails.InformSelfRegistrationMail(recipient=recipient, registration=registration)
|
||||
email.send()
|
||||
|
||||
@@ -12,5 +12,3 @@ def render_event_paragraphs(event):
|
||||
@register.simple_tag
|
||||
def render_event_facts(event):
|
||||
return render_to_string('dav_registration/event/facts.html', {'event': event})
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ from ..models import Registration
|
||||
THIS_YEAR = timezone.now().year
|
||||
|
||||
|
||||
class RegistrationMixin(object):
|
||||
class RegistrationMixin: # pylint: disable=too-few-public-methods
|
||||
def create_registration(self, data):
|
||||
r = Registration(**data)
|
||||
r.save()
|
||||
|
||||
@@ -95,7 +95,7 @@ Zeitpunkt der Datenlöschung: {purge_at}
|
||||
|
||||
class EmailsTestCase(EmailTestMixin, EventMixin, RegistrationMixin, TestCase):
|
||||
def setUp(self):
|
||||
super(EmailsTestCase, self).setUp()
|
||||
super().setUp()
|
||||
|
||||
app_config = apps.get_app_config('dav_events')
|
||||
app_config.settings.enable_email_on_status_update = False
|
||||
|
||||
@@ -11,7 +11,7 @@ from .generic import THIS_YEAR, RegistrationMixin
|
||||
|
||||
class RegistrationTestCase(EventMixin, RegistrationMixin, TestCase):
|
||||
def setUp(self):
|
||||
super(RegistrationTestCase, self).setUp()
|
||||
super().setUp()
|
||||
|
||||
app_config = apps.get_app_config('dav_events')
|
||||
app_config.settings.enable_email_on_status_update = False
|
||||
@@ -100,4 +100,3 @@ class RegistrationTestCase(EventMixin, RegistrationMixin, TestCase):
|
||||
'dav_member': False,
|
||||
}
|
||||
self.create_registration(registration_data)
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ class UtilsTestCase(RegistrationMixin, EventMixin, TestCase):
|
||||
self.submit_event(event)
|
||||
self.accept_event(event)
|
||||
|
||||
for i in range(0, registrations_per_event):
|
||||
for _ in range(0, registrations_per_event):
|
||||
d = registration_data
|
||||
d['event'] = event
|
||||
self.create_registration(d)
|
||||
|
||||
@@ -23,7 +23,7 @@ class RootView(generic.RedirectView):
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
purge_registrations()
|
||||
return super(RootView, self).get(request, *args, **kwargs)
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
|
||||
class EventListView(generic.ListView):
|
||||
@@ -33,14 +33,14 @@ class EventListView(generic.ListView):
|
||||
def get_queryset(self):
|
||||
today = datetime.date.today()
|
||||
|
||||
filter = Q(flags__status__code__in=('publishing', 'publishing_web', 'publishing_facebook',
|
||||
'published', 'published_web', 'published_facebook'))
|
||||
filter &= Q(planned_publication_date__isnull=True) | Q(planned_publication_date__lte=today)
|
||||
filter &= Q(first_day__gte=today)
|
||||
# filter &= Q(registration_closed=False)
|
||||
# filter &= Q(deadline__isnull=True) | Q(deadline__gte=today)
|
||||
filter_exp = Q(flags__status__code__in=('publishing', 'publishing_web', 'publishing_facebook',
|
||||
'published', 'published_web', 'published_facebook'))
|
||||
filter_exp &= Q(planned_publication_date__isnull=True) | Q(planned_publication_date__lte=today)
|
||||
filter_exp &= Q(first_day__gte=today)
|
||||
# filter_exp &= Q(registration_closed=False)
|
||||
# filter_exp &= Q(deadline__isnull=True) | Q(deadline__gte=today)
|
||||
|
||||
qs = self.model.objects.filter(filter).order_by('first_day', 'number').distinct()
|
||||
qs = self.model.objects.filter(filter_exp).order_by('first_day', 'number').distinct()
|
||||
|
||||
return qs
|
||||
|
||||
@@ -52,14 +52,14 @@ class EventDetailView(generic.DetailView):
|
||||
def get_queryset(self):
|
||||
today = datetime.date.today()
|
||||
|
||||
filter = Q(flags__status__code__in=('publishing', 'publishing_web', 'publishing_facebook',
|
||||
'published', 'published_web', 'published_facebook'))
|
||||
filter &= Q(planned_publication_date__isnull=True) | Q(planned_publication_date__lte=today)
|
||||
filter &= Q(first_day__gte=today)
|
||||
# filter &= Q(registration_closed=False)
|
||||
# filter &= Q(deadline__isnull=True) | Q(deadline__gte=today)
|
||||
filter_exp = Q(flags__status__code__in=('publishing', 'publishing_web', 'publishing_facebook',
|
||||
'published', 'published_web', 'published_facebook'))
|
||||
filter_exp &= Q(planned_publication_date__isnull=True) | Q(planned_publication_date__lte=today)
|
||||
filter_exp &= Q(first_day__gte=today)
|
||||
# filter_exp &= Q(registration_closed=False)
|
||||
# filter_exp &= Q(deadline__isnull=True) | Q(deadline__gte=today)
|
||||
|
||||
qs = self.model.objects.filter(filter).distinct()
|
||||
qs = self.model.objects.filter(filter_exp).distinct()
|
||||
|
||||
return qs
|
||||
|
||||
@@ -74,72 +74,72 @@ class RegistrationView(generic.CreateView):
|
||||
def get_queryset(self):
|
||||
today = datetime.date.today()
|
||||
|
||||
filter = Q(flags__status__code__in=('publishing', 'publishing_web', 'publishing_facebook',
|
||||
'published', 'published_web', 'published_facebook'))
|
||||
filter &= Q(planned_publication_date__isnull=True) | Q(planned_publication_date__lte=today)
|
||||
filter &= Q(first_day__gte=today)
|
||||
filter &= Q(registration_closed=False)
|
||||
filter &= Q(deadline__isnull=True) | Q(deadline__gte=today)
|
||||
filter_exp = Q(flags__status__code__in=('publishing', 'publishing_web', 'publishing_facebook',
|
||||
'published', 'published_web', 'published_facebook'))
|
||||
filter_exp &= Q(planned_publication_date__isnull=True) | Q(planned_publication_date__lte=today)
|
||||
filter_exp &= Q(first_day__gte=today)
|
||||
filter_exp &= Q(registration_closed=False)
|
||||
filter_exp &= Q(deadline__isnull=True) | Q(deadline__gte=today)
|
||||
|
||||
qs = Event.objects.filter(filter).distinct()
|
||||
qs = Event.objects.filter(filter_exp).distinct()
|
||||
|
||||
return qs
|
||||
|
||||
def get_initial(self):
|
||||
initials = super(RegistrationView, self).get_initial()
|
||||
initials = super().get_initial()
|
||||
return initials
|
||||
|
||||
def get_form(self, form_class=None):
|
||||
form = super(RegistrationView, self).get_form(form_class)
|
||||
form = super().get_form(form_class)
|
||||
|
||||
event = self.get_object()
|
||||
|
||||
experience_label = form.fields['experience'].label
|
||||
experience_help_text = form.fields['experience'].help_text
|
||||
if event.sport == 'B':
|
||||
experience_label = _(u'Eigene Bergerfahrung')
|
||||
experience_label = _('Eigene Bergerfahrung')
|
||||
elif event.sport == 'K' and event.terrain == 'alpine':
|
||||
experience_label = _(u'Eigene Fels- und Bergerfahrung')
|
||||
experience_label = _('Eigene Fels- und Bergerfahrung')
|
||||
if event.level == 'beginner':
|
||||
experience_help_text = u'%s<br /> %s<br /> %s' % (
|
||||
_(u'Warst du schon mal im Gebirge klettern?'),
|
||||
_(u'In welchem Schwierigkeitsgrad hast du Spaß?'),
|
||||
_(u'Bist du schon mal vorgestiegen?')
|
||||
experience_help_text = '%s<br /> %s<br /> %s' % (
|
||||
_('Warst du schon mal im Gebirge klettern?'),
|
||||
_('In welchem Schwierigkeitsgrad hast du Spaß?'),
|
||||
_('Bist du schon mal vorgestiegen?')
|
||||
)
|
||||
else:
|
||||
experience_help_text = u'%s<br /> %s<br /> %s' % (
|
||||
_(u'In welchen Klettergebieten/Touren warst du bisher unterwegs?'),
|
||||
_(u'In welchem Schwierigkeitsgrad hast du im Vorstieg Spaß?'),
|
||||
_(u'Wie waren die Touren abgesichert, in denen du dich noch wohlgefühlt hast?')
|
||||
experience_help_text = '%s<br /> %s<br /> %s' % (
|
||||
_('In welchen Klettergebieten/Touren warst du bisher unterwegs?'),
|
||||
_('In welchem Schwierigkeitsgrad hast du im Vorstieg Spaß?'),
|
||||
_('Wie waren die Touren abgesichert, in denen du dich noch wohlgefühlt hast?')
|
||||
)
|
||||
elif event.sport == 'K':
|
||||
experience_label = _(u'Eigene Klettererfahrung')
|
||||
experience_label = _('Eigene Klettererfahrung')
|
||||
if event.level == 'beginner':
|
||||
experience_help_text = u'%s<br /> %s<br /> %s' % (
|
||||
_(u'Warst du schon mal am Fels klettern?'),
|
||||
_(u'In welchem Schwierigkeitsgrad hast du Spaß?'),
|
||||
_(u'Bist du schon mal vorgestiegen?')
|
||||
experience_help_text = '%s<br /> %s<br /> %s' % (
|
||||
_('Warst du schon mal am Fels klettern?'),
|
||||
_('In welchem Schwierigkeitsgrad hast du Spaß?'),
|
||||
_('Bist du schon mal vorgestiegen?')
|
||||
)
|
||||
else:
|
||||
experience_help_text = u'%s<br /> %s<br /> %s' % (
|
||||
_(u'In welchen Klettergebieten warst du bisher unterwegs?'),
|
||||
_(u'In welchem Schwierigkeitsgrad hast du im Vorstieg Spaß?'),
|
||||
_(u'Wie waren die Touren abgesichert, in denen du dich noch wohlgefühlt hast?')
|
||||
experience_help_text = '%s<br /> %s<br /> %s' % (
|
||||
_('In welchen Klettergebieten warst du bisher unterwegs?'),
|
||||
_('In welchem Schwierigkeitsgrad hast du im Vorstieg Spaß?'),
|
||||
_('Wie waren die Touren abgesichert, in denen du dich noch wohlgefühlt hast?')
|
||||
)
|
||||
elif event.sport == 'M':
|
||||
experience_label = _(u'Eigene MTB-Erfahrung')
|
||||
experience_help_text = u'%s' % (
|
||||
_(u'Was für Touren bist du schon gefahren?')
|
||||
experience_label = _('Eigene MTB-Erfahrung')
|
||||
experience_help_text = '%s' % (
|
||||
_('Was für Touren bist du schon gefahren?')
|
||||
)
|
||||
if event.level != 'beginner':
|
||||
experience_help_text += u'<br /> %s' % (
|
||||
_(u'Single-Trail-Schwierigkeit (S0-S5) bei der du dich wohl fühlst?')
|
||||
experience_help_text += '<br /> %s' % (
|
||||
_('Single-Trail-Schwierigkeit (S0-S5) bei der du dich wohl fühlst?')
|
||||
)
|
||||
elif event.sport == 'S':
|
||||
experience_label = _(u'Eigene Skitouren- und Bergerfahrung')
|
||||
experience_label = _('Eigene Skitouren- und Bergerfahrung')
|
||||
elif event.sport == 'W':
|
||||
experience_help_text += u'<br /> %s' % (
|
||||
_(u'Kann frei gelassen werden.')
|
||||
experience_help_text += '<br /> %s' % (
|
||||
_('Kann frei gelassen werden.')
|
||||
)
|
||||
|
||||
form.fields['experience'].label = experience_label
|
||||
@@ -150,7 +150,7 @@ class RegistrationView(generic.CreateView):
|
||||
return form
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(RegistrationView, self).get_context_data(**kwargs)
|
||||
context = super().get_context_data(**kwargs)
|
||||
event = self.get_object()
|
||||
context['event'] = event
|
||||
context['privacy_policy'] = app_config.settings.privacy_policy
|
||||
@@ -158,16 +158,16 @@ class RegistrationView(generic.CreateView):
|
||||
return context
|
||||
|
||||
def form_valid(self, form):
|
||||
r = super(RegistrationView, self).form_valid(form)
|
||||
r = super().form_valid(form)
|
||||
self.request.session['registration_id'] = form.instance.pk
|
||||
message = _(u'Deine Anmeldung wurde erfolgreich gespeichert.')
|
||||
message = _('Deine Anmeldung wurde erfolgreich gespeichert.')
|
||||
messages.success(self.request, message)
|
||||
return r
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
if 'registration_id' in request.session:
|
||||
del request.session['registration_id']
|
||||
return super(RegistrationView, self).post(request, *args, **kwargs)
|
||||
return super().post(request, *args, **kwargs)
|
||||
|
||||
|
||||
class RegistrationSuccessView(generic.DetailView):
|
||||
|
||||
@@ -1 +1 @@
|
||||
default_app_config = 'dav_submission.apps.AppConfig'
|
||||
default_app_config = 'dav_submission.apps.AppConfig' # pylint: disable=invalid-name
|
||||
|
||||
@@ -19,5 +19,5 @@ DEFAULT_SETTINGS = (
|
||||
|
||||
class AppConfig(_AppConfig):
|
||||
name = 'dav_submission'
|
||||
verbose_name = u'DAV Beitragsupload (150 Jahre DAV)'
|
||||
verbose_name = 'DAV Beitragsupload (150 Jahre DAV)'
|
||||
default_settings = DEFAULT_SETTINGS
|
||||
|
||||
@@ -6,8 +6,8 @@ from dav_base.emails import AbstractMail
|
||||
app_config = apps.get_containing_app_config(__package__)
|
||||
|
||||
|
||||
class NewSubmissionMail(AbstractMail):
|
||||
_subject = u'Neuer Beitrag: {title}'
|
||||
class NewSubmissionMail(AbstractMail): # pylint: disable=too-few-public-methods
|
||||
_subject = 'Neuer Beitrag: {title}'
|
||||
_template_name = 'dav_submission/emails/new_submission.txt'
|
||||
|
||||
def __init__(self, metadata):
|
||||
@@ -15,18 +15,18 @@ class NewSubmissionMail(AbstractMail):
|
||||
|
||||
def _get_subject(self, subject_fmt=None, **kwargs):
|
||||
kwargs['title'] = self._metadata['title']
|
||||
return super(NewSubmissionMail, self)._get_subject(subject_fmt=subject_fmt, **kwargs)
|
||||
return super()._get_subject(subject_fmt=subject_fmt, **kwargs)
|
||||
|
||||
def _get_reply_to(self):
|
||||
s = u'"{fullname}" <{email}>'.format(fullname=self._metadata['name'],
|
||||
email=self._metadata['email_address'])
|
||||
return [s]
|
||||
reply_to = '"{fullname}" <{email}>'.format(fullname=self._metadata['name'],
|
||||
email=self._metadata['email_address'])
|
||||
return [reply_to]
|
||||
|
||||
def _get_recipients(self):
|
||||
r = app_config.settings.notify_address
|
||||
return [r]
|
||||
|
||||
def _get_context_data(self, extra_context=None):
|
||||
context = super(NewSubmissionMail, self)._get_context_data(extra_context=extra_context)
|
||||
context = super()._get_context_data(extra_context=extra_context)
|
||||
context['metadata'] = self._metadata
|
||||
return context
|
||||
|
||||
@@ -8,59 +8,59 @@ app_config = apps.get_containing_app_config(__package__)
|
||||
|
||||
class UploadForm(forms.Form):
|
||||
name = forms.CharField(max_length=1024,
|
||||
label=_(u'Dein Name'),
|
||||
help_text=_(u'Wenn wir wissen, wie du heißt, wird uns das echt weiter helfen'))
|
||||
email_address = forms.EmailField(label=_(u'Deine E-Mail-Adresse'),
|
||||
help_text=_(u'Damit wir dich für Rückfragen kontaktieren können'))
|
||||
label=_('Dein Name'),
|
||||
help_text=_('Wenn wir wissen, wie du heißt, wird uns das echt weiter helfen'))
|
||||
email_address = forms.EmailField(label=_('Deine E-Mail-Adresse'),
|
||||
help_text=_('Damit wir dich für Rückfragen kontaktieren können'))
|
||||
|
||||
group = forms.CharField(max_length=1024,
|
||||
required=False,
|
||||
label=_(u'DAV Gruppe'),
|
||||
help_text=_(u'Optional, falls du aktiv in einer der Sektionsgruppen bist'))
|
||||
label=_('DAV Gruppe'),
|
||||
help_text=_('Optional, falls du aktiv in einer der Sektionsgruppen bist'))
|
||||
|
||||
title = forms.CharField(max_length=60,
|
||||
label=_(u'Titel deines Beitrags / Stichwort'),
|
||||
help_text=u'%s<br />\n%s' % (
|
||||
_(u'Kommt zum Bild, falls es veröffentlicht wird'),
|
||||
_(u'Maximal 60 Zeichen')
|
||||
label=_('Titel deines Beitrags / Stichwort'),
|
||||
help_text='%s<br />\n%s' % (
|
||||
_('Kommt zum Bild, falls es veröffentlicht wird'),
|
||||
_('Maximal 60 Zeichen')
|
||||
))
|
||||
|
||||
description = forms.CharField(max_length=300,
|
||||
label=_(u'Beschreibung'),
|
||||
help_text=u'%s<br />\n%s' % (
|
||||
_(u'Wo warst du? Was hast du gemacht? Worum ging es bei der Aktion?'),
|
||||
_(u'Maximal 300 Zeichen')
|
||||
label=_('Beschreibung'),
|
||||
help_text='%s<br />\n%s' % (
|
||||
_('Wo warst du? Was hast du gemacht? Worum ging es bei der Aktion?'),
|
||||
_('Maximal 300 Zeichen')
|
||||
),
|
||||
widget=forms.Textarea(attrs={'rows': 2}))
|
||||
|
||||
files = forms.FileField(label=_(u'Dateien'),
|
||||
help_text=_(u'Wenn du auf den Button klickst, kannst du mehrere Dateien auswählen'
|
||||
u' (nötigenfalls Strg- oder Command-Taste benutzen)'),
|
||||
files = forms.FileField(label=_('Dateien'),
|
||||
help_text=_('Wenn du auf den Button klickst, kannst du mehrere Dateien auswählen'
|
||||
' (nötigenfalls Strg- oder Command-Taste benutzen)'),
|
||||
widget=forms.ClearableFileInput(attrs={'multiple': True}))
|
||||
|
||||
accepted = forms.BooleanField(required=False,
|
||||
label=_(u'Ja, ich stimme den Teilnahmebedingungen zu!'))
|
||||
label=_('Ja, ich stimme den Teilnahmebedingungen zu!'))
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(UploadForm, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.fields['title'].widget.attrs['placeholder'] = \
|
||||
u'z.B. Nacktbesteigung der Nose' \
|
||||
u' oder Juma jümart Jung-Mann-Weg'[:self.fields['title'].max_length]
|
||||
'z.B. Nacktbesteigung der Nose' \
|
||||
' oder Juma jümart Jung-Mann-Weg'[:self.fields['title'].max_length]
|
||||
|
||||
self.fields['group'].widget.attrs['placeholder'] = \
|
||||
ugettext(u'Kann frei gelassen werden')[:self.fields['title'].max_length]
|
||||
ugettext('Kann frei gelassen werden')[:self.fields['title'].max_length]
|
||||
|
||||
help_text = self.fields['files'].help_text
|
||||
if app_config.settings.max_files:
|
||||
help_text += u'<br />\n%s' % (ugettext(u'Wähle bis zu %d Dateien aus')
|
||||
% app_config.settings.max_files)
|
||||
help_text += '<br />\n%s' % (ugettext('Wähle bis zu %d Dateien aus')
|
||||
% app_config.settings.max_files)
|
||||
if app_config.settings.max_file_size_mib:
|
||||
help_text += u'<br />\n%s' % (ugettext(u'Einzelne Dateien dürfen maximal %d MiB groß sein')
|
||||
% app_config.settings.max_file_size_mib)
|
||||
help_text += '<br />\n%s' % (ugettext('Einzelne Dateien dürfen maximal %d MiB groß sein')
|
||||
% app_config.settings.max_file_size_mib)
|
||||
if app_config.settings.max_total_size_mib:
|
||||
help_text += u'<br />\n%s' % (ugettext(u'Alle Dateien zusammen dürfen maximal %d MiB groß sein')
|
||||
% app_config.settings.max_total_size_mib)
|
||||
help_text += '<br />\n%s' % (ugettext('Alle Dateien zusammen dürfen maximal %d MiB groß sein')
|
||||
% app_config.settings.max_total_size_mib)
|
||||
self.fields['files'].help_text = help_text
|
||||
|
||||
def clean_files(self):
|
||||
@@ -77,35 +77,35 @@ class UploadForm(forms.Form):
|
||||
n_files = 0
|
||||
for file in files:
|
||||
if file.name in not_allowed_file_names:
|
||||
ve = forms.ValidationError(
|
||||
ugettext(u'Dateiname nicht erlaubt: %s') % file.name,
|
||||
e = forms.ValidationError(
|
||||
ugettext('Dateiname nicht erlaubt: %s') % file.name,
|
||||
code='filename_not_allowed',
|
||||
)
|
||||
validation_errors.append(ve)
|
||||
validation_errors.append(e)
|
||||
if max_file_size and file.size > max_file_size:
|
||||
ve = forms.ValidationError(
|
||||
ugettext(u'Die Datei ist insgesamt zu groß:'
|
||||
u' %(name)s (> %(max_mib)s MiB)') % {'name': file.name, 'max_mib': max_file_size_mib},
|
||||
e = forms.ValidationError(
|
||||
ugettext('Die Datei ist insgesamt zu groß:'
|
||||
' %(name)s (> %(max_mib)s MiB)') % {'name': file.name, 'max_mib': max_file_size_mib},
|
||||
code='file_to_big',
|
||||
)
|
||||
validation_errors.append(ve)
|
||||
validation_errors.append(e)
|
||||
size_total += file.size
|
||||
n_files += 1
|
||||
|
||||
max_total_size = max_total_size_mib * 1024 * 1024
|
||||
if max_total_size and size_total > max_total_size:
|
||||
ve = forms.ValidationError(
|
||||
ugettext(u'Dein Beitrag ist zu groß (%s MiB)') % max_total_size_mib,
|
||||
e = forms.ValidationError(
|
||||
ugettext('Dein Beitrag ist zu groß (%s MiB)') % max_total_size_mib,
|
||||
code='files_to_big',
|
||||
)
|
||||
validation_errors.append(ve)
|
||||
validation_errors.append(e)
|
||||
|
||||
if max_files and n_files > max_files:
|
||||
ve = forms.ValidationError(
|
||||
ugettext(u'Dein Beitrag enthält mehr als %d Dateien') % max_files,
|
||||
e = forms.ValidationError(
|
||||
ugettext('Dein Beitrag enthält mehr als %d Dateien') % max_files,
|
||||
code='files_to_big',
|
||||
)
|
||||
validation_errors.append(ve)
|
||||
validation_errors.append(e)
|
||||
|
||||
if validation_errors:
|
||||
raise forms.ValidationError(validation_errors)
|
||||
@@ -116,9 +116,9 @@ class UploadForm(forms.Form):
|
||||
val = self.cleaned_data.get('accepted')
|
||||
if not val:
|
||||
raise forms.ValidationError(
|
||||
ugettext(u'Um deinen Beitrag hochladen zu können,'
|
||||
u' musst du den Teilnahmebedingungen zustimmen.'
|
||||
u' Dazu musst du das Kästchen ankreuzen!'),
|
||||
ugettext('Um deinen Beitrag hochladen zu können,'
|
||||
' musst du den Teilnahmebedingungen zustimmen.'
|
||||
' Dazu musst du das Kästchen ankreuzen!'),
|
||||
code='not_accepted',
|
||||
)
|
||||
return val
|
||||
|
||||
@@ -3,10 +3,10 @@ import codecs
|
||||
import datetime
|
||||
import logging
|
||||
import os
|
||||
import pytz
|
||||
import re
|
||||
import urllib
|
||||
import zipfile
|
||||
import pytz
|
||||
from django.apps import apps
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
@@ -90,7 +90,7 @@ class ListView(generic.ListView):
|
||||
permission_group = app_config.settings.download_group
|
||||
if not request.user.groups.filter(name=permission_group).exists():
|
||||
raise PermissionDenied()
|
||||
return super(ListView, self).dispatch(request, *args, **kwargs)
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
||||
class DownloadView(generic.DetailView):
|
||||
@@ -139,7 +139,7 @@ class DownloadView(generic.DetailView):
|
||||
permission_group = app_config.settings.download_group
|
||||
if not request.user.groups.filter(name=permission_group).exists():
|
||||
raise PermissionDenied()
|
||||
return super(DownloadView, self).dispatch(request, *args, **kwargs)
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
||||
class UploadView(generic.edit.FormView):
|
||||
@@ -155,30 +155,30 @@ class UploadView(generic.edit.FormView):
|
||||
form_class = UploadForm
|
||||
success_url = reverse_lazy('dav_submission:success')
|
||||
|
||||
def _sanitize_filename(self, input):
|
||||
def _sanitize_filename(self, filename):
|
||||
max_length = None
|
||||
discard_chars = u''
|
||||
discard_chars = ''
|
||||
replace_chars = {
|
||||
u'ä': u'ae',
|
||||
u'ö': u'oe',
|
||||
u'ü': u'ue',
|
||||
u'ß': u'ss',
|
||||
u'Ä': u'Ae',
|
||||
u'Ö': u'Oe',
|
||||
u'Ü': u'Ue',
|
||||
'ä': 'ae',
|
||||
'ö': 'oe',
|
||||
'ü': 'ue',
|
||||
'ß': 'ss',
|
||||
'Ä': 'Ae',
|
||||
'Ö': 'Oe',
|
||||
'Ü': 'Ue',
|
||||
}
|
||||
allowed_chars = (u'abcdefghijklmnopqrstuvwxyz'
|
||||
u'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
u'0123456789'
|
||||
u'._-')
|
||||
non_allowed_substitute = u'_'
|
||||
space_substitute = u'_'
|
||||
allowed_chars = ('abcdefghijklmnopqrstuvwxyz'
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
'0123456789'
|
||||
'._-')
|
||||
non_allowed_substitute = '_'
|
||||
space_substitute = '_'
|
||||
|
||||
if space_substitute is None:
|
||||
space_substitute = non_allowed_substitute
|
||||
|
||||
r = ''
|
||||
for c in input:
|
||||
for c in filename:
|
||||
if c in discard_chars:
|
||||
continue
|
||||
elif c in replace_chars:
|
||||
@@ -195,14 +195,14 @@ class UploadView(generic.edit.FormView):
|
||||
return r[:max_length]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
c = super(UploadView, self).get_context_data(**kwargs)
|
||||
c = super().get_context_data(**kwargs)
|
||||
c['show_upload_form'] = app_config.settings.enable_upload
|
||||
return c
|
||||
|
||||
def form_valid(self, form):
|
||||
base_path = app_config.settings.upload_path
|
||||
|
||||
subdir_format_str = u'{datetime}--{title}'
|
||||
subdir_format_str = '{datetime}--{title}'
|
||||
now = timezone.now()
|
||||
subdir_format_kwargs = {'datetime': now.strftime('%Y-%m-%d--%H%M%S'),
|
||||
'date': now.strftime('%Y-%m-%d'),
|
||||
@@ -214,7 +214,7 @@ class UploadView(generic.edit.FormView):
|
||||
subdir_path = os.path.join(base_path, subdir_name)
|
||||
|
||||
if os.path.isdir(subdir_path):
|
||||
message = _(u'Es gibt bereits einen Beitrag mit dem Titel "%(title)s".') % subdir_format_kwargs
|
||||
message = _('Es gibt bereits einen Beitrag mit dem Titel "%(title)s".') % subdir_format_kwargs
|
||||
messages.error(self.request, message)
|
||||
form.add_error('title', message)
|
||||
return self.render_to_response(self.get_context_data(form=form))
|
||||
@@ -222,7 +222,7 @@ class UploadView(generic.edit.FormView):
|
||||
os.makedirs(subdir_path)
|
||||
|
||||
try:
|
||||
metadata_format_str = u"""Absender: {name} <{email_address}>
|
||||
metadata_format_str = """Absender: {name} <{email_address}>
|
||||
Gruppe: {group}
|
||||
Datum: {date} {time}
|
||||
Titel: {title}
|
||||
@@ -246,10 +246,10 @@ Beschreibung:
|
||||
with codecs.open(metadata_file_path, 'w', encoding='utf-8') as metadata_file:
|
||||
metadata_file.write(metadata)
|
||||
except Exception as e:
|
||||
message = _(u'Jetzt ist irgendwas schief gelaufen.')
|
||||
message = _('Jetzt ist irgendwas schief gelaufen.')
|
||||
messages.error(self.request, message)
|
||||
logger.error('dav_submission.views.UploadView.form_valid(): Catched Exception #2: %s', str(e))
|
||||
return super(UploadView, self).form_valid(form)
|
||||
return super().form_valid(form)
|
||||
|
||||
try:
|
||||
for input_file in form.files.getlist('files'):
|
||||
@@ -257,7 +257,7 @@ Beschreibung:
|
||||
file_path = os.path.join(subdir_path, file_name)
|
||||
|
||||
if os.path.exists(file_path):
|
||||
message = _(u'Die Datei %(name)s haben wir bereits.') % {'name': input_file.name}
|
||||
message = _('Die Datei %(name)s haben wir bereits.') % {'name': input_file.name}
|
||||
messages.error(self.request, message)
|
||||
continue
|
||||
|
||||
@@ -267,28 +267,28 @@ Beschreibung:
|
||||
|
||||
size = os.path.getsize(file_path)
|
||||
if size > (1024 * 1024):
|
||||
size_str = u'%s MiB' % ('%.3f' % (size / 1024.0 / 1024.0)).rstrip('0').rstrip('.')
|
||||
size_str = '%s MiB' % ('%.3f' % (size / 1024.0 / 1024.0)).rstrip('0').rstrip('.')
|
||||
elif size > 1024:
|
||||
size_str = u'%s KiB' % ('%.3f' % (size / 1024.0)).rstrip('0').rstrip('.')
|
||||
size_str = '%s KiB' % ('%.3f' % (size / 1024.0)).rstrip('0').rstrip('.')
|
||||
else:
|
||||
size_str = u'%d Byte' % size
|
||||
message = _(u'Datei erfolgreich hochgeladen: %(name)s (%(size)s)') % {'name': input_file.name,
|
||||
'size': size_str}
|
||||
size_str = '%d Byte' % size
|
||||
message = _('Datei erfolgreich hochgeladen: %(name)s (%(size)s)') % {'name': input_file.name,
|
||||
'size': size_str}
|
||||
messages.success(self.request, message)
|
||||
except Exception as e:
|
||||
message = _(u'Jetzt ist irgendwas schief gelaufen.')
|
||||
message = _('Jetzt ist irgendwas schief gelaufen.')
|
||||
messages.error(self.request, message)
|
||||
logger.error('dav_submission.views.UploadView.form_valid(): Catched Exception #3: %s', str(e))
|
||||
return super(UploadView, self).form_valid(form)
|
||||
return super().form_valid(form)
|
||||
|
||||
mail = NewSubmissionMail(metadata_format_kwargs)
|
||||
mail.send()
|
||||
return super(UploadView, self).form_valid(form)
|
||||
return super().form_valid(form)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
if not app_config.settings.enable_upload:
|
||||
raise PermissionDenied(_(u'Der Upload ist noch nicht freigeschaltet.'))
|
||||
return super(UploadView, self).post(request, *args, **kwargs)
|
||||
raise PermissionDenied(_('Der Upload ist noch nicht freigeschaltet.'))
|
||||
return super().post(request, *args, **kwargs)
|
||||
|
||||
|
||||
class SuccessView(generic.TemplateView):
|
||||
|
||||
4
tests/settings.py
Normal file
4
tests/settings.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from pathlib import Path
|
||||
BASE_DIR = Path(__file__).resolve().parent
|
||||
|
||||
SECRET_KEY = 'fake-key'
|
||||
@@ -1,19 +1,19 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
import datetime
|
||||
import django
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import django
|
||||
from django.test.utils import get_runner
|
||||
|
||||
#from dav_base.console_scripts.admin import DJANGO_MAIN_MODULE
|
||||
DJANGO_MAIN_MODULE = 'main'
|
||||
from dav_base.tests.utils import mkdtemp
|
||||
|
||||
# from dav_base.console_scripts.admin import DJANGO_MAIN_MODULE
|
||||
DJANGO_MAIN_MODULE = 'main'
|
||||
|
||||
class DjangoEnvironment(object):
|
||||
|
||||
class DjangoEnvironment:
|
||||
@staticmethod
|
||||
def _install_djangoproject(path, modules=None):
|
||||
cmd = 'django-dav-admin setup "{}"'.format(path)
|
||||
@@ -35,6 +35,8 @@ class DjangoEnvironment(object):
|
||||
else:
|
||||
self._enable_modules = []
|
||||
|
||||
self.settings = None
|
||||
|
||||
def __enter__(self):
|
||||
if self.path is None:
|
||||
prefix = 'testrun-{datetime}-'.format(
|
||||
@@ -51,7 +53,7 @@ class DjangoEnvironment(object):
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = '{}.settings'.format(DJANGO_MAIN_MODULE)
|
||||
django.setup()
|
||||
|
||||
from django.conf import settings
|
||||
from django.conf import settings # pylint: disable=import-outside-toplevel
|
||||
self.settings = settings
|
||||
|
||||
return self
|
||||
@@ -64,7 +66,7 @@ class DjangoEnvironment(object):
|
||||
shutil.rmtree(self.path)
|
||||
|
||||
|
||||
class TestSuite(object):
|
||||
class TestSuite:
|
||||
@staticmethod
|
||||
def run():
|
||||
modules = ['dav_auth', 'dav_events', 'dav_registration', 'dav_event_office']
|
||||
|
||||
Reference in New Issue
Block a user