openedx_authz.models package#

Submodules#

openedx_authz.models.authz_migration module#

Models for tracking migration runs between legacy and AuthZ systems.

class openedx_authz.models.authz_migration.AuthzCourseAuthoringMigrationRun(*args, **kwargs)

Bases: Model

Track the status of course authoring migration tasks.

This model is used to track async migrations between the legacy CourseAccessRole system and the new AuthZ system.

exception DoesNotExist

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

completed_at

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

classmethod create_running(migration_type, scope_type, scope_key, metadata=None) → AuthzCourseAuthoringMigrationRun

Create a migration run in running state.

classmethod create_skipped(migration_type, scope_type, scope_key, metadata=None) → AuthzCourseAuthoringMigrationRun

Create a migration run in skipped state.

created_at

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

get_migration_type_display(*, field=<django.db.models.fields.CharField: migration_type>)
get_next_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=True, **kwargs)
get_next_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=True, **kwargs)
get_previous_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=False, **kwargs)
get_previous_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=False, **kwargs)
get_scope_type_display(*, field=<django.db.models.fields.CharField: scope_type>)
get_status_display(*, field=<django.db.models.fields.CharField: status>)
id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

mark_completed(*, metadata_updates=None) → AuthzCourseAuthoringMigrationRun

Mark the migration run as completed.

mark_failed(*, exception=None) → AuthzCourseAuthoringMigrationRun

Mark the migration run as failed.

mark_partial_success(*, metadata_updates=None) → AuthzCourseAuthoringMigrationRun

Mark the migration run as partially successful.

metadata

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

migration_type

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects = <django.db.models.manager.Manager object>
save(*args, **kwargs) → AuthzCourseAuthoringMigrationRun

Enforce at most one RUNNING record per (scope_type, scope_key).

MySQL does not support partial unique indexes, so this check is done at the application level. select_for_update() is used to reduce (but not fully eliminate) the race-condition window on concurrent inserts.

scope_key

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

scope_type

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

status

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

updated_at

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

class openedx_authz.models.authz_migration.MigrationType(*values)

Bases: TextChoices

Direction of migration.

FORWARD = 'forward'
ROLLBACK = 'rollback'
class openedx_authz.models.authz_migration.ScopeType(*values)

Bases: TextChoices

Type of scope being migrated.

COURSE = 'course'
ORG = 'org'
class openedx_authz.models.authz_migration.Status(*values)

Bases: TextChoices

Status of the migration task.

COMPLETED = 'completed'
FAILED = 'failed'
PARTIAL_SUCCESS = 'partial_success'
RUNNING = 'running'
SKIPPED = 'skipped'

openedx_authz.models.base module#

Shared abstract base models for the authorization framework.

These are reusable building blocks meant to remove field-level duplication across the models package. They carry no table of their own (abstract = True) and add no PII.

class openedx_authz.models.base.TimeStampedModel(*args, **kwargs)

Bases: Model

Abstract base adding self-managed created_at / updated_at timestamps.

Mirrors the created_at / updated_at convention already used across this repo (see openedx_authz.models.core and openedx_authz.models.authz_migration) rather than the created / modified names of model_utils.models.TimeStampedModel, so adopting it needs no column renames. New models should inherit this instead of repeating the two fields; existing models can migrate to it over time.

created_at is set once on insert (auto_now_add); updated_at is refreshed on every save (auto_now).

class Meta

Bases: object

abstract = False
created_at

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

get_next_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=True, **kwargs)
get_next_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=True, **kwargs)
get_previous_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=False, **kwargs)
get_previous_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=False, **kwargs)
updated_at

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

openedx_authz.models.core module#

Core models for the authorization framework.

These models will be used to store additional data about roles and permissions that are not natively supported by Casbin, so as to avoid modifying the Casbin schema that focuses on the core authorization logic.

class openedx_authz.models.core.BaseRegistryModel(*args, **kwargs)

Bases: Model

