@longzai-intelligence-auth/elysia 0.0.4 → 0.0.5
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/index.d.ts +648 -25
- package/dist/index.js +1 -15
- package/package.json +12 -30
- package/dist/core/auth-strategy.d.ts +0 -14
- package/dist/core/auth-strategy.js +0 -98
- package/dist/core/error-mapper.d.ts +0 -2
- package/dist/core/error-mapper.js +0 -27
- package/dist/plugin.d.ts +0 -6
- package/dist/plugin.js +0 -39
- package/dist/plugins/audit.plugin.d.ts +0 -38
- package/dist/plugins/audit.plugin.js +0 -13
- package/dist/plugins/error-handler.plugin.d.ts +0 -46
- package/dist/plugins/error-handler.plugin.js +0 -45
- package/dist/plugins/jwt-verify.plugin.d.ts +0 -9
- package/dist/plugins/jwt-verify.plugin.js +0 -31
- package/dist/plugins/logger.plugin.d.ts +0 -33
- package/dist/plugins/logger.plugin.js +0 -16
- package/dist/plugins/rate-limit.plugin.d.ts +0 -40
- package/dist/plugins/rate-limit.plugin.js +0 -39
- package/dist/plugins/rbac.plugin.d.ts +0 -36
- package/dist/plugins/rbac.plugin.js +0 -42
- package/dist/plugins/tenant.plugin.d.ts +0 -38
- package/dist/plugins/tenant.plugin.js +0 -19
- package/dist/presets/basic-preset.d.ts +0 -11
- package/dist/presets/basic-preset.js +0 -11
- package/dist/presets/standard-preset.d.ts +0 -13
- package/dist/presets/standard-preset.js +0 -26
- package/dist/routes/auth.routes.d.ts +0 -17
- package/dist/routes/auth.routes.js +0 -145
- package/dist/types/auth-plugin-config.d.ts +0 -40
- package/dist/types/auth-plugin-config.js +0 -1
- package/dist/utils/extract-client-ip.d.ts +0 -1
- package/dist/utils/extract-client-ip.js +0 -5
- package/dist/utils/extract-user-agent.d.ts +0 -1
- package/dist/utils/extract-user-agent.js +0 -3
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { Elysia } from "elysia";
|
|
2
|
-
import { createRoleChecker } from "@longzai-intelligence-auth/rbac";
|
|
3
|
-
import { createJwtVerifier } from "@longzai-intelligence-auth/jwt";
|
|
4
|
-
import { TokenMissingError, TokenInvalidError } from "@longzai-intelligence-auth/core";
|
|
5
|
-
export function createRbacPlugin(options) {
|
|
6
|
-
const { jwt: jwtConfig, defaultTenantId = "default" } = options;
|
|
7
|
-
const roleChecker = createRoleChecker();
|
|
8
|
-
let verifierPromise = null;
|
|
9
|
-
const getVerifier = () => {
|
|
10
|
-
if (!verifierPromise) {
|
|
11
|
-
verifierPromise = createJwtVerifier(jwtConfig);
|
|
12
|
-
}
|
|
13
|
-
return verifierPromise;
|
|
14
|
-
};
|
|
15
|
-
return new Elysia({ name: "@longzai-intelligence-auth/rbac" })
|
|
16
|
-
.macro(({ onBeforeHandle }) => ({
|
|
17
|
-
permission(permission) {
|
|
18
|
-
onBeforeHandle(async ({ request }) => {
|
|
19
|
-
const authHeader = request.headers.get("Authorization");
|
|
20
|
-
const bearer = authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : null;
|
|
21
|
-
if (!bearer) {
|
|
22
|
-
throw new TokenMissingError();
|
|
23
|
-
}
|
|
24
|
-
const verifier = await getVerifier();
|
|
25
|
-
const result = await verifier.verifyAccessToken(bearer);
|
|
26
|
-
if (!result.success || !result.payload) {
|
|
27
|
-
throw new TokenInvalidError(result.error);
|
|
28
|
-
}
|
|
29
|
-
const payload = result.payload;
|
|
30
|
-
const [resource, action] = permission.split(":");
|
|
31
|
-
if (!resource || !action) {
|
|
32
|
-
throw new Error(`无效的权限格式: ${permission},应为 resource:action`);
|
|
33
|
-
}
|
|
34
|
-
const hasPermission = roleChecker.hasPermission(payload, resource, action);
|
|
35
|
-
if (!hasPermission) {
|
|
36
|
-
const { PermissionDeniedError } = await import("@longzai-intelligence/error");
|
|
37
|
-
throw new PermissionDeniedError(resource, action);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
},
|
|
41
|
-
}));
|
|
42
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { Elysia } from "elysia";
|
|
2
|
-
import type { AuthBackendPort } from "@longzai-intelligence-auth/core";
|
|
3
|
-
export type TenantPluginOptions = {
|
|
4
|
-
defaultTenantId?: string;
|
|
5
|
-
adapter?: AuthBackendPort;
|
|
6
|
-
};
|
|
7
|
-
export declare function createTenantPlugin(options?: TenantPluginOptions): Elysia<"", {
|
|
8
|
-
decorator: {};
|
|
9
|
-
store: {};
|
|
10
|
-
derive: {};
|
|
11
|
-
resolve: {};
|
|
12
|
-
}, {
|
|
13
|
-
typebox: {};
|
|
14
|
-
error: {};
|
|
15
|
-
}, {
|
|
16
|
-
schema: {};
|
|
17
|
-
standaloneSchema: {};
|
|
18
|
-
macro: {};
|
|
19
|
-
macroFn: {};
|
|
20
|
-
parser: {};
|
|
21
|
-
response: {};
|
|
22
|
-
}, {}, {
|
|
23
|
-
derive: {
|
|
24
|
-
tenantId: string;
|
|
25
|
-
};
|
|
26
|
-
resolve: {};
|
|
27
|
-
schema: {};
|
|
28
|
-
standaloneSchema: {};
|
|
29
|
-
response: import("elysia").ExtractErrorFromHandle<{
|
|
30
|
-
tenantId: string;
|
|
31
|
-
}>;
|
|
32
|
-
}, {
|
|
33
|
-
derive: {};
|
|
34
|
-
resolve: {};
|
|
35
|
-
schema: {};
|
|
36
|
-
standaloneSchema: {};
|
|
37
|
-
response: {};
|
|
38
|
-
}>;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Elysia } from "elysia";
|
|
2
|
-
export function createTenantPlugin(options = {}) {
|
|
3
|
-
const { defaultTenantId = "default", adapter } = options;
|
|
4
|
-
return new Elysia({ name: "@longzai-intelligence-auth/tenant" })
|
|
5
|
-
.derive(({ request }) => {
|
|
6
|
-
const headerTenantId = request.headers.get("x-tenant-id");
|
|
7
|
-
return { tenantId: headerTenantId ?? defaultTenantId };
|
|
8
|
-
})
|
|
9
|
-
.as("scoped")
|
|
10
|
-
.onBeforeHandle(async ({ tenantId }) => {
|
|
11
|
-
if (adapter && tenantId !== defaultTenantId) {
|
|
12
|
-
const result = await adapter.tenant.validateStatus(tenantId);
|
|
13
|
-
if (!result.valid) {
|
|
14
|
-
const { PermissionDeniedError } = await import("@longzai-intelligence/error");
|
|
15
|
-
throw new PermissionDeniedError("tenant", "access");
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Elysia } from "elysia";
|
|
2
|
-
import type { JwtSignerConfig } from "@longzai-intelligence-auth/jwt";
|
|
3
|
-
import type { LoggerService } from "@longzai-intelligence-auth/core";
|
|
4
|
-
export type BasicPresetOptions = {
|
|
5
|
-
jwt: JwtSignerConfig;
|
|
6
|
-
defaultTenantId?: string;
|
|
7
|
-
logger?: LoggerService;
|
|
8
|
-
};
|
|
9
|
-
type AnyElysia = Elysia<any, any, any, any, any, any, any>;
|
|
10
|
-
export declare function createBasicPreset(options: BasicPresetOptions): AnyElysia;
|
|
11
|
-
export {};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Elysia } from "elysia";
|
|
2
|
-
import { createJwtVerifyPlugin } from "../plugins/jwt-verify.plugin";
|
|
3
|
-
import { createErrorHandlerPlugin } from "../plugins/error-handler.plugin";
|
|
4
|
-
export function createBasicPreset(options) {
|
|
5
|
-
return new Elysia({ name: "@longzai-intelligence-auth/basic-preset" })
|
|
6
|
-
.use(createJwtVerifyPlugin({
|
|
7
|
-
jwt: options.jwt,
|
|
8
|
-
defaultTenantId: options.defaultTenantId,
|
|
9
|
-
}))
|
|
10
|
-
.use(createErrorHandlerPlugin({ logger: options.logger }));
|
|
11
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { Elysia } from "elysia";
|
|
2
|
-
import type { JwtSignerConfig } from "@longzai-intelligence-auth/jwt";
|
|
3
|
-
import type { AuthBackendPort } from "@longzai-intelligence-auth/core";
|
|
4
|
-
import type { LoggerService } from "@longzai-intelligence-auth/core";
|
|
5
|
-
export type StandardPresetOptions = {
|
|
6
|
-
jwt: JwtSignerConfig;
|
|
7
|
-
defaultTenantId?: string;
|
|
8
|
-
adapter: AuthBackendPort;
|
|
9
|
-
logger?: LoggerService;
|
|
10
|
-
};
|
|
11
|
-
type AnyElysia = Elysia<any, any, any, any, any, any, any>;
|
|
12
|
-
export declare function createStandardPreset(options: StandardPresetOptions): AnyElysia;
|
|
13
|
-
export {};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { Elysia } from "elysia";
|
|
2
|
-
import { createJwtVerifyPlugin } from "../plugins/jwt-verify.plugin";
|
|
3
|
-
import { createRbacPlugin } from "../plugins/rbac.plugin";
|
|
4
|
-
import { createTenantPlugin } from "../plugins/tenant.plugin";
|
|
5
|
-
import { createRateLimitPlugin } from "../plugins/rate-limit.plugin";
|
|
6
|
-
import { createErrorHandlerPlugin } from "../plugins/error-handler.plugin";
|
|
7
|
-
export function createStandardPreset(options) {
|
|
8
|
-
return new Elysia({ name: "@longzai-intelligence-auth/standard-preset" })
|
|
9
|
-
.use(createJwtVerifyPlugin({
|
|
10
|
-
jwt: options.jwt,
|
|
11
|
-
defaultTenantId: options.defaultTenantId,
|
|
12
|
-
}))
|
|
13
|
-
.use(createRbacPlugin({
|
|
14
|
-
jwt: options.jwt,
|
|
15
|
-
defaultTenantId: options.defaultTenantId,
|
|
16
|
-
}))
|
|
17
|
-
.use(createTenantPlugin({
|
|
18
|
-
defaultTenantId: options.defaultTenantId,
|
|
19
|
-
adapter: options.adapter,
|
|
20
|
-
}))
|
|
21
|
-
.use(createRateLimitPlugin({
|
|
22
|
-
windowSeconds: 60,
|
|
23
|
-
maxRequests: 100,
|
|
24
|
-
}))
|
|
25
|
-
.use(createErrorHandlerPlugin({ logger: options.logger }));
|
|
26
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { Elysia } from "elysia";
|
|
2
|
-
import type { JwtSignerConfig } from "@longzai-intelligence-auth/jwt";
|
|
3
|
-
import type { AuthBackendPort, PasswordHasher } from "@longzai-intelligence-auth/core";
|
|
4
|
-
export type AuthRoutesConfig = {
|
|
5
|
-
jwt: JwtSignerConfig;
|
|
6
|
-
adapter: AuthBackendPort;
|
|
7
|
-
passwordHasher: PasswordHasher;
|
|
8
|
-
defaultTenantId: string;
|
|
9
|
-
};
|
|
10
|
-
type AnyElysia = Elysia<any, any, any, any, any, any, any>;
|
|
11
|
-
export declare function createAuthRoutes(config: AuthRoutesConfig): AnyElysia;
|
|
12
|
-
export type MeRouteConfig = {
|
|
13
|
-
jwt: JwtSignerConfig;
|
|
14
|
-
defaultTenantId: string;
|
|
15
|
-
};
|
|
16
|
-
export declare function createMeRoute(config: MeRouteConfig): AnyElysia;
|
|
17
|
-
export {};
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { Elysia, t } from "elysia";
|
|
2
|
-
import { createJwtSigner, createJwtVerifier } from "@longzai-intelligence-auth/jwt";
|
|
3
|
-
import { validatePasswordPolicy } from "@longzai-intelligence-auth/password";
|
|
4
|
-
import { createSessionManager } from "@longzai-intelligence-auth/session";
|
|
5
|
-
import { createLoginUseCase } from "@longzai-intelligence-auth/session";
|
|
6
|
-
import { createLogoutUseCase } from "@longzai-intelligence-auth/session";
|
|
7
|
-
import { createRefreshSessionUseCase } from "@longzai-intelligence-auth/session";
|
|
8
|
-
import { TokenMissingError, TokenInvalidError, UserAlreadyExistsError, PasswordPolicyViolationError, } from "@longzai-intelligence-auth/core";
|
|
9
|
-
export function createAuthRoutes(config) {
|
|
10
|
-
const { jwt: jwtConfig, adapter, passwordHasher, defaultTenantId } = config;
|
|
11
|
-
const sessionManager = createSessionManager();
|
|
12
|
-
let signerPromise = null;
|
|
13
|
-
const getTokenSigner = () => {
|
|
14
|
-
if (!signerPromise) {
|
|
15
|
-
signerPromise = createJwtSigner(jwtConfig);
|
|
16
|
-
}
|
|
17
|
-
return signerPromise;
|
|
18
|
-
};
|
|
19
|
-
let verifierPromise = null;
|
|
20
|
-
const getVerifier = () => {
|
|
21
|
-
if (!verifierPromise) {
|
|
22
|
-
verifierPromise = createJwtVerifier(jwtConfig);
|
|
23
|
-
}
|
|
24
|
-
return verifierPromise;
|
|
25
|
-
};
|
|
26
|
-
return new Elysia({ name: "@longzai-intelligence-auth/routes", prefix: "/auth" })
|
|
27
|
-
.post("/login", async ({ body, request }) => {
|
|
28
|
-
const { email, password } = body;
|
|
29
|
-
const ipAddress = request.headers.get("x-forwarded-for") ?? request.headers.get("x-real-ip") ?? undefined;
|
|
30
|
-
const userAgent = request.headers.get("user-agent") ?? undefined;
|
|
31
|
-
const tokenSigner = await getTokenSigner();
|
|
32
|
-
const loginUseCase = createLoginUseCase({ adapter, tokenSigner, sessionManager, defaultTenantId });
|
|
33
|
-
return loginUseCase.execute(email, password, userAgent, ipAddress);
|
|
34
|
-
}, {
|
|
35
|
-
body: t.Object({
|
|
36
|
-
email: t.String({ format: "email" }),
|
|
37
|
-
password: t.String({ minLength: 1 }),
|
|
38
|
-
}),
|
|
39
|
-
detail: {
|
|
40
|
-
summary: "用户登录",
|
|
41
|
-
description: "使用邮箱和密码登录,返回访问令牌和刷新令牌",
|
|
42
|
-
},
|
|
43
|
-
})
|
|
44
|
-
.post("/logout", async ({ request }) => {
|
|
45
|
-
const authHeader = request.headers.get("Authorization");
|
|
46
|
-
const bearer = authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : null;
|
|
47
|
-
if (!bearer) {
|
|
48
|
-
throw new TokenMissingError();
|
|
49
|
-
}
|
|
50
|
-
const verifier = await getVerifier();
|
|
51
|
-
const verifyResult = await verifier.verifyAccessToken(bearer);
|
|
52
|
-
if (!verifyResult.success || !verifyResult.payload) {
|
|
53
|
-
throw new TokenInvalidError(verifyResult.error);
|
|
54
|
-
}
|
|
55
|
-
const tokenSigner = await getTokenSigner();
|
|
56
|
-
const logoutUseCase = createLogoutUseCase({ adapter, tokenSigner, sessionManager });
|
|
57
|
-
return logoutUseCase.execute("session-revoked");
|
|
58
|
-
}, {
|
|
59
|
-
detail: {
|
|
60
|
-
summary: "用户登出",
|
|
61
|
-
description: "使当前会话失效",
|
|
62
|
-
},
|
|
63
|
-
})
|
|
64
|
-
.post("/refresh", async ({ body }) => {
|
|
65
|
-
const { refreshToken } = body;
|
|
66
|
-
const tokenSigner = await getTokenSigner();
|
|
67
|
-
const refreshSessionUseCase = createRefreshSessionUseCase({ adapter, tokenSigner, sessionManager });
|
|
68
|
-
return refreshSessionUseCase.execute(refreshToken);
|
|
69
|
-
}, {
|
|
70
|
-
body: t.Object({
|
|
71
|
-
refreshToken: t.String({ minLength: 1 }),
|
|
72
|
-
}),
|
|
73
|
-
detail: {
|
|
74
|
-
summary: "刷新令牌",
|
|
75
|
-
description: "使用刷新令牌获取新的访问令牌",
|
|
76
|
-
},
|
|
77
|
-
})
|
|
78
|
-
.post("/register", async ({ body }) => {
|
|
79
|
-
const { email, password, name } = body;
|
|
80
|
-
const validation = validatePasswordPolicy(password);
|
|
81
|
-
if (!validation.valid) {
|
|
82
|
-
throw new PasswordPolicyViolationError(validation.errors.join(", "));
|
|
83
|
-
}
|
|
84
|
-
const existingUser = await adapter.user.findByEmail(email);
|
|
85
|
-
if (existingUser) {
|
|
86
|
-
throw new UserAlreadyExistsError();
|
|
87
|
-
}
|
|
88
|
-
const passwordHash = await passwordHasher.hash(password);
|
|
89
|
-
const newUser = await adapter.user.create({
|
|
90
|
-
email,
|
|
91
|
-
username: email,
|
|
92
|
-
passwordHash,
|
|
93
|
-
displayName: name,
|
|
94
|
-
});
|
|
95
|
-
return {
|
|
96
|
-
userId: newUser.id,
|
|
97
|
-
message: "注册成功",
|
|
98
|
-
};
|
|
99
|
-
}, {
|
|
100
|
-
body: t.Object({
|
|
101
|
-
email: t.String({ format: "email" }),
|
|
102
|
-
password: t.String({ minLength: 8 }),
|
|
103
|
-
name: t.String({ minLength: 1 }),
|
|
104
|
-
}),
|
|
105
|
-
detail: {
|
|
106
|
-
summary: "用户注册",
|
|
107
|
-
description: "创建新用户账户",
|
|
108
|
-
},
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
export function createMeRoute(config) {
|
|
112
|
-
const { jwt: jwtConfig, defaultTenantId } = config;
|
|
113
|
-
let verifierPromise = null;
|
|
114
|
-
const getVerifier = () => {
|
|
115
|
-
if (!verifierPromise) {
|
|
116
|
-
verifierPromise = createJwtVerifier(jwtConfig);
|
|
117
|
-
}
|
|
118
|
-
return verifierPromise;
|
|
119
|
-
};
|
|
120
|
-
return new Elysia({ name: "@longzai-intelligence-auth/me-route", prefix: "/auth" })
|
|
121
|
-
.get("/me", async ({ request }) => {
|
|
122
|
-
const authHeader = request.headers.get("Authorization");
|
|
123
|
-
const bearer = authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : null;
|
|
124
|
-
if (!bearer) {
|
|
125
|
-
throw new TokenMissingError();
|
|
126
|
-
}
|
|
127
|
-
const verifier = await getVerifier();
|
|
128
|
-
const result = await verifier.verifyAccessToken(bearer);
|
|
129
|
-
if (!result.success || !result.payload) {
|
|
130
|
-
throw new TokenInvalidError(result.error);
|
|
131
|
-
}
|
|
132
|
-
const payload = result.payload;
|
|
133
|
-
const userId = payload.sub;
|
|
134
|
-
const tenantId = payload.tenantId ?? defaultTenantId;
|
|
135
|
-
return {
|
|
136
|
-
userId,
|
|
137
|
-
...(tenantId ? { tenantId } : {}),
|
|
138
|
-
};
|
|
139
|
-
}, {
|
|
140
|
-
detail: {
|
|
141
|
-
summary: "获取当前用户信息",
|
|
142
|
-
description: "使用 Bearer Token 获取当前认证用户的信息",
|
|
143
|
-
},
|
|
144
|
-
});
|
|
145
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import type { JwtSignerConfig } from "@longzai-intelligence-auth/jwt";
|
|
2
|
-
import type { AuthBackendPort, PasswordHasher } from "@longzai-intelligence-auth/core";
|
|
3
|
-
import type { LoggerService } from "@longzai-intelligence-auth/core";
|
|
4
|
-
export type JwtStrategyConfig = {
|
|
5
|
-
strategy: "jwt";
|
|
6
|
-
jwt: JwtSignerConfig;
|
|
7
|
-
defaultTenantId?: string;
|
|
8
|
-
};
|
|
9
|
-
export type StandaloneStrategyConfig = {
|
|
10
|
-
strategy: "standalone";
|
|
11
|
-
jwt: JwtSignerConfig;
|
|
12
|
-
adapter: AuthBackendPort;
|
|
13
|
-
passwordHasher: PasswordHasher;
|
|
14
|
-
defaultTenantId?: string;
|
|
15
|
-
};
|
|
16
|
-
export type EnvBasicStrategyConfig = {
|
|
17
|
-
strategy: "env-basic";
|
|
18
|
-
jwt: JwtSignerConfig;
|
|
19
|
-
adminUsername?: string;
|
|
20
|
-
adminPassword?: string;
|
|
21
|
-
defaultTenantId?: string;
|
|
22
|
-
};
|
|
23
|
-
export type AuthPluginConfig = (JwtStrategyConfig & {
|
|
24
|
-
registerRoutes?: boolean;
|
|
25
|
-
}) | (StandaloneStrategyConfig & {
|
|
26
|
-
registerRoutes?: boolean;
|
|
27
|
-
}) | (EnvBasicStrategyConfig & {
|
|
28
|
-
registerRoutes?: boolean;
|
|
29
|
-
});
|
|
30
|
-
export type AuthPluginOptions = AuthPluginConfig & {
|
|
31
|
-
logger?: LoggerService;
|
|
32
|
-
};
|
|
33
|
-
export type StrategyName = AuthPluginConfig["strategy"];
|
|
34
|
-
export type StrategyContext = {
|
|
35
|
-
strategy: StrategyName;
|
|
36
|
-
defaultTenantId: string;
|
|
37
|
-
registerRoutes: boolean;
|
|
38
|
-
adapter?: AuthBackendPort;
|
|
39
|
-
passwordHasher?: PasswordHasher;
|
|
40
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function extractClientIp(request: Request): string | undefined;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function extractUserAgent(request: Request): string | undefined;
|