@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 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/auth/context.ts","../../src/auth/providers/JwtAuthProvider.ts","../../src/auth/providers/SessionAuthProvider.ts","../../src/auth/mixin/withAuth.ts","../../src/auth/mixin/withRoomAuth.ts","../../src/auth/decorators/requireAuth.ts","../../src/auth/decorators/requireRole.ts"],"names":["defaultUserExtractor","getId","user","u","id","String","userId","sub","getRoles","Array","isArray","roles","filter","r","role","AuthContext","extractor","_isAuthenticated","_user","_userId","_roles","_authenticatedAt","_expiresAt","_extractor","isAuthenticated","Date","now","authenticatedAt","expiresAt","hasRole","includes","hasAnyRole","some","hasAllRoles","every","setAuthenticated","result","success","clear","createGuestContext","createAuthContext","context","JwtAuthProvider","config","name","_config","algorithm","expiresIn","verify","token","error","errorCode","verifyOptions","algorithms","issuer","audience","payload","secret","getUser","exp","undefined","err","message","refresh","decode","iat","nbf","restPayload","newToken","sign","signOptions","createJwtAuthProvider","SessionAuthProvider","sessionTTL","prefix","autoRenew","_getKey","sessionId","key","session","storage","get","validateUser","isValid","lastActiveAt","set","createdAt","revoke","delete","createSession","data","_generateSessionId","getSession","updateSession","randomBytes","toString","createSessionAuthProvider","AUTH_CONTEXT_KEY","getAuthContext","conn","setAuthContext","withAuth","server","provider","extractCredentials","autoAuthOnConnect","disconnectOnAuthFailure","onAuthSuccess","onAuthFailure","originalConnections","connections","connectionAuthMap","WeakMap","authServer","authProvider","authenticate","credentials","authContext","originalOnConnect","_onConnect","req","connReq","close","console","originalOnDisconnect","_onDisconnect","requireAuthentication","options","auth","Error","errorMessage","requireRole","roleArray","mode","playerAuthContexts","wrapPlayerWithAuth","player","Object","defineProperty","enumerable","configurable","withRoomAuth","Base","requireAuth","allowedRoles","roleCheckMode","AuthRoom","args","_originalOnJoin","onJoin","bind","_authOnJoin","connection","_conn","warn","kick","length","authPlayer","onAuth","allowed","getAuthPlayer","getPlayer","getAuthPlayers","players","getPlayersByRole","p","getPlayerByUserId","find","AuthRoomBase","authConfig","AUTH_METADATA_KEY","getAuthMetadata","target","propertyKey","metadata","setAuthMetadata","Map","descriptor","existing","roleMode"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @zh 认证上下文实现\n * @en Authentication context implementation\n */\n\nimport type { IAuthContext, AuthResult } from './types.js';\n\n/**\n * @zh 用户信息提取器\n * @en User info extractor\n */\nexport interface UserInfoExtractor<TUser> {\n /**\n * @zh 提取用户 ID\n * @en Extract user ID\n */\n getId(user: TUser): string;\n\n /**\n * @zh 提取用户角色\n * @en Extract user roles\n */\n getRoles(user: TUser): string[];\n}\n\n/**\n * @zh 默认用户信息提取器\n * @en Default user info extractor\n */\nexport const defaultUserExtractor: UserInfoExtractor<unknown> = {\n getId(user: unknown): string {\n if (user && typeof user === 'object') {\n const u = user as Record<string, unknown>;\n if (typeof u.id === 'string') return u.id;\n if (typeof u.id === 'number') return String(u.id);\n if (typeof u.userId === 'string') return u.userId;\n if (typeof u.userId === 'number') return String(u.userId);\n if (typeof u.sub === 'string') return u.sub;\n }\n return '';\n },\n\n getRoles(user: unknown): string[] {\n if (user && typeof user === 'object') {\n const u = user as Record<string, unknown>;\n if (Array.isArray(u.roles)) {\n return u.roles.filter((r): r is string => typeof r === 'string');\n }\n if (typeof u.role === 'string') {\n return [u.role];\n }\n }\n return [];\n }\n};\n\n/**\n * @zh 认证上下文\n * @en Authentication context\n *\n * @zh 存储连接的认证状态\n * @en Stores authentication state for a connection\n */\nexport class AuthContext<TUser = unknown> implements IAuthContext<TUser> {\n private _isAuthenticated: boolean = false;\n private _user: TUser | null = null;\n private _userId: string | null = null;\n private _roles: string[] = [];\n private _authenticatedAt: number | null = null;\n private _expiresAt: number | null = null;\n private _extractor: UserInfoExtractor<TUser>;\n\n constructor(extractor?: UserInfoExtractor<TUser>) {\n this._extractor = (extractor ?? defaultUserExtractor) as UserInfoExtractor<TUser>;\n }\n\n /**\n * @zh 是否已认证\n * @en Whether authenticated\n */\n get isAuthenticated(): boolean {\n if (this._expiresAt && Date.now() > this._expiresAt) {\n return false;\n }\n return this._isAuthenticated;\n }\n\n /**\n * @zh 用户信息\n * @en User information\n */\n get user(): TUser | null {\n return this._user;\n }\n\n /**\n * @zh 用户 ID\n * @en User ID\n */\n get userId(): string | null {\n return this._userId;\n }\n\n /**\n * @zh 用户角色\n * @en User roles\n */\n get roles(): ReadonlyArray<string> {\n return this._roles;\n }\n\n /**\n * @zh 认证时间\n * @en Authentication timestamp\n */\n get authenticatedAt(): number | null {\n return this._authenticatedAt;\n }\n\n /**\n * @zh 令牌过期时间\n * @en Token expiration time\n */\n get expiresAt(): number | null {\n return this._expiresAt;\n }\n\n /**\n * @zh 检查是否有指定角色\n * @en Check if has specified role\n */\n hasRole(role: string): boolean {\n return this._roles.includes(role);\n }\n\n /**\n * @zh 检查是否有任一指定角色\n * @en Check if has any of specified roles\n */\n hasAnyRole(roles: string[]): boolean {\n return roles.some(role => this._roles.includes(role));\n }\n\n /**\n * @zh 检查是否有所有指定角色\n * @en Check if has all specified roles\n */\n hasAllRoles(roles: string[]): boolean {\n return roles.every(role => this._roles.includes(role));\n }\n\n /**\n * @zh 设置认证结果\n * @en Set authentication result\n */\n setAuthenticated(result: AuthResult<TUser>): void {\n if (result.success && result.user) {\n this._isAuthenticated = true;\n this._user = result.user;\n this._userId = this._extractor.getId(result.user);\n this._roles = this._extractor.getRoles(result.user);\n this._authenticatedAt = Date.now();\n this._expiresAt = result.expiresAt ?? null;\n } else {\n this.clear();\n }\n }\n\n /**\n * @zh 清除认证状态\n * @en Clear authentication state\n */\n clear(): void {\n this._isAuthenticated = false;\n this._user = null;\n this._userId = null;\n this._roles = [];\n this._authenticatedAt = null;\n this._expiresAt = null;\n }\n}\n\n/**\n * @zh 创建访客认证上下文\n * @en Create guest auth context\n */\nexport function createGuestContext<TUser = unknown>(): IAuthContext<TUser> {\n return new AuthContext<TUser>();\n}\n\n/**\n * @zh 从认证结果创建认证上下文\n * @en Create auth context from auth result\n */\nexport function createAuthContext<TUser = unknown>(\n result: AuthResult<TUser>,\n extractor?: UserInfoExtractor<TUser>\n): AuthContext<TUser> {\n const context = new AuthContext<TUser>(extractor);\n context.setAuthenticated(result);\n return context;\n}\n","/**\n * @zh JWT 认证提供者\n * @en JWT authentication provider\n */\n\nimport type { IAuthProvider, AuthResult, AuthErrorCode } from '../types.js';\nimport * as jwt from 'jsonwebtoken';\n\n/**\n * @zh JWT 载荷\n * @en JWT payload\n */\nexport interface JwtPayload {\n /**\n * @zh 主题(用户 ID)\n * @en Subject (user ID)\n */\n sub?: string;\n\n /**\n * @zh 签发时间\n * @en Issued at\n */\n iat?: number;\n\n /**\n * @zh 过期时间\n * @en Expiration time\n */\n exp?: number;\n\n /**\n * @zh 自定义字段\n * @en Custom fields\n */\n [key: string]: unknown;\n}\n\n/**\n * @zh JWT 认证配置\n * @en JWT authentication configuration\n */\nexport interface JwtAuthConfig<TUser = unknown> {\n /**\n * @zh 密钥\n * @en Secret key\n */\n secret: string;\n\n /**\n * @zh 算法\n * @en Algorithm\n * @defaultValue 'HS256'\n */\n algorithm?: 'HS256' | 'HS384' | 'HS512' | 'RS256' | 'RS384' | 'RS512';\n\n /**\n * @zh 令牌过期时间(秒)\n * @en Token expiration in seconds\n * @defaultValue 3600\n */\n expiresIn?: number;\n\n /**\n * @zh 从载荷获取用户信息\n * @en Get user from payload\n */\n getUser?: (payload: JwtPayload) => TUser | Promise<TUser | null> | null;\n\n /**\n * @zh 签发者\n * @en Issuer\n */\n issuer?: string;\n\n /**\n * @zh 受众\n * @en Audience\n */\n audience?: string;\n}\n\n/**\n * @zh JWT 认证提供者\n * @en JWT authentication provider\n *\n * @zh 使用 jsonwebtoken 库实现 JWT 认证\n * @en Uses jsonwebtoken library for JWT authentication\n *\n * @example\n * ```typescript\n * const jwtProvider = createJwtAuthProvider({\n * secret: 'your-secret-key',\n * expiresIn: 3600,\n * getUser: async (payload) => {\n * return await db.users.findById(payload.sub);\n * }\n * });\n * ```\n */\nexport class JwtAuthProvider<TUser = unknown> implements IAuthProvider<TUser, string> {\n readonly name = 'jwt';\n\n private _config: Required<Pick<JwtAuthConfig<TUser>, 'secret' | 'algorithm' | 'expiresIn'>> & JwtAuthConfig<TUser>;\n\n constructor(config: JwtAuthConfig<TUser>) {\n this._config = {\n algorithm: 'HS256',\n expiresIn: 3600,\n ...config\n };\n }\n\n /**\n * @zh 验证令牌\n * @en Verify token\n */\n async verify(token: string): Promise<AuthResult<TUser>> {\n if (!token) {\n return {\n success: false,\n error: 'Token is required',\n errorCode: 'INVALID_TOKEN'\n };\n }\n\n try {\n const verifyOptions: jwt.VerifyOptions = {\n algorithms: [this._config.algorithm]\n };\n if (this._config.issuer) {\n verifyOptions.issuer = this._config.issuer;\n }\n if (this._config.audience) {\n verifyOptions.audience = this._config.audience;\n }\n const payload = jwt.verify(token, this._config.secret, verifyOptions) as JwtPayload;\n\n let user: TUser | null = null;\n\n if (this._config.getUser) {\n user = await this._config.getUser(payload);\n if (!user) {\n return {\n success: false,\n error: 'User not found',\n errorCode: 'USER_NOT_FOUND'\n };\n }\n } else {\n user = payload as unknown as TUser;\n }\n\n return {\n success: true,\n user,\n token,\n expiresAt: payload.exp ? payload.exp * 1000 : undefined\n };\n } catch (error) {\n const err = error as Error;\n\n if (err.name === 'TokenExpiredError') {\n return {\n success: false,\n error: 'Token has expired',\n errorCode: 'EXPIRED_TOKEN'\n };\n }\n\n return {\n success: false,\n error: err.message || 'Invalid token',\n errorCode: 'INVALID_TOKEN'\n };\n }\n }\n\n /**\n * @zh 刷新令牌\n * @en Refresh token\n */\n async refresh(token: string): Promise<AuthResult<TUser>> {\n const result = await this.verify(token);\n\n if (!result.success || !result.user) {\n return result;\n }\n\n const payload = jwt.decode(token) as JwtPayload;\n\n // Remove JWT standard claims that will be regenerated\n const { iat, exp, nbf, ...restPayload } = payload;\n\n const newToken = this.sign(restPayload);\n\n return {\n success: true,\n user: result.user,\n token: newToken,\n expiresAt: Date.now() + this._config.expiresIn * 1000\n };\n }\n\n /**\n * @zh 生成令牌\n * @en Generate token\n */\n sign(payload: Record<string, unknown>): string {\n const signOptions: jwt.SignOptions = {\n algorithm: this._config.algorithm,\n expiresIn: this._config.expiresIn\n };\n if (this._config.issuer) {\n signOptions.issuer = this._config.issuer;\n }\n if (this._config.audience) {\n signOptions.audience = this._config.audience;\n }\n return jwt.sign(payload, this._config.secret, signOptions);\n }\n\n /**\n * @zh 解码令牌(不验证)\n * @en Decode token (without verification)\n */\n decode(token: string): JwtPayload | null {\n return jwt.decode(token) as JwtPayload | null;\n }\n}\n\n/**\n * @zh 创建 JWT 认证提供者\n * @en Create JWT authentication provider\n *\n * @example\n * ```typescript\n * import { createJwtAuthProvider } from '@esengine/server/auth';\n *\n * const jwtProvider = createJwtAuthProvider({\n * secret: process.env.JWT_SECRET!,\n * expiresIn: 3600,\n * getUser: async (payload) => {\n * return { id: payload.sub, name: payload.name };\n * }\n * });\n * ```\n */\nexport function createJwtAuthProvider<TUser = unknown>(\n config: JwtAuthConfig<TUser>\n): JwtAuthProvider<TUser> {\n return new JwtAuthProvider<TUser>(config);\n}\n","/**\n * @zh Session 认证提供者\n * @en Session authentication provider\n */\n\nimport { randomBytes } from 'crypto';\nimport type { IAuthProvider, AuthResult } from '../types.js';\n\n/**\n * @zh Session 存储接口(兼容 ITransactionStorage)\n * @en Session storage interface (compatible with ITransactionStorage)\n */\nexport interface ISessionStorage {\n get<T>(key: string): Promise<T | null>;\n set<T>(key: string, value: T, ttl?: number): Promise<void>;\n delete(key: string): Promise<boolean>;\n}\n\n/**\n * @zh Session 数据\n * @en Session data\n */\nexport interface SessionData<TUser = unknown> {\n /**\n * @zh 用户信息\n * @en User information\n */\n user: TUser;\n\n /**\n * @zh 创建时间\n * @en Created at\n */\n createdAt: number;\n\n /**\n * @zh 最后活跃时间\n * @en Last active at\n */\n lastActiveAt: number;\n\n /**\n * @zh 自定义数据\n * @en Custom data\n */\n data?: Record<string, unknown>;\n}\n\n/**\n * @zh Session 认证配置\n * @en Session authentication configuration\n */\nexport interface SessionAuthConfig<TUser = unknown> {\n /**\n * @zh Session 存储\n * @en Session storage\n */\n storage: ISessionStorage;\n\n /**\n * @zh Session 过期时间(毫秒)\n * @en Session expiration in milliseconds\n * @defaultValue 86400000 (24h)\n */\n sessionTTL?: number;\n\n /**\n * @zh Session 键前缀\n * @en Session key prefix\n * @defaultValue 'session:'\n */\n prefix?: string;\n\n /**\n * @zh 验证用户(可选额外验证)\n * @en Validate user (optional extra validation)\n */\n validateUser?: (user: TUser) => boolean | Promise<boolean>;\n\n /**\n * @zh 是否自动续期\n * @en Auto renew session\n * @defaultValue true\n */\n autoRenew?: boolean;\n}\n\n/**\n * @zh Session 认证提供者\n * @en Session authentication provider\n *\n * @zh 基于存储的会话认证,支持 Redis、MongoDB 等后端\n * @en Storage-based session authentication, supports Redis, MongoDB, etc.\n *\n * @example\n * ```typescript\n * import { createSessionAuthProvider } from '@esengine/server/auth';\n * import { createRedisStorage } from '@esengine/transaction';\n *\n * const sessionProvider = createSessionAuthProvider({\n * storage: createRedisStorage({ factory: () => new Redis() }),\n * sessionTTL: 86400000, // 24 hours\n * });\n * ```\n */\nexport class SessionAuthProvider<TUser = unknown> implements IAuthProvider<TUser, string> {\n readonly name = 'session';\n\n private _config: Required<Pick<SessionAuthConfig<TUser>, 'sessionTTL' | 'prefix' | 'autoRenew'>> & SessionAuthConfig<TUser>;\n\n constructor(config: SessionAuthConfig<TUser>) {\n this._config = {\n sessionTTL: 86400000,\n prefix: 'session:',\n autoRenew: true,\n ...config\n };\n }\n\n /**\n * @zh 获取存储键\n * @en Get storage key\n */\n private _getKey(sessionId: string): string {\n return `${this._config.prefix}${sessionId}`;\n }\n\n /**\n * @zh 验证 Session\n * @en Verify session\n */\n async verify(sessionId: string): Promise<AuthResult<TUser>> {\n if (!sessionId) {\n return {\n success: false,\n error: 'Session ID is required',\n errorCode: 'INVALID_TOKEN'\n };\n }\n\n const key = this._getKey(sessionId);\n const session = await this._config.storage.get<SessionData<TUser>>(key);\n\n if (!session) {\n return {\n success: false,\n error: 'Session not found or expired',\n errorCode: 'EXPIRED_TOKEN'\n };\n }\n\n if (this._config.validateUser) {\n const isValid = await this._config.validateUser(session.user);\n if (!isValid) {\n return {\n success: false,\n error: 'User validation failed',\n errorCode: 'ACCOUNT_DISABLED'\n };\n }\n }\n\n if (this._config.autoRenew) {\n session.lastActiveAt = Date.now();\n await this._config.storage.set(key, session, this._config.sessionTTL);\n }\n\n return {\n success: true,\n user: session.user,\n token: sessionId,\n expiresAt: session.createdAt + this._config.sessionTTL\n };\n }\n\n /**\n * @zh 刷新 Session\n * @en Refresh session\n */\n async refresh(sessionId: string): Promise<AuthResult<TUser>> {\n const result = await this.verify(sessionId);\n\n if (!result.success) {\n return result;\n }\n\n const key = this._getKey(sessionId);\n const session = await this._config.storage.get<SessionData<TUser>>(key);\n\n if (session) {\n session.lastActiveAt = Date.now();\n await this._config.storage.set(key, session, this._config.sessionTTL);\n }\n\n return {\n ...result,\n expiresAt: Date.now() + this._config.sessionTTL\n };\n }\n\n /**\n * @zh 撤销 Session\n * @en Revoke session\n */\n async revoke(sessionId: string): Promise<boolean> {\n const key = this._getKey(sessionId);\n return await this._config.storage.delete(key);\n }\n\n /**\n * @zh 创建 Session\n * @en Create session\n */\n async createSession(user: TUser, data?: Record<string, unknown>): Promise<string> {\n const sessionId = this._generateSessionId();\n const key = this._getKey(sessionId);\n\n const session: SessionData<TUser> = {\n user,\n createdAt: Date.now(),\n lastActiveAt: Date.now(),\n data\n };\n\n await this._config.storage.set(key, session, this._config.sessionTTL);\n\n return sessionId;\n }\n\n /**\n * @zh 获取 Session 数据\n * @en Get session data\n */\n async getSession(sessionId: string): Promise<SessionData<TUser> | null> {\n const key = this._getKey(sessionId);\n return await this._config.storage.get<SessionData<TUser>>(key);\n }\n\n /**\n * @zh 更新 Session 数据\n * @en Update session data\n */\n async updateSession(sessionId: string, data: Record<string, unknown>): Promise<boolean> {\n const key = this._getKey(sessionId);\n const session = await this._config.storage.get<SessionData<TUser>>(key);\n\n if (!session) {\n return false;\n }\n\n session.data = { ...session.data, ...data };\n session.lastActiveAt = Date.now();\n await this._config.storage.set(key, session, this._config.sessionTTL);\n\n return true;\n }\n\n /**\n * @zh 生成 Session ID(使用加密安全的随机数)\n * @en Generate session ID (using cryptographically secure random)\n */\n private _generateSessionId(): string {\n return randomBytes(32).toString('hex');\n }\n}\n\n/**\n * @zh 创建 Session 认证提供者\n * @en Create session authentication provider\n *\n * @example\n * ```typescript\n * import { createSessionAuthProvider } from '@esengine/server/auth';\n * import { MemoryStorage } from '@esengine/transaction';\n *\n * const sessionProvider = createSessionAuthProvider({\n * storage: new MemoryStorage(),\n * sessionTTL: 3600000, // 1 hour\n * });\n *\n * // Create a session\n * const sessionId = await sessionProvider.createSession({ id: '1', name: 'Alice' });\n *\n * // Verify session\n * const result = await sessionProvider.verify(sessionId);\n * ```\n */\nexport function createSessionAuthProvider<TUser = unknown>(\n config: SessionAuthConfig<TUser>\n): SessionAuthProvider<TUser> {\n return new SessionAuthProvider<TUser>(config);\n}\n","/**\n * @zh 服务器认证 Mixin\n * @en Server authentication mixin\n */\n\nimport type { ServerConnection, GameServer } from '../../types/index.js';\nimport type {\n IAuthProvider,\n AuthResult,\n AuthServerConfig,\n AuthGameServer,\n IAuthContext,\n ConnectionRequest\n} from '../types.js';\nimport { AuthContext } from '../context.js';\n\n/**\n * @zh 认证数据键\n * @en Auth data key\n */\nconst AUTH_CONTEXT_KEY = Symbol('authContext');\n\n/**\n * @zh 获取连接的认证上下文\n * @en Get auth context for connection\n */\nexport function getAuthContext<TUser = unknown>(conn: ServerConnection): IAuthContext<TUser> | null {\n const data = conn.data as Record<symbol, unknown>;\n return (data[AUTH_CONTEXT_KEY] as IAuthContext<TUser>) ?? null;\n}\n\n/**\n * @zh 设置连接的认证上下文\n * @en Set auth context for connection\n */\nexport function setAuthContext<TUser = unknown>(conn: ServerConnection, context: IAuthContext<TUser>): void {\n const data = conn.data as Record<symbol, unknown>;\n data[AUTH_CONTEXT_KEY] = context;\n}\n\n/**\n * @zh 包装服务器添加认证功能\n * @en Wrap server with authentication functionality\n *\n * @zh 使用 mixin 模式为服务器添加认证能力,不修改原始服务器\n * @en Uses mixin pattern to add authentication to server without modifying original\n *\n * @example\n * ```typescript\n * import { createServer } from '@esengine/server';\n * import { withAuth, createJwtAuthProvider } from '@esengine/server/auth';\n *\n * const jwtProvider = createJwtAuthProvider({\n * secret: 'your-secret-key',\n * expiresIn: 3600,\n * });\n *\n * const server = withAuth(await createServer({ port: 3000 }), {\n * provider: jwtProvider,\n * extractCredentials: (req) => {\n * const url = new URL(req.url, 'http://localhost');\n * return url.searchParams.get('token');\n * },\n * onAuthSuccess: (conn, user) => {\n * console.log(`User ${user.name} authenticated`);\n * },\n * onAuthFailure: (conn, error) => {\n * console.log(`Auth failed: ${error.error}`);\n * }\n * });\n *\n * await server.start();\n * ```\n */\nexport function withAuth<TUser = unknown>(\n server: GameServer,\n config: AuthServerConfig<TUser>\n): AuthGameServer<TUser> {\n const {\n provider,\n extractCredentials,\n autoAuthOnConnect = true,\n disconnectOnAuthFailure = false,\n onAuthSuccess,\n onAuthFailure\n } = config;\n\n const originalConnections = server.connections;\n const connectionAuthMap = new WeakMap<ServerConnection, AuthContext<TUser>>();\n\n const authServer: AuthGameServer<TUser> = {\n ...server,\n\n get authProvider(): IAuthProvider<TUser> {\n return provider;\n },\n\n async authenticate(\n conn: ServerConnection,\n credentials: unknown\n ): Promise<AuthResult<TUser>> {\n const result = await provider.verify(credentials as never);\n\n let authContext = connectionAuthMap.get(conn);\n if (!authContext) {\n authContext = new AuthContext<TUser>();\n connectionAuthMap.set(conn, authContext);\n setAuthContext(conn, authContext);\n }\n\n if (result.success) {\n authContext.setAuthenticated(result);\n await onAuthSuccess?.(conn, result.user!);\n } else {\n authContext.clear();\n await onAuthFailure?.(conn, result);\n }\n\n return result;\n },\n\n getAuthContext(conn: ServerConnection): IAuthContext<TUser> | null {\n return connectionAuthMap.get(conn) ?? null;\n },\n\n get connections(): ReadonlyArray<ServerConnection> {\n return originalConnections;\n }\n };\n\n const originalOnConnect = (server as any)._onConnect;\n (server as any)._onConnect = async (conn: ServerConnection, req?: unknown) => {\n const authContext = new AuthContext<TUser>();\n connectionAuthMap.set(conn, authContext);\n setAuthContext(conn, authContext);\n\n if (autoAuthOnConnect && extractCredentials && req) {\n try {\n const connReq = req as ConnectionRequest;\n const credentials = await extractCredentials(connReq);\n\n if (credentials) {\n const result = await provider.verify(credentials as never);\n\n if (result.success) {\n authContext.setAuthenticated(result);\n await onAuthSuccess?.(conn, result.user!);\n } else {\n await onAuthFailure?.(conn, result);\n\n if (disconnectOnAuthFailure) {\n (conn as any).close?.();\n return;\n }\n }\n }\n } catch (error) {\n console.error('[Auth] Error during auto-authentication:', error);\n }\n }\n\n if (originalOnConnect) {\n await originalOnConnect(conn, req);\n }\n };\n\n const originalOnDisconnect = (server as any)._onDisconnect;\n (server as any)._onDisconnect = async (conn: ServerConnection) => {\n connectionAuthMap.delete(conn);\n\n if (originalOnDisconnect) {\n await originalOnDisconnect(conn);\n }\n };\n\n return authServer;\n}\n\n/**\n * @zh 创建认证中间件\n * @en Create authentication middleware\n *\n * @zh 用于在 API 处理器中检查认证状态\n * @en Used to check authentication status in API handlers\n */\nexport function requireAuthentication<TUser = unknown>(\n conn: ServerConnection,\n options?: { errorMessage?: string }\n): IAuthContext<TUser> {\n const auth = getAuthContext<TUser>(conn);\n\n if (!auth || !auth.isAuthenticated) {\n throw new Error(options?.errorMessage ?? 'Authentication required');\n }\n\n return auth;\n}\n\n/**\n * @zh 创建角色检查中间件\n * @en Create role check middleware\n */\nexport function requireRole<TUser = unknown>(\n conn: ServerConnection,\n roles: string | string[],\n options?: { mode?: 'any' | 'all'; errorMessage?: string }\n): IAuthContext<TUser> {\n const auth = requireAuthentication<TUser>(conn);\n const roleArray = Array.isArray(roles) ? roles : [roles];\n const mode = options?.mode ?? 'any';\n\n const hasRole = mode === 'any'\n ? auth.hasAnyRole(roleArray)\n : auth.hasAllRoles(roleArray);\n\n if (!hasRole) {\n throw new Error(options?.errorMessage ?? 'Insufficient permissions');\n }\n\n return auth;\n}\n","/**\n * @zh 房间认证 Mixin\n * @en Room authentication mixin\n */\n\nimport type { Room, Player } from '../../room/index.js';\nimport type { IAuthContext, AuthRoomConfig } from '../types.js';\nimport { getAuthContext } from './withAuth.js';\nimport { createGuestContext } from '../context.js';\n\n/**\n * @zh 带认证的玩家\n * @en Player with authentication\n */\nexport interface AuthPlayer<TUser = unknown, TData = Record<string, unknown>> extends Player<TData> {\n /**\n * @zh 认证上下文\n * @en Authentication context\n */\n readonly auth: IAuthContext<TUser>;\n\n /**\n * @zh 用户信息(快捷访问)\n * @en User info (shortcut)\n */\n readonly user: TUser | null;\n}\n\n/**\n * @zh 带认证的房间接口\n * @en Room with authentication interface\n */\nexport interface IAuthRoom<TUser = unknown> {\n /**\n * @zh 认证钩子(在 onJoin 之前调用)\n * @en Auth hook (called before onJoin)\n */\n onAuth?(player: AuthPlayer<TUser>): boolean | Promise<boolean>;\n\n /**\n * @zh 获取带认证信息的玩家\n * @en Get player with auth info\n */\n getAuthPlayer(id: string): AuthPlayer<TUser> | undefined;\n\n /**\n * @zh 获取所有带认证信息的玩家\n * @en Get all players with auth info\n */\n getAuthPlayers(): AuthPlayer<TUser>[];\n\n /**\n * @zh 按角色获取玩家\n * @en Get players by role\n */\n getPlayersByRole(role: string): AuthPlayer<TUser>[];\n\n /**\n * @zh 按用户 ID 获取玩家\n * @en Get player by user ID\n */\n getPlayerByUserId(userId: string): AuthPlayer<TUser> | undefined;\n}\n\n/**\n * @zh 认证房间构造器类型\n * @en Auth room constructor type\n */\nexport type AuthRoomClass<TUser = unknown> = new (...args: any[]) => Room & IAuthRoom<TUser>;\n\n/**\n * @zh 玩家认证上下文存储\n * @en Player auth context storage\n */\nconst playerAuthContexts = new WeakMap<Player, IAuthContext<unknown>>();\n\n/**\n * @zh 包装玩家对象添加认证信息\n * @en Wrap player object with auth info\n */\nfunction wrapPlayerWithAuth<TUser>(player: Player, authContext: IAuthContext<TUser>): AuthPlayer<TUser> {\n playerAuthContexts.set(player, authContext);\n\n Object.defineProperty(player, 'auth', {\n get: () => playerAuthContexts.get(player) ?? createGuestContext<TUser>(),\n enumerable: true,\n configurable: false\n });\n\n Object.defineProperty(player, 'user', {\n get: () => (playerAuthContexts.get(player) as IAuthContext<TUser> | undefined)?.user ?? null,\n enumerable: true,\n configurable: false\n });\n\n return player as AuthPlayer<TUser>;\n}\n\n/**\n * @zh 包装房间类添加认证功能\n * @en Wrap room class with authentication functionality\n *\n * @zh 使用 mixin 模式为房间添加认证检查,在玩家加入前验证认证状态\n * @en Uses mixin pattern to add auth checks to room, validates auth before player joins\n *\n * @example\n * ```typescript\n * import { Room, onMessage } from '@esengine/server';\n * import { withRoomAuth, type AuthPlayer } from '@esengine/server/auth';\n *\n * interface User {\n * id: string;\n * name: string;\n * roles: string[];\n * }\n *\n * class GameRoom extends withRoomAuth<User>(Room, {\n * requireAuth: true,\n * allowedRoles: ['player', 'premium'],\n * }) {\n * onJoin(player: AuthPlayer<User>) {\n * console.log(`${player.user?.name} joined the game`);\n * this.broadcast('PlayerJoined', {\n * id: player.id,\n * name: player.user?.name\n * });\n * }\n *\n * // Optional: custom auth validation\n * async onAuth(player: AuthPlayer<User>): Promise<boolean> {\n * // Additional validation logic\n * if (player.auth.hasRole('banned')) {\n * return false;\n * }\n * return true;\n * }\n *\n * @onMessage('Chat')\n * handleChat(data: { text: string }, player: AuthPlayer<User>) {\n * this.broadcast('Chat', {\n * from: player.user?.name ?? 'Guest',\n * text: data.text\n * });\n * }\n * }\n * ```\n */\nexport function withRoomAuth<TUser = unknown, TBase extends new (...args: any[]) => Room = new (...args: any[]) => Room>(\n Base: TBase,\n config: AuthRoomConfig = {}\n): TBase & (new (...args: any[]) => IAuthRoom<TUser>) {\n const {\n requireAuth = true,\n allowedRoles = [],\n roleCheckMode = 'any'\n } = config;\n\n abstract class AuthRoom extends (Base as new (...args: any[]) => Room) implements IAuthRoom<TUser> {\n private _originalOnJoin: ((player: Player) => void | Promise<void>) | undefined;\n\n constructor(...args: any[]) {\n super(...args);\n this._originalOnJoin = this.onJoin?.bind(this);\n this.onJoin = this._authOnJoin.bind(this);\n }\n\n /**\n * @zh 认证钩子(可覆盖)\n * @en Auth hook (can be overridden)\n */\n onAuth?(player: AuthPlayer<TUser>): boolean | Promise<boolean>;\n\n /**\n * @zh 包装的 onJoin 方法\n * @en Wrapped onJoin method\n */\n private async _authOnJoin(player: Player): Promise<void> {\n const conn = (player as any).connection ?? (player as any)._conn;\n const authContext = conn\n ? (getAuthContext<TUser>(conn) ?? createGuestContext<TUser>())\n : createGuestContext<TUser>();\n\n if (requireAuth && !authContext.isAuthenticated) {\n console.warn(`[AuthRoom] Rejected unauthenticated player: ${player.id}`);\n this.kick(player as any, 'Authentication required');\n return;\n }\n\n if (allowedRoles.length > 0) {\n const hasRole = roleCheckMode === 'any'\n ? authContext.hasAnyRole(allowedRoles)\n : authContext.hasAllRoles(allowedRoles);\n\n if (!hasRole) {\n console.warn(`[AuthRoom] Rejected player ${player.id}: insufficient roles`);\n this.kick(player as any, 'Insufficient permissions');\n return;\n }\n }\n\n const authPlayer = wrapPlayerWithAuth<TUser>(player, authContext);\n\n if (typeof this.onAuth === 'function') {\n try {\n const allowed = await this.onAuth(authPlayer);\n if (!allowed) {\n console.warn(`[AuthRoom] Rejected player ${player.id}: onAuth returned false`);\n this.kick(player as any, 'Authentication rejected');\n return;\n }\n } catch (error) {\n console.error(`[AuthRoom] Error in onAuth for player ${player.id}:`, error);\n this.kick(player as any, 'Authentication error');\n return;\n }\n }\n\n if (this._originalOnJoin) {\n await this._originalOnJoin(authPlayer as unknown as Player);\n }\n }\n\n /**\n * @zh 获取带认证信息的玩家\n * @en Get player with auth info\n */\n getAuthPlayer(id: string): AuthPlayer<TUser> | undefined {\n const player = this.getPlayer(id);\n return player as AuthPlayer<TUser> | undefined;\n }\n\n /**\n * @zh 获取所有带认证信息的玩家\n * @en Get all players with auth info\n */\n getAuthPlayers(): AuthPlayer<TUser>[] {\n return this.players as AuthPlayer<TUser>[];\n }\n\n /**\n * @zh 按角色获取玩家\n * @en Get players by role\n */\n getPlayersByRole(role: string): AuthPlayer<TUser>[] {\n return this.getAuthPlayers().filter(p => p.auth?.hasRole(role));\n }\n\n /**\n * @zh 按用户 ID 获取玩家\n * @en Get player by user ID\n */\n getPlayerByUserId(userId: string): AuthPlayer<TUser> | undefined {\n return this.getAuthPlayers().find(p => p.auth?.userId === userId);\n }\n }\n\n return AuthRoom as unknown as TBase & (new (...args: any[]) => IAuthRoom<TUser>);\n}\n\n/**\n * @zh 抽象认证房间基类\n * @en Abstract auth room base class\n *\n * @zh 如果不想使用 mixin,可以直接继承此类\n * @en If you don't want to use mixin, you can extend this class directly\n *\n * @example\n * ```typescript\n * import { AuthRoomBase } from '@esengine/server/auth';\n *\n * class GameRoom extends AuthRoomBase<User> {\n * protected readonly authConfig = {\n * requireAuth: true,\n * allowedRoles: ['player']\n * };\n *\n * onJoin(player: AuthPlayer<User>) {\n * // player has .auth and .user properties\n * }\n * }\n * ```\n */\nexport abstract class AuthRoomBase<TUser = unknown, TState = any, TPlayerData = Record<string, unknown>>\n implements IAuthRoom<TUser> {\n\n /**\n * @zh 认证配置(子类可覆盖)\n * @en Auth config (can be overridden by subclass)\n */\n protected readonly authConfig: AuthRoomConfig = {\n requireAuth: true,\n allowedRoles: [],\n roleCheckMode: 'any'\n };\n\n /**\n * @zh 认证钩子\n * @en Auth hook\n */\n onAuth?(player: AuthPlayer<TUser>): boolean | Promise<boolean>;\n\n getAuthPlayer(id: string): AuthPlayer<TUser> | undefined {\n return undefined;\n }\n\n getAuthPlayers(): AuthPlayer<TUser>[] {\n return [];\n }\n\n getPlayersByRole(role: string): AuthPlayer<TUser>[] {\n return [];\n }\n\n getPlayerByUserId(userId: string): AuthPlayer<TUser> | undefined {\n return undefined;\n }\n}\n","/**\n * @zh requireAuth 装饰器\n * @en requireAuth decorator\n */\n\nimport type { RequireAuthOptions } from '../types.js';\n\n/**\n * @zh 认证元数据键\n * @en Auth metadata key\n */\nexport const AUTH_METADATA_KEY = Symbol('authMetadata');\n\n/**\n * @zh 认证元数据\n * @en Auth metadata\n */\nexport interface AuthMetadata {\n requireAuth: boolean;\n options?: RequireAuthOptions;\n roles?: string[];\n roleMode?: 'any' | 'all';\n}\n\n/**\n * @zh 获取方法的认证元数据\n * @en Get auth metadata for method\n */\nexport function getAuthMetadata(target: any, propertyKey: string): AuthMetadata | undefined {\n const metadata = target[AUTH_METADATA_KEY] as Map<string, AuthMetadata> | undefined;\n return metadata?.get(propertyKey);\n}\n\n/**\n * @zh 设置方法的认证元数据\n * @en Set auth metadata for method\n */\nfunction setAuthMetadata(target: any, propertyKey: string, metadata: AuthMetadata): void {\n if (!target[AUTH_METADATA_KEY]) {\n target[AUTH_METADATA_KEY] = new Map<string, AuthMetadata>();\n }\n (target[AUTH_METADATA_KEY] as Map<string, AuthMetadata>).set(propertyKey, metadata);\n}\n\n/**\n * @zh 要求认证装饰器\n * @en Require authentication decorator\n *\n * @zh 标记方法需要认证才能访问,用于消息处理器\n * @en Marks method as requiring authentication, used for message handlers\n *\n * @example\n * ```typescript\n * class GameRoom extends withRoomAuth(Room) {\n * @requireAuth()\n * @onMessage('Trade')\n * handleTrade(data: TradeData, player: AuthPlayer) {\n * // Only authenticated players can trade\n * }\n *\n * @requireAuth({ allowGuest: true })\n * @onMessage('Chat')\n * handleChat(data: ChatData, player: AuthPlayer) {\n * // Guests can also chat\n * }\n * }\n * ```\n */\nexport function requireAuth(options?: RequireAuthOptions): MethodDecorator {\n return function (\n target: any,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor\n ) {\n const key = String(propertyKey);\n const existing = getAuthMetadata(target, key);\n\n setAuthMetadata(target, key, {\n ...existing,\n requireAuth: true,\n options\n });\n\n return descriptor;\n };\n}\n","/**\n * @zh requireRole 装饰器\n * @en requireRole decorator\n */\n\nimport type { RequireRoleOptions } from '../types.js';\nimport { AUTH_METADATA_KEY, getAuthMetadata, type AuthMetadata } from './requireAuth.js';\n\n/**\n * @zh 设置方法的认证元数据\n * @en Set auth metadata for method\n */\nfunction setAuthMetadata(target: any, propertyKey: string, metadata: AuthMetadata): void {\n if (!target[AUTH_METADATA_KEY]) {\n target[AUTH_METADATA_KEY] = new Map<string, AuthMetadata>();\n }\n (target[AUTH_METADATA_KEY] as Map<string, AuthMetadata>).set(propertyKey, metadata);\n}\n\n/**\n * @zh 要求角色装饰器\n * @en Require role decorator\n *\n * @zh 标记方法需要特定角色才能访问\n * @en Marks method as requiring specific role(s)\n *\n * @example\n * ```typescript\n * class AdminRoom extends withRoomAuth(Room) {\n * @requireRole('admin')\n * @onMessage('Ban')\n * handleBan(data: BanData, player: AuthPlayer) {\n * // Only admins can ban\n * }\n *\n * @requireRole(['moderator', 'admin'])\n * @onMessage('Mute')\n * handleMute(data: MuteData, player: AuthPlayer) {\n * // Moderators or admins can mute\n * }\n *\n * @requireRole(['verified', 'premium'], { mode: 'all' })\n * @onMessage('SpecialFeature')\n * handleSpecial(data: any, player: AuthPlayer) {\n * // Requires both verified AND premium roles\n * }\n * }\n * ```\n */\nexport function requireRole(\n roles: string | string[],\n options?: RequireRoleOptions\n): MethodDecorator {\n return function (\n target: any,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor\n ) {\n const key = String(propertyKey);\n const existing = getAuthMetadata(target, key);\n const roleArray = Array.isArray(roles) ? roles : [roles];\n\n setAuthMetadata(target, key, {\n ...existing,\n requireAuth: true,\n roles: roleArray,\n roleMode: options?.mode ?? 'any',\n options\n });\n\n return descriptor;\n };\n}\n"]}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { a as IAuthProvider, A as AuthResult } from '../../types-BmO5ykKp.js';
|
|
2
|
+
import '../../index-DgaJIm6-.js';
|
|
3
|
+
import '@esengine/rpc';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @zh 模拟认证提供者
|
|
7
|
+
* @en Mock authentication provider
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @zh 模拟用户
|
|
12
|
+
* @en Mock user
|
|
13
|
+
*/
|
|
14
|
+
interface MockUser {
|
|
15
|
+
id: string;
|
|
16
|
+
name?: string;
|
|
17
|
+
roles?: string[];
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* @zh 模拟认证配置
|
|
22
|
+
* @en Mock authentication configuration
|
|
23
|
+
*/
|
|
24
|
+
interface MockAuthConfig {
|
|
25
|
+
/**
|
|
26
|
+
* @zh 预设用户列表
|
|
27
|
+
* @en Preset user list
|
|
28
|
+
*/
|
|
29
|
+
users?: MockUser[];
|
|
30
|
+
/**
|
|
31
|
+
* @zh 默认用户(无 token 时返回)
|
|
32
|
+
* @en Default user (returned when no token)
|
|
33
|
+
*/
|
|
34
|
+
defaultUser?: MockUser;
|
|
35
|
+
/**
|
|
36
|
+
* @zh 模拟延迟(毫秒)
|
|
37
|
+
* @en Simulated delay (ms)
|
|
38
|
+
*/
|
|
39
|
+
delay?: number;
|
|
40
|
+
/**
|
|
41
|
+
* @zh 是否自动创建用户
|
|
42
|
+
* @en Auto create users
|
|
43
|
+
*/
|
|
44
|
+
autoCreate?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* @zh 验证令牌格式
|
|
47
|
+
* @en Token format validator
|
|
48
|
+
*/
|
|
49
|
+
validateToken?: (token: string) => boolean;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* @zh 模拟认证提供者
|
|
53
|
+
* @en Mock authentication provider
|
|
54
|
+
*
|
|
55
|
+
* @zh 用于测试的认证提供者,不需要真实的 JWT 或数据库
|
|
56
|
+
* @en Authentication provider for testing, no real JWT or database required
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* import { createMockAuthProvider } from '@esengine/server/auth/testing';
|
|
61
|
+
*
|
|
62
|
+
* const mockProvider = createMockAuthProvider({
|
|
63
|
+
* users: [
|
|
64
|
+
* { id: '1', name: 'Alice', roles: ['player'] },
|
|
65
|
+
* { id: '2', name: 'Bob', roles: ['admin'] },
|
|
66
|
+
* ],
|
|
67
|
+
* autoCreate: true, // Unknown tokens create guest users
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* // Verify with user ID as token
|
|
71
|
+
* const result = await mockProvider.verify('1');
|
|
72
|
+
* // result.user = { id: '1', name: 'Alice', roles: ['player'] }
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
declare class MockAuthProvider<TUser extends MockUser = MockUser> implements IAuthProvider<TUser, string> {
|
|
76
|
+
readonly name = "mock";
|
|
77
|
+
private _users;
|
|
78
|
+
private _config;
|
|
79
|
+
private _revokedTokens;
|
|
80
|
+
constructor(config?: MockAuthConfig);
|
|
81
|
+
/**
|
|
82
|
+
* @zh 模拟延迟
|
|
83
|
+
* @en Simulate delay
|
|
84
|
+
*/
|
|
85
|
+
private _delay;
|
|
86
|
+
/**
|
|
87
|
+
* @zh 验证令牌
|
|
88
|
+
* @en Verify token
|
|
89
|
+
*/
|
|
90
|
+
verify(token: string): Promise<AuthResult<TUser>>;
|
|
91
|
+
/**
|
|
92
|
+
* @zh 刷新令牌
|
|
93
|
+
* @en Refresh token
|
|
94
|
+
*/
|
|
95
|
+
refresh(token: string): Promise<AuthResult<TUser>>;
|
|
96
|
+
/**
|
|
97
|
+
* @zh 撤销令牌
|
|
98
|
+
* @en Revoke token
|
|
99
|
+
*/
|
|
100
|
+
revoke(token: string): Promise<boolean>;
|
|
101
|
+
/**
|
|
102
|
+
* @zh 添加用户
|
|
103
|
+
* @en Add user
|
|
104
|
+
*/
|
|
105
|
+
addUser(user: TUser): void;
|
|
106
|
+
/**
|
|
107
|
+
* @zh 移除用户
|
|
108
|
+
* @en Remove user
|
|
109
|
+
*/
|
|
110
|
+
removeUser(id: string): boolean;
|
|
111
|
+
/**
|
|
112
|
+
* @zh 获取用户
|
|
113
|
+
* @en Get user
|
|
114
|
+
*/
|
|
115
|
+
getUser(id: string): TUser | undefined;
|
|
116
|
+
/**
|
|
117
|
+
* @zh 获取所有用户
|
|
118
|
+
* @en Get all users
|
|
119
|
+
*/
|
|
120
|
+
getUsers(): TUser[];
|
|
121
|
+
/**
|
|
122
|
+
* @zh 清空所有状态
|
|
123
|
+
* @en Clear all state
|
|
124
|
+
*/
|
|
125
|
+
clear(): void;
|
|
126
|
+
/**
|
|
127
|
+
* @zh 生成测试令牌
|
|
128
|
+
* @en Generate test token
|
|
129
|
+
*/
|
|
130
|
+
generateToken(userId: string): string;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* @zh 创建模拟认证提供者
|
|
134
|
+
* @en Create mock authentication provider
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* const provider = createMockAuthProvider({
|
|
139
|
+
* users: [
|
|
140
|
+
* { id: 'admin', name: 'Admin', roles: ['admin'] }
|
|
141
|
+
* ]
|
|
142
|
+
* });
|
|
143
|
+
*
|
|
144
|
+
* // Use in tests
|
|
145
|
+
* const server = withAuth(await createServer({ port: 0 }), {
|
|
146
|
+
* provider,
|
|
147
|
+
* extractCredentials: (req) => req.headers['x-token']
|
|
148
|
+
* });
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
declare function createMockAuthProvider<TUser extends MockUser = MockUser>(config?: MockAuthConfig): MockAuthProvider<TUser>;
|
|
152
|
+
|
|
153
|
+
export { type MockAuthConfig, MockAuthProvider, type MockUser, createMockAuthProvider };
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { __name, __publicField } from '../../chunk-T626JPC7.js';
|
|
2
|
+
|
|
3
|
+
// src/auth/testing/MockAuthProvider.ts
|
|
4
|
+
var _MockAuthProvider = class _MockAuthProvider {
|
|
5
|
+
constructor(config = {}) {
|
|
6
|
+
__publicField(this, "name", "mock");
|
|
7
|
+
__publicField(this, "_users");
|
|
8
|
+
__publicField(this, "_config");
|
|
9
|
+
__publicField(this, "_revokedTokens", /* @__PURE__ */ new Set());
|
|
10
|
+
this._config = config;
|
|
11
|
+
this._users = /* @__PURE__ */ new Map();
|
|
12
|
+
if (config.users) {
|
|
13
|
+
for (const user of config.users) {
|
|
14
|
+
this._users.set(user.id, user);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* @zh 模拟延迟
|
|
20
|
+
* @en Simulate delay
|
|
21
|
+
*/
|
|
22
|
+
async _delay() {
|
|
23
|
+
if (this._config.delay && this._config.delay > 0) {
|
|
24
|
+
await new Promise((resolve) => setTimeout(resolve, this._config.delay));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* @zh 验证令牌
|
|
29
|
+
* @en Verify token
|
|
30
|
+
*/
|
|
31
|
+
async verify(token) {
|
|
32
|
+
await this._delay();
|
|
33
|
+
if (!token) {
|
|
34
|
+
if (this._config.defaultUser) {
|
|
35
|
+
return {
|
|
36
|
+
success: true,
|
|
37
|
+
user: this._config.defaultUser,
|
|
38
|
+
token: "default"
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
success: false,
|
|
43
|
+
error: "Token is required",
|
|
44
|
+
errorCode: "INVALID_TOKEN"
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (this._revokedTokens.has(token)) {
|
|
48
|
+
return {
|
|
49
|
+
success: false,
|
|
50
|
+
error: "Token has been revoked",
|
|
51
|
+
errorCode: "INVALID_TOKEN"
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (this._config.validateToken && !this._config.validateToken(token)) {
|
|
55
|
+
return {
|
|
56
|
+
success: false,
|
|
57
|
+
error: "Invalid token format",
|
|
58
|
+
errorCode: "INVALID_TOKEN"
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const user = this._users.get(token);
|
|
62
|
+
if (user) {
|
|
63
|
+
return {
|
|
64
|
+
success: true,
|
|
65
|
+
user,
|
|
66
|
+
token,
|
|
67
|
+
expiresAt: Date.now() + 36e5
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (this._config.autoCreate) {
|
|
71
|
+
const newUser = {
|
|
72
|
+
id: token,
|
|
73
|
+
name: `User_${token}`,
|
|
74
|
+
roles: [
|
|
75
|
+
"guest"
|
|
76
|
+
]
|
|
77
|
+
};
|
|
78
|
+
this._users.set(token, newUser);
|
|
79
|
+
return {
|
|
80
|
+
success: true,
|
|
81
|
+
user: newUser,
|
|
82
|
+
token,
|
|
83
|
+
expiresAt: Date.now() + 36e5
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
success: false,
|
|
88
|
+
error: "User not found",
|
|
89
|
+
errorCode: "USER_NOT_FOUND"
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* @zh 刷新令牌
|
|
94
|
+
* @en Refresh token
|
|
95
|
+
*/
|
|
96
|
+
async refresh(token) {
|
|
97
|
+
return this.verify(token);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* @zh 撤销令牌
|
|
101
|
+
* @en Revoke token
|
|
102
|
+
*/
|
|
103
|
+
async revoke(token) {
|
|
104
|
+
this._revokedTokens.add(token);
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* @zh 添加用户
|
|
109
|
+
* @en Add user
|
|
110
|
+
*/
|
|
111
|
+
addUser(user) {
|
|
112
|
+
this._users.set(user.id, user);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* @zh 移除用户
|
|
116
|
+
* @en Remove user
|
|
117
|
+
*/
|
|
118
|
+
removeUser(id) {
|
|
119
|
+
return this._users.delete(id);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* @zh 获取用户
|
|
123
|
+
* @en Get user
|
|
124
|
+
*/
|
|
125
|
+
getUser(id) {
|
|
126
|
+
return this._users.get(id);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* @zh 获取所有用户
|
|
130
|
+
* @en Get all users
|
|
131
|
+
*/
|
|
132
|
+
getUsers() {
|
|
133
|
+
return Array.from(this._users.values());
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* @zh 清空所有状态
|
|
137
|
+
* @en Clear all state
|
|
138
|
+
*/
|
|
139
|
+
clear() {
|
|
140
|
+
this._users.clear();
|
|
141
|
+
this._revokedTokens.clear();
|
|
142
|
+
if (this._config.users) {
|
|
143
|
+
for (const user of this._config.users) {
|
|
144
|
+
this._users.set(user.id, user);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* @zh 生成测试令牌
|
|
150
|
+
* @en Generate test token
|
|
151
|
+
*/
|
|
152
|
+
generateToken(userId) {
|
|
153
|
+
return userId;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
__name(_MockAuthProvider, "MockAuthProvider");
|
|
157
|
+
var MockAuthProvider = _MockAuthProvider;
|
|
158
|
+
function createMockAuthProvider(config) {
|
|
159
|
+
return new MockAuthProvider(config);
|
|
160
|
+
}
|
|
161
|
+
__name(createMockAuthProvider, "createMockAuthProvider");
|
|
162
|
+
|
|
163
|
+
export { MockAuthProvider, createMockAuthProvider };
|
|
164
|
+
//# sourceMappingURL=index.js.map
|
|
165
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/auth/testing/MockAuthProvider.ts"],"names":["MockAuthProvider","config","name","_users","_config","_revokedTokens","Set","Map","users","user","set","id","_delay","delay","Promise","resolve","setTimeout","verify","token","defaultUser","success","error","errorCode","has","validateToken","get","expiresAt","Date","now","autoCreate","newUser","roles","refresh","revoke","add","addUser","removeUser","delete","getUser","getUsers","Array","from","values","clear","generateToken","userId","createMockAuthProvider"],"mappings":";;;AA8EO,IAAMA,iBAAAA,GAAN,MAAMA,iBAAAA,CAAAA;EAST,WAAA,CAAYC,MAAAA,GAAyB,EAAC,EAAG;AANhCC,IAAAA,aAAAA,CAAAA,IAAAA,EAAAA,MAAAA,EAAO,MAAA,CAAA;AAERC,IAAAA,aAAAA,CAAAA,IAAAA,EAAAA,QAAAA,CAAAA;AACAC,IAAAA,aAAAA,CAAAA,IAAAA,EAAAA,SAAAA,CAAAA;AACAC,IAAAA,aAAAA,CAAAA,IAAAA,EAAAA,gBAAAA,sBAAkCC,GAAAA,EAAAA,CAAAA;AAGtC,IAAA,IAAA,CAAKF,OAAAA,GAAUH,MAAAA;AACf,IAAA,IAAA,CAAKE,MAAAA,uBAAaI,GAAAA,EAAAA;AAElB,IAAA,IAAIN,OAAOO,KAAAA,EAAO;AACd,MAAA,KAAA,MAAWC,IAAAA,IAAQR,OAAOO,KAAAA,EAAO;AAC7B,QAAA,IAAA,CAAKL,MAAAA,CAAOO,GAAAA,CAAID,IAAAA,CAAKE,EAAAA,EAAIF,IAAAA,CAAAA;AAC7B,MAAA;AACJ,IAAA;AACJ,EAAA;;;;;AAMA,EAAA,MAAcG,MAAAA,GAAwB;AAClC,IAAA,IAAI,KAAKR,OAAAA,CAAQS,KAAAA,IAAS,IAAA,CAAKT,OAAAA,CAAQS,QAAQ,CAAA,EAAG;AAC9C,MAAA,MAAM,IAAIC,QAAQC,CAAAA,OAAAA,KAAWC,WAAWD,OAAAA,EAAS,IAAA,CAAKX,OAAAA,CAAQS,KAAK,CAAA,CAAA;AACvE,IAAA;AACJ,EAAA;;;;;AAMA,EAAA,MAAMI,OAAOC,KAAAA,EAA2C;AACpD,IAAA,MAAM,KAAKN,MAAAA,EAAM;AAEjB,IAAA,IAAI,CAACM,KAAAA,EAAO;AACR,MAAA,IAAI,IAAA,CAAKd,QAAQe,WAAAA,EAAa;AAC1B,QAAA,OAAO;UACHC,OAAAA,EAAS,IAAA;AACTX,UAAAA,IAAAA,EAAM,KAAKL,OAAAA,CAAQe,WAAAA;UACnBD,KAAAA,EAAO;AACX,SAAA;AACJ,MAAA;AACA,MAAA,OAAO;QACHE,OAAAA,EAAS,KAAA;QACTC,KAAAA,EAAO,mBAAA;QACPC,SAAAA,EAAW;AACf,OAAA;AACJ,IAAA;AAEA,IAAA,IAAI,IAAA,CAAKjB,cAAAA,CAAekB,GAAAA,CAAIL,KAAAA,CAAAA,EAAQ;AAChC,MAAA,OAAO;QACHE,OAAAA,EAAS,KAAA;QACTC,KAAAA,EAAO,wBAAA;QACPC,SAAAA,EAAW;AACf,OAAA;AACJ,IAAA;AAEA,IAAA,IAAI,IAAA,CAAKlB,QAAQoB,aAAAA,IAAiB,CAAC,KAAKpB,OAAAA,CAAQoB,aAAAA,CAAcN,KAAAA,CAAAA,EAAQ;AAClE,MAAA,OAAO;QACHE,OAAAA,EAAS,KAAA;QACTC,KAAAA,EAAO,sBAAA;QACPC,SAAAA,EAAW;AACf,OAAA;AACJ,IAAA;AAEA,IAAA,MAAMb,IAAAA,GAAO,IAAA,CAAKN,MAAAA,CAAOsB,GAAAA,CAAIP,KAAAA,CAAAA;AAE7B,IAAA,IAAIT,IAAAA,EAAM;AACN,MAAA,OAAO;QACHW,OAAAA,EAAS,IAAA;AACTX,QAAAA,IAAAA;AACAS,QAAAA,KAAAA;QACAQ,SAAAA,EAAWC,IAAAA,CAAKC,KAAG,GAAK;AAC5B,OAAA;AACJ,IAAA;AAEA,IAAA,IAAI,IAAA,CAAKxB,QAAQyB,UAAAA,EAAY;AACzB,MAAA,MAAMC,OAAAA,GAAU;QACZnB,EAAAA,EAAIO,KAAAA;AACJhB,QAAAA,IAAAA,EAAM,QAAQgB,KAAAA,CAAAA,CAAAA;QACda,KAAAA,EAAO;AAAC,UAAA;;AACZ,OAAA;AAEA,MAAA,IAAA,CAAK5B,MAAAA,CAAOO,GAAAA,CAAIQ,KAAAA,EAAOY,OAAAA,CAAAA;AAEvB,MAAA,OAAO;QACHV,OAAAA,EAAS,IAAA;QACTX,IAAAA,EAAMqB,OAAAA;AACNZ,QAAAA,KAAAA;QACAQ,SAAAA,EAAWC,IAAAA,CAAKC,KAAG,GAAK;AAC5B,OAAA;AACJ,IAAA;AAEA,IAAA,OAAO;MACHR,OAAAA,EAAS,KAAA;MACTC,KAAAA,EAAO,gBAAA;MACPC,SAAAA,EAAW;AACf,KAAA;AACJ,EAAA;;;;;AAMA,EAAA,MAAMU,QAAQd,KAAAA,EAA2C;AACrD,IAAA,OAAO,IAAA,CAAKD,OAAOC,KAAAA,CAAAA;AACvB,EAAA;;;;;AAMA,EAAA,MAAMe,OAAOf,KAAAA,EAAiC;AAC1C,IAAA,IAAA,CAAKb,cAAAA,CAAe6B,IAAIhB,KAAAA,CAAAA;AACxB,IAAA,OAAO,IAAA;AACX,EAAA;;;;;AAMAiB,EAAAA,OAAAA,CAAQ1B,IAAAA,EAAmB;AACvB,IAAA,IAAA,CAAKN,MAAAA,CAAOO,GAAAA,CAAID,IAAAA,CAAKE,EAAAA,EAAIF,IAAAA,CAAAA;AAC7B,EAAA;;;;;AAMA2B,EAAAA,UAAAA,CAAWzB,EAAAA,EAAqB;AAC5B,IAAA,OAAO,IAAA,CAAKR,MAAAA,CAAOkC,MAAAA,CAAO1B,EAAAA,CAAAA;AAC9B,EAAA;;;;;AAMA2B,EAAAA,OAAAA,CAAQ3B,EAAAA,EAA+B;AACnC,IAAA,OAAO,IAAA,CAAKR,MAAAA,CAAOsB,GAAAA,CAAId,EAAAA,CAAAA;AAC3B,EAAA;;;;;EAMA4B,QAAAA,GAAoB;AAChB,IAAA,OAAOC,KAAAA,CAAMC,IAAAA,CAAK,IAAA,CAAKtC,MAAAA,CAAOuC,QAAM,CAAA;AACxC,EAAA;;;;;EAMAC,KAAAA,GAAc;AACV,IAAA,IAAA,CAAKxC,OAAOwC,KAAAA,EAAK;AACjB,IAAA,IAAA,CAAKtC,eAAesC,KAAAA,EAAK;AAEzB,IAAA,IAAI,IAAA,CAAKvC,QAAQI,KAAAA,EAAO;AACpB,MAAA,KAAA,MAAWC,IAAAA,IAAQ,IAAA,CAAKL,OAAAA,CAAQI,KAAAA,EAAO;AACnC,QAAA,IAAA,CAAKL,MAAAA,CAAOO,GAAAA,CAAID,IAAAA,CAAKE,EAAAA,EAAIF,IAAAA,CAAAA;AAC7B,MAAA;AACJ,IAAA;AACJ,EAAA;;;;;AAMAmC,EAAAA,aAAAA,CAAcC,MAAAA,EAAwB;AAClC,IAAA,OAAOA,MAAAA;AACX,EAAA;AACJ,CAAA;AA9Ka7C,MAAAA,CAAAA,iBAAAA,EAAAA,kBAAAA,CAAAA;AAAN,IAAMA,gBAAAA,GAAN;AAmMA,SAAS8C,uBACZ7C,MAAAA,EAAuB;AAEvB,EAAA,OAAO,IAAID,iBAAwBC,MAAAA,CAAAA;AACvC;AAJgB6C,MAAAA,CAAAA,sBAAAA,EAAAA,wBAAAA,CAAAA","file":"index.js","sourcesContent":["/**\n * @zh 模拟认证提供者\n * @en Mock authentication provider\n */\n\nimport type { IAuthProvider, AuthResult, AuthErrorCode } from '../types.js';\n\n/**\n * @zh 模拟用户\n * @en Mock user\n */\nexport interface MockUser {\n id: string;\n name?: string;\n roles?: string[];\n [key: string]: unknown;\n}\n\n/**\n * @zh 模拟认证配置\n * @en Mock authentication configuration\n */\nexport interface MockAuthConfig {\n /**\n * @zh 预设用户列表\n * @en Preset user list\n */\n users?: MockUser[];\n\n /**\n * @zh 默认用户(无 token 时返回)\n * @en Default user (returned when no token)\n */\n defaultUser?: MockUser;\n\n /**\n * @zh 模拟延迟(毫秒)\n * @en Simulated delay (ms)\n */\n delay?: number;\n\n /**\n * @zh 是否自动创建用户\n * @en Auto create users\n */\n autoCreate?: boolean;\n\n /**\n * @zh 验证令牌格式\n * @en Token format validator\n */\n validateToken?: (token: string) => boolean;\n}\n\n/**\n * @zh 模拟认证提供者\n * @en Mock authentication provider\n *\n * @zh 用于测试的认证提供者,不需要真实的 JWT 或数据库\n * @en Authentication provider for testing, no real JWT or database required\n *\n * @example\n * ```typescript\n * import { createMockAuthProvider } from '@esengine/server/auth/testing';\n *\n * const mockProvider = createMockAuthProvider({\n * users: [\n * { id: '1', name: 'Alice', roles: ['player'] },\n * { id: '2', name: 'Bob', roles: ['admin'] },\n * ],\n * autoCreate: true, // Unknown tokens create guest users\n * });\n *\n * // Verify with user ID as token\n * const result = await mockProvider.verify('1');\n * // result.user = { id: '1', name: 'Alice', roles: ['player'] }\n * ```\n */\nexport class MockAuthProvider<TUser extends MockUser = MockUser>\n implements IAuthProvider<TUser, string> {\n\n readonly name = 'mock';\n\n private _users: Map<string, TUser>;\n private _config: MockAuthConfig;\n private _revokedTokens: Set<string> = new Set();\n\n constructor(config: MockAuthConfig = {}) {\n this._config = config;\n this._users = new Map();\n\n if (config.users) {\n for (const user of config.users) {\n this._users.set(user.id, user as TUser);\n }\n }\n }\n\n /**\n * @zh 模拟延迟\n * @en Simulate delay\n */\n private async _delay(): Promise<void> {\n if (this._config.delay && this._config.delay > 0) {\n await new Promise(resolve => setTimeout(resolve, this._config.delay));\n }\n }\n\n /**\n * @zh 验证令牌\n * @en Verify token\n */\n async verify(token: string): Promise<AuthResult<TUser>> {\n await this._delay();\n\n if (!token) {\n if (this._config.defaultUser) {\n return {\n success: true,\n user: this._config.defaultUser as TUser,\n token: 'default'\n };\n }\n return {\n success: false,\n error: 'Token is required',\n errorCode: 'INVALID_TOKEN'\n };\n }\n\n if (this._revokedTokens.has(token)) {\n return {\n success: false,\n error: 'Token has been revoked',\n errorCode: 'INVALID_TOKEN'\n };\n }\n\n if (this._config.validateToken && !this._config.validateToken(token)) {\n return {\n success: false,\n error: 'Invalid token format',\n errorCode: 'INVALID_TOKEN'\n };\n }\n\n const user = this._users.get(token);\n\n if (user) {\n return {\n success: true,\n user,\n token,\n expiresAt: Date.now() + 3600000\n };\n }\n\n if (this._config.autoCreate) {\n const newUser = {\n id: token,\n name: `User_${token}`,\n roles: ['guest']\n } as TUser;\n\n this._users.set(token, newUser);\n\n return {\n success: true,\n user: newUser,\n token,\n expiresAt: Date.now() + 3600000\n };\n }\n\n return {\n success: false,\n error: 'User not found',\n errorCode: 'USER_NOT_FOUND'\n };\n }\n\n /**\n * @zh 刷新令牌\n * @en Refresh token\n */\n async refresh(token: string): Promise<AuthResult<TUser>> {\n return this.verify(token);\n }\n\n /**\n * @zh 撤销令牌\n * @en Revoke token\n */\n async revoke(token: string): Promise<boolean> {\n this._revokedTokens.add(token);\n return true;\n }\n\n /**\n * @zh 添加用户\n * @en Add user\n */\n addUser(user: TUser): void {\n this._users.set(user.id, user);\n }\n\n /**\n * @zh 移除用户\n * @en Remove user\n */\n removeUser(id: string): boolean {\n return this._users.delete(id);\n }\n\n /**\n * @zh 获取用户\n * @en Get user\n */\n getUser(id: string): TUser | undefined {\n return this._users.get(id);\n }\n\n /**\n * @zh 获取所有用户\n * @en Get all users\n */\n getUsers(): TUser[] {\n return Array.from(this._users.values());\n }\n\n /**\n * @zh 清空所有状态\n * @en Clear all state\n */\n clear(): void {\n this._users.clear();\n this._revokedTokens.clear();\n\n if (this._config.users) {\n for (const user of this._config.users) {\n this._users.set(user.id, user as TUser);\n }\n }\n }\n\n /**\n * @zh 生成测试令牌\n * @en Generate test token\n */\n generateToken(userId: string): string {\n return userId;\n }\n}\n\n/**\n * @zh 创建模拟认证提供者\n * @en Create mock authentication provider\n *\n * @example\n * ```typescript\n * const provider = createMockAuthProvider({\n * users: [\n * { id: 'admin', name: 'Admin', roles: ['admin'] }\n * ]\n * });\n *\n * // Use in tests\n * const server = withAuth(await createServer({ port: 0 }), {\n * provider,\n * extractCredentials: (req) => req.headers['x-token']\n * });\n * ```\n */\nexport function createMockAuthProvider<TUser extends MockUser = MockUser>(\n config?: MockAuthConfig\n): MockAuthProvider<TUser> {\n return new MockAuthProvider<TUser>(config);\n}\n"]}
|