Base model that supports automatic subclass registration.

This model provides a registry mechanism for its subclasses, allowing dynamic retrieval of subclasses based on a namespace identifier.

Subclasses should define a NAMESPACE class attribute (e.g., ‘user’ for users) and implement get_or_create_for_external_key() classmethod.

class Meta

Bases: object

abstract = False
NAMESPACE: ClassVar[str] = None
classmethod get_registry() → dict[str, type[BaseRegistryModel]]

Get the registry of subclasses.

Returns:

A dictionary mapping namespace strings to subclass types.

Return type:

dict

class openedx_authz.models.core.ExtendedCasbinRule(*args, **kwargs)

Bases: Model

Extended model for Casbin rules to store additional metadata.

This model extends the CasbinRule model provided by the casbin_adapter package to include additional fields for storing metadata about each rule.

exception DoesNotExist

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

casbin_rule

Accessor to the related object on the forward side of a one-to-one relation.

In the example:

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Restaurant.place is a ForwardOneToOneDescriptor instance.

casbin_rule_id
casbin_rule_key

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

classmethod create_based_on_policy(subject, role, scope, adapter)

Helper method to create an ExtendedCasbinRule based on policy components.

Parameters:
  • subject – SubjectData object with namespaced_key and external_key

  • role – RoleData object with namespaced_key and external_key

  • scope – ScopeData object with namespaced_key and external_key

  • adapter – The Casbin adapter instance.

Returns:

The created ExtendedCasbinRule instance.

Return type:

ExtendedCasbinRule

created_at

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

description

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

get_next_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=True, **kwargs)
get_next_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=True, **kwargs)
get_previous_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=False, **kwargs)
get_previous_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=False, **kwargs)
id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

metadata

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects = <django.db.models.manager.Manager object>
scope

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

scope_id
subject

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

subject_id
updated_at

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

class openedx_authz.models.core.RoleAssignmentAudit(*args, **kwargs)

Bases: Model

Model to audit role assignments and unassignments.

This model captures the history of role assignments and unassignments for subjects within specific scopes. It can be used for auditing purposes to track changes in role assignments over time.

exception DoesNotExist

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

OPERATIONS = ('created', 'deleted')
class Operations(created, deleted)

Bases: NamedTuple

created: str

Alias for field number 0

deleted: str

Alias for field number 1

actor_id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

get_next_by_timestamp(*, field=<django.db.models.fields.DateTimeField: timestamp>, is_next=True, **kwargs)
get_operation_display(*, field=<django.db.models.fields.CharField: operation>)
get_previous_by_timestamp(*, field=<django.db.models.fields.DateTimeField: timestamp>, is_next=False, **kwargs)
id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects = <django.db.models.manager.ManagerFromRoleAssignmentAuditQuerySet object>
operation

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

role

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

property role_display: str

Role name without the namespace prefix (e.g. library_admin for role^library_admin).

scope

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

property scope_display: str

Scope key without the namespace prefix (e.g. lib:Org1:lib1 for lib^lib:Org1:lib1).

subject

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

property subject_display: str

Subject key without the namespace prefix (e.g. john_doe for user^john_doe).

timestamp

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

class openedx_authz.models.core.RoleAssignmentAuditQuerySet(model=None, query=None, using=None, hints=None)

Bases: QuerySet

QuerySet for RoleAssignmentAudit with scope-based filtering.

for_scope_namespace(namespace: str) → RoleAssignmentAuditQuerySet

Return records whose scope starts with the given namespace prefix.

Parameters:

namespace – The namespace to filter by (e.g. 'lib', 'course-v1'). Use the NAMESPACE class attribute from the corresponding ScopeData subclass (e.g. ContentLibraryData.NAMESPACE).

Returns:

Queryset filtered to records matching the scope type.

class openedx_authz.models.core.Scope(*args, **kwargs)

Bases: BaseRegistryModel

Model representing a scope in the authorization system.

