Files
HealthLog/src/lib/validations/polar.ts
T
Marc-André Bombeck 38c7604ce4 feat(integrations): per-user Polar and Oura OAuth credentials
Polar and Oura resolved their OAuth client id/secret from the server
environment only, forcing every user on a deploy to share one app. Both
now read per-user BYO keys first, falling back to the shared env app when
unset, mirroring the WHOOP and Fitbit model.

- Add DB-first-then-env resolvers in src/lib/{polar,oura}/credentials.ts,
  encrypting the client id/secret at rest on User.
- Repoint the connect, callback, status routes and the Oura refresh path
  to the user-scoped resolver.
- Add /api/{polar,oura}/credentials (GET/PUT/DELETE) with Zod-validated
  input and userId narrowed from the session.
- Render an optional 'your OAuth app credentials' form on the Polar and
  Oura cards; the status read exposes hasOwnCredentials for the saved
  placeholder. Existing env-only deploys keep working unchanged.
- Cover both resolvers (DB hit, env fallback, no creds) and the card form
  with unit tests; add the new strings across all six locales.
2026-06-14 23:19:47 +02:00

17 lines
658 B
TypeScript

import { z } from "zod/v4";
/**
* Per-user Polar BYO-key credentials. Each self-hoster registers their own
* Polar AccessLink app and pastes the client id/secret into Settings. Stored
* encrypted on `User`. When unset, the integration falls back to the shared
* env-configured OAuth app.
*/
export const polarCredentialsSchema = z.object({
// Trimmed: a trailing space or newline from the portal's copy button reaches
// Polar verbatim and answers as "unknown client".
clientId: z.string().trim().min(1).max(200),
clientSecret: z.string().trim().min(1).max(200),
});
export type PolarCredentialsInput = z.infer<typeof polarCredentialsSchema>;