@esengine/server 1.1.4 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Room-BnKpl5Sj.d.ts +237 -0
- package/dist/auth/index.d.ts +711 -0
- package/dist/auth/index.js +707 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/testing/index.d.ts +153 -0
- package/dist/auth/testing/index.js +165 -0
- package/dist/auth/testing/index.js.map +1 -0
- package/dist/chunk-7C6JZO4O.js +744 -0
- package/dist/chunk-7C6JZO4O.js.map +1 -0
- package/dist/chunk-T626JPC7.js +8 -0
- package/dist/chunk-T626JPC7.js.map +1 -0
- package/dist/index-DgaJIm6-.d.ts +170 -0
- package/dist/index.d.ts +4 -403
- package/dist/index.js +3 -745
- package/dist/index.js.map +1 -1
- package/dist/testing/index.d.ts +386 -0
- package/dist/testing/index.js +629 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/types-BmO5ykKp.d.ts +311 -0
- package/package.json +26 -3
|
@@ -0,0 +1,711 @@
|
|
|
1
|
+
import { I as IAuthContext, A as AuthResult, a as IAuthProvider, b as AuthServerConfig, c as AuthGameServer, d as AuthRoomConfig, R as RequireAuthOptions, e as RequireRoleOptions } from '../types-BmO5ykKp.js';
|
|
2
|
+
export { i as AuthApiContext, h as AuthConnection, g as AuthConnectionData, f as AuthErrorCode, j as AuthMsgContext, C as ConnectionRequest } from '../types-BmO5ykKp.js';
|
|
3
|
+
import { G as GameServer, a as ServerConnection } from '../index-DgaJIm6-.js';
|
|
4
|
+
import { R as Room, P as Player } from '../Room-BnKpl5Sj.js';
|
|
5
|
+
import '@esengine/rpc';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @zh 认证上下文实现
|
|
9
|
+
* @en Authentication context implementation
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @zh 用户信息提取器
|
|
14
|
+
* @en User info extractor
|
|
15
|
+
*/
|
|
16
|
+
interface UserInfoExtractor<TUser> {
|
|
17
|
+
/**
|
|
18
|
+
* @zh 提取用户 ID
|
|
19
|
+
* @en Extract user ID
|
|
20
|
+
*/
|
|
21
|
+
getId(user: TUser): string;
|
|
22
|
+
/**
|
|
23
|
+
* @zh 提取用户角色
|
|
24
|
+
* @en Extract user roles
|
|
25
|
+
*/
|
|
26
|
+
getRoles(user: TUser): string[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* @zh 默认用户信息提取器
|
|
30
|
+
* @en Default user info extractor
|
|
31
|
+
*/
|
|
32
|
+
declare const defaultUserExtractor: UserInfoExtractor<unknown>;
|
|
33
|
+
/**
|
|
34
|
+
* @zh 认证上下文
|
|
35
|
+
* @en Authentication context
|
|
36
|
+
*
|
|
37
|
+
* @zh 存储连接的认证状态
|
|
38
|
+
* @en Stores authentication state for a connection
|
|
39
|
+
*/
|
|
40
|
+
declare class AuthContext<TUser = unknown> implements IAuthContext<TUser> {
|
|
41
|
+
private _isAuthenticated;
|
|
42
|
+
private _user;
|
|
43
|
+
private _userId;
|
|
44
|
+
private _roles;
|
|
45
|
+
private _authenticatedAt;
|
|
46
|
+
private _expiresAt;
|
|
47
|
+
private _extractor;
|
|
48
|
+
constructor(extractor?: UserInfoExtractor<TUser>);
|
|
49
|
+
/**
|
|
50
|
+
* @zh 是否已认证
|
|
51
|
+
* @en Whether authenticated
|
|
52
|
+
*/
|
|
53
|
+
get isAuthenticated(): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* @zh 用户信息
|
|
56
|
+
* @en User information
|
|
57
|
+
*/
|
|
58
|
+
get user(): TUser | null;
|
|
59
|
+
/**
|
|
60
|
+
* @zh 用户 ID
|
|
61
|
+
* @en User ID
|
|
62
|
+
*/
|
|
63
|
+
get userId(): string | null;
|
|
64
|
+
/**
|
|
65
|
+
* @zh 用户角色
|
|
66
|
+
* @en User roles
|
|
67
|
+
*/
|
|
68
|
+
get roles(): ReadonlyArray<string>;
|
|
69
|
+
/**
|
|
70
|
+
* @zh 认证时间
|
|
71
|
+
* @en Authentication timestamp
|
|
72
|
+
*/
|
|
73
|
+
get authenticatedAt(): number | null;
|
|
74
|
+
/**
|
|
75
|
+
* @zh 令牌过期时间
|
|
76
|
+
* @en Token expiration time
|
|
77
|
+
*/
|
|
78
|
+
get expiresAt(): number | null;
|
|
79
|
+
/**
|
|
80
|
+
* @zh 检查是否有指定角色
|
|
81
|
+
* @en Check if has specified role
|
|
82
|
+
*/
|
|
83
|
+
hasRole(role: string): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* @zh 检查是否有任一指定角色
|
|
86
|
+
* @en Check if has any of specified roles
|
|
87
|
+
*/
|
|
88
|
+
hasAnyRole(roles: string[]): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* @zh 检查是否有所有指定角色
|
|
91
|
+
* @en Check if has all specified roles
|
|
92
|
+
*/
|
|
93
|
+
hasAllRoles(roles: string[]): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* @zh 设置认证结果
|
|
96
|
+
* @en Set authentication result
|
|
97
|
+
*/
|
|
98
|
+
setAuthenticated(result: AuthResult<TUser>): void;
|
|
99
|
+
/**
|
|
100
|
+
* @zh 清除认证状态
|
|
101
|
+
* @en Clear authentication state
|
|
102
|
+
*/
|
|
103
|
+
clear(): void;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* @zh 创建访客认证上下文
|
|
107
|
+
* @en Create guest auth context
|
|
108
|
+
*/
|
|
109
|
+
declare function createGuestContext<TUser = unknown>(): IAuthContext<TUser>;
|
|
110
|
+
/**
|
|
111
|
+
* @zh 从认证结果创建认证上下文
|
|
112
|
+
* @en Create auth context from auth result
|
|
113
|
+
*/
|
|
114
|
+
declare function createAuthContext<TUser = unknown>(result: AuthResult<TUser>, extractor?: UserInfoExtractor<TUser>): AuthContext<TUser>;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @zh JWT 认证提供者
|
|
118
|
+
* @en JWT authentication provider
|
|
119
|
+
*/
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @zh JWT 载荷
|
|
123
|
+
* @en JWT payload
|
|
124
|
+
*/
|
|
125
|
+
interface JwtPayload {
|
|
126
|
+
/**
|
|
127
|
+
* @zh 主题(用户 ID)
|
|
128
|
+
* @en Subject (user ID)
|
|
129
|
+
*/
|
|
130
|
+
sub?: string;
|
|
131
|
+
/**
|
|
132
|
+
* @zh 签发时间
|
|
133
|
+
* @en Issued at
|
|
134
|
+
*/
|
|
135
|
+
iat?: number;
|
|
136
|
+
/**
|
|
137
|
+
* @zh 过期时间
|
|
138
|
+
* @en Expiration time
|
|
139
|
+
*/
|
|
140
|
+
exp?: number;
|
|
141
|
+
/**
|
|
142
|
+
* @zh 自定义字段
|
|
143
|
+
* @en Custom fields
|
|
144
|
+
*/
|
|
145
|
+
[key: string]: unknown;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* @zh JWT 认证配置
|
|
149
|
+
* @en JWT authentication configuration
|
|
150
|
+
*/
|
|
151
|
+
interface JwtAuthConfig<TUser = unknown> {
|
|
152
|
+
/**
|
|
153
|
+
* @zh 密钥
|
|
154
|
+
* @en Secret key
|
|
155
|
+
*/
|
|
156
|
+
secret: string;
|
|
157
|
+
/**
|
|
158
|
+
* @zh 算法
|
|
159
|
+
* @en Algorithm
|
|
160
|
+
* @defaultValue 'HS256'
|
|
161
|
+
*/
|
|
162
|
+
algorithm?: 'HS256' | 'HS384' | 'HS512' | 'RS256' | 'RS384' | 'RS512';
|
|
163
|
+
/**
|
|
164
|
+
* @zh 令牌过期时间(秒)
|
|
165
|
+
* @en Token expiration in seconds
|
|
166
|
+
* @defaultValue 3600
|
|
167
|
+
*/
|
|
168
|
+
expiresIn?: number;
|
|
169
|
+
/**
|
|
170
|
+
* @zh 从载荷获取用户信息
|
|
171
|
+
* @en Get user from payload
|
|
172
|
+
*/
|
|
173
|
+
getUser?: (payload: JwtPayload) => TUser | Promise<TUser | null> | null;
|
|
174
|
+
/**
|
|
175
|
+
* @zh 签发者
|
|
176
|
+
* @en Issuer
|
|
177
|
+
*/
|
|
178
|
+
issuer?: string;
|
|
179
|
+
/**
|
|
180
|
+
* @zh 受众
|
|
181
|
+
* @en Audience
|
|
182
|
+
*/
|
|
183
|
+
audience?: string;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* @zh JWT 认证提供者
|
|
187
|
+
* @en JWT authentication provider
|
|
188
|
+
*
|
|
189
|
+
* @zh 使用 jsonwebtoken 库实现 JWT 认证
|
|
190
|
+
* @en Uses jsonwebtoken library for JWT authentication
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```typescript
|
|
194
|
+
* const jwtProvider = createJwtAuthProvider({
|
|
195
|
+
* secret: 'your-secret-key',
|
|
196
|
+
* expiresIn: 3600,
|
|
197
|
+
* getUser: async (payload) => {
|
|
198
|
+
* return await db.users.findById(payload.sub);
|
|
199
|
+
* }
|
|
200
|
+
* });
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
declare class JwtAuthProvider<TUser = unknown> implements IAuthProvider<TUser, string> {
|
|
204
|
+
readonly name = "jwt";
|
|
205
|
+
private _config;
|
|
206
|
+
constructor(config: JwtAuthConfig<TUser>);
|
|
207
|
+
/**
|
|
208
|
+
* @zh 验证令牌
|
|
209
|
+
* @en Verify token
|
|
210
|
+
*/
|
|
211
|
+
verify(token: string): Promise<AuthResult<TUser>>;
|
|
212
|
+
/**
|
|
213
|
+
* @zh 刷新令牌
|
|
214
|
+
* @en Refresh token
|
|
215
|
+
*/
|
|
216
|
+
refresh(token: string): Promise<AuthResult<TUser>>;
|
|
217
|
+
/**
|
|
218
|
+
* @zh 生成令牌
|
|
219
|
+
* @en Generate token
|
|
220
|
+
*/
|
|
221
|
+
sign(payload: Record<string, unknown>): string;
|
|
222
|
+
/**
|
|
223
|
+
* @zh 解码令牌(不验证)
|
|
224
|
+
* @en Decode token (without verification)
|
|
225
|
+
*/
|
|
226
|
+
decode(token: string): JwtPayload | null;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* @zh 创建 JWT 认证提供者
|
|
230
|
+
* @en Create JWT authentication provider
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```typescript
|
|
234
|
+
* import { createJwtAuthProvider } from '@esengine/server/auth';
|
|
235
|
+
*
|
|
236
|
+
* const jwtProvider = createJwtAuthProvider({
|
|
237
|
+
* secret: process.env.JWT_SECRET!,
|
|
238
|
+
* expiresIn: 3600,
|
|
239
|
+
* getUser: async (payload) => {
|
|
240
|
+
* return { id: payload.sub, name: payload.name };
|
|
241
|
+
* }
|
|
242
|
+
* });
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
declare function createJwtAuthProvider<TUser = unknown>(config: JwtAuthConfig<TUser>): JwtAuthProvider<TUser>;
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* @zh Session 认证提供者
|
|
249
|
+
* @en Session authentication provider
|
|
250
|
+
*/
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* @zh Session 存储接口(兼容 ITransactionStorage)
|
|
254
|
+
* @en Session storage interface (compatible with ITransactionStorage)
|
|
255
|
+
*/
|
|
256
|
+
interface ISessionStorage {
|
|
257
|
+
get<T>(key: string): Promise<T | null>;
|
|
258
|
+
set<T>(key: string, value: T, ttl?: number): Promise<void>;
|
|
259
|
+
delete(key: string): Promise<boolean>;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* @zh Session 数据
|
|
263
|
+
* @en Session data
|
|
264
|
+
*/
|
|
265
|
+
interface SessionData<TUser = unknown> {
|
|
266
|
+
/**
|
|
267
|
+
* @zh 用户信息
|
|
268
|
+
* @en User information
|
|
269
|
+
*/
|
|
270
|
+
user: TUser;
|
|
271
|
+
/**
|
|
272
|
+
* @zh 创建时间
|
|
273
|
+
* @en Created at
|
|
274
|
+
*/
|
|
275
|
+
createdAt: number;
|
|
276
|
+
/**
|
|
277
|
+
* @zh 最后活跃时间
|
|
278
|
+
* @en Last active at
|
|
279
|
+
*/
|
|
280
|
+
lastActiveAt: number;
|
|
281
|
+
/**
|
|
282
|
+
* @zh 自定义数据
|
|
283
|
+
* @en Custom data
|
|
284
|
+
*/
|
|
285
|
+
data?: Record<string, unknown>;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* @zh Session 认证配置
|
|
289
|
+
* @en Session authentication configuration
|
|
290
|
+
*/
|
|
291
|
+
interface SessionAuthConfig<TUser = unknown> {
|
|
292
|
+
/**
|
|
293
|
+
* @zh Session 存储
|
|
294
|
+
* @en Session storage
|
|
295
|
+
*/
|
|
296
|
+
storage: ISessionStorage;
|
|
297
|
+
/**
|
|
298
|
+
* @zh Session 过期时间(毫秒)
|
|
299
|
+
* @en Session expiration in milliseconds
|
|
300
|
+
* @defaultValue 86400000 (24h)
|
|
301
|
+
*/
|
|
302
|
+
sessionTTL?: number;
|
|
303
|
+
/**
|
|
304
|
+
* @zh Session 键前缀
|
|
305
|
+
* @en Session key prefix
|
|
306
|
+
* @defaultValue 'session:'
|
|
307
|
+
*/
|
|
308
|
+
prefix?: string;
|
|
309
|
+
/**
|
|
310
|
+
* @zh 验证用户(可选额外验证)
|
|
311
|
+
* @en Validate user (optional extra validation)
|
|
312
|
+
*/
|
|
313
|
+
validateUser?: (user: TUser) => boolean | Promise<boolean>;
|
|
314
|
+
/**
|
|
315
|
+
* @zh 是否自动续期
|
|
316
|
+
* @en Auto renew session
|
|
317
|
+
* @defaultValue true
|
|
318
|
+
*/
|
|
319
|
+
autoRenew?: boolean;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* @zh Session 认证提供者
|
|
323
|
+
* @en Session authentication provider
|
|
324
|
+
*
|
|
325
|
+
* @zh 基于存储的会话认证,支持 Redis、MongoDB 等后端
|
|
326
|
+
* @en Storage-based session authentication, supports Redis, MongoDB, etc.
|
|
327
|
+
*
|
|
328
|
+
* @example
|
|
329
|
+
* ```typescript
|
|
330
|
+
* import { createSessionAuthProvider } from '@esengine/server/auth';
|
|
331
|
+
* import { createRedisStorage } from '@esengine/transaction';
|
|
332
|
+
*
|
|
333
|
+
* const sessionProvider = createSessionAuthProvider({
|
|
334
|
+
* storage: createRedisStorage({ factory: () => new Redis() }),
|
|
335
|
+
* sessionTTL: 86400000, // 24 hours
|
|
336
|
+
* });
|
|
337
|
+
* ```
|
|
338
|
+
*/
|
|
339
|
+
declare class SessionAuthProvider<TUser = unknown> implements IAuthProvider<TUser, string> {
|
|
340
|
+
readonly name = "session";
|
|
341
|
+
private _config;
|
|
342
|
+
constructor(config: SessionAuthConfig<TUser>);
|
|
343
|
+
/**
|
|
344
|
+
* @zh 获取存储键
|
|
345
|
+
* @en Get storage key
|
|
346
|
+
*/
|
|
347
|
+
private _getKey;
|
|
348
|
+
/**
|
|
349
|
+
* @zh 验证 Session
|
|
350
|
+
* @en Verify session
|
|
351
|
+
*/
|
|
352
|
+
verify(sessionId: string): Promise<AuthResult<TUser>>;
|
|
353
|
+
/**
|
|
354
|
+
* @zh 刷新 Session
|
|
355
|
+
* @en Refresh session
|
|
356
|
+
*/
|
|
357
|
+
refresh(sessionId: string): Promise<AuthResult<TUser>>;
|
|
358
|
+
/**
|
|
359
|
+
* @zh 撤销 Session
|
|
360
|
+
* @en Revoke session
|
|
361
|
+
*/
|
|
362
|
+
revoke(sessionId: string): Promise<boolean>;
|
|
363
|
+
/**
|
|
364
|
+
* @zh 创建 Session
|
|
365
|
+
* @en Create session
|
|
366
|
+
*/
|
|
367
|
+
createSession(user: TUser, data?: Record<string, unknown>): Promise<string>;
|
|
368
|
+
/**
|
|
369
|
+
* @zh 获取 Session 数据
|
|
370
|
+
* @en Get session data
|
|
371
|
+
*/
|
|
372
|
+
getSession(sessionId: string): Promise<SessionData<TUser> | null>;
|
|
373
|
+
/**
|
|
374
|
+
* @zh 更新 Session 数据
|
|
375
|
+
* @en Update session data
|
|
376
|
+
*/
|
|
377
|
+
updateSession(sessionId: string, data: Record<string, unknown>): Promise<boolean>;
|
|
378
|
+
/**
|
|
379
|
+
* @zh 生成 Session ID(使用加密安全的随机数)
|
|
380
|
+
* @en Generate session ID (using cryptographically secure random)
|
|
381
|
+
*/
|
|
382
|
+
private _generateSessionId;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* @zh 创建 Session 认证提供者
|
|
386
|
+
* @en Create session authentication provider
|
|
387
|
+
*
|
|
388
|
+
* @example
|
|
389
|
+
* ```typescript
|
|
390
|
+
* import { createSessionAuthProvider } from '@esengine/server/auth';
|
|
391
|
+
* import { MemoryStorage } from '@esengine/transaction';
|
|
392
|
+
*
|
|
393
|
+
* const sessionProvider = createSessionAuthProvider({
|
|
394
|
+
* storage: new MemoryStorage(),
|
|
395
|
+
* sessionTTL: 3600000, // 1 hour
|
|
396
|
+
* });
|
|
397
|
+
*
|
|
398
|
+
* // Create a session
|
|
399
|
+
* const sessionId = await sessionProvider.createSession({ id: '1', name: 'Alice' });
|
|
400
|
+
*
|
|
401
|
+
* // Verify session
|
|
402
|
+
* const result = await sessionProvider.verify(sessionId);
|
|
403
|
+
* ```
|
|
404
|
+
*/
|
|
405
|
+
declare function createSessionAuthProvider<TUser = unknown>(config: SessionAuthConfig<TUser>): SessionAuthProvider<TUser>;
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* @zh 服务器认证 Mixin
|
|
409
|
+
* @en Server authentication mixin
|
|
410
|
+
*/
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* @zh 获取连接的认证上下文
|
|
414
|
+
* @en Get auth context for connection
|
|
415
|
+
*/
|
|
416
|
+
declare function getAuthContext<TUser = unknown>(conn: ServerConnection): IAuthContext<TUser> | null;
|
|
417
|
+
/**
|
|
418
|
+
* @zh 设置连接的认证上下文
|
|
419
|
+
* @en Set auth context for connection
|
|
420
|
+
*/
|
|
421
|
+
declare function setAuthContext<TUser = unknown>(conn: ServerConnection, context: IAuthContext<TUser>): void;
|
|
422
|
+
/**
|
|
423
|
+
* @zh 包装服务器添加认证功能
|
|
424
|
+
* @en Wrap server with authentication functionality
|
|
425
|
+
*
|
|
426
|
+
* @zh 使用 mixin 模式为服务器添加认证能力,不修改原始服务器
|
|
427
|
+
* @en Uses mixin pattern to add authentication to server without modifying original
|
|
428
|
+
*
|
|
429
|
+
* @example
|
|
430
|
+
* ```typescript
|
|
431
|
+
* import { createServer } from '@esengine/server';
|
|
432
|
+
* import { withAuth, createJwtAuthProvider } from '@esengine/server/auth';
|
|
433
|
+
*
|
|
434
|
+
* const jwtProvider = createJwtAuthProvider({
|
|
435
|
+
* secret: 'your-secret-key',
|
|
436
|
+
* expiresIn: 3600,
|
|
437
|
+
* });
|
|
438
|
+
*
|
|
439
|
+
* const server = withAuth(await createServer({ port: 3000 }), {
|
|
440
|
+
* provider: jwtProvider,
|
|
441
|
+
* extractCredentials: (req) => {
|
|
442
|
+
* const url = new URL(req.url, 'http://localhost');
|
|
443
|
+
* return url.searchParams.get('token');
|
|
444
|
+
* },
|
|
445
|
+
* onAuthSuccess: (conn, user) => {
|
|
446
|
+
* console.log(`User ${user.name} authenticated`);
|
|
447
|
+
* },
|
|
448
|
+
* onAuthFailure: (conn, error) => {
|
|
449
|
+
* console.log(`Auth failed: ${error.error}`);
|
|
450
|
+
* }
|
|
451
|
+
* });
|
|
452
|
+
*
|
|
453
|
+
* await server.start();
|
|
454
|
+
* ```
|
|
455
|
+
*/
|
|
456
|
+
declare function withAuth<TUser = unknown>(server: GameServer, config: AuthServerConfig<TUser>): AuthGameServer<TUser>;
|
|
457
|
+
/**
|
|
458
|
+
* @zh 创建认证中间件
|
|
459
|
+
* @en Create authentication middleware
|
|
460
|
+
*
|
|
461
|
+
* @zh 用于在 API 处理器中检查认证状态
|
|
462
|
+
* @en Used to check authentication status in API handlers
|
|
463
|
+
*/
|
|
464
|
+
declare function requireAuthentication<TUser = unknown>(conn: ServerConnection, options?: {
|
|
465
|
+
errorMessage?: string;
|
|
466
|
+
}): IAuthContext<TUser>;
|
|
467
|
+
/**
|
|
468
|
+
* @zh 创建角色检查中间件
|
|
469
|
+
* @en Create role check middleware
|
|
470
|
+
*/
|
|
471
|
+
declare function requireRole$1<TUser = unknown>(conn: ServerConnection, roles: string | string[], options?: {
|
|
472
|
+
mode?: 'any' | 'all';
|
|
473
|
+
errorMessage?: string;
|
|
474
|
+
}): IAuthContext<TUser>;
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* @zh 房间认证 Mixin
|
|
478
|
+
* @en Room authentication mixin
|
|
479
|
+
*/
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* @zh 带认证的玩家
|
|
483
|
+
* @en Player with authentication
|
|
484
|
+
*/
|
|
485
|
+
interface AuthPlayer<TUser = unknown, TData = Record<string, unknown>> extends Player<TData> {
|
|
486
|
+
/**
|
|
487
|
+
* @zh 认证上下文
|
|
488
|
+
* @en Authentication context
|
|
489
|
+
*/
|
|
490
|
+
readonly auth: IAuthContext<TUser>;
|
|
491
|
+
/**
|
|
492
|
+
* @zh 用户信息(快捷访问)
|
|
493
|
+
* @en User info (shortcut)
|
|
494
|
+
*/
|
|
495
|
+
readonly user: TUser | null;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* @zh 带认证的房间接口
|
|
499
|
+
* @en Room with authentication interface
|
|
500
|
+
*/
|
|
501
|
+
interface IAuthRoom<TUser = unknown> {
|
|
502
|
+
/**
|
|
503
|
+
* @zh 认证钩子(在 onJoin 之前调用)
|
|
504
|
+
* @en Auth hook (called before onJoin)
|
|
505
|
+
*/
|
|
506
|
+
onAuth?(player: AuthPlayer<TUser>): boolean | Promise<boolean>;
|
|
507
|
+
/**
|
|
508
|
+
* @zh 获取带认证信息的玩家
|
|
509
|
+
* @en Get player with auth info
|
|
510
|
+
*/
|
|
511
|
+
getAuthPlayer(id: string): AuthPlayer<TUser> | undefined;
|
|
512
|
+
/**
|
|
513
|
+
* @zh 获取所有带认证信息的玩家
|
|
514
|
+
* @en Get all players with auth info
|
|
515
|
+
*/
|
|
516
|
+
getAuthPlayers(): AuthPlayer<TUser>[];
|
|
517
|
+
/**
|
|
518
|
+
* @zh 按角色获取玩家
|
|
519
|
+
* @en Get players by role
|
|
520
|
+
*/
|
|
521
|
+
getPlayersByRole(role: string): AuthPlayer<TUser>[];
|
|
522
|
+
/**
|
|
523
|
+
* @zh 按用户 ID 获取玩家
|
|
524
|
+
* @en Get player by user ID
|
|
525
|
+
*/
|
|
526
|
+
getPlayerByUserId(userId: string): AuthPlayer<TUser> | undefined;
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* @zh 认证房间构造器类型
|
|
530
|
+
* @en Auth room constructor type
|
|
531
|
+
*/
|
|
532
|
+
type AuthRoomClass<TUser = unknown> = new (...args: any[]) => Room & IAuthRoom<TUser>;
|
|
533
|
+
/**
|
|
534
|
+
* @zh 包装房间类添加认证功能
|
|
535
|
+
* @en Wrap room class with authentication functionality
|
|
536
|
+
*
|
|
537
|
+
* @zh 使用 mixin 模式为房间添加认证检查,在玩家加入前验证认证状态
|
|
538
|
+
* @en Uses mixin pattern to add auth checks to room, validates auth before player joins
|
|
539
|
+
*
|
|
540
|
+
* @example
|
|
541
|
+
* ```typescript
|
|
542
|
+
* import { Room, onMessage } from '@esengine/server';
|
|
543
|
+
* import { withRoomAuth, type AuthPlayer } from '@esengine/server/auth';
|
|
544
|
+
*
|
|
545
|
+
* interface User {
|
|
546
|
+
* id: string;
|
|
547
|
+
* name: string;
|
|
548
|
+
* roles: string[];
|
|
549
|
+
* }
|
|
550
|
+
*
|
|
551
|
+
* class GameRoom extends withRoomAuth<User>(Room, {
|
|
552
|
+
* requireAuth: true,
|
|
553
|
+
* allowedRoles: ['player', 'premium'],
|
|
554
|
+
* }) {
|
|
555
|
+
* onJoin(player: AuthPlayer<User>) {
|
|
556
|
+
* console.log(`${player.user?.name} joined the game`);
|
|
557
|
+
* this.broadcast('PlayerJoined', {
|
|
558
|
+
* id: player.id,
|
|
559
|
+
* name: player.user?.name
|
|
560
|
+
* });
|
|
561
|
+
* }
|
|
562
|
+
*
|
|
563
|
+
* // Optional: custom auth validation
|
|
564
|
+
* async onAuth(player: AuthPlayer<User>): Promise<boolean> {
|
|
565
|
+
* // Additional validation logic
|
|
566
|
+
* if (player.auth.hasRole('banned')) {
|
|
567
|
+
* return false;
|
|
568
|
+
* }
|
|
569
|
+
* return true;
|
|
570
|
+
* }
|
|
571
|
+
*
|
|
572
|
+
* @onMessage('Chat')
|
|
573
|
+
* handleChat(data: { text: string }, player: AuthPlayer<User>) {
|
|
574
|
+
* this.broadcast('Chat', {
|
|
575
|
+
* from: player.user?.name ?? 'Guest',
|
|
576
|
+
* text: data.text
|
|
577
|
+
* });
|
|
578
|
+
* }
|
|
579
|
+
* }
|
|
580
|
+
* ```
|
|
581
|
+
*/
|
|
582
|
+
declare function withRoomAuth<TUser = unknown, TBase extends new (...args: any[]) => Room = new (...args: any[]) => Room>(Base: TBase, config?: AuthRoomConfig): TBase & (new (...args: any[]) => IAuthRoom<TUser>);
|
|
583
|
+
/**
|
|
584
|
+
* @zh 抽象认证房间基类
|
|
585
|
+
* @en Abstract auth room base class
|
|
586
|
+
*
|
|
587
|
+
* @zh 如果不想使用 mixin,可以直接继承此类
|
|
588
|
+
* @en If you don't want to use mixin, you can extend this class directly
|
|
589
|
+
*
|
|
590
|
+
* @example
|
|
591
|
+
* ```typescript
|
|
592
|
+
* import { AuthRoomBase } from '@esengine/server/auth';
|
|
593
|
+
*
|
|
594
|
+
* class GameRoom extends AuthRoomBase<User> {
|
|
595
|
+
* protected readonly authConfig = {
|
|
596
|
+
* requireAuth: true,
|
|
597
|
+
* allowedRoles: ['player']
|
|
598
|
+
* };
|
|
599
|
+
*
|
|
600
|
+
* onJoin(player: AuthPlayer<User>) {
|
|
601
|
+
* // player has .auth and .user properties
|
|
602
|
+
* }
|
|
603
|
+
* }
|
|
604
|
+
* ```
|
|
605
|
+
*/
|
|
606
|
+
declare abstract class AuthRoomBase<TUser = unknown, TState = any, TPlayerData = Record<string, unknown>> implements IAuthRoom<TUser> {
|
|
607
|
+
/**
|
|
608
|
+
* @zh 认证配置(子类可覆盖)
|
|
609
|
+
* @en Auth config (can be overridden by subclass)
|
|
610
|
+
*/
|
|
611
|
+
protected readonly authConfig: AuthRoomConfig;
|
|
612
|
+
/**
|
|
613
|
+
* @zh 认证钩子
|
|
614
|
+
* @en Auth hook
|
|
615
|
+
*/
|
|
616
|
+
onAuth?(player: AuthPlayer<TUser>): boolean | Promise<boolean>;
|
|
617
|
+
getAuthPlayer(id: string): AuthPlayer<TUser> | undefined;
|
|
618
|
+
getAuthPlayers(): AuthPlayer<TUser>[];
|
|
619
|
+
getPlayersByRole(role: string): AuthPlayer<TUser>[];
|
|
620
|
+
getPlayerByUserId(userId: string): AuthPlayer<TUser> | undefined;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* @zh requireAuth 装饰器
|
|
625
|
+
* @en requireAuth decorator
|
|
626
|
+
*/
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* @zh 认证元数据键
|
|
630
|
+
* @en Auth metadata key
|
|
631
|
+
*/
|
|
632
|
+
declare const AUTH_METADATA_KEY: unique symbol;
|
|
633
|
+
/**
|
|
634
|
+
* @zh 认证元数据
|
|
635
|
+
* @en Auth metadata
|
|
636
|
+
*/
|
|
637
|
+
interface AuthMetadata {
|
|
638
|
+
requireAuth: boolean;
|
|
639
|
+
options?: RequireAuthOptions;
|
|
640
|
+
roles?: string[];
|
|
641
|
+
roleMode?: 'any' | 'all';
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* @zh 获取方法的认证元数据
|
|
645
|
+
* @en Get auth metadata for method
|
|
646
|
+
*/
|
|
647
|
+
declare function getAuthMetadata(target: any, propertyKey: string): AuthMetadata | undefined;
|
|
648
|
+
/**
|
|
649
|
+
* @zh 要求认证装饰器
|
|
650
|
+
* @en Require authentication decorator
|
|
651
|
+
*
|
|
652
|
+
* @zh 标记方法需要认证才能访问,用于消息处理器
|
|
653
|
+
* @en Marks method as requiring authentication, used for message handlers
|
|
654
|
+
*
|
|
655
|
+
* @example
|
|
656
|
+
* ```typescript
|
|
657
|
+
* class GameRoom extends withRoomAuth(Room) {
|
|
658
|
+
* @requireAuth()
|
|
659
|
+
* @onMessage('Trade')
|
|
660
|
+
* handleTrade(data: TradeData, player: AuthPlayer) {
|
|
661
|
+
* // Only authenticated players can trade
|
|
662
|
+
* }
|
|
663
|
+
*
|
|
664
|
+
* @requireAuth({ allowGuest: true })
|
|
665
|
+
* @onMessage('Chat')
|
|
666
|
+
* handleChat(data: ChatData, player: AuthPlayer) {
|
|
667
|
+
* // Guests can also chat
|
|
668
|
+
* }
|
|
669
|
+
* }
|
|
670
|
+
* ```
|
|
671
|
+
*/
|
|
672
|
+
declare function requireAuth(options?: RequireAuthOptions): MethodDecorator;
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* @zh requireRole 装饰器
|
|
676
|
+
* @en requireRole decorator
|
|
677
|
+
*/
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* @zh 要求角色装饰器
|
|
681
|
+
* @en Require role decorator
|
|
682
|
+
*
|
|
683
|
+
* @zh 标记方法需要特定角色才能访问
|
|
684
|
+
* @en Marks method as requiring specific role(s)
|
|
685
|
+
*
|
|
686
|
+
* @example
|
|
687
|
+
* ```typescript
|
|
688
|
+
* class AdminRoom extends withRoomAuth(Room) {
|
|
689
|
+
* @requireRole('admin')
|
|
690
|
+
* @onMessage('Ban')
|
|
691
|
+
* handleBan(data: BanData, player: AuthPlayer) {
|
|
692
|
+
* // Only admins can ban
|
|
693
|
+
* }
|
|
694
|
+
*
|
|
695
|
+
* @requireRole(['moderator', 'admin'])
|
|
696
|
+
* @onMessage('Mute')
|
|
697
|
+
* handleMute(data: MuteData, player: AuthPlayer) {
|
|
698
|
+
* // Moderators or admins can mute
|
|
699
|
+
* }
|
|
700
|
+
*
|
|
701
|
+
* @requireRole(['verified', 'premium'], { mode: 'all' })
|
|
702
|
+
* @onMessage('SpecialFeature')
|
|
703
|
+
* handleSpecial(data: any, player: AuthPlayer) {
|
|
704
|
+
* // Requires both verified AND premium roles
|
|
705
|
+
* }
|
|
706
|
+
* }
|
|
707
|
+
* ```
|
|
708
|
+
*/
|
|
709
|
+
declare function requireRole(roles: string | string[], options?: RequireRoleOptions): MethodDecorator;
|
|
710
|
+
|
|
711
|
+
export { AUTH_METADATA_KEY, AuthContext, AuthGameServer, type AuthMetadata, type AuthPlayer, AuthResult, AuthRoomBase, type AuthRoomClass, AuthRoomConfig, AuthServerConfig, IAuthContext, IAuthProvider, type IAuthRoom, type ISessionStorage, type JwtAuthConfig, JwtAuthProvider, type JwtPayload, RequireAuthOptions, RequireRoleOptions, type SessionAuthConfig, SessionAuthProvider, type SessionData, type UserInfoExtractor, createAuthContext, createGuestContext, createJwtAuthProvider, createSessionAuthProvider, defaultUserExtractor, getAuthContext, getAuthMetadata, requireAuth, requireAuthentication, requireRole, requireRole$1 as requireRoleCheck, setAuthContext, withAuth, withRoomAuth };
|