Skip to content

Show the Integrations (Google Search Console) tab on self-hosted when Google OAuth is configured #1106

Description

@iplanwebsites

First off - thanks for Rybbit. The self-hosting story is genuinely good, and getting an instance up behind our own ingress was painless.

I set up the Google Search Console integration on a self-hosted instance and got everything working on the backend, but there's no way to reach it in the UI. The Integrations tab is hidden unless IS_CLOUD is true:

client/src/components/SiteSettings/SiteSettings.tsx:109
  { key: "integrations", label: t("Integrations"), icon: Plug, hidden: !IS_CLOUD },

client/src/components/SiteSettings/SiteSettings.tsx:186
  {activeTab === "integrations" && IS_CLOUD && <IntegrationsTab disabled={disabled} />}

What made me think this might be unintentional is that the server side isn't gated at all — there's no IS_CLOUD check anywhere in server/src/api/gsc/. With GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET / GOOGLE_REDIRECT_URI set on the backend, the routes work fine on self-host:

$ curl -s -w ' %{http_code}\n' https://<our-instance>/api/gsc/callback
{"error":"Missing code or state parameter"} 400

$ curl -s -w ' %{http_code}\n' https://<our-instance>/api/sites/1/gsc/connect
{"error":"Forbidden"} 403

Both handlers are running — 403 is the admin-access check on an unauthenticated request, and neither returns 500 Google OAuth not configured. So the feature appears fully functional on self-host; it's just that the only entry point to it is hidden.

This is on v2.8.0, and the gate is still present on master as of 806e368.

For contrast, R2 replay storage is gated deliberately and consistently — r2StorageService short-circuits on IS_CLOUD server-side, and the env vars live only in docker-compose.cloud.yml. GSC has the cloud-only compose vars but no server-side gate, which is what made the client-side hiding feel more like an oversight than a product decision.

Describe the solution you'd like

Show the Integrations tab on self-hosted when Google OAuth is actually configured, rather than keying it off IS_CLOUD. Something like exposing a googleOAuthConfigured boolean from the backend config endpoint (true when GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET are both set) and using that for hidden instead. That keeps the tab out of the way for the majority of self-hosters who haven't set up an OAuth client, while letting those who have actually reach it.

If it's simpler, gating on IS_CLOUD || googleOAuthConfigured would preserve today's cloud behaviour exactly.

I'm happy to open a PR if you'd like — just wanted to check first whether the current gating is deliberate, since I might be missing a reason it's cloud-only (quota or verification constraints on the OAuth client, maybe?). Entirely possible there's context I don't have.

Additional context

Worth flagging separately, since anyone who does get the tab enabled will hit it: the GSC error redirects don't land anywhere useful. callback.ts redirects failures to ${BASE_URL}/error, but the client app has no /error route, so the user gets a generic 404 with the message dropped. The "no properties found" branch uses ${CLIENT_URL}, which isn't defined in either compose file or .env.example, producing a Location of undefined/error?.... Your own FEATURE_AUDIT.md:561 documents this. The success path is fine.

Relatedly, both connect.ts:33 and callback.ts:63 fall back to ${process.env.SERVER_URL}/api/gsc/callback when GOOGLE_REDIRECT_URI is unset, but SERVER_URL doesn't seem to be defined anywhere in the repo — so the fallback yields a literal undefined/api/gsc/callback. Setting GOOGLE_REDIRECT_URI explicitly works around it. Happy to split these into their own issue if you'd rather keep this one focused.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions