Normalize portal kinds before checking feature access
Magent CI/CD / verify (push) Successful in 11m13s
Magent CI/CD / deploy-prod (push) Skipped
Magent CI/CD / deploy-beta (push) Successful in 1m49s

This commit is contained in:
2026-09-11 12:32:51 +12:00
parent ec0a866ef3
commit df6fe58278
2 changed files with 18 additions and 2 deletions
+8 -2
View File
@@ -55,9 +55,15 @@ async def require_portal_access(request: Request, user: dict = Depends(get_curre
check(user, "requests" if item.get("kind") == "request" else "issues") check(user, "requests" if item.get("kind") == "request" else "issues")
elif path.endswith("/items") and request.method == "POST": elif path.endswith("/items") and request.method == "POST":
payload = await request.json() payload = await request.json()
check(user, "new_requests" if isinstance(payload, dict) and payload.get("kind", "request") == "request" else "issues") kind = str(payload.get("kind") or "").strip().lower() if isinstance(payload, dict) else ""
check(user, "new_requests" if not kind or kind == "request" else "issues")
elif path.endswith(("/items", "/overview")) and request.query_params.get("kind"): elif path.endswith(("/items", "/overview")) and request.query_params.get("kind"):
check(user, "requests" if request.query_params["kind"] == "request" else "issues") kind = request.query_params["kind"].strip().lower()
if not kind:
check(user, "requests")
check(user, "issues")
else:
check(user, "requests" if kind == "request" else "issues")
else: else:
# Unfiltered lists/overview can include both kinds. # Unfiltered lists/overview can include both kinds.
check(user, "requests") check(user, "requests")
+10
View File
@@ -108,3 +108,13 @@ class FeatureAccessTests(TempDatabaseMixin, unittest.TestCase):
with self.assertRaises(StopAsyncIteration): with self.assertRaises(StopAsyncIteration):
await anext(iterator) await anext(iterator)
asyncio.run(scenario()) asyncio.run(scenario())
def test_legacy_portal_kind_normalization_cannot_bypass_permissions(self):
update_permissions({'requests': False, 'new_requests': False, 'issues': True}, self.user['username'])
for kind in ['request', 'REQUEST', ' Request ', ' ', '']:
with self.subTest(kind=kind):
self.assertEqual(self.client.get('/portal/items', params={'kind': kind}).status_code, 403)
self.assertEqual(self.client.get('/portal/overview', params={'kind': kind}).status_code, 403)
self.assertEqual(self.client.post('/portal/items', json={'kind': kind}).status_code, 403)
self.assertEqual(self.client.post('/portal/items', json={'kind': None}).status_code, 403)
self.assertEqual(self.client.post('/portal/items', json={}).status_code, 403)