0002-a2_rbac-fix-inconsistencies-in-OUs-user-password-res.patch
src/authentic2/a2_rbac/migrations/0025_auto_20210622_1132.py | ||
---|---|---|
1 |
# Generated by Django 2.2.19 on 2021-06-22 09:32 |
|
2 | ||
3 |
from django.db import migrations, models |
|
4 | ||
5 | ||
6 |
class Migration(migrations.Migration): |
|
7 | ||
8 |
dependencies = [ |
|
9 |
('a2_rbac', '0024_fix_self_admin_perm'), |
|
10 |
] |
|
11 | ||
12 |
operations = [ |
|
13 |
migrations.AlterField( |
|
14 |
model_name='organizationalunit', |
|
15 |
name='user_can_reset_password', |
|
16 |
field=models.NullBooleanField( |
|
17 |
choices=[(None, 'System default'), (True, 'Yes'), (False, 'No')], |
|
18 |
verbose_name='Users can reset password', |
|
19 |
), |
|
20 |
), |
|
21 |
] |
src/authentic2/a2_rbac/models.py | ||
---|---|---|
56 | 56 |
(MANUAL_PASSWORD_POLICY, _('Manual password definition')), |
57 | 57 |
) |
58 | 58 | |
59 |
USER_CAN_RESET_PASSWD_CHOICES = ( |
|
60 |
(None, _("System default")), |
|
61 |
(True, _("Yes")), |
|
62 |
(False, _("No")), |
|
63 |
) |
|
64 | ||
59 | 65 |
PolicyValue = namedtuple( |
60 | 66 |
'PolicyValue', |
61 | 67 |
['generate_password', 'reset_password_at_next_login', 'send_mail', 'send_password_reset'], |
... | ... | |
78 | 84 |
rbac_utils.get_permission_model_name(), content_type_field='target_ct', object_id_field='target_id' |
79 | 85 |
) |
80 | 86 | |
81 |
user_can_reset_password = models.NullBooleanField(verbose_name=_('Users can reset password')) |
|
87 |
user_can_reset_password = models.NullBooleanField( |
|
88 |
verbose_name=_('Users can reset password'), choices=USER_CAN_RESET_PASSWD_CHOICES |
|
89 |
) |
|
82 | 90 | |
83 | 91 |
user_add_password_policy = models.IntegerField( |
84 | 92 |
verbose_name=_('User creation password policy'), choices=USER_ADD_PASSWD_POLICY_CHOICES, default=0 |
src/authentic2/views.py | ||
---|---|---|
794 | 794 |
can_reset_password = utils.get_user_flag( |
795 | 795 |
user=self.user, name='can_reset_password', default=self.user.has_usable_password() |
796 | 796 |
) |
797 |
if not can_reset_password: |
|
797 |
if ( |
|
798 |
can_reset_password is False |
|
799 |
or can_reset_password is None |
|
800 |
and not app_settings.A2_USER_CAN_RESET_PASSWORD |
|
801 |
): |
|
798 | 802 |
messages.warning( |
799 | 803 |
request, _('It\'s not possible to reset your password. Please contact an administrator.') |
800 | 804 |
) |
tests/test_password_reset.py | ||
---|---|---|
13 | 13 |
# |
14 | 14 |
# You should have received a copy of the GNU Affero General Public License |
15 | 15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 |
import re |
|
17 | ||
16 | 18 |
import pytest |
17 | 19 |
from django.test.utils import override_settings |
18 | 20 |
from django.urls import reverse |
... | ... | |
207 | 209 |
response = response.follow() |
208 | 210 |
assert len(mailoutbox) == 0 |
209 | 211 |
assert 'Your password reset request has been refused' in response |
212 | ||
213 | ||
214 |
def test_ou_policies(app, db, settings, user_ou1, ou1, user_ou2, ou2, mailoutbox): |
|
215 | ||
216 |
settings.A2_USER_CAN_RESET_PASSWORD = True |
|
217 | ||
218 |
user_ou1.email = 'john.doe.ou1@example.net' |
|
219 |
user_ou1.save() |
|
220 |
ou1.user_can_reset_password = False # impossible |
|
221 |
ou1.save() |
|
222 | ||
223 |
url = reverse('password_reset') |
|
224 |
resp = app.get(url, status=200) |
|
225 |
resp.form.set('email', user_ou1.email) |
|
226 |
resp = resp.form.submit() |
|
227 |
url = utils.get_link_from_mail(mailoutbox[0]) |
|
228 |
relative_url = url.split('testserver')[1] |
|
229 |
resp = app.get(relative_url, status=302) # impossible, redirected to / |
|
230 |
assert resp['Location'] == '/' |
|
231 | ||
232 |
ou2.user_can_reset_password = None # system default |
|
233 |
ou2.save() |
|
234 | ||
235 |
url = reverse('password_reset') |
|
236 |
resp = app.get(url, status=200) |
|
237 |
resp.form.set('email', user_ou2.email) |
|
238 |
resp = resp.form.submit() |
|
239 |
url = utils.get_link_from_mail(mailoutbox[1]) |
|
240 |
relative_url = url.split('testserver')[1] |
|
241 |
resp = app.get(relative_url, status=200) |
|
242 |
assert 'In order to create a secure password' in resp.text |
|
243 | ||
244 |
settings.A2_USER_CAN_RESET_PASSWORD = False |
|
245 | ||
246 |
url = reverse('password_reset') |
|
247 |
resp = app.get(url, status=404) # globally deactivated, page not found |
|
210 |
- |