feat(web): show password setup prompt for OIDC users in CLI config (PROJQUAY-9898)
when using OIDC authentication and the user has no password set, display
an info alert with a "Set password" button to guide users through setting
up their CLI password
Signed-off-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
fix(data): clear pull statistics when tags are deleted (PROJQUAY-9887)
When a tag is deleted and re-pushed, pull statistics now start fresh
at 0 instead of persisting from the deleted tag.
Changes:
- Clear TagPullStatistics in _delete_tag()
- Clear TagPullStatistics in remove_tag_from_timemachine()
- Add tests for tag deletion clearing pull statistics
- Add test for re-push scenario starting with fresh stats
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Signed-off-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: jbpratt <bpratt@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
fix(api): return manifest pull stats for digest-only pulls (PROJQUAY-9877)
When images are pulled by digest only (not by tag), the API endpoint
was returning 0 for manifest_pull_count because it ignored manifest_stats
when tag_stats was None.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
chore(deps): update go version to 1.24.8 (PROJQUAY-9842)
Update go version 1.24.8
Fix for CVE-2025-58183
Co-authored-by: Deirdre Malone <dmalone@redhat.com>
fix(web): disable buttons for global readonly superuser (PROJQUAY-9873)
Global readonly superusers could click Create Message and Service Key
buttons which then failed with 403 errors. These buttons are now disabled
using the existing useSuperuserPermissions hook's canModify flag.
Co-authored-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
chore: add workflow to label original PR on backport merge
When a cherry-pick PR merges to a redhat-* branch, this workflow
labels the original PR with backported/<branch> to track which
releases contain the fix.
Signed-off-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
fix(web): use correct error modal titles for different operations (PROJQUAY-9874)
Previously, all errors on the Organizations page showed "Org deletion failed"
as the modal title, even for unrelated operations like registry size
calculation. This was confusing for Global Readonly Superusers who saw
"Org deletion failed" when trying to calculate registry size.
Changes:
- Separated error states in OrganizationsList.tsx (deletionErr, registryCalcErr)
- Added separate ErrorModal for registry calculation with correct title
- Fixed RepositoriesList.tsx ErrorModal title to "Repository deletion failed"
- Added Cypress test to verify correct error modal title
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
fix(web): show user namespace quota for non-superusers (PROJQUAY-9886)
Normal users couldn't see their own namespace quota in the Organizations
list Size column. The backend already returns quota_report in /api/v1/user/
but the frontend wasn't using it. Added fallback to use current user's
quota_report when superuser data isn't available.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
* fix(web): display avatars for all entries in org table (PROJQUAY-9749)
Previously only organizations and the logged-in user showed avatars.
Now all users and superusers display avatars by passing avatar data
from the API response through component props.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Brady Pratt <bpratt@redhat.com>
* add waits to test
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
---------
Signed-off-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: jbpratt <jbpratt78@gmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
fix(web): hide Enable Team Sync when FEATURE_TEAM_SYNCING is false (PROJQUAY-9878)
The UI was showing the "Enable OIDC Team Sync" button even when
FEATURE_TEAM_SYNCING was disabled in the config. Added check for
config?.features?.TEAM_SYNCING before displaying the team sync button.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Signed-off-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
chore: resolve fork PR labeling 403 errors with workflow_run pattern
Refactor PR auto-labeling using two-workflow pattern to handle fork PRs
securely. The label-status job is replaced with capture-pr-data (read-only)
and a new pr-status-labeler workflow that runs with write permissions via
workflow_run trigger.
Fixes 403 errors when labeling PRs from forks.
Signed-off-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
chore: add automated PR labeling workflow
Implement GitHub Actions workflow to automatically label pull requests
based on changed files, PR status, and target branch.
Features:
- Area labels (area/api, area/web-ui, etc.) based on file paths
- Status labels (needs-rebase, approved) based on PR state and reviews
- Backport labels (backport/redhat-3.x) for PRs targeting release branches
- Works with PRs from forks using pull_request_target trigger
The workflow uses actions/labeler for path-based labeling and
actions/github-script for dynamic status detection.
Signed-off-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Brady Pratt <bpratt@redhat.com>
fix(web): load external scripts only when BILLING enabled (PROJQUAY-9803)
Stripe and StatusPage scripts were hardcoded in index.html, causing
85-second delays in air-gapped/restricted networks as browsers waited
for connection timeouts.
Created useExternalScripts hook to dynamically load scripts only when
BILLING feature is enabled. Scripts load asynchronously to prevent
blocking page render. On-premise deployments (BILLING=false) no longer
make external requests.
Signed-off-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
* fix(oauth): prevent redirect URI validation bypass (PROJQUAY-9849)
Co-authored-by: Claude <noreply@anthropic.com>
* test(oauth): add comprehensive coverage for redirect URI validation (PROJQUAY-9849)
Co-authored-by: Claude <noreply@anthropic.com>
* fix(oauth): add percent-encoding protection and improve test coverage (PROJQUAY-9849)
Co-authored-by: Claude <noreply@anthropic.com>
---------
Co-authored-by: harishsurf <hgovinda@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
fix(ui): show quota consumed column for all users in organizations list (PROJQUAY-9850)
Co-authored-by: harishsurf <hgovinda@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
fix(web): sort Build History by timestamp instead of string (PROJQUAY-9686)
Converts date strings to numeric timestamps for correct chronological sorting
Co-authored-by: Brady Pratt <bpratt@redhat.com>
pullstats: updated bulk upsert function to track correct pull count and timestamp in case of race condition
Co-authored-by: shudeshp <shudeshp@redhat.com>
* fix(test): prevent MySQL deadlocks in parallel proxy model tests (PROJQUAY-0000)
Mark all registry proxy model test classes to run serially using
pytest-xdist group markers. These tests all use the same "quayio-cache"
organization and were causing MySQL deadlocks when run in parallel
across multiple workers with pytest -n auto.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(test): resolve Flask app naming conflict in quotaregistrysizeworker tests (PROJQUAY-0000)
Import Flask app with alias to avoid conflict with pytest 'app' fixture.
The test was using 'app.config' but 'app' resolved to a pytest fixture
definition instead of the Flask application object.
Follows the same pattern as test_securityscanningnotificationworker.py.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Brady Pratt <bpratt@redhat.com>
---------
Signed-off-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
fix(ui): preserve mirroring credentials when updating tag pattern (PROJQUAY-9608)
When updating mirroring configuration fields like tag patterns, credentials
were being cleared because the password field is empty by default for security.
Modified UseMirroringConfig to conditionally exclude credentials from the
update payload when the password field is empty and updating existing config.
This matches the Angular UI behavior where only changed fields are sent.
Added Cypress tests to verify credentials are preserved when updating other
fields without changing the password, and that credentials are included when
explicitly updated.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Signed-off-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
* Fix race conditions in pull metrics tracking and flushing
Replace non-atomic operations with atomic Redis operations to prevent
data loss when concurrent pulls occur during flush operations.
* fixing tests
* updating tests
* added uuid to the rename factors to ensure unique key at concurrent requests
---------
Co-authored-by: shudeshp <shudeshp@redhat.com>
* Fix: Add lazy Redis connection with retry logic for pull metrics
- Implement lazy initialization to prevent startup failures when Redis unavailable
- Add retry logic (3 attempts, 1s delay) for automatic reconnection
- Add health checks before each Redis operation
- Improve error logging from DEBUG to WARNING level
- Fix silent failures after pod restart when Redis not immediately available
This fixes the issue where pull statistics tracking was permanently broken
after registry component restart if Redis wasn't available at startup.
* fixing tests
* fixing tests
---------
Co-authored-by: shudeshp <shudeshp@redhat.com>
Co-authored-by: Shubhra Deshpande <shubhrajayant+github@gmail.com>
Co-authored-by: Brandon Caton <bcaton@redhat.com>
* chore: update ci to use new large ubuntu 24.04 runner
Signed-off-by: Brady Pratt <bpratt@redhat.com>
Co-Authored-By: Dave O'Connor <doconnor@redhat.com>
* fix: add libfreetype6-dev for Ubuntu 24.04 compatibility
The reportlab package requires FreeType development headers to build.
On Ubuntu 24.04, this dependency is not pulled in transitively and
must be explicitly installed. This fixes the "cannot find ft2build.h"
build error.
Added libfreetype6-dev to all jobs that install system dependencies
in CI.yaml and CI-nightly.yaml workflows.
Signed-off-by: Brady Pratt <bpratt@redhat.com>
Co-Authored-By: Dave O'Connor <doconnor@redhat.com>
* chore: set the TEST_DATETIME to a static value
this caused an issue in xdist when generating test names
Signed-off-by: Brady Pratt <bpratt@redhat.com>
* chore: cache pip packages in CI
Signed-off-by: Brady Pratt <bpratt@redhat.com>
* chore: run registry tests with -n auto
Signed-off-by: Brady Pratt <bpratt@redhat.com>
* chore: run psql with -n auto
Signed-off-by: Brady Pratt <bpratt@redhat.com>
* chore: add file locking to prevent parallel test db init race condition
When running pytest -n auto with multiple workers, both workers would
simultaneously execute populate_database(), causing duplicate key
violations on shared tables like imagestoragelocation:
Worker 1: Check if User "devtable" exists → No → Start populating
Worker 2: Check if User "devtable" exists → No → Start populating
Both: INSERT INTO imagestoragelocation (name) VALUES ('local_eu')
Result: IntegrityError - duplicate key violation
Solution: Wrap init_db_path fixture with FileLock to ensure only one
worker initializes the database at a time. The lock file is created
in pytest's shared temp directory, coordinating across all workers.
- First worker acquires lock and populates database
- Subsequent workers wait at lock, then see database is already
populated (via User.get() check in populate_database())
- Works for both PostgreSQL and MySQL
- 300-second timeout prevents deadlocks
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* chore: run mysql with -n auto
Signed-off-by: Brady Pratt <bpratt@redhat.com>
---------
Signed-off-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Dave O'Connor <doconnor@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
chore: add /about and /security static pages to new UI
adds two new static information pages to the React UI:
- /about page with company info cards and bill-of-materials table
- /security page with security practices and features documentation
implementation includes:
- PatternFly components for consistent UI design
- sortable/filterable packages table with pagination
- actual CoreOS and Red Hat logos
- nginx routing configuration for new paths
- webpack config updates to handle image assets from src/assets
Signed-off-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
fix(ui): Add OAuth state parameter for CSRF protection (PROJQUAY-9805)
Implement RFC 6749 Section 10.12 compliant state parameter to prevent
CSRF attacks in OAuth token generation flow.
Changes:
- Generate cryptographically secure state using crypto.randomUUID()
- Store state in sessionStorage before OAuth redirect
- Parent window validates state from popup via postMessage
- Read state from query params (backend echoes it back)
- Display security error for invalid/missing state
- Add Cypress tests for state validation and CSRF protection
Security Impact:
- Prevents CSRF token theft and session fixation attacks
- Complies with OAuth 2.0 security best practices
- React UI only; Angular UI remains unchanged
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: harishsurf <hgovinda@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
* fix(ui): Enable organization/user visibility for read-only superusers (PROJQUAY-6882)
Users listed under GLOBAL_READONLY_SUPER_USERS can now see all
organizations and users in the UI, matching regular superuser visibility
with read-only restrictions on actions.
- Update UseCurrentUser to include global_readonly_super_user in isSuperUser check
- Add Cypress tests for read-only superuser visibility and action restrictions
- Settings column actions correctly hidden via existing canModify permission
Co-authored-by: Claude <noreply@anthropic.com>
* fix(ui): Add global_readonly_super_user field to API responses (PROJQUAY-6882)
- Add global_readonly_super_user field to user API response in endpoints/api/user.py
- Allow read-only superusers to view organization teams in endpoints/api/organization.py
- Allow read-only superusers to view robot permissions in endpoints/api/robot.py
* fix(ui): Prevent read-only superusers from deleting orgs/users
Security fix: Read-only superusers should not be able to delete
orgs or users they don't own, even though they can view them.
* Fix inline import + incorrect assert + add codecov tests
---------
Co-authored-by: harishsurf <hgovinda@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
fix: allow global readonly superusers to access quota limit endpoints (PROJQUAY-9804)
This fixes an issue where global readonly superusers were blocked from
accessing organization quota limit endpoints when FEATURE_SUPERUSERS_FULL_ACCESS
was set to false.
Fixed endpoints in endpoints/api/namespacequota.py:
- OrganizationQuotaLimitList.get() - List quota limits
- OrganizationQuotaLimit.get() - Get individual quota limit
Both endpoints now use the consistent permission pattern:
permission.can() OR
allow_if_global_readonly_superuser() OR
allow_if_superuser_with_full_access()
Added comprehensive tests in test_global_readonly_superuser.py:
- test_global_readonly_superuser_can_access_quota_limit_list
- test_global_readonly_superuser_can_access_individual_quota_limit
- test_regular_superuser_cannot_access_quota_limits_without_full_access
Test implementation uses autouse fixture to ensure FEATURE_SUPERUSERS_FULL_ACCESS
is disabled for all tests in the class, following the pattern from
TestOrganizationLogsAccessWithoutFullAccess.
Tests verify:
1. Global readonly superusers CAN access quota limits for auditing,
regardless of FEATURE_SUPERUSERS_FULL_ACCESS setting
2. Regular superusers are still blocked when FEATURE_SUPERUSERS_FULL_ACCESS
is false (correct security behavior)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Dave O'Connor <doconnor@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
fix(web): fetch build logs from separate endpoint in superuser panel (PROJQUAY-9714)
The superuser build logs feature was calling only
/api/v1/superuser/<build_uuid>/build which returns build metadata but
NOT logs. Logs are available from a separate
/api/v1/superuser/<build_uuid>/logs endpoint that must be called
separately.
Updated fetchBuildLogsSuperuser() to fetch both endpoints in parallel
using Promise.all and merge the results. This matches the behavior of
the old AngularJS UI which called both endpoints separately.
Updated Cypress tests to mock both API endpoints.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Signed-off-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
fix(web): fix inline markdown code rendering (PROJQUAY-9809)
React-markdown v10.x no longer reliably passes the inline prop to
custom code components. Changed detection to check for newlines in
code content instead, which correctly distinguishes inline code from
code blocks.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Brady Pratt <bpratt@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
* updated new UI to ask user to verify the mail when creating new account with email enabled
* fixed failing cypress test
---------
Co-authored-by: shudeshp <shudeshp@redhat.com>