Skip to content
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
15 changes: 6 additions & 9 deletions back/boxtribute_server/authz.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ def authorize_cross_organisation_access(
# functionality, while each of the larger levels additively builds up on the previous
# one. The user's maximum beta-level defines the functionality range that the user can
# access.
DEFAULT_MAX_BETA_LEVEL = 4 # update authz spec ADR when bumping
DEFAULT_MAX_BETA_LEVEL = 5 # update authz spec ADR when bumping
MUTATIONS_FOR_BETA_LEVEL: Dict[int, Tuple[str, ...]] = {
# ### BETA-LEVEL 0 ###
# - actions for BoxView/BoxEdit pages
Expand Down Expand Up @@ -378,9 +378,9 @@ def authorize_cross_organisation_access(
)

# ### BETA-LEVEL 6 ###
# In addition to level 4,
# - bulk-create beneficiaries (esp. for Google-Sheets add-on)
MUTATIONS_FOR_BETA_LEVEL[6] = MUTATIONS_FOR_BETA_LEVEL[4] + (
# In addition to level 5,
# - bulk-create beneficiaries/boxes (esp. for Google-Sheets add-on)
MUTATIONS_FOR_BETA_LEVEL[6] = MUTATIONS_FOR_BETA_LEVEL[5] + (
"createBeneficiaries",
"createBoxes",
)
Expand All @@ -391,20 +391,17 @@ def authorize_cross_organisation_access(
MUTATIONS_FOR_BETA_LEVEL[7] = MUTATIONS_FOR_BETA_LEVEL[6] + ("createBoxFromBox",)

# ### BETA-LEVEL 98 ###
# In addition to level 5,
# In addition to level 7,
# - actions for managing beneficiaries
# !!!
# Any new mutation should be added here
# !!!
MUTATIONS_FOR_BETA_LEVEL[98] = MUTATIONS_FOR_BETA_LEVEL[5] + (
MUTATIONS_FOR_BETA_LEVEL[98] = MUTATIONS_FOR_BETA_LEVEL[7] + (
"createBeneficiary",
"createBeneficiaries",
"updateBeneficiary",
"deactivateBeneficiary",
"assignTag",
"unassignTag",
"createBoxes",
"createBoxFromBox",
)

# ### BETA-LEVEL 99 ###
Expand Down
2 changes: 1 addition & 1 deletion back/test/auth0_integration_tests/test_permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,6 @@ def test_check_beta_feature_access(auth0_client):
mutation = "mutation { createQrCode { id } }"
assert_successful_request(auth0_client, mutation)

mutation = "mutation { deleteTag(id: 1) { id } }"
mutation = "mutation { updateBeneficiary(id: 1) { __typename } }"
response = assert_bad_request(auth0_client, mutation, expect_errors=True)
assert response.json["errors"] == [{"message": "Insufficient beta-level"}]
18 changes: 15 additions & 3 deletions back/test/unit_tests/test_authz.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,9 +340,9 @@ def test_check_user_beta_level():
"query { base(id: 1) { name } }", current_user=current_user
)

# Level 4 is the default, hence users with unknown level have the same permissions
# Level 5 is the default, hence users with unknown level have the same permissions
current_user._max_beta_level = 50
for mutation in ["createTag", "createBeneficiary", "createBeneficiaries"]:
for mutation in ["createBeneficiary", "createBeneficiaries", "createBoxFromBox"]:
payload = f"mutation {{ {mutation} }}"
assert not check_user_beta_level(payload, current_user=current_user)
for mutation in MUTATIONS_FOR_BETA_LEVEL[DEFAULT_MAX_BETA_LEVEL]:
Expand All @@ -367,6 +367,18 @@ def test_check_user_beta_level():
"query { base(id: 1) { name } }", current_user=current_user
)

# User with level 6 can additionally run bulk mutations
current_user._max_beta_level = 5
for mutation in ["createBeneficiary", "createBoxFromBox"]:
payload = f"mutation {{ {mutation} }}"
assert not check_user_beta_level(payload, current_user=current_user)
for mutation in MUTATIONS_FOR_BETA_LEVEL[max_beta_level]:
payload = f"mutation {{ {mutation} }}"
assert check_user_beta_level(payload, current_user=current_user)
assert check_user_beta_level(
"query { base(id: 1) { name } }", current_user=current_user
)

# More complex (non-existing) mutation with Fragments and FragmentSpreads
mutation = """
fragment BoxFields on Box {
Expand Down Expand Up @@ -394,7 +406,7 @@ def test_check_user_beta_level():

# User with level 7 can additionally run createBoxFromBox
current_user._max_beta_level = 7
for mutation in ["createTag", "createBeneficiary"]:
for mutation in ["createBeneficiary"]:
payload = f"mutation {{ {mutation} }}"
assert not check_user_beta_level(payload, current_user=current_user)
for mutation in MUTATIONS_FOR_BETA_LEVEL[max_beta_level]:
Expand Down
2 changes: 1 addition & 1 deletion docs/adr/adr_authorization-specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ The ground truth for permissions management are the Auth0 Action scripts. Any up

There are two scenarios that require an additional guarding mechanism in boxtribute v2. We introduce a series of levels, each associated with certain available app functionality. The lowest level provides the least functionality, while each of the larger levels additively builds up on the previous one. We can now assign beta-level values to individual users to control their access to certain functionality because a user can only access functionality of a beta-level smaller or equal to the user's beta-level value.

**The default beta-level value is 4 (June 2025)**. On the back-end side, this is controlled in the `authz` module:
**The default beta-level value is 5 (April 2026)**. On the back-end side, this is controlled in the `authz` module:
- on [staging](https://github.com/boxwise/boxtribute/blob/master/back/boxtribute_server/authz.py#L310)
- on [production](https://github.com/boxwise/boxtribute/blob/production/back/boxtribute_server/authz.py#L310)

Expand Down
Loading