* Creates the pending credential draft at click time so its TTL starts when the * user actually initiates the connect. Better Auth's `account.create.after` hook * consumes this draft to materialize the real credential after the OAuth * callback; starting the clock here guarantees the draft outliv
(params: {
userId: string
workspaceId: string
providerId: string
})
| 27 | * credential. |
| 28 | */ |
| 29 | async function createConnectDraft(params: { |
| 30 | userId: string |
| 31 | workspaceId: string |
| 32 | providerId: string |
| 33 | }): Promise<void> { |
| 34 | const { userId, workspaceId, providerId } = params |
| 35 | |
| 36 | const service = getAllOAuthServices().find((s) => s.providerId === providerId) |
| 37 | const serviceName = service?.name ?? providerId |
| 38 | |
| 39 | let displayName = serviceName |
| 40 | try { |
| 41 | const [row] = await db.select({ name: user.name }).from(user).where(eq(user.id, userId)) |
| 42 | if (row?.name) { |
| 43 | displayName = `${row.name}'s ${serviceName}` |
| 44 | } |
| 45 | } catch { |
| 46 | // Fall back to service name only |
| 47 | } |
| 48 | |
| 49 | const now = new Date() |
| 50 | const expiresAt = new Date(now.getTime() + DRAFT_TTL_MS) |
| 51 | await db |
| 52 | .delete(pendingCredentialDraft) |
| 53 | .where( |
| 54 | and(eq(pendingCredentialDraft.userId, userId), lt(pendingCredentialDraft.expiresAt, now)) |
| 55 | ) |
| 56 | await db |
| 57 | .insert(pendingCredentialDraft) |
| 58 | .values({ |
| 59 | id: generateId(), |
| 60 | userId, |
| 61 | workspaceId, |
| 62 | providerId, |
| 63 | displayName, |
| 64 | expiresAt, |
| 65 | createdAt: now, |
| 66 | }) |
| 67 | .onConflictDoUpdate({ |
| 68 | target: [ |
| 69 | pendingCredentialDraft.userId, |
| 70 | pendingCredentialDraft.providerId, |
| 71 | pendingCredentialDraft.workspaceId, |
| 72 | ], |
| 73 | set: { displayName, expiresAt, createdAt: now }, |
| 74 | }) |
| 75 | |
| 76 | logger.info('Created OAuth connect credential draft', { userId, workspaceId, providerId }) |
| 77 | } |
| 78 | |
| 79 | /** |
| 80 | * Browser-initiated entrypoint for linking a generic OAuth2 account. |
no test coverage detected