This model can be extended to represent different types of scopes, such as courses or content libraries.

Subclasses should define a NAMESPACE class attribute (e.g., ‘lib’ for content libraries), a LINKED_OBJECT_FIELD naming their FK to the backing object (e.g. ‘content_library’), and implement external_key_for_object().

exception DoesNotExist

Bases: ObjectDoesNotExist

LINKED_OBJECT_FIELD: ClassVar[str] = None
exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

casbin_rules

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

contentlibraryscope

Accessor to the related object on the reverse side of a one-to-one relation.

In the example:

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

coursescope

Accessor to the related object on the reverse side of a one-to-one relation.

In the example:

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

external_key

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

classmethod external_key_for_object(linked_object) → str

Return the canonical external_key string for one of this scope’s backing objects.

Subclasses must override this to match how their ScopeData computes external_key (e.g. the course id, or the library key).

Parameters:

linked_object – An instance of the model named by LINKED_OBJECT_FIELD.

Returns:

The canonical external_key for that instance.

Return type:

str

classmethod get_or_create_for_external_key(scope) → Scope

Get or create a scope instance for the given external key.

The backing object (CourseOverview, ContentLibrary, …) need not exist yet (e.g. during a course rerun, the destination course id is known before the course is cloned): the scope is created with its LINKED_OBJECT_FIELD left None in that case, and gets linked up automatically once a matching object is saved (see link_pending_scope() below and the backfill signal receivers in openedx_authz/handlers.py).

Parameters:

scope – ScopeData object with an external_key attribute.

Returns:

The (possibly newly created) scope instance for this subclass.

Return type:

Scope

id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

classmethod link_pending_scope(linked_object) → None

Link a pending scope to the object that was just created for it.

Called from the relevant post_save signal receiver in openedx_authz/handlers.py once an object with a matching external_key shows up.

Parameters:

linked_object – The model instance (CourseOverview, ContentLibrary, …) that was just saved.

objects = <openedx_authz.models.core.ScopeManager object>
class openedx_authz.models.core.ScopeManager(*args, **kwargs)

Bases: Manager

Custom manager for Scope model that handles polymorphic behavior.

get_or_create_for_external_key(scope_data)

Get or create a Scope instance for the given scope data.

This method determines the appropriate subclass based on the namespace in the scope_data and delegates to that subclass’s get_or_create_for_external_key.

Parameters:

scope_data – The scope (ScopeData) object with NAMESPACE class attribute

Returns:

The Scope instance

Return type:

Scope

Raises:

ValueError – If the namespace is not registered

class openedx_authz.models.core.Subject(*args, **kwargs)

Bases: BaseRegistryModel

Model representing a subject in the authorization system.

This model can be extended to represent different types of subjects, such as users or groups.

Subclasses should define a NAMESPACE class attribute (e.g., ‘user’ for users) and implement get_or_create_for_external_key() classmethod.

exception DoesNotExist

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

casbin_rules

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects = <openedx_authz.models.core.SubjectManager object>
usersubject

Accessor to the related object on the reverse side of a one-to-one relation.

In the example:

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

class openedx_authz.models.core.SubjectManager(*args, **kwargs)

Bases: Manager

Custom manager for Subject model that handles polymorphic behavior.

get_or_create_for_external_key(subject_data)

Get or create a Subject instance for the given subject data.

This method determines the appropriate subclass based on the namespace in the subject_data and delegates to that subclass’s get_or_create_for_external_key.

Parameters:

subject_data – The subject (SubjectData) object with NAMESPACE class attribute

Returns:

The Subject instance

Return type:

Subject

Raises:

ValueError – If the namespace is not registered

openedx_authz.models.engine module#

Models for the authorization engine.

class openedx_authz.models.engine.PolicyCacheControl(*args, **kwargs)

Bases: Model

Singleton row that both versions and guards the authorization policy.

