openedx-authz 2.3.0__tar.gz → 2.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/CHANGELOG.rst +5 -0
- {openedx_authz-2.3.0/src/openedx_authz.egg-info → openedx_authz-2.5.0}/PKG-INFO +1 -1
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0026-rest-api-domain-ownership-boundary.rst +7 -0
- openedx_authz-2.5.0/docs/decisions/0032-applets-for-built-in-authorization-capabilities.rst +190 -0
- openedx_authz-2.5.0/docs/decisions/0033-shared-applet-for-course-team-roles.rst +43 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/pyproject.toml +1 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/authz/schema/course_roles.yaml +0 -2
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/authz-schema-v1.json +11 -3
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/validation.py +16 -0
- openedx_authz-2.5.0/src/openedx_authz/tests/schema/test_json_schema.py +48 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/schema/test_renderer.py +25 -1
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/schema/test_validation.py +10 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0/src/openedx_authz.egg-info}/PKG-INFO +1 -1
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz.egg-info/SOURCES.txt +3 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz.egg-info/scm_file_list.json +3 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/uv.lock +10 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/.annotation_safe_list.yml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/.editorconfig +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/.github/dependabot.yml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/.github/workflows/add-depr-ticket-to-depr-board.yml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/.github/workflows/add-remove-label-on-comment.yml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/.github/workflows/ci.yml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/.github/workflows/commitlint.yml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/.github/workflows/release.yml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/.github/workflows/self-assign-issue.yml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/.github/workflows/upgrade-python-requirements.yml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/.gitignore +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/.pii_annotations.yml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/.readthedocs.yaml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/LICENSE +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/MANIFEST.in +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/Makefile +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/README.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/catalog-info.yaml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/codecov.yml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/Makefile +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/_images/architecture-overview.png +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/_static/theme_overrides.css +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/changelog.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/concepts/core_roles_and_permissions/content_library_roles.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/concepts/core_roles_and_permissions/course_roles.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/concepts/core_roles_and_permissions/index.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/concepts/index.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/conf.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0001-purpose-of-this-repo.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0002-authorization-model-foundation.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0003-jwt-usage.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0004-technology-selection.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0005-architecture-and-data-modeling.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0007-enforcement-mechanisms-mfe.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0008-compatibility-scheme.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0009-authz-for-course-authoring.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0010-course-authoring-flag.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0011-course-authoring-migration-process.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0012-auditability.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0012-glob-support-for-role-assignments.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0013-course-authoring-automatic-migration.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0014-bulk-assignment-queries-without-casbin-enforce.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0015-expose-course-authoring-waffle-flag-state-via-rest-api.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0016-static-and-dynamic-roles.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0017-static-authorization-schema.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0018-authorization-schema-lifecycle.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0019-authorization-schema-discovery.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0020-authorization-schema-internationalization.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0021-authorization-definition-api.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0022-defer-authorization-implications.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0023-extend-static-roles.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0024-api-contract-for-user-grouped-role-assignments.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0025-authorization-schema-source-tracking.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0027-cross-domain-filtering-via-openedx-filters.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0028-api-contract-for-role-catalog.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0029-paragon-icon-list-maintenance.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0030-tutor-implementation-authz-schema-discovery.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/0031-priority-applies-to-role-extensions-only.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions/README.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/decisions.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/getting_started.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/how-tos/index.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/index.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/internationalization.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/make.bat +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/quickstarts/index.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/readme.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/references/authorization-schema-json.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/references/authorization-schema.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/references/index.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/docs/testing.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/manage.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/pylintrc +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/pylintrc_tweaks +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/ruff.toml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/scripts/generate_paragon_icons.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/setup.cfg +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/admin.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/api/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/api/catalog.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/api/data.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/api/permissions.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/api/roles.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/api/users.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/api/utils.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/apps.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/authz/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/authz/schema/course_permissions.yaml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/authz/schema/library_permissions.yaml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/authz/schema/library_roles.yaml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/conf/locale/config.yaml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/constants/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/constants/permissions.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/constants/roles.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/constants/schema.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/data.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/adapter.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/apps.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/config/model.conf +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/enforcer.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/filter.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/matcher.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/policy.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/renderer.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/compilation.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/discovery.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/exceptions.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/issues.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/loading.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/paragon_icons.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/parsing.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/pipeline.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/syntax.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/translation.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/types/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/types/compilation.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/types/definitions.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/types/loading.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/utils.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/filters.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/handlers.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/management/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/management/commands/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/management/commands/authz_migrate_course_authoring.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/management/commands/authz_rollback_course_authoring.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/management/commands/enforcement.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/management/commands/extract_schema_translations.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/management/commands/load_authz_schema.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/management/commands/load_policies.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/migrations/0001_add_casbin_dependency.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/migrations/0002_initial.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/migrations/0003_usersubject.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/migrations/0004_contentlibraryscope.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/migrations/0005_policycachecontrol.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/migrations/0006_migrate_legacy_permissions.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/migrations/0007_coursescope.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/migrations/0008_authzcourseauthoringmigrationrun.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/migrations/0009_roleassignmentaudit.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/migrations/0010_scope_external_key.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/migrations/0011_authz_schema_definitions.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/migrations/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/models/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/models/authz_migration.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/models/base.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/models/core.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/models/engine.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/models/schema.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/models/scopes.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/models/subjects.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/data.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/decorators.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/urls.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/utils.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/v1/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/v1/admin_console/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/v1/admin_console/filters.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/v1/admin_console/serializers.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/v1/admin_console/views.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/v1/course_authoring/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/v1/course_authoring/pipeline.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/v1/course_authoring/views.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/v1/fields.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/v1/paginators.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/v1/permissions.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/v1/serializers.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/v1/urls.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/rest_api/v1/views.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/settings/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/settings/common.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/settings/production.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/settings/test.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/templates/openedx_authz/base.html +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/api/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/api/test_catalog.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/api/test_data.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/api/test_roles.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/api/test_users.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/authz/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/authz/test_resources.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/conftest.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/fixtures/schema_pipeline/invalid_compiled/categories.yaml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/fixtures/schema_pipeline/invalid_compiled/extensions.yaml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/fixtures/schema_pipeline/invalid_compiled/permissions.yaml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/fixtures/schema_pipeline/invalid_compiled/roles.yaml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/fixtures/schema_pipeline/invalid_parse/malformed.yaml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/fixtures/schema_pipeline/invalid_semantics/unknown_category.yaml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/fixtures/schema_pipeline/invalid_structure/items.yml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/fixtures/schema_pipeline/invalid_structure/priority.yaml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/fixtures/schema_pipeline/valid/categories.yaml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/fixtures/schema_pipeline/valid/extensions.yaml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/fixtures/schema_pipeline/valid/permissions.yml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/fixtures/schema_pipeline/valid/roles.yaml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/test_handlers.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/test_models.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/test_schema_apply.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/test_schema_pipeline.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/integration/test_views.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/rest_api/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/rest_api/admin_console/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/rest_api/admin_console/test_views.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/rest_api/course_authoring/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/rest_api/course_authoring/test_pipeline.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/rest_api/course_authoring/test_views.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/rest_api/mixins.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/rest_api/test_permissions.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/rest_api/test_utils.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/rest_api/test_views.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/schema/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/schema/factories.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/schema/test_apply.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/schema/test_compilation.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/schema/test_discovery.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/schema/test_load_authz_schema_command.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/schema/test_loading.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/schema/test_parsing.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/schema/test_pipeline.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/schema/test_schema_models.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/schema/test_source_storage.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/schema/test_syntax.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/schema/test_translation.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/schema/test_types.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/stubs/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/stubs/apps.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/stubs/migrations/0001_initial.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/stubs/migrations/0002_learningpackage_contentlibrary_learning_package.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/stubs/migrations/0002_userprofile.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/stubs/models.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/test_commands.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/test_enforcement.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/test_enforcer.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/test_engine_utils.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/test_filter.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/test_handlers.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/test_imports.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/test_migrations.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/test_models.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/test_policy.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/test_utils.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/urls.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/utils.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz.egg-info/dependency_links.txt +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz.egg-info/entry_points.txt +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz.egg-info/requires.txt +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz.egg-info/top_level.txt +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/tox.ini +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/tutor/tutor-contrib-authz/.gitignore +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/tutor/tutor-contrib-authz/LICENSE.txt +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/tutor/tutor-contrib-authz/MANIFEST.in +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/tutor/tutor-contrib-authz/Makefile +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/tutor/tutor-contrib-authz/README.rst +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/tutor/tutor-contrib-authz/pyproject.toml +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/tutor/tutor-contrib-authz/tutor_authz/__about__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/tutor/tutor-contrib-authz/tutor_authz/__init__.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/tutor/tutor-contrib-authz/tutor_authz/patches/openedx-common-settings +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/tutor/tutor-contrib-authz/tutor_authz/plugin.py +0 -0
- {openedx_authz-2.3.0 → openedx_authz-2.5.0}/tutor/tutor-contrib-authz/tutor_authz/templates/apps/openedx/config/authz-schema.yml +0 -0
|
@@ -52,6 +52,11 @@ Added
|
|
|
52
52
|
``openedx_authz/engine/schema/paragon_icons.py`` and regenerated with
|
|
53
53
|
``make paragon_icons`` (ADR 0029).
|
|
54
54
|
|
|
55
|
+
Changed
|
|
56
|
+
========
|
|
57
|
+
|
|
58
|
+
* Static roles may declare an empty permission list when ``role_extensions`` contribute their permissions. Permission lists used by extension edits remain non-empty.
|
|
59
|
+
|
|
55
60
|
Fixed
|
|
56
61
|
=====
|
|
57
62
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openedx-authz
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.0
|
|
4
4
|
Summary: Open edX AuthZ provides the architecture and foundations of the authorization framework.
|
|
5
5
|
Author-email: Open edX Project <oscm@openedx.org>
|
|
6
6
|
License-Expression: AGPL-3.0-or-later
|
|
@@ -105,6 +105,11 @@ Rejected Alternatives
|
|
|
105
105
|
**Adding application-specific visibility rules to reusable endpoint code**
|
|
106
106
|
This would make reusable authorization code interpret data that authorization does not own. A general hook keeps the rule in a separate implementation, and `openedx_catalog`_ follows a related approach for installation-specific visibility rules.
|
|
107
107
|
|
|
108
|
+
Addendum 2026-10-20
|
|
109
|
+
*******************
|
|
110
|
+
|
|
111
|
+
`ADR 0032`_ replaces the package layout in decisions 4, 6, and 8, so client-specific and cross-domain endpoints now belong in the applet for the capability they serve, while the ownership rules in this ADR still apply.
|
|
112
|
+
|
|
108
113
|
References
|
|
109
114
|
**********
|
|
110
115
|
|
|
@@ -115,6 +120,7 @@ References
|
|
|
115
120
|
* `Issue #377`_
|
|
116
121
|
* `PR #361`_
|
|
117
122
|
* `openedx_catalog`_
|
|
123
|
+
* `ADR 0032`_
|
|
118
124
|
|
|
119
125
|
.. _edX DDD Bounded Contexts: https://openedx.atlassian.net/wiki/spaces/AC/pages/663224968/edX+DDD+Bounded+Contexts
|
|
120
126
|
.. _ADR 0018 in openedx-events: https://github.com/openedx/openedx-events/blob/main/docs/decisions/0018-supporting-subdomain-modules.rst
|
|
@@ -123,3 +129,4 @@ References
|
|
|
123
129
|
.. _Issue #377: https://github.com/openedx/openedx-authz/issues/377
|
|
124
130
|
.. _PR #361: https://github.com/openedx/openedx-authz/pull/361
|
|
125
131
|
.. _openedx_catalog: https://github.com/openedx/openedx-core/blob/main/src/openedx_catalog/api.py
|
|
132
|
+
.. _ADR 0032: 0032-applets-for-built-in-authorization-capabilities.rst
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
0032: Applets for Built-In Authorization Capabilities
|
|
2
|
+
#####################################################
|
|
3
|
+
|
|
4
|
+
Status
|
|
5
|
+
******
|
|
6
|
+
|
|
7
|
+
**Draft**
|
|
8
|
+
|
|
9
|
+
Context
|
|
10
|
+
*******
|
|
11
|
+
|
|
12
|
+
`ADR 0005`_ defines ``openedx_authz.api`` as the public API for the reusable authorization framework, although the package also ships the Open edX-specific roles and permissions that the platform uses, as YAML schema files and Python constants. These definitions are grouped by type, so ``authz/schema/course_permissions.yaml`` defines every course permission and ``authz/schema/course_roles.yaml`` lists the complete permissions for each course role.
|
|
13
|
+
|
|
14
|
+
Grouping by type keeps roles apart from permissions, but it also puts definitions from unrelated responsibilities into the same course-level files, so a reader can see that a permission applies to a course without being able to tell whether enrollments, grading, or another area owns it.
|
|
15
|
+
|
|
16
|
+
`Issue #484`_ defines permissions for the Instructor Dashboard, which brings together several areas of course administration, including enrollments, the gradebook, learner extensions, and cohorts. The `edX DDD Bounded Contexts`_ map places those areas in different parts of the platform, so adding their permissions to the shared files would mix definitions from several bounded contexts and make those files the place where every new contribution has to be added.
|
|
17
|
+
|
|
18
|
+
The existing decisions do not say where these definitions belong, because `ADR 0026`_ defines ownership and placement rules only for REST endpoints, while `PR #421`_ raised the same ownership question for constants and schema definitions.
|
|
19
|
+
|
|
20
|
+
`ADR 0010 in openedx-core`_ answers a similar question for a single Django app by giving each bounded responsibility its own internal package, which it calls an applet. The authorization schema can already support that structure, since `ADR 0019`_ allows a package to load several schema directories and `ADR 0023`_ allows one schema contribution to extend a role defined by another.
|
|
21
|
+
|
|
22
|
+
Decision
|
|
23
|
+
********
|
|
24
|
+
|
|
25
|
+
We will organize built-in Open edX authorization capabilities as applets under ``openedx_authz.applets``, while the existing public API and import paths remain stable, since ``openedx_authz.constants`` re-exports each applet's constants and the ``authz.schema`` provider lists each applet's schema directory.
|
|
26
|
+
|
|
27
|
+
1. Applet boundaries
|
|
28
|
+
====================
|
|
29
|
+
|
|
30
|
+
An applet is an internal Python package that gives one bounded responsibility a concrete place inside the existing ``openedx_authz`` Django app and keeps the related YAML definitions, Python constants, REST endpoints, filters, and tests together when those elements exist:
|
|
31
|
+
|
|
32
|
+
.. code-block:: text
|
|
33
|
+
|
|
34
|
+
openedx_authz/applets/
|
|
35
|
+
course_team_roles/
|
|
36
|
+
constants.py
|
|
37
|
+
schema/
|
|
38
|
+
enrollments/
|
|
39
|
+
constants.py
|
|
40
|
+
schema/
|
|
41
|
+
course_authoring/
|
|
42
|
+
constants.py
|
|
43
|
+
schema/
|
|
44
|
+
rest_api/
|
|
45
|
+
...
|
|
46
|
+
|
|
47
|
+
The `edX DDD Bounded Contexts`_ map says where each responsibility belongs, but it does not prescribe a package layout inside one Django app, so applets turn those boundaries into Python packages that keep the code and definitions for each responsibility together. Reusable schema handling, enforcement, persistence, and public APIs stay in their existing top-level packages, since every applet depends on them.
|
|
48
|
+
|
|
49
|
+
Dependencies point in one direction, from clients to the public modules, from those modules to the applets, and from the applets to the shared packages:
|
|
50
|
+
|
|
51
|
+
.. code-block:: text
|
|
52
|
+
|
|
53
|
+
clients, such as openedx-platform
|
|
54
|
+
└── openedx_authz.api, openedx_authz.constants
|
|
55
|
+
└── openedx_authz.applets.<applet>
|
|
56
|
+
└── openedx_authz.api.data, openedx_authz.data
|
|
57
|
+
|
|
58
|
+
Applets do not import each other, since role extensions in YAML already connect their definitions. Applets are internal, so clients import constants from ``openedx_authz.constants``, and an applet can change or move without changing client code.
|
|
59
|
+
|
|
60
|
+
2. Definition ownership
|
|
61
|
+
=======================
|
|
62
|
+
|
|
63
|
+
A permission belongs to the applet responsible for the action or data that the permission controls. For example, the ``enrollments`` applet defines the permissions for viewing or changing enrollments, along with their metadata, constants, and contributions to shared roles, so code elsewhere may check those permissions through the public API while their definitions remain in ``enrollments``.
|
|
64
|
+
|
|
65
|
+
A role belongs to the applet for the bounded context where it is assigned, as with the library roles, and other applets add the permissions they own through ``role_extensions``. Roles that cut across several contexts need a specific decision about where they live, which `ADR 0033`_ makes for the course-team roles.
|
|
66
|
+
|
|
67
|
+
Both rules rely on the `edX DDD Bounded Contexts`_ map, which shows the context that owns each action or data even when a user interface combines several capabilities. To place a new permission, we find the bounded context that owns its action or data in the map and add the permission to that context's applet, or create an applet when the context has none yet. Applet names describe the definitions they hold, so the following table records which bounded context each one stands for:
|
|
68
|
+
|
|
69
|
+
.. list-table::
|
|
70
|
+
:header-rows: 1
|
|
71
|
+
|
|
72
|
+
* - Applet
|
|
73
|
+
- Bounded context
|
|
74
|
+
- Definitions
|
|
75
|
+
* - ``course_authoring``
|
|
76
|
+
- Course Run Authoring and Learning Content Authoring
|
|
77
|
+
- Course authoring and course-team permissions
|
|
78
|
+
* - ``content_libraries``
|
|
79
|
+
- Learning Content Authoring and Learning Content Repository
|
|
80
|
+
- Library roles and permissions
|
|
81
|
+
* - ``enrollments``
|
|
82
|
+
- Content Access / Enrollments
|
|
83
|
+
- Viewing and changing course enrollments
|
|
84
|
+
* - ``learner_grading``
|
|
85
|
+
- Consuming Learning Content
|
|
86
|
+
- The gradebook and grading tools for individual learners
|
|
87
|
+
* - ``learner_administration``
|
|
88
|
+
- Support Learning
|
|
89
|
+
- Course information, learner extensions, and cohorts
|
|
90
|
+
* - ``course_team_roles``
|
|
91
|
+
- Shared by several bounded contexts
|
|
92
|
+
- Roles held by members of a course team
|
|
93
|
+
* - ``role_management``
|
|
94
|
+
- Authorization
|
|
95
|
+
- Admin Console role assignment workflows
|
|
96
|
+
|
|
97
|
+
3. Course roles
|
|
98
|
+
===============
|
|
99
|
+
|
|
100
|
+
Following `ADR 0033`_, ``course_team_roles`` defines the identifiers and metadata for the course-team roles, and their base definitions list only the permissions that ``course_team_roles`` owns, such as the legacy compatibility permissions, while each capability applet adds the permissions it owns through ``role_extensions``:
|
|
101
|
+
|
|
102
|
+
.. code-block:: yaml
|
|
103
|
+
|
|
104
|
+
# course_team_roles/schema/roles.yaml
|
|
105
|
+
roles:
|
|
106
|
+
- id: course_admin
|
|
107
|
+
display_name: Course Admin
|
|
108
|
+
description: Can manage the course team and all course settings.
|
|
109
|
+
scopes:
|
|
110
|
+
- course-v1
|
|
111
|
+
permissions:
|
|
112
|
+
- courses.legacy_instructor_role_permissions
|
|
113
|
+
|
|
114
|
+
# enrollments/schema/role_extensions.yaml
|
|
115
|
+
role_extensions:
|
|
116
|
+
- role_id: course_admin
|
|
117
|
+
add_permissions:
|
|
118
|
+
- courses.view_enrollments
|
|
119
|
+
- courses.enroll_learners
|
|
120
|
+
|
|
121
|
+
Roles such as ``course_editor`` have no permissions of their own, so schema version 1 will accept an empty permission list, while the compiled roles will still contain the complete permission lists contributed by the applets.
|
|
122
|
+
|
|
123
|
+
4. REST endpoints
|
|
124
|
+
=================
|
|
125
|
+
|
|
126
|
+
REST endpoints continue to follow the ownership rules in `ADR 0026`_, and applets now give those rules a package boundary. The Admin Console endpoints therefore move to ``role_management``, since they support the same role-management workflow, although this placement does not settle the ownership of the organization data returned by ``AdminConsoleOrgsAPIView``, and ``WaffleFlagStatesAPIView`` moves to ``course_authoring``. In both cases, the existing URLs and route names remain unchanged.
|
|
127
|
+
|
|
128
|
+
5. Imports
|
|
129
|
+
==========
|
|
130
|
+
|
|
131
|
+
Although applets are internal packages, ``openedx_authz.constants.permissions`` and ``openedx_authz.constants.roles`` continue to export every existing constant, while ``COURSE_ADMIN`` and ``COURSE_STAFF`` continue to contain their complete permission lists, so existing import paths remain valid when code moves into an applet.
|
|
132
|
+
|
|
133
|
+
YAML remains the source of truth for static definitions, although each applet will maintain its Python constants manually for now, so tests compare those constants with the applet's YAML definitions, and generating them from YAML may replace this process in later work.
|
|
134
|
+
|
|
135
|
+
6. Future extraction
|
|
136
|
+
====================
|
|
137
|
+
|
|
138
|
+
The applets remain inside ``openedx-authz`` for this work, so implementing the ownership model and the permissions from `Issue #484`_ does not require coordinated changes across the services that use the library, and since their definitions describe the underlying actions and data rather than one user interface, another client can reuse the same permissions when it exposes the same responsibility.
|
|
139
|
+
|
|
140
|
+
An applet may later move to the service that owns its responsibility and contribute its definitions through the existing ``authz.schema`` entry point, although this decision does not include that extraction because the service boundary, package dependency, and compatibility path for the Python constants would need to be agreed first.
|
|
141
|
+
|
|
142
|
+
Consequences
|
|
143
|
+
************
|
|
144
|
+
|
|
145
|
+
1. Each built-in definition has an explicit owner based on the capability it protects.
|
|
146
|
+
2. Adding a capability does not require adding its definitions to shared course permission and role files.
|
|
147
|
+
3. The complete permission list for a course role is assembled from several schema contributions, so readers use the compiled schema or the public role constants to inspect that list.
|
|
148
|
+
4. Each permission identifier appears in YAML and Python until generated constants replace the manually maintained files.
|
|
149
|
+
5. The schema accepts an empty base permission list for applets that define roles whose permissions come from other applets. Validation logs a warning so contributors can confirm that the empty list is intentional and that ``role_extensions`` provide the role's permissions.
|
|
150
|
+
6. The Admin Console and course-authoring endpoints move again after `ADR 0026`_, although their public URLs, route names, request and response contracts, and import paths remain stable.
|
|
151
|
+
7. Reviewers must identify unwanted dependencies between applets because this decision does not add automated import-boundary checks.
|
|
152
|
+
8. Applets create boundaries that can support later extraction, although moving one to another service requires a separate decision about dependencies and compatibility.
|
|
153
|
+
|
|
154
|
+
Rejected Alternatives
|
|
155
|
+
*********************
|
|
156
|
+
|
|
157
|
+
**Keeping all definitions in the shared files**
|
|
158
|
+
Definitions would remain grouped by type, leaving ownership implicit and continuing the growth of the shared course files.
|
|
159
|
+
|
|
160
|
+
**One applet for each screen, such as the Instructor Dashboard**
|
|
161
|
+
A permission that Studio and the dashboard both use would have two possible owners.
|
|
162
|
+
|
|
163
|
+
**A separate Django app for each feature**
|
|
164
|
+
Each feature would gain a separate app label and installation boundary, which the definitions and integrations covered by this decision do not require.
|
|
165
|
+
|
|
166
|
+
**Moving the definitions to their owning services now**
|
|
167
|
+
This would place the definitions at their eventual service boundary, but it would also require coordinating package dependencies and compatibility imports before implementing the permissions in `Issue #484`_, while the existing schema contribution mechanism leaves that move available after those boundaries are agreed.
|
|
168
|
+
|
|
169
|
+
References
|
|
170
|
+
**********
|
|
171
|
+
|
|
172
|
+
* `Issue #484`_
|
|
173
|
+
* `PR #421`_
|
|
174
|
+
* `ADR 0005`_
|
|
175
|
+
* `ADR 0010 in openedx-core`_
|
|
176
|
+
* `edX DDD Bounded Contexts`_
|
|
177
|
+
* `ADR 0019`_
|
|
178
|
+
* `ADR 0023`_
|
|
179
|
+
* `ADR 0026`_
|
|
180
|
+
* `ADR 0033`_
|
|
181
|
+
|
|
182
|
+
.. _Issue #484: https://github.com/openedx/openedx-authz/issues/484
|
|
183
|
+
.. _PR #421: https://github.com/openedx/openedx-authz/pull/421
|
|
184
|
+
.. _ADR 0005: 0005-architecture-and-data-modeling.rst
|
|
185
|
+
.. _ADR 0010 in openedx-core: https://github.com/openedx/openedx-core/blob/6a26b3a4181815a44e9d724c16857b61b484b0ea/docs/openedx_content/decisions/0010-merge-authoring-apps-into-openedx-content.rst
|
|
186
|
+
.. _edX DDD Bounded Contexts: https://openedx.atlassian.net/wiki/spaces/AC/pages/663224968/edX+DDD+Bounded+Contexts
|
|
187
|
+
.. _ADR 0019: 0019-authorization-schema-discovery.rst
|
|
188
|
+
.. _ADR 0023: 0023-extend-static-roles.rst
|
|
189
|
+
.. _ADR 0026: 0026-rest-api-domain-ownership-boundary.rst
|
|
190
|
+
.. _ADR 0033: 0033-shared-applet-for-course-team-roles.rst
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
0033: Shared Applet for Course-Team Roles
|
|
2
|
+
#########################################
|
|
3
|
+
|
|
4
|
+
Status
|
|
5
|
+
******
|
|
6
|
+
|
|
7
|
+
**Draft**
|
|
8
|
+
|
|
9
|
+
Context
|
|
10
|
+
*******
|
|
11
|
+
|
|
12
|
+
`ADR 0032`_ places a role in the applet for the bounded context where it is assigned, while roles that cut across several contexts need a specific decision about where they live. The course-team roles are the first case, since they are assigned to members of a course team and combine permissions from course authoring, enrollments, grading, and learner administration.
|
|
13
|
+
|
|
14
|
+
These roles do not all combine permissions in the same way today. ``course_admin`` and ``course_staff`` receive permissions from several applets, ``course_editor`` and ``course_auditor`` receive every permission from ``course_authoring``, and the legacy roles such as ``course_limited_staff`` only list their legacy compatibility permission. However, the `Instructor Dashboard Permissions`_ proposal allows more restricted roles to receive a subset of the dashboard permissions, so the roles that rely on one applet today may combine several later.
|
|
15
|
+
|
|
16
|
+
Decision
|
|
17
|
+
********
|
|
18
|
+
|
|
19
|
+
The course-team roles are cross-cutting, so they live in the shared ``course_team_roles`` applet regardless of which applets currently provide their permissions. Their base definitions list only the permissions that ``course_team_roles`` owns, such as the legacy compatibility permissions, while every other applet adds the permissions it owns through ``role_extensions``.
|
|
20
|
+
|
|
21
|
+
Any other group of cross-cutting roles needs its own decision about where it lives.
|
|
22
|
+
|
|
23
|
+
Consequences
|
|
24
|
+
************
|
|
25
|
+
|
|
26
|
+
1. A course-team role keeps its owner when another applet starts adding permissions to it.
|
|
27
|
+
2. Every role that a course team can assign is defined in one place, next to the legacy role equivalences.
|
|
28
|
+
3. Base definitions such as ``course_editor`` may list no permissions, so the schema has to accept an empty permission list.
|
|
29
|
+
|
|
30
|
+
Rejected Alternatives
|
|
31
|
+
*********************
|
|
32
|
+
|
|
33
|
+
**Placing each course-team role in the applet that provides its permissions**
|
|
34
|
+
``course_editor`` and ``course_auditor`` would move to ``course_authoring``, splitting one group of roles across applets, and each role would have to move again once another applet added permissions to it.
|
|
35
|
+
|
|
36
|
+
References
|
|
37
|
+
**********
|
|
38
|
+
|
|
39
|
+
* `ADR 0032`_
|
|
40
|
+
* `Instructor Dashboard Permissions`_
|
|
41
|
+
|
|
42
|
+
.. _ADR 0032: 0032-applets-for-built-in-authorization-capabilities.rst
|
|
43
|
+
.. _Instructor Dashboard Permissions: https://openedx.atlassian.net/wiki/spaces/OEPM/pages/6789234689/Instructor+Dashboard+Permissions
|
{openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/authz/schema/course_roles.yaml
RENAMED
|
@@ -88,7 +88,6 @@ roles:
|
|
|
88
88
|
description: Can create and edit course content, but cannot publish or change critical course settings.
|
|
89
89
|
scopes:
|
|
90
90
|
- course-v1
|
|
91
|
-
hidden: true
|
|
92
91
|
permissions:
|
|
93
92
|
- courses.view_course
|
|
94
93
|
- courses.view_course_updates
|
|
@@ -118,7 +117,6 @@ roles:
|
|
|
118
117
|
description: Can view course content and settings, but cannot make changes.
|
|
119
118
|
scopes:
|
|
120
119
|
- course-v1
|
|
121
|
-
hidden: true
|
|
122
120
|
permissions:
|
|
123
121
|
- courses.view_course
|
|
124
122
|
- courses.view_course_updates
|
{openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/engine/schema/authz-schema-v1.json
RENAMED
|
@@ -151,6 +151,14 @@
|
|
|
151
151
|
"minItems": 1,
|
|
152
152
|
"uniqueItems": true
|
|
153
153
|
},
|
|
154
|
+
"role_permission_list": {
|
|
155
|
+
"description": "A list of unique, complete permission identifiers. The list may be empty when role extensions contribute every permission.",
|
|
156
|
+
"type": "array",
|
|
157
|
+
"items": {
|
|
158
|
+
"$ref": "#/$defs/permission_id"
|
|
159
|
+
},
|
|
160
|
+
"uniqueItems": true
|
|
161
|
+
},
|
|
154
162
|
"scope_list": {
|
|
155
163
|
"description": "A non-empty list of unique scope namespaces.",
|
|
156
164
|
"type": "array",
|
|
@@ -240,7 +248,7 @@
|
|
|
240
248
|
},
|
|
241
249
|
"role": {
|
|
242
250
|
"title": "Role",
|
|
243
|
-
"description": "A static role
|
|
251
|
+
"description": "A static role definition. Permissions may be assigned by this definition or contributed by role extensions.",
|
|
244
252
|
"type": "object",
|
|
245
253
|
"additionalProperties": false,
|
|
246
254
|
"required": ["id", "display_name", "description", "scopes", "permissions"],
|
|
@@ -269,9 +277,9 @@
|
|
|
269
277
|
},
|
|
270
278
|
"permissions": {
|
|
271
279
|
"title": "Role permissions",
|
|
272
|
-
"description": "
|
|
280
|
+
"description": "Permissions assigned by this base definition. Role extensions may contribute the complete permission set.",
|
|
273
281
|
"examples": [["courses.view_course"]],
|
|
274
|
-
"$ref": "#/$defs/
|
|
282
|
+
"$ref": "#/$defs/role_permission_list"
|
|
275
283
|
},
|
|
276
284
|
"icon": {
|
|
277
285
|
"title": "Role icon",
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
Rules come from ADR 0017 §4 and the field reference:
|
|
4
4
|
|
|
5
5
|
Per-document checks:
|
|
6
|
+
* Roles with no base permissions are accepted with a warning because
|
|
7
|
+
``role_extensions`` may contribute their complete permission set.
|
|
6
8
|
* ``icon`` values, where present, are valid ``@openedx/paragon/icons`` names
|
|
7
9
|
(ADR 0017 §4). The allowed set is vendored in :mod:`paragon_icons`
|
|
8
10
|
(regenerate with ``make paragon_icons``; see ADR 0029).
|
|
@@ -104,6 +106,7 @@ class SchemaValidator:
|
|
|
104
106
|
|
|
105
107
|
for role in document.roles:
|
|
106
108
|
issues.extend(self._check_icon(role.icon, f"role {role.id}", sid))
|
|
109
|
+
issues.extend(self._check_permissions(role.id, role.permissions, sid))
|
|
107
110
|
|
|
108
111
|
for extension in document.role_extensions:
|
|
109
112
|
issues.extend(self._check_icon(extension.icon, f"role_extension {extension.role_id}", sid))
|
|
@@ -203,6 +206,19 @@ class SchemaValidator:
|
|
|
203
206
|
return [ValidationIssue(IssueLevel.WARNING, f"Duplicate identical {kind} {key!r}.", sid)]
|
|
204
207
|
return [ValidationIssue(IssueLevel.ERROR, f"Conflicting {kind} definition for {key!r}.", sid)]
|
|
205
208
|
|
|
209
|
+
@staticmethod
|
|
210
|
+
def _check_permissions(role_id: str, permissions: tuple[str, ...], sid: str) -> list[ValidationIssue]:
|
|
211
|
+
"""Warn when a role relies entirely on permissions from role extensions."""
|
|
212
|
+
if permissions:
|
|
213
|
+
return []
|
|
214
|
+
return [
|
|
215
|
+
ValidationIssue(
|
|
216
|
+
IssueLevel.WARNING,
|
|
217
|
+
f"role {role_id!r} declares no base permissions; role_extensions must contribute them.",
|
|
218
|
+
sid,
|
|
219
|
+
)
|
|
220
|
+
]
|
|
221
|
+
|
|
206
222
|
@staticmethod
|
|
207
223
|
def _check_role_permission_scope(
|
|
208
224
|
role_id: str,
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Tests for the published authorization JSON Schema."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from importlib.resources import files
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
from jsonschema import Draft202012Validator, ValidationError
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.fixture(name="schema_validator", scope="module")
|
|
11
|
+
def fixture_schema_validator():
|
|
12
|
+
"""Build a validator from the packaged version 1 schema."""
|
|
13
|
+
schema_path = files("openedx_authz.engine.schema").joinpath("authz-schema-v1.json")
|
|
14
|
+
schema = json.loads(schema_path.read_text(encoding="utf-8"))
|
|
15
|
+
return Draft202012Validator(schema)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class TestPublishedAuthorizationJsonSchema:
|
|
19
|
+
"""The published schema enforces the supported permission-list shapes."""
|
|
20
|
+
|
|
21
|
+
def test_role_may_declare_an_empty_permission_list(self, schema_validator):
|
|
22
|
+
"""A base role may rely entirely on role extensions for its permissions."""
|
|
23
|
+
contribution = {
|
|
24
|
+
"schema_version": "1.0",
|
|
25
|
+
"priority": 100,
|
|
26
|
+
"roles": [
|
|
27
|
+
{
|
|
28
|
+
"id": "course_staff",
|
|
29
|
+
"display_name": "Course Staff",
|
|
30
|
+
"description": "Administers a course.",
|
|
31
|
+
"scopes": ["course-v1"],
|
|
32
|
+
"permissions": [],
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
schema_validator.validate(contribution)
|
|
38
|
+
|
|
39
|
+
def test_role_extension_permission_edits_remain_non_empty(self, schema_validator):
|
|
40
|
+
"""An extension cannot use an empty permission edit to satisfy its change requirement."""
|
|
41
|
+
contribution = {
|
|
42
|
+
"schema_version": "1.0",
|
|
43
|
+
"priority": 100,
|
|
44
|
+
"role_extensions": [{"role_id": "course_staff", "add_permissions": []}],
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
with pytest.raises(ValidationError):
|
|
48
|
+
schema_validator.validate(contribution)
|
|
@@ -12,8 +12,9 @@ from unittest import mock
|
|
|
12
12
|
from openedx_authz.engine.policy import PolicyStore
|
|
13
13
|
from openedx_authz.engine.renderer import PolicyRenderer, SchemaApplier
|
|
14
14
|
from openedx_authz.engine.schema.compilation import SchemaCompiler
|
|
15
|
+
from openedx_authz.engine.schema.validation import SchemaValidator
|
|
15
16
|
|
|
16
|
-
from .factories import category, make_document, permission, role
|
|
17
|
+
from .factories import category, extension, make_document, permission, role
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
class TestPolicyRendering:
|
|
@@ -68,6 +69,29 @@ class TestPolicyRendering:
|
|
|
68
69
|
scopes = {row.scope for row in rendered.rows}
|
|
69
70
|
assert scopes == {"course-v1^*", "ccx-v1^*"}
|
|
70
71
|
|
|
72
|
+
def test_role_extensions_supply_all_permissions_for_an_empty_base_role(self):
|
|
73
|
+
"""An empty base role validates, compiles, and renders its extension permissions."""
|
|
74
|
+
base = make_document(
|
|
75
|
+
"roles",
|
|
76
|
+
categories=[category("enrollments")],
|
|
77
|
+
permissions=[permission(name="view_enrollments", cat="enrollments")],
|
|
78
|
+
roles=[role(rid="course_staff", permissions=())],
|
|
79
|
+
)
|
|
80
|
+
contribution = make_document(
|
|
81
|
+
"enrollments",
|
|
82
|
+
role_extensions=[extension("course_staff", add_permissions=("courses.view_enrollments",))],
|
|
83
|
+
)
|
|
84
|
+
validator = SchemaValidator()
|
|
85
|
+
|
|
86
|
+
assert not any(issue.is_error for issue in validator.validate([base, contribution]))
|
|
87
|
+
schema = SchemaCompiler().compile([base, contribution])
|
|
88
|
+
assert not any(issue.is_error for issue in validator.validate_compiled(schema))
|
|
89
|
+
|
|
90
|
+
rendered = PolicyRenderer().render(schema)
|
|
91
|
+
assert [row.as_policy() for row in rendered.rows] == [
|
|
92
|
+
["role^course_staff", "act^courses.view_enrollments", "course-v1^*", "allow"]
|
|
93
|
+
]
|
|
94
|
+
|
|
71
95
|
|
|
72
96
|
class TestPolicyStoreInjection:
|
|
73
97
|
"""``SchemaApplier`` holds only a :class:`PolicyStore`, never the enforcer.
|
{openedx_authz-2.3.0 → openedx_authz-2.5.0}/src/openedx_authz/tests/schema/test_validation.py
RENAMED
|
@@ -66,6 +66,16 @@ class TestDocumentValidation:
|
|
|
66
66
|
messages = [i.message for i in _errors(SchemaValidator().validate([doc]))]
|
|
67
67
|
assert any("unknown role" in m for m in messages)
|
|
68
68
|
|
|
69
|
+
def test_role_without_base_permissions_warns(self):
|
|
70
|
+
"""An empty base permission list is accepted but reported."""
|
|
71
|
+
doc = make_document("roles", roles=[role(rid="course_editor", permissions=())])
|
|
72
|
+
|
|
73
|
+
issues = SchemaValidator().validate([doc])
|
|
74
|
+
|
|
75
|
+
assert not _errors(issues)
|
|
76
|
+
assert any("role 'course_editor' declares no base permissions" in i.message for i in _warnings(issues))
|
|
77
|
+
assert [i.source_id for i in _warnings(issues)] == [make_source("roles").source_id]
|
|
78
|
+
|
|
69
79
|
def test_conflicting_duplicate_definition_is_error(self):
|
|
70
80
|
"""Two definitions with the same id but different content conflict."""
|
|
71
81
|
doc = make_document(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openedx-authz
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.0
|
|
4
4
|
Summary: Open edX AuthZ provides the architecture and foundations of the authorization framework.
|
|
5
5
|
Author-email: Open edX Project <oscm@openedx.org>
|
|
6
6
|
License-Expression: AGPL-3.0-or-later
|
|
@@ -73,6 +73,8 @@ docs/decisions/0028-api-contract-for-role-catalog.rst
|
|
|
73
73
|
docs/decisions/0029-paragon-icon-list-maintenance.rst
|
|
74
74
|
docs/decisions/0030-tutor-implementation-authz-schema-discovery.rst
|
|
75
75
|
docs/decisions/0031-priority-applies-to-role-extensions-only.rst
|
|
76
|
+
docs/decisions/0032-applets-for-built-in-authorization-capabilities.rst
|
|
77
|
+
docs/decisions/0033-shared-applet-for-course-team-roles.rst
|
|
76
78
|
docs/decisions/README.rst
|
|
77
79
|
docs/how-tos/index.rst
|
|
78
80
|
docs/quickstarts/index.rst
|
|
@@ -244,6 +246,7 @@ src/openedx_authz/tests/schema/factories.py
|
|
|
244
246
|
src/openedx_authz/tests/schema/test_apply.py
|
|
245
247
|
src/openedx_authz/tests/schema/test_compilation.py
|
|
246
248
|
src/openedx_authz/tests/schema/test_discovery.py
|
|
249
|
+
src/openedx_authz/tests/schema/test_json_schema.py
|
|
247
250
|
src/openedx_authz/tests/schema/test_load_authz_schema_command.py
|
|
248
251
|
src/openedx_authz/tests/schema/test_loading.py
|
|
249
252
|
src/openedx_authz/tests/schema/test_parsing.py
|
|
@@ -62,6 +62,8 @@
|
|
|
62
62
|
"docs/decisions/0029-paragon-icon-list-maintenance.rst",
|
|
63
63
|
"docs/decisions/0030-tutor-implementation-authz-schema-discovery.rst",
|
|
64
64
|
"docs/decisions/0031-priority-applies-to-role-extensions-only.rst",
|
|
65
|
+
"docs/decisions/0032-applets-for-built-in-authorization-capabilities.rst",
|
|
66
|
+
"docs/decisions/0033-shared-applet-for-course-team-roles.rst",
|
|
65
67
|
"docs/decisions/README.rst",
|
|
66
68
|
"docs/getting_started.rst",
|
|
67
69
|
"docs/how-tos/index.rst",
|
|
@@ -224,6 +226,7 @@
|
|
|
224
226
|
"src/openedx_authz/tests/schema/test_apply.py",
|
|
225
227
|
"src/openedx_authz/tests/schema/test_compilation.py",
|
|
226
228
|
"src/openedx_authz/tests/schema/test_discovery.py",
|
|
229
|
+
"src/openedx_authz/tests/schema/test_json_schema.py",
|
|
227
230
|
"src/openedx_authz/tests/schema/test_load_authz_schema_command.py",
|
|
228
231
|
"src/openedx_authz/tests/schema/test_loading.py",
|
|
229
232
|
"src/openedx_authz/tests/schema/test_parsing.py",
|
|
@@ -1553,6 +1553,7 @@ dev = [
|
|
|
1553
1553
|
{ name = "doc8" },
|
|
1554
1554
|
{ name = "edx-i18n-tools" },
|
|
1555
1555
|
{ name = "edx-lint" },
|
|
1556
|
+
{ name = "jsonschema" },
|
|
1556
1557
|
{ name = "polib" },
|
|
1557
1558
|
{ name = "pydocstyle" },
|
|
1558
1559
|
{ name = "pytest-cov" },
|
|
@@ -1573,6 +1574,7 @@ doc = [
|
|
|
1573
1574
|
{ name = "ddt" },
|
|
1574
1575
|
{ name = "django" },
|
|
1575
1576
|
{ name = "doc8" },
|
|
1577
|
+
{ name = "jsonschema" },
|
|
1576
1578
|
{ name = "polib" },
|
|
1577
1579
|
{ name = "pytest-cov" },
|
|
1578
1580
|
{ name = "pytest-django" },
|
|
@@ -1588,6 +1590,7 @@ quality = [
|
|
|
1588
1590
|
{ name = "ddt" },
|
|
1589
1591
|
{ name = "django" },
|
|
1590
1592
|
{ name = "edx-lint" },
|
|
1593
|
+
{ name = "jsonschema" },
|
|
1591
1594
|
{ name = "polib" },
|
|
1592
1595
|
{ name = "pydocstyle" },
|
|
1593
1596
|
{ name = "pytest-cov" },
|
|
@@ -1599,6 +1602,7 @@ test = [
|
|
|
1599
1602
|
{ name = "coverage" },
|
|
1600
1603
|
{ name = "ddt" },
|
|
1601
1604
|
{ name = "django" },
|
|
1605
|
+
{ name = "jsonschema" },
|
|
1602
1606
|
{ name = "polib" },
|
|
1603
1607
|
{ name = "pytest-cov" },
|
|
1604
1608
|
{ name = "pytest-django" },
|
|
@@ -1607,6 +1611,7 @@ test-base = [
|
|
|
1607
1611
|
{ name = "code-annotations" },
|
|
1608
1612
|
{ name = "coverage" },
|
|
1609
1613
|
{ name = "ddt" },
|
|
1614
|
+
{ name = "jsonschema" },
|
|
1610
1615
|
{ name = "polib" },
|
|
1611
1616
|
{ name = "pytest-cov" },
|
|
1612
1617
|
{ name = "pytest-django" },
|
|
@@ -1648,6 +1653,7 @@ dev = [
|
|
|
1648
1653
|
{ name = "doc8" },
|
|
1649
1654
|
{ name = "edx-i18n-tools" },
|
|
1650
1655
|
{ name = "edx-lint" },
|
|
1656
|
+
{ name = "jsonschema" },
|
|
1651
1657
|
{ name = "polib" },
|
|
1652
1658
|
{ name = "pydocstyle" },
|
|
1653
1659
|
{ name = "pytest-cov" },
|
|
@@ -1667,6 +1673,7 @@ doc = [
|
|
|
1667
1673
|
{ name = "ddt" },
|
|
1668
1674
|
{ name = "django", specifier = ">=5.2,<6.0" },
|
|
1669
1675
|
{ name = "doc8" },
|
|
1676
|
+
{ name = "jsonschema" },
|
|
1670
1677
|
{ name = "polib" },
|
|
1671
1678
|
{ name = "pytest-cov" },
|
|
1672
1679
|
{ name = "pytest-django" },
|
|
@@ -1681,6 +1688,7 @@ quality = [
|
|
|
1681
1688
|
{ name = "ddt" },
|
|
1682
1689
|
{ name = "django", specifier = ">=5.2,<6.0" },
|
|
1683
1690
|
{ name = "edx-lint" },
|
|
1691
|
+
{ name = "jsonschema" },
|
|
1684
1692
|
{ name = "polib" },
|
|
1685
1693
|
{ name = "pydocstyle" },
|
|
1686
1694
|
{ name = "pytest-cov" },
|
|
@@ -1692,6 +1700,7 @@ test = [
|
|
|
1692
1700
|
{ name = "coverage" },
|
|
1693
1701
|
{ name = "ddt" },
|
|
1694
1702
|
{ name = "django", specifier = ">=5.2,<6.0" },
|
|
1703
|
+
{ name = "jsonschema" },
|
|
1695
1704
|
{ name = "polib" },
|
|
1696
1705
|
{ name = "pytest-cov" },
|
|
1697
1706
|
{ name = "pytest-django" },
|
|
@@ -1700,6 +1709,7 @@ test-base = [
|
|
|
1700
1709
|
{ name = "code-annotations" },
|
|
1701
1710
|
{ name = "coverage" },
|
|
1702
1711
|
{ name = "ddt" },
|
|
1712
|
+
{ name = "jsonschema" },
|
|
1703
1713
|
{ name = "polib" },
|
|
1704
1714
|
{ name = "pytest-cov" },
|
|
1705
1715
|
{ name = "pytest-django" },
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_authz-2.3.0 → openedx_authz-2.5.0}/.github/workflows/add-depr-ticket-to-depr-board.yml
RENAMED
|
File without changes
|
{openedx_authz-2.3.0 → openedx_authz-2.5.0}/.github/workflows/add-remove-label-on-comment.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_authz-2.3.0 → openedx_authz-2.5.0}/.github/workflows/upgrade-python-requirements.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|