@lark-apaas/auth-sdk 0.1.1 → 0.1.3

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 CHANGED
@@ -16,7 +16,7 @@ yarn add @lark-apaas/auth-sdk
16
16
 
17
17
  ```tsx
18
18
  import React from 'react';
19
- import { AuthProvider, CanRole, useAuthAbility } from '@lark-apaas/auth-sdk';
19
+ import { AuthProvider, CanRole, useAuth } from '@lark-apaas/auth-sdk';
20
20
 
21
21
  export default function App() {
22
22
  return (
@@ -11,6 +11,7 @@ export declare const AbilityContext: React.Context<MongoAbility<import("@casl/ab
11
11
  */
12
12
  interface AuthStateContextValue {
13
13
  ability: MongoAbility;
14
+ permissions: string[];
14
15
  isLoading: boolean;
15
16
  error: Error | null;
16
17
  fetchPermissions: (userId?: string) => Promise<void>;
@@ -57,11 +58,10 @@ export declare function getAbility(permissionApiConfig: AuthSdkConfig['permissio
57
58
  *
58
59
  * @example
59
60
  * ```tsx
60
- * import { useAuth, useAbility } from '@lark-apaas/auth-sdk';
61
+ * import { useAuth } from '@lark-apaas/auth-sdk';
61
62
  *
62
63
  * function MyComponent() {
63
- * const { permissions, isLoading } = useAuth();
64
- * const ability = useAbility();
64
+ * const { ability, isLoading } = useAuth();
65
65
  *
66
66
  * if (isLoading) return <div>Loading...</div>;
67
67
  *
@@ -75,63 +75,87 @@ export declare function getAbility(permissionApiConfig: AuthSdkConfig['permissio
75
75
  */
76
76
  export declare function useAuth(): AuthStateContextValue;
77
77
  /**
78
- * useAuthAbility Hook - 获取 Ability 实例
78
+ * CASL 原始 Can 组件(内部使用)
79
+ */
80
+ declare const CaslCan: React.FunctionComponent<import("@casl/react").BoundCanProps<MongoAbility<import("@casl/ability").AbilityTuple, import("@casl/ability").MongoQuery>>>;
81
+ /**
82
+ * Can Component - 基于 Ability 实例的条件渲染组件
83
+ *
84
+ * 内置 isLoading 保护:权限加载期间渲染 fallback(默认为 null),
85
+ * 避免因 ability 未就绪而误判为无权限导致内容闪烁。
79
86
  *
80
87
  * @example
81
88
  * ```tsx
82
- * import { useAuthAbility } from '@lark-apaas/auth-sdk';
89
+ * import { Can } from '@lark-apaas/auth-sdk';
83
90
  *
84
91
  * function MyComponent() {
85
- * const ability = useAuthAbility();
86
- *
87
92
  * return (
88
- * <button disabled={ability.cannot('create', 'Task')}>
89
- * Create Task
90
- * </button>
93
+ * <Can I="Admin" a="@role" fallback={<Loading />}>
94
+ * <TaskList />
95
+ * </Can>
91
96
  * );
92
97
  * }
93
98
  * ```
94
99
  */
95
- export declare function useAuthAbility(): MongoAbility;
100
+ export declare function Can({ fallback, ...props }: React.ComponentProps<typeof CaslCan> & {
101
+ fallback?: React.ReactNode;
102
+ }): import("react/jsx-runtime").JSX.Element;
96
103
  /**
97
- * Can Component - 基于 Ability 实例的条件渲染组件
104
+ * CanRole Component - 基于角色的条件渲染组件
105
+ *
106
+ * 支持 fallback prop,用于在权限加载期间显示自定义内容(如 Loading),
107
+ * 避免加载期间因 can() 返回 false 而误判为无权限。
98
108
  *
99
109
  * @example
100
110
  * ```tsx
101
- * import { Can } from '@lark-apaas/auth-sdk';
111
+ * import { CanRole } from '@lark-apaas/auth-sdk';
102
112
  *
103
113
  * function MyComponent() {
104
114
  * return (
105
- * <Can I="Admin" a="@role">
106
- * <TaskList />
107
- * </Can>
115
+ * <CanRole roles={['admin']} fallback={<Loading />}>
116
+ * <AdminPanel />
117
+ * </CanRole>
108
118
  * );
109
119
  * }
110
120
  * ```
111
121
  */
112
- export declare const Can: React.FunctionComponent<import("@casl/react").BoundCanProps<MongoAbility<import("@casl/ability").AbilityTuple, import("@casl/ability").MongoQuery>>>;
113
- export declare const useCanRole: ({ roles }: {
122
+ export declare function CanRole({ children, roles, fallback, }: {
123
+ children: React.ReactNode;
114
124
  roles: string[];
115
- }) => boolean;
125
+ fallback?: React.ReactNode;
126
+ }): import("react/jsx-runtime").JSX.Element | null;
116
127
  /**
117
- * CanRole Component - 基于 Ability 实例的角色条件渲染组件
128
+ * useUserPermissions Hook - 获取当前用户的权限点位列表
129
+ */
130
+ export declare function useUserPermissions(): string[];
131
+ /**
132
+ * useCanPermission Hook - 判断用户是否拥有指定权限点位
133
+ *
134
+ * @param permissions - 需要检查的权限点位列表
135
+ * @param match - 匹配模式:'any' 任一匹配即可,'all' 需要全部匹配
136
+ */
137
+ export declare function useCanPermission(permissions: string[], match?: 'any' | 'all'): boolean;
138
+ /**
139
+ * CanPermission Component - 基于权限点位的条件渲染组件
118
140
  *
119
141
  * @example
120
142
  * ```tsx
121
- * import { CanRole } from '@lark-apaas/auth-sdk';
143
+ * import { CanPermission } from '@lark-apaas/auth-sdk';
122
144
  *
123
145
  * function MyComponent() {
124
146
  * return (
125
- * <CanRole roles={['role_admin', 'role_editor']}>
126
- * <TaskList />
127
- * </CanRole>
147
+ * <CanPermission permissions={['task:create', 'task:edit']} match="any">
148
+ * <TaskEditor />
149
+ * </CanPermission>
128
150
  * );
129
151
  * }
130
152
  * ```
131
153
  */
132
- export declare function CanRole({ children, roles, }: {
154
+ export declare function CanPermission({ children, permissions, match, fallback, }: {
133
155
  children: React.ReactNode;
134
- roles: string[];
135
- }): import("react/jsx-runtime").JSX.Element | null;
156
+ permissions: string[];
157
+ match?: 'any' | 'all';
158
+ fallback?: React.ReactNode;
159
+ }): import("react/jsx-runtime").JSX.Element;
136
160
  export {};
137
161
  //# sourceMappingURL=AuthProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AuthProvider.d.ts","sourceRoot":"","sources":["../src/AuthProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAK7C;;GAEG;AACH,eAAO,MAAM,cAAc,uGAE1B,CAAC;AAEF;;;GAGG;AACH,UAAU,qBAAqB;IAC7B,OAAO,EAAE,YAAY,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,gBAAgB,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtD;AAOD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,iBAAiB,2CA8DnE;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,mBAAmB,EAAE,aAAa,CAAC,eAAe,CAAC,2GAmBpD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,OAAO,IAAI,qBAAqB,CAQ/C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,IAAI,YAAY,CAE7C;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,GAAG,sJAA+C,CAAC;AAEhE,eAAO,MAAM,UAAU,GAAa,WAAW;IAAE,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,KAAG,OASpE,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,EACtB,QAAQ,EACR,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,kDAIA"}
1
+ {"version":3,"file":"AuthProvider.d.ts","sourceRoot":"","sources":["../src/AuthProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAK7C;;GAEG;AACH,eAAO,MAAM,cAAc,uGAE1B,CAAC;AAOF;;;GAGG;AACH,UAAU,qBAAqB;IAC7B,OAAO,EAAE,YAAY,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,gBAAgB,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtD;AAOD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,iBAAiB,2CA+EnE;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,mBAAmB,EAAE,aAAa,CAAC,eAAe,CAAC,2GAmBpD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,OAAO,IAAI,qBAAqB,CAQ/C;AAED;;GAEG;AACH,QAAA,MAAM,OAAO,sJAA+C,CAAC;AAE7D;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,GAAG,CAAC,EAClB,QAAe,EACf,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,OAAO,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,2CAKvE;AAoBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,OAAO,CAAC,EACtB,QAAQ,EACR,KAAK,EACL,QAAe,GAChB,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,kDAKA;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAE7C;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EAAE,EACrB,KAAK,GAAE,KAAK,GAAG,KAAa,GAC3B,OAAO,CAOT;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,WAAW,EACX,KAAa,EACb,QAAe,GAChB,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACtB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,2CAGA"}
@@ -7,12 +7,14 @@ const AbilityContext = /*#__PURE__*/ createContext(createAbility({
7
7
  permissions: [],
8
8
  roles: []
9
9
  }));
10
+ const PermissionsContext = /*#__PURE__*/ createContext([]);
10
11
  const AuthStateContext = /*#__PURE__*/ createContext(null);
11
12
  function AuthProvider({ children, config }) {
12
13
  const [ability, setAbility] = useState(()=>createAbility({}));
13
- const [isLoading, setIsLoading] = useState(false);
14
- const [error, setError] = useState(null);
14
+ const [permissions, setPermissions] = useState([]);
15
15
  const [client] = useState(()=>config?.permissionApi ? new PermissionClient(config.permissionApi) : null);
16
+ const [isLoading, setIsLoading] = useState(()=>config?.enable !== false && null !== client);
17
+ const [error, setError] = useState(null);
16
18
  const fetchPermissions = useCallback(async ()=>{
17
19
  if (!client) return;
18
20
  setIsLoading(true);
@@ -23,6 +25,10 @@ function AuthProvider({ children, config }) {
23
25
  roles: data.roles
24
26
  });
25
27
  setAbility(newAbility);
28
+ if (config?.permissionPointsApi) try {
29
+ const userPermissions = await client.fetchUserPermissions(config.permissionPointsApi);
30
+ setPermissions(userPermissions);
31
+ } catch {}
26
32
  config?.onSuccess?.(data);
27
33
  } catch (err) {
28
34
  const error = err instanceof Error ? err : new Error(String(err));
@@ -43,15 +49,19 @@ function AuthProvider({ children, config }) {
43
49
  ]);
44
50
  const stateContextValue = {
45
51
  ability,
52
+ permissions,
46
53
  isLoading,
47
54
  error,
48
55
  fetchPermissions
49
56
  };
50
57
  return /*#__PURE__*/ jsx(AbilityContext.Provider, {
51
58
  value: ability,
52
- children: /*#__PURE__*/ jsx(AuthStateContext.Provider, {
53
- value: stateContextValue,
54
- children: children
59
+ children: /*#__PURE__*/ jsx(PermissionsContext.Provider, {
60
+ value: permissions,
61
+ children: /*#__PURE__*/ jsx(AuthStateContext.Provider, {
62
+ value: stateContextValue,
63
+ children: children
64
+ })
55
65
  })
56
66
  });
57
67
  }
@@ -74,21 +84,51 @@ function useAuth() {
74
84
  if (!context) throw new Error('useAuth must be used within an AuthProvider');
75
85
  return context;
76
86
  }
77
- function useAuthAbility() {
78
- return useContext(AbilityContext);
87
+ const CaslCan = createContextualCan(AbilityContext.Consumer);
88
+ function Can({ fallback = null, ...props }) {
89
+ const authState = useContext(AuthStateContext);
90
+ if (authState?.isLoading) return /*#__PURE__*/ jsx(Fragment, {
91
+ children: fallback
92
+ });
93
+ return /*#__PURE__*/ jsx(CaslCan, {
94
+ ...props
95
+ });
79
96
  }
80
- const Can = createContextualCan(AbilityContext.Consumer);
81
- const useCanRole = function({ roles }) {
97
+ function useCanRole({ roles }) {
82
98
  const ability = useContext(AbilityContext);
99
+ const authState = useContext(AuthStateContext);
83
100
  const allowed = !roles || 0 === roles.length || roles.length > 0 && roles.some((role)=>ability.can(role, ROLE_SUBJECT));
84
- return !!allowed;
85
- };
86
- function CanRole({ children, roles }) {
87
- const allowed = useCanRole({
101
+ return {
102
+ allowed: !!allowed,
103
+ isLoading: authState?.isLoading ?? false
104
+ };
105
+ }
106
+ function CanRole({ children, roles, fallback = null }) {
107
+ const { allowed, isLoading } = useCanRole({
88
108
  roles
89
109
  });
110
+ if (isLoading) return /*#__PURE__*/ jsx(Fragment, {
111
+ children: fallback
112
+ });
90
113
  return allowed ? /*#__PURE__*/ jsx(Fragment, {
91
114
  children: children
92
115
  }) : null;
93
116
  }
94
- export { AbilityContext, AuthProvider, Can, CanRole, getAbility, useAuth, useAuthAbility, useCanRole };
117
+ function useUserPermissions() {
118
+ return useContext(PermissionsContext);
119
+ }
120
+ function useCanPermission(permissions, match = 'any') {
121
+ const userPermissions = useContext(PermissionsContext);
122
+ if (!permissions || 0 === permissions.length) return true;
123
+ const permSet = new Set(userPermissions);
124
+ return 'all' === match ? permissions.every((p)=>permSet.has(p)) : permissions.some((p)=>permSet.has(p));
125
+ }
126
+ function CanPermission({ children, permissions, match = 'any', fallback = null }) {
127
+ const allowed = useCanPermission(permissions, match);
128
+ return allowed ? /*#__PURE__*/ jsx(Fragment, {
129
+ children: children
130
+ }) : /*#__PURE__*/ jsx(Fragment, {
131
+ children: fallback
132
+ });
133
+ }
134
+ export { AbilityContext, AuthProvider, Can, CanPermission, CanRole, getAbility, useAuth, useCanPermission, useUserPermissions };
package/lib/index.d.ts CHANGED
@@ -7,6 +7,7 @@
7
7
  export type { PermissionApiResponse, PermissionApiConfig, AuthSdkConfig, } from './types';
8
8
  export { ROLE_SUBJECT } from './ability-factory';
9
9
  export { PermissionClient } from './permission-client';
10
- export { AuthProvider, useAuth, CanRole, AbilityContext } from './AuthProvider';
10
+ export { AuthProvider, useAuth, CanRole, AbilityContext, useUserPermissions, useCanPermission, CanPermission, } from './AuthProvider';
11
+ export { CanPermission as CanPerm } from './AuthProvider';
11
12
  export type { AuthProviderProps } from './AuthProvider';
12
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,qBAAqB,EACrB,mBAAmB,EACnB,aAAa,GACd,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhF,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,qBAAqB,EACrB,mBAAmB,EACnB,aAAa,GACd,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGvD,OAAO,EACL,YAAY,EACZ,OAAO,EACP,OAAO,EACP,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,GACd,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,aAAa,IAAI,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE1D,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC"}
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import { ROLE_SUBJECT } from "./ability-factory.js";
2
2
  import { PermissionClient } from "./permission-client.js";
3
- import { AbilityContext, AuthProvider, CanRole, useAuth } from "./AuthProvider.js";
4
- export { AbilityContext, AuthProvider, CanRole, PermissionClient, ROLE_SUBJECT, useAuth };
3
+ import { AbilityContext, AuthProvider, CanPermission, CanRole, useAuth, useCanPermission, useUserPermissions } from "./AuthProvider.js";
4
+ export { AbilityContext, AuthProvider, CanPermission as CanPerm, CanPermission, CanRole, PermissionClient, ROLE_SUBJECT, useAuth, useCanPermission, useUserPermissions };
@@ -9,6 +9,10 @@ export declare class PermissionClient {
9
9
  * 获取用户权限数据
10
10
  */
11
11
  fetchPermissions(): Promise<PermissionApiResponse>;
12
+ /**
13
+ * 获取用户权限点位列表
14
+ */
15
+ fetchUserPermissions(config: PermissionApiConfig): Promise<string[]>;
12
16
  /**
13
17
  * 更新配置
14
18
  */
@@ -1 +1 @@
1
- {"version":3,"file":"permission-client.d.ts","sourceRoot":"","sources":["../src/permission-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAE1E;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAsB;gBAExB,MAAM,EAAE,mBAAmB;IAIvC;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,qBAAqB,CAAC;IAkDxD;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,IAAI;IAOxD;;OAEG;IACH,SAAS,IAAI,mBAAmB;CAGjC"}
1
+ {"version":3,"file":"permission-client.d.ts","sourceRoot":"","sources":["../src/permission-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAG1E;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAsB;gBAExB,MAAM,EAAE,mBAAmB;IAIvC;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,qBAAqB,CAAC;IAoDxD;;OAEG;IACG,oBAAoB,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA4C1E;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,IAAI;IAOxD;;OAEG;IACH,SAAS,IAAI,mBAAmB;CAGjC"}
@@ -1,3 +1,4 @@
1
+ import { slardar } from "@lark-apaas/internal-slardar";
1
2
  class PermissionClient {
2
3
  constructor(config){
3
4
  this.config = config;
@@ -27,7 +28,43 @@ class PermissionClient {
27
28
  };
28
29
  } catch (error) {
29
30
  clearTimeout(timeoutId);
30
- if (error instanceof Error && 'AbortError' === error.name) throw new Error(`Permission API request timeout after ${timeout}ms`);
31
+ if (error instanceof Error && 'AbortError' === error.name) {
32
+ slardar.captureException(error, {
33
+ source: 'auth-sdk',
34
+ type: 'timeout'
35
+ });
36
+ throw new Error(`Permission API request timeout after ${timeout}ms`);
37
+ }
38
+ slardar.captureException(error, {
39
+ source: 'auth-sdk',
40
+ type: 'fetch'
41
+ });
42
+ throw error;
43
+ }
44
+ }
45
+ async fetchUserPermissions(config) {
46
+ const { url, timeout = 5000, headers = {} } = config;
47
+ const requestHeaders = {
48
+ ...headers,
49
+ 'Content-Type': 'application/json',
50
+ 'X-Suda-Csrf-Token': window.csrfToken || ''
51
+ };
52
+ const controller = new AbortController();
53
+ const timeoutId = setTimeout(()=>controller.abort(), timeout);
54
+ try {
55
+ const response = await fetch(url, {
56
+ method: 'POST',
57
+ headers: requestHeaders,
58
+ signal: controller.signal,
59
+ credentials: 'include'
60
+ });
61
+ clearTimeout(timeoutId);
62
+ if (!response.ok) throw new Error(`Permissions API returned ${response.status}: ${response.statusText}`);
63
+ const data = await response.json();
64
+ return data.data?.permissions || [];
65
+ } catch (error) {
66
+ clearTimeout(timeoutId);
67
+ if (error instanceof Error && 'AbortError' === error.name) throw new Error(`Permissions API request timeout after ${timeout}ms`);
31
68
  throw error;
32
69
  }
33
70
  }
package/lib/types.d.ts CHANGED
@@ -35,6 +35,8 @@ export interface UserRole {
35
35
  */
36
36
  export interface PermissionApiResponse {
37
37
  roles: string[];
38
+ /** 用户的有效权限点位列表 */
39
+ permissions?: string[];
38
40
  fetchedAt?: string | Date;
39
41
  }
40
42
  /**
@@ -63,6 +65,11 @@ export interface AuthSdkConfig {
63
65
  * 权限 API 配置
64
66
  */
65
67
  permissionApi?: PermissionApiConfig;
68
+ /**
69
+ * 权限点位 API 配置(可选)
70
+ * 配置后 AuthProvider 会额外请求用户的有效权限点位
71
+ */
72
+ permissionPointsApi?: PermissionApiConfig;
66
73
  /**
67
74
  * 是否在初始化时使用获取权限
68
75
  * @default false
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB;CACF;AAED;;GAEG;AACH,MAAM,MAAM,MAAM,GACd,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,MAAM,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAE7B;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,aAAa,CAAC,EAAE,mBAAmB,CAAC;IAEpC;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAEjC;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,IAAI,CAAC;CACnD;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,OAAO,EAAE,OAAO,GAAG,OAAO,EAAE,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB;CACF;AAED;;GAEG;AACH,MAAM,MAAM,MAAM,GACd,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,MAAM,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAE7B;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,kBAAkB;IAClB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,aAAa,CAAC,EAAE,mBAAmB,CAAC;IAEpC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAE1C;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAEjC;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,IAAI,CAAC;CACnD;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,OAAO,EAAE,OAAO,GAAG,OAAO,EAAE,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/auth-sdk",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "基于 CASL 的前端鉴权 SDK",
5
5
  "types": "./lib/index.d.ts",
6
6
  "main": "./lib/index.js",
@@ -20,7 +20,8 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "@casl/ability": "^6.7.5",
23
- "@casl/react": "^5.0.0"
23
+ "@casl/react": "^5.0.0",
24
+ "@lark-apaas/internal-slardar": "^0.0.3"
24
25
  },
25
26
  "devDependencies": {
26
27
  "@rsbuild/core": "~1.4.13",