GitHubSetupCallback (GET /api/github/setup) handles the redirect GitHub sends after a user installs (or re-authorizes) the App. We expect ?installation_id= &state= . We persist the installation row (workspace ↔ installation_id mapping), then bounce the user back to the new Settings →
(w http.ResponseWriter, r *http.Request)
| 297 | // GitHub-tab split would land users on the default profile tab instead of |
| 298 | // the place that shows the connection they just completed. |
| 299 | func (h *Handler) GitHubSetupCallback(w http.ResponseWriter, r *http.Request) { |
| 300 | q := r.URL.Query() |
| 301 | installationIDStr := q.Get("installation_id") |
| 302 | state := q.Get("state") |
| 303 | frontend := strings.TrimSpace(os.Getenv("FRONTEND_ORIGIN")) |
| 304 | if frontend == "" { |
| 305 | frontend = "http://localhost:3000" |
| 306 | } |
| 307 | settingsURL := strings.TrimRight(frontend, "/") + "/settings?tab=github" |
| 308 | |
| 309 | if installationIDStr == "" || state == "" { |
| 310 | http.Redirect(w, r, settingsURL+"&github_error=missing_params", http.StatusFound) |
| 311 | return |
| 312 | } |
| 313 | workspaceID, ok := verifyState(state) |
| 314 | if !ok { |
| 315 | http.Redirect(w, r, settingsURL+"&github_error=invalid_state", http.StatusFound) |
| 316 | return |
| 317 | } |
| 318 | installationID, err := strconv.ParseInt(installationIDStr, 10, 64) |
| 319 | if err != nil { |
| 320 | http.Redirect(w, r, settingsURL+"&github_error=bad_installation_id", http.StatusFound) |
| 321 | return |
| 322 | } |
| 323 | wsUUID, err := parseStrictUUID(workspaceID) |
| 324 | if err != nil { |
| 325 | http.Redirect(w, r, settingsURL+"&github_error=bad_workspace", http.StatusFound) |
| 326 | return |
| 327 | } |
| 328 | // Resolve the installation against GitHub's API to capture display info. |
| 329 | // If the App auth is not configured we still create the row with the |
| 330 | // minimum we know; webhook events will refresh it as soon as one fires. |
| 331 | login, accountType, avatar := fetchInstallationAccount(r.Context(), installationID) |
| 332 | |
| 333 | // Best-effort capture of the connecting user (may be nil if the public |
| 334 | // callback was hit without a session — e.g. user wasn't logged in to |
| 335 | // Multica when they finished the GitHub install). Either way we save |
| 336 | // the row so the workspace owner sees the connection on next reload. |
| 337 | connectedBy := pgtype.UUID{} |
| 338 | if userID := requestUserID(r); userID != "" { |
| 339 | if u, err := parseStrictUUID(userID); err == nil { |
| 340 | connectedBy = u |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | inst, err := h.Queries.CreateGitHubInstallation(r.Context(), db.CreateGitHubInstallationParams{ |
| 345 | WorkspaceID: wsUUID, |
| 346 | InstallationID: installationID, |
| 347 | AccountLogin: login, |
| 348 | AccountType: accountType, |
| 349 | AccountAvatarUrl: ptrToText(avatar), |
| 350 | ConnectedByID: connectedBy, |
| 351 | }) |
| 352 | if err != nil { |
| 353 | slog.Error("github: failed to persist installation", "err", err, "installation_id", installationID) |
| 354 | http.Redirect(w, r, settingsURL+"&github_error=persist_failed", http.StatusFound) |
| 355 | return |
| 356 | } |