stash
This commit is contained in:
parent
23185e1721
commit
9f3dc7c993
8 changed files with 335 additions and 103 deletions
|
|
@ -53,56 +53,47 @@ class GroupApiTestCase(UserTestMixin, GroupTestMixin, ToolshedTestCase):
|
|||
|
||||
def test_group_detail_member(self):
|
||||
self.prepare_groups()
|
||||
reply = client.get('/api/groups/{}/'.format(self.f['group1'].id), self.f['local_user1'])
|
||||
group = self.f['group1']
|
||||
reply = client.get('/api/groups/{}@{}/'.format(group.name, group.domain), self.f['local_user1'])
|
||||
self.assertEqual(reply.status_code, 200)
|
||||
self.assertEqual(reply.json()['handle'], str(self.f['group1']))
|
||||
self.assertEqual(reply.json()['handle'], str(group))
|
||||
self.assertEqual(len(reply.json()['members']), 1)
|
||||
|
||||
def test_group_detail_non_member(self):
|
||||
self.prepare_groups()
|
||||
reply = client.get('/api/groups/{}/'.format(self.f['group1'].id), self.f['local_user2'])
|
||||
group = self.f['group1']
|
||||
reply = client.get('/api/groups/{}@{}/'.format(group.name, group.domain), self.f['local_user2'])
|
||||
self.assertEqual(reply.status_code, 404)
|
||||
|
||||
def test_group_detail_by_handle_member(self):
|
||||
self.prepare_groups()
|
||||
group = self.f['group1']
|
||||
reply = client.get('/api/groups/handle/{}/{}/'.format(group.name, group.domain), self.f['local_user1'])
|
||||
self.assertEqual(reply.status_code, 200)
|
||||
self.assertEqual(reply.json()['id'], group.id)
|
||||
self.assertEqual(reply.json()['handle'], str(group))
|
||||
|
||||
def test_group_detail_by_handle_non_member(self):
|
||||
self.prepare_groups()
|
||||
group = self.f['group1']
|
||||
reply = client.get('/api/groups/handle/{}/{}/'.format(group.name, group.domain), self.f['local_user2'])
|
||||
self.assertEqual(reply.status_code, 404)
|
||||
|
||||
def test_group_detail_by_handle_no_such_group(self):
|
||||
reply = client.get('/api/groups/handle/nonexistent/example.com/', self.f['local_user1'])
|
||||
def test_group_detail_no_such_group(self):
|
||||
reply = client.get('/api/groups/nonexistent@example.com/', self.f['local_user1'])
|
||||
self.assertEqual(reply.status_code, 404)
|
||||
|
||||
def test_remove_member(self):
|
||||
self.prepare_groups()
|
||||
self.f['group1'].members.add(self.f['local_user2'].public_identity)
|
||||
reply = client.delete('/api/groups/{}/members/{}/'.format(
|
||||
self.f['group1'].id, self.f['local_user2'].public_identity.id), self.f['local_user1'])
|
||||
group = self.f['group1']
|
||||
group.members.add(self.f['local_user2'].public_identity)
|
||||
reply = client.delete('/api/groups/{}@{}/members/{}/'.format(
|
||||
group.name, group.domain, self.f['local_user2'].public_identity.id), self.f['local_user1'])
|
||||
self.assertEqual(reply.status_code, 204)
|
||||
self.assertEqual(self.f['group1'].members.count(), 1)
|
||||
self.assertEqual(group.members.count(), 1)
|
||||
|
||||
def test_remove_last_member_blocked(self):
|
||||
self.prepare_groups()
|
||||
reply = client.delete('/api/groups/{}/members/{}/'.format(
|
||||
self.f['group1'].id, self.f['local_user1'].public_identity.id), self.f['local_user1'])
|
||||
group = self.f['group1']
|
||||
reply = client.delete('/api/groups/{}@{}/members/{}/'.format(
|
||||
group.name, group.domain, self.f['local_user1'].public_identity.id), self.f['local_user1'])
|
||||
self.assertEqual(reply.status_code, 400)
|
||||
self.assertEqual(self.f['group1'].members.count(), 1)
|
||||
self.assertEqual(group.members.count(), 1)
|
||||
|
||||
def test_remove_member_non_member_denied(self):
|
||||
self.prepare_groups()
|
||||
self.f['group1'].members.add(self.f['local_user2'].public_identity)
|
||||
reply = client.delete('/api/groups/{}/members/{}/'.format(
|
||||
self.f['group1'].id, self.f['local_user1'].public_identity.id), self.f['ext_user1'])
|
||||
group = self.f['group1']
|
||||
group.members.add(self.f['local_user2'].public_identity)
|
||||
reply = client.delete('/api/groups/{}@{}/members/{}/'.format(
|
||||
group.name, group.domain, self.f['local_user1'].public_identity.id), self.f['ext_user1'])
|
||||
self.assertEqual(reply.status_code, 404)
|
||||
self.assertEqual(self.f['group1'].members.count(), 2)
|
||||
self.assertEqual(group.members.count(), 2)
|
||||
|
||||
|
||||
class GroupInviteApiTestCase(UserTestMixin, GroupTestMixin, ToolshedTestCase):
|
||||
|
|
@ -116,7 +107,8 @@ class GroupInviteApiTestCase(UserTestMixin, GroupTestMixin, ToolshedTestCase):
|
|||
inviter = self.f['local_user1']
|
||||
invitee = self.f['local_user2']
|
||||
|
||||
reply1 = client.post('/api/groups/{}/invites/'.format(group.id), inviter, {'invitee': str(invitee)})
|
||||
reply1 = client.post('/api/groups/{}@{}/invites/'.format(group.name, group.domain), inviter,
|
||||
{'invitee': str(invitee)})
|
||||
self.assertEqual(reply1.status_code, 201)
|
||||
secret = reply1.json()['secret']
|
||||
self.assertEqual(GroupInvite.objects.count(), 1)
|
||||
|
|
@ -152,7 +144,7 @@ class GroupInviteApiTestCase(UserTestMixin, GroupTestMixin, ToolshedTestCase):
|
|||
|
||||
def test_invite_non_member_denied(self):
|
||||
group = self.f['group1']
|
||||
reply = client.post('/api/groups/{}/invites/'.format(group.id), self.f['local_user2'],
|
||||
reply = client.post('/api/groups/{}@{}/invites/'.format(group.name, group.domain), self.f['local_user2'],
|
||||
{'invitee': str(self.f['ext_user1'])})
|
||||
self.assertEqual(reply.status_code, 404)
|
||||
self.assertEqual(GroupInvite.objects.count(), 0)
|
||||
|
|
@ -160,7 +152,7 @@ class GroupInviteApiTestCase(UserTestMixin, GroupTestMixin, ToolshedTestCase):
|
|||
def test_invite_already_member(self):
|
||||
group = self.f['group1']
|
||||
group.members.add(self.f['local_user2'].public_identity)
|
||||
reply = client.post('/api/groups/{}/invites/'.format(group.id), self.f['local_user1'],
|
||||
reply = client.post('/api/groups/{}@{}/invites/'.format(group.name, group.domain), self.f['local_user1'],
|
||||
{'invitee': str(self.f['local_user2'])})
|
||||
self.assertEqual(reply.status_code, 208)
|
||||
|
||||
|
|
@ -177,7 +169,7 @@ class GroupInviteApiTestCase(UserTestMixin, GroupTestMixin, ToolshedTestCase):
|
|||
group = self.f['group1']
|
||||
inviter = self.f['local_user1']
|
||||
invitee = self.f['local_user2']
|
||||
client.post('/api/groups/{}/invites/'.format(group.id), inviter, {'invitee': str(invitee)})
|
||||
client.post('/api/groups/{}@{}/invites/'.format(group.name, group.domain), inviter, {'invitee': str(invitee)})
|
||||
reply = client.post('/api/group_invites/accept/', invitee, {
|
||||
'group': str(group), 'invitee': str(invitee), 'invitee_key': invitee.public_key(),
|
||||
'secret': 'not-the-right-secret'
|
||||
|
|
@ -189,7 +181,8 @@ class GroupInviteApiTestCase(UserTestMixin, GroupTestMixin, ToolshedTestCase):
|
|||
group = self.f['group1']
|
||||
inviter = self.f['local_user1']
|
||||
invitee = DummyExternalUser('newmember', 'remote.example', known=False)
|
||||
reply1 = client.post('/api/groups/{}/invites/'.format(group.id), inviter, {'invitee': str(invitee)})
|
||||
reply1 = client.post('/api/groups/{}@{}/invites/'.format(group.name, group.domain), inviter,
|
||||
{'invitee': str(invitee)})
|
||||
secret = reply1.json()['secret']
|
||||
|
||||
reply = client.post('/api/group_invites/accept/', invitee, {
|
||||
|
|
@ -206,7 +199,8 @@ class GroupInviteApiTestCase(UserTestMixin, GroupTestMixin, ToolshedTestCase):
|
|||
group = self.f['group1']
|
||||
inviter = self.f['local_user1']
|
||||
invitee = self.f['local_user2']
|
||||
reply1 = client.post('/api/groups/{}/invites/'.format(group.id), inviter, {'invitee': str(invitee)})
|
||||
reply1 = client.post('/api/groups/{}@{}/invites/'.format(group.name, group.domain), inviter,
|
||||
{'invitee': str(invitee)})
|
||||
secret = reply1.json()['secret']
|
||||
bad_signature_client = SignatureAuthClient(bad_signature=True)
|
||||
reply = bad_signature_client.post('/api/group_invites/accept/', invitee, {
|
||||
|
|
|
|||
|
|
@ -353,7 +353,7 @@ class GroupOwnedInventoryApiTestCase(UserTestMixin, GroupTestMixin, CategoryTest
|
|||
def create_group_item(self, name='drill'):
|
||||
return client.post('/api/inventory_items/', self.f['local_user1'], {
|
||||
'name': name, 'owned_quantity': 1, 'availability_policy': 'private',
|
||||
'owner_group': self.f['group1'].id,
|
||||
'owner_group': str(self.f['group1'])[1:],
|
||||
})
|
||||
|
||||
def test_create_group_owned_item(self):
|
||||
|
|
@ -368,7 +368,7 @@ class GroupOwnedInventoryApiTestCase(UserTestMixin, GroupTestMixin, CategoryTest
|
|||
def test_create_group_owned_item_non_member_denied(self):
|
||||
reply = client.post('/api/inventory_items/', self.f['ext_user1'], {
|
||||
'name': 'drill', 'owned_quantity': 1, 'availability_policy': 'private',
|
||||
'owner_group': self.f['group1'].id,
|
||||
'owner_group': str(self.f['group1'])[1:],
|
||||
})
|
||||
self.assertEqual(reply.status_code, 403)
|
||||
self.assertEqual(InventoryItem.objects.count(), 0)
|
||||
|
|
@ -413,14 +413,14 @@ class GroupOwnedInventoryApiTestCase(UserTestMixin, GroupTestMixin, CategoryTest
|
|||
|
||||
def test_group_items_listed_by_group_query_param(self):
|
||||
self.create_group_item()
|
||||
reply = client.get('/api/inventory_items/?group={}'.format(self.f['group1'].id), self.f['local_user2'])
|
||||
reply = client.get('/api/inventory_items/?group={}'.format(str(self.f['group1'])[1:]), self.f['local_user2'])
|
||||
self.assertEqual(reply.status_code, 200)
|
||||
self.assertEqual(len(reply.json()), 1)
|
||||
self.assertEqual(reply.json()[0]['name'], 'drill')
|
||||
|
||||
def test_group_items_not_listed_for_non_member_query_param(self):
|
||||
self.create_group_item()
|
||||
reply = client.get('/api/inventory_items/?group={}'.format(self.f['group1'].id), self.f['ext_user1'])
|
||||
reply = client.get('/api/inventory_items/?group={}'.format(str(self.f['group1'])[1:]), self.f['ext_user1'])
|
||||
self.assertEqual(reply.status_code, 200)
|
||||
self.assertEqual(len(reply.json()), 0)
|
||||
|
||||
|
|
@ -435,7 +435,7 @@ class GroupOwnedInventoryApiTestCase(UserTestMixin, GroupTestMixin, CategoryTest
|
|||
'owned_quantity': 3,
|
||||
'tags': ['tag1', 'tag2'],
|
||||
'properties': [{'name': 'prop1', 'value': 'value1'}, {'name': 'prop2', 'value': 'value2'}],
|
||||
'owner_group': self.f['group1'].id,
|
||||
'owner_group': str(self.f['group1'])[1:],
|
||||
})
|
||||
self.assertEqual(reply.status_code, 201)
|
||||
item = InventoryItem.objects.get(name='drill')
|
||||
|
|
@ -451,20 +451,21 @@ class GroupOwnedInventoryApiTestCase(UserTestMixin, GroupTestMixin, CategoryTest
|
|||
def test_create_group_owned_item_empty_fails(self):
|
||||
# Parity with InventoryApiTestCase.test_post_new_item_empty: clean()'s name-or-files validation still applies.
|
||||
reply = client.post('/api/inventory_items/', self.f['local_user1'], {
|
||||
'availability_policy': 'private', 'owned_quantity': 1, 'owner_group': self.f['group1'].id,
|
||||
'availability_policy': 'private', 'owned_quantity': 1, 'owner_group': str(self.f['group1'])[1:],
|
||||
})
|
||||
self.assertEqual(reply.status_code, 400)
|
||||
self.assertEqual(InventoryItem.objects.count(), 0)
|
||||
|
||||
def test_create_group_owned_item_nonexistent_group(self):
|
||||
reply = client.post('/api/inventory_items/', self.f['local_user1'], {
|
||||
'name': 'drill', 'owned_quantity': 1, 'availability_policy': 'private', 'owner_group': 999999,
|
||||
'name': 'drill', 'owned_quantity': 1, 'availability_policy': 'private',
|
||||
'owner_group': 'nonexistent@example.com',
|
||||
})
|
||||
self.assertEqual(reply.status_code, 404)
|
||||
self.assertEqual(InventoryItem.objects.count(), 0)
|
||||
|
||||
def test_group_items_listed_for_nonexistent_group_query_param(self):
|
||||
reply = client.get('/api/inventory_items/?group=999999', self.f['local_user1'])
|
||||
reply = client.get('/api/inventory_items/?group=nonexistent@example.com', self.f['local_user1'])
|
||||
self.assertEqual(reply.status_code, 200)
|
||||
self.assertEqual(len(reply.json()), 0)
|
||||
|
||||
|
|
@ -495,7 +496,7 @@ class GroupOwnedInventoryApiTestCase(UserTestMixin, GroupTestMixin, CategoryTest
|
|||
reply = client.post('/api/inventory_items/', self.f['local_user1'], {
|
||||
'name': 'drill', 'owned_quantity': 1, 'availability_policy': 'private',
|
||||
'category': 'cat1', 'tags': ['tag1'],
|
||||
'owner_group': self.f['group1'].id,
|
||||
'owner_group': str(self.f['group1'])[1:],
|
||||
})
|
||||
item_id = reply.json()['id']
|
||||
reply = client.patch('/api/inventory_items/{}/'.format(item_id), self.f['local_user2'], {
|
||||
|
|
@ -509,7 +510,7 @@ class GroupOwnedInventoryApiTestCase(UserTestMixin, GroupTestMixin, CategoryTest
|
|||
def test_group_item_storage_location(self):
|
||||
reply = client.post('/api/inventory_items/', self.f['local_user1'], {
|
||||
'name': 'drill', 'owned_quantity': 1, 'availability_policy': 'private',
|
||||
'storage_location': self.f['loc1'].id, 'owner_group': self.f['group1'].id,
|
||||
'storage_location': self.f['loc1'].id, 'owner_group': str(self.f['group1'])[1:],
|
||||
})
|
||||
self.assertEqual(reply.status_code, 201)
|
||||
item = InventoryItem.objects.get(name='drill')
|
||||
|
|
@ -519,7 +520,7 @@ class GroupOwnedInventoryApiTestCase(UserTestMixin, GroupTestMixin, CategoryTest
|
|||
# Parity with TestInventoryItemWithFileApiTestCase.test_post_item_with_file_id.
|
||||
reply = client.post('/api/inventory_items/', self.f['local_user1'], {
|
||||
'name': 'drill', 'owned_quantity': 1, 'availability_policy': 'private',
|
||||
'files': [self.f['test_file1'].id], 'owner_group': self.f['group1'].id,
|
||||
'files': [self.f['test_file1'].id], 'owner_group': str(self.f['group1'])[1:],
|
||||
})
|
||||
self.assertEqual(reply.status_code, 201)
|
||||
item = InventoryItem.objects.get(name='drill')
|
||||
|
|
@ -529,7 +530,7 @@ class GroupOwnedInventoryApiTestCase(UserTestMixin, GroupTestMixin, CategoryTest
|
|||
reply = client.post('/api/inventory_items/', self.f['local_user1'], {
|
||||
'name': 'drill', 'owned_quantity': 1, 'availability_policy': 'private',
|
||||
'files': [{'data': self.f['encoded_content3'], 'mime_type': 'text/plain'}],
|
||||
'owner_group': self.f['group1'].id,
|
||||
'owner_group': str(self.f['group1'])[1:],
|
||||
})
|
||||
self.assertEqual(reply.status_code, 201)
|
||||
item = InventoryItem.objects.get(name='drill')
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from authentication.tests import SignatureAuthClient, UserTestMixin, ToolshedTestCase
|
||||
from authentication.tests import SignatureAuthClient, UserTestMixin, GroupTestMixin, ToolshedTestCase
|
||||
from files.tests import FilesTestMixin
|
||||
from toolshed.models import InventoryItem, Category, StorageLocation
|
||||
from toolshed.tests import InventoryTestMixin, LocationTestMixin
|
||||
|
|
@ -129,3 +129,110 @@ class LocationApiTestCase(UserTestMixin, InventoryTestMixin, LocationTestMixin,
|
|||
self.assertEqual(reply.status_code, 404)
|
||||
self.assertEqual(StorageLocation.objects.filter(id=self.f['loc1'].id).count(), 1)
|
||||
|
||||
|
||||
class GroupOwnedLocationApiTestCase(UserTestMixin, GroupTestMixin, ToolshedTestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.prepare_users()
|
||||
self.prepare_groups()
|
||||
self.f['group1'].members.add(self.f['local_user2'].public_identity)
|
||||
|
||||
def create_group_location(self, name='shelf'):
|
||||
return client.post('/api/storage_locations/', self.f['local_user1'], {
|
||||
'name': name, 'owner_group': str(self.f['group1'])[1:],
|
||||
})
|
||||
|
||||
def test_create_group_owned_location(self):
|
||||
reply = self.create_group_location()
|
||||
self.assertEqual(reply.status_code, 201)
|
||||
location = StorageLocation.objects.get(name='shelf')
|
||||
self.assertIsNone(location.owner)
|
||||
self.assertEqual(location.owner_group, self.f['group1'])
|
||||
self.assertEqual(reply.json()['owner_group'], str(self.f['group1']))
|
||||
self.assertIsNone(reply.json()['owner'])
|
||||
|
||||
def test_create_group_owned_location_non_member_denied(self):
|
||||
reply = client.post('/api/storage_locations/', self.f['ext_user1'], {
|
||||
'name': 'shelf', 'owner_group': str(self.f['group1'])[1:],
|
||||
})
|
||||
self.assertEqual(reply.status_code, 403)
|
||||
self.assertEqual(StorageLocation.objects.count(), 0)
|
||||
|
||||
def test_other_member_can_edit(self):
|
||||
location_id = self.create_group_location().json()['id']
|
||||
reply = client.patch('/api/storage_locations/{}/'.format(location_id), self.f['local_user2'], {
|
||||
'name': 'shelf-renamed'
|
||||
})
|
||||
self.assertEqual(reply.status_code, 200)
|
||||
self.assertEqual(StorageLocation.objects.get(id=location_id).name, 'shelf-renamed')
|
||||
|
||||
def test_other_member_can_delete(self):
|
||||
location_id = self.create_group_location().json()['id']
|
||||
reply = client.delete('/api/storage_locations/{}/'.format(location_id), self.f['local_user2'])
|
||||
self.assertEqual(reply.status_code, 204)
|
||||
self.assertEqual(StorageLocation.objects.filter(id=location_id).count(), 0)
|
||||
|
||||
def test_remote_member_without_local_account_can_edit(self):
|
||||
# A remote member (KnownIdentity, no ToolshedUser row) must still act on group-owned
|
||||
# locations - not unauthorized just because .user.exists() is False.
|
||||
self.f['group1'].members.add(self.f['ext_user1'].public_identity)
|
||||
location_id = self.create_group_location().json()['id']
|
||||
reply = client.get('/api/storage_locations/{}/'.format(location_id), self.f['ext_user1'])
|
||||
self.assertEqual(reply.status_code, 200)
|
||||
reply = client.patch('/api/storage_locations/{}/'.format(location_id), self.f['ext_user1'], {
|
||||
'name': 'shelf-renamed-by-remote-member'
|
||||
})
|
||||
self.assertEqual(reply.status_code, 200)
|
||||
self.assertEqual(StorageLocation.objects.get(id=location_id).name, 'shelf-renamed-by-remote-member')
|
||||
|
||||
def test_non_member_cannot_see_or_edit(self):
|
||||
location_id = self.create_group_location().json()['id']
|
||||
reply = client.get('/api/storage_locations/{}/'.format(location_id), self.f['ext_user1'])
|
||||
self.assertEqual(reply.status_code, 404)
|
||||
|
||||
def test_group_locations_excluded_from_personal_list(self):
|
||||
self.create_group_location()
|
||||
reply = client.get('/api/storage_locations/', self.f['local_user1'])
|
||||
self.assertEqual(reply.status_code, 200)
|
||||
self.assertEqual(len(reply.json()), 0)
|
||||
|
||||
def test_group_locations_listed_by_group_query_param(self):
|
||||
self.create_group_location()
|
||||
reply = client.get('/api/storage_locations/?group={}'.format(str(self.f['group1'])[1:]), self.f['local_user2'])
|
||||
self.assertEqual(reply.status_code, 200)
|
||||
self.assertEqual(len(reply.json()), 1)
|
||||
self.assertEqual(reply.json()[0]['name'], 'shelf')
|
||||
|
||||
def test_group_locations_not_listed_for_non_member_query_param(self):
|
||||
self.create_group_location()
|
||||
reply = client.get('/api/storage_locations/?group={}'.format(str(self.f['group1'])[1:]), self.f['ext_user1'])
|
||||
self.assertEqual(reply.status_code, 200)
|
||||
self.assertEqual(len(reply.json()), 0)
|
||||
|
||||
def test_group_location_can_be_parent_for_group_member(self):
|
||||
parent_id = self.create_group_location('shelf').json()['id']
|
||||
reply = client.post('/api/storage_locations/', self.f['local_user2'], {
|
||||
'name': 'bin', 'owner_group': str(self.f['group1'])[1:], 'parent': parent_id,
|
||||
})
|
||||
self.assertEqual(reply.status_code, 201)
|
||||
self.assertEqual(reply.json()['path'], 'shelf/bin')
|
||||
|
||||
def test_own_personal_location_can_be_parent_of_group_location(self):
|
||||
# OwnerScopedPrimaryKeyRelatedField (see serializers.py) scopes `parent` to every
|
||||
# location the requester can act on - own personal ones plus any group's - with no
|
||||
# further check that it matches the new location's own owner_group. Same behavior
|
||||
# InventoryItem.storage_location already had before group ownership existed here; not
|
||||
# something this feature narrows.
|
||||
personal = StorageLocation.create_for_owner(name='mine', owner=self.f['local_user1'])
|
||||
reply = client.post('/api/storage_locations/', self.f['local_user1'], {
|
||||
'name': 'bin', 'owner_group': str(self.f['group1'])[1:], 'parent': personal.id,
|
||||
})
|
||||
self.assertEqual(reply.status_code, 201)
|
||||
|
||||
def test_group_location_not_valid_parent_for_non_member(self):
|
||||
parent_id = self.create_group_location('shelf').json()['id']
|
||||
reply = client.post('/api/storage_locations/', self.f['ext_user1'], {
|
||||
'name': 'bin', 'parent': parent_id,
|
||||
})
|
||||
self.assertEqual(reply.status_code, 400)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue