@nocobase/portal-template-default 1.0.0 → 1.0.2

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.
Files changed (194) hide show
  1. package/README.MD +90 -1
  2. package/components.json +3 -1
  3. package/package.json +21 -5
  4. package/registry/nocobase-acl/README.md +19 -0
  5. package/registry/nocobase-acl/components/acl-boundary.tsx +106 -0
  6. package/registry/nocobase-acl/components/index.ts +3 -0
  7. package/registry/nocobase-acl/components/role-options.ts +36 -0
  8. package/registry/nocobase-acl/components/role-switcher.tsx +135 -0
  9. package/registry/nocobase-acl/demo/boundary-api.tsx +186 -0
  10. package/registry/nocobase-acl/demo/components.tsx +231 -0
  11. package/registry/nocobase-acl/demo/index.tsx +505 -0
  12. package/registry/nocobase-acl/demo/lazy-route.tsx +10 -0
  13. package/registry/nocobase-acl/demo/prompt-generator.tsx +134 -0
  14. package/registry/nocobase-acl/demo/role-switcher-prompt-generator.tsx +198 -0
  15. package/registry/nocobase-acl/demo/scenario-section.tsx +37 -0
  16. package/registry/nocobase-acl/extension.tsx +71 -0
  17. package/registry/nocobase-acl/index.ts +1 -0
  18. package/registry/nocobase-acl/tests/acl-regression.mjs +314 -0
  19. package/registry/nocobase-ai/README.md +70 -0
  20. package/registry/nocobase-ai/adapters/react-hook-form.ts +20 -0
  21. package/registry/nocobase-ai/assets/nocobase-ai-chat.svg +50 -0
  22. package/registry/nocobase-ai/components/ai-root-provider.tsx +32 -0
  23. package/registry/nocobase-ai/components/chat/ai-employee-avatar.tsx +31 -0
  24. package/registry/nocobase-ai/components/chat/chat-attachment.tsx +92 -0
  25. package/registry/nocobase-ai/components/chat/chat-compact.tsx +90 -0
  26. package/registry/nocobase-ai/components/chat/chat-composer.tsx +429 -0
  27. package/registry/nocobase-ai/components/chat/chat-empty-state.tsx +51 -0
  28. package/registry/nocobase-ai/components/chat/chat-header.tsx +88 -0
  29. package/registry/nocobase-ai/components/chat/chat-history-dialog.tsx +77 -0
  30. package/registry/nocobase-ai/components/chat/chat-message.tsx +252 -0
  31. package/registry/nocobase-ai/components/chat/chat-messages.tsx +173 -0
  32. package/registry/nocobase-ai/components/chat/chat-window.tsx +118 -0
  33. package/registry/nocobase-ai/components/chat/conversation-list.tsx +343 -0
  34. package/registry/nocobase-ai/components/chat/markdown-message.tsx +165 -0
  35. package/registry/nocobase-ai/components/chat/model-select-options.tsx +30 -0
  36. package/registry/nocobase-ai/components/chat/reasoning-panel.tsx +29 -0
  37. package/registry/nocobase-ai/components/chat/sub-agent-conversation.tsx +142 -0
  38. package/registry/nocobase-ai/components/chat/tool-call-card.tsx +316 -0
  39. package/registry/nocobase-ai/components/chat/user-prompt-editor.tsx +99 -0
  40. package/registry/nocobase-ai/components/chat/work-context-chip.tsx +114 -0
  41. package/registry/nocobase-ai/components/index.ts +59 -0
  42. package/registry/nocobase-ai/components/page-elements/ai-form.tsx +44 -0
  43. package/registry/nocobase-ai/components/page-elements/page-element-provider.tsx +469 -0
  44. package/registry/nocobase-ai/components/surfaces/chat-dialog.tsx +31 -0
  45. package/registry/nocobase-ai/components/surfaces/chat-inline.tsx +18 -0
  46. package/registry/nocobase-ai/components/surfaces/chat-page.tsx +18 -0
  47. package/registry/nocobase-ai/components/surfaces/chat-side-panel-layout.tsx +54 -0
  48. package/registry/nocobase-ai/components/surfaces/chat-side-panel.tsx +74 -0
  49. package/registry/nocobase-ai/components/surfaces/chat-surface-actions.tsx +54 -0
  50. package/registry/nocobase-ai/components/tools/builtin-tool-renderers.tsx +31 -0
  51. package/registry/nocobase-ai/components/tools/business-report-dialog.tsx +364 -0
  52. package/registry/nocobase-ai/components/tools/business-report-renderer.tsx +122 -0
  53. package/registry/nocobase-ai/components/tools/business-report-utils.tsx +282 -0
  54. package/registry/nocobase-ai/components/tools/chart-renderer.tsx +99 -0
  55. package/registry/nocobase-ai/components/tools/echarts-preview.tsx +59 -0
  56. package/registry/nocobase-ai/components/tools/echarts-runtime-advanced.ts +18 -0
  57. package/registry/nocobase-ai/components/tools/echarts-runtime-common.ts +20 -0
  58. package/registry/nocobase-ai/components/tools/echarts-runtime-components.ts +34 -0
  59. package/registry/nocobase-ai/components/tools/echarts-runtime-hierarchy.ts +24 -0
  60. package/registry/nocobase-ai/components/tools/echarts-runtime.ts +138 -0
  61. package/registry/nocobase-ai/components/tools/sub-agent-renderer.tsx +67 -0
  62. package/registry/nocobase-ai/components/tools/suggestions-renderer.tsx +59 -0
  63. package/registry/nocobase-ai/components/tools/tool-renderer-provider.tsx +55 -0
  64. package/registry/nocobase-ai/components/tools/tool-renderer-utils.ts +18 -0
  65. package/registry/nocobase-ai/components/tools/workflow-renderer.tsx +108 -0
  66. package/registry/nocobase-ai/components/triggers/ai-chat-floating-trigger.tsx +73 -0
  67. package/registry/nocobase-ai/components/triggers/ai-employee-shortcut.tsx +149 -0
  68. package/registry/nocobase-ai/demo/configuration-gate.tsx +49 -0
  69. package/registry/nocobase-ai/demo/container-showcase.tsx +210 -0
  70. package/registry/nocobase-ai/demo/floating.tsx +134 -0
  71. package/registry/nocobase-ai/demo/index.tsx +346 -0
  72. package/registry/nocobase-ai/demo/interaction-showcase.tsx +151 -0
  73. package/registry/nocobase-ai/demo/page-context-prompt-generator.tsx +355 -0
  74. package/registry/nocobase-ai/demo/page-context.tsx +884 -0
  75. package/registry/nocobase-ai/demo/page-element-showcase.tsx +197 -0
  76. package/registry/nocobase-ai/demo/prompt-card.tsx +41 -0
  77. package/registry/nocobase-ai/demo/prompt-generator.tsx +452 -0
  78. package/registry/nocobase-ai/demo/shortcut.tsx +1207 -0
  79. package/registry/nocobase-ai/demo/tool-cards.tsx +530 -0
  80. package/registry/nocobase-ai/extension.tsx +158 -0
  81. package/registry/nocobase-ai/global-ai-chat.tsx +213 -0
  82. package/registry/nocobase-ai/index.ts +3 -0
  83. package/registry/nocobase-ai/providers/ai-provider.tsx +323 -0
  84. package/registry/nocobase-ai/providers/avatars.ts +817 -0
  85. package/registry/nocobase-ai/providers/chat-context.tsx +109 -0
  86. package/registry/nocobase-ai/providers/chat-controller.ts +84 -0
  87. package/registry/nocobase-ai/providers/chat-message-utils.ts +198 -0
  88. package/registry/nocobase-ai/providers/chat-provider.tsx +871 -0
  89. package/registry/nocobase-ai/providers/chat-reducer.ts +147 -0
  90. package/registry/nocobase-ai/providers/chat-task-utils.ts +105 -0
  91. package/registry/nocobase-ai/providers/chat-transport.ts +184 -0
  92. package/registry/nocobase-ai/providers/form-registry.tsx +271 -0
  93. package/registry/nocobase-ai/providers/frontend-tool-registry.tsx +231 -0
  94. package/registry/nocobase-ai/providers/index.ts +61 -0
  95. package/registry/nocobase-ai/providers/model.ts +32 -0
  96. package/registry/nocobase-ai/providers/page-context.tsx +136 -0
  97. package/registry/nocobase-ai/providers/stream-coalescer.ts +60 -0
  98. package/registry/nocobase-ai/providers/stream-event-utils.ts +82 -0
  99. package/registry/nocobase-ai/providers/stream-parser.ts +61 -0
  100. package/registry/nocobase-ai/providers/sub-agent-stream.ts +316 -0
  101. package/registry/nocobase-ai/providers/types.ts +183 -0
  102. package/registry/nocobase-ai/providers/ui-message-stream.ts +463 -0
  103. package/registry/nocobase-ai/providers/use-automatic-tool-approval.ts +94 -0
  104. package/registry/nocobase-ai/providers/use-chat-attachments.ts +206 -0
  105. package/registry/nocobase-ai/providers/use-chat-message-actions.ts +554 -0
  106. package/registry/nocobase-ai/providers/use-chat-runtime.ts +210 -0
  107. package/registry/nocobase-ai/providers/use-chat-work-context.ts +93 -0
  108. package/registry/nocobase-ai/providers/use-conversation-catalog.ts +108 -0
  109. package/registry/nocobase-ai/providers/use-conversation-history.ts +178 -0
  110. package/registry/nocobase-ai/services/index.ts +7 -0
  111. package/registry/nocobase-ai/services/nocobase-ai-service.ts +454 -0
  112. package/registry/nocobase-ai/services/types.ts +82 -0
  113. package/registry/nocobase-ai/tests/business-report-regression.mjs +70 -0
  114. package/registry/nocobase-ai/tests/form-filler-regression.mjs +129 -0
  115. package/registry/nocobase-ai/tests/frontend-tool-regression.mjs +128 -0
  116. package/registry/nocobase-ai/tests/page-context-regression.mjs +48 -0
  117. package/registry/nocobase-ai/tests/stream-regression.mjs +207 -0
  118. package/registry/nocobase-i18n/README.md +53 -0
  119. package/registry/nocobase-i18n/components/index.ts +1 -0
  120. package/registry/nocobase-i18n/components/language-switcher.tsx +138 -0
  121. package/registry/nocobase-i18n/demo/index.tsx +209 -0
  122. package/registry/nocobase-i18n/demo/prompt-generator.tsx +155 -0
  123. package/registry/nocobase-i18n/extension.tsx +46 -0
  124. package/registry/nocobase-i18n/i18n-provider.ts +9 -0
  125. package/registry/nocobase-i18n/index.ts +6 -0
  126. package/registry/nocobase-i18n/locale-store.ts +134 -0
  127. package/registry/nocobase-i18n/locales/en-US.ts +89 -0
  128. package/registry/nocobase-i18n/locales/zh-CN.ts +85 -0
  129. package/registry/nocobase-i18n/provider.tsx +32 -0
  130. package/registry/nocobase-i18n/runtime.ts +118 -0
  131. package/registry/nocobase-i18n/server-resources.ts +184 -0
  132. package/registry/nocobase-i18n/tests/i18n-regression.mjs +42 -0
  133. package/registry.config.json +163 -0
  134. package/scripts/registry.mjs +164 -0
  135. package/src/App.css +95 -0
  136. package/src/App.tsx +87 -69
  137. package/src/app/extension.ts +11 -0
  138. package/src/app/extensions.tsx +49 -0
  139. package/src/components/access-control/access-denied.tsx +30 -0
  140. package/src/components/access-control/acl-bootstrap.tsx +9 -0
  141. package/src/components/access-control/acl-gate.tsx +36 -0
  142. package/src/components/access-control/navigate-to-accessible-resource.tsx +17 -0
  143. package/src/components/access-control/resource-access-guard.tsx +21 -0
  144. package/src/components/access-control/use-acl-runtime.ts +28 -0
  145. package/src/components/app-shell/breadcrumb.tsx +39 -3
  146. package/src/components/app-shell/document-title-handler.tsx +11 -20
  147. package/src/components/app-shell/header.tsx +22 -4
  148. package/src/components/app-shell/loading-overlay.tsx +2 -4
  149. package/src/components/app-shell/loading-state.tsx +15 -0
  150. package/src/components/app-shell/sidebar.tsx +103 -45
  151. package/src/components/data-table/data-table-pagination.tsx +27 -7
  152. package/src/components/data-table/data-table-styles.ts +57 -0
  153. package/src/components/data-table/data-table.tsx +14 -59
  154. package/src/components/resources/resource-label.ts +101 -0
  155. package/src/components/resources/views/create-view.tsx +17 -14
  156. package/src/components/resources/views/edit-view.tsx +17 -15
  157. package/src/components/resources/views/list-view.tsx +20 -10
  158. package/src/components/resources/views/show-view.tsx +20 -18
  159. package/src/index.tsx +2 -3
  160. package/src/lib/i18n.ts +161 -0
  161. package/src/lib/nocobase/acl/action.ts +147 -0
  162. package/src/lib/nocobase/acl/data-source.ts +24 -0
  163. package/src/lib/nocobase/acl/index.ts +6 -0
  164. package/src/lib/nocobase/acl/menu.ts +41 -0
  165. package/src/lib/nocobase/acl/record-permissions.ts +111 -0
  166. package/src/lib/nocobase/acl/store.ts +182 -0
  167. package/src/lib/nocobase/acl/types.ts +96 -0
  168. package/src/lib/nocobase/client.ts +279 -0
  169. package/src/lib/nocobase/error.ts +32 -0
  170. package/src/locales/en-US.ts +82 -0
  171. package/src/locales/index.ts +13 -0
  172. package/src/locales/zh-CN.ts +79 -0
  173. package/src/pages/users/create.tsx +98 -0
  174. package/src/pages/users/edit.tsx +92 -0
  175. package/src/pages/users/form-context.ts +57 -0
  176. package/src/pages/users/form-fields.tsx +211 -0
  177. package/src/pages/users/list.tsx +205 -0
  178. package/src/pages/users/show.tsx +187 -0
  179. package/src/pages/users/types.ts +20 -0
  180. package/src/providers/access-control.ts +34 -0
  181. package/src/providers/auth.ts +74 -60
  182. package/src/providers/constants.ts +3 -37
  183. package/src/providers/data.ts +242 -85
  184. package/vite.config.ts +17 -0
  185. package/src/pages/blog-posts/create.tsx +0 -177
  186. package/src/pages/blog-posts/edit.tsx +0 -197
  187. package/src/pages/blog-posts/list.tsx +0 -131
  188. package/src/pages/blog-posts/show.tsx +0 -81
  189. package/src/pages/categories/create.tsx +0 -73
  190. package/src/pages/categories/edit.tsx +0 -73
  191. package/src/pages/categories/index.ts +0 -4
  192. package/src/pages/categories/list.tsx +0 -86
  193. package/src/pages/categories/show.tsx +0 -37
  194. /package/src/pages/{blog-posts → users}/index.ts +0 -0
