Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix permissions on Bid v2 endpoint [#186384302] #614

Merged
merged 1 commit into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 37 additions & 34 deletions tests/apiv2/test_bids.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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',
Expand All @@ -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={
Expand Down
25 changes: 24 additions & 1 deletion tests/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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}'),
Expand All @@ -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

Expand Down Expand Up @@ -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'):
Expand Down
6 changes: 3 additions & 3 deletions tracker/api/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
)

Expand All @@ -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')
)


Expand All @@ -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')
)
Loading