Show More
@@ -18,11 +18,14 b'' | |||||
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
20 | |||
|
21 | import time | |||
21 | import logging |
|
22 | import logging | |
22 | from pylons import tmpl_context as c |
|
23 | from pylons import tmpl_context as c | |
23 | from pyramid.httpexceptions import HTTPFound |
|
24 | from pyramid.httpexceptions import HTTPFound | |
24 |
|
25 | |||
25 |
from rhodecode.lib |
|
26 | from rhodecode.lib import helpers as h | |
|
27 | from rhodecode.lib.utils2 import StrictAttributeDict, safe_int | |||
|
28 | from rhodecode.model.db import User | |||
26 |
|
29 | |||
27 | log = logging.getLogger(__name__) |
|
30 | log = logging.getLogger(__name__) | |
28 |
|
31 | |||
@@ -43,6 +46,34 b' class BaseAppView(object):' | |||||
43 | self.session = request.session |
|
46 | self.session = request.session | |
44 | self._rhodecode_user = request.user # auth user |
|
47 | self._rhodecode_user = request.user # auth user | |
45 | self._rhodecode_db_user = self._rhodecode_user.get_instance() |
|
48 | self._rhodecode_db_user = self._rhodecode_user.get_instance() | |
|
49 | self._maybe_needs_password_change( | |||
|
50 | request.matched_route.name, self._rhodecode_db_user) | |||
|
51 | ||||
|
52 | def _maybe_needs_password_change(self, view_name, user_obj): | |||
|
53 | log.debug('Checking if user %s needs password change on view %s', | |||
|
54 | user_obj, view_name) | |||
|
55 | skip_user_views = [ | |||
|
56 | 'logout', 'login', | |||
|
57 | 'my_account_password', 'my_account_password_update' | |||
|
58 | ] | |||
|
59 | ||||
|
60 | if not user_obj: | |||
|
61 | return | |||
|
62 | ||||
|
63 | if user_obj.username == User.DEFAULT_USER: | |||
|
64 | return | |||
|
65 | ||||
|
66 | now = time.time() | |||
|
67 | should_change = user_obj.user_data.get('force_password_change') | |||
|
68 | change_after = safe_int(should_change) or 0 | |||
|
69 | if should_change and now > change_after: | |||
|
70 | log.debug('User %s requires password change', user_obj) | |||
|
71 | h.flash('You are required to change your password', 'warning', | |||
|
72 | ignore_duplicate=True) | |||
|
73 | ||||
|
74 | if view_name not in skip_user_views: | |||
|
75 | raise HTTPFound( | |||
|
76 | self.request.route_path('my_account_password')) | |||
46 |
|
77 | |||
47 | def _get_local_tmpl_context(self): |
|
78 | def _get_local_tmpl_context(self): | |
48 | c = TemplateArgs() |
|
79 | c = TemplateArgs() |
@@ -24,6 +24,7 b' import pytest' | |||||
24 |
|
24 | |||
25 | from rhodecode.apps.login.views import LoginView, CaptchaData |
|
25 | from rhodecode.apps.login.views import LoginView, CaptchaData | |
26 | from rhodecode.config.routing import ADMIN_PREFIX |
|
26 | from rhodecode.config.routing import ADMIN_PREFIX | |
|
27 | from rhodecode.lib.utils2 import AttributeDict | |||
27 | from rhodecode.model.settings import SettingsModel |
|
28 | from rhodecode.model.settings import SettingsModel | |
28 | from rhodecode.tests.utils import AssertResponse |
|
29 | from rhodecode.tests.utils import AssertResponse | |
29 |
|
30 | |||
@@ -40,7 +41,7 b' class RhodeCodeSetting(object):' | |||||
40 | model.create_or_update_setting(name=self.name, val=self.value) |
|
41 | model.create_or_update_setting(name=self.name, val=self.value) | |
41 | return self |
|
42 | return self | |
42 |
|
43 | |||
43 |
def __exit__(self, type, val |
|
44 | def __exit__(self, exc_type, exc_val, exc_tb): | |
44 | model = SettingsModel() |
|
45 | model = SettingsModel() | |
45 | if self.old_setting: |
|
46 | if self.old_setting: | |
46 | model.create_or_update_setting( |
|
47 | model.create_or_update_setting( | |
@@ -57,8 +58,12 b' class TestRegisterCaptcha(object):' | |||||
57 | ('privkey', '', CaptchaData(True, 'privkey', '')), |
|
58 | ('privkey', '', CaptchaData(True, 'privkey', '')), | |
58 | ('privkey', 'pubkey', CaptchaData(True, 'privkey', 'pubkey')), |
|
59 | ('privkey', 'pubkey', CaptchaData(True, 'privkey', 'pubkey')), | |
59 | ]) |
|
60 | ]) | |
60 |
def test_get_captcha_data(self, private_key, public_key, expected, db |
|
61 | def test_get_captcha_data(self, private_key, public_key, expected, db, | |
61 | login_view = LoginView(mock.Mock(), mock.Mock()) |
|
62 | request_stub, user_util): | |
|
63 | request_stub.user = user_util.create_user().AuthUser | |||
|
64 | request_stub.matched_route = AttributeDict({'name': 'login'}) | |||
|
65 | login_view = LoginView(mock.Mock(), request_stub) | |||
|
66 | ||||
62 | with RhodeCodeSetting('captcha_private_key', private_key): |
|
67 | with RhodeCodeSetting('captcha_private_key', private_key): | |
63 | with RhodeCodeSetting('captcha_public_key', public_key): |
|
68 | with RhodeCodeSetting('captcha_public_key', public_key): | |
64 | captcha = login_view._get_captcha_data() |
|
69 | captcha = login_view._get_captcha_data() |
@@ -489,21 +489,12 b' class BaseController(WSGIController):' | |||||
489 | _route_name) |
|
489 | _route_name) | |
490 | ) |
|
490 | ) | |
491 |
|
491 | |||
492 | # TODO: Maybe this should be move to pyramid to cover all views. |
|
|||
493 | # check user attributes for password change flag |
|
|||
494 | user_obj = auth_user.get_instance() |
|
492 | user_obj = auth_user.get_instance() | |
495 | if user_obj and user_obj.user_data.get('force_password_change'): |
|
493 | if user_obj and user_obj.user_data.get('force_password_change'): | |
496 | h.flash('You are required to change your password', 'warning', |
|
494 | h.flash('You are required to change your password', 'warning', | |
497 | ignore_duplicate=True) |
|
495 | ignore_duplicate=True) | |
498 |
|
496 | return self._dispatch_redirect( | ||
499 | skip_user_check_urls = [ |
|
497 | url('my_account_password'), environ, start_response) | |
500 | 'error.document', 'login.logout', 'login.index', |
|
|||
501 | 'admin/my_account.my_account_password', |
|
|||
502 | 'admin/my_account.my_account_password_update' |
|
|||
503 | ] |
|
|||
504 | if _route_name not in skip_user_check_urls: |
|
|||
505 | return self._dispatch_redirect( |
|
|||
506 | url('my_account_password'), environ, start_response) |
|
|||
507 |
|
498 | |||
508 | return WSGIController.__call__(self, environ, start_response) |
|
499 | return WSGIController.__call__(self, environ, start_response) | |
509 |
|
500 |
General Comments 0
You need to be logged in to leave comments.
Login now