@@ -0,0 +1,34 @@
1
+ import type { AccessControlProvider } from "@refinedev/core";
2
+
3
+ import {
4
+ canAccessWithSnapshot,
5
+ getAclSnapshot,
6
+ loadAcl,
7
+ } from "@/lib/nocobase/acl";
8
+
9
+ export const accessControlProvider: AccessControlProvider = {
10
+ can: async ({ resource, action, params }) => {
11
+ const snapshot = await loadAcl();
12
+ const can = canAccessWithSnapshot(snapshot, { resource, action, params });
13
+
14
+ return {
15
+ can,
16
+ reason: can
17
+ ? undefined
18
+ : "You don't have permission to perform this action.",
19
+ };
20
+ },
21
+ options: {
22
+ buttons: {
23
+ enableAccessControl: true,
24
+ hideIfUnauthorized: true,
25
+ },
26
+ queryOptions: {
27
+ staleTime: Infinity,
28
+ },
29
+ },
30
+ };
31
+
32
+ export const canAccessCurrentAcl = (
33
+ params: Parameters<typeof canAccessWithSnapshot>[1]
34
+ ) => canAccessWithSnapshot(getAclSnapshot(), params);
@@ -1,10 +1,15 @@
1
1
  import type { AuthProvider } from "@refinedev/core";
