@frank-auth/react
Version:
Flexible and customizable React UI components for Frank Authentication
313 lines (312 loc) • 9.17 kB
JavaScript
'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