Skip to content

Commit 3d67b0f

Browse files
committed
fix: address code review observations for multi-platform integration
- Add explicit check for accounts already linked to other users in OAuth callback - Change GitLab client to use standard Bearer auth header for OAuth consistency - Update implementation tracker to mark P1 deliverables complete - Add note about Bitbucket date filtering limitation
1 parent 069337c commit 3d67b0f

4 files changed

Lines changed: 30 additions & 11 deletions

File tree

apps/web/src/app/api/auth/[provider]/callback/route.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,23 @@ export async function GET(
138138

139139
const isFirstConnection = count === 0;
140140

141+
// Check if this external account is already linked to a different user
142+
const { data: existingConnection } = await service
143+
.from("platform_connections")
144+
.select("user_id")
145+
.eq("platform", provider)
146+
.eq("platform_user_id", platformUserId)
147+
.single();
148+
149+
if (existingConnection && existingConnection.user_id !== userId) {
150+
// This external account is linked to another user
151+
console.warn(`${provider} account ${platformUserId} already linked to user ${existingConnection.user_id}, current user: ${userId}`);
152+
url.pathname = "/login";
153+
url.searchParams.set("error", "account_already_linked");
154+
url.searchParams.set("provider", provider);
155+
return NextResponse.redirect(url);
156+
}
157+
141158
// Prepare upsert data
142159
const upsertData = {
143160
user_id: userId,
@@ -153,10 +170,10 @@ export async function GET(
153170
...(isFirstConnection ? { is_primary: true } : {}),
154171
};
155172

156-
// Upsert platform connection
173+
// Upsert platform connection using user_id + platform to handle reconnections properly
157174
await service.from("platform_connections").upsert(
158175
upsertData,
159-
{ onConflict: "platform, platform_user_id" }
176+
{ onConflict: "user_id, platform" }
160177
);
161178
}
162179

apps/web/src/app/login/LoginButton.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { createSupabaseBrowserClient } from "@/lib/supabase/browser";
44
import { useState } from "react";
55
import { OAUTH_CONFIG, OAuthProvider } from "@/lib/platforms/oauth";
6+
import { PlatformIcon } from "@/components/icons/platform";
67

78
interface LoginButtonProps {
89
provider?: OAuthProvider;
@@ -77,10 +78,11 @@ export default function LoginButton({ provider = "github" }: LoginButtonProps) {
7778
<div className="flex flex-col gap-3">
7879
<button
7980
type="button"
80-
className="rounded-md bg-black px-4 py-2 text-white disabled:opacity-60"
81+
className="flex items-center justify-center gap-2 rounded-md bg-black px-4 py-2 text-white disabled:opacity-60"
8182
onClick={signIn}
8283
disabled={isLoading}
8384
>
85+
<PlatformIcon platform={provider} className="h-5 w-5" />
8486
{isLoading ? "Signing in..." : `Sign in with ${config.label}`}
8587
</button>
8688
{error ? <p className="whitespace-pre-wrap text-sm text-red-600">{error}</p> : null}

docs/implementation-trackers/multi-platform-integration.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ This tracker accompanies `docs/prd/platform/prd-multi-platform-integration.md`.
88
### P1. Platform Client Abstraction
99
**Task:** Create platform abstraction layer in `@vibed/core` without breaking existing functionality.
1010
**Deliverables:**
11-
- [ ] Platform types created (`packages/core/src/platforms/types.ts`)
12-
- [ ] GitHub client extracted from existing code
13-
- [ ] GitLab client implemented (including file_paths via diff endpoint)
14-
- [ ] Bitbucket client implemented (including file_paths via diffstat endpoint)
15-
- [ ] Factory and exports created (`packages/core/src/platforms/index.ts`)
16-
- [ ] Unit tests for all platform clients
11+
- [x] Platform types created (`packages/core/src/platforms/types.ts`)
12+
- [x] GitHub client extracted from existing code
13+
- [x] GitLab client implemented (including file_paths via diff endpoint)
14+
- [x] Bitbucket client implemented (including file_paths via diffstat endpoint; note: no date filtering support, uses recent commits)
15+
- [x] Factory and exports created (`packages/core/src/platforms/index.ts`)
16+
- [x] Unit tests for all platform clients (`packages/core/src/__tests__/platform-clients.test.ts`)
1717
**Success Criteria:** `npm run type-check` and `npm run test` pass; existing analysis works; all clients return `filePaths` in `NormalizedCommit`
1818
**Blocks:** P3, P5, P6
1919

packages/core/src/platforms/gitlab.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ export class GitLabClient implements CommitFetcher, RepoLister {
5757
constructor(
5858
private readonly accessToken: string,
5959
private readonly fetcher: typeof fetch = fetch
60-
) {}
60+
) { }
6161

6262
private async gitlabFetch<T>(url: string): Promise<T> {
6363
const res = await this.fetcher(url, {
6464
headers: {
65-
"PRIVATE-TOKEN": this.accessToken,
65+
Authorization: `Bearer ${this.accessToken}`,
6666
Accept: "application/json",
6767
},
6868
});

0 commit comments

Comments
 (0)