@iqauth/sdk 2.6.4 → 2.7.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/README.md +173 -1
- package/dist/browser-session.d.mts +4 -4
- package/dist/browser-session.d.ts +4 -4
- package/dist/browser-session.js +181 -41
- package/dist/browser-session.mjs +3 -3
- package/dist/browser.d.mts +5 -5
- package/dist/browser.d.ts +5 -5
- package/dist/browser.js +271 -32
- package/dist/browser.mjs +5 -5
- package/dist/{chunk-6I6RM4MN.mjs → chunk-6PJRLRB4.mjs} +33 -3
- package/dist/{chunk-LIZYFXH7.mjs → chunk-DFWHSDYQ.mjs} +1 -1
- package/dist/chunk-GLXSIGVS.mjs +66 -0
- package/dist/{chunk-DJIBN2N7.mjs → chunk-GN37E64I.mjs} +29 -7
- package/dist/{chunk-WQWBJSSS.mjs → chunk-HVHNYPDC.mjs} +6 -6
- package/dist/{chunk-W3F4JYGP.mjs → chunk-JXQI62A7.mjs} +108 -18
- package/dist/{chunk-UNYDG2L4.mjs → chunk-NUO2I65G.mjs} +56 -23
- package/dist/chunk-PMAFENVI.mjs +229 -0
- package/dist/chunk-RR2MGPTK.mjs +2724 -0
- package/dist/{chunk-XAWYUPMO.mjs → chunk-RTJAIBXY.mjs} +220 -20
- package/dist/{chunk-6TDJJER7.mjs → chunk-RUJXRTEW.mjs} +164 -5
- package/dist/{chunk-3JULWS6F.mjs → chunk-WCELYTJ3.mjs} +3 -3
- package/dist/{chunk-MKKZULZR.mjs → chunk-WIFG74IK.mjs} +1 -1
- package/dist/{chunk-BVV54LPI.mjs → chunk-YVALAG3B.mjs} +10 -4
- package/dist/cli/index.js +2 -2
- package/dist/cli/index.mjs +2 -2
- package/dist/{client-kYlJFgPv.d.mts → client-BGFnBpfc.d.mts} +47 -4
- package/dist/{client-BNQe3AgF.d.ts → client-CDQ21LvW.d.ts} +47 -4
- package/dist/{doctor-YYNHNMLD.mjs → doctor-JAFXWU3X.mjs} +2 -2
- package/dist/errors-Jl1Jtm-6.d.mts +107 -0
- package/dist/errors-Jl1Jtm-6.d.ts +107 -0
- package/dist/{express-B6_1vBYZ.d.mts → express-CVNQEkOr.d.mts} +2 -2
- package/dist/{express-CHpfa7D_.d.ts → express-Piv2WhWM.d.ts} +2 -2
- package/dist/express.d.mts +7 -6
- package/dist/express.d.ts +7 -6
- package/dist/express.js +349 -52
- package/dist/express.mjs +39 -12
- package/dist/fastify.d.mts +2 -0
- package/dist/fastify.d.ts +2 -0
- package/dist/fastify.js +332 -52
- package/dist/fastify.mjs +23 -8
- package/dist/hono.d.mts +2 -0
- package/dist/hono.d.ts +2 -0
- package/dist/hono.js +329 -52
- package/dist/hono.mjs +20 -8
- package/dist/index-5KSZEnDe.d.ts +1626 -0
- package/dist/index-CKoZHAoc.d.mts +1626 -0
- package/dist/index.d.mts +56 -8
- package/dist/index.d.ts +56 -8
- package/dist/index.js +565 -69
- package/dist/index.mjs +29 -9
- package/dist/{keys-NLWFAOEM.mjs → keys-6Y776TG2.mjs} +2 -2
- package/dist/locales.d.mts +1 -1
- package/dist/locales.d.ts +1 -1
- package/dist/mobile.d.mts +77 -7
- package/dist/mobile.d.ts +77 -7
- package/dist/mobile.js +276 -41
- package/dist/mobile.mjs +98 -3
- package/dist/next.d.mts +2 -1
- package/dist/next.d.ts +2 -1
- package/dist/next.js +391 -201
- package/dist/next.mjs +22 -7
- package/dist/{provisioningBridge-DnTfzdZK.d.ts → provisioningBridge-CGpMRie4.d.ts} +1 -1
- package/dist/{provisioningBridge-88xjOS2n.d.mts → provisioningBridge-M5G47LWO.d.mts} +1 -1
- package/dist/{publishableKey-BaR0HoAH.d.ts → publishableKey-f2kq-rKw.d.mts} +1 -1
- package/dist/{publishableKey-BaR0HoAH.d.mts → publishableKey-f2kq-rKw.d.ts} +1 -1
- package/dist/react-permissions.d.mts +52 -0
- package/dist/react-permissions.d.ts +52 -0
- package/dist/react-permissions.js +239 -0
- package/dist/react-permissions.mjs +97 -0
- package/dist/react.d.mts +9 -1624
- package/dist/react.d.ts +9 -1624
- package/dist/react.js +313 -33
- package/dist/react.mjs +58 -2632
- package/dist/{reverify-4UEJXUS6.mjs → reverify-C64QXKJO.mjs} +2 -2
- package/dist/server/handlers.d.mts +148 -3
- package/dist/server/handlers.d.ts +148 -3
- package/dist/server/handlers.js +410 -11
- package/dist/server/handlers.mjs +12 -3
- package/dist/server.d.mts +151 -8
- package/dist/server.d.ts +151 -8
- package/dist/server.js +406 -50
- package/dist/server.mjs +93 -11
- package/dist/service.d.mts +4 -4
- package/dist/service.d.ts +4 -4
- package/dist/service.js +181 -41
- package/dist/service.mjs +3 -3
- package/dist/{signIn-OCr88Zf8.d.ts → signIn-BLFnz8SV.d.ts} +78 -3
- package/dist/{signIn-4OKLDEIH.mjs → signIn-SHBW6Z4T.mjs} +1 -1
- package/dist/{signIn-CiIBTJIh.d.mts → signIn-T-CZ6t6r.d.mts} +78 -3
- package/dist/test.mjs +3 -3
- package/dist/{tokens-DCyzzn8L.d.mts → tokens-Bqhmqq_R.d.ts} +9 -2
- package/dist/{tokens-aHiGFr_E.d.ts → tokens-CITeoG6P.d.mts} +9 -2
- package/dist/{types-6bNdxesb.d.ts → types-BdQ2lqfT.d.mts} +1 -1
- package/dist/{types-6bNdxesb.d.mts → types-BdQ2lqfT.d.ts} +1 -1
- package/dist/{types-DZAflmmq.d.mts → types-XOV9XPVi.d.mts} +99 -10
- package/dist/{types-DZAflmmq.d.ts → types-XOV9XPVi.d.ts} +99 -10
- package/dist/webhooks.d.mts +100 -17
- package/dist/webhooks.d.ts +100 -17
- package/dist/webhooks.js +164 -15
- package/dist/webhooks.mjs +7 -1
- package/dist/ws.d.mts +2 -2
- package/dist/ws.d.ts +2 -2
- package/dist/ws.js +80 -30
- package/dist/ws.mjs +4 -4
- package/docs/error-handling.md +101 -0
- package/docs/guides/effective-permissions.md +171 -0
- package/package.json +13 -3
- package/dist/chunk-UKZLOHZG.mjs +0 -83
- package/dist/errors-CDdl24MP.d.mts +0 -52
- package/dist/errors-CDdl24MP.d.ts +0 -52
package/dist/next.mjs
CHANGED
|
@@ -2,15 +2,16 @@ import {
|
|
|
2
2
|
handleCallback,
|
|
3
3
|
handleRefresh,
|
|
4
4
|
handleSignout,
|
|
5
|
+
handleUserinfo,
|
|
5
6
|
serializeCookie
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-RUJXRTEW.mjs";
|
|
7
8
|
import {
|
|
8
9
|
assertPublishableKey
|
|
9
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-HVHNYPDC.mjs";
|
|
10
11
|
import {
|
|
11
12
|
TokensModule
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-NUO2I65G.mjs";
|
|
14
|
+
import "./chunk-6PJRLRB4.mjs";
|
|
14
15
|
import "./chunk-Y6FXYEAI.mjs";
|
|
15
16
|
|
|
16
17
|
// src/next.ts
|
|
@@ -43,8 +44,19 @@ function handler(options) {
|
|
|
43
44
|
return async (req) => {
|
|
44
45
|
const url = new URL(req.url);
|
|
45
46
|
const action = url.pathname.split("/").pop();
|
|
46
|
-
const body = await req.json().catch(() => ({}));
|
|
47
47
|
const cookieHeader = req.headers.get("cookie");
|
|
48
|
+
if (action === "me" && req.method === "GET") {
|
|
49
|
+
if (!options.mountUserinfo) {
|
|
50
|
+
return new Response(JSON.stringify({ success: false, error: { code: "NOT_FOUND", message: "userinfo route not enabled" } }), {
|
|
51
|
+
status: 404,
|
|
52
|
+
headers: { "Content-Type": "application/json" }
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
const auth = req.headers.get("authorization");
|
|
56
|
+
const accessToken = auth && auth.replace(/^Bearer /i, "") || readCookieFromHeader(cookieHeader, accessCookie);
|
|
57
|
+
return toResponse(await handleUserinfo(helperConfig, { accessToken, req }));
|
|
58
|
+
}
|
|
59
|
+
const body = await req.json().catch(() => ({}));
|
|
48
60
|
if (action === "callback") {
|
|
49
61
|
return toResponse(await handleCallback(helperConfig, {
|
|
50
62
|
code: body.code,
|
|
@@ -54,12 +66,15 @@ function handler(options) {
|
|
|
54
66
|
}
|
|
55
67
|
if (action === "refresh") {
|
|
56
68
|
const refreshToken = body.refreshToken || readCookieFromHeader(cookieHeader, refreshCookie);
|
|
57
|
-
|
|
69
|
+
const idempotencyToken = req.headers.get("x-iqauth-idempotency") || body.idempotencyToken;
|
|
70
|
+
return toResponse(await handleRefresh(helperConfig, { refreshToken, idempotencyToken: idempotencyToken ?? void 0 }));
|
|
58
71
|
}
|
|
59
72
|
if (action === "signout") {
|
|
60
73
|
const auth = req.headers.get("authorization");
|
|
61
74
|
const accessToken = auth && auth.replace(/^Bearer /i, "") || readCookieFromHeader(cookieHeader, accessCookie);
|
|
62
|
-
|
|
75
|
+
const refreshToken = readCookieFromHeader(cookieHeader, refreshCookie);
|
|
76
|
+
const idempotencyToken = req.headers.get("x-iqauth-idempotency") ?? void 0;
|
|
77
|
+
return toResponse(await handleSignout(helperConfig, { accessToken, refreshToken, idempotencyToken, ssoCookieHeader: cookieHeader ?? void 0 }));
|
|
63
78
|
}
|
|
64
79
|
return new Response(JSON.stringify({ success: false, error: { code: "NOT_FOUND", message: `Unknown action: ${action}` } }), {
|
|
65
80
|
status: 404,
|
|
@@ -20,7 +20,7 @@ declare function encodePublishableKey(mode: KeyMode, payload: PublishableKeyPayl
|
|
|
20
20
|
declare function parsePublishableKey(raw: string): ParsedPublishableKey | null;
|
|
21
21
|
/**
|
|
22
22
|
* Strict counterpart to `parsePublishableKey` — throws a typed `IQAuthError`
|
|
23
|
-
* (`code: "
|
|
23
|
+
* (`code: "config_invalid"`) with an actionable message when the key is
|
|
24
24
|
* missing, malformed, or encodes a non-URL `iss`. Use this at SDK init so a
|
|
25
25
|
* bad key fails loudly at boot instead of cryptically at first verify.
|
|
26
26
|
*/
|
|
@@ -20,7 +20,7 @@ declare function encodePublishableKey(mode: KeyMode, payload: PublishableKeyPayl
|
|
|
20
20
|
declare function parsePublishableKey(raw: string): ParsedPublishableKey | null;
|
|
21
21
|
/**
|
|
22
22
|
* Strict counterpart to `parsePublishableKey` — throws a typed `IQAuthError`
|
|
23
|
-
* (`code: "
|
|
23
|
+
* (`code: "config_invalid"`) with an actionable message when the key is
|
|
24
24
|
* missing, malformed, or encodes a non-URL `iss`. Use this at SDK init so a
|
|
25
25
|
* bad key fails loudly at boot instead of cryptically at first verify.
|
|
26
26
|
*/
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { S as SessionError } from './index-CKoZHAoc.mjs';
|
|
2
|
+
import 'csstype';
|
|
3
|
+
import 'react/jsx-runtime';
|
|
4
|
+
import 'react';
|
|
5
|
+
import './signIn-T-CZ6t6r.mjs';
|
|
6
|
+
import './publishableKey-f2kq-rKw.mjs';
|
|
7
|
+
import './types-XOV9XPVi.mjs';
|
|
8
|
+
import './types-BdQ2lqfT.mjs';
|
|
9
|
+
|
|
10
|
+
interface UseEffectivePermissionsOptions {
|
|
11
|
+
/**
|
|
12
|
+
* App key (OIDC client_id / manifest key) the permissions should be
|
|
13
|
+
* resolved against. Required — permissions in IQAuth are app-scoped.
|
|
14
|
+
*/
|
|
15
|
+
appKey: string;
|
|
16
|
+
/** Disable the network fetch (claims fallback still applies). */
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
/** Stale window in ms. Default 5min. */
|
|
19
|
+
staleTime?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Override the issuer URL the hook calls. Defaults to the issuer the
|
|
22
|
+
* provider was booted with.
|
|
23
|
+
*/
|
|
24
|
+
issuer?: string;
|
|
25
|
+
}
|
|
26
|
+
interface UseEffectivePermissionsResult {
|
|
27
|
+
/** Normalized, wildcard-collapsed set of granted permission ids. */
|
|
28
|
+
permissions: string[];
|
|
29
|
+
/** Wildcard-aware membership check. Identical semantics on server. */
|
|
30
|
+
hasPermission: (id: string) => boolean;
|
|
31
|
+
/** True only while a fetch is actively in flight (and no cached data yet). */
|
|
32
|
+
isLoading: boolean;
|
|
33
|
+
/** Last fetch error, if any. Cleared on next successful refetch. */
|
|
34
|
+
error: SessionError | null;
|
|
35
|
+
/** Force a refetch, bypassing the staleTime window. */
|
|
36
|
+
refetch: () => Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Canonical hook for resolving the *full* effective permission set of the
|
|
40
|
+
* signed-in user against a single app. Use this whenever the JWT
|
|
41
|
+
* `entitlements` claim is too small (apps with hundreds of nodes can't fit
|
|
42
|
+
* them in the token).
|
|
43
|
+
*
|
|
44
|
+
* Requires a `<QueryClientProvider>` (`@tanstack/react-query`) somewhere
|
|
45
|
+
* above this hook in the tree.
|
|
46
|
+
*
|
|
47
|
+
* Returns `{ permissions, hasPermission, isLoading, error, refetch }`.
|
|
48
|
+
* `hasPermission` honours wildcard semantics (`*`, `metrics.*`).
|
|
49
|
+
*/
|
|
50
|
+
declare function useEffectivePermissions(opts: UseEffectivePermissionsOptions): UseEffectivePermissionsResult;
|
|
51
|
+
|
|
52
|
+
export { type UseEffectivePermissionsOptions, type UseEffectivePermissionsResult, useEffectivePermissions };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { S as SessionError } from './index-5KSZEnDe.js';
|
|
2
|
+
import 'csstype';
|
|
3
|
+
import 'react/jsx-runtime';
|
|
4
|
+
import 'react';
|
|
5
|
+
import './signIn-BLFnz8SV.js';
|
|
6
|
+
import './publishableKey-f2kq-rKw.js';
|
|
7
|
+
import './types-XOV9XPVi.js';
|
|
8
|
+
import './types-BdQ2lqfT.js';
|
|
9
|
+
|
|
10
|
+
interface UseEffectivePermissionsOptions {
|
|
11
|
+
/**
|
|
12
|
+
* App key (OIDC client_id / manifest key) the permissions should be
|
|
13
|
+
* resolved against. Required — permissions in IQAuth are app-scoped.
|
|
14
|
+
*/
|
|
15
|
+
appKey: string;
|
|
16
|
+
/** Disable the network fetch (claims fallback still applies). */
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
/** Stale window in ms. Default 5min. */
|
|
19
|
+
staleTime?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Override the issuer URL the hook calls. Defaults to the issuer the
|
|
22
|
+
* provider was booted with.
|
|
23
|
+
*/
|
|
24
|
+
issuer?: string;
|
|
25
|
+
}
|
|
26
|
+
interface UseEffectivePermissionsResult {
|
|
27
|
+
/** Normalized, wildcard-collapsed set of granted permission ids. */
|
|
28
|
+
permissions: string[];
|
|
29
|
+
/** Wildcard-aware membership check. Identical semantics on server. */
|
|
30
|
+
hasPermission: (id: string) => boolean;
|
|
31
|
+
/** True only while a fetch is actively in flight (and no cached data yet). */
|
|
32
|
+
isLoading: boolean;
|
|
33
|
+
/** Last fetch error, if any. Cleared on next successful refetch. */
|
|
34
|
+
error: SessionError | null;
|
|
35
|
+
/** Force a refetch, bypassing the staleTime window. */
|
|
36
|
+
refetch: () => Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Canonical hook for resolving the *full* effective permission set of the
|
|
40
|
+
* signed-in user against a single app. Use this whenever the JWT
|
|
41
|
+
* `entitlements` claim is too small (apps with hundreds of nodes can't fit
|
|
42
|
+
* them in the token).
|
|
43
|
+
*
|
|
44
|
+
* Requires a `<QueryClientProvider>` (`@tanstack/react-query`) somewhere
|
|
45
|
+
* above this hook in the tree.
|
|
46
|
+
*
|
|
47
|
+
* Returns `{ permissions, hasPermission, isLoading, error, refetch }`.
|
|
48
|
+
* `hasPermission` honours wildcard semantics (`*`, `metrics.*`).
|
|
49
|
+
*/
|
|
50
|
+
declare function useEffectivePermissions(opts: UseEffectivePermissionsOptions): UseEffectivePermissionsResult;
|
|
51
|
+
|
|
52
|
+
export { type UseEffectivePermissionsOptions, type UseEffectivePermissionsResult, useEffectivePermissions };
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __esm = (fn, res) => function __init() {
|
|
7
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
8
|
+
};
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
|
+
|
|
23
|
+
// src/errors.ts
|
|
24
|
+
var init_errors = __esm({
|
|
25
|
+
"src/errors.ts"() {
|
|
26
|
+
"use strict";
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// src/browser/storage.ts
|
|
31
|
+
var init_storage = __esm({
|
|
32
|
+
"src/browser/storage.ts"() {
|
|
33
|
+
"use strict";
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// src/browser/pkce.ts
|
|
38
|
+
var init_pkce = __esm({
|
|
39
|
+
"src/browser/pkce.ts"() {
|
|
40
|
+
"use strict";
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// src/browser/signIn.ts
|
|
45
|
+
var init_signIn = __esm({
|
|
46
|
+
"src/browser/signIn.ts"() {
|
|
47
|
+
"use strict";
|
|
48
|
+
init_pkce();
|
|
49
|
+
init_storage();
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// src/react-permissions.ts
|
|
54
|
+
var react_permissions_exports = {};
|
|
55
|
+
__export(react_permissions_exports, {
|
|
56
|
+
useEffectivePermissions: () => useEffectivePermissions
|
|
57
|
+
});
|
|
58
|
+
module.exports = __toCommonJS(react_permissions_exports);
|
|
59
|
+
|
|
60
|
+
// src/react/permissions.tsx
|
|
61
|
+
var import_react2 = require("react");
|
|
62
|
+
var import_react_query = require("@tanstack/react-query");
|
|
63
|
+
|
|
64
|
+
// src/permissions/wildcard.ts
|
|
65
|
+
var SUFFIX = ".*";
|
|
66
|
+
function wildcardPrefix(pattern) {
|
|
67
|
+
return pattern.slice(0, -SUFFIX.length);
|
|
68
|
+
}
|
|
69
|
+
function hasPermission(set, id) {
|
|
70
|
+
if (!id) return false;
|
|
71
|
+
if (!set) return false;
|
|
72
|
+
if (id === "*") {
|
|
73
|
+
for (const entry of set) if (entry === "*") return true;
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
const queryIsWildcard = id.endsWith(SUFFIX);
|
|
77
|
+
const queryPrefix = queryIsWildcard ? wildcardPrefix(id) : null;
|
|
78
|
+
for (const entry of set) {
|
|
79
|
+
if (!entry) continue;
|
|
80
|
+
if (entry === "*") return true;
|
|
81
|
+
if (entry === id) return true;
|
|
82
|
+
if (entry.endsWith(SUFFIX)) {
|
|
83
|
+
const prefix = wildcardPrefix(entry);
|
|
84
|
+
if (!queryIsWildcard) {
|
|
85
|
+
if (id === prefix) return true;
|
|
86
|
+
if (id.startsWith(prefix + ".")) return true;
|
|
87
|
+
} else {
|
|
88
|
+
if (queryPrefix === prefix) return true;
|
|
89
|
+
if (queryPrefix !== null && queryPrefix.startsWith(prefix + ".")) return true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
function expandPermissions(set) {
|
|
96
|
+
if (!set) return [];
|
|
97
|
+
const seen = /* @__PURE__ */ new Set();
|
|
98
|
+
for (const raw of set) {
|
|
99
|
+
if (typeof raw !== "string" || raw.length === 0) continue;
|
|
100
|
+
seen.add(raw);
|
|
101
|
+
}
|
|
102
|
+
if (seen.has("*")) return ["*"];
|
|
103
|
+
const wildcards = [];
|
|
104
|
+
for (const entry of seen) if (entry.endsWith(SUFFIX)) wildcards.push(entry);
|
|
105
|
+
const out = [];
|
|
106
|
+
for (const entry of seen) {
|
|
107
|
+
let covered = false;
|
|
108
|
+
for (const w of wildcards) {
|
|
109
|
+
if (w === entry) continue;
|
|
110
|
+
const prefix = wildcardPrefix(w);
|
|
111
|
+
if (entry === prefix) {
|
|
112
|
+
covered = true;
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
if (entry.startsWith(prefix + ".")) {
|
|
116
|
+
covered = true;
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (!covered) out.push(entry);
|
|
121
|
+
}
|
|
122
|
+
out.sort();
|
|
123
|
+
return out;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/react/index.tsx
|
|
127
|
+
var import_react = require("react");
|
|
128
|
+
|
|
129
|
+
// src/browser/sessionManager.ts
|
|
130
|
+
init_errors();
|
|
131
|
+
|
|
132
|
+
// src/publishableKey.ts
|
|
133
|
+
init_errors();
|
|
134
|
+
|
|
135
|
+
// src/browser/sessionManager.ts
|
|
136
|
+
init_storage();
|
|
137
|
+
|
|
138
|
+
// src/react/index.tsx
|
|
139
|
+
init_signIn();
|
|
140
|
+
|
|
141
|
+
// src/browser/accountRegistry.ts
|
|
142
|
+
init_storage();
|
|
143
|
+
var COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
|
|
144
|
+
|
|
145
|
+
// src/react/index.tsx
|
|
146
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
147
|
+
var IQAuthContext = (0, import_react.createContext)(null);
|
|
148
|
+
function __useIQAuthInternal() {
|
|
149
|
+
return useCtx();
|
|
150
|
+
}
|
|
151
|
+
function useCtx() {
|
|
152
|
+
const ctx = (0, import_react.useContext)(IQAuthContext);
|
|
153
|
+
if (!ctx) throw new Error("IQAuth hooks must be used inside <IQAuthProvider>");
|
|
154
|
+
return ctx;
|
|
155
|
+
}
|
|
156
|
+
var MultisessionContext = (0, import_react.createContext)(null);
|
|
157
|
+
var SDK_CSS_MAX_LEN = 50 * 1024;
|
|
158
|
+
|
|
159
|
+
// src/react/permissions.tsx
|
|
160
|
+
var DEFAULT_PERMS_STALE_MS = 5 * 60 * 1e3;
|
|
161
|
+
function projectAllowedScopes(rows) {
|
|
162
|
+
if (!Array.isArray(rows)) return [];
|
|
163
|
+
const allowed = [];
|
|
164
|
+
const denied = /* @__PURE__ */ new Set();
|
|
165
|
+
for (const r of rows) {
|
|
166
|
+
if (!r || typeof r.scope !== "string" || !r.scope) continue;
|
|
167
|
+
if (r.effect === "deny") denied.add(r.scope);
|
|
168
|
+
else allowed.push(r.scope);
|
|
169
|
+
}
|
|
170
|
+
return expandPermissions(allowed.filter((s) => !denied.has(s)));
|
|
171
|
+
}
|
|
172
|
+
function useEffectivePermissions(opts) {
|
|
173
|
+
const { manager, snapshot } = __useIQAuthInternal();
|
|
174
|
+
const { appKey, enabled = true, staleTime = DEFAULT_PERMS_STALE_MS, issuer } = opts;
|
|
175
|
+
const claims = snapshot.claims;
|
|
176
|
+
const isPlatformAdmin = Array.isArray(claims?.roles) && claims.roles.includes("platform_admin");
|
|
177
|
+
const userId = snapshot.user?.sub ?? null;
|
|
178
|
+
const tenantId = snapshot.tenantId ?? claims?.tenantId ?? null;
|
|
179
|
+
const issuerUrl = (issuer ?? manager.issuerUrl).replace(/\/$/, "");
|
|
180
|
+
const queryEnabled = enabled && !!userId && !!tenantId && !!appKey && !isPlatformAdmin;
|
|
181
|
+
const query = (0, import_react_query.useQuery)({
|
|
182
|
+
queryKey: ["iqauth", "effective-permissions", issuerUrl, tenantId, userId, appKey],
|
|
183
|
+
queryFn: async () => {
|
|
184
|
+
const url = `${issuerUrl}/api/v1/tenants/${encodeURIComponent(tenantId)}/users/${encodeURIComponent(userId)}/permissions/effective?appKey=${encodeURIComponent(appKey)}`;
|
|
185
|
+
const res = await manager.fetch(url);
|
|
186
|
+
const json = await res.json().catch(() => ({}));
|
|
187
|
+
if (!res.ok) {
|
|
188
|
+
const code = json?.error?.code || `HTTP_${res.status}`;
|
|
189
|
+
const message = json?.error?.message || `HTTP ${res.status}`;
|
|
190
|
+
const e = { code, message };
|
|
191
|
+
throw e;
|
|
192
|
+
}
|
|
193
|
+
const rows = Array.isArray(json) ? json : json?.data ?? [];
|
|
194
|
+
return projectAllowedScopes(rows);
|
|
195
|
+
},
|
|
196
|
+
enabled: queryEnabled,
|
|
197
|
+
staleTime,
|
|
198
|
+
refetchOnWindowFocus: false,
|
|
199
|
+
retry: false
|
|
200
|
+
});
|
|
201
|
+
const refetch = (0, import_react2.useCallback)(async () => {
|
|
202
|
+
if (!queryEnabled) return;
|
|
203
|
+
await query.refetch();
|
|
204
|
+
}, [query, queryEnabled]);
|
|
205
|
+
return (0, import_react2.useMemo)(() => {
|
|
206
|
+
if (isPlatformAdmin) {
|
|
207
|
+
return {
|
|
208
|
+
permissions: ["*"],
|
|
209
|
+
hasPermission: () => true,
|
|
210
|
+
isLoading: false,
|
|
211
|
+
error: null,
|
|
212
|
+
refetch
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
const fetched = query.data;
|
|
216
|
+
const perms = fetched ?? expandPermissions(claims?.entitlements ?? []);
|
|
217
|
+
const isLoading = queryEnabled && query.isLoading;
|
|
218
|
+
const error = query.error ? "code" in query.error && typeof query.error.code === "string" ? query.error : { code: "PERMISSIONS_FETCH_FAILED", message: query.error.message || "Failed to fetch permissions" } : null;
|
|
219
|
+
return {
|
|
220
|
+
permissions: perms,
|
|
221
|
+
hasPermission: (id) => hasPermission(perms, id),
|
|
222
|
+
isLoading,
|
|
223
|
+
error,
|
|
224
|
+
refetch
|
|
225
|
+
};
|
|
226
|
+
}, [
|
|
227
|
+
isPlatformAdmin,
|
|
228
|
+
queryEnabled,
|
|
229
|
+
query.data,
|
|
230
|
+
query.isLoading,
|
|
231
|
+
query.error,
|
|
232
|
+
claims?.entitlements,
|
|
233
|
+
refetch
|
|
234
|
+
]);
|
|
235
|
+
}
|
|
236
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
237
|
+
0 && (module.exports = {
|
|
238
|
+
useEffectivePermissions
|
|
239
|
+
});
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__useIQAuthInternal
|
|
3
|
+
} from "./chunk-RR2MGPTK.mjs";
|
|
4
|
+
import "./chunk-RTJAIBXY.mjs";
|
|
5
|
+
import "./chunk-GN37E64I.mjs";
|
|
6
|
+
import "./chunk-C2ZTBOAC.mjs";
|
|
7
|
+
import {
|
|
8
|
+
expandPermissions,
|
|
9
|
+
hasPermission
|
|
10
|
+
} from "./chunk-GLXSIGVS.mjs";
|
|
11
|
+
import "./chunk-HVHNYPDC.mjs";
|
|
12
|
+
import "./chunk-5T7GHBX6.mjs";
|
|
13
|
+
import "./chunk-6PJRLRB4.mjs";
|
|
14
|
+
import "./chunk-Y6FXYEAI.mjs";
|
|
15
|
+
|
|
16
|
+
// src/react/permissions.tsx
|
|
17
|
+
import { useCallback, useMemo } from "react";
|
|
18
|
+
import { useQuery } from "@tanstack/react-query";
|
|
19
|
+
var DEFAULT_PERMS_STALE_MS = 5 * 60 * 1e3;
|
|
20
|
+
function projectAllowedScopes(rows) {
|
|
21
|
+
if (!Array.isArray(rows)) return [];
|
|
22
|
+
const allowed = [];
|
|
23
|
+
const denied = /* @__PURE__ */ new Set();
|
|
24
|
+
for (const r of rows) {
|
|
25
|
+
if (!r || typeof r.scope !== "string" || !r.scope) continue;
|
|
26
|
+
if (r.effect === "deny") denied.add(r.scope);
|
|
27
|
+
else allowed.push(r.scope);
|
|
28
|
+
}
|
|
29
|
+
return expandPermissions(allowed.filter((s) => !denied.has(s)));
|
|
30
|
+
}
|
|
31
|
+
function useEffectivePermissions(opts) {
|
|
32
|
+
const { manager, snapshot } = __useIQAuthInternal();
|
|
33
|
+
const { appKey, enabled = true, staleTime = DEFAULT_PERMS_STALE_MS, issuer } = opts;
|
|
34
|
+
const claims = snapshot.claims;
|
|
35
|
+
const isPlatformAdmin = Array.isArray(claims?.roles) && claims.roles.includes("platform_admin");
|
|
36
|
+
const userId = snapshot.user?.sub ?? null;
|
|
37
|
+
const tenantId = snapshot.tenantId ?? claims?.tenantId ?? null;
|
|
38
|
+
const issuerUrl = (issuer ?? manager.issuerUrl).replace(/\/$/, "");
|
|
39
|
+
const queryEnabled = enabled && !!userId && !!tenantId && !!appKey && !isPlatformAdmin;
|
|
40
|
+
const query = useQuery({
|
|
41
|
+
queryKey: ["iqauth", "effective-permissions", issuerUrl, tenantId, userId, appKey],
|
|
42
|
+
queryFn: async () => {
|
|
43
|
+
const url = `${issuerUrl}/api/v1/tenants/${encodeURIComponent(tenantId)}/users/${encodeURIComponent(userId)}/permissions/effective?appKey=${encodeURIComponent(appKey)}`;
|
|
44
|
+
const res = await manager.fetch(url);
|
|
45
|
+
const json = await res.json().catch(() => ({}));
|
|
46
|
+
if (!res.ok) {
|
|
47
|
+
const code = json?.error?.code || `HTTP_${res.status}`;
|
|
48
|
+
const message = json?.error?.message || `HTTP ${res.status}`;
|
|
49
|
+
const e = { code, message };
|
|
50
|
+
throw e;
|
|
51
|
+
}
|
|
52
|
+
const rows = Array.isArray(json) ? json : json?.data ?? [];
|
|
53
|
+
return projectAllowedScopes(rows);
|
|
54
|
+
},
|
|
55
|
+
enabled: queryEnabled,
|
|
56
|
+
staleTime,
|
|
57
|
+
refetchOnWindowFocus: false,
|
|
58
|
+
retry: false
|
|
59
|
+
});
|
|
60
|
+
const refetch = useCallback(async () => {
|
|
61
|
+
if (!queryEnabled) return;
|
|
62
|
+
await query.refetch();
|
|
63
|
+
}, [query, queryEnabled]);
|
|
64
|
+
return useMemo(() => {
|
|
65
|
+
if (isPlatformAdmin) {
|
|
66
|
+
return {
|
|
67
|
+
permissions: ["*"],
|
|
68
|
+
hasPermission: () => true,
|
|
69
|
+
isLoading: false,
|
|
70
|
+
error: null,
|
|
71
|
+
refetch
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
const fetched = query.data;
|
|
75
|
+
const perms = fetched ?? expandPermissions(claims?.entitlements ?? []);
|
|
76
|
+
const isLoading = queryEnabled && query.isLoading;
|
|
77
|
+
const error = query.error ? "code" in query.error && typeof query.error.code === "string" ? query.error : { code: "PERMISSIONS_FETCH_FAILED", message: query.error.message || "Failed to fetch permissions" } : null;
|
|
78
|
+
return {
|
|
79
|
+
permissions: perms,
|
|
80
|
+
hasPermission: (id) => hasPermission(perms, id),
|
|
81
|
+
isLoading,
|
|
82
|
+
error,
|
|
83
|
+
refetch
|
|
84
|
+
};
|
|
85
|
+
}, [
|
|
86
|
+
isPlatformAdmin,
|
|
87
|
+
queryEnabled,
|
|
88
|
+
query.data,
|
|
89
|
+
query.isLoading,
|
|
90
|
+
query.error,
|
|
91
|
+
claims?.entitlements,
|
|
92
|
+
refetch
|
|
93
|
+
]);
|
|
94
|
+
}
|
|
95
|
+
export {
|
|
96
|
+
useEffectivePermissions
|
|
97
|
+
};
|