@edcalderon/auth 1.3.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edcalderon/auth",
3
- "version": "1.3.0",
3
+ "version": "1.4.1",
4
4
  "description": "A universal, provider-agnostic authentication package (Web + Next.js + Expo/React Native)",
5
5
  "exports": {
6
6
  ".": {
@@ -9,6 +9,11 @@
9
9
  "require": "./dist/index.js",
10
10
  "react-native": "./dist/index.js"
11
11
  },
12
+ "./authentik": {
13
+ "types": "./dist/authentik/index.d.ts",
14
+ "import": "./dist/authentik/index.js",
15
+ "require": "./dist/authentik/index.js"
16
+ },
12
17
  "./supabase": {
13
18
  "types": "./dist/providers/SupabaseClient.d.ts",
14
19
  "import": "./dist/providers/SupabaseClient.js",
@@ -42,6 +47,9 @@
42
47
  "scripts": {
43
48
  "build": "tsc",
44
49
  "dev": "tsc --watch",
50
+ "test": "jest",
51
+ "test:watch": "jest --watch",
52
+ "test:coverage": "jest --coverage",
45
53
  "prepublishOnly": "npm run build",
46
54
  "update-readme": "versioning update-readme"
47
55
  },
@@ -90,10 +98,20 @@
90
98
  }
91
99
  },
92
100
  "devDependencies": {
101
+ "@types/jest": "^29.5.12",
93
102
  "@types/react": "^19.2.7",
103
+ "jest": "^29.7.0",
104
+ "ts-jest": "^29.1.2",
94
105
  "typescript": "^5.9.3"
95
106
  },
96
107
  "engines": {
97
108
  "node": ">=18.0.0"
109
+ },
110
+ "jest": {
111
+ "testEnvironment": "node",
112
+ "testMatch": ["**/__tests__/**/*.test.ts"],
113
+ "transform": {
114
+ "^.+\\.ts$": "ts-jest"
115
+ }
98
116
  }
99
117
  }
@@ -0,0 +1,81 @@
1
+ -- ============================================================================
2
+ -- 003_authentik_shadow_auth_users.sql
3
+ -- Optional migration for projects using the Authentik ↔ Supabase integrated
4
+ -- sync mode in @edcalderon/auth.
5
+ --
6
+ -- This migration adds app_metadata columns and an index to support the
7
+ -- shadow auth.users pattern where Authentik-authenticated users are mirrored
8
+ -- into Supabase auth.users with identity-first matching.
9
+ --
10
+ -- The public.users table is already created by 001_create_app_users.sql.
11
+ -- This migration adds columns to support the shadow-user linkage and
12
+ -- rollback-safe provisioning.
13
+ --
14
+ -- Reference: CIG apps/dashboard/lib/authSync.ts
15
+ -- ============================================================================
16
+
17
+ -- Add optional column to track the linked Supabase auth.users shadow ID
18
+ alter table public.users
19
+ add column if not exists shadow_auth_user_id uuid;
20
+
21
+ -- Add optional column to record when the shadow link was established
22
+ alter table public.users
23
+ add column if not exists shadow_linked_at timestamptz;
24
+
25
+ -- Index for quick lookup by shadow auth user ID
26
+ create index if not exists users_shadow_auth_user_id_idx
27
+ on public.users (shadow_auth_user_id)
28
+ where shadow_auth_user_id is not null;
29
+
30
+ -- ============================================================================
31
+ -- Helper RPC: link a public.users row to a Supabase auth.users shadow record.
32
+ -- Called by the SupabaseSyncAdapter after creating/finding the shadow user.
33
+ --
34
+ -- This is an additive helper — the core upsert_oidc_user RPC from migration
35
+ -- 001 continues to work unchanged. The raw_claims payload can optionally
36
+ -- carry shadow_supabase_auth_user_id to record the linkage.
37
+ -- ============================================================================
38
+
39
+ create or replace function public.link_shadow_auth_user(
40
+ p_sub text,
41
+ p_iss text,
42
+ p_shadow_auth_user_id uuid
43
+ )
44
+ returns public.users
45
+ language plpgsql
46
+ security definer
47
+ set search_path = public
48
+ as $$
49
+ declare
50
+ v_claims jsonb := coalesce(
51
+ nullif(current_setting('request.jwt.claims', true), ''),
52
+ '{}'
53
+ )::jsonb;
54
+ v_role text := coalesce(nullif(v_claims ->> 'role', ''), 'unknown');
55
+ v_user public.users;
56
+ begin
57
+ if v_role <> 'service_role' then
58
+ raise exception 'link_shadow_auth_user() requires a trusted server-side caller';
59
+ end if;
60
+
61
+ update public.users
62
+ set shadow_auth_user_id = p_shadow_auth_user_id,
63
+ shadow_linked_at = timezone('utc', now()),
64
+ updated_at = timezone('utc', now())
65
+ where sub = p_sub
66
+ and iss = p_iss
67
+ returning * into v_user;
68
+
69
+ if not found then
70
+ raise exception 'No public.users row found for sub=% iss=%', p_sub, p_iss;
71
+ end if;
72
+
73
+ return v_user;
74
+ end;
75
+ $$;
76
+
77
+ revoke all on function public.link_shadow_auth_user(text, text, uuid)
78
+ from public, anon, authenticated;
79
+
80
+ grant execute on function public.link_shadow_auth_user(text, text, uuid)
81
+ to service_role;