diff --git a/src/wuttaweb/templates/base.mako b/src/wuttaweb/templates/base.mako index 67adb61..14d0306 100644 --- a/src/wuttaweb/templates/base.mako +++ b/src/wuttaweb/templates/base.mako @@ -661,7 +661,9 @@ ${h.end_form()} % endif - ${h.link_to("Change Password", url('change_password'), class_='navbar-item')} + % if request.is_root or not request.user.prevent_edit: + ${h.link_to("Change Password", url('change_password'), class_='navbar-item')} + % endif ${h.link_to("Logout", url('logout'), class_='navbar-item')} diff --git a/src/wuttaweb/views/auth.py b/src/wuttaweb/views/auth.py index abb52ea..0b4ebc2 100644 --- a/src/wuttaweb/views/auth.py +++ b/src/wuttaweb/views/auth.py @@ -157,6 +157,9 @@ class AuthView(View): if not self.request.user: return self.redirect(self.request.route_url('home')) + if self.request.user.prevent_edit: + raise self.forbidden() + form = self.make_form(schema=self.change_password_make_schema(), show_button_cancel=False, show_button_reset=True) diff --git a/src/wuttaweb/views/essential.py b/src/wuttaweb/views/essential.py index 56c669b..4b87a13 100644 --- a/src/wuttaweb/views/essential.py +++ b/src/wuttaweb/views/essential.py @@ -29,8 +29,8 @@ Most apps should include this module:: That will in turn include the following modules: -* :mod:`wuttaweb.views.auth` * :mod:`wuttaweb.views.common` +* :mod:`wuttaweb.views.auth` * :mod:`wuttaweb.views.settings` * :mod:`wuttaweb.views.progress` * :mod:`wuttaweb.views.people` @@ -43,8 +43,8 @@ That will in turn include the following modules: def defaults(config, **kwargs): mod = lambda spec: kwargs.get(spec, spec) - config.include(mod('wuttaweb.views.auth')) config.include(mod('wuttaweb.views.common')) + config.include(mod('wuttaweb.views.auth')) config.include(mod('wuttaweb.views.settings')) config.include(mod('wuttaweb.views.progress')) config.include(mod('wuttaweb.views.people')) diff --git a/src/wuttaweb/views/users.py b/src/wuttaweb/views/users.py index 5e28a26..f679061 100644 --- a/src/wuttaweb/views/users.py +++ b/src/wuttaweb/views/users.py @@ -95,6 +95,15 @@ class UserView(MasterView): if not user.active: return 'has-background-warning' + def is_editable(self, user): + """ """ + + # only root can edit certain users + if user.prevent_edit and not self.request.is_root: + return False + + return True + def configure_form(self, f): """ """ super().configure_form(f) diff --git a/tests/views/test_auth.py b/tests/views/test_auth.py index 4fd5413..5e7607f 100644 --- a/tests/views/test_auth.py +++ b/tests/views/test_auth.py @@ -80,11 +80,18 @@ class TestAuthView(WebTestCase): redirect = view.change_password() self.assertIsInstance(redirect, HTTPFound) - # now "login" the user, and set initial password - self.request.user = barney + # set initial password auth.set_user_password(barney, 'foo') self.session.commit() + # forbidden if prevent_edit is set for user + self.request.user = barney + barney.prevent_edit = True + self.assertRaises(HTTPForbidden, view.change_password) + + # okay let's test with edit allowed + barney.prevent_edit = False + # view should now return context w/ form context = view.change_password() self.assertIn('form', context) diff --git a/tests/views/test_users.py b/tests/views/test_users.py index 5b09e83..ea49d49 100644 --- a/tests/views/test_users.py +++ b/tests/views/test_users.py @@ -42,6 +42,26 @@ class TestUserView(WebTestCase): user.active = False self.assertEqual(view.grid_row_class(user, data, 1), 'has-background-warning') + def test_is_editable(self): + model = self.app.model + view = self.make_view() + + # active user is editable + user = model.User(username='barney', active=True) + self.assertTrue(view.is_editable(user)) + + # inactive also editable + user = model.User(username='barney', active=False) + self.assertTrue(view.is_editable(user)) + + # but not if prevent_edit flag is set + user = model.User(username='barney', prevent_edit=True) + self.assertFalse(view.is_editable(user)) + + # unless request user is root + self.request.is_root = True + self.assertTrue(view.is_editable(user)) + def test_configure_form(self): model = self.app.model barney = model.User(username='barney')