diff --git a/tests/apiv2/test_bids.py b/tests/apiv2/test_bids.py index 685553047..60ea1a35e 100644 --- a/tests/apiv2/test_bids.py +++ b/tests/apiv2/test_bids.py @@ -11,10 +11,12 @@ class TestBidViewSet(TestBidBase, APITestCase): model_name = 'bid' + view_user_permissions = ['view_hidden_bid'] + add_user_permissions = ['top_level_bid'] def setUp(self): super().setUp() - self.client.force_authenticate(user=self.super_user) + self.client.force_authenticate(user=self.locked_user) def test_detail(self): serialized = BidSerializer(self.opened_parent_bid, tree=True) @@ -174,9 +176,9 @@ def test_create(self): serialized = BidSerializer(models.Bid.objects.get(pk=data['id'])) self.assertEqual(data, serialized.data) - with self.subTest('attach to locked event with permission'): + with self.subTest('attach to parent'): data = self.post_new( - data={'name': 'New Locked Event Bid', 'event': self.locked_event.pk}, + data={'name': 'New Child', 'parent': self.opened_parent_bid.pk}, ) serialized = BidSerializer(models.Bid.objects.get(pk=data['id'])) self.assertEqual(data, serialized.data) @@ -188,27 +190,28 @@ def test_create(self): serialized = BidSerializer(models.Bid.objects.get(pk=data['id'])) self.assertEqual(data, serialized.data) - with self.subTest('attach to locked speedrun with permission'): + with self.subTest('attach to chain'): data = self.post_new( - data={'name': 'New Locked Run Bid', 'speedrun': self.locked_run.pk}, + data={ + 'name': 'Chain Abyss', + 'parent': self.chain_bottom.pk, + 'goal': 50, + }, ) serialized = BidSerializer(models.Bid.objects.get(pk=data['id'])) self.assertEqual(data, serialized.data) - with self.subTest('attach to parent'): + with self.subTest('attach to locked event with permission'): data = self.post_new( - data={'name': 'New Child', 'parent': self.opened_parent_bid.pk}, + data={'name': 'New Locked Event Bid', 'event': self.locked_event.pk}, + user=self.locked_user, ) serialized = BidSerializer(models.Bid.objects.get(pk=data['id'])) self.assertEqual(data, serialized.data) - with self.subTest('attach to chain'): + with self.subTest('attach to locked speedrun with permission'): data = self.post_new( - data={ - 'name': 'Chain Abyss', - 'parent': self.chain_bottom.pk, - 'goal': 50, - }, + data={'name': 'New Locked Run Bid', 'speedrun': self.locked_run.pk}, ) serialized = BidSerializer(models.Bid.objects.get(pk=data['id'])) self.assertEqual(data, serialized.data) @@ -248,28 +251,7 @@ def test_create(self): self.client.force_authenticate(user=self.add_user) - with self.subTest('require top level permission for bids without parents'): - self.post_new( - data={'name': 'New Event Bid 2', 'event': self.event.pk}, - status_code=403, - ) - - self.post_new( - data={ - 'name': 'New Child 2', - 'parent': self.opened_parent_bid.pk, - }, - status_code=201, - ) - with self.subTest('require locked permission'): - self.add_user.user_permissions.add( - Permission.objects.get(codename='top_level_bid') - ) - # TODO: maybe make a separate user for this - del self.add_user._perm_cache - del self.add_user._user_perm_cache - self.post_new( data={ 'name': 'New Locked Event Bid 2', @@ -294,6 +276,27 @@ def test_create(self): status_code=403, ) + with self.subTest('require top level permission for bids without parents'): + self.add_user.user_permissions.remove( + Permission.objects.get(codename='top_level_bid') + ) + # TODO: maybe make a separate user for this + del self.add_user._perm_cache + del self.add_user._user_perm_cache + + self.post_new( + data={'name': 'New Event Bid 2', 'event': self.event.pk}, + status_code=403, + ) + + self.post_new( + data={ + 'name': 'New Child 2', + 'parent': self.opened_parent_bid.pk, + }, + status_code=201, + ) + with self.subTest('anonymous'): self.post_new( data={ diff --git a/tests/util.py b/tests/util.py index ae61f130e..82d765cf5 100644 --- a/tests/util.py +++ b/tests/util.py @@ -120,6 +120,9 @@ def test_nulls_removed(self): class APITestCase(TransactionTestCase): model_name = None + view_user_permissions = [] # trickles to add_user and locked_user + add_user_permissions = [] # trickles to locked_user + locked_user_permissions = [] encoder = DjangoJSONEncoder() def parseJSON(self, response, status_code=200): @@ -515,6 +518,7 @@ def setUp(self): self.view_user.user_permissions.add( Permission.objects.get(name=f'Can view {self.model_name}'), ) + self.add_user.user_permissions.add( Permission.objects.get(name=f'Can add {self.model_name}'), Permission.objects.get(name=f'Can change {self.model_name}'), @@ -525,6 +529,25 @@ def setUp(self): Permission.objects.get(name=f'Can change {self.model_name}'), Permission.objects.get(name=f'Can view {self.model_name}'), ) + self.view_user.user_permissions.add( + *(Permission.objects.filter(codename__in=self.view_user_permissions)) + ) + self.add_user.user_permissions.add( + *( + Permission.objects.filter( + codename__in=self.view_user_permissions + self.add_user_permissions + ) + ) + ) + self.locked_user.user_permissions.add( + *( + Permission.objects.filter( + codename__in=self.view_user_permissions + + self.add_user_permissions + + self.locked_user_permissions + ) + ) + ) self.super_user = User.objects.create(username='super', is_superuser=True) self.maxDiff = None @@ -581,7 +604,7 @@ def tearDown(self): f'./test-results/TEST-{self.id()}.{int(time.time())}.png' ) raise Exception( - f'data:image/png;base64,{self.webdriver.get_screenshot_as_base64()}' + f'{self.webdriver.current_url}\ndata:image/png;base64,{self.webdriver.get_screenshot_as_base64()}' ) def tracker_login(self, username, password='password'): diff --git a/tracker/api/permissions.py b/tracker/api/permissions.py index 9fd0f9084..46ab5197e 100644 --- a/tracker/api/permissions.py +++ b/tracker/api/permissions.py @@ -37,7 +37,7 @@ class EventLockedPermission(DjangoModelPermissionsOrAnonReadOnly): def has_permission(self, request: Request, view: t.Callable): return super().has_permission(request, view) and ( request.method in SAFE_METHODS - or request.user.has_perm('tracker.edit_locked_events') + or request.user.has_perm('tracker.can_edit_locked_events') or not view.is_event_locked(request) ) @@ -59,7 +59,7 @@ def has_permission(self, request: Request, view: t.Callable): return super().has_permission(request, view) and ( feed is None or feed in self.PUBLIC_FEEDS - or request.user.has_perm('tracker.view_hidden_bids') + or request.user.has_perm('tracker.view_hidden_bid') ) @@ -71,5 +71,5 @@ class BidStatePermission(BasePermission): def has_object_permission(self, request: Request, view: t.Callable, obj: t.Any): return super().has_object_permission(request, view, obj) and ( obj.state in self.PUBLIC_STATES - or request.user.has_perm('tracker.view_hidden_bids') + or request.user.has_perm('tracker.view_hidden_bid') )