Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history

google-oauth-env.test.ts

Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.

google-oauth-env.test.tsBlame133 lines · 1 contributor
27d5fd3Claude1import { describe, expect, test } from "bun:test";
9887dd0Claude2import {
3 googleOauthConfigFromEnv,
4 resolveGoogleOauthConfig,
5} from "../lib/sso";
6import type { SsoConfig } from "../db/schema";
7
8/** Minimal SsoConfig row builder for precedence tests. */
9function row(overrides: Partial<SsoConfig>): SsoConfig {
10 const now = new Date();
11 return {
12 id: "google",
13 enabled: false,
14 providerName: "Google",
15 issuer: "https://accounts.google.com",
16 authorizationEndpoint: "https://accounts.google.com/o/oauth2/v2/auth",
17 tokenEndpoint: "https://oauth2.googleapis.com/token",
18 userinfoEndpoint: "https://openidconnect.googleapis.com/v1/userinfo",
19 clientId: null,
20 clientSecret: null,
21 scopes: "openid email profile",
22 allowedEmailDomains: null,
23 autoCreateUsers: true,
24 createdAt: now,
25 updatedAt: now,
26 ...overrides,
27 } as SsoConfig;
28}
29
30const ENV_CFG = googleOauthConfigFromEnv({
31 GOOGLE_OAUTH_CLIENT_ID: "env-id.apps.googleusercontent.com",
32 GOOGLE_OAUTH_CLIENT_SECRET: "env-secret",
33});
27d5fd3Claude34
35describe("googleOauthConfigFromEnv", () => {
36 test("returns null when credentials are absent", () => {
37 expect(googleOauthConfigFromEnv({})).toBeNull();
38 expect(
39 googleOauthConfigFromEnv({ GOOGLE_OAUTH_CLIENT_ID: "id-only" })
40 ).toBeNull();
41 expect(
42 googleOauthConfigFromEnv({ GOOGLE_OAUTH_CLIENT_SECRET: "secret-only" })
43 ).toBeNull();
44 expect(
45 googleOauthConfigFromEnv({
46 GOOGLE_OAUTH_CLIENT_ID: " ",
47 GOOGLE_OAUTH_CLIENT_SECRET: "s",
48 })
49 ).toBeNull();
50 });
51
52 test("builds an enabled config from the env pair", () => {
53 const cfg = googleOauthConfigFromEnv({
54 GOOGLE_OAUTH_CLIENT_ID: "abc.apps.googleusercontent.com",
55 GOOGLE_OAUTH_CLIENT_SECRET: "shh",
56 });
57 expect(cfg).not.toBeNull();
58 expect(cfg!.enabled).toBe(true);
59 expect(cfg!.id).toBe("google");
60 expect(cfg!.clientId).toBe("abc.apps.googleusercontent.com");
61 expect(cfg!.clientSecret).toBe("shh");
62 expect(cfg!.authorizationEndpoint).toBe(
63 "https://accounts.google.com/o/oauth2/v2/auth"
64 );
65 expect(cfg!.tokenEndpoint).toBe("https://oauth2.googleapis.com/token");
66 expect(cfg!.userinfoEndpoint).toBe(
67 "https://openidconnect.googleapis.com/v1/userinfo"
68 );
69 expect(cfg!.scopes).toBe("openid email profile");
70 expect(cfg!.autoCreateUsers).toBe(true);
71 expect(cfg!.allowedEmailDomains).toBeNull();
72 });
73
74 test("honours optional knobs", () => {
75 const cfg = googleOauthConfigFromEnv({
76 GOOGLE_OAUTH_CLIENT_ID: "id",
77 GOOGLE_OAUTH_CLIENT_SECRET: "secret",
78 GOOGLE_OAUTH_AUTO_CREATE: "0",
79 GOOGLE_OAUTH_ALLOWED_DOMAINS: "example.com,corp.example.com",
80 });
81 expect(cfg!.autoCreateUsers).toBe(false);
82 expect(cfg!.allowedEmailDomains).toBe("example.com,corp.example.com");
83 });
84});
9887dd0Claude85
86describe("resolveGoogleOauthConfig — precedence", () => {
87 test("an enabled, fully-credentialed admin row wins over env", () => {
88 const dbRow = row({
89 enabled: true,
90 clientId: "db-id",
91 clientSecret: "db-secret",
92 });
93 const live = resolveGoogleOauthConfig(dbRow, ENV_CFG);
94 expect(live).toBe(dbRow);
95 expect(live!.clientId).toBe("db-id");
96 });
97
98 test("a DISABLED credentialed row does NOT shadow the env bootstrap", () => {
99 // Regression: a half-finished /admin/google-oauth save (creds entered,
100 // Enable left off) used to suppress a working GOOGLE_OAUTH_* bootstrap,
101 // leaving "Sign in with Google" dark with a misleading "not enabled".
102 const dbRow = row({
103 enabled: false,
104 clientId: "db-id",
105 clientSecret: "db-secret",
106 });
107 const live = resolveGoogleOauthConfig(dbRow, ENV_CFG);
108 expect(live).toBe(ENV_CFG);
109 expect(live!.enabled).toBe(true);
110 });
111
112 test("a credential-less row never shadows the env bootstrap", () => {
113 const live = resolveGoogleOauthConfig(row({ enabled: true }), ENV_CFG);
114 expect(live).toBe(ENV_CFG);
115 });
116
117 test("env bootstrap alone (no DB row) is live", () => {
118 expect(resolveGoogleOauthConfig(null, ENV_CFG)).toBe(ENV_CFG);
119 });
120
121 test("with no env, a disabled row is returned as-is (caller gates on it)", () => {
122 const dbRow = row({
123 enabled: false,
124 clientId: "db-id",
125 clientSecret: "db-secret",
126 });
127 expect(resolveGoogleOauthConfig(dbRow, null)).toBe(dbRow);
128 });
129
130 test("nothing configured anywhere resolves to null", () => {
131 expect(resolveGoogleOauthConfig(null, null)).toBeNull();
132 });
133});