UNPKG

@frank-auth/react

Version:

Flexible and customizable React UI components for Frank Authentication

313 lines (312 loc) 9.17 kB
'use client'; import { jsx as x, Fragment as C } from "react/jsx-runtime"; import { useState as S, useCallback as o, useEffect as L, useMemo as Q } from "react"; import { useAuth as ee } from "./use-auth.js"; const te = { // Generic CRUD actions CREATE: "create", READ: "read", UPDATE: "update", DELETE: "delete", // User management actions INVITE: "invite", REMOVE: "remove", SUSPEND: "suspend", ACTIVATE: "activate", // Admin actions MANAGE: "manage", CONFIGURE: "configure", AUDIT: "audit", // Special actions TRANSFER: "transfer", EXPORT: "export", IMPORT: "import" }, oe = { // User resources USER: "user", USER_PROFILE: "user:profile", USER_SESSION: "user:session", USER_MFA: "user:mfa", // Organization resources ORGANIZATION: "organization", ORGANIZATION_SETTINGS: "organization:settings", ORGANIZATION_MEMBERS: "organization:members", ORGANIZATION_INVITATIONS: "organization:invitations", ORGANIZATION_BILLING: "organization:billing", ORGANIZATION_AUDIT: "organization:audit", // Application resources APPLICATION: "application", APPLICATION_SETTINGS: "application:settings", APPLICATION_USERS: "application:users", APPLICATION_SESSIONS: "application:sessions", // System resources SYSTEM: "system", SYSTEM_USERS: "system:users", SYSTEM_ORGANIZATIONS: "system:organizations", SYSTEM_SETTINGS: "system:settings", SYSTEM_BILLING: "system:billing", SYSTEM_AUDIT: "system:audit" }, N = { SUPER_ADMIN: "system:super_admin", ADMIN: "system:admin", SUPPORT: "system:support" }, v = { OWNER: "organization:owner", ADMIN: "organization:admin", MEMBER: "organization:member", BILLING: "organization:billing", SUPPORT: "organization:support" }; function w() { const { user: a, activeOrganization: s, sdk: m } = ee(), [d, u] = S([]), [p, z] = S([]), [t, A] = S([]), [y, T] = S([]), [E, f] = S(!1), [h, g] = S(null), [R, b] = S({ type: "system", organizationId: s?.id }), G = o((e) => { const n = { code: e.code || "UNKNOWN_ERROR", message: e.message || "An unknown error occurred", details: e.details, field: e.field }; g(n); }, []), P = o(async () => { if (!(!m.auth || !a)) try { f(!0), g(null); const [e, n] = await Promise.all([ m.auth.getUserRoles(a.id), m.auth.getUserPermissions(a.id) ]); A(e), T(n); const i = e.map((r) => r.role.name), l = n.map((r) => r.permission.name), D = e.flatMap( (r) => r.role.permissions?.map((O) => O.name) || [] ); z(i), u([.../* @__PURE__ */ new Set([...l, ...D])]); } catch (e) { G(e); } finally { f(!1); } }, [m.auth, a, G]); L(() => { P(); }, [P]), L(() => { s && b((e) => ({ ...e, organizationId: s.id })); }, [s]); const c = o((e, n) => { const i = n || R; return y.some((r) => { if (r.permission.name !== e) return !1; switch (i.type) { case "system": return r.contextType === "system"; case "organization": return r.contextType === "organization" && r.resourceId === i.organizationId; case "application": return r.contextType === "application" && r.resourceId === i.applicationId; default: return !1; } }) ? !0 : t.some((r) => { let O = !1; switch (i.type) { case "system": O = r.contextType === "system"; break; case "organization": O = r.contextType === "organization" && r.resourceId === i.organizationId; break; case "application": O = r.contextType === "application" && r.resourceId === i.applicationId; break; } return O && r.role.permissions?.some((J) => J.name === e) || !1; }); }, [y, t, R]), I = o((e, n) => { const i = n || R; return t.some((l) => { if (l.role.name !== e) return !1; switch (i.type) { case "system": return l.contextType === "system"; case "organization": return l.contextType === "organization" && l.resourceId === i.organizationId; case "application": return l.contextType === "application" && l.resourceId === i.applicationId; default: return !1; } }); }, [t, R]), M = o((e, n) => e.some((i) => c(i, n)), [c]), _ = o((e, n) => e.every((i) => c(i, n)), [c]), q = o((e, n, i) => { const l = `${n}:${e}`; return c(l, i); }, [c]), k = o((e, n) => { const i = n || s?.id; return i ? c(e, { type: "organization", organizationId: i }) : !1; }, [c, s]), Z = o((e, n) => c(e, { type: "application", applicationId: n }), [c]), B = o((e) => c(e, { type: "system" }), [c]), Y = Q(() => I(N.SUPER_ADMIN) || I(N.ADMIN), [I]), U = o((e) => { const n = e || s?.id; return n ? I(v.OWNER, { type: "organization", organizationId: n }) : !1; }, [I, s]), V = o((e) => { const n = e || s?.id; return n ? I(v.ADMIN, { type: "organization", organizationId: n }) || U(n) : !1; }, [I, U, s]), $ = o((e) => { const n = e || s?.id; return n ? t.some( (i) => i.contextType === "organization" && i.resourceId === n ) : !1; }, [t, s]), F = o((e, n) => { if (!c(e, n)) throw new Error(`Permission required: ${e}`); }, [c]), j = o((e, n) => { if (!I(e, n)) throw new Error(`Role required: ${e}`); }, [I]), W = o((e, n) => { if (!M(e, n)) throw new Error(`One of these permissions required: ${e.join(", ")}`); }, [M]), K = o((e, n) => { if (!_(e, n)) throw new Error(`All of these permissions required: ${e.join(", ")}`); }, [_]), X = o(async () => { await P(); }, [P]), H = o((e) => { b(e); }, []); return { // Permission state permissions: d, roles: p, roleAssignments: t, permissionAssignments: y, isLoaded: !!a, isLoading: E, error: h, // Permission checking hasPermission: c, hasRole: I, hasAnyPermission: M, hasAllPermissions: _, can: q, // Context-aware checking canInOrganization: k, canInApplication: Z, hasSystemPermission: B, // Role checking isSystemAdmin: Y, isOrganizationOwner: U, isOrganizationAdmin: V, isOrganizationMember: $, // Permission management refreshPermissions: X, // Convenience methods requirePermission: F, requireRole: j, requireAnyPermission: W, requireAllPermissions: K, // Current context currentContext: R, setContext: H }; } function re(a) { const { canInOrganization: s, isOrganizationOwner: m, isOrganizationAdmin: d, isOrganizationMember: u, hasRole: p, activeOrganization: z } = w(), t = a || z?.id; return { organizationId: t, isOwner: m(t), isAdmin: d(t), isMember: u(t), // Common organization permissions canManageMembers: s("organization:members:manage", t), canInviteMembers: s("organization:members:invite", t), canRemoveMembers: s("organization:members:remove", t), canManageSettings: s("organization:settings:manage", t), canManageBilling: s("organization:billing:manage", t), canViewAudit: s("organization:audit:read", t), canDeleteOrganization: s("organization:delete", t), // Role checking for organization hasOrganizationRole: (A) => p(A, { type: "organization", organizationId: t }) }; } function ae() { const { hasSystemPermission: a, isSystemAdmin: s, hasRole: m, userType: d } = w(), u = d === "internal"; return { canAccessSystem: u, isSystemAdmin: s, // Common system permissions canManageUsers: u && a("system:users:manage"), canManageOrganizations: u && a("system:organizations:manage"), canManageSystem: u && a("system:manage"), canViewSystemAudit: u && a("system:audit:read"), canManageBilling: u && a("system:billing:manage"), // Role checking for system hasSystemRole: (p) => m(p, { type: "system" }), isSuperAdmin: m(N.SUPER_ADMIN, { type: "system" }), isSupport: m(N.SUPPORT, { type: "system" }) }; } function ce() { const { hasPermission: a, hasRole: s, hasAnyPermission: m, hasAllPermissions: d, requirePermission: u, requireRole: p } = w(); return { PermissionGuard: o(({ permission: t, role: A, anyPermissions: y, allPermissions: T, context: E, fallback: f = null, children: h }) => { let g = !0; return t && (g = g && a(t, E)), A && (g = g && s(A, E)), y && (g = g && m(y, E)), T && (g = g && d(T, E)), g ? /* @__PURE__ */ x(C, { children: h }) : /* @__PURE__ */ x(C, { children: f }); }, [a, s, m, d]), requirePermission: u, requireRole: p }; } export { v as ORGANIZATION_ROLES, te as PERMISSION_ACTIONS, oe as PERMISSION_RESOURCES, N as SYSTEM_ROLES, re as useOrganizationPermissions, ce as usePermissionGuard, w as usePermissions, ae as useSystemPermissions }; //# sourceMappingURL=use-permissions.js.map