mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
refactor(polar): read the token through the shared OAuth lifecycle
This commit is contained in:
1 parent
a12174bcaa
commit
f9ed07551f
2 files changed
+40
-9
No files matched your search
@@ -11,7 +11,9 @@
|
||||
*/
|
||||
import { prisma } from "@/lib/db";
|
||||
import { decrypt, encrypt } from "@/lib/crypto";
|
||||
import { obtainAccessToken } from "@/lib/integrations/oauth-kit/token";
|
||||
import { getPolarCredentials, type PolarCredentials } from "./client";
|
||||
import { polarTokenDescriptor } from "./oauth-descriptor";
|
||||
|
||||
/**
|
||||
* Resolve the user's Polar OAuth client id/secret, DB-first then env.
|
||||
@@ -80,24 +82,22 @@ export interface PolarConnection {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch + decrypt the user's stored Polar token. Returns null when the user has
|
||||
* Fetch + decrypt the user's stored Polar token, read through the shared OAuth
|
||||
* token lifecycle like every other provider's. Returns null when the user has
|
||||
* not connected Polar (no access token) or the member id is missing.
|
||||
*/
|
||||
export async function getPolarConnection(
|
||||
userId: string,
|
||||
): Promise<PolarConnection | null> {
|
||||
const grant = await obtainAccessToken(polarTokenDescriptor, userId);
|
||||
if (grant.kind !== "token") return null;
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: {
|
||||
polarAccessTokenEncrypted: true,
|
||||
polarUserIdEncrypted: true,
|
||||
},
|
||||
select: { polarUserIdEncrypted: true },
|
||||
});
|
||||
if (!user?.polarAccessTokenEncrypted || !user?.polarUserIdEncrypted) {
|
||||
return null;
|
||||
}
|
||||
if (!user?.polarUserIdEncrypted) return null;
|
||||
return {
|
||||
accessToken: decrypt(user.polarAccessTokenEncrypted),
|
||||
accessToken: grant.accessToken,
|
||||
polarUserId: decrypt(user.polarUserIdEncrypted),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Where a Polar grant lives, for the shared token lifecycle
|
||||
* (`src/lib/integrations/oauth-kit/token.ts`).
|
||||
*
|
||||
* Polar AccessLink tokens do not expire and come without a refresh token, so
|
||||
* the kit only reads them: there is nothing to refresh and nothing to write
|
||||
* back. A revoked grant surfaces as a refused read, and the person reconnects.
|
||||
*/
|
||||
import type { OAuthTokenDescriptor } from "@/lib/integrations/oauth-kit/token";
|
||||
|
||||
export const polarTokenDescriptor: OAuthTokenDescriptor<never> = {
|
||||
provider: "polar",
|
||||
tracksExpiry: false,
|
||||
expiryBufferMs: 0,
|
||||
async readGrant(db, userId) {
|
||||
const row = await db.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: { polarAccessTokenEncrypted: true },
|
||||
});
|
||||
if (!row?.polarAccessTokenEncrypted) return null;
|
||||
return {
|
||||
accessCiphertext: row.polarAccessTokenEncrypted,
|
||||
refreshCiphertext: null,
|
||||
expiresAt: null,
|
||||
};
|
||||
},
|
||||
// Never reached: a grant without a refresh token is never refreshed.
|
||||
writeGrant: async () => 0,
|
||||
loadCredentials: async () => null,
|
||||
refresh: null,
|
||||
};
|
||||
Reference in new issue
Block a user