Its version is the cache-invalidation signal: whenever the stored policy changes, the version is bumped and every enforcer reloads on its next check (see AuthzEnforcer.load_policy_if_needed()).

Because this one row is also what every reader polls, it doubles as the natural serialization point for writers: lock() takes an exclusive row lock on it so concurrent schema applies run one at a time. The lock lives here only as a thin primitive over this row; the orchestration of the critical section (ordering, enforcer reload, bumping the version inside the writer’s transaction) belongs to the applier that owns the write, not to this model (see SchemaApplier._serialized_section).

exception DoesNotExist

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

classmethod ensure_exists()

Create the singleton row if missing. Call outside the apply transaction.

select_for_update cannot lock a row that does not exist, so the row has to be there before lock() runs. This must be called before the apply transaction.atomic() block opens, not inside it: a plain SELECT/INSERT inside that transaction would be its first read and, under InnoDB Repeatable Read, would pin the consistent-read snapshot before lock() blocks — defeating the lock, because the post-lock reads would still see the pre-lock snapshot. Keeping row creation out of the apply transaction leaves the locking read in lock() as the genuinely first read of that transaction.

classmethod get()

Get the singleton instance of the model.

classmethod get_version()

Get the version for policy cache control.

Returns:

The version of the last update.

Return type:

UUID

id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

classmethod lock()

Take an exclusive row lock on the singleton (SELECT ... FOR UPDATE).

A thin serialization primitive: it blocks until any other transaction holding the lock commits or rolls back, then returns the row. It does not manage its own transaction or ordering — the caller owns both. For the lock to actually serialize a read-modify-write cycle it must be taken inside a transaction.atomic() block, as that transaction’s first read (so the Repeatable Read snapshot forms after the lock is granted), and held across the reads and writes. SchemaApplier._serialized_section is the orchestrator that satisfies those requirements; this method only provides the lock itself.

ensure_exists() must have run and committed first, since select_for_update cannot lock a row that does not exist yet.

Returns:

The locked singleton instance.

Return type:

PolicyCacheControl

objects = <django.db.models.manager.Manager object>
save(*args, **kwargs)

Override save to ensure a single instance.

classmethod set_version(version: UUID)

Update the cache version.

This method updates the cache version, which can be used to signal that the policy cache should be invalidated.

version

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

openedx_authz.models.schema module#

Models for compiled authorization definitions and their sources (ADR 0025).

These tables are the authoritative store of the compiled static schema: permission categories, permission definitions, role definitions, and the role-permission grants rendered into Casbin p rows. Each definition and each role-permission grant is attributed to one or more contributing sources so the origin of any role or permission can be queried, so a built-in role and a module-added grant on that role stay distinguishable, and so a future application removal can prune only what that application uniquely provided.

Casbin p rows remain the enforcement representation; these tables are the definition/provenance record written alongside them in the same transaction.

By convention, all models in this package are prefixed with Authz (e.g. AuthzSchemaSource, AuthzRoleDefinition) so the project’s tables are easy to identify at a glance in the shared database and admin, and to avoid name collisions with models from other installed apps.

class openedx_authz.models.schema.AuthzCategorySource(*args, **kwargs)

Bases: _BaseSourceLink

Links a category to a contributing source.

exception DoesNotExist

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

category

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

category_id
get_origin_kind_display(*, field=<django.db.models.fields.CharField: origin_kind>)
id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects = <django.db.models.manager.Manager object>
origin_kind

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

priority

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

source

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

source_id
class openedx_authz.models.schema.AuthzPermissionCategory(*args, **kwargs)

Bases: TimeStampedModel

A display/grouping category for permissions (grants no access).

exception DoesNotExist

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

authzcategorysource_set

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

category_id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

created_at

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

description

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

display_name

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

get_next_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=True, **kwargs)
get_next_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=True, **kwargs)
get_previous_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=False, **kwargs)
get_previous_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=False, **kwargs)
icon

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects = <django.db.models.manager.Manager object>
permissions

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

