diff --git a/src/wuttaweb/forms/base.py b/src/wuttaweb/forms/base.py
index ceaeeb7..9dd6760 100644
--- a/src/wuttaweb/forms/base.py
+++ b/src/wuttaweb/forms/base.py
@@ -1002,7 +1002,7 @@ class Form:
# for now we explicitly translate here, ugh. also
# note this does not yet allow for null values.. :(
if isinstance(field.typ, colander.Boolean):
- value = True if field.typ.true_val else False
+ value = True if value == field.typ.true_val else False
model_data[field.oid] = make_json_safe(value)
diff --git a/src/wuttaweb/templates/appinfo/index.mako b/src/wuttaweb/templates/appinfo/index.mako
index 383157f..ab49018 100644
--- a/src/wuttaweb/templates/appinfo/index.mako
+++ b/src/wuttaweb/templates/appinfo/index.mako
@@ -8,10 +8,10 @@
- ${app.get_distribution(obj=app.get_web_handler()) or f'?? - set config for `{app.appname}.app_dist`'}
+ ${app.get_distribution() or f'?? - set config for `{app.appname}.app_dist`'}
- ${app.get_version(obj=app.get_web_handler()) or f'?? - set config for `{app.appname}.app_dist`'}
+ ${app.get_version() or f'?? - set config for `{app.appname}.app_dist`'}
${app.get_title()}
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')