3
0
Fork 0

feat: expose Role permissions for editing

This commit is contained in:
Lance Edgar 2024-08-14 15:10:54 -05:00
parent 97e914c2e0
commit 230e2fd1ab
19 changed files with 736 additions and 34 deletions

View file

@ -1,14 +1,10 @@
# -*- coding: utf-8; -*-
from unittest import TestCase
from pyramid import testing
from tests.util import WebTestCase
class TestIncludeMe(TestCase):
class TestIncludeMe(WebTestCase):
def test_basic(self):
with testing.testConfig() as pyramid_config:
# just ensure no error happens when included..
pyramid_config.include('wuttaweb.views')
# just ensure no error happens when included..
self.pyramid_config.include('wuttaweb.views')

View file

@ -162,6 +162,24 @@ class TestMasterView(WebTestCase):
model_class=MyModel):
self.assertEqual(master.MasterView.get_route_prefix(), 'trucks')
def test_get_permission_prefix(self):
# error by default (since no model class)
self.assertRaises(AttributeError, master.MasterView.get_permission_prefix)
# subclass may specify permission prefix
with patch.object(master.MasterView, 'permission_prefix', new='widgets', create=True):
self.assertEqual(master.MasterView.get_permission_prefix(), 'widgets')
# subclass may specify route prefix
with patch.object(master.MasterView, 'route_prefix', new='widgets', create=True):
self.assertEqual(master.MasterView.get_permission_prefix(), 'widgets')
# or it may specify model class
Truck = MagicMock(__name__='Truck')
with patch.object(master.MasterView, 'model_class', new=Truck, create=True):
self.assertEqual(master.MasterView.get_permission_prefix(), 'trucks')
def test_get_url_prefix(self):
# error by default (since no model class)
@ -315,6 +333,9 @@ class TestMasterView(WebTestCase):
##############################
def test_render_to_response(self):
self.pyramid_config.include('wuttaweb.views.common')
self.pyramid_config.include('wuttaweb.views.auth')
self.pyramid_config.add_route('appinfo', '/appinfo/')
def widgets(request): return {}
self.pyramid_config.add_route('widgets', '/widgets/')
@ -539,28 +560,38 @@ class TestMasterView(WebTestCase):
##############################
def test_index(self):
self.pyramid_config.include('wuttaweb.views.common')
self.pyramid_config.include('wuttaweb.views.auth')
self.pyramid_config.add_route('settings.create', '/settings/new')
self.pyramid_config.add_route('settings.view', '/settings/{name}')
self.pyramid_config.add_route('settings.edit', '/settings/{name}/edit')
self.pyramid_config.add_route('settings.delete', '/settings/{name}/delete')
# sanity/coverage check using /settings/
master.MasterView.model_name = 'Setting'
master.MasterView.model_key = 'name'
master.MasterView.grid_columns = ['name', 'value']
view = master.MasterView(self.request)
response = view.index()
# then again with data, to include view action url
data = [{'name': 'foo', 'value': 'bar'}]
with patch.object(view, 'get_grid_data', return_value=data):
with patch.multiple(master.MasterView, create=True,
model_name='Setting',
model_key='name',
get_index_url=MagicMock(return_value='/settings/'),
grid_columns=['name', 'value']):
view = master.MasterView(self.request)
response = view.index()
del master.MasterView.model_name
del master.MasterView.model_key
del master.MasterView.grid_columns
# then again with data, to include view action url
data = [{'name': 'foo', 'value': 'bar'}]
with patch.object(view, 'get_grid_data', return_value=data):
response = view.index()
def test_create(self):
self.pyramid_config.include('wuttaweb.views.common')
self.pyramid_config.include('wuttaweb.views.auth')
self.pyramid_config.add_route('settings.view', '/settings/{name}')
model = self.app.model
# sanity/coverage check using /settings/new
with patch.multiple(master.MasterView, create=True,
model_name='Setting',
model_key='name',
get_index_url=MagicMock(return_value='/settings/'),
form_fields=['name', 'value']):
view = master.MasterView(self.request)
@ -604,6 +635,11 @@ class TestMasterView(WebTestCase):
self.assertEqual(self.app.get_setting(self.session, 'foo.bar'), 'fraggle')
def test_view(self):
self.pyramid_config.include('wuttaweb.views.common')
self.pyramid_config.include('wuttaweb.views.auth')
self.pyramid_config.add_route('settings.create', '/settings/new')
self.pyramid_config.add_route('settings.edit', '/settings/{name}/edit')
self.pyramid_config.add_route('settings.delete', '/settings/{name}/delete')
# sanity/coverage check using /settings/XXX
setting = {'name': 'foo.bar', 'value': 'baz'}
@ -611,6 +647,7 @@ class TestMasterView(WebTestCase):
with patch.multiple(master.MasterView, create=True,
model_name='Setting',
model_key='name',
get_index_url=MagicMock(return_value='/settings/'),
grid_columns=['name', 'value'],
form_fields=['name', 'value']):
view = master.MasterView(self.request)
@ -618,6 +655,11 @@ class TestMasterView(WebTestCase):
response = view.view()
def test_edit(self):
self.pyramid_config.include('wuttaweb.views.common')
self.pyramid_config.include('wuttaweb.views.auth')
self.pyramid_config.add_route('settings.create', '/settings/new')
self.pyramid_config.add_route('settings.view', '/settings/{name}')
self.pyramid_config.add_route('settings.delete', '/settings/{name}/delete')
model = self.app.model
self.app.save_setting(self.session, 'foo.bar', 'frazzle')
self.session.commit()
@ -634,6 +676,7 @@ class TestMasterView(WebTestCase):
with patch.multiple(master.MasterView, create=True,
model_name='Setting',
model_key='name',
get_index_url=MagicMock(return_value='/settings/'),
form_fields=['name', 'value']):
view = master.MasterView(self.request)
with patch.object(view, 'get_instance', new=get_instance):
@ -675,6 +718,11 @@ class TestMasterView(WebTestCase):
self.assertEqual(self.app.get_setting(self.session, 'foo.bar'), 'froogle')
def test_delete(self):
self.pyramid_config.include('wuttaweb.views.common')
self.pyramid_config.include('wuttaweb.views.auth')
self.pyramid_config.add_route('settings.create', '/settings/new')
self.pyramid_config.add_route('settings.view', '/settings/{name}')
self.pyramid_config.add_route('settings.edit', '/settings/{name}/edit')
model = self.app.model
self.app.save_setting(self.session, 'foo.bar', 'frazzle')
self.session.commit()
@ -692,6 +740,7 @@ class TestMasterView(WebTestCase):
with patch.multiple(master.MasterView, create=True,
model_name='Setting',
model_key='name',
get_index_url=MagicMock(return_value='/settings/'),
form_fields=['name', 'value']):
view = master.MasterView(self.request)
with patch.object(view, 'get_instance', new=get_instance):
@ -730,6 +779,8 @@ class TestMasterView(WebTestCase):
self.assertEqual(self.session.query(model.Setting).count(), 0)
def test_configure(self):
self.pyramid_config.include('wuttaweb.views.common')
self.pyramid_config.include('wuttaweb.views.auth')
model = self.app.model
# mock settings
@ -750,6 +801,7 @@ class TestMasterView(WebTestCase):
route_prefix='appinfo',
template_prefix='/appinfo',
creatable=False,
get_index_url=MagicMock(return_value='/appinfo/'),
configure_get_simple_settings=MagicMock(return_value=settings)):
# get the form page