sources

Accessor to the related objects manager on the forward and reverse sides of a many-to-many relation.

In the example:

class Pizza(Model):
    toppings = ManyToManyField(Topping, related_name='pizzas')

Pizza.toppings and Topping.pizzas are ManyToManyDescriptor instances.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

updated_at

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

class openedx_authz.models.schema.AuthzPermissionDefinition(*args, **kwargs)

Bases: TimeStampedModel

A compiled permission definition.

The complete permission id is namespace.name (see identifier).

exception DoesNotExist

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

authzpermissionsource_set

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

category

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

category_id
created_at

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

description

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

display_name

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

get_next_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=True, **kwargs)
get_next_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=True, **kwargs)
get_previous_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=False, **kwargs)
get_previous_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=False, **kwargs)
icon

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

property identifier: str

Complete permission id, e.g. 'courses.view_course'.

name

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

namespace

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects = <django.db.models.manager.Manager object>
role_permissions

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

scopes

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

sources

Accessor to the related objects manager on the forward and reverse sides of a many-to-many relation.

In the example:

class Pizza(Model):
    toppings = ManyToManyField(Topping, related_name='pizzas')

Pizza.toppings and Topping.pizzas are ManyToManyDescriptor instances.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

updated_at

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

class openedx_authz.models.schema.AuthzPermissionSource(*args, **kwargs)

Bases: _BaseSourceLink

Links a permission definition to a contributing source.

exception DoesNotExist

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

get_origin_kind_display(*, field=<django.db.models.fields.CharField: origin_kind>)
id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects = <django.db.models.manager.Manager object>
origin_kind

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

permission

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

permission_id
priority

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

source

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

source_id
class openedx_authz.models.schema.AuthzRoleDefinition(*args, **kwargs)

Bases: TimeStampedModel

A compiled role definition.

hidden mirrors ADR 0023: a hidden role is excluded from normal role discovery/selection but keeps its assignments, permission checks, and reserved id.

exception DoesNotExist

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

authzrolesource_set

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

created_at

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

description

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

display_name

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

get_next_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=True, **kwargs)
get_next_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=True, **kwargs)
get_previous_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=False, **kwargs)
get_previous_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=False, **kwargs)
hidden

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

icon

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects = <django.db.models.manager.Manager object>
role_id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

role_permissions

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

scopes

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

sources

Accessor to the related objects manager on the forward and reverse sides of a many-to-many relation.

In the example:

class Pizza(Model):
    toppings = ManyToManyField(Topping, related_name='pizzas')

Pizza.toppings and Topping.pizzas are ManyToManyDescriptor instances.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

updated_at

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

class openedx_authz.models.schema.AuthzRolePermission(*args, **kwargs)

Bases: TimeStampedModel

A single role-permission-scope association (one per rendered Casbin p row).

This records the association declared by the schema; Casbin still manages the actual permission check. It is the atomic unit of attribution: a base association and an extension association on the same role are distinct rows with distinct sources.

exception DoesNotExist

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

authzrolepermissionsource_set

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

created_at

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

get_next_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=True, **kwargs)
get_next_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=True, **kwargs)
get_previous_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=False, **kwargs)
get_previous_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=False, **kwargs)
id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects = <django.db.models.manager.Manager object>
permission

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

permission_id
role

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

role_id
scope

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

sources

Accessor to the related objects manager on the forward and reverse sides of a many-to-many relation.

In the example:

class Pizza(Model):
    toppings = ManyToManyField(Topping, related_name='pizzas')

Pizza.toppings and Topping.pizzas are ManyToManyDescriptor instances.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

updated_at

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

class openedx_authz.models.schema.AuthzRolePermissionSource(*args, **kwargs)

Bases: _BaseSourceLink

Links a role-permission grant to a contributing source.

This is where the extension case is recorded: a grant defined together with the role links to that role’s source (origin_kind=base), while a grant added via a role_extension links to the extending source (origin_kind=extension).

exception DoesNotExist

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

get_origin_kind_display(*, field=<django.db.models.fields.CharField: origin_kind>)
id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects = <django.db.models.manager.Manager object>
origin_kind

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

priority

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

role_permission

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

role_permission_id
source

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

source_id
class openedx_authz.models.schema.AuthzRoleSource(*args, **kwargs)

Bases: _BaseSourceLink

Links a role definition to a contributing source.

exception DoesNotExist

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

get_origin_kind_display(*, field=<django.db.models.fields.CharField: origin_kind>)
id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects = <django.db.models.manager.Manager object>
origin_kind

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

priority

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

role

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

role_id
source

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

source_id
class openedx_authz.models.schema.AuthzSchemaSource(*args, **kwargs)

Bases: TimeStampedModel

A distinct schema contribution, identified by distribution and module.

Identity is (distribution, module) — moving a definition between files within the same module does not change its source. resource_path and content_digest are non-identifying and advisory (kept latest-seen for diagnostics); change detection relies on diffing compiled definitions.

exception DoesNotExist

Bases: ObjectDoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

authzcategorysource_set

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

authzpermissionsource_set

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

authzrolepermissionsource_set

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

authzrolesource_set

Accessor to the related objects manager on the reverse side of a many-to-one relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Parent.children is a ReverseManyToOneDescriptor instance.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

categories

Accessor to the related objects manager on the forward and reverse sides of a many-to-many relation.

In the example:

class Pizza(Model):
    toppings = ManyToManyField(Topping, related_name='pizzas')

Pizza.toppings and Topping.pizzas are ManyToManyDescriptor instances.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

content_digest

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

created_at

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

distribution

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

distribution_version

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

get_next_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=True, **kwargs)
get_next_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=True, **kwargs)
get_previous_by_created_at(*, field=<django.db.models.fields.DateTimeField: created_at>, is_next=False, **kwargs)
get_previous_by_updated_at(*, field=<django.db.models.fields.DateTimeField: updated_at>, is_next=False, **kwargs)
id

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

module

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

objects = <django.db.models.manager.ManagerFromAuthzSchemaSourceQuerySet object>
permissions

Accessor to the related objects manager on the forward and reverse sides of a many-to-many relation.

In the example:

class Pizza(Model):
    toppings = ManyToManyField(Topping, related_name='pizzas')

Pizza.toppings and Topping.pizzas are ManyToManyDescriptor instances.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

resource_path

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

role_permissions

Accessor to the related objects manager on the forward and reverse sides of a many-to-many relation.

In the example:

class Pizza(Model):
    toppings = ManyToManyField(Topping, related_name='pizzas')

Pizza.toppings and Topping.pizzas are ManyToManyDescriptor instances.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

roles

Accessor to the related objects manager on the forward and reverse sides of a many-to-many relation.

In the example:

class Pizza(Model):
    toppings = ManyToManyField(Topping, related_name='pizzas')

Pizza.toppings and Topping.pizzas are ManyToManyDescriptor instances.

Most of the implementation is delegated to a dynamically defined manager class built by create_forward_many_to_many_manager() defined below.

schema_version

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

property source_id: str

Stable identifier, e.g. 'openedx-authz:openedx_authz/authz'.

updated_at

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

class openedx_authz.models.schema.OriginKind(*values)

Bases: TextChoices

Whether a contribution is a base definition or an extension (ADR 0023/0025).

Values are sourced from openedx_authz.constants.SchemaOriginKind so the persistence layer and the (Django-free) engine schema types share a single source of truth; the second tuple element is the human-readable label.

BASE = 'base'
EXTENSION = 'extension'
openedx_authz.models.schema.origin_for_role_permission(role_id: str, permission_identifier: str) → list[str]

Return the distributions that contribute a specific role-permission grant.

This distinguishes, for one role, the grants provided by one module vs another, even though both live in the same role.

