* fix: allow global readonly superusers to access all organization data without FULL_ACCESS (PROJQUAY-9798)
This is a comprehensive fix for multiple endpoints where global readonly superusers
were incorrectly blocked from accessing organization data when
FEATURE_SUPERUSERS_FULL_ACCESS was set to false.
Fixed endpoints in endpoints/api/logs.py:
- OrgLogs.get() - Organization audit logs
- OrgAggregateLogs.get() - Aggregated organization logs
- ExportOrgLogs.post() - Export organization logs
Fixed endpoints in endpoints/api/team.py:
- TeamMemberList.get() - Team member list
- TeamPermissions.get() - Team repository permissions
Fixed endpoints in endpoints/api/organization.py:
- OrganizationMemberList.get() - Organization member list
- OrganizationMember.get() - Individual member details
- OrganizationApplications.get() - OAuth application list
- OrganizationApplication.get() - Individual application details
Fixed endpoints in endpoints/api/prototype.py:
- PermissionPrototypeList.get() - Default permission prototypes
All endpoints now use consistent permission logic:
permission.can() OR
allow_if_global_readonly_superuser() OR
allow_if_superuser_with_full_access()
Added comprehensive tests verifying:
1. Global readonly superusers CAN access all data for auditing, regardless
of FEATURE_SUPERUSERS_FULL_ACCESS setting
2. Regular superusers are still blocked when FEATURE_SUPERUSERS_FULL_ACCESS
is false (correct behavior)
* fix(test): ensure owners team exists for testorglogs org in test setup
Addresses review feedback from PR #4549 comment #2539202868.
The test was attempting to access the 'owners' team in 'testorglogs'
org, but the fixture only created the organization without creating
any teams. This could cause the test to receive a 404 (team not found)
instead of 403 (permission denied), making it pass for the wrong reason.
Also simplified the test logic to only expect 403 since the team now
exists in the fixtures, ensuring the test validates permission blocking
rather than missing resources.
fix(api): implement proper superuser permission model and fix access controls
Fixes multiple issues with superuser functionality and implements a comprehensive
permission model for FEATURE_SUPERUSERS_FULL_ACCESS:
**Permission Model:**
- Global Readonly Superusers (auditors): Always have read access to all content,
independent of FEATURE_SUPERUSERS_FULL_ACCESS setting
- Regular Superusers: Can access /v1/superuser endpoints and their own content.
Require FEATURE_SUPERUSERS_FULL_ACCESS=true for cross-namespace read access
- Full Access Superusers: Regular superusers with FULL_ACCESS enabled, can
perform CRUD on content they don't own
- Write operations: Only allowed for full access superusers (global readonly
superusers never get write access)
**Key Fixes:**
1. Fixed superuser panel endpoints returning 403 when FULL_ACCESS was disabled.
Basic panel operations (user list, logs, org list, messages) now work with
just FEATURE_SUPER_USERS enabled.
2. Updated decorators to properly differentiate between basic superuser
operations and permission bypass operations.
3. Implemented license bypass: Superusers with FULL_ACCESS now bypass
license/quota limits when creating or modifying private repositories.
4. Fixed 18 permission checks across 7 files to properly implement cross-namespace
access controls for different superuser types.
**Changes:**
- endpoints/api/__init__.py: Fixed allow_if_superuser(), require_repo_permission, and decorators
- endpoints/api/superuser.py: Updated SuperUserAppTokens permission check
- endpoints/api/organization.py: Updated 4 GET endpoints to require FULL_ACCESS
- endpoints/api/namespacequota.py: Updated 2 GET endpoints to require FULL_ACCESS
- endpoints/api/team.py: Updated 2 GET endpoints to require FULL_ACCESS
- endpoints/api/prototype.py: Updated 1 GET endpoint to require FULL_ACCESS
- endpoints/api/policy.py: Updated auto-prune policy endpoints
- endpoints/api/robot.py: Updated robot endpoints
- endpoints/api/build.py: Updated repository build logs
- endpoints/api/repository.py: Added license bypass for superusers with FULL_ACCESS
- endpoints/api/repository_models_pre_oci.py: Updated repository visibility query
- endpoints/api/logs.py: Fixed log access to require FULL_ACCESS for permission bypass
- endpoints/api/test/test_superuser_full_access.py: Added comprehensive test suite
- endpoints/api/test/test_appspecifictoken.py: Updated test mocking and added 403 test
- test/test_api_usage.py: Updated test expectations for license bypass behavior
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements global read-only superuser permissions for v1 endpoints, adjusts superuser write checks, and updates app token listing and detail endpoints; includes comprehensive tests.
---------
Co-authored-by: Claude <noreply@anthropic.com>
* add migration for orgrhskus table
* add endpoints for managing and listing skus bound to an org
* create checks in billing flow to look for org-bound skus
* refactor RH marketplace api objects to be more usable in tests
* update cypress test db data and exclude it from pre-commit hook formatting
* api: feature to limit org creation to superusers
Introduces the following configuration flags:
FEATURE_SUPERUSERS_ORG_CREATION_ONLY:
Limit org creation to superusers only
FEATURE_SUPERUSERS_FULL_ACCESS:
Grant superusers read/write access to registry content in all namespaces
FEATURE_RESTRICTED_USERS:
Users considered as restricted are not anle to create organization
RESTRICTED_USERS_WHITELIST:
Whitelist for FEATURE_RESTRICTED_USERS
RESTRICTED_USER_INCLUDE_ROBOTS:
Whether or not to include the user namespace's robots
RESTRICTED_USER_READ_ONLY:
Only allow read-only operations for restricted users
* Revert superuser repositorylist endpoint
* Change verbs to use a DerivedStorageForManifest table instead of DerivedStorageForImage
This allows us to deprecate the DerivedStorageForImage table.
Fixes https://issues.redhat.com/browse/PROJQUAY-519
* Change uploaded blob tracking to use its own table and deprecate
RepositoryTag
* Start recording the compressed layers size and config media type on the
manifest row in the database
NOTE: This change includes a database migration which will *lock* the
manifest table
* Change tag API to return the layers size from the manifest
* Remove unused code
* Add new config_media_type field to OCI types
* Fix secscan V2 test for us no longer writing temp images
* Remove unused uploading field
* Switch registry model to use synthetic legacy images
Legacy images are now (with exception of the V2 security model) read from the *manifest* and sythensized in memory. The legacy image IDs are generated realtime based on the hashids library. This change also further deprecates a bunch of our Image APIs, reducing them to only returning the image IDs, and emptying out the remaining metadata (to avoid the requirement of us loading the information for the manifest from storage).
This has been tested with our full clients test suite with success.
* Add a backfill worker for manifest layers compressed sizes
* Change image tracks into manifest tracks now that we no longer have
manifest-less tags
* Add back in the missing method
* Add missing joins to reduce extra queries
* Remove unnecessary join when looking up legacy images
* Remove extra hidden filter on tag queries
* Further DB improvements
* Delete all Verbs, as they were deprecated
* Add back missing parameter in manifest data type
* Fix join to return None for the robot if not defined on mirror config
* switch to using secscan_v4_model for all indexing and remove most of secscan_v2_model code
* Add a missing join
* Remove files accidentally re-added due to rebase
* Add back hashids lib
* Rebase fixes
* Fix broken test
* Remove unused GPG signer now that ACI conversion is removed
* Remove duplicated repomirrorworker
* Remove unused notification code for secscan. We'll re-add it once Clair
V4 security notifications are ready to go
* Fix formatting
* Stop writing Image rows when creating manifests
* Stop writing empty layer blobs for manifests
As these blobs are shared, we don't need to write ManifestBlob rows
for them
* Remove further unused code
* Add doc comment to _build_blob_map
* Add unit test for synthetic V1 IDs
* Remove unused import
* Add an invalid value test to synthetic ID decode tests
* Add manifest backfill worker back in
Seems to have been removed at some point
* Add a test for cached active tags
* Rename test_shared to not conflict with another same-named test file
Pytest doesn't like having two test modules with the same name
* Have manifestbackfillworker also copy over the config_media_type if present
Co-authored-by: alecmerdler <alecmerdler@gmail.com>
* Move truthy_bool to a neutral location.
* Add dba operator migration version generation code.
Change existing migrations to use an injected and wrapped op.
* Generate databasemigration hints files for all existing migrations.
* Reformat with black.