snipe-auth-rbac 0.3.1 → 0.4.0
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/dist/admin/index.cjs +201 -11
- package/dist/admin/index.cjs.map +1 -1
- package/dist/admin/index.d.cts +112 -3
- package/dist/admin/index.d.ts +112 -3
- package/dist/admin/index.js +200 -12
- package/dist/admin/index.js.map +1 -1
- package/dist/{chunk-NRDW233A.js → chunk-5UAIIOKT.js} +65 -1
- package/dist/chunk-5UAIIOKT.js.map +1 -0
- package/dist/{chunk-C76JHCKM.js → chunk-XHPBUCFN.js} +33 -1
- package/dist/chunk-XHPBUCFN.js.map +1 -0
- package/dist/index-CJqb5nY5.d.cts +191 -0
- package/dist/index-nfrns9Ye.d.ts +191 -0
- package/dist/index.cjs +42 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -118
- package/dist/index.d.ts +3 -118
- package/dist/index.js +4 -2
- package/dist/react/index.cjs +106 -11
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +34 -59
- package/dist/react/index.d.ts +34 -59
- package/dist/react/index.js +14 -13
- package/dist/react/index.js.map +1 -1
- package/dist/types-Oj9yfWvz.d.cts +132 -0
- package/dist/types-Oj9yfWvz.d.ts +132 -0
- package/package.json +1 -1
- package/sql/0001_initial.sql +137 -2
- package/dist/chunk-C76JHCKM.js.map +0 -1
- package/dist/chunk-NRDW233A.js.map +0 -1
- package/dist/types-DxvFudPF.d.cts +0 -69
- package/dist/types-DxvFudPF.d.ts +0 -69
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/fetchers.ts"],"sourcesContent":["/**\n * Built-in fetchers — adopters can use these or pass their own\n * implementation of `AuthRbacFetcher`.\n */\n\nimport type { AuthRbacFetcher, UserProfile } from \"./types.js\";\n\n/**\n * Calls the package's SQL function `rbac.user_profile(uuid)` via\n * a Supabase JS client. Easiest path when the host project already\n * uses Supabase.\n *\n * The function lives in the dedicated `rbac` Postgres schema, so the\n * adopter must add `rbac` to their PostgREST exposed-schemas list\n * (Supabase Studio → Settings → API → Exposed schemas) for the\n * `.schema('rbac')` call below to reach it.\n *\n * @example\n * createSupabaseFetcher({ supabase, userId: session.user.id })\n */\nexport function createSupabaseFetcher(opts: {\n supabase: {\n schema: (name: string) => {\n rpc: (\n fn: string,\n args: Record<string, unknown>,\n ) => Promise<{ data: unknown; error: { message: string } | null }>;\n };\n };\n userId: string;\n}): AuthRbacFetcher {\n return {\n async fetchProfile(): Promise<UserProfile> {\n const { data, error } = await opts.supabase.schema(\"rbac\").rpc(\n \"user_profile\",\n { p_user_id: opts.userId },\n );\n if (error) {\n throw new Error(\n `auth-rbac: failed to load user profile via Supabase RPC: ${error.message}`,\n );\n }\n return normalizeProfile(data);\n },\n };\n}\n\n/**\n * Cheap probe — returns true if the package's `rbac` schema looks\n * reachable. Useful at app start to fail loudly if the migration\n * hasn't been applied OR if `rbac` isn't in the project's PostgREST\n * exposed-schemas list.\n *\n * @example\n * if (!(await detectRbacSchema(supabase))) {\n * console.error(\"rbac schema not reachable — apply 0001_initial.sql\");\n * }\n */\nexport async function detectRbacSchema(supabase: {\n schema: (name: string) => {\n rpc: (\n fn: string,\n args: Record<string, unknown>,\n ) => Promise<{ data: unknown; error: { message: string } | null }>;\n };\n}): Promise<boolean> {\n try {\n const { error } = await supabase.schema(\"rbac\").rpc(\"user_can\", {\n p_user_id: \"00000000-0000-0000-0000-000000000000\",\n p_resource: \"__rbac_self_check__\",\n p_action: \"read\",\n p_company_id: null,\n });\n return error === null;\n } catch {\n return false;\n }\n}\n\n/**\n * Calls a regular HTTP endpoint that returns a `UserProfile` JSON\n * payload. Use this when the host project has its own backend that\n * wraps the package's Python helpers (or any equivalent).\n *\n * @example\n * createHttpFetcher({ url: \"/api/users/me/profile\" })\n */\nexport function createHttpFetcher(opts: {\n url: string;\n /** Forwarded as-is to `fetch`. Use this to attach auth headers. */\n init?: RequestInit;\n /** Override the global `fetch` if you're in a non-browser env. */\n fetch?: typeof fetch;\n}): AuthRbacFetcher {\n const fetchImpl = opts.fetch ?? globalThis.fetch;\n return {\n async fetchProfile(): Promise<UserProfile> {\n const res = await fetchImpl(opts.url, opts.init);\n if (!res.ok) {\n throw new Error(\n `auth-rbac: profile endpoint ${opts.url} returned ${res.status}`,\n );\n }\n const json = (await res.json()) as unknown;\n return normalizeProfile(json);\n },\n };\n}\n\n/**\n * Defensive normalisation: the Supabase RPC returns whatever the SQL\n * function emitted. We coerce missing fields into the empty defaults\n * so consumers can iterate without null checks. Throws if the shape\n * is unrecognisable.\n */\nfunction normalizeProfile(raw: unknown): UserProfile {\n if (!raw || typeof raw !== \"object\") {\n throw new Error(\"auth-rbac: profile payload is not an object\");\n }\n const p = raw as Partial<UserProfile> & Record<string, unknown>;\n if (typeof p.user_id !== \"string\") {\n throw new Error(\"auth-rbac: profile payload missing user_id\");\n }\n return {\n user_id: p.user_id,\n is_super_admin: !!p.is_super_admin,\n system_roles: Array.isArray(p.system_roles) ? p.system_roles : [],\n system_permissions:\n p.system_permissions && typeof p.system_permissions === \"object\"\n ? (p.system_permissions as UserProfile[\"system_permissions\"])\n : {},\n system_frontend_config:\n p.system_frontend_config && typeof p.system_frontend_config === \"object\"\n ? (p.system_frontend_config as UserProfile[\"system_frontend_config\"])\n : {},\n memberships: Array.isArray(p.memberships)\n ? (p.memberships as UserProfile[\"memberships\"])\n : [],\n };\n}\n"],"mappings":";AAoBO,SAAS,sBAAsB,MAUlB;AAClB,SAAO;AAAA,IACL,MAAM,eAAqC;AACzC,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,KAAK,SAAS,OAAO,MAAM,EAAE;AAAA,QACzD;AAAA,QACA,EAAE,WAAW,KAAK,OAAO;AAAA,MAC3B;AACA,UAAI,OAAO;AACT,cAAM,IAAI;AAAA,UACR,4DAA4D,MAAM,OAAO;AAAA,QAC3E;AAAA,MACF;AACA,aAAO,iBAAiB,IAAI;AAAA,IAC9B;AAAA,EACF;AACF;AAaA,eAAsB,iBAAiB,UAOlB;AACnB,MAAI;AACF,UAAM,EAAE,MAAM,IAAI,MAAM,SAAS,OAAO,MAAM,EAAE,IAAI,YAAY;AAAA,MAC9D,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,cAAc;AAAA,IAChB,CAAC;AACD,WAAO,UAAU;AAAA,EACnB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAUO,SAAS,kBAAkB,MAMd;AAClB,QAAM,YAAY,KAAK,SAAS,WAAW;AAC3C,SAAO;AAAA,IACL,MAAM,eAAqC;AACzC,YAAM,MAAM,MAAM,UAAU,KAAK,KAAK,KAAK,IAAI;AAC/C,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI;AAAA,UACR,+BAA+B,KAAK,GAAG,aAAa,IAAI,MAAM;AAAA,QAChE;AAAA,MACF;AACA,YAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,aAAO,iBAAiB,IAAI;AAAA,IAC9B;AAAA,EACF;AACF;AAQA,SAAS,iBAAiB,KAA2B;AACnD,MAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACnC,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AACA,QAAM,IAAI;AACV,MAAI,OAAO,EAAE,YAAY,UAAU;AACjC,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AACA,SAAO;AAAA,IACL,SAAS,EAAE;AAAA,IACX,gBAAgB,CAAC,CAAC,EAAE;AAAA,IACpB,cAAc,MAAM,QAAQ,EAAE,YAAY,IAAI,EAAE,eAAe,CAAC;AAAA,IAChE,oBACE,EAAE,sBAAsB,OAAO,EAAE,uBAAuB,WACnD,EAAE,qBACH,CAAC;AAAA,IACP,wBACE,EAAE,0BAA0B,OAAO,EAAE,2BAA2B,WAC3D,EAAE,yBACH,CAAC;AAAA,IACP,aAAa,MAAM,QAAQ,EAAE,WAAW,IACnC,EAAE,cACH,CAAC;AAAA,EACP;AACF;","names":[]}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Core types — used by both the transport-agnostic client and the
|
|
3
|
-
* React layer. Adopters that don't use React only need to depend on
|
|
4
|
-
* the `index` entry; the `react` entry's types extend these.
|
|
5
|
-
*/
|
|
6
|
-
type Action = "read" | "write" | "update" | "delete";
|
|
7
|
-
type ResourceScope = "system" | "company";
|
|
8
|
-
interface ResourceDescriptor {
|
|
9
|
-
resource: string;
|
|
10
|
-
scope: ResourceScope;
|
|
11
|
-
label: string;
|
|
12
|
-
description?: string;
|
|
13
|
-
group?: string;
|
|
14
|
-
}
|
|
15
|
-
interface RoleSummary {
|
|
16
|
-
id: string;
|
|
17
|
-
name: string;
|
|
18
|
-
is_system?: boolean;
|
|
19
|
-
is_super?: boolean;
|
|
20
|
-
frontend_config?: FrontendConfig;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Free-form per-role config that the host project can interpret as
|
|
24
|
-
* it sees fit. A typical shape includes `sidebar` (list of section
|
|
25
|
-
* keys), `default_dashboard` (string), `home_route` (string).
|
|
26
|
-
*/
|
|
27
|
-
type FrontendConfig = Record<string, unknown>;
|
|
28
|
-
interface PermissionGrid {
|
|
29
|
-
read: boolean;
|
|
30
|
-
write: boolean;
|
|
31
|
-
update: boolean;
|
|
32
|
-
delete: boolean;
|
|
33
|
-
}
|
|
34
|
-
type PermissionMap = Record<string, PermissionGrid>;
|
|
35
|
-
interface CompanyMembership {
|
|
36
|
-
company_id: string;
|
|
37
|
-
company_name: string;
|
|
38
|
-
company_slug?: string | null;
|
|
39
|
-
roles: RoleSummary[];
|
|
40
|
-
permissions: PermissionMap;
|
|
41
|
-
/** Merged frontend_config across all roles the user holds in this company. */
|
|
42
|
-
frontend_config: FrontendConfig;
|
|
43
|
-
}
|
|
44
|
-
interface UserProfile {
|
|
45
|
-
user_id: string;
|
|
46
|
-
is_super_admin: boolean;
|
|
47
|
-
system_roles: RoleSummary[];
|
|
48
|
-
system_permissions: PermissionMap;
|
|
49
|
-
/** Merged frontend_config across all of the user's system roles. */
|
|
50
|
-
system_frontend_config: FrontendConfig;
|
|
51
|
-
memberships: CompanyMembership[];
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Adopter-supplied transport. Two flavours are supported out of the
|
|
55
|
-
* box:
|
|
56
|
-
*
|
|
57
|
-
* 1. Pass a Supabase client + a JWT-derived `user_id` and the
|
|
58
|
-
* library calls the package's SQL RPC `rbac.user_profile`.
|
|
59
|
-
* 2. Pass a plain `fetcher` (anything that resolves a `UserProfile`)
|
|
60
|
-
* and the library calls that. Use this when your backend serves
|
|
61
|
-
* a custom `/api/users/me/profile` endpoint or when you don't
|
|
62
|
-
* run Supabase at all.
|
|
63
|
-
*/
|
|
64
|
-
interface AuthRbacFetcher {
|
|
65
|
-
fetchProfile(): Promise<UserProfile>;
|
|
66
|
-
}
|
|
67
|
-
type ResourceRegistry = ReadonlyArray<ResourceDescriptor>;
|
|
68
|
-
|
|
69
|
-
export type { Action as A, CompanyMembership as C, FrontendConfig as F, PermissionGrid as P, ResourceScope as R, UserProfile as U, ResourceDescriptor as a, AuthRbacFetcher as b, ResourceRegistry as c, PermissionMap as d, RoleSummary as e };
|
package/dist/types-DxvFudPF.d.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Core types — used by both the transport-agnostic client and the
|
|
3
|
-
* React layer. Adopters that don't use React only need to depend on
|
|
4
|
-
* the `index` entry; the `react` entry's types extend these.
|
|
5
|
-
*/
|
|
6
|
-
type Action = "read" | "write" | "update" | "delete";
|
|
7
|
-
type ResourceScope = "system" | "company";
|
|
8
|
-
interface ResourceDescriptor {
|
|
9
|
-
resource: string;
|
|
10
|
-
scope: ResourceScope;
|
|
11
|
-
label: string;
|
|
12
|
-
description?: string;
|
|
13
|
-
group?: string;
|
|
14
|
-
}
|
|
15
|
-
interface RoleSummary {
|
|
16
|
-
id: string;
|
|
17
|
-
name: string;
|
|
18
|
-
is_system?: boolean;
|
|
19
|
-
is_super?: boolean;
|
|
20
|
-
frontend_config?: FrontendConfig;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Free-form per-role config that the host project can interpret as
|
|
24
|
-
* it sees fit. A typical shape includes `sidebar` (list of section
|
|
25
|
-
* keys), `default_dashboard` (string), `home_route` (string).
|
|
26
|
-
*/
|
|
27
|
-
type FrontendConfig = Record<string, unknown>;
|
|
28
|
-
interface PermissionGrid {
|
|
29
|
-
read: boolean;
|
|
30
|
-
write: boolean;
|
|
31
|
-
update: boolean;
|
|
32
|
-
delete: boolean;
|
|
33
|
-
}
|
|
34
|
-
type PermissionMap = Record<string, PermissionGrid>;
|
|
35
|
-
interface CompanyMembership {
|
|
36
|
-
company_id: string;
|
|
37
|
-
company_name: string;
|
|
38
|
-
company_slug?: string | null;
|
|
39
|
-
roles: RoleSummary[];
|
|
40
|
-
permissions: PermissionMap;
|
|
41
|
-
/** Merged frontend_config across all roles the user holds in this company. */
|
|
42
|
-
frontend_config: FrontendConfig;
|
|
43
|
-
}
|
|
44
|
-
interface UserProfile {
|
|
45
|
-
user_id: string;
|
|
46
|
-
is_super_admin: boolean;
|
|
47
|
-
system_roles: RoleSummary[];
|
|
48
|
-
system_permissions: PermissionMap;
|
|
49
|
-
/** Merged frontend_config across all of the user's system roles. */
|
|
50
|
-
system_frontend_config: FrontendConfig;
|
|
51
|
-
memberships: CompanyMembership[];
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Adopter-supplied transport. Two flavours are supported out of the
|
|
55
|
-
* box:
|
|
56
|
-
*
|
|
57
|
-
* 1. Pass a Supabase client + a JWT-derived `user_id` and the
|
|
58
|
-
* library calls the package's SQL RPC `rbac.user_profile`.
|
|
59
|
-
* 2. Pass a plain `fetcher` (anything that resolves a `UserProfile`)
|
|
60
|
-
* and the library calls that. Use this when your backend serves
|
|
61
|
-
* a custom `/api/users/me/profile` endpoint or when you don't
|
|
62
|
-
* run Supabase at all.
|
|
63
|
-
*/
|
|
64
|
-
interface AuthRbacFetcher {
|
|
65
|
-
fetchProfile(): Promise<UserProfile>;
|
|
66
|
-
}
|
|
67
|
-
type ResourceRegistry = ReadonlyArray<ResourceDescriptor>;
|
|
68
|
-
|
|
69
|
-
export type { Action as A, CompanyMembership as C, FrontendConfig as F, PermissionGrid as P, ResourceScope as R, UserProfile as U, ResourceDescriptor as a, AuthRbacFetcher as b, ResourceRegistry as c, PermissionMap as d, RoleSummary as e };
|