Skip to content

[Tagging] Taxonomies for Org API #74

Closed
openedx/openedx-platform
#32871

Description

@pomegranited

Story

"As a content author, I want to see all the taxonomies available for use with my course, block, or library, so that I can tag my content."

Description

Implement a Python and a REST API that allows retrieving the full list of taxonomies given a certain block/context.
This API will be used to fetch the taxonomies relevant to creating/editing content on Studio.

Note: this API should be marked as “unstable” for the MVP.

Completion criteria

Build on/subclass the "taxonomy REST API view" added by #73, and implement this REST API endpoint:

/api/content_tagging/v1/taxonomy?org=<org>&enabled=True|False&page_size=<size>&page=1

  • Returns a paginated list of Taxonomy metadata (including their pks), with the same fields and serializers as the "oel_tagging taxonomy list view".
  • Always returns the system-defined and instance-wide Taxonomies (subject to the enabled parameter)
  • org parameter: (optional) Organization short name
    • Limits the returned taxonomies to the ones that are "owned by" the requested .
  • (optional) enabled parameter: bool (same behavior as [Tagging] Taxonomy view/management APIs #73)
    • If omitted, then returns both enabled and disabled Taxonomies.
    • If True, then returns only enabled Taxonomies
    • If False, then returns only disabled Taxonomies
  • Paginate this data, with a default MAX_PAGE_SIZE = 100, to allow most people to retrieve all of their taxonomies in one hit.
    People with more taxonomies will need to know where to go to get their next page of data, and so this endpoint should support that too.

Note: it's ok to adjust the openedx.features.content_tagging.rules to meet the behavioral requirements noted below.

Automated testing must cover common paths in behavioral specification.

Pagination

You're welcome to rename the pagination parameters and data specified here to whatever is the standard recommended by DRF Pagination or Django Pagination.

For your tests, feel free to set a more reasonable MAX_PAGE_SIZE to test the next page behavior.

Behavioral specifications

Suppose the Open edX instance has these taxonomies:

  • system-defined taxonomies: st1 (enabled), st2 (disabled)
  • 1 instance-wide taxonomy: t1 (enabled), t2 (disabled)
  • 2 taxonomies owned by organization A: tA1 (enabled), tA2 (disabled)
  • 2 taxonomies owned by organization B: tB1 (enabled), tB2 (disabled)
  • 2 taxonomies owned by both organizations A & B: tC1 (enabled), tC2 (disabled)

and the following users:

  • userA: ordinary, non-staff user

  • userS: global staff user

  • Anyone can view an enabled taxonomy or its tags

  • Only superusers or global staff can view a disabled taxonomy or its tags.

  • Only superusers or global staff can assign orgs to a taxonomy.
    These assigned "orgs" will be used to filter which taxonomies returned when the org parameter is provided for the list view, but don't affect taxonomy/tag permissions.

  • No users can add/edit/delete a system-defined taxonomy.

  • Only superusers or global staff can add/edit/delete a taxonomy (so long as it isn't system-defined)

  • Only superusers can add/edit/delete tags on a taxonomy (where allow_free_text=False)

  • No users can add/edit/delete tags on a free text taxonomy.

/api/content_tagging/v1/taxonomy/ -- returns all taxonomies the user is allowed to view.

  • When userA requests ^, they receive taxonomy metadata for these taxonomies: s1, t1, tA1, tB1, tC1
  • When userS requests ^ they receive taxonomy metadata for these taxonomies: s1, s2, t1, t2, tA1, tA2, tB1, tB2, tC1, tC2

/api/content_tagging/v1/taxonomy/context/?enabled=True -- returns enabled taxonomies the user is allowed to view.

  • When userA or userS requests ^, they receive taxonomy metadata for these taxonomies: s1, t1, tA1, tB1, tC1

/api/content_tagging/v1/taxonomy/context/?enabled=False -- returns disabled taxonomies the user is allowed to view.

  • When userA requests ^, they receive no taxonomy metadata at all
  • When userS requests ^ they receive taxonomy metadata for these taxonomies: s2, t2, tA2, tB2, tC2

/api/content_tagging/v1/taxonomy/?org=A -- returns taxonomies the user is allowed to view which are configured for use with content owned by org A

  • When userA requests ^, they receive taxonomy metadata for these taxonomies: s1, t1, tA1, tA2, tC1, tC2
  • When userS requests ^ they receive taxonomy metadata for these taxonomies: s1, s2, t1, t2, tA1, tA2, tC1, tC2

/api/content_tagging/v1/taxonomy/?org=B -- returns taxonomies the user is allowed to view which are configured for use with content owned by org B

  • When userA requests ^, they receive taxonomy metadata for these taxonomies: s1, t1, tB1, tB2, tC1, tC2
  • When userS requests ^ they receive taxonomy metadata for these taxonomies: s1, s2, t1, t2, tB1, tB2, tC1, tC2

/api/content_tagging/v1/taxonomy/?org=A&enabled=True -- returns enabled taxonomies the user is allowed to view which are configured for use with content owned by org A

  • When userA requests ^, they receive taxonomy metadata for these taxonomies: s1, t1, tA1, tC1
  • When userS requests ^ they receive taxonomy metadata for these taxonomies: s1, t1, tA1, tC1

/api/content_tagging/v1/taxonomy/?org=A&enabled=False -- returns disabled taxonomies the user is allowed to view which are configured for use with content owned by org A (No explicit use case exists for this combination, but it's included here for completeness.)

  • When userA requests ^, they receive no taxonomy metadata at all
  • When userS requests ^ they receive taxonomy metadata for these taxonomies: s2, t2, tA2, tC2

/api/content_tagging/v1/taxonomy/?org=X -- returns taxonomies the user is allowed to view which are configured for use with content owned by org X.
But there are no taxonomies configured for use with org X -- org X may not even exist -- and so only returns:

  • When userA requests ^, they receive taxonomy metadata for these taxonomies: s1, t1
  • When userS requests ^ they receive taxonomy metadata for these taxonomies: s1, s2, t1, t2

/api/content_tagging/v1/taxonomy/?page_size=2&page=3 -- returns "page 3 of the taxonomies the user is allowed to view.
Since we've specified page_size=2, we'd see the following returned taxonomies here:

  • When userA requests ^, they receive taxonomy metadata for these taxonomies: tC1
  • When userS requests ^ they receive taxonomy metadata for these taxonomies: tA1, tA2 (with next url providing page=4)

Documentation updates & improvements criteria

  • API endpoint and its parameters should be well-documented

Relevant PRs/repositories

Activity

  1. changed the title [-]Taxonomy view API[/-] [+][Tagging] Taxonomy view API[/+] on Jul 20, 2023
  2. changed the title [-][Tagging] Taxonomy view API[/-] [+][Tagging] Taxonomies for Org API[/+] on Jul 20, 2023
  3. rpenido commented on Jul 25, 2023

    @rpenido

    /api/content_tagging/v1/taxonomy/ -- returns all taxonomies the user is allowed to view.

    • When userA requests ^, they receive taxonomy metadata for these taxonomies: s1, t1, tA1, tA2, tC1, tC2
    • When userB requests ^, they receive taxonomy metadata for these taxonomies: s1, t1, tA1, tB1, tB2, tC1, tC2

    Hi @pomegranited!
    I think that is a typo here. It should be either:

    • When userA requests ^, they receive taxonomy metadata for these taxonomies: s1, t1, tA1, tA2, tB1, tC1, tC2
    • When userB requests ^, they receive taxonomy metadata for these taxonomies: s1, t1, tA1, tB1, tB2, tC1, tC2

    Or:

    • When userA requests ^, they receive taxonomy metadata for these taxonomies: s1, t1, tA1, tA2, tC1, tC2
    • When userB requests ^, they receive taxonomy metadata for these taxonomies: s1, t1, tA1, tB1, tB2, tC1, tC2

    I supose the former, right?

  4. pomegranited commented on Jul 26, 2023

    @pomegranited
    Author

    Good catch, thank you @rpenido ! Issue updated with your first suggestion.

  5. rpenido commented on Jul 28, 2023

    @rpenido

    /api/content_tagging/v1/taxonomy/?org=X -- returns taxonomies the user is allowed to view which are configured for use with content owned by org X. But there are no taxonomies configured for use with org X -- org X may not even exist -- and so only returns:

    • When userA requests ^, they receive taxonomy metadata for these taxonomies: s1, t1
    • When userB requests ^, they receive taxonomy metadata for these taxonomies: s1, t1
    • When userC requests ^, they receive taxonomy metadata for these taxonomies: s1, t1
    • When userS requests ^ they receive taxonomy metadata for these taxonomies: s1, s2, t1, t2

    What about returning 400 with {'org': [ErrorDetail(string='Invalid organization short name', code='invalid')]} message in case orgX doesn't exist here?

  6. pomegranited commented on Aug 1, 2023

    @pomegranited
    Author

    @rpenido I'm not sure.. it's ok to return a 400 for now, and if we need to change it to return an empty list, we can do that later.

  7. pomegranited commented on Aug 9, 2023

    @pomegranited
    Author

    I updated this issue with the effects of Product's amendment to our interpretation of taxonomy permissions:

    we don't want to open up the possibility for anyone who can create a course to also create or edit a taxonomy. It needs to be more limited than that, so confining it to a superuser admin and global staff might be the best way forward

  8. rpenido commented on Aug 9, 2023

    @rpenido

    Hi @pomegranited!

    Some small questions:


    • userA: ordinary, non-staff user

    This should be

    • userA: content creator for orgA, non-staff user

    This doesn't change anything for the Taxonomy API, but only content creators will tag objects, right?


    Is ok to restrict the list by user org?

    /api/content_tagging/v1/taxonomy/ -- returns all taxonomies the user is allowed to view.

    • When userA requests ^, they receive taxonomy metadata for these taxonomies: s1, t1, tA1, tB1, tC1

    • When userS requests ^ they receive taxonomy metadata for these taxonomies: s1, s2, t1, t2, tA1, tA2, tB1, tB2, tC1, tC2

    /api/content_tagging/v1/taxonomy/ -- returns all taxonomies the user is allowed to view.

    • When userA requests ^, they receive taxonomy metadata for these taxonomies: s1, t1, tA1, tC1
    • When userS requests ^ they receive taxonomy metadata for these taxonomies: s1, s2, t1, t2, tA1, tA2, tB1, tB2, tC1, tC2

    /api/content_tagging/v1/taxonomy/context/?enabled=True -- returns enabled taxonomies the user is allowed to view.

    • When userA or userS requests ^, they receive taxonomy metadata for these taxonomies: s1, t1, tA1, tB1, tC1

    /api/content_tagging/v1/taxonomy/context/?enabled=True -- returns enabled taxonomies the user is allowed to view.

    • When userA or userS requests ^, they receive taxonomy metadata for these taxonomies: s1, t1, tA1, tC1
  9. pomegranited commented on Aug 9, 2023

    @pomegranited
    Author

    @rpenido

    This doesn't change anything for the Taxonomy API, but only content creators will tag objects, right?

    Correct -- users will have to be "content creators for the content object's org" in order to tag objects.

    Is ok to restrict the list by user org?

    No.

    There is no need to involve the user's orgs here at all. It simplifies/speeds up the queries, and keeps the code simple too. This data is not protected or precious, so we don't need to treat it as such.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions