feat: authorize tags and taxonomies endpoints via openedx-authz when …#38292
feat: authorize tags and taxonomies endpoints via openedx-authz when …#38292wgu-taylor-payne wants to merge 1 commit intoopenedx:masterfrom
Conversation
|
Thanks for the pull request, @wgu-taylor-payne! This repository is currently maintained by Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review. 🔘 Get product approvalIf you haven't already, check this list to see if your contribution needs to go through the product review process.
🔘 Provide contextTo help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:
🔘 Get a green buildIf one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green. 🔘 Update the status of your PRYour PR is currently marked as a draft. After completing the steps above, update its status by clicking "Ready for Review", or removing "WIP" from the title, as appropriate. Where can I find more information?If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources: When can I expect my changes to be merged?Our goal is to get community contributions seen and reviewed as efficiently as possible. However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:
💡 As a result it may take up to several weeks or months to complete a review and merge your PR. |
df1a06b to
d1ae95c
Compare
…flag is enabled Add RBAC permission checks (courses.manage_tags, courses.manage_taxonomies) to content tagging API endpoints behind AUTHZ_COURSE_AUTHORING_FLAG. Non-course-scoped taxonomy endpoints check the global flag; course-scoped object_tags endpoints check per-course. Serializer permission fields (can_change_taxonomy, can_delete_taxonomy, can_tag_object) are authz-aware so the frontend needs no changes. Co-authored-by: Kiro <kiro-noreply@amazon.com>
d1ae95c to
c26f972
Compare
Description
Adds openedx-authz permission checks (
courses.manage_tagsandcourses.manage_taxonomies) to all content tagging API endpoints, behind the existingAUTHZ_COURSE_AUTHORING_FLAGfeature flag. When the flag is off, behavior is unchanged — all endpoints use the existing legacydjango-rulespermission checks.Key design decisions:
Non-course-scoped taxonomy endpoints (e.g.,
GET /taxonomies/,DELETE /taxonomies/{id}/,POST /taxonomies/import/) check the flag globally viaAUTHZ_COURSE_AUTHORING_FLAG.is_enabled()with nocourse_key. This means authz only activates for these endpoints when the flag is enabled for everyone — not when it's enabled for a single course via override.Course-scoped object_tags endpoints (
PUT /object_tags/{course_id}/) check the flag per-course viaAUTHZ_COURSE_AUTHORING_FLAG.is_enabled(course_key), respecting course and org overrides.For non-course-scoped authz checks, we use
get_scopes_for_user_and_permission()to verify the user has the permission in any scope, since there's no specificcourse_keyto check against. This aligns with the Casbin policy wherecourse_staffhasmanage_tagsforcourse-v1^*andcourse_adminhasmanage_taxonomiesforcourse-v1^*.When authz is globally enabled,
TaxonomyOrgView.get_permissions()replaces the parent'sDjangoObjectPermissionswithIsAuthenticated. This prevents the legacy permission classes from blocking users who are authorized via authz but don't have legacy roles.Serializer permission fields (
can_change_taxonomy,can_delete_taxonomy,can_tag_object) are overridden inTaxonomyOrgSerializerto be authz-aware when the flag is on, and delegate to the parent's cached_can()path when the flag is off. This means the frontend adapts automatically — no frontend changes needed.Impacted user roles: Course Author, Operator (anyone managing taxonomies/tags in Studio).
Endpoint → permission mapping:
PUT /taxonomies/{id}/orgs/courses.manage_taxonomiesDELETE /taxonomies/{id}/courses.manage_taxonomiesGET /taxonomies/{id}/export/courses.manage_taxonomiesPOST /taxonomies/import/courses.manage_taxonomiesPUT /taxonomies/{id}/tags/import/plan/courses.manage_taxonomiesPUT /taxonomies/{id}/tags/import/courses.manage_tagsPUT /object_tags/{course_id}/courses.manage_tagsGET /object_tags/{course_id}/export/courses.export_tags(existing)Supporting information
Testing instructions
Flag OFF (legacy behavior unchanged):
authz.enable_course_authoringwaffle flag is inactiveFlag ON globally (taxonomy management):
authz.enable_course_authoring→ set "Everyone" to Yescourse_adminauthz role: verify delete taxonomy, update orgs, import/export all return200/201/204403GET /taxonomies/should returncan_change_taxonomy: true/falseandcan_delete_taxonomy: true/falsematching the user's authz permissionsFlag ON per-course (object tags):
authz.enable_course_authoringfor a specific course → Force Oncourse_staffauthz role for that course:PUT /object_tags/{course_id}/should succeed403Deadline
Verawood
Other information
TestTaxonomyTagsViewSet::test_taxonomy_tags_query_counthas a query count mismatch that exists on master before this PR. Not caused by these changes.course_adminhas bothmanage_tagsandmanage_taxonomies, whilecourse_staffonly hasmanage_tags. This means only course admins can manage taxonomies (create/delete/import/export/manage orgs), while course staff can manage tags (tag objects, import tags into existing taxonomies).