composable-functions实战案例:构建完整的用户认证系统
composable-functions实战案例构建完整的用户认证系统【免费下载链接】domain-functionsTypes and functions to make composition easy and safe项目地址: https://gitcode.com/gh_mirrors/do/domain-functions在当今的Web开发中构建安全可靠的用户认证系统是每个应用的核心需求。composable-functions作为一个强大的函数组合库能够帮助我们以类型安全、可维护的方式构建完整的用户认证流程。本文将展示如何使用composable-functions创建一个端到端类型安全的用户认证系统涵盖注册、登录、会话管理和权限控制等关键功能。为什么选择composable-functions构建认证系统传统的认证系统代码往往充斥着复杂的错误处理、异步操作和类型不一致的问题。composable-functions通过以下特性完美解决了这些痛点类型安全组合- 确保函数组合时的类型一致性避免运行时错误 统一的错误处理- 消除繁琐的try/catch语法专注于业务逻辑 ️业务逻辑隔离- 将认证逻辑拆分为可组合的单一职责函数 端到端类型安全- 从后端到前端保持类型一致性核心认证模块设计1. 用户注册流程让我们从用户注册开始。首先我们需要定义用户数据验证和创建逻辑// 用户注册相关函数 import { composable, pipe, all, applySchema } from composable-functions import { z } from zod // 定义用户注册模式 const registerSchema z.object({ email: z.string().email(), password: z.string().min(8), username: z.string().min(3), confirmPassword: z.string() }).refine(data data.password data.confirmPassword, { message: 密码不匹配, path: [confirmPassword] }) // 验证用户输入 const validateRegistration applySchema(registerSchema) // 检查邮箱是否已存在 const checkEmailExists composable(async (email: string) { const existingUser await db.users.findUnique({ where: { email } }) if (existingUser) { throw new Error(邮箱已被注册) } return email }) // 加密密码 const hashPassword composable(async (password: string) { const salt await bcrypt.genSalt(10) const hashedPassword await bcrypt.hash(password, salt) return hashedPassword }) // 创建用户记录 const createUser composable(async (data: { email: string, username: string, hashedPassword: string }) { const user await db.users.create({ data: { email: data.email, username: data.username, password: data.hashedPassword, createdAt: new Date() } }) return { userId: user.id, email: user.email } })2. 组合注册流程使用pipe函数将这些验证步骤串联起来// 完整的注册流程组合 const registerUser pipe( validateRegistration, // 验证输入 async (validatedData) ({ email: validatedData.email, username: validatedData.username, password: validatedData.password }), all( checkEmailExists, // 并行检查邮箱 hashPassword // 并行加密密码 ), async ([email, hashedPassword], username) ({ email, username, hashedPassword }), createUser // 创建用户 ) // 使用注册函数 const result await registerUser({ email: userexample.com, password: secure123, username: newuser, confirmPassword: secure123 }) if (result.success) { console.log(注册成功:, result.data) } else { console.log(注册失败:, result.errors) }3. 用户登录认证登录流程需要验证凭证并生成访问令牌// 登录认证函数 import { branch, catchFailure, mapErrors } from composable-functions // 验证登录凭证 const validateCredentials applySchema( z.object({ email: z.string().email(), password: z.string() }) ) // 查找用户 const findUserByEmail composable(async (email: string) { const user await db.users.findUnique({ where: { email }, select: { id: true, email: true, password: true } }) if (!user) { throw new Error(用户不存在) } return user }) // 验证密码 const verifyPassword composable(async (user: any, password: string) { const isValid await bcrypt.compare(password, user.password) if (!isValid) { throw new Error(密码错误) } return user }) // 生成JWT令牌 const generateToken composable(async (userId: string) { const token jwt.sign( { userId, exp: Math.floor(Date.now() / 1000) (60 * 60) }, process.env.JWT_SECRET! ) return { token, expiresIn: 3600 } }) // 完整的登录流程 const loginUser pipe( validateCredentials, async (credentials) ({ email: credentials.email, password: credentials.password }), branch( findUserByEmail, // 查找用户 verifyPassword // 验证密码 ), async (user) user.id, generateToken // 生成访问令牌 ) // 优雅的错误处理 const loginWithGracefulErrors catchFailure( loginUser, (errors, credentials) { // 将技术错误转换为用户友好的消息 const errorMessages errors.map(error { if (error.message.includes(用户不存在)) { return 邮箱或密码错误 } if (error.message.includes(密码错误)) { return 邮箱或密码错误 } return 登录失败请稍后重试 }) return { success: false, errors: errorMessages } } )4. 会话管理和权限控制// 会话验证中间件 import { context } from composable-functions // 验证JWT令牌 const verifyToken composable(async (token: string) { try { const decoded jwt.verify(token, process.env.JWT_SECRET!) return decoded as { userId: string } } catch { throw new Error(无效的访问令牌) } }) // 获取用户信息 const getUserFromToken pipe( verifyToken, async (decoded) decoded.userId, async (userId) { const user await db.users.findUnique({ where: { id: userId }, select: { id: true, email: true, role: true } }) if (!user) { throw new Error(用户不存在) } return user } ) // 权限检查函数 const requireRole (requiredRole: string) composable(async (user: { role: string }) { if (user.role ! requiredRole) { throw new Error(权限不足) } return user }) // 使用上下文共享认证信息 const authenticatedContext context{ userId: string }() // 受保护的业务函数 const getProtectedData authenticatedContext( composable(async (context) { const user await db.users.findUnique({ where: { id: context.userId }, select: { sensitiveData: true } }) return user?.sensitiveData }) )5. 完整的认证API端点// 认证API端点组合 import { inputFromFormData } from composable-functions // 注册端点 const registerEndpoint pipe( inputFromFormData, // 从FormData解析输入 registerUser, // 注册用户 map(result ({ // 映射结果格式 status: result.success ? 201 : 400, body: result.success ? { user: result.data } : { errors: result.errors } })) ) // 登录端点 const loginEndpoint pipe( inputFromFormData, // 从FormData解析输入 loginWithGracefulErrors, // 登录处理 map(result ({ status: result.success ? 200 : 401, body: result.success ? { token: result.data.token } : { errors: result.errors } })) ) // 受保护的数据端点 const protectedDataEndpoint pipe( inputFromFormData, // 解析输入 async (data) data.get(token), // 提取token getUserFromToken, // 验证token并获取用户 requireRole(admin), // 检查权限 getProtectedData, // 获取保护数据 map(data ({ status: 200, body: { data } })) )实战优势与最佳实践 性能优化技巧并行执行验证使用all组合器并行执行多个验证步骤懒加载依赖只在需要时加载数据库连接和加密库缓存策略对频繁验证的token实现缓存机制 错误处理策略// 统一的错误处理中间件 const withErrorHandling T(composableFn: ComposableT) catchFailure(composableFn, (errors, input) { // 记录错误日志 console.error(认证错误:, errors, 输入:, input) // 根据错误类型返回不同的响应 const isValidationError errors.some(e e instanceof InputError || e.message.includes(验证失败) ) return { success: false, errors: isValidationError ? errors.map(e ({ message: e.message, code: VALIDATION_ERROR })) : [{ message: 服务器内部错误, code: INTERNAL_ERROR }] } }) 监控和调试使用trace函数监控认证流程// 跟踪认证流程 const tracedRegister trace(registerUser, { onStart: (input) console.log(开始注册:, input.email), onSuccess: (result) console.log(注册成功:, result.userId), onFailure: (errors) console.log(注册失败:, errors) })总结通过composable-functions构建用户认证系统我们获得了✅类型安全- 从输入验证到数据库操作全程类型检查 ✅可组合性- 将复杂流程拆分为可重用的函数单元 ✅错误处理- 统一的错误处理机制避免遗漏 ✅可测试性- 每个函数都可以独立测试 ✅可维护性- 清晰的函数组合易于理解和修改这个实战案例展示了composable-functions在构建企业级认证系统时的强大能力。通过函数组合的模式我们能够创建出既安全又易于维护的认证解决方案为现代Web应用提供坚实的用户认证基础。想要了解更多关于composable-functions的高级用法可以参考项目中的示例代码和API文档探索更多函数组合的可能性。【免费下载链接】domain-functionsTypes and functions to make composition easy and safe项目地址: https://gitcode.com/gh_mirrors/do/domain-functions创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考