com-angel-authorization 1.0.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/LICENSE +21 -0
- package/README.md +276 -0
- package/dist/index.cjs +110 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +55 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +107 -0
- package/dist/index.js.map +1 -0
- package/dist/react/index.cjs +156 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +119 -0
- package/dist/react/index.d.ts +119 -0
- package/dist/react/index.js +134 -0
- package/dist/react/index.js.map +1 -0
- package/dist/vue/index.cjs +241 -0
- package/dist/vue/index.cjs.map +1 -0
- package/dist/vue/index.d.cts +173 -0
- package/dist/vue/index.d.ts +173 -0
- package/dist/vue/index.js +213 -0
- package/dist/vue/index.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/react/index.ts
|
|
22
|
+
var react_exports = {};
|
|
23
|
+
__export(react_exports, {
|
|
24
|
+
Can: () => Can,
|
|
25
|
+
PermissionProvider: () => PermissionProvider,
|
|
26
|
+
PermissionStore: () => import_core2.PermissionStore,
|
|
27
|
+
createPermissionStore: () => import_core2.createPermissionStore,
|
|
28
|
+
useHasPermission: () => useHasPermission,
|
|
29
|
+
useHasRole: () => useHasRole,
|
|
30
|
+
usePermission: () => usePermission
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(react_exports);
|
|
33
|
+
|
|
34
|
+
// src/react/context.tsx
|
|
35
|
+
var import_react = require("react");
|
|
36
|
+
var import_core = require("../core");
|
|
37
|
+
var PermissionContext = (0, import_react.createContext)(null);
|
|
38
|
+
function PermissionProvider({
|
|
39
|
+
children,
|
|
40
|
+
store: externalStore,
|
|
41
|
+
initialState
|
|
42
|
+
}) {
|
|
43
|
+
const store = (0, import_react.useMemo)(
|
|
44
|
+
() => externalStore ?? (0, import_core.createPermissionStore)(initialState),
|
|
45
|
+
// store identity is intentional; initialState only applies on first create
|
|
46
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
47
|
+
[externalStore]
|
|
48
|
+
);
|
|
49
|
+
return (0, import_react.createElement)(PermissionContext.Provider, { value: store }, children);
|
|
50
|
+
}
|
|
51
|
+
function useStore() {
|
|
52
|
+
const store = (0, import_react.useContext)(PermissionContext);
|
|
53
|
+
if (!store) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
"[com-angel-authorization/react] usePermission* hooks must be used within <PermissionProvider>."
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
return store;
|
|
59
|
+
}
|
|
60
|
+
function usePermissionSnapshot(store) {
|
|
61
|
+
const [state, setState] = (0, import_react.useState)(() => store.getState());
|
|
62
|
+
(0, import_react.useEffect)(() => {
|
|
63
|
+
setState(store.getState());
|
|
64
|
+
return store.subscribe(setState);
|
|
65
|
+
}, [store]);
|
|
66
|
+
return state;
|
|
67
|
+
}
|
|
68
|
+
function usePermission() {
|
|
69
|
+
const store = useStore();
|
|
70
|
+
const state = usePermissionSnapshot(store);
|
|
71
|
+
const hasPermission = (0, import_react.useCallback)(
|
|
72
|
+
(codes, options) => store.hasPermission(codes, options),
|
|
73
|
+
[store]
|
|
74
|
+
);
|
|
75
|
+
const hasRole = (0, import_react.useCallback)(
|
|
76
|
+
(codes, options) => store.hasRole(codes, options),
|
|
77
|
+
[store]
|
|
78
|
+
);
|
|
79
|
+
const can = (0, import_react.useCallback)(
|
|
80
|
+
(codes, options) => store.can(codes, options),
|
|
81
|
+
[store]
|
|
82
|
+
);
|
|
83
|
+
return {
|
|
84
|
+
permissions: state.permissions,
|
|
85
|
+
roles: state.roles,
|
|
86
|
+
isSuperAdmin: Boolean(state.isSuperAdmin),
|
|
87
|
+
hasPermission,
|
|
88
|
+
hasRole,
|
|
89
|
+
can,
|
|
90
|
+
setPermissions: store.setPermissions.bind(store),
|
|
91
|
+
setRoles: store.setRoles.bind(store),
|
|
92
|
+
setSuperAdmin: store.setSuperAdmin.bind(store),
|
|
93
|
+
hydrate: store.hydrate.bind(store),
|
|
94
|
+
clear: store.clear.bind(store),
|
|
95
|
+
store
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function useHasPermission(codes, options) {
|
|
99
|
+
const { hasPermission, permissions, isSuperAdmin } = usePermission();
|
|
100
|
+
void permissions;
|
|
101
|
+
void isSuperAdmin;
|
|
102
|
+
return hasPermission(codes, options);
|
|
103
|
+
}
|
|
104
|
+
function useHasRole(codes, options) {
|
|
105
|
+
const { hasRole, roles, isSuperAdmin } = usePermission();
|
|
106
|
+
void roles;
|
|
107
|
+
void isSuperAdmin;
|
|
108
|
+
return hasRole(codes, options);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/react/Can.tsx
|
|
112
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
113
|
+
function evaluateAccess(hasPermission, hasRole, props) {
|
|
114
|
+
const { permission, role, mode, combine = "and" } = props;
|
|
115
|
+
const options = { mode };
|
|
116
|
+
const hasPermCheck = permission !== void 0;
|
|
117
|
+
const hasRoleCheck = role !== void 0;
|
|
118
|
+
if (!hasPermCheck && !hasRoleCheck) return true;
|
|
119
|
+
const permOk = hasPermCheck ? hasPermission(permission, options) : true;
|
|
120
|
+
const roleOk = hasRoleCheck ? hasRole(role, options) : true;
|
|
121
|
+
if (hasPermCheck && hasRoleCheck) {
|
|
122
|
+
return combine === "or" ? permOk || roleOk : permOk && roleOk;
|
|
123
|
+
}
|
|
124
|
+
return hasPermCheck ? permOk : roleOk;
|
|
125
|
+
}
|
|
126
|
+
function Can({
|
|
127
|
+
permission,
|
|
128
|
+
role,
|
|
129
|
+
mode,
|
|
130
|
+
combine,
|
|
131
|
+
children,
|
|
132
|
+
fallback = null
|
|
133
|
+
}) {
|
|
134
|
+
const { hasPermission, hasRole } = usePermission();
|
|
135
|
+
const allowed = evaluateAccess(hasPermission, hasRole, {
|
|
136
|
+
permission,
|
|
137
|
+
role,
|
|
138
|
+
mode,
|
|
139
|
+
combine
|
|
140
|
+
});
|
|
141
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: allowed ? children : fallback });
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// src/react/index.ts
|
|
145
|
+
var import_core2 = require("../core");
|
|
146
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
147
|
+
0 && (module.exports = {
|
|
148
|
+
Can,
|
|
149
|
+
PermissionProvider,
|
|
150
|
+
PermissionStore,
|
|
151
|
+
createPermissionStore,
|
|
152
|
+
useHasPermission,
|
|
153
|
+
useHasRole,
|
|
154
|
+
usePermission
|
|
155
|
+
});
|
|
156
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/react/index.ts","../../src/react/context.tsx","../../src/react/Can.tsx"],"sourcesContent":["export { PermissionProvider, usePermission, useHasPermission, useHasRole } from './context';\nexport type { PermissionProviderProps, UsePermissionResult } from './context';\n\nexport { Can } from './Can';\nexport type { CanProps } from './Can';\n\nexport type {\n CheckOptions,\n MatchMode,\n PermissionChecker,\n PermissionCode,\n PermissionListener,\n PermissionState,\n RoleCode,\n} from '../core';\n\nexport { PermissionStore, createPermissionStore } from '../core';\n","import {\n createContext,\n createElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\nimport {\n createPermissionStore,\n type CheckOptions,\n type PermissionCode,\n type PermissionState,\n type PermissionStore,\n type RoleCode,\n} from '../core';\n\nconst PermissionContext = createContext<PermissionStore | null>(null);\n\nexport interface PermissionProviderProps {\n children: ReactNode;\n /** Pass an existing store to share across trees, or omit to create one. */\n store?: PermissionStore;\n /** Initial state when the provider creates its own store. */\n initialState?: Partial<PermissionState>;\n}\n\nexport function PermissionProvider({\n children,\n store: externalStore,\n initialState,\n}: PermissionProviderProps) {\n const store = useMemo(\n () => externalStore ?? createPermissionStore(initialState),\n // store identity is intentional; initialState only applies on first create\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [externalStore],\n );\n\n return createElement(PermissionContext.Provider, { value: store }, children);\n}\n\nfunction useStore(): PermissionStore {\n const store = useContext(PermissionContext);\n if (!store) {\n throw new Error(\n '[com-angel-authorization/react] usePermission* hooks must be used within <PermissionProvider>.',\n );\n }\n return store;\n}\n\nfunction usePermissionSnapshot(store: PermissionStore): PermissionState {\n const [state, setState] = useState(() => store.getState());\n\n useEffect(() => {\n setState(store.getState());\n return store.subscribe(setState);\n }, [store]);\n\n return state;\n}\n\nexport interface UsePermissionResult {\n permissions: PermissionCode[];\n roles: RoleCode[];\n isSuperAdmin: boolean;\n hasPermission: (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => boolean;\n hasRole: (codes: RoleCode | RoleCode[], options?: CheckOptions) => boolean;\n can: (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => boolean;\n setPermissions: (permissions: PermissionCode[]) => void;\n setRoles: (roles: RoleCode[]) => void;\n setSuperAdmin: (isSuperAdmin: boolean) => void;\n hydrate: (payload: Partial<PermissionState>) => void;\n clear: () => void;\n store: PermissionStore;\n}\n\nexport function usePermission(): UsePermissionResult {\n const store = useStore();\n const state = usePermissionSnapshot(store);\n\n const hasPermission = useCallback(\n (codes: PermissionCode | PermissionCode[], options?: CheckOptions) =>\n store.hasPermission(codes, options),\n [store],\n );\n\n const hasRole = useCallback(\n (codes: RoleCode | RoleCode[], options?: CheckOptions) => store.hasRole(codes, options),\n [store],\n );\n\n const can = useCallback(\n (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => store.can(codes, options),\n [store],\n );\n\n return {\n permissions: state.permissions,\n roles: state.roles,\n isSuperAdmin: Boolean(state.isSuperAdmin),\n hasPermission,\n hasRole,\n can,\n setPermissions: store.setPermissions.bind(store),\n setRoles: store.setRoles.bind(store),\n setSuperAdmin: store.setSuperAdmin.bind(store),\n hydrate: store.hydrate.bind(store),\n clear: store.clear.bind(store),\n store,\n };\n}\n\n/** Returns whether the current user has the given permission(s). */\nexport function useHasPermission(\n codes: PermissionCode | PermissionCode[],\n options?: CheckOptions,\n): boolean {\n const { hasPermission, permissions, isSuperAdmin } = usePermission();\n // re-compute when permission list / super-admin changes\n void permissions;\n void isSuperAdmin;\n return hasPermission(codes, options);\n}\n\n/** Returns whether the current user has the given role(s). */\nexport function useHasRole(\n codes: RoleCode | RoleCode[],\n options?: CheckOptions,\n): boolean {\n const { hasRole, roles, isSuperAdmin } = usePermission();\n void roles;\n void isSuperAdmin;\n return hasRole(codes, options);\n}\n","import type { ReactNode } from 'react';\nimport type { CheckOptions, PermissionCode, RoleCode } from '../core';\nimport { usePermission } from './context';\n\nexport interface CanProps {\n /** Permission codes to check. */\n permission?: PermissionCode | PermissionCode[];\n /** Role codes to check. */\n role?: RoleCode | RoleCode[];\n /**\n * `any` — pass when at least one code matches (default)\n * `all` — pass only when every code matches\n */\n mode?: CheckOptions['mode'];\n /**\n * How permission and role conditions combine when both are provided.\n * Default: `and` (must satisfy both).\n */\n combine?: 'and' | 'or';\n children: ReactNode;\n /** Fallback when access is denied. */\n fallback?: ReactNode;\n}\n\nfunction evaluateAccess(\n hasPermission: (c: PermissionCode | PermissionCode[], o?: CheckOptions) => boolean,\n hasRole: (c: RoleCode | RoleCode[], o?: CheckOptions) => boolean,\n props: Pick<CanProps, 'permission' | 'role' | 'mode' | 'combine'>,\n): boolean {\n const { permission, role, mode, combine = 'and' } = props;\n const options: CheckOptions = { mode };\n\n const hasPermCheck = permission !== undefined;\n const hasRoleCheck = role !== undefined;\n\n if (!hasPermCheck && !hasRoleCheck) return true;\n\n const permOk = hasPermCheck ? hasPermission(permission!, options) : true;\n const roleOk = hasRoleCheck ? hasRole(role!, options) : true;\n\n if (hasPermCheck && hasRoleCheck) {\n return combine === 'or' ? permOk || roleOk : permOk && roleOk;\n }\n\n return hasPermCheck ? permOk : roleOk;\n}\n\n/**\n * Conditionally render children based on permission / role.\n *\n * @example\n * <Can permission=\"user:edit\">\n * <button>Edit</button>\n * </Can>\n *\n * <Can permission={['user:edit', 'user:delete']} mode=\"all\" fallback={null}>\n * <AdminPanel />\n * </Can>\n */\nexport function Can({\n permission,\n role,\n mode,\n combine,\n children,\n fallback = null,\n}: CanProps) {\n const { hasPermission, hasRole } = usePermission();\n const allowed = evaluateAccess(hasPermission, hasRole, {\n permission,\n role,\n mode,\n combine,\n });\n\n return <>{allowed ? children : fallback}</>;\n}\n"],"mappings":"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","names":["import_core"]}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
type PermissionCode = string;
|
|
5
|
+
type RoleCode = string;
|
|
6
|
+
interface PermissionState {
|
|
7
|
+
/** Permission codes owned by the current user */
|
|
8
|
+
permissions: PermissionCode[];
|
|
9
|
+
/** Roles owned by the current user */
|
|
10
|
+
roles: RoleCode[];
|
|
11
|
+
/** Super admin bypasses all checks when true */
|
|
12
|
+
isSuperAdmin?: boolean;
|
|
13
|
+
}
|
|
14
|
+
type MatchMode = 'all' | 'any';
|
|
15
|
+
interface CheckOptions {
|
|
16
|
+
/**
|
|
17
|
+
* `any` — pass when at least one code matches (default)
|
|
18
|
+
* `all` — pass only when every code matches
|
|
19
|
+
*/
|
|
20
|
+
mode?: MatchMode;
|
|
21
|
+
}
|
|
22
|
+
type PermissionListener = (state: PermissionState) => void;
|
|
23
|
+
interface PermissionChecker {
|
|
24
|
+
hasPermission(codes: PermissionCode | PermissionCode[], options?: CheckOptions): boolean;
|
|
25
|
+
hasRole(codes: RoleCode | RoleCode[], options?: CheckOptions): boolean;
|
|
26
|
+
can(codes: PermissionCode | PermissionCode[], options?: CheckOptions): boolean;
|
|
27
|
+
getState(): PermissionState;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Mutable permission store shared by React / Vue adapters.
|
|
32
|
+
* Framework-agnostic — safe to use in Node, browser, or any UI lib.
|
|
33
|
+
*/
|
|
34
|
+
declare class PermissionStore implements PermissionChecker {
|
|
35
|
+
private state;
|
|
36
|
+
private permissionSet;
|
|
37
|
+
private roleSet;
|
|
38
|
+
private listeners;
|
|
39
|
+
constructor(initial?: Partial<PermissionState>);
|
|
40
|
+
getState(): PermissionState;
|
|
41
|
+
setState(next: Partial<PermissionState>): void;
|
|
42
|
+
setPermissions(permissions: PermissionCode[]): void;
|
|
43
|
+
setRoles(roles: RoleCode[]): void;
|
|
44
|
+
setSuperAdmin(isSuperAdmin: boolean): void;
|
|
45
|
+
/** Replace permissions, roles and super-admin flag in one shot (typical after login). */
|
|
46
|
+
hydrate(payload: Partial<PermissionState>): void;
|
|
47
|
+
/** Clear all authz data (typical after logout). */
|
|
48
|
+
clear(): void;
|
|
49
|
+
hasPermission(codes: PermissionCode | PermissionCode[], options?: CheckOptions): boolean;
|
|
50
|
+
hasRole(codes: RoleCode | RoleCode[], options?: CheckOptions): boolean;
|
|
51
|
+
/** Alias of `hasPermission` for template-friendly APIs. */
|
|
52
|
+
can(codes: PermissionCode | PermissionCode[], options?: CheckOptions): boolean;
|
|
53
|
+
subscribe(listener: PermissionListener): () => void;
|
|
54
|
+
private emit;
|
|
55
|
+
}
|
|
56
|
+
declare function createPermissionStore(initial?: Partial<PermissionState>): PermissionStore;
|
|
57
|
+
|
|
58
|
+
interface PermissionProviderProps {
|
|
59
|
+
children: ReactNode;
|
|
60
|
+
/** Pass an existing store to share across trees, or omit to create one. */
|
|
61
|
+
store?: PermissionStore;
|
|
62
|
+
/** Initial state when the provider creates its own store. */
|
|
63
|
+
initialState?: Partial<PermissionState>;
|
|
64
|
+
}
|
|
65
|
+
declare function PermissionProvider({ children, store: externalStore, initialState, }: PermissionProviderProps): react.FunctionComponentElement<react.ProviderProps<PermissionStore | null>>;
|
|
66
|
+
interface UsePermissionResult {
|
|
67
|
+
permissions: PermissionCode[];
|
|
68
|
+
roles: RoleCode[];
|
|
69
|
+
isSuperAdmin: boolean;
|
|
70
|
+
hasPermission: (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => boolean;
|
|
71
|
+
hasRole: (codes: RoleCode | RoleCode[], options?: CheckOptions) => boolean;
|
|
72
|
+
can: (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => boolean;
|
|
73
|
+
setPermissions: (permissions: PermissionCode[]) => void;
|
|
74
|
+
setRoles: (roles: RoleCode[]) => void;
|
|
75
|
+
setSuperAdmin: (isSuperAdmin: boolean) => void;
|
|
76
|
+
hydrate: (payload: Partial<PermissionState>) => void;
|
|
77
|
+
clear: () => void;
|
|
78
|
+
store: PermissionStore;
|
|
79
|
+
}
|
|
80
|
+
declare function usePermission(): UsePermissionResult;
|
|
81
|
+
/** Returns whether the current user has the given permission(s). */
|
|
82
|
+
declare function useHasPermission(codes: PermissionCode | PermissionCode[], options?: CheckOptions): boolean;
|
|
83
|
+
/** Returns whether the current user has the given role(s). */
|
|
84
|
+
declare function useHasRole(codes: RoleCode | RoleCode[], options?: CheckOptions): boolean;
|
|
85
|
+
|
|
86
|
+
interface CanProps {
|
|
87
|
+
/** Permission codes to check. */
|
|
88
|
+
permission?: PermissionCode | PermissionCode[];
|
|
89
|
+
/** Role codes to check. */
|
|
90
|
+
role?: RoleCode | RoleCode[];
|
|
91
|
+
/**
|
|
92
|
+
* `any` — pass when at least one code matches (default)
|
|
93
|
+
* `all` — pass only when every code matches
|
|
94
|
+
*/
|
|
95
|
+
mode?: CheckOptions['mode'];
|
|
96
|
+
/**
|
|
97
|
+
* How permission and role conditions combine when both are provided.
|
|
98
|
+
* Default: `and` (must satisfy both).
|
|
99
|
+
*/
|
|
100
|
+
combine?: 'and' | 'or';
|
|
101
|
+
children: ReactNode;
|
|
102
|
+
/** Fallback when access is denied. */
|
|
103
|
+
fallback?: ReactNode;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Conditionally render children based on permission / role.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* <Can permission="user:edit">
|
|
110
|
+
* <button>Edit</button>
|
|
111
|
+
* </Can>
|
|
112
|
+
*
|
|
113
|
+
* <Can permission={['user:edit', 'user:delete']} mode="all" fallback={null}>
|
|
114
|
+
* <AdminPanel />
|
|
115
|
+
* </Can>
|
|
116
|
+
*/
|
|
117
|
+
declare function Can({ permission, role, mode, combine, children, fallback, }: CanProps): react.JSX.Element;
|
|
118
|
+
|
|
119
|
+
export { Can, type CanProps, type CheckOptions, type MatchMode, type PermissionChecker, type PermissionCode, type PermissionListener, PermissionProvider, type PermissionProviderProps, type PermissionState, PermissionStore, type RoleCode, type UsePermissionResult, createPermissionStore, useHasPermission, useHasRole, usePermission };
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
type PermissionCode = string;
|
|
5
|
+
type RoleCode = string;
|
|
6
|
+
interface PermissionState {
|
|
7
|
+
/** Permission codes owned by the current user */
|
|
8
|
+
permissions: PermissionCode[];
|
|
9
|
+
/** Roles owned by the current user */
|
|
10
|
+
roles: RoleCode[];
|
|
11
|
+
/** Super admin bypasses all checks when true */
|
|
12
|
+
isSuperAdmin?: boolean;
|
|
13
|
+
}
|
|
14
|
+
type MatchMode = 'all' | 'any';
|
|
15
|
+
interface CheckOptions {
|
|
16
|
+
/**
|
|
17
|
+
* `any` — pass when at least one code matches (default)
|
|
18
|
+
* `all` — pass only when every code matches
|
|
19
|
+
*/
|
|
20
|
+
mode?: MatchMode;
|
|
21
|
+
}
|
|
22
|
+
type PermissionListener = (state: PermissionState) => void;
|
|
23
|
+
interface PermissionChecker {
|
|
24
|
+
hasPermission(codes: PermissionCode | PermissionCode[], options?: CheckOptions): boolean;
|
|
25
|
+
hasRole(codes: RoleCode | RoleCode[], options?: CheckOptions): boolean;
|
|
26
|
+
can(codes: PermissionCode | PermissionCode[], options?: CheckOptions): boolean;
|
|
27
|
+
getState(): PermissionState;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Mutable permission store shared by React / Vue adapters.
|
|
32
|
+
* Framework-agnostic — safe to use in Node, browser, or any UI lib.
|
|
33
|
+
*/
|
|
34
|
+
declare class PermissionStore implements PermissionChecker {
|
|
35
|
+
private state;
|
|
36
|
+
private permissionSet;
|
|
37
|
+
private roleSet;
|
|
38
|
+
private listeners;
|
|
39
|
+
constructor(initial?: Partial<PermissionState>);
|
|
40
|
+
getState(): PermissionState;
|
|
41
|
+
setState(next: Partial<PermissionState>): void;
|
|
42
|
+
setPermissions(permissions: PermissionCode[]): void;
|
|
43
|
+
setRoles(roles: RoleCode[]): void;
|
|
44
|
+
setSuperAdmin(isSuperAdmin: boolean): void;
|
|
45
|
+
/** Replace permissions, roles and super-admin flag in one shot (typical after login). */
|
|
46
|
+
hydrate(payload: Partial<PermissionState>): void;
|
|
47
|
+
/** Clear all authz data (typical after logout). */
|
|
48
|
+
clear(): void;
|
|
49
|
+
hasPermission(codes: PermissionCode | PermissionCode[], options?: CheckOptions): boolean;
|
|
50
|
+
hasRole(codes: RoleCode | RoleCode[], options?: CheckOptions): boolean;
|
|
51
|
+
/** Alias of `hasPermission` for template-friendly APIs. */
|
|
52
|
+
can(codes: PermissionCode | PermissionCode[], options?: CheckOptions): boolean;
|
|
53
|
+
subscribe(listener: PermissionListener): () => void;
|
|
54
|
+
private emit;
|
|
55
|
+
}
|
|
56
|
+
declare function createPermissionStore(initial?: Partial<PermissionState>): PermissionStore;
|
|
57
|
+
|
|
58
|
+
interface PermissionProviderProps {
|
|
59
|
+
children: ReactNode;
|
|
60
|
+
/** Pass an existing store to share across trees, or omit to create one. */
|
|
61
|
+
store?: PermissionStore;
|
|
62
|
+
/** Initial state when the provider creates its own store. */
|
|
63
|
+
initialState?: Partial<PermissionState>;
|
|
64
|
+
}
|
|
65
|
+
declare function PermissionProvider({ children, store: externalStore, initialState, }: PermissionProviderProps): react.FunctionComponentElement<react.ProviderProps<PermissionStore | null>>;
|
|
66
|
+
interface UsePermissionResult {
|
|
67
|
+
permissions: PermissionCode[];
|
|
68
|
+
roles: RoleCode[];
|
|
69
|
+
isSuperAdmin: boolean;
|
|
70
|
+
hasPermission: (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => boolean;
|
|
71
|
+
hasRole: (codes: RoleCode | RoleCode[], options?: CheckOptions) => boolean;
|
|
72
|
+
can: (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => boolean;
|
|
73
|
+
setPermissions: (permissions: PermissionCode[]) => void;
|
|
74
|
+
setRoles: (roles: RoleCode[]) => void;
|
|
75
|
+
setSuperAdmin: (isSuperAdmin: boolean) => void;
|
|
76
|
+
hydrate: (payload: Partial<PermissionState>) => void;
|
|
77
|
+
clear: () => void;
|
|
78
|
+
store: PermissionStore;
|
|
79
|
+
}
|
|
80
|
+
declare function usePermission(): UsePermissionResult;
|
|
81
|
+
/** Returns whether the current user has the given permission(s). */
|
|
82
|
+
declare function useHasPermission(codes: PermissionCode | PermissionCode[], options?: CheckOptions): boolean;
|
|
83
|
+
/** Returns whether the current user has the given role(s). */
|
|
84
|
+
declare function useHasRole(codes: RoleCode | RoleCode[], options?: CheckOptions): boolean;
|
|
85
|
+
|
|
86
|
+
interface CanProps {
|
|
87
|
+
/** Permission codes to check. */
|
|
88
|
+
permission?: PermissionCode | PermissionCode[];
|
|
89
|
+
/** Role codes to check. */
|
|
90
|
+
role?: RoleCode | RoleCode[];
|
|
91
|
+
/**
|
|
92
|
+
* `any` — pass when at least one code matches (default)
|
|
93
|
+
* `all` — pass only when every code matches
|
|
94
|
+
*/
|
|
95
|
+
mode?: CheckOptions['mode'];
|
|
96
|
+
/**
|
|
97
|
+
* How permission and role conditions combine when both are provided.
|
|
98
|
+
* Default: `and` (must satisfy both).
|
|
99
|
+
*/
|
|
100
|
+
combine?: 'and' | 'or';
|
|
101
|
+
children: ReactNode;
|
|
102
|
+
/** Fallback when access is denied. */
|
|
103
|
+
fallback?: ReactNode;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Conditionally render children based on permission / role.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* <Can permission="user:edit">
|
|
110
|
+
* <button>Edit</button>
|
|
111
|
+
* </Can>
|
|
112
|
+
*
|
|
113
|
+
* <Can permission={['user:edit', 'user:delete']} mode="all" fallback={null}>
|
|
114
|
+
* <AdminPanel />
|
|
115
|
+
* </Can>
|
|
116
|
+
*/
|
|
117
|
+
declare function Can({ permission, role, mode, combine, children, fallback, }: CanProps): react.JSX.Element;
|
|
118
|
+
|
|
119
|
+
export { Can, type CanProps, type CheckOptions, type MatchMode, type PermissionChecker, type PermissionCode, type PermissionListener, PermissionProvider, type PermissionProviderProps, type PermissionState, PermissionStore, type RoleCode, type UsePermissionResult, createPermissionStore, useHasPermission, useHasRole, usePermission };
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/react/context.tsx
|
|
4
|
+
import {
|
|
5
|
+
createContext,
|
|
6
|
+
createElement,
|
|
7
|
+
useCallback,
|
|
8
|
+
useContext,
|
|
9
|
+
useEffect,
|
|
10
|
+
useMemo,
|
|
11
|
+
useState
|
|
12
|
+
} from "react";
|
|
13
|
+
import {
|
|
14
|
+
createPermissionStore
|
|
15
|
+
} from "../core";
|
|
16
|
+
var PermissionContext = createContext(null);
|
|
17
|
+
function PermissionProvider({
|
|
18
|
+
children,
|
|
19
|
+
store: externalStore,
|
|
20
|
+
initialState
|
|
21
|
+
}) {
|
|
22
|
+
const store = useMemo(
|
|
23
|
+
() => externalStore ?? createPermissionStore(initialState),
|
|
24
|
+
// store identity is intentional; initialState only applies on first create
|
|
25
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
26
|
+
[externalStore]
|
|
27
|
+
);
|
|
28
|
+
return createElement(PermissionContext.Provider, { value: store }, children);
|
|
29
|
+
}
|
|
30
|
+
function useStore() {
|
|
31
|
+
const store = useContext(PermissionContext);
|
|
32
|
+
if (!store) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
"[com-angel-authorization/react] usePermission* hooks must be used within <PermissionProvider>."
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
return store;
|
|
38
|
+
}
|
|
39
|
+
function usePermissionSnapshot(store) {
|
|
40
|
+
const [state, setState] = useState(() => store.getState());
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
setState(store.getState());
|
|
43
|
+
return store.subscribe(setState);
|
|
44
|
+
}, [store]);
|
|
45
|
+
return state;
|
|
46
|
+
}
|
|
47
|
+
function usePermission() {
|
|
48
|
+
const store = useStore();
|
|
49
|
+
const state = usePermissionSnapshot(store);
|
|
50
|
+
const hasPermission = useCallback(
|
|
51
|
+
(codes, options) => store.hasPermission(codes, options),
|
|
52
|
+
[store]
|
|
53
|
+
);
|
|
54
|
+
const hasRole = useCallback(
|
|
55
|
+
(codes, options) => store.hasRole(codes, options),
|
|
56
|
+
[store]
|
|
57
|
+
);
|
|
58
|
+
const can = useCallback(
|
|
59
|
+
(codes, options) => store.can(codes, options),
|
|
60
|
+
[store]
|
|
61
|
+
);
|
|
62
|
+
return {
|
|
63
|
+
permissions: state.permissions,
|
|
64
|
+
roles: state.roles,
|
|
65
|
+
isSuperAdmin: Boolean(state.isSuperAdmin),
|
|
66
|
+
hasPermission,
|
|
67
|
+
hasRole,
|
|
68
|
+
can,
|
|
69
|
+
setPermissions: store.setPermissions.bind(store),
|
|
70
|
+
setRoles: store.setRoles.bind(store),
|
|
71
|
+
setSuperAdmin: store.setSuperAdmin.bind(store),
|
|
72
|
+
hydrate: store.hydrate.bind(store),
|
|
73
|
+
clear: store.clear.bind(store),
|
|
74
|
+
store
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function useHasPermission(codes, options) {
|
|
78
|
+
const { hasPermission, permissions, isSuperAdmin } = usePermission();
|
|
79
|
+
void permissions;
|
|
80
|
+
void isSuperAdmin;
|
|
81
|
+
return hasPermission(codes, options);
|
|
82
|
+
}
|
|
83
|
+
function useHasRole(codes, options) {
|
|
84
|
+
const { hasRole, roles, isSuperAdmin } = usePermission();
|
|
85
|
+
void roles;
|
|
86
|
+
void isSuperAdmin;
|
|
87
|
+
return hasRole(codes, options);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// src/react/Can.tsx
|
|
91
|
+
import { Fragment, jsx } from "react/jsx-runtime";
|
|
92
|
+
function evaluateAccess(hasPermission, hasRole, props) {
|
|
93
|
+
const { permission, role, mode, combine = "and" } = props;
|
|
94
|
+
const options = { mode };
|
|
95
|
+
const hasPermCheck = permission !== void 0;
|
|
96
|
+
const hasRoleCheck = role !== void 0;
|
|
97
|
+
if (!hasPermCheck && !hasRoleCheck) return true;
|
|
98
|
+
const permOk = hasPermCheck ? hasPermission(permission, options) : true;
|
|
99
|
+
const roleOk = hasRoleCheck ? hasRole(role, options) : true;
|
|
100
|
+
if (hasPermCheck && hasRoleCheck) {
|
|
101
|
+
return combine === "or" ? permOk || roleOk : permOk && roleOk;
|
|
102
|
+
}
|
|
103
|
+
return hasPermCheck ? permOk : roleOk;
|
|
104
|
+
}
|
|
105
|
+
function Can({
|
|
106
|
+
permission,
|
|
107
|
+
role,
|
|
108
|
+
mode,
|
|
109
|
+
combine,
|
|
110
|
+
children,
|
|
111
|
+
fallback = null
|
|
112
|
+
}) {
|
|
113
|
+
const { hasPermission, hasRole } = usePermission();
|
|
114
|
+
const allowed = evaluateAccess(hasPermission, hasRole, {
|
|
115
|
+
permission,
|
|
116
|
+
role,
|
|
117
|
+
mode,
|
|
118
|
+
combine
|
|
119
|
+
});
|
|
120
|
+
return /* @__PURE__ */ jsx(Fragment, { children: allowed ? children : fallback });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// src/react/index.ts
|
|
124
|
+
import { PermissionStore, createPermissionStore as createPermissionStore2 } from "../core";
|
|
125
|
+
export {
|
|
126
|
+
Can,
|
|
127
|
+
PermissionProvider,
|
|
128
|
+
PermissionStore,
|
|
129
|
+
createPermissionStore2 as createPermissionStore,
|
|
130
|
+
useHasPermission,
|
|
131
|
+
useHasRole,
|
|
132
|
+
usePermission
|
|
133
|
+
};
|
|
134
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/react/context.tsx","../../src/react/Can.tsx","../../src/react/index.ts"],"sourcesContent":["import {\n createContext,\n createElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\nimport {\n createPermissionStore,\n type CheckOptions,\n type PermissionCode,\n type PermissionState,\n type PermissionStore,\n type RoleCode,\n} from '../core';\n\nconst PermissionContext = createContext<PermissionStore | null>(null);\n\nexport interface PermissionProviderProps {\n children: ReactNode;\n /** Pass an existing store to share across trees, or omit to create one. */\n store?: PermissionStore;\n /** Initial state when the provider creates its own store. */\n initialState?: Partial<PermissionState>;\n}\n\nexport function PermissionProvider({\n children,\n store: externalStore,\n initialState,\n}: PermissionProviderProps) {\n const store = useMemo(\n () => externalStore ?? createPermissionStore(initialState),\n // store identity is intentional; initialState only applies on first create\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [externalStore],\n );\n\n return createElement(PermissionContext.Provider, { value: store }, children);\n}\n\nfunction useStore(): PermissionStore {\n const store = useContext(PermissionContext);\n if (!store) {\n throw new Error(\n '[com-angel-authorization/react] usePermission* hooks must be used within <PermissionProvider>.',\n );\n }\n return store;\n}\n\nfunction usePermissionSnapshot(store: PermissionStore): PermissionState {\n const [state, setState] = useState(() => store.getState());\n\n useEffect(() => {\n setState(store.getState());\n return store.subscribe(setState);\n }, [store]);\n\n return state;\n}\n\nexport interface UsePermissionResult {\n permissions: PermissionCode[];\n roles: RoleCode[];\n isSuperAdmin: boolean;\n hasPermission: (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => boolean;\n hasRole: (codes: RoleCode | RoleCode[], options?: CheckOptions) => boolean;\n can: (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => boolean;\n setPermissions: (permissions: PermissionCode[]) => void;\n setRoles: (roles: RoleCode[]) => void;\n setSuperAdmin: (isSuperAdmin: boolean) => void;\n hydrate: (payload: Partial<PermissionState>) => void;\n clear: () => void;\n store: PermissionStore;\n}\n\nexport function usePermission(): UsePermissionResult {\n const store = useStore();\n const state = usePermissionSnapshot(store);\n\n const hasPermission = useCallback(\n (codes: PermissionCode | PermissionCode[], options?: CheckOptions) =>\n store.hasPermission(codes, options),\n [store],\n );\n\n const hasRole = useCallback(\n (codes: RoleCode | RoleCode[], options?: CheckOptions) => store.hasRole(codes, options),\n [store],\n );\n\n const can = useCallback(\n (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => store.can(codes, options),\n [store],\n );\n\n return {\n permissions: state.permissions,\n roles: state.roles,\n isSuperAdmin: Boolean(state.isSuperAdmin),\n hasPermission,\n hasRole,\n can,\n setPermissions: store.setPermissions.bind(store),\n setRoles: store.setRoles.bind(store),\n setSuperAdmin: store.setSuperAdmin.bind(store),\n hydrate: store.hydrate.bind(store),\n clear: store.clear.bind(store),\n store,\n };\n}\n\n/** Returns whether the current user has the given permission(s). */\nexport function useHasPermission(\n codes: PermissionCode | PermissionCode[],\n options?: CheckOptions,\n): boolean {\n const { hasPermission, permissions, isSuperAdmin } = usePermission();\n // re-compute when permission list / super-admin changes\n void permissions;\n void isSuperAdmin;\n return hasPermission(codes, options);\n}\n\n/** Returns whether the current user has the given role(s). */\nexport function useHasRole(\n codes: RoleCode | RoleCode[],\n options?: CheckOptions,\n): boolean {\n const { hasRole, roles, isSuperAdmin } = usePermission();\n void roles;\n void isSuperAdmin;\n return hasRole(codes, options);\n}\n","import type { ReactNode } from 'react';\nimport type { CheckOptions, PermissionCode, RoleCode } from '../core';\nimport { usePermission } from './context';\n\nexport interface CanProps {\n /** Permission codes to check. */\n permission?: PermissionCode | PermissionCode[];\n /** Role codes to check. */\n role?: RoleCode | RoleCode[];\n /**\n * `any` — pass when at least one code matches (default)\n * `all` — pass only when every code matches\n */\n mode?: CheckOptions['mode'];\n /**\n * How permission and role conditions combine when both are provided.\n * Default: `and` (must satisfy both).\n */\n combine?: 'and' | 'or';\n children: ReactNode;\n /** Fallback when access is denied. */\n fallback?: ReactNode;\n}\n\nfunction evaluateAccess(\n hasPermission: (c: PermissionCode | PermissionCode[], o?: CheckOptions) => boolean,\n hasRole: (c: RoleCode | RoleCode[], o?: CheckOptions) => boolean,\n props: Pick<CanProps, 'permission' | 'role' | 'mode' | 'combine'>,\n): boolean {\n const { permission, role, mode, combine = 'and' } = props;\n const options: CheckOptions = { mode };\n\n const hasPermCheck = permission !== undefined;\n const hasRoleCheck = role !== undefined;\n\n if (!hasPermCheck && !hasRoleCheck) return true;\n\n const permOk = hasPermCheck ? hasPermission(permission!, options) : true;\n const roleOk = hasRoleCheck ? hasRole(role!, options) : true;\n\n if (hasPermCheck && hasRoleCheck) {\n return combine === 'or' ? permOk || roleOk : permOk && roleOk;\n }\n\n return hasPermCheck ? permOk : roleOk;\n}\n\n/**\n * Conditionally render children based on permission / role.\n *\n * @example\n * <Can permission=\"user:edit\">\n * <button>Edit</button>\n * </Can>\n *\n * <Can permission={['user:edit', 'user:delete']} mode=\"all\" fallback={null}>\n * <AdminPanel />\n * </Can>\n */\nexport function Can({\n permission,\n role,\n mode,\n combine,\n children,\n fallback = null,\n}: CanProps) {\n const { hasPermission, hasRole } = usePermission();\n const allowed = evaluateAccess(hasPermission, hasRole, {\n permission,\n role,\n mode,\n combine,\n });\n\n return <>{allowed ? children : fallback}</>;\n}\n","export { PermissionProvider, usePermission, useHasPermission, useHasRole } from './context';\nexport type { PermissionProviderProps, UsePermissionResult } from './context';\n\nexport { Can } from './Can';\nexport type { CanProps } from './Can';\n\nexport type {\n CheckOptions,\n MatchMode,\n PermissionChecker,\n PermissionCode,\n PermissionListener,\n PermissionState,\n RoleCode,\n} from '../core';\n\nexport { PermissionStore, createPermissionStore } from '../core';\n"],"mappings":"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","names":["createPermissionStore"]}
|