1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
"""Test functions dealing with group management."""
from uuid import UUID
import pytest
from pymonad.maybe import Nothing
from gn3.auth import db
from gn3.auth.authentication.users import User
from gn3.auth.authorisation.roles import Role
from gn3.auth.authorisation.privileges import Privilege
from gn3.auth.authorisation.errors import AuthorisationError
from gn3.auth.authorisation.groups.models import (
Group, GroupRole, user_group, create_group, create_group_role)
from tests.unit.auth import conftest
create_group_failure = {
"status": "error",
"message": "Unauthorised: Failed to create group."
}
def uuid_fn():
"""Return a specific UUID"""
return UUID("d32611e3-07fc-4564-b56c-786c6db6de2b")
GROUP = Group(UUID("9988c21d-f02f-4d45-8966-22c968ac2fbf"), "TheTestGroup",
{"group_description": "The test group"})
PRIVILEGES = (
Privilege(
"group:resource:view-resource",
"view a resource and use it in computations"),
Privilege("group:resource:edit-resource", "edit/update a resource"))
@pytest.mark.unit_test
@pytest.mark.parametrize(
"user,expected", tuple(zip(conftest.TEST_USERS[0:1], (
Group(
UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), "a_test_group",
{"group_description": "A test group"}),
create_group_failure, create_group_failure, create_group_failure,
create_group_failure))))
def test_create_group(# pylint: disable=[too-many-arguments]
fxtr_app, auth_testdb_path, mocker, fxtr_users, user, expected):# pylint: disable=[unused-argument]
"""
GIVEN: an authenticated user
WHEN: the user attempts to create a group
THEN: verify they are only able to create the group if they have the
appropriate privileges
"""
mocker.patch("gn3.auth.authorisation.groups.models.uuid4", uuid_fn)
mocker.patch("gn3.auth.authorisation.checks.require_oauth.acquire",
conftest.get_tokeniser(user))
with db.connection(auth_testdb_path) as conn:
assert create_group(
conn, "a_test_group", user, "A test group") == expected
@pytest.mark.unit_test
@pytest.mark.parametrize("user", conftest.TEST_USERS[1:])
def test_create_group_raises_exception_with_non_privileged_user(# pylint: disable=[too-many-arguments]
fxtr_app, auth_testdb_path, mocker, fxtr_users, user):# pylint: disable=[unused-argument]
"""
GIVEN: an authenticated user, without appropriate privileges
WHEN: the user attempts to create a group
THEN: verify the system raises an exception
"""
mocker.patch("gn3.auth.authorisation.groups.models.uuid4", uuid_fn)
mocker.patch("gn3.auth.authorisation.checks.require_oauth.acquire",
conftest.get_tokeniser(user))
with db.connection(auth_testdb_path) as conn:
with pytest.raises(AuthorisationError):
assert create_group(conn, "a_test_group", user, "A test group")
create_role_failure = {
"status": "error",
"message": "Unauthorised: Could not create the group role"
}
@pytest.mark.unit_test
@pytest.mark.parametrize(
"user,expected", tuple(zip(conftest.TEST_USERS[0:1], (
GroupRole(
UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"),
GROUP,
Role(UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"),
"ResourceEditor", True, PRIVILEGES)),))))
def test_create_group_role(mocker, fxtr_users_in_group, user, expected):
"""
GIVEN: an authenticated user
WHEN: the user attempts to create a role, attached to a group
THEN: verify they are only able to create the role if they have the
appropriate privileges and that the role is attached to the given group
"""
mocker.patch("gn3.auth.authorisation.groups.models.uuid4", uuid_fn)
mocker.patch("gn3.auth.authorisation.roles.models.uuid4", uuid_fn)
mocker.patch("gn3.auth.authorisation.checks.require_oauth.acquire",
conftest.get_tokeniser(user))
conn, _group, _users = fxtr_users_in_group
with db.cursor(conn) as cursor:
assert create_group_role(
conn, GROUP, "ResourceEditor", PRIVILEGES) == expected
# cleanup
cursor.execute(
("DELETE FROM group_roles "
"WHERE group_role_id=? AND group_id=? AND role_id=?"),
(str(uuid_fn()), str(GROUP.group_id), str(uuid_fn())))
@pytest.mark.unit_test
@pytest.mark.parametrize(
"user,expected", tuple(zip(conftest.TEST_USERS[1:], (
create_role_failure, create_role_failure, create_role_failure))))
def test_create_group_role_raises_exception_with_unauthorised_users(
mocker, fxtr_users_in_group, user, expected):
"""
GIVEN: an authenticated user
WHEN: the user attempts to create a role, attached to a group
THEN: verify they are only able to create the role if they have the
appropriate privileges and that the role is attached to the given group
"""
mocker.patch("gn3.auth.authorisation.groups.models.uuid4", uuid_fn)
mocker.patch("gn3.auth.authorisation.roles.models.uuid4", uuid_fn)
mocker.patch("gn3.auth.authorisation.checks.require_oauth.acquire",
conftest.get_tokeniser(user))
conn, _group, _users = fxtr_users_in_group
with pytest.raises(AuthorisationError):
assert create_group_role(
conn, GROUP, "ResourceEditor", PRIVILEGES) == expected
@pytest.mark.unit_test
def test_create_multiple_groups(mocker, fxtr_users):
"""
GIVEN: An authenticated user with appropriate authorisation
WHEN: The user attempts to create a new group, while being a member of an
existing group
THEN: The system should prevent that, and respond with an appropriate error
message
"""
mocker.patch("gn3.auth.authorisation.groups.models.uuid4", uuid_fn)
user = User(
UUID("ecb52977-3004-469e-9428-2a1856725c7f"), "group@lead.er",
"Group Leader")
mocker.patch("gn3.auth.authorisation.checks.require_oauth.acquire",
conftest.get_tokeniser(user))
conn, _test_users = fxtr_users
# First time, successfully creates the group
assert create_group(conn, "a_test_group", user) == Group(
UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), "a_test_group",
{})
# subsequent attempts should fail
with pytest.raises(AuthorisationError):
create_group(conn, "another_test_group", user)
@pytest.mark.unit_test
@pytest.mark.parametrize(
"user,expected",
tuple(zip(
conftest.TEST_USERS,
(([Group(UUID("9988c21d-f02f-4d45-8966-22c968ac2fbf"), "TheTestGroup", {})] * 3)
+ [Nothing]))))
def test_user_group(fxtr_users_in_group, user, expected):
"""
GIVEN: A bunch of registered users, some of whom are members of a group, and
others are not
WHEN: a particular user's group is requested,
THEN: return a Maybe containing the group that the user belongs to, or
Nothing
"""
conn, _group, _users = fxtr_users_in_group
assert (
user_group(conn, user).maybe(Nothing, lambda val: val)
== expected)
|