View file

@ -15,6 +15,9 @@ class TestRoleView(WebTestCase):
def make_view(self):
return mod.RoleView(self.request)
def test_includeme(self):
self.pyramid_config.include('wuttaweb.views.roles')
def test_get_query(self):
view = self.make_view()
query = view.get_query(session=self.session)
@ -30,8 +33,9 @@ class TestRoleView(WebTestCase):
def test_configure_form(self):
model = self.app.model
role = model.Role(name="Foo")
view = self.make_view()
form = view.make_form(model_class=model.Person)
form = view.make_form(model_instance=role)
self.assertNotIn('name', form.validators)
view.configure_form(form)
self.assertIsNotNone(form.validators['name'])
@ -55,3 +59,132 @@ class TestRoleView(WebTestCase):
self.request.matchdict = {'uuid': role.uuid}
node = colander.SchemaNode(colander.String(), name='name')
self.assertIsNone(view.unique_name(node, 'Foo'))
def get_permissions(self):
return {
'widgets': {
'label': "Widgets",
'perms': {
'widgets.list': {
'label': "List widgets",
},
'widgets.polish': {
'label': "Polish the widgets",
},
'widgets.view': {
'label': "View widget",
},
},
},
}
def test_get_available_permissions(self):
model = self.app.model
auth = self.app.get_auth_handler()
blokes = model.Role(name="Blokes")
auth.grant_permission(blokes, 'widgets.list')
self.session.add(blokes)
barney = model.User(username='barney')
barney.roles.append(blokes)
self.session.add(barney)
self.session.commit()
view = self.make_view()
all_perms = self.get_permissions()
self.request.registry.settings['wutta_permissions'] = all_perms
def has_perm(perm):
if perm == 'widgets.list':
return True
return False
with patch.object(self.request, 'has_perm', new=has_perm, create=True):
# sanity check; current request has 1 perm
self.assertTrue(self.request.has_perm('widgets.list'))
self.assertFalse(self.request.has_perm('widgets.polish'))
self.assertFalse(self.request.has_perm('widgets.view'))
# when editing, user sees only the 1 perm
with patch.object(view, 'editing', new=True):
perms = view.get_available_permissions()
self.assertEqual(list(perms), ['widgets'])
self.assertEqual(list(perms['widgets']['perms']), ['widgets.list'])
# but when viewing, same user sees all perms
with patch.object(view, 'viewing', new=True):
perms = view.get_available_permissions()
self.assertEqual(list(perms), ['widgets'])
self.assertEqual(list(perms['widgets']['perms']),
['widgets.list', 'widgets.polish', 'widgets.view'])
# also, when admin user is editing, sees all perms
self.request.is_admin = True
with patch.object(view, 'editing', new=True):
perms = view.get_available_permissions()
self.assertEqual(list(perms), ['widgets'])
self.assertEqual(list(perms['widgets']['perms']),
['widgets.list', 'widgets.polish', 'widgets.view'])
def test_objectify(self):
model = self.app.model
auth = self.app.get_auth_handler()
blokes = model.Role(name="Blokes")
self.session.add(blokes)
barney = model.User(username='barney')
barney.roles.append(blokes)
self.session.add(barney)
self.session.commit()
view = self.make_view()
permissions = self.get_permissions()
# sanity check, role has just 1 perm
auth.grant_permission(blokes, 'widgets.list')
self.session.commit()
self.assertEqual(blokes.permissions, ['widgets.list'])
# form can update role perms
view.editing = True
self.request.matchdict = {'uuid': blokes.uuid}
with patch.object(view, 'get_available_permissions', return_value=permissions):
form = view.make_model_form(model_instance=blokes)
form.validated = {'name': 'Blokes',
'permissions': {'widgets.list', 'widgets.polish', 'widgets.view'}}
role = view.objectify(form)
self.session.commit()
self.assertIs(role, blokes)
self.assertEqual(blokes.permissions, ['widgets.list', 'widgets.polish', 'widgets.view'])
def test_update_permissions(self):
model = self.app.model
auth = self.app.get_auth_handler()
blokes = model.Role(name="Blokes")
auth.grant_permission(blokes, 'widgets.list')
self.session.add(blokes)
barney = model.User(username='barney')
barney.roles.append(blokes)
self.session.add(barney)
self.session.commit()
view = self.make_view()
permissions = self.get_permissions()
with patch.object(view, 'get_available_permissions', return_value=permissions):
# no error if data is missing perms
form = view.make_model_form(model_instance=blokes)
form.validated = {'name': 'BloX'}
role = view.objectify(form)
self.session.commit()
self.assertIs(role, blokes)
self.assertEqual(blokes.name, 'BloX')
# sanity check, role has just 1 perm
self.assertEqual(blokes.permissions, ['widgets.list'])
# role perms are updated
form = view.make_model_form(model_instance=blokes)
form.validated = {'name': 'Blokes',
'permissions': {'widgets.polish', 'widgets.view'}}
role = view.objectify(form)
self.session.commit()
self.assertIs(role, blokes)
self.assertEqual(blokes.permissions, ['widgets.polish', 'widgets.view'])

View file

@ -10,6 +10,10 @@ from tests.util import WebTestCase
class TestAppInfoView(WebTestCase):
def setUp(self):
self.setup_web()
self.pyramid_config.include('wuttaweb.views.essential')
def make_view(self):
return settings.AppInfoView(self.request)