Skip to content

Commit

Permalink
feat: override permissions for exporting a taxonomy (#33483)
Browse files Browse the repository at this point in the history
  • Loading branch information
rpenido authored Oct 16, 2023
1 parent 9bf042b commit bbb7ef8
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -270,18 +270,18 @@ def test_list_invalid_page(self):
assert response.status_code == status.HTTP_404_NOT_FOUND

@ddt.data(
(None, "ot1", status.HTTP_403_FORBIDDEN),
(None, "ot2", status.HTTP_403_FORBIDDEN),
(None, "st1", status.HTTP_403_FORBIDDEN),
(None, "st2", status.HTTP_403_FORBIDDEN),
(None, "t1", status.HTTP_403_FORBIDDEN),
(None, "t2", status.HTTP_403_FORBIDDEN),
(None, "tA1", status.HTTP_403_FORBIDDEN),
(None, "tA2", status.HTTP_403_FORBIDDEN),
(None, "tB1", status.HTTP_403_FORBIDDEN),
(None, "tB2", status.HTTP_403_FORBIDDEN),
(None, "tC1", status.HTTP_403_FORBIDDEN),
(None, "tC2", status.HTTP_403_FORBIDDEN),
(None, "ot1", status.HTTP_401_UNAUTHORIZED),
(None, "ot2", status.HTTP_401_UNAUTHORIZED),
(None, "st1", status.HTTP_401_UNAUTHORIZED),
(None, "st2", status.HTTP_401_UNAUTHORIZED),
(None, "t1", status.HTTP_401_UNAUTHORIZED),
(None, "t2", status.HTTP_401_UNAUTHORIZED),
(None, "tA1", status.HTTP_401_UNAUTHORIZED),
(None, "tA2", status.HTTP_401_UNAUTHORIZED),
(None, "tB1", status.HTTP_401_UNAUTHORIZED),
(None, "tB2", status.HTTP_401_UNAUTHORIZED),
(None, "tC1", status.HTTP_401_UNAUTHORIZED),
(None, "tC2", status.HTTP_401_UNAUTHORIZED),
("user", "ot1", status.HTTP_200_OK),
("user", "ot2", status.HTTP_404_NOT_FOUND),
("user", "st1", status.HTTP_200_OK),
Expand Down Expand Up @@ -336,7 +336,7 @@ def test_detail_taxonomy(self, user_attr, taxonomy_attr, expected_status):
check_taxonomy(response.data, taxonomy.pk, **(TaxonomySerializer(taxonomy.cast()).data))

@ddt.data(
(None, status.HTTP_403_FORBIDDEN),
(None, status.HTTP_401_UNAUTHORIZED),
("user", status.HTTP_403_FORBIDDEN),
("userA", status.HTTP_403_FORBIDDEN),
("userS", status.HTTP_201_CREATED),
Expand Down Expand Up @@ -368,18 +368,18 @@ def test_create_taxonomy(self, user_attr, expected_status):
check_taxonomy(response.data, response.data["id"], **create_data)

@ddt.data(
(None, "ot1", status.HTTP_403_FORBIDDEN),
(None, "ot2", status.HTTP_403_FORBIDDEN),
(None, "st1", status.HTTP_403_FORBIDDEN),
(None, "st2", status.HTTP_403_FORBIDDEN),
(None, "t1", status.HTTP_403_FORBIDDEN),
(None, "t2", status.HTTP_403_FORBIDDEN),
(None, "tA1", status.HTTP_403_FORBIDDEN),
(None, "tA2", status.HTTP_403_FORBIDDEN),
(None, "tB1", status.HTTP_403_FORBIDDEN),
(None, "tB2", status.HTTP_403_FORBIDDEN),
(None, "tC1", status.HTTP_403_FORBIDDEN),
(None, "tC2", status.HTTP_403_FORBIDDEN),
(None, "ot1", status.HTTP_401_UNAUTHORIZED),
(None, "ot2", status.HTTP_401_UNAUTHORIZED),
(None, "st1", status.HTTP_401_UNAUTHORIZED),
(None, "st2", status.HTTP_401_UNAUTHORIZED),
(None, "t1", status.HTTP_401_UNAUTHORIZED),
(None, "t2", status.HTTP_401_UNAUTHORIZED),
(None, "tA1", status.HTTP_401_UNAUTHORIZED),
(None, "tA2", status.HTTP_401_UNAUTHORIZED),
(None, "tB1", status.HTTP_401_UNAUTHORIZED),
(None, "tB2", status.HTTP_401_UNAUTHORIZED),
(None, "tC1", status.HTTP_401_UNAUTHORIZED),
(None, "tC2", status.HTTP_401_UNAUTHORIZED),
("user", "ot1", status.HTTP_403_FORBIDDEN),
("user", "ot2", status.HTTP_403_FORBIDDEN),
("user", "st1", status.HTTP_403_FORBIDDEN),
Expand Down Expand Up @@ -465,18 +465,18 @@ def test_update_taxonomy_system_defined(self, update_value, expected_status):
assert response.data["system_defined"] is True

@ddt.data(
(None, "ot1", status.HTTP_403_FORBIDDEN),
(None, "ot2", status.HTTP_403_FORBIDDEN),
(None, "st1", status.HTTP_403_FORBIDDEN),
(None, "st2", status.HTTP_403_FORBIDDEN),
(None, "t1", status.HTTP_403_FORBIDDEN),
(None, "t2", status.HTTP_403_FORBIDDEN),
(None, "tA1", status.HTTP_403_FORBIDDEN),
(None, "tA2", status.HTTP_403_FORBIDDEN),
(None, "tB1", status.HTTP_403_FORBIDDEN),
(None, "tB2", status.HTTP_403_FORBIDDEN),
(None, "tC1", status.HTTP_403_FORBIDDEN),
(None, "tC2", status.HTTP_403_FORBIDDEN),
(None, "ot1", status.HTTP_401_UNAUTHORIZED),
(None, "ot2", status.HTTP_401_UNAUTHORIZED),
(None, "st1", status.HTTP_401_UNAUTHORIZED),
(None, "st2", status.HTTP_401_UNAUTHORIZED),
(None, "t1", status.HTTP_401_UNAUTHORIZED),
(None, "t2", status.HTTP_401_UNAUTHORIZED),
(None, "tA1", status.HTTP_401_UNAUTHORIZED),
(None, "tA2", status.HTTP_401_UNAUTHORIZED),
(None, "tB1", status.HTTP_401_UNAUTHORIZED),
(None, "tB2", status.HTTP_401_UNAUTHORIZED),
(None, "tC1", status.HTTP_401_UNAUTHORIZED),
(None, "tC2", status.HTTP_401_UNAUTHORIZED),
("user", "ot1", status.HTTP_403_FORBIDDEN),
("user", "ot2", status.HTTP_403_FORBIDDEN),
("user", "st1", status.HTTP_403_FORBIDDEN),
Expand Down Expand Up @@ -560,18 +560,18 @@ def test_patch_taxonomy_system_defined(self, update_value, expected_status):
assert response.data["system_defined"] is True

@ddt.data(
(None, "ot1", status.HTTP_403_FORBIDDEN),
(None, "ot2", status.HTTP_403_FORBIDDEN),
(None, "st1", status.HTTP_403_FORBIDDEN),
(None, "st2", status.HTTP_403_FORBIDDEN),
(None, "t1", status.HTTP_403_FORBIDDEN),
(None, "t2", status.HTTP_403_FORBIDDEN),
(None, "tA1", status.HTTP_403_FORBIDDEN),
(None, "tA2", status.HTTP_403_FORBIDDEN),
(None, "tB1", status.HTTP_403_FORBIDDEN),
(None, "tB2", status.HTTP_403_FORBIDDEN),
(None, "tC1", status.HTTP_403_FORBIDDEN),
(None, "tC2", status.HTTP_403_FORBIDDEN),
(None, "ot1", status.HTTP_401_UNAUTHORIZED),
(None, "ot2", status.HTTP_401_UNAUTHORIZED),
(None, "st1", status.HTTP_401_UNAUTHORIZED),
(None, "st2", status.HTTP_401_UNAUTHORIZED),
(None, "t1", status.HTTP_401_UNAUTHORIZED),
(None, "t2", status.HTTP_401_UNAUTHORIZED),
(None, "tA1", status.HTTP_401_UNAUTHORIZED),
(None, "tA2", status.HTTP_401_UNAUTHORIZED),
(None, "tB1", status.HTTP_401_UNAUTHORIZED),
(None, "tB2", status.HTTP_401_UNAUTHORIZED),
(None, "tC1", status.HTTP_401_UNAUTHORIZED),
(None, "tC2", status.HTTP_401_UNAUTHORIZED),
("user", "ot1", status.HTTP_403_FORBIDDEN),
("user", "ot2", status.HTTP_403_FORBIDDEN),
("user", "st1", status.HTTP_403_FORBIDDEN),
Expand Down Expand Up @@ -695,24 +695,24 @@ def setUp(self):

@ddt.data(
# userA and userS are staff in courseA and can tag using enabled taxonomies
(None, "tA1", ["Tag 1"], status.HTTP_403_FORBIDDEN),
(None, "tA1", ["Tag 1"], status.HTTP_401_UNAUTHORIZED),
("user", "tA1", ["Tag 1"], status.HTTP_403_FORBIDDEN),
("userA", "tA1", ["Tag 1"], status.HTTP_200_OK),
("userS", "tA1", ["Tag 1"], status.HTTP_200_OK),
(None, "tA1", [], status.HTTP_403_FORBIDDEN),
(None, "tA1", [], status.HTTP_401_UNAUTHORIZED),
("user", "tA1", [], status.HTTP_403_FORBIDDEN),
("userA", "tA1", [], status.HTTP_200_OK),
("userS", "tA1", [], status.HTTP_200_OK),
(None, "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_403_FORBIDDEN),
(None, "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_401_UNAUTHORIZED),
("user", "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_403_FORBIDDEN),
("userA", "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_200_OK),
("userS", "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_200_OK),
(None, "open_taxonomy", ["tag1"], status.HTTP_403_FORBIDDEN),
(None, "open_taxonomy", ["tag1"], status.HTTP_401_UNAUTHORIZED),
("user", "open_taxonomy", ["tag1"], status.HTTP_403_FORBIDDEN),
("userA", "open_taxonomy", ["tag1"], status.HTTP_200_OK),
("userS", "open_taxonomy", ["tag1"], status.HTTP_200_OK),
# Only userS is Tagging Admin and can tag objects using disabled taxonomies
(None, "tA2", ["Tag 1"], status.HTTP_403_FORBIDDEN),
(None, "tA2", ["Tag 1"], status.HTTP_401_UNAUTHORIZED),
("user", "tA2", ["Tag 1"], status.HTTP_403_FORBIDDEN),
("userA", "tA2", ["Tag 1"], status.HTTP_403_FORBIDDEN),
("userS", "tA2", ["Tag 1"], status.HTTP_200_OK),
Expand All @@ -736,11 +736,11 @@ def test_tag_course(self, user_attr, taxonomy_attr, tag_values, expected_status)

@ddt.data(
# Can't add invalid tags to a object using a closed taxonomy
(None, "tA1", ["invalid"], status.HTTP_403_FORBIDDEN),
(None, "tA1", ["invalid"], status.HTTP_401_UNAUTHORIZED),
("user", "tA1", ["invalid"], status.HTTP_403_FORBIDDEN),
("userA", "tA1", ["invalid"], status.HTTP_400_BAD_REQUEST),
("userS", "tA1", ["invalid"], status.HTTP_400_BAD_REQUEST),
(None, "multiple_taxonomy", ["invalid"], status.HTTP_403_FORBIDDEN),
(None, "multiple_taxonomy", ["invalid"], status.HTTP_401_UNAUTHORIZED),
("user", "multiple_taxonomy", ["invalid"], status.HTTP_403_FORBIDDEN),
("userA", "multiple_taxonomy", ["invalid"], status.HTTP_400_BAD_REQUEST),
("userS", "multiple_taxonomy", ["invalid"], status.HTTP_400_BAD_REQUEST),
Expand All @@ -763,24 +763,24 @@ def test_tag_course_invalid(self, user_attr, taxonomy_attr, tag_values, expected

@ddt.data(
# userA and userS are staff in courseA (owner of xblockA) and can tag using enabled taxonomies
(None, "tA1", ["Tag 1"], status.HTTP_403_FORBIDDEN),
(None, "tA1", ["Tag 1"], status.HTTP_401_UNAUTHORIZED),
("user", "tA1", ["Tag 1"], status.HTTP_403_FORBIDDEN),
("userA", "tA1", ["Tag 1"], status.HTTP_200_OK),
("userS", "tA1", ["Tag 1"], status.HTTP_200_OK),
(None, "tA1", [], status.HTTP_403_FORBIDDEN),
(None, "tA1", [], status.HTTP_401_UNAUTHORIZED),
("user", "tA1", [], status.HTTP_403_FORBIDDEN),
("userA", "tA1", [], status.HTTP_200_OK),
("userS", "tA1", [], status.HTTP_200_OK),
(None, "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_403_FORBIDDEN),
(None, "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_401_UNAUTHORIZED),
("user", "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_403_FORBIDDEN),
("userA", "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_200_OK),
("userS", "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_200_OK),
(None, "open_taxonomy", ["tag1"], status.HTTP_403_FORBIDDEN),
(None, "open_taxonomy", ["tag1"], status.HTTP_401_UNAUTHORIZED),
("user", "open_taxonomy", ["tag1"], status.HTTP_403_FORBIDDEN),
("userA", "open_taxonomy", ["tag1"], status.HTTP_200_OK),
("userS", "open_taxonomy", ["tag1"], status.HTTP_200_OK),
# Only userS is Tagging Admin and can tag objects using disabled taxonomies
(None, "tA2", ["Tag 1"], status.HTTP_403_FORBIDDEN),
(None, "tA2", ["Tag 1"], status.HTTP_401_UNAUTHORIZED),
("user", "tA2", ["Tag 1"], status.HTTP_403_FORBIDDEN),
("userA", "tA2", ["Tag 1"], status.HTTP_403_FORBIDDEN),
("userS", "tA2", ["Tag 1"], status.HTTP_200_OK),
Expand All @@ -804,11 +804,11 @@ def test_tag_xblock(self, user_attr, taxonomy_attr, tag_values, expected_status)

@ddt.data(
# Can't add invalid tags to a object using a closed taxonomy
(None, "tA1", ["invalid"], status.HTTP_403_FORBIDDEN),
(None, "tA1", ["invalid"], status.HTTP_401_UNAUTHORIZED),
("user", "tA1", ["invalid"], status.HTTP_403_FORBIDDEN),
("userA", "tA1", ["invalid"], status.HTTP_400_BAD_REQUEST),
("userS", "tA1", ["invalid"], status.HTTP_400_BAD_REQUEST),
(None, "multiple_taxonomy", ["invalid"], status.HTTP_403_FORBIDDEN),
(None, "multiple_taxonomy", ["invalid"], status.HTTP_401_UNAUTHORIZED),
("user", "multiple_taxonomy", ["invalid"], status.HTTP_403_FORBIDDEN),
("userA", "multiple_taxonomy", ["invalid"], status.HTTP_400_BAD_REQUEST),
("userS", "multiple_taxonomy", ["invalid"], status.HTTP_400_BAD_REQUEST),
Expand Down
1 change: 1 addition & 0 deletions openedx/core/djangoapps/content_tagging/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def can_change_taxonomy_tag(user: UserType, tag: oel_tagging.Tag | None = None)
rules.set_perm("oel_tagging.change_taxonomy", oel_tagging.can_change_taxonomy)
rules.set_perm("oel_tagging.delete_taxonomy", oel_tagging.can_change_taxonomy)
rules.set_perm("oel_tagging.view_taxonomy", oel_tagging.can_view_taxonomy)
rules.set_perm("oel_tagging.export_taxonomy", oel_tagging.can_view_taxonomy)

# Tag
rules.set_perm("oel_tagging.add_tag", can_change_taxonomy_tag)
Expand Down
2 changes: 1 addition & 1 deletion requirements/constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ libsass==0.10.0
click==8.1.6

# pinning this version to avoid updates while the library is being developed
openedx-learning==0.2.3
openedx-learning==0.2.4

# lti-consumer-xblock 9.6.2 contains a breaking change that makes
# existing custom parameter configurations unusable.
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,7 @@ openedx-filters==1.6.0
# via
# -r requirements/edx/kernel.in
# lti-consumer-xblock
openedx-learning==0.2.3
openedx-learning==0.2.4
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/kernel.in
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/development.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1318,7 +1318,7 @@ openedx-filters==1.6.0
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# lti-consumer-xblock
openedx-learning==0.2.3
openedx-learning==0.2.4
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/doc.txt
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/doc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ openedx-filters==1.6.0
# via
# -r requirements/edx/base.txt
# lti-consumer-xblock
openedx-learning==0.2.3
openedx-learning==0.2.4
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/testing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -992,7 +992,7 @@ openedx-filters==1.6.0
# via
# -r requirements/edx/base.txt
# lti-consumer-xblock
openedx-learning==0.2.3
openedx-learning==0.2.4
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt
Expand Down

0 comments on commit bbb7ef8

Please sign in to comment.