2
2
 
3
+ import { nocobaseClient } from "@/lib/nocobase/client";
3
4
  import {
4
- AUTH_API_URL,
5
- getNocoBaseHeaders,
6
- NOCOBASE_TOKEN_KEY,
7
- } from "./constants";
5
+ clearAcl,
6
+ loadAcl,
7
+ type Role,
8
+ } from "@/lib/nocobase/acl";
9
+ import {
10
+ getNocoBaseErrorMessage,
11
+ NocoBaseHttpError,
12
+ } from "@/lib/nocobase/error";
8
13
 
9
14
  type NocoBaseUser = {
10
15
  id: number | string;
@@ -12,6 +17,7 @@ type NocoBaseUser = {
12
17
  username?: string;
13
18
  email?: string;
14
19
  avatar?: string;
20
+ roles?: Role[];
15
21
  };
16
22
 
17
23
  type NocoBaseSignInResponse = {
@@ -29,18 +35,9 @@ const CURRENT_USER_CACHE_MS = 30_000;
29
35
  let currentUserCache: CurrentUserCache | undefined;
30
36
  let currentUserRequest: Promise<NocoBaseUser> | undefined;
31
37
 
32
- const authUrl = (action: "signIn" | "signOut" | "check") =>
33
- `${AUTH_API_URL.replace(/\/$/, "")}/auth:${action}`;
34
-
35
38
  const getErrorMessage = (payload: unknown, fallback: string) => {
36
- if (typeof payload !== "object" || payload === null) return fallback;
37
- const error = payload as { message?: string; errors?: Array<{ message?: string }> };
38
- return error.errors?.[0]?.message ?? error.message ?? fallback;
39
- };
40
-
41
- const saveRenewedToken = (response: Response) => {
42
- const token = response.headers.get("x-new-token");
43
- if (token) localStorage.setItem(NOCOBASE_TOKEN_KEY, token);
39
+ if (payload instanceof NocoBaseHttpError) return payload.message;
40
+ return getNocoBaseErrorMessage(payload, fallback);
44
41
  };
45
42
 
46
43
  const clearCurrentUserCache = () => {
@@ -49,26 +46,23 @@ const clearCurrentUserCache = () => {
49
46
  };
50
47
 
51
48
  const getCurrentUser = async (): Promise<NocoBaseUser> => {
52
- const token = localStorage.getItem(NOCOBASE_TOKEN_KEY);
49
+ const token = nocobaseClient.getToken();
53
50
  if (!token) throw new Error("No NocoBase token");
54
51
 
55
- if (currentUserCache?.token === token && currentUserCache.expiresAt > Date.now()) {
56
- return currentUserCache.user;
52
+ const cached = currentUserCache;
53
+ if (cached && cached.token === token && cached.expiresAt > Date.now()) {
54
+ return cached.user;
57
55
  }
58
56
 
59
57
  if (currentUserRequest) return currentUserRequest;
60
58
 
61
59
  currentUserRequest = (async () => {
62
- const response = await fetch(authUrl("check"), {
63
- headers: getNocoBaseHeaders({ token, includeAuthenticator: true }),
60
+ const user = await nocobaseClient.action<NocoBaseUser>("auth", "check", {
61
+ token,
62
+ includeAuthenticator: true,
64
63
  });
65
- const payload = await response.json().catch(() => undefined);
66
- if (!response.ok) throw new Error(getErrorMessage(payload, "NocoBase session is invalid"));
67
-
68
- saveRenewedToken(response);
69
- const user = (payload?.data ?? payload) as NocoBaseUser;
70
64
  currentUserCache = {
71
- token: localStorage.getItem(NOCOBASE_TOKEN_KEY) ?? token,
65
+ token: nocobaseClient.getToken() ?? token,
72
66
  user,
73
67
  expiresAt: Date.now() + CURRENT_USER_CACHE_MS,
74
68
  };
@@ -89,7 +83,8 @@ export const authProvider: AuthProvider = {
89
83
  success: false,
90
84
  error: {
91
85
  name: "UnsupportedAuthenticator",
92
- message: "Configure this provider as a NocoBase authenticator before using social sign-in.",
86
+ message:
87
+ "Configure this provider as a NocoBase authenticator before using social sign-in.",
93
88
  },
94
89
  };
95
90
  }
@@ -98,62 +93,68 @@ export const authProvider: AuthProvider = {
98
93
  if (!account || !password) {
99
94
  return {
100
95
  success: false,
101
- error: { name: "LoginError", message: "Please enter your account and password." },
96
+ error: {
97
+ name: "LoginError",
98
+ message: "Please enter your account and password.",
99
+ },
102
100
  };
103
101
  }
104
102
 
105
103
  try {
106
- const response = await fetch(authUrl("signIn"), {
107
- method: "POST",
108
- headers: getNocoBaseHeaders({
104
+ const result = await nocobaseClient.action<NocoBaseSignInResponse>(
105
+ "auth",
106
+ "signIn",
107
+ {
108
+ method: "POST",
109
109
  includeAuthenticator: true,
110
- includeContentType: true,
111
- }),
112
- body: JSON.stringify({ account, password }),
113
- });
114
- const payload = await response.json().catch(() => undefined);
115
- if (!response.ok) {
116
- return {
117
- success: false,
118
- error: { name: "LoginError", message: getErrorMessage(payload, "Unable to sign in.") },
119
- };
120
- }
121
-
122
- const result = (payload?.data ?? payload) as NocoBaseSignInResponse;
110
+ body: { account, password },
111
+ }
112
+ );
123
113
  if (!result.token) {
124
114
  return {
125
115
  success: false,
126
- error: { name: "LoginError", message: "NocoBase did not return an access token." },
116
+ error: {
117
+ name: "LoginError",
118
+ message: "NocoBase did not return an access token.",
119
+ },
127
120
  };
128
121
  }
129
122
 
130
- localStorage.setItem(NOCOBASE_TOKEN_KEY, result.token);
123
+ nocobaseClient.setToken(result.token);
124
+ nocobaseClient.setRole(null);
131
125
  clearCurrentUserCache();
126
+ clearAcl();
132
127
  return { success: true, redirectTo: "/" };
133
- } catch {
128
+ } catch (error) {
134
129
  return {
135
130
  success: false,
136
131
  error: {
137
- name: "NetworkError",
138
- message:
139
- "Unable to reach the NocoBase server. If this is a remote NocoBase from localhost, enable backend CORS for X-Authenticator or use the Vite proxy.",
132
+ name:
133
+ error instanceof NocoBaseHttpError ? "LoginError" : "NetworkError",
134
+ message: getErrorMessage(
135
+ error,
136
+ "Unable to reach the NocoBase server. If this is a remote NocoBase from localhost, enable backend CORS for X-Authenticator or use the Vite proxy."
137
+ ),
140
138
  },
141
139
  };
142
140
  }
143
141
  },
144
142
 
145
143
  logout: async () => {
146
- const token = localStorage.getItem(NOCOBASE_TOKEN_KEY);
144
+ const token = nocobaseClient.getToken();
147
145
  try {
148
146
  if (token) {
149
- await fetch(authUrl("signOut"), {
147
+ await nocobaseClient.action("auth", "signOut", {
150
148
  method: "POST",
151
- headers: getNocoBaseHeaders({ token, includeAuthenticator: true }),
149
+ token,
150
+ includeAuthenticator: true,
152
151
  });
153
152
  }
154
153
  } finally {
155
- localStorage.removeItem(NOCOBASE_TOKEN_KEY);
154
+ nocobaseClient.setToken(null);
155
+ nocobaseClient.setRole(null);
156
156
  clearCurrentUserCache();
157
+ clearAcl();
157
158
  }
158
159
 
159
160
  return { success: true, redirectTo: "/login" };
@@ -164,18 +165,27 @@ export const authProvider: AuthProvider = {
164
165
  await getCurrentUser();
165
166
  return { authenticated: true };
166
167
  } catch {
167
- localStorage.removeItem(NOCOBASE_TOKEN_KEY);
168
+ nocobaseClient.setToken(null);
169
+ nocobaseClient.setRole(null);
168
170
  clearCurrentUserCache();
171
+ clearAcl();
169
172
  return { authenticated: false, redirectTo: "/login" };
170
173
  }
171
174
  },
172
175
 
173
- getPermissions: async () => null,
176
+ getPermissions: async () => {
177
+ try {
178
+ return await loadAcl();
179
+ } catch {
180
+ return null;
181
+ }
182
+ },
174
183
 
175
184
  getIdentity: async () => {
176
185
  try {
177
186
  const user = await getCurrentUser();
178
- const fullName = user.nickname ?? user.username ?? user.email ?? "NocoBase user";
187
+ const fullName =
188
+ user.nickname ?? user.username ?? user.email ?? "NocoBase user";
179
189
  return {
180
190
  id: user.id,
181
191
  firstName: fullName,
@@ -183,6 +193,7 @@ export const authProvider: AuthProvider = {
183
193
  fullName,
184
194
  email: user.email ?? "",
185
195
  avatar: user.avatar,
196
+ roles: user.roles ?? [],
186
197
  };
187
198
  } catch {
188
199
  return null;
@@ -190,12 +201,15 @@ export const authProvider: AuthProvider = {
190
201
  },
191
202
 
192
203
  onError: async (error) => {
193
- const status = (error as { status?: number; statusCode?: number }).status ??
204
+ const status =
205
+ (error as { status?: number; statusCode?: number }).status ??
194
206
  (error as { status?: number; statusCode?: number }).statusCode;
195
207
 
196
- if (status === 401 || status === 403) {
197
- localStorage.removeItem(NOCOBASE_TOKEN_KEY);
208
+ if (status === 401) {
209
+ nocobaseClient.setToken(null);
210
+ nocobaseClient.setRole(null);
198
211
  clearCurrentUserCache();
212
+ clearAcl();
199
213
  return { logout: true, redirectTo: "/login" };
200
214
  }
201
215
 
@@ -32,44 +32,10 @@ const toProxyRelativeUrl = (url: string, target?: string) => {
32
32
  return url;
33
33
  };
34
34
 
35
- const getClientLocale = () =>
36
- typeof navigator !== "undefined" ? navigator.language : undefined;
37
-
38
- const getClientTimezone = () => {
39
- const offsetMinutes = -new Date().getTimezoneOffset();
40
- const sign = offsetMinutes >= 0 ? "+" : "-";
41
- const absoluteMinutes = Math.abs(offsetMinutes);
42
- const hours = String(Math.floor(absoluteMinutes / 60)).padStart(2, "0");
43
- const minutes = String(absoluteMinutes % 60).padStart(2, "0");
44
-
45
- return `${sign}${hours}:${minutes}`;
46
- };
47
-
48
35
  export const API_URL = toProxyRelativeUrl(rawApiUrl, proxyTarget);
49
- export const AUTH_API_URL = API_URL;
50
- export const TOKEN_KEY = "refine-auth";
36
+ export const API_ORIGIN = getDefaultProxyTarget(rawApiUrl);
51
37
  export const NOCOBASE_TOKEN_KEY = "nocobase-auth-token";
38
+ export const NOCOBASE_ROLE_KEY = "nocobase-auth-role";
39
+ export const NOCOBASE_LOCALE_KEY = "nocobase-locale";
52
40
  export const NOCOBASE_AUTHENTICATOR =
53
41
  import.meta.env.NOCOBASE_AUTHENTICATOR ?? "basic";
54
-
55
- export const getNocoBaseHeaders = ({
56
- token,
57
- includeAuthenticator = false,
58
- includeContentType = false,
59
- }: {
60
- token?: string;
61
- includeAuthenticator?: boolean;
62
- includeContentType?: boolean;
63
- } = {}) => {
64
- const locale = getClientLocale();
65
- const timezone = getClientTimezone();
66
-
67
- return {
68
- Accept: "application/json",
69
- ...(includeContentType ? { "Content-Type": "application/json" } : {}),
70
- ...(includeAuthenticator ? { "X-Authenticator": NOCOBASE_AUTHENTICATOR } : {}),
71
- ...(locale ? { "X-Locale": locale } : {}),
72
- ...(timezone ? { "X-Timezone": timezone } : {}),
73
- ...(token ? { Authorization: `Bearer ${token}` } : {}),
74
- };
75
- };