openedx_authz.models.schema.origins_for_category(category_id: str) → list[str]

Return the distributions that define a category.

openedx_authz.models.schema.origins_for_permission(identifier: str) → list[str]

Return the distributions that define a permission, by complete id.

openedx_authz.models.schema.origins_for_role(role_id: str) → list[str]

Return the distributions that contribute to a role (base + extensions).

openedx_authz.models.scopes module#

Models for ContentLibrary scopes in the authorization framework.

These models extend the base Scope model to represent content library scopes, which are used to define permissions and roles related to content libraries within the Open edX platform.

class openedx_authz.models.scopes.ContentLibraryScope(*args, **kwargs)

Bases: Scope

Scope representing a content library in the authorization system.

exception DoesNotExist

Bases: DoesNotExist

LINKED_OBJECT_FIELD: ClassVar[str] = 'content_library'
exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

NAMESPACE: ClassVar[str] = 'lib'
content_library

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

content_library_id
classmethod external_key_for_object(linked_object) → str

Return the canonical external_key string for a ContentLibrary instance.

scope_ptr

Accessor to the related object on the forward side of a one-to-one relation.

In the example:

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Restaurant.place is a ForwardOneToOneDescriptor instance.

scope_ptr_id
class openedx_authz.models.scopes.CourseScope(*args, **kwargs)

Bases: Scope

Scope representing a course in the authorization system.

exception DoesNotExist

Bases: DoesNotExist

LINKED_OBJECT_FIELD: ClassVar[str] = 'course_overview'
exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

NAMESPACE: ClassVar[str] = 'course-v1'
course_overview

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

course_overview_id
classmethod external_key_for_object(linked_object) → str

Return the canonical external_key string for a CourseOverview instance.

scope_ptr

Accessor to the related object on the forward side of a one-to-one relation.

In the example:

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Restaurant.place is a ForwardOneToOneDescriptor instance.

scope_ptr_id
openedx_authz.models.scopes.get_content_library_model()

Return the ContentLibrary model class specified by settings.

The setting OPENEDX_AUTHZ_CONTENT_LIBRARY_MODEL should be an app_label.ModelName string (e.g. ‘content_libraries.ContentLibrary’).

openedx_authz.models.scopes.get_course_overview_model()

Return the CourseOverview model class specified by settings.

The setting OPENEDX_AUTHZ_COURSE_OVERVIEW_MODEL should be an app_label.ModelName string (e.g. ‘course_overviews.CourseOverview’).

openedx_authz.models.subjects module#

Models for User subjects in the authorization framework.

These models extend the base Subject model to represent user subjects, which are used to define permissions and roles related to users within the Open edX platform.

class openedx_authz.models.subjects.UserSubject(*args, **kwargs)

Bases: Subject

Subject representing a user in the authorization system.

exception DoesNotExist

Bases: DoesNotExist

exception MultipleObjectsReturned

Bases: MultipleObjectsReturned

NAMESPACE: ClassVar[str] = 'user'
classmethod get_or_create_for_external_key(subject)

Get or create a UserSubject for the given external key.

Parameters:

subject_external_key – Username string

Returns:

The Subject instance for the given User

Return type:

UserSubject

subject_ptr

Accessor to the related object on the forward side of a one-to-one relation.

In the example:

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Restaurant.place is a ForwardOneToOneDescriptor instance.

subject_ptr_id
user

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example:

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

user_id

Module contents#

Database models for the authorization framework.

These models will be used to store additional data about roles and permissions that are not natively supported by Casbin, so as to avoid modifying the Casbin schema that focuses on the core authorization logic.

For example, we may want to store metadata about roles, such as a description or the date it was created.

This model is transversal to the implementation of the public API for authorization, which is defined in openedx_authz.api. So it can be used by various functions in the API to store and retrieve additional data about roles and permissions. That’s why we avoid coupling this model to too specific concepts and also importing too specific classes from the API to avoid circular dependencies.