Merge branch '18-password-expiry' into 'master'

Resolve "Password Expiry"

Closes #18

See merge request BeryJu.org/passbook!2
This commit is contained in:
Jens Langhammer 2019-03-03 16:53:31 +00:00
commit e86cae6cac
10 changed files with 119 additions and 1 deletions

View File

@ -37,6 +37,10 @@ values =
[bumpversion:file:passbook/lib/__init__.py] [bumpversion:file:passbook/lib/__init__.py]
[bumpversion:file:passbook/hibp_policy/__init__.py]
[bumpversion:file:passbook/password_expiry_policy/__init__.py]
[bumpversion:file:passbook/saml_idp/__init__.py] [bumpversion:file:passbook/saml_idp/__init__.py]
[bumpversion:file:passbook/audit/__init__.py] [bumpversion:file:passbook/audit/__init__.py]

View File

@ -75,6 +75,7 @@ INSTALLED_APPS = [
'passbook.captcha_factor.apps.PassbookCaptchaFactorConfig', 'passbook.captcha_factor.apps.PassbookCaptchaFactorConfig',
'passbook.hibp_policy.apps.PassbookHIBPConfig', 'passbook.hibp_policy.apps.PassbookHIBPConfig',
'passbook.pretend.apps.PassbookPretendConfig', 'passbook.pretend.apps.PassbookPretendConfig',
'passbook.password_expiry_policy.apps.PassbookPasswordExpiryPolicyConfig',
] ]
# Message Tag fix for bootstrap CSS Classes # Message Tag fix for bootstrap CSS Classes

View File

@ -1,2 +1,2 @@
"""passbook hibp_policy""" """passbook hibp_policy"""
__version__ = '0.0.7-alpha' __version__ = '0.1.1-beta'

View File

@ -0,0 +1,2 @@
"""passbook password_expiry"""
__version__ = '0.1.1-beta'

View File

@ -0,0 +1,5 @@
"""Passbook password_expiry_policy Admin"""
from passbook.lib.admin import admin_autoregister
admin_autoregister('passbook_password_expiry_policy')

View File

@ -0,0 +1,11 @@
"""Passbook password_expiry_policy app config"""
from django.apps import AppConfig
class PassbookPasswordExpiryPolicyConfig(AppConfig):
"""Passbook password_expiry_policy app config"""
name = 'passbook.password_expiry_policy'
label = 'passbook_password_expiry_policy'
verbose_name = 'passbook Password Expiry Policy'

View File

@ -0,0 +1,24 @@
"""passbook PasswordExpiry Policy forms"""
from django import forms
from django.utils.translation import gettext as _
from passbook.core.forms.policies import GENERAL_FIELDS
from passbook.password_expiry_policy.models import PasswordExpiryPolicy
class PasswordExpiryPolicyForm(forms.ModelForm):
"""Edit PasswordExpiryPolicy instances"""
class Meta:
model = PasswordExpiryPolicy
fields = GENERAL_FIELDS + ['days', 'deny_only']
widgets = {
'name': forms.TextInput(),
'order': forms.NumberInput(),
'days': forms.NumberInput(),
}
labels = {
'deny_only': _("Only fail the policy, don't set user's password.")
}

View File

@ -0,0 +1,29 @@
# Generated by Django 2.1.7 on 2019-03-03 13:46
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('passbook_core', '0016_auto_20190227_1355'),
]
operations = [
migrations.CreateModel(
name='PasswordExpiryPolicy',
fields=[
('policy_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Policy')),
('deny_only', models.BooleanField(default=False)),
('days', models.IntegerField()),
],
options={
'verbose_name': 'Password Expiry Policy',
'verbose_name_plural': 'Password Expiry Policies',
},
bases=('passbook_core.policy',),
),
]

View File

@ -0,0 +1,42 @@
"""passbook password_expiry_policy Models"""
from datetime import timedelta
from logging import getLogger
from django.db import models
from django.utils.timezone import now
from django.utils.translation import gettext as _
from passbook.core.models import Policy, User
LOGGER = getLogger(__name__)
class PasswordExpiryPolicy(Policy):
"""If password change date is more than x days in the past, call set_unusable_password
and show a notice"""
deny_only = models.BooleanField(default=False)
days = models.IntegerField()
form = 'passbook.password_expiry_policy.forms.PasswordExpiryPolicyForm'
def passes(self, user: User) -> bool:
"""If password change date is more than x days in the past, call set_unusable_password
and show a notice"""
actual_days = (now() - user.password_change_date).days
days_since_expiry = now() - (user.password_change_date + timedelta(days=self.days)).days
if actual_days >= self.days:
if not self.deny_only:
user.set_unusable_password()
user.save()
return False, _(('Password expired %(days)d days ago. '
'Please update your password.') % {
'days': days_since_expiry
})
return False, _('Password has expired.')
return True
class Meta:
verbose_name = _('Password Expiry Policy')
verbose_name_plural = _('Password Expiry Policies')