add password policy
This commit is contained in:
		| @ -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] | ||||||
|  | |||||||
| @ -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 | ||||||
|  | |||||||
| @ -1,2 +1,2 @@ | |||||||
| """passbook hibp_policy""" | """passbook hibp_policy""" | ||||||
| __version__ = '0.0.7-alpha' | __version__ = '0.1.1-beta' | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								passbook/password_expiry_policy/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								passbook/password_expiry_policy/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | """passbook password_expiry""" | ||||||
|  | __version__ = '0.1.1-beta' | ||||||
							
								
								
									
										5
									
								
								passbook/password_expiry_policy/admin.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								passbook/password_expiry_policy/admin.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | """Passbook password_expiry_policy Admin""" | ||||||
|  |  | ||||||
|  | from passbook.lib.admin import admin_autoregister | ||||||
|  |  | ||||||
|  | admin_autoregister('passbook_password_expiry_policy') | ||||||
							
								
								
									
										11
									
								
								passbook/password_expiry_policy/apps.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								passbook/password_expiry_policy/apps.py
									
									
									
									
									
										Normal 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' | ||||||
							
								
								
									
										24
									
								
								passbook/password_expiry_policy/forms.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								passbook/password_expiry_policy/forms.py
									
									
									
									
									
										Normal 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.") | ||||||
|  |         } | ||||||
							
								
								
									
										29
									
								
								passbook/password_expiry_policy/migrations/0001_initial.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								passbook/password_expiry_policy/migrations/0001_initial.py
									
									
									
									
									
										Normal 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',), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
							
								
								
									
										40
									
								
								passbook/password_expiry_policy/models.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								passbook/password_expiry_policy/models.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | |||||||
|  | """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.') | ||||||
|  |  | ||||||
|  |     class Meta: | ||||||
|  |  | ||||||
|  |         verbose_name = _('Password Expiry Policy') | ||||||
|  |         verbose_name_plural = _('Password Expiry Policies') | ||||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer