Skip to content

Documents Tagging architecture decisions - #55

Merged
ormsbee merged 9 commits into
openedx:mainfrom
open-craft:jill/tagging-data-arch-adr
Jun 13, 2023
Merged

Documents Tagging architecture decisions#55
ormsbee merged 9 commits into
openedx:mainfrom
open-craft:jill/tagging-data-arch-adr

Conversation

@pomegranited

@pomegranited pomegranited commented Jun 1, 2023

Copy link
Copy Markdown
Contributor

This PR documents the decisions that arose from openedx/modular-learning#60.

It also builds on #54 and enforces ADR 7. Tagging app structure by moving the tagging app to a separate package outside of openedx_learning, called openedx_tagging. The models in this app will be altered and aligned with the other ADRs as part of subsequent PRs.

Testing instructions

  1. When running the automated tests, check that the openedx_tagging test runs.
  2. Check the added ADRs for clarity and correctness.

Supporting information

Closes openedx/modular-learning#60

@openedx-webhooks openedx-webhooks added the open-source-contribution PR author is not from Axim or 2U label Jun 1, 2023
@openedx-webhooks

Copy link
Copy Markdown

Thanks for the pull request, @pomegranited! Please note that it may take us up to several weeks or months to complete a review and merge your PR.

Feel free to add as much of the following information to the ticket as you can:

  • supporting documentation
  • Open edX discussion forum threads
  • timeline information ("this must be merged by XX date", and why that is)
  • partner information ("this is a course on edx.org")
  • any other information that can help Product understand the context for the PR

All technical communication about the code itself will be done via the GitHub pull request interface. As a reminder, our process documentation is here.

Please let us know once your PR is ready for our review and all tests are green.

@pomegranited
pomegranited force-pushed the jill/tagging-data-arch-adr branch from f7837f5 to 2182b55 Compare June 1, 2023 07:19
@ChrisChV

ChrisChV commented Jun 1, 2023

Copy link
Copy Markdown
Contributor

@pomegranited Great work! 👍

I think we need also to specify how will the link with the contents be handled. I have seen that ContenTag is mentioned in the ADRs, but I feel that it has to be specified more. Specify that we have to create subclasses of ObjectTag to link the content, like ContentTag or the class to link the learning core content.


Permission #1 requires no external access, so can be enforced by the ``openedx_tagging`` app.

But because permissions #2 + #3 require access to the edx-platform CMS model `CourseCreator`_, this access can only be enforced in Studio, and so will live under `cms.djangoapps.tagging` along with the ``ContentTag`` class. Tagging MVP must work for libraries v1, v2 and courses created in Studio, and so tying these permissions to Studio is reasonable for the MVP.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per OEP-9, these three rules that you listed above can be defined using rules... with #1 defined in openedx_tagging and #2 and #3 defined in Studio. I think that what that gets us is that any application can then use the standard Django API to query things like user.has_perm('openedx_tagging.edit_taxonomy', taxonomy) and get the right result without needing to be aware of how those permissions are defined or even where they are defined (in Studio).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be really cool @bradenmacdonald , but can django-rules handle chaining multiple rule definitions together?

Ref rules.RuleSet:

  • add_rule raises a KeyError if another rule by that name already exists.
  • set_rule sets the rule, regardless of whether one already exists

But I don't see how to combine them?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pomegranited Isn't combining rules what you mean? It supports combining rules with "and", "or", "not", etc.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bradenmacdonald Yes, we can combine rules logically and explicitly -- what I meant was, there's no magic provided by django or django-rules to chain these calls to set_rule.

It's totally doable, it just takes a little care. For example:

  1. openedx_tagging calls set_rule('openedx_tagging.edit_taxonomy', can_edit_taxonomy) where can_edit_taxonomy checks e.g user.is_staff | user.is_superuser. This is fine, openedx_tagging can stand alone.
  2. openedx.features.tagging.SystemTaxonomy might want to call set_rule('openedx_tagging.edit_taxonomy', can_edit_taxonomy) too, where its can_edit_taxonomy disallows editing for all SystemTaxonomy no matter who you are.
  3. openedx.features.tagging.OrgTaxonomy might want to call set_rule('openedx_tagging.edit_taxonomy', can_edit_taxonomy) too, where its can_edit_taxonomy checks openedx_tagging.can_edit_taxonomy and the user's rights against the OrgTaxonomy.org.

But they can't all pile on and call set_rule, because the most recently called set_rule wins.

So to make sure user.has_perm('openedx_tagging.edit_taxonomy', taxonomy) returns the right thing, the openedx.features.tagging rules must be aware of its different Taxonomy subclasses, and explicitly combine with the openedx_tagging rules where needed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pomegranited Ah, I see. Yeah it's too bad there's not a nice API for combining those. maybe we can add a lightweight way to do that?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bradenmacdonald Sure, will see.. I'll start by trying to use consistent convention, and if it ends up being abstractable into something we can reuse, that would be awesome :) Thanks for pointing me to OEP-9 here, and clarifying the end goal of these permission rules.

Instance
~~~~~~~~

A Taxonomy can be enabled/disabled for all contexts using its ``enabled`` flag.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to be clarified. It sounds like this is saying "the taxonomy can be enabled for all contexts (forced on for all courses, regardless of other settings) when enabled=True or disabled for all contexts (forced off for all courses, regardless of other settings) when enabled=False". We either need a third state (can be selectively enabled/disabled at other levels when this is set to None), or make this into either a "global disable" or "global enable" boolean, but not both. I hope that makes sense.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"""

# Content id to which this tag is associated
content_id = models.CharField(max_length=255)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think some namespacing spec is required here.

What if I want to tag a user, which has a numeric ID? Should we specify the format for this field? Perhaps that it's always an "Opaque Key" serialized as a string, or that if it's not an opaque key, it's a similarly prefixed string like "user:15" ?

@pomegranited pomegranited Jun 7, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this model is going to change substantially when we start implementation -- I just included it here because #54 adds it, and I needed to move it under openedx_tagging.

But re your comment: I'd rather add a short string content_type field than prefix the content_id -- or in terms of the ObjectTag class that will ultimately be the base class for ContentTag, I'd rather use object_type and object_id fields.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bradenmacdonald Thoughts on ^?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that sounds good! As long as it's namespaced in some way.

@pomegranited
pomegranited force-pushed the jill/tagging-data-arch-adr branch from 184962d to 9f38046 Compare June 7, 2023 01:05
@pomegranited

Copy link
Copy Markdown
Contributor Author

Thank you for your feedback @ChrisChV @bradenmacdonald -- I've addressed what I can from your comments, and from watching the meeting on 6 June. @ormsbee did you have any comments or changes needed here?

I guess I'm also not sure how much of the data model document needs to be enshrined in ADRs, and how much can be done when we do the implementation.. Is there anything missing that should be in here?

@ormsbee ormsbee left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor question about taxonomy enablement. It doesn't need to block merging.

Comment thread docs/decisions/0007-tagging-app.rst Outdated
+-------------+-----------------------------+--------------------------+-------------------------------+
| True | False | True | False |
+-------------+-----------------------------+--------------------------+-------------------------------+
| True | True | False | False |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the course hasn't enabled all taxonomies, but it has enabled this specific one, shouldn't it be shown for the course?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this doesn't allow enabling taxonomies at the course level (yet)... I misunderstood this at first too, but I think tax.enabled_for(course.org) means tax.enabled_for(org) (where org comes from the course), not tax.enabled_for(course | org) as I first read this.

Comment thread setup.py
@bradenmacdonald

Copy link
Copy Markdown
Contributor

Thanks. I like how this is shaping up!

@pomegranited

Copy link
Copy Markdown
Contributor Author

@bradenmacdonald @ormsbee Thanks for your comments! I'm pretty pleased with it too :)

If you're happy with what's here, could one of you approve and squash+merge?
Or if there's more that needs to be in here, please let me know? I'm starting implementation this week.

@pomegranited

Copy link
Copy Markdown
Contributor Author

Thanks for your 👍 @bradenmacdonald :) I don't have merge rights here, so could you or @ormsbee merge if it's ready? Thank you!

@ormsbee
ormsbee merged commit f1b8579 into openedx:main Jun 13, 2023
@openedx-webhooks

Copy link
Copy Markdown

@pomegranited 🎉 Your pull request was merged! Please take a moment to answer a two question survey so we can improve your experience in the future.

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

Labels

open-source-contribution PR author is not from Axim or 2U

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

[Tagging] Architectural Discovery: Data models for taxonomies

5 participants