feat: expose User password for editing in master views
This commit is contained in:
parent
230e2fd1ab
commit
330ee324ba
|
@ -674,6 +674,13 @@ class Form:
|
|||
schema = SQLAlchemySchemaNode(self.model_class,
|
||||
includes=includes)
|
||||
|
||||
# fill in the blanks if anything got missed
|
||||
for key in fields:
|
||||
if key not in schema:
|
||||
log.warning("key '%s' not in schema", key)
|
||||
node = colander.SchemaNode(colander.String(), name=key)
|
||||
schema.add(node)
|
||||
|
||||
else:
|
||||
|
||||
# make basic schema
|
||||
|
|
|
@ -31,12 +31,15 @@ in the namespace:
|
|||
* :class:`deform:deform.widget.Widget` (base class)
|
||||
* :class:`deform:deform.widget.TextInputWidget`
|
||||
* :class:`deform:deform.widget.TextAreaWidget`
|
||||
* :class:`deform:deform.widget.PasswordWidget`
|
||||
* :class:`deform:deform.widget.CheckedPasswordWidget`
|
||||
* :class:`deform:deform.widget.SelectWidget`
|
||||
* :class:`deform:deform.widget.CheckboxChoiceWidget`
|
||||
"""
|
||||
|
||||
import colander
|
||||
from deform.widget import (Widget, TextInputWidget, TextAreaWidget,
|
||||
PasswordWidget, CheckedPasswordWidget,
|
||||
SelectWidget, CheckboxChoiceWidget)
|
||||
from webhelpers2.html import HTML
|
||||
|
||||
|
|
|
@ -25,11 +25,11 @@ Auth Views
|
|||
"""
|
||||
|
||||
import colander
|
||||
from deform.widget import TextInputWidget, PasswordWidget, CheckedPasswordWidget
|
||||
|
||||
from wuttaweb.views import View
|
||||
from wuttaweb.db import Session
|
||||
from wuttaweb.auth import login_user, logout_user
|
||||
from wuttaweb.forms import widgets
|
||||
|
||||
|
||||
class AuthView(View):
|
||||
|
@ -97,14 +97,14 @@ class AuthView(View):
|
|||
schema.add(colander.SchemaNode(
|
||||
colander.String(),
|
||||
name='username',
|
||||
widget=TextInputWidget(attributes={
|
||||
widget=widgets.TextInputWidget(attributes={
|
||||
'ref': 'username',
|
||||
})))
|
||||
|
||||
schema.add(colander.SchemaNode(
|
||||
colander.String(),
|
||||
name='password',
|
||||
widget=PasswordWidget(attributes={
|
||||
widget=widgets.PasswordWidget(attributes={
|
||||
'ref': 'password',
|
||||
})))
|
||||
|
||||
|
@ -174,13 +174,13 @@ class AuthView(View):
|
|||
schema.add(colander.SchemaNode(
|
||||
colander.String(),
|
||||
name='current_password',
|
||||
widget=PasswordWidget(),
|
||||
widget=widgets.PasswordWidget(),
|
||||
validator=self.change_password_validate_current_password))
|
||||
|
||||
schema.add(colander.SchemaNode(
|
||||
colander.String(),
|
||||
name='new_password',
|
||||
widget=CheckedPasswordWidget(),
|
||||
widget=widgets.CheckedPasswordWidget(),
|
||||
validator=self.change_password_validate_new_password))
|
||||
|
||||
return schema
|
||||
|
|
|
@ -28,6 +28,7 @@ import colander
|
|||
|
||||
from wuttjamaican.db.model import User
|
||||
from wuttaweb.views import MasterView
|
||||
from wuttaweb.forms import widgets
|
||||
from wuttaweb.forms.schema import PersonRef, RoleRefs
|
||||
from wuttaweb.db import Session
|
||||
|
||||
|
@ -93,9 +94,15 @@ class UserView(MasterView):
|
|||
f.set_validator('username', self.unique_username)
|
||||
|
||||
# password
|
||||
# if not (self.creating or self.editing):
|
||||
# f.remove('password')
|
||||
# nb. we must avoid 'password' as field name since
|
||||
# ColanderAlchemy wants to handle the raw/hashed value
|
||||
f.remove('password')
|
||||
# nb. no need for password field if readonly
|
||||
if self.creating or self.editing:
|
||||
# nb. use 'set_password' as field name
|
||||
f.append('set_password')
|
||||
f.set_required('set_password', False)
|
||||
f.set_widget('set_password', widgets.CheckedPasswordWidget())
|
||||
|
||||
# roles
|
||||
f.append('roles')
|
||||
|
@ -121,9 +128,16 @@ class UserView(MasterView):
|
|||
|
||||
def objectify(self, form, session=None):
|
||||
""" """
|
||||
data = form.validated
|
||||
|
||||
# normal logic first
|
||||
user = super().objectify(form)
|
||||
|
||||
# maybe set user password
|
||||
if 'set_password' in form and data.get('set_password'):
|
||||
auth = self.app.get_auth_handler()
|
||||
auth.set_user_password(user, data['set_password'])
|
||||
|
||||
# update roles for user
|
||||
# TODO
|
||||
# if self.has_perm('edit_roles'):
|
||||
|
|
|
@ -218,6 +218,18 @@ class TestForm(TestCase):
|
|||
self.assertIn('name', schema)
|
||||
self.assertIn('value', schema)
|
||||
|
||||
# ColanderAlchemy schema still has *all* requested fields
|
||||
form = self.make_form(model_instance=model.Setting(name='uhoh'),
|
||||
fields=['name', 'value', 'foo', 'bar'])
|
||||
self.assertEqual(form.fields, ['name', 'value', 'foo', 'bar'])
|
||||
self.assertIsNone(form.schema)
|
||||
schema = form.get_schema()
|
||||
self.assertEqual(len(schema.children), 4)
|
||||
self.assertIn('name', schema)
|
||||
self.assertIn('value', schema)
|
||||
self.assertIn('foo', schema)
|
||||
self.assertIn('bar', schema)
|
||||
|
||||
# schema nodes are required by default
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
schema = form.get_schema()
|
||||
|
|
|
@ -15,6 +15,9 @@ class TestUserView(WebTestCase):
|
|||
def make_view(self):
|
||||
return mod.UserView(self.request)
|
||||
|
||||
def test_includeme(self):
|
||||
self.pyramid_config.include('wuttaweb.views.users')
|
||||
|
||||
def test_get_query(self):
|
||||
view = self.make_view()
|
||||
query = view.get_query(session=self.session)
|
||||
|
@ -76,11 +79,13 @@ class TestUserView(WebTestCase):
|
|||
|
||||
def test_objectify(self):
|
||||
model = self.app.model
|
||||
auth = self.app.get_auth_handler()
|
||||
blokes = model.Role(name="Blokes")
|
||||
self.session.add(blokes)
|
||||
others = model.Role(name="Others")
|
||||
self.session.add(others)
|
||||
barney = model.User(username='barney')
|
||||
auth.set_user_password(barney, 'testpass')
|
||||
barney.roles.append(blokes)
|
||||
self.session.add(barney)
|
||||
self.session.commit()
|
||||
|
@ -93,6 +98,14 @@ class TestUserView(WebTestCase):
|
|||
self.assertEqual(len(barney.roles), 1)
|
||||
self.assertEqual(barney.roles[0].name, "Blokes")
|
||||
|
||||
# form can update user password
|
||||
self.assertTrue(auth.check_user_password(barney, 'testpass'))
|
||||
form = view.make_model_form(model_instance=barney)
|
||||
form.validated = {'username': 'barney', 'set_password': 'testpass2'}
|
||||
user = view.objectify(form, session=self.session)
|
||||
self.assertIs(user, barney)
|
||||
self.assertTrue(auth.check_user_password(barney, 'testpass2'))
|
||||
|
||||
# form can update user roles
|
||||
form = view.make_model_form(model_instance=barney)
|
||||
form.validated = {'username': 'barney', 'roles': {others.uuid}}
|
||||
|
|
Loading…
Reference in a new issue