3
0
Fork 0
wuttaweb/tests/views/test_roles.py

463 lines
17 KiB
Python
Raw Normal View History

# -*- coding: utf-8; -*-
from unittest.mock import patch
from sqlalchemy import orm
import colander
from wuttaweb.views import roles as mod
from wuttaweb.grids import Grid
from wuttaweb.forms.schema import RoleRef
from wuttaweb.testing import WebTestCase
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)
self.assertIsInstance(query, orm.Query)
def test_configure_grid(self):
model = self.app.model
view = self.make_view()
grid = view.make_grid(model_class=model.Role)
self.assertFalse(grid.is_linked("name"))
view.configure_grid(grid)
self.assertTrue(grid.is_linked("name"))
def test_is_editable(self):
model = self.app.model
auth = self.app.get_auth_handler()
blokes = model.Role(name="Blokes")
self.session.add(blokes)
self.session.commit()
view = self.make_view()
admin = auth.get_role_administrator(self.session)
authed = auth.get_role_authenticated(self.session)
anon = auth.get_role_anonymous(self.session)
# editable by default
self.assertTrue(view.is_editable(blokes))
# built-in roles not editable by default
self.assertFalse(view.is_editable(admin))
self.assertFalse(view.is_editable(authed))
self.assertFalse(view.is_editable(anon))
# reset
del self.request.user_permissions
barney = model.User(username="barney")
self.session.add(barney)
barney.roles.append(blokes)
auth.grant_permission(blokes, "roles.edit_builtin")
self.session.commit()
# user with perms can edit *some* built-in
self.request.user = barney
self.assertTrue(view.is_editable(authed))
self.assertTrue(view.is_editable(anon))
# nb. not this one yet
self.assertFalse(view.is_editable(admin))
2024-08-14 16:58:08 -05:00
def test_is_deletable(self):
model = self.app.model
auth = self.app.get_auth_handler()
blokes = model.Role(name="Blokes")
self.session.add(blokes)
self.session.commit()
view = self.make_view()
# deletable by default
self.assertTrue(view.is_deletable(blokes))
# built-in roles not deletable
self.assertFalse(view.is_deletable(auth.get_role_administrator(self.session)))
self.assertFalse(view.is_deletable(auth.get_role_authenticated(self.session)))
self.assertFalse(view.is_deletable(auth.get_role_anonymous(self.session)))
def test_configure_form(self):
model = self.app.model
role = model.Role(name="Foo")
view = self.make_view()
form = view.make_form(model_instance=role)
self.assertNotIn("name", form.validators)
view.configure_form(form)
self.assertIsNotNone(form.validators["name"])
def test_make_users_grid(self):
self.pyramid_config.add_route("users.view", "/users/{uuid}/view")
self.pyramid_config.add_route("users.edit", "/users/{uuid}/edit")
model = self.app.model
view = self.make_view()
role = model.Role(name="Manager")
self.session.add(role)
user = model.User(username="freddie")
user.roles.append(role)
self.session.add(user)
self.session.commit()
# basic
grid = view.make_users_grid(role)
self.assertIsInstance(grid, Grid)
self.assertFalse(grid.linked_columns)
self.assertFalse(grid.actions)
# view + edit actions
with patch.object(self.request, "is_root", new=True):
grid = view.make_users_grid(role)
self.assertIsInstance(grid, Grid)
self.assertIn("person", grid.linked_columns)
self.assertIn("username", grid.linked_columns)
self.assertEqual(len(grid.actions), 2)
self.assertEqual(grid.actions[0].key, "view")
self.assertEqual(grid.actions[1].key, "edit")
# render grid to ensure coverage for link urls
grid.render_vue_template()
def test_unique_name(self):
model = self.app.model
view = self.make_view()
role = model.Role(name="Foo")
self.session.add(role)
self.session.commit()
with patch.object(mod, "Session", return_value=self.session):
# invalid if same name in data
node = colander.SchemaNode(colander.String(), name="name")
self.assertRaises(colander.Invalid, view.unique_name, node, "Foo")
# but not if name belongs to current role
view.editing = True
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"])
2026-03-22 11:10:01 -05:00
def test_merge_get_data(self):
model = self.app.model
auth = self.app.get_auth_handler()
role = model.Role(name="whatever")
auth.grant_permission(role, "people.list")
auth.grant_permission(role, "people.view")
auth.grant_permission(role, "people.edit")
self.session.add(role)
user1 = model.User(username="user1")
user1.roles.append(role)
self.session.add(user1)
user2 = model.User(username="user2")
user2.roles.append(role)
self.session.add(user2)
self.session.commit()
self.assertEqual(len(role.permissions), 3)
self.assertEqual(len(role.users), 2)
view = self.make_view()
with patch.object(view, "Session", return_value=self.session):
data = view.merge_get_data(role)
self.assertEqual(
sorted(data["permissions"]),
["people.edit", "people.list", "people.view"],
)
self.assertEqual(data["permission_count"], 3)
self.assertEqual(data["usernames"], ["user1", "user2"])
self.assertEqual(data["user_count"], 2)
def test_merge_get_final_data(self):
model = self.app.model
auth = self.app.get_auth_handler()
role1 = model.Role(name="whatever1")
auth.grant_permission(role1, "people.list")
auth.grant_permission(role1, "people.view")
auth.grant_permission(role1, "people.edit")
self.session.add(role1)
role2 = model.Role(name="whatever2")
auth.grant_permission(role2, "people.list")
auth.grant_permission(role2, "people.view")
self.session.add(role2)
user1 = model.User(username="user1")
user1.roles.append(role1)
self.session.add(user1)
user2 = model.User(username="user2")
user2.roles.append(role1)
user2.roles.append(role2)
self.session.add(user2)
self.session.commit()
self.assertEqual(len(role1.permissions), 3)
self.assertEqual(len(role1.users), 2)
self.assertEqual(len(role2.permissions), 2)
self.assertEqual(len(role2.users), 1)
view = self.make_view()
with patch.object(view, "Session", return_value=self.session):
removing = view.merge_get_data(role1)
keeping = view.merge_get_data(role2)
final = view.merge_get_final_data(removing, keeping)
self.assertEqual(final["permission_count"], 3)
self.assertEqual(final["user_count"], 2)
def test_merge_why_not(self):
model = self.app.model
auth = self.app.get_auth_handler()
role1 = model.Role(name="whatever1")
self.session.add(role1)
role2 = model.Role(name="whatever2")
self.session.add(role2)
self.session.commit()
view = self.make_view()
with patch.object(view, "Session", return_value=self.session):
# normal merge is allowed
self.assertIsNone(view.merge_why_not(role1, role2))
# special roles can be part of a merge if they are being "kept"
# but not if being "removed"
admin = auth.get_role_administrator(self.session)
self.assertIsNone(view.merge_why_not(role1, admin))
reason = view.merge_why_not(admin, role1)
self.assertEqual(reason, "Cannot remove the Administrator role.")
authed = auth.get_role_authenticated(self.session)
self.assertIsNone(view.merge_why_not(role1, authed))
reason = view.merge_why_not(authed, role1)
self.assertEqual(reason, "Cannot remove the Authenticated role.")
anon = auth.get_role_anonymous(self.session)
self.assertIsNone(view.merge_why_not(role1, anon))
reason = view.merge_why_not(anon, role1)
self.assertEqual(reason, "Cannot remove the Anonymous role.")
def test_merge_execute(self):
model = self.app.model
auth = self.app.get_auth_handler()
role1 = model.Role(name="whatever1")
auth.grant_permission(role1, "people.list")
auth.grant_permission(role1, "people.view")
auth.grant_permission(role1, "people.edit")
self.session.add(role1)
role2 = model.Role(name="whatever2")
auth.grant_permission(role2, "people.list")
auth.grant_permission(role2, "people.view")
self.session.add(role2)
user1 = model.User(username="user1")
user1.roles.append(role1)
self.session.add(user1)
user2 = model.User(username="user2")
user2.roles.append(role1)
user2.roles.append(role2)
self.session.add(user2)
self.session.commit()
self.assertEqual(self.session.query(model.Role).count(), 2)
self.assertEqual(len(role1.permissions), 3)
self.assertEqual(len(role1.users), 2)
self.assertEqual(len(role2.permissions), 2)
self.assertEqual(len(role2.users), 1)
view = self.make_view()
with patch.object(view, "Session", return_value=self.session):
view.merge_execute(role1, role2)
self.session.commit()
self.assertEqual(self.session.query(model.Role).count(), 1)
self.assertNotIn(role1, self.session)
self.assertIn(role2, self.session)
self.assertIs(role2, self.session.query(model.Role).one())
self.assertEqual(len(role2.permissions), 3)
self.assertEqual(len(role2.users), 2)
class TestPermissionView(WebTestCase):
def make_view(self):
return mod.PermissionView(self.request)
def test_get_query(self):
view = self.make_view()
query = view.get_query(session=self.session)
self.assertIsInstance(query, orm.Query)
def test_configure_grid(self):
model = self.app.model
view = self.make_view()
grid = view.make_grid(model_class=model.Permission)
self.assertFalse(grid.is_linked("role"))
view.configure_grid(grid)
self.assertTrue(grid.is_linked("role"))
def test_configure_form(self):
model = self.app.model
role = model.Role(name="Foo")
perm = model.Permission(role=role, permission="whatever")
view = self.make_view()
form = view.make_form(model_instance=perm)
self.assertIsNone(form.schema)
view.configure_form(form)
schema = form.get_schema()
self.assertIsInstance(schema["role"].typ, RoleRef)