@choiceform/shared-auth 0.1.2 → 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/dist/components/auth-sync.d.ts +4 -3
- package/dist/components/auth-sync.d.ts.map +1 -1
- package/dist/components/auth-sync.js +69 -25
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +1 -1
- package/dist/lib/auth-client.d.ts +8 -0
- package/dist/lib/auth-client.d.ts.map +1 -1
- package/dist/lib/auth-client.js +29 -1
- package/dist/store/actions.d.ts +9 -1
- package/dist/store/actions.d.ts.map +1 -1
- package/dist/store/actions.js +31 -11
- package/dist/types.d.ts +50 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +9 -7
- package/LICENSE.md +0 -149
|
@@ -3,13 +3,14 @@ import type { AuthInstance } from "../core";
|
|
|
3
3
|
* Better Auth 认证状态同步组件
|
|
4
4
|
*
|
|
5
5
|
* 功能说明:
|
|
6
|
-
* - 使用 better-auth 的 useSession hook
|
|
7
|
-
* - 监听 authStore
|
|
6
|
+
* - 使用 better-auth 的 useSession hook 同步认证状态到 Legend State
|
|
7
|
+
* - 监听 authStore 状态,在用户登录成功后自动设置组织/团队上下文
|
|
8
8
|
* - 确保登录流程的完整性和权限上下文的正确性
|
|
9
9
|
*
|
|
10
10
|
* 技术实现:
|
|
11
11
|
* - 使用 Legend State 的 use$ hook 响应式监听状态变化
|
|
12
|
-
* - 使用 useRef
|
|
12
|
+
* - 使用 useRef 确保组织/团队设置只执行一次
|
|
13
|
+
* - 使用 useCallback 缓存映射函数,避免不必要的重渲染
|
|
13
14
|
* - 分离 session 同步和团队设置的逻辑,保持代码清晰
|
|
14
15
|
*
|
|
15
16
|
* 边缘情况处理:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-sync.d.ts","sourceRoot":"","sources":["../../src/components/auth-sync.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"auth-sync.d.ts","sourceRoot":"","sources":["../../src/components/auth-sync.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAuS3C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,QA0FxD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useRef } from "react";
|
|
1
|
+
import { useEffect, useRef, useCallback } from "react";
|
|
2
2
|
import { use$ } from "@legendapp/state/react";
|
|
3
3
|
/**
|
|
4
4
|
* 将日期转换为 ISO 字符串
|
|
@@ -11,7 +11,7 @@ function toISOString(date) {
|
|
|
11
11
|
/**
|
|
12
12
|
* 将 Better Auth session 用户数据映射为 SessionUser
|
|
13
13
|
*/
|
|
14
|
-
function mapSessionUserToSessionUser(sessionUser,
|
|
14
|
+
function mapSessionUserToSessionUser(sessionUser, sessionData) {
|
|
15
15
|
return {
|
|
16
16
|
banExpires: sessionUser.banExpires,
|
|
17
17
|
banReason: sessionUser.banReason,
|
|
@@ -21,10 +21,12 @@ function mapSessionUserToSessionUser(sessionUser, sessionCreatedAt) {
|
|
|
21
21
|
emailVerified: sessionUser.emailVerified,
|
|
22
22
|
id: sessionUser.id,
|
|
23
23
|
image: sessionUser.image || undefined,
|
|
24
|
-
lastLoginAt: toISOString(
|
|
24
|
+
lastLoginAt: toISOString(sessionData?.createdAt),
|
|
25
25
|
name: sessionUser.name,
|
|
26
26
|
role: sessionUser.role,
|
|
27
27
|
updatedAt: toISOString(sessionUser.updatedAt) ?? "",
|
|
28
|
+
activeOrganizationId: sessionData?.activeOrganizationId,
|
|
29
|
+
activeTeamId: sessionData?.activeTeamId,
|
|
28
30
|
};
|
|
29
31
|
}
|
|
30
32
|
/**
|
|
@@ -86,7 +88,7 @@ async function parseErrorResponse(response) {
|
|
|
86
88
|
* - API 返回错误:记录详细错误信息
|
|
87
89
|
* - 无效响应数据:记录错误但不影响登录
|
|
88
90
|
*/
|
|
89
|
-
async function setupCompanionTeam(
|
|
91
|
+
async function setupCompanionTeam(auth, token, refetchSession) {
|
|
90
92
|
try {
|
|
91
93
|
// 1. 验证环境变量配置
|
|
92
94
|
const oneAuthBaseUrl = getEnvVar("VITE_AUTH_API_URL") || getEnvVar("VITE_CORE_AI_API_URL");
|
|
@@ -188,6 +190,42 @@ async function setupCompanionTeam(_auth, token) {
|
|
|
188
190
|
if (isDev) {
|
|
189
191
|
console.log("[AuthSync] Successfully set active team");
|
|
190
192
|
}
|
|
193
|
+
// 刷新 session 并更新 authStore
|
|
194
|
+
if (refetchSession) {
|
|
195
|
+
refetchSession();
|
|
196
|
+
}
|
|
197
|
+
// 使用 fetch 直接调用 get-session 获取最新数据
|
|
198
|
+
try {
|
|
199
|
+
const getSessionUrl = `${authBaseURL}/v1/auth/get-session`;
|
|
200
|
+
const sessionResponse = await fetch(getSessionUrl, {
|
|
201
|
+
headers: {
|
|
202
|
+
Authorization: `Bearer ${encodedToken}`,
|
|
203
|
+
"Content-Type": "application/json",
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
if (sessionResponse.ok) {
|
|
207
|
+
const sessionData = await sessionResponse.json();
|
|
208
|
+
const data = sessionData;
|
|
209
|
+
if (data.user && data.session) {
|
|
210
|
+
const currentUser = auth.authStore.user.get();
|
|
211
|
+
if (currentUser) {
|
|
212
|
+
auth.authStore.user.set({
|
|
213
|
+
...currentUser,
|
|
214
|
+
activeOrganizationId: data.session.activeOrganizationId,
|
|
215
|
+
activeTeamId: data.session.activeTeamId,
|
|
216
|
+
});
|
|
217
|
+
if (isDev) {
|
|
218
|
+
console.log("[AuthSync] Updated authStore with activeOrganizationId and activeTeamId");
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
if (isDev) {
|
|
226
|
+
console.error("[AuthSync] Failed to refresh session:", err);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
191
229
|
}
|
|
192
230
|
else if (isDev) {
|
|
193
231
|
console.warn("[AuthSync] First team has invalid ID, skipping team setup");
|
|
@@ -214,13 +252,14 @@ async function setupCompanionTeam(_auth, token) {
|
|
|
214
252
|
* Better Auth 认证状态同步组件
|
|
215
253
|
*
|
|
216
254
|
* 功能说明:
|
|
217
|
-
* - 使用 better-auth 的 useSession hook
|
|
218
|
-
* - 监听 authStore
|
|
255
|
+
* - 使用 better-auth 的 useSession hook 同步认证状态到 Legend State
|
|
256
|
+
* - 监听 authStore 状态,在用户登录成功后自动设置组织/团队上下文
|
|
219
257
|
* - 确保登录流程的完整性和权限上下文的正确性
|
|
220
258
|
*
|
|
221
259
|
* 技术实现:
|
|
222
260
|
* - 使用 Legend State 的 use$ hook 响应式监听状态变化
|
|
223
|
-
* - 使用 useRef
|
|
261
|
+
* - 使用 useRef 确保组织/团队设置只执行一次
|
|
262
|
+
* - 使用 useCallback 缓存映射函数,避免不必要的重渲染
|
|
224
263
|
* - 分离 session 同步和团队设置的逻辑,保持代码清晰
|
|
225
264
|
*
|
|
226
265
|
* 边缘情况处理:
|
|
@@ -237,13 +276,27 @@ export function AuthSync({ auth }) {
|
|
|
237
276
|
const isLoaded = use$(authStore.isLoaded);
|
|
238
277
|
// 监听 better-auth 的 session(用于同步到 store)
|
|
239
278
|
const sessionResult = authClient.useSession();
|
|
240
|
-
const { data: session, isPending, error } = sessionResult || {
|
|
279
|
+
const { data: session, isPending, error, refetch } = sessionResult || {
|
|
241
280
|
data: null,
|
|
242
281
|
isPending: false,
|
|
243
|
-
error: null
|
|
282
|
+
error: null,
|
|
283
|
+
refetch: undefined,
|
|
244
284
|
};
|
|
245
|
-
// 使用 ref
|
|
285
|
+
// 使用 ref 确保组织/团队设置只执行一次
|
|
246
286
|
const teamSetupRef = useRef(false);
|
|
287
|
+
// 使用 useCallback 缓存 session 映射逻辑,避免不必要的重计算
|
|
288
|
+
const handleSessionUpdate = useCallback((sessionData) => {
|
|
289
|
+
if (sessionData?.user) {
|
|
290
|
+
try {
|
|
291
|
+
const mappedUser = mapSessionUserToSessionUser(sessionData.user, sessionData.session);
|
|
292
|
+
authActions.initialize(mappedUser, true);
|
|
293
|
+
}
|
|
294
|
+
catch (mappingError) {
|
|
295
|
+
console.error("[AuthSync] Failed to map session user:", mappingError);
|
|
296
|
+
// 映射失败时不清空用户信息,可能已有有效的用户数据
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}, [authActions]);
|
|
247
300
|
// Effect 1: 同步 better-auth session 到 store
|
|
248
301
|
useEffect(() => {
|
|
249
302
|
// 加载中状态
|
|
@@ -254,27 +307,18 @@ export function AuthSync({ auth }) {
|
|
|
254
307
|
authActions.setLoading(false);
|
|
255
308
|
// 错误处理
|
|
256
309
|
if (error) {
|
|
257
|
-
const errorMessage = error instanceof Error
|
|
258
|
-
? error.message
|
|
259
|
-
: (typeof error === "string" ? error : "Authentication error");
|
|
310
|
+
const errorMessage = error instanceof Error ? error.message : typeof error === "string" ? error : "Authentication error";
|
|
260
311
|
authActions.setError(errorMessage);
|
|
261
312
|
authActions.initialize(null, true);
|
|
262
313
|
teamSetupRef.current = false;
|
|
263
314
|
return;
|
|
264
315
|
}
|
|
265
316
|
// Session 存在:映射用户数据并更新 store
|
|
266
|
-
if (session
|
|
267
|
-
|
|
268
|
-
const mappedUser = mapSessionUserToSessionUser(session.user, session.session?.createdAt);
|
|
269
|
-
authActions.initialize(mappedUser, true);
|
|
270
|
-
}
|
|
271
|
-
catch (mappingError) {
|
|
272
|
-
console.error("[AuthSync] Failed to map session user:", mappingError);
|
|
273
|
-
// 映射失败时不清空用户信息,可能已有有效的用户数据
|
|
274
|
-
}
|
|
317
|
+
if (session) {
|
|
318
|
+
handleSessionUpdate(session);
|
|
275
319
|
}
|
|
276
320
|
// 注意:没有 session 时不主动清空用户信息,因为可能已经从 token 加载了
|
|
277
|
-
}, [session, isPending, error, authActions]);
|
|
321
|
+
}, [session, isPending, error, authActions, handleSessionUpdate]);
|
|
278
322
|
// Effect 2: 监听 authStore 状态,设置伴生团队
|
|
279
323
|
useEffect(() => {
|
|
280
324
|
// 条件检查:只有在用户已认证且已加载完成时才设置伴生团队
|
|
@@ -283,7 +327,7 @@ export function AuthSync({ auth }) {
|
|
|
283
327
|
const token = tokenStorage.get();
|
|
284
328
|
// 验证 token 存在
|
|
285
329
|
if (token && typeof token === "string" && token.trim().length > 0) {
|
|
286
|
-
setupCompanionTeam(auth, token).catch((error) => {
|
|
330
|
+
setupCompanionTeam(auth, token, refetch).catch((error) => {
|
|
287
331
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
288
332
|
console.error("[AuthSync] Failed to setup companion team:", errorMessage);
|
|
289
333
|
// 失败后重置 ref,允许在特定条件下重试(如 token 更新后)
|
|
@@ -298,7 +342,7 @@ export function AuthSync({ auth }) {
|
|
|
298
342
|
if (isLoaded && !isAuthenticated) {
|
|
299
343
|
teamSetupRef.current = false;
|
|
300
344
|
}
|
|
301
|
-
}, [user, isAuthenticated, isLoaded, auth, tokenStorage]);
|
|
345
|
+
}, [user, isAuthenticated, isLoaded, auth, tokenStorage, refetch]);
|
|
302
346
|
// 这是一个隐形组件,不渲染任何内容
|
|
303
347
|
return null;
|
|
304
348
|
}
|
package/dist/core.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAE1C;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
|
package/dist/core.js
CHANGED
|
@@ -7,7 +7,7 @@ import { createBoundAuthUtils } from "./store/utils";
|
|
|
7
7
|
* 创建认证系统实例
|
|
8
8
|
*/
|
|
9
9
|
export function createAuth(config) {
|
|
10
|
-
// 创建 auth client
|
|
10
|
+
// 创建 auth client (传递 tokenStorageKey 以支持 bearer token 认证)
|
|
11
11
|
const authClient = createAuthClientFromConfig(config);
|
|
12
12
|
// 创建 store
|
|
13
13
|
const { authStore, tokenStorage } = createAuthStore({
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import type { AuthConfig } from "../config";
|
|
2
2
|
/**
|
|
3
3
|
* 创建 Better Auth 客户端
|
|
4
|
+
*
|
|
5
|
+
* 配置说明:
|
|
6
|
+
* - 使用 Bearer Token 认证模式
|
|
7
|
+
* - Token 从 localStorage 中动态读取
|
|
8
|
+
* - 支持服务器端 Bearer Plugin 的 session 管理
|
|
9
|
+
*
|
|
10
|
+
* @param config - 认证配置对象
|
|
11
|
+
* @returns Better Auth 客户端实例
|
|
4
12
|
*/
|
|
5
13
|
export declare function createAuthClientFromConfig(config: AuthConfig): {
|
|
6
14
|
signIn: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-client.d.ts","sourceRoot":"","sources":["../../src/lib/auth-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAE3C
|
|
1
|
+
{"version":3,"file":"auth-client.d.ts","sourceRoot":"","sources":["../../src/lib/auth-client.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/auth-client.js
CHANGED
|
@@ -1,11 +1,39 @@
|
|
|
1
1
|
import { createAuthClient } from "better-auth/react";
|
|
2
2
|
/**
|
|
3
3
|
* 创建 Better Auth 客户端
|
|
4
|
+
*
|
|
5
|
+
* 配置说明:
|
|
6
|
+
* - 使用 Bearer Token 认证模式
|
|
7
|
+
* - Token 从 localStorage 中动态读取
|
|
8
|
+
* - 支持服务器端 Bearer Plugin 的 session 管理
|
|
9
|
+
*
|
|
10
|
+
* @param config - 认证配置对象
|
|
11
|
+
* @returns Better Auth 客户端实例
|
|
4
12
|
*/
|
|
5
13
|
export function createAuthClientFromConfig(config) {
|
|
6
|
-
const { baseURL, plugins = [] } = config;
|
|
14
|
+
const { baseURL, plugins = [], tokenStorageKey = "auth-token" } = config;
|
|
7
15
|
return createAuthClient({
|
|
8
16
|
baseURL: `${baseURL}/v1/auth`,
|
|
9
17
|
plugins,
|
|
18
|
+
fetchOptions: {
|
|
19
|
+
auth: {
|
|
20
|
+
type: "Bearer",
|
|
21
|
+
token: () => {
|
|
22
|
+
// 从 localStorage 获取存储的 bearer token
|
|
23
|
+
// SSR 环境下 localStorage 不存在,返回空字符串
|
|
24
|
+
if (typeof window === "undefined" || typeof localStorage === "undefined") {
|
|
25
|
+
return "";
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
const token = localStorage.getItem(tokenStorageKey);
|
|
29
|
+
return token || "";
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// localStorage 访问失败(如隐私模式),返回空字符串
|
|
33
|
+
return "";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
10
38
|
});
|
|
11
39
|
}
|
package/dist/store/actions.d.ts
CHANGED
|
@@ -19,7 +19,15 @@ export declare function createAuthActions(authStore: Observable<AuthState>, toke
|
|
|
19
19
|
*/
|
|
20
20
|
initialize(user: SessionUser | null, isLoaded: boolean): Promise<void>;
|
|
21
21
|
/**
|
|
22
|
-
* 使用
|
|
22
|
+
* 使用 Bearer Token 获取 session
|
|
23
|
+
*
|
|
24
|
+
* 流程:
|
|
25
|
+
* 1. 保存 token 到 localStorage
|
|
26
|
+
* 2. 使用 Bearer Token 请求 session endpoint
|
|
27
|
+
* 3. 解析响应数据并提取用户信息
|
|
28
|
+
* 4. 更新 authStore 状态
|
|
29
|
+
*
|
|
30
|
+
* @param token - Bearer Token
|
|
23
31
|
*/
|
|
24
32
|
fetchSessionWithToken(token: string): Promise<void>;
|
|
25
33
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/store/actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/store/actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAgE3C;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,EAChC,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE;IACV,MAAM,EAAE;QACN,MAAM,EAAE,CAAC,OAAO,EAAE;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;KACjF,CAAA;IACD,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;CAChC;IAeC;;OAEG;qBACoB,WAAW,GAAG,IAAI,YAAY,OAAO;IAe5D;;;;;;;;;;OAUG;iCACgC,MAAM;IAuDzC;;;OAGG;;IAOH;;OAEG;wBACiB,OAAO;IAI3B;;OAEG;oBACa,MAAM,GAAG,IAAI;IAI7B;;;;;;OAMG;sBACoB,MAAM,eAA0B,MAAM;IAmC7D;;OAEG;;IAgCH;;OAEG;qBACc,WAAW,GAAG,IAAI;IAUnC;;OAEG;eACQ,WAAW,GAAG,IAAI;EAIhC;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAA"}
|
package/dist/store/actions.js
CHANGED
|
@@ -8,14 +8,21 @@ function toISOString(date) {
|
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* 从服务器响应中提取用户数据
|
|
11
|
-
*
|
|
11
|
+
*
|
|
12
|
+
* 支持多种数据结构格式以提供更好的兼容性:
|
|
13
|
+
* - 标准格式: { user: {...}, session: {...} }
|
|
14
|
+
* - 嵌套格式: { session: { user: {...} } }
|
|
15
|
+
* - 包装格式: { data: { user: {...} } }
|
|
16
|
+
* - 扁平格式: { id, email, ... }
|
|
17
|
+
*
|
|
18
|
+
* @param sessionData - 服务器返回的 session 数据
|
|
19
|
+
* @returns 映射后的 SessionUser 对象,失败返回 null
|
|
12
20
|
*/
|
|
13
21
|
function extractUserData(sessionData) {
|
|
14
22
|
if (!sessionData || typeof sessionData !== "object")
|
|
15
23
|
return null;
|
|
16
24
|
const data = sessionData;
|
|
17
25
|
// 尝试从不同的数据结构中提取用户信息
|
|
18
|
-
// 优先使用标准格式:{session: {...}, user: {...}}
|
|
19
26
|
const rawUserData = data.user || // 标准格式
|
|
20
27
|
data.session?.user || // 嵌套格式
|
|
21
28
|
data.data?.user || // 包装格式
|
|
@@ -23,10 +30,13 @@ function extractUserData(sessionData) {
|
|
|
23
30
|
if (!rawUserData || typeof rawUserData !== "object")
|
|
24
31
|
return null;
|
|
25
32
|
const user = rawUserData;
|
|
26
|
-
// 提取 session
|
|
27
|
-
const
|
|
28
|
-
|
|
33
|
+
// 提取 session 相关数据(activeOrganizationId 和 activeTeamId 存储在 session 中)
|
|
34
|
+
const sessionInfo = data.session;
|
|
35
|
+
const sessionCreatedAt = sessionInfo?.createdAt
|
|
36
|
+
? toISOString(sessionInfo.createdAt)
|
|
29
37
|
: undefined;
|
|
38
|
+
const activeOrganizationId = sessionInfo?.activeOrganizationId;
|
|
39
|
+
const activeTeamId = sessionInfo?.activeTeamId;
|
|
30
40
|
return {
|
|
31
41
|
banExpires: user.banExpires,
|
|
32
42
|
banReason: user.banReason,
|
|
@@ -40,6 +50,8 @@ function extractUserData(sessionData) {
|
|
|
40
50
|
name: user.name,
|
|
41
51
|
role: user.role,
|
|
42
52
|
updatedAt: toISOString(user.updatedAt) ?? "",
|
|
53
|
+
activeOrganizationId,
|
|
54
|
+
activeTeamId,
|
|
43
55
|
};
|
|
44
56
|
}
|
|
45
57
|
/**
|
|
@@ -71,14 +83,22 @@ export function createAuthActions(authStore, tokenStorage, config, authClient) {
|
|
|
71
83
|
authStore.loading.set(!isLoaded);
|
|
72
84
|
},
|
|
73
85
|
/**
|
|
74
|
-
* 使用
|
|
86
|
+
* 使用 Bearer Token 获取 session
|
|
87
|
+
*
|
|
88
|
+
* 流程:
|
|
89
|
+
* 1. 保存 token 到 localStorage
|
|
90
|
+
* 2. 使用 Bearer Token 请求 session endpoint
|
|
91
|
+
* 3. 解析响应数据并提取用户信息
|
|
92
|
+
* 4. 更新 authStore 状态
|
|
93
|
+
*
|
|
94
|
+
* @param token - Bearer Token
|
|
75
95
|
*/
|
|
76
96
|
async fetchSessionWithToken(token) {
|
|
77
97
|
try {
|
|
78
98
|
if (!token) {
|
|
79
99
|
throw new Error("Token is required");
|
|
80
100
|
}
|
|
81
|
-
// 保存 token 到 localStorage
|
|
101
|
+
// 保存 token 到 localStorage(供 authClient 使用)
|
|
82
102
|
tokenStorage.save(token);
|
|
83
103
|
const endpoint = `${baseURL}${getSessionEndpoint}`;
|
|
84
104
|
const response = await fetch(endpoint, {
|
|
@@ -88,10 +108,10 @@ export function createAuthActions(authStore, tokenStorage, config, authClient) {
|
|
|
88
108
|
"Content-Type": "application/json",
|
|
89
109
|
},
|
|
90
110
|
});
|
|
91
|
-
const responseText = await response.text();
|
|
92
111
|
if (!response.ok) {
|
|
93
112
|
throw new Error(`Failed to fetch session: ${response.status}`);
|
|
94
113
|
}
|
|
114
|
+
const responseText = await response.text();
|
|
95
115
|
// 解析响应数据
|
|
96
116
|
let sessionData = null;
|
|
97
117
|
try {
|
|
@@ -100,7 +120,7 @@ export function createAuthActions(authStore, tokenStorage, config, authClient) {
|
|
|
100
120
|
}
|
|
101
121
|
}
|
|
102
122
|
catch (error) {
|
|
103
|
-
console.error("Failed to parse session response:", error);
|
|
123
|
+
console.error("[fetchSessionWithToken] Failed to parse session response:", error);
|
|
104
124
|
this.handleUnauthorized();
|
|
105
125
|
return;
|
|
106
126
|
}
|
|
@@ -113,12 +133,12 @@ export function createAuthActions(authStore, tokenStorage, config, authClient) {
|
|
|
113
133
|
authStore.loading.set(false);
|
|
114
134
|
}
|
|
115
135
|
else {
|
|
116
|
-
console.error("Invalid session data received");
|
|
136
|
+
console.error("[fetchSessionWithToken] Invalid session data received");
|
|
117
137
|
this.handleUnauthorized();
|
|
118
138
|
}
|
|
119
139
|
}
|
|
120
140
|
catch (error) {
|
|
121
|
-
console.error("Failed to fetch session:", error);
|
|
141
|
+
console.error("[fetchSessionWithToken] Failed to fetch session:", error);
|
|
122
142
|
this.handleUnauthorized();
|
|
123
143
|
}
|
|
124
144
|
},
|
package/dist/types.d.ts
CHANGED
|
@@ -1,37 +1,87 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 认证相关的类型定义
|
|
3
3
|
*/
|
|
4
|
+
/**
|
|
5
|
+
* 会话用户信息
|
|
6
|
+
*
|
|
7
|
+
* 包含用户基本信息和当前活动的组织/团队上下文
|
|
8
|
+
*/
|
|
4
9
|
export type SessionUser = {
|
|
10
|
+
/** 当前活动的组织 ID */
|
|
11
|
+
activeOrganizationId?: string;
|
|
12
|
+
/** 当前活动的团队 ID */
|
|
13
|
+
activeTeamId?: string;
|
|
14
|
+
/** 禁用到期时间 */
|
|
5
15
|
banExpires?: string;
|
|
16
|
+
/** 禁用原因 */
|
|
6
17
|
banReason?: string;
|
|
18
|
+
/** 是否被禁用 */
|
|
7
19
|
banned?: boolean;
|
|
20
|
+
/** 用户创建时间 */
|
|
8
21
|
createdAt: string;
|
|
22
|
+
/** 用户邮箱 */
|
|
9
23
|
email: string;
|
|
24
|
+
/** 邮箱是否已验证 */
|
|
10
25
|
emailVerified: boolean;
|
|
26
|
+
/** 用户 ID */
|
|
11
27
|
id: string;
|
|
28
|
+
/** 用户头像 URL */
|
|
12
29
|
image?: string;
|
|
30
|
+
/** 最后登录时间 */
|
|
13
31
|
lastLoginAt?: string;
|
|
32
|
+
/** 用户名称 */
|
|
14
33
|
name: string;
|
|
34
|
+
/** 用户角色 */
|
|
15
35
|
role?: string;
|
|
36
|
+
/** 用户信息更新时间 */
|
|
16
37
|
updatedAt: string;
|
|
17
38
|
};
|
|
39
|
+
/**
|
|
40
|
+
* Better Auth Session 对象
|
|
41
|
+
*
|
|
42
|
+
* 包含会话信息和关联的用户数据
|
|
43
|
+
*/
|
|
18
44
|
export type Session = {
|
|
45
|
+
/** 当前活动的组织 ID(存储在 session 中) */
|
|
46
|
+
activeOrganizationId?: string;
|
|
47
|
+
/** 当前活动的团队 ID(存储在 session 中) */
|
|
48
|
+
activeTeamId?: string;
|
|
49
|
+
/** 会话创建时间 */
|
|
19
50
|
createdAt: string;
|
|
51
|
+
/** 会话过期时间 */
|
|
20
52
|
expiresAt: string;
|
|
53
|
+
/** 会话 ID */
|
|
21
54
|
id: string;
|
|
55
|
+
/** 客户端 IP 地址 */
|
|
22
56
|
ipAddress?: string;
|
|
57
|
+
/** 会话 Token */
|
|
23
58
|
token: string;
|
|
59
|
+
/** 会话更新时间 */
|
|
24
60
|
updatedAt: string;
|
|
61
|
+
/** 关联的用户信息 */
|
|
25
62
|
user: SessionUser;
|
|
63
|
+
/** 客户端 User-Agent */
|
|
26
64
|
userAgent?: string;
|
|
65
|
+
/** 用户 ID */
|
|
27
66
|
userId: string;
|
|
28
67
|
};
|
|
68
|
+
/**
|
|
69
|
+
* 认证状态
|
|
70
|
+
*
|
|
71
|
+
* 存储在 Legend State 中的认证状态数据
|
|
72
|
+
*/
|
|
29
73
|
export interface AuthState {
|
|
74
|
+
/** 错误信息 */
|
|
30
75
|
error: string | null;
|
|
76
|
+
/** 是否已认证 */
|
|
31
77
|
isAuthenticated: boolean;
|
|
78
|
+
/** 是否已加载完成 */
|
|
32
79
|
isLoaded: boolean;
|
|
80
|
+
/** 是否正在加载 */
|
|
33
81
|
loading: boolean;
|
|
82
|
+
/** 认证 Token */
|
|
34
83
|
token: string | null;
|
|
84
|
+
/** 当前用户信息 */
|
|
35
85
|
user: SessionUser | null;
|
|
36
86
|
}
|
|
37
87
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,CAAC,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,iBAAiB;IACjB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,iBAAiB;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY;IACZ,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW;IACX,KAAK,EAAE,MAAM,CAAC;IACd,cAAc;IACd,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,eAAe;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe;IACf,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG;IACpB,gCAAgC;IAChC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gCAAgC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,gBAAgB;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe;IACf,KAAK,EAAE,MAAM,CAAC;IACd,aAAa;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc;IACd,IAAI,EAAE,WAAW,CAAC;IAClB,qBAAqB;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY;IACZ,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,WAAW;IACX,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,YAAY;IACZ,eAAe,EAAE,OAAO,CAAA;IACxB,cAAc;IACd,QAAQ,EAAE,OAAO,CAAA;IACjB,aAAa;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,eAAe;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,aAAa;IACb,IAAI,EAAE,WAAW,GAAG,IAAI,CAAA;CACzB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@choiceform/shared-auth",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Shared authentication package for Choiceform projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -16,6 +16,12 @@
|
|
|
16
16
|
"dist",
|
|
17
17
|
"README.md"
|
|
18
18
|
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"dev": "tsc --watch",
|
|
22
|
+
"clean": "rimraf dist",
|
|
23
|
+
"prepublishOnly": "pnpm run build"
|
|
24
|
+
},
|
|
19
25
|
"repository": {
|
|
20
26
|
"type": "git",
|
|
21
27
|
"url": "git+https://github.com/choiceform/automation.git",
|
|
@@ -51,10 +57,6 @@
|
|
|
51
57
|
"@types/react-dom": "18.2.22",
|
|
52
58
|
"typescript": "^5.5.3",
|
|
53
59
|
"rimraf": "^6.0.1"
|
|
54
|
-
},
|
|
55
|
-
"scripts": {
|
|
56
|
-
"build": "tsc",
|
|
57
|
-
"dev": "tsc --watch",
|
|
58
|
-
"clean": "rimraf dist"
|
|
59
60
|
}
|
|
60
|
-
}
|
|
61
|
+
}
|
|
62
|
+
|
package/LICENSE.md
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
# License
|
|
2
|
-
|
|
3
|
-
Portions of this software are licensed as follows:
|
|
4
|
-
|
|
5
|
-
- Content of branches other than the main branch are not licensed.
|
|
6
|
-
- Source code files that contain `.ee.` in their filename or `.ee` in their directory name are NOT licensed under the Sustainable Use License. To use source code files that contain `.ee.` in their filename or `.ee` in their directory name you must hold a valid Rungraf Enterprise License specifically allowing you access to such source code files and as defined in "LICENSE_EE.md".
|
|
7
|
-
- All third party components incorporated into the Rungraf software are licensed under the original license provided by the owner of the applicable component.
|
|
8
|
-
- Content outside of the above mentioned files or restrictions is available under the "Sustainable Use License" as defined below.
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## Sustainable Use License
|
|
13
|
-
|
|
14
|
-
**Version 1.0**
|
|
15
|
-
|
|
16
|
-
### Acceptance
|
|
17
|
-
|
|
18
|
-
By using the software, you agree to all of the terms and conditions below.
|
|
19
|
-
|
|
20
|
-
### Copyright License
|
|
21
|
-
|
|
22
|
-
The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject to the limitations below.
|
|
23
|
-
|
|
24
|
-
### Limitations
|
|
25
|
-
|
|
26
|
-
You may use or modify the software only for your own internal business purposes or for non-commercial or personal use. You may distribute the software or provide it to others only if you do so free of charge for non-commercial purposes. You may not alter, remove, or obscure any licensing, copyright, or other notices of the licensor in the software. Any use of the licensor's trademarks is subject to applicable law.
|
|
27
|
-
|
|
28
|
-
### Patents
|
|
29
|
-
|
|
30
|
-
The licensor grants you a license, under any patent claims the licensor can license, or becomes able to license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case subject to the limitations and conditions in this license. This license does not cover any patent claims that you cause to be infringed by modifications or additions to the software. If you or your company make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
|
|
31
|
-
|
|
32
|
-
### Notices
|
|
33
|
-
|
|
34
|
-
You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms. If you modify the software, you must include in any modified copies of the software a prominent notice stating that you have modified the software.
|
|
35
|
-
|
|
36
|
-
### No Other Rights
|
|
37
|
-
|
|
38
|
-
These terms do not imply any licenses other than those expressly granted in these terms.
|
|
39
|
-
|
|
40
|
-
### Termination
|
|
41
|
-
|
|
42
|
-
If you use the software in violation of these terms, such use is not licensed, and your license will automatically terminate. If the licensor provides you with a notice of your violation, and you cease all violation of this license no later than 30 days after you receive that notice, your license will be reinstated retroactively. However, if you violate these terms after such reinstatement, any additional violation of these terms will cause your license to terminate automatically and permanently.
|
|
43
|
-
|
|
44
|
-
### No Liability
|
|
45
|
-
|
|
46
|
-
As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.
|
|
47
|
-
|
|
48
|
-
### Definitions
|
|
49
|
-
|
|
50
|
-
- The **"licensor"** is the entity offering these terms, which is the Rungraf project and its contributors.
|
|
51
|
-
|
|
52
|
-
- The **"software"** is the software the licensor makes available under these terms, including any portion of it.
|
|
53
|
-
|
|
54
|
-
- **"You"** refers to the individual or entity agreeing to these terms.
|
|
55
|
-
|
|
56
|
-
- **"Your company"** is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. Control means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
|
|
57
|
-
|
|
58
|
-
- **"Your license"** is the license granted to you for the software under these terms.
|
|
59
|
-
|
|
60
|
-
- **"Use"** means anything you do with the software requiring your license.
|
|
61
|
-
|
|
62
|
-
- **"Trademark"** means trademarks, service marks, and similar rights.
|
|
63
|
-
|
|
64
|
-
---
|
|
65
|
-
|
|
66
|
-
## Additional Terms for Rungraf
|
|
67
|
-
|
|
68
|
-
In addition to the Sustainable Use License terms above, the following specific limitations apply to Rungraf:
|
|
69
|
-
|
|
70
|
-
### Multi-Tenant SaaS Restriction
|
|
71
|
-
|
|
72
|
-
You may NOT use Rungraf to operate a multi-tenant Software-as-a-Service (SaaS) offering where you provide Rungraf as a hosted service to multiple external customers or organizations, unless you obtain a separate commercial license from the Rungraf project.
|
|
73
|
-
|
|
74
|
-
**Examples of PROHIBITED use without commercial license:**
|
|
75
|
-
- Operating "AI Agent Platform as a Service" for multiple paying customers
|
|
76
|
-
- Providing Rungraf as a white-labeled workflow automation service
|
|
77
|
-
- Running a marketplace where multiple organizations build AI Agents on your hosted Rungraf instance
|
|
78
|
-
|
|
79
|
-
**Examples of PERMITTED use:**
|
|
80
|
-
- Deploying Rungraf within your organization for your employees and internal use
|
|
81
|
-
- Embedding Rungraf in your product where each customer gets their own dedicated Rungraf instance
|
|
82
|
-
- Using Rungraf as a backend service for your own application (single-tenant)
|
|
83
|
-
|
|
84
|
-
**Workspace Definition:** Within Rungraf, one workspace represents one tenant. A workspace provides an isolated environment for each tenant's AI Agents, workflows, data, and configurations.
|
|
85
|
-
|
|
86
|
-
### Branding and Attribution
|
|
87
|
-
|
|
88
|
-
When using Rungraf's frontend interface, you may not remove, alter, or obscure the Rungraf logo, branding, or copyright notices displayed in the user interface. This restriction applies only to the visual frontend components.
|
|
89
|
-
|
|
90
|
-
**Frontend Definition:** The "frontend" of Rungraf includes all components located in the `packages/client/` directory when running from source code, or the "client" Docker image when running via containers.
|
|
91
|
-
|
|
92
|
-
**Examples of PERMITTED use:**
|
|
93
|
-
- Using only Rungraf's backend APIs with your own custom frontend (no branding requirement)
|
|
94
|
-
- Forking and customizing the codebase while maintaining attribution
|
|
95
|
-
- White-labeling with a separate commercial license
|
|
96
|
-
|
|
97
|
-
**Examples of PROHIBITED use:**
|
|
98
|
-
- Using the Rungraf frontend with logos and branding removed
|
|
99
|
-
- Distributing modified versions without proper attribution
|
|
100
|
-
|
|
101
|
-
### Core Engine Protection
|
|
102
|
-
|
|
103
|
-
The Rungraf AI Agent Runtime (located in `packages/runner/`) and Expression Engine may be used and modified for your own purposes, but you may NOT:
|
|
104
|
-
|
|
105
|
-
- Extract the Agent Runtime as a standalone product and sell it separately
|
|
106
|
-
- Use Rungraf's core orchestration engine to build a competing workflow automation platform for sale
|
|
107
|
-
- Offer the Expression Engine as a standalone commercial service
|
|
108
|
-
|
|
109
|
-
**Examples of PERMITTED use:**
|
|
110
|
-
- Integrating Rungraf into your product's backend
|
|
111
|
-
- Modifying the runtime for your specific use case
|
|
112
|
-
- Contributing improvements back to the open source project
|
|
113
|
-
|
|
114
|
-
**Examples of PROHIBITED use:**
|
|
115
|
-
- Packaging the Elixir Agent Runtime as "SuperAgent Engine" and selling it
|
|
116
|
-
- Building a competitor workflow platform using Rungraf's core code
|
|
117
|
-
|
|
118
|
-
---
|
|
119
|
-
|
|
120
|
-
## Fair Code Principles
|
|
121
|
-
|
|
122
|
-
Rungraf follows the [Fair Code](https://faircode.io) principles. We believe in:
|
|
123
|
-
|
|
124
|
-
1. **Transparency**: Source code is publicly available for review and contribution
|
|
125
|
-
2. **Sustainability**: Protecting the project's ability to fund ongoing development
|
|
126
|
-
3. **Community**: Encouraging contributions while preventing exploitation
|
|
127
|
-
4. **Freedom**: Allowing use for internal business purposes and non-commercial projects
|
|
128
|
-
|
|
129
|
-
---
|
|
130
|
-
|
|
131
|
-
## Getting a Commercial License
|
|
132
|
-
|
|
133
|
-
If your use case falls under the restrictions above, you can obtain a commercial Rungraf Enterprise License. Enterprise licenses include:
|
|
134
|
-
|
|
135
|
-
- Multi-tenant SaaS deployment rights
|
|
136
|
-
- White-labeling permissions
|
|
137
|
-
- Priority support and SLA guarantees
|
|
138
|
-
- Enterprise features (SSO, advanced RBAC, audit logs)
|
|
139
|
-
- Custom development support
|
|
140
|
-
|
|
141
|
-
Contact us for enterprise licensing:
|
|
142
|
-
- **Email**: [enterprise@rungraf.io](mailto:enterprise@rungraf.io)
|
|
143
|
-
- **Website**: [https://rungraf.io/enterprise](https://rungraf.io/enterprise)
|
|
144
|
-
|
|
145
|
-
---
|
|
146
|
-
|
|
147
|
-
**© 2024-2025 Rungraf Project**
|
|
148
|
-
|
|
149
|
-
This software is provided "as is", without warranty of any kind, express or implied.
|