feat(webui): prompt anonymous visitors to log in on the reviews tab - #2148
Draft
netomi wants to merge 1 commit into
Draft
feat(webui): prompt anonymous visitors to log in on the reviews tab#2148netomi wants to merge 1 commit into
netomi wants to merge 1 commit into
Conversation
The reviews tab gave a signed-out visitor no hint that reviewing needs an account: renderButton() returned an empty string whenever there was no user, so the slot where "Write a Review" sits was simply blank. Landing there from an IDE's star-rating link - which is how you get to this tab without ever passing the header - left nothing to act on. On an extension with no reviews yet it was worse, since "Be the first to review this extension" invited an action with no affordance anywhere on the page. Render the existing LoginComponent in that slot instead, labelled "Log in to Review". It already handles both shapes: a single configured provider becomes a direct link, several open the provider picker. Suppressed on a registry with no login providers configured, matching the guard the header and the publish page already use. This is the nudge asked for in #1975. Redirecting back to the extension afterwards is deliberately not part of it - the login lands on the landing page as before, since carrying a target across the OAuth2 dance needs server-side work. Refs #1975 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft — the nudge half of #1975. Opening early for feedback; expect refinements.
The problem
On the reviews tab,
renderButton()bailed out whenever there was no user, so the slot where Write a Review sits was simply blank for a signed-out visitor:The path in the issue is arriving from an IDE's star-rating link, which lands you on this tab without ever passing the header — so there was nothing on the page to act on, and nothing saying an account is needed. On an extension with no reviews yet it reads worse, since "Be the first to review this extension" invites an action that has no affordance anywhere on screen.
The change
Handle the signed-out case first and render the existing
LoginComponentin that slot, labelled Log in to Review. Reusing that component rather than hand-rolling a button means no new login plumbing:/oauth2/authorization/{provider};loginProvidersguardmenu-content.tsxandpublish-page.tsxalready use.The
!reviewListcheck moved below it, since the prompt doesn't depend on the list having loaded — only the signed-in branches do, to know whether this user already reviewed.Be the first to review this extensionis left as-is: with a login button directly above it, it now reads as an invitation with a real affordance.Scope: this is only the nudge
@netomi's suggestion in the issue was to also redirect back to the current URL after login. That is deliberately not here — login still lands on the landing page as before. It needs server-side work, and two approaches that look like they'd work don't:
CustomAuthenticationSuccessHandlerextendsSavedRequestAwareAuthenticationSuccessHandlerso it would honour one, but the entry point isHttp403ForbiddenEntryPoint(SecurityConfig.java:95), which returns a bare 403 and saves nothing. The webui also links straight to the authorization endpoint, so nothing is ever saved.targetUrlParameter—setTargetUrlParameter(...)reads the parameter off the request that reaches the success handler, i.e. the OAuth2 callback/login/oauth2/code/{provider}, whose URL is pinned by the registeredredirect_uri. A parameter appended to the authorization URL doesn't survive the round trip.So it needs state carried across the dance — a session attribute read back in
determineTargetUrl, or a customAuthorizationRequestRepositoryputting the target in the OAuth2state. Either way the stored target must be validated as a same-origin relative path (reject a scheme, protocol-relative//, backslashes) or it's an open redirect.One thing worth deciding before that part is scoped:
CustomAuthenticationSuccessHandler.java:35unconditionally sends theeclipseprovider to/user-settings/profile. That override runs before any return-to-URL logic would, so wherevereclipseis an enabled login provider the redirect-back would silently not work. In-repo deploy configs register onlygithub, andgithubis the sole built-in default inOAuth2AttributesConfig, soeclipsecomes from out-of-repo config — someone who knows the production config should confirm whether open-vsx.org enables it for login.Testing
New
webui/test/unit/pages/extension-detail/extension-detail-reviews.spec.tsx, 4 cases: single-provider direct link, multi-provider picker, no-providers suppression, and signed-in still getting Write a Review. Confirmed not vacuous — with the source change stashed, the two new-behaviour cases fail and the other two pass.Full webui suite green (51 files, 264 tests);
tsc,eslintandprettierclean.Known loose end
The container's responsive rule at ≤360px is
'& button': { maxWidth: '12rem' }, and MUI renders the single-provider case as an<a>, not a<button>— so that cap doesn't match it. The prompt is wrapped in a<Box>mirroring the existing Write a Review branch, which makes the Box the stretching flex child and leaves the inline-flex anchor content-sized, so it should behave. Reasoned, not eyeballed — worth a look in a narrow viewport.Refs #1975
🤖 Generated with Claude Code