Skip to content

Fetch private project and group avatars through the API (#690)#767

Open
rpaasche wants to merge 1 commit into
jenkinsci:masterfrom
rpaasche:fix/690-private-avatar-401
Open

Fetch private project and group avatars through the API (#690)#767
rpaasche wants to merge 1 commit into
jenkinsci:masterfrom
rpaasche:fix/690-private-avatar-401

Conversation

@rpaasche

Copy link
Copy Markdown

The /uploads/-/system/.../avatar web URLs need a browser session, so anonymous fetches 401 on private projects and groups and we end up showing a generated avatar. Detect those URLs, take the id from the path and download the image via ProjectApi/GroupApi.getAvatar() using the matching server's credentials.

The fetch runs on a background thread with no authenticated user, so the credential lookup is wrapped in ACL.as2(SYSTEM2). If the API call fails (e.g. an older GitLab without the endpoint) we fall back to the plain URL, which still works for public projects and groups; user avatars and unknown hosts keep using that path too.
Fixes #690 (JENKINS-64814).

Trade-offs worth noting for review:

  • The background fetch only has the avatar URL, not the folder/source credentialsId, so credentials are resolved from the matching server's configuration. Setups that configure the token only on the folder/source (and leave the server without credentials) will still fall back to the placeholder for private resources.
  • Project/group avatars now always go through the API. getAvatar() exposes no Last-Modified, so the browser re-fetches once per hourly cache refresh (304s still work within a refresh window).

Testing done

  • Unit tests (GitLabAvatarCacheTest) cover the URL→server/type/id matching: project and group avatars, a server URL with a trailing slash, a server hosted under a sub-path, and the cases that must not match (user avatars, other hosts, an id too large to parse).
  • JenkinsRule test (GitLabAvatarCacheCredentialsTest) locks in the regression this PR fixes: on a secured instance, resolving the server credentials directly as the anonymous background user throws AccessDeniedException, while the avatar fetch resolves the token successfully via the SYSTEM impersonation.
  • Manual verification against a private GitLab instance (self-managed, GitLab 17.x): before the change a private group's avatar logged HTTP 401 for .../uploads/-/system/group/avatar/<id>/... and rendered the generated placeholder; after the change (re-scan + reload) the real avatar renders. Confirmed via FINE logging that the API path runs (Fetching avatar via API: ...) and decodes the image.

Submitter checklist

  • Make sure you are opening from a topic/feature/bugfix branch (right side) and not your main branch!
  • Ensure that the pull request title represents the desired changelog entry
  • Please describe what you did
  • Link to relevant issues in GitHub or Jira - [x] Link to relevant pull requests, esp. upstream and downstream changes
  • Ensure you have provided tests that demonstrate the feature works or the issue is fixed

@rpaasche
rpaasche requested a review from jetersen as a code owner July 21, 2026 15:52
The /uploads/-/system/.../avatar web URLs need a browser session, so anonymous
fetches 401 on private projects and groups and we end up showing a generated
avatar. Detect those URLs, take the id from the path and download the image via
ProjectApi/GroupApi.getAvatar() using the matching server's credentials.

The fetch runs on a background thread with no authenticated user, so the
credential lookup is wrapped in ACL.as2(SYSTEM2). If the API call fails (e.g. an
older GitLab without the endpoint) we fall back to the plain URL, which still
works for public projects and groups; user avatars and unknown hosts keep using
that path too.
@rpaasche
rpaasche force-pushed the fix/690-private-avatar-401 branch from a548dde to a77d9da Compare July 21, 2026 16:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[JENKINS-64814] GitLab Branch Source unable to download project avatar

1 participant