auth.service.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import debug from 'debug';
  2. import { JWTService, JWTPayload } from './jwt.service.js';
  3. import { EnableStatus } from '@d8d/shared-types';
  4. const logger = {
  5. info: debug('auth-core:auth:info'),
  6. error: debug('auth-core:auth:error')
  7. }
  8. export interface User {
  9. id: number;
  10. username: string;
  11. nickname?: string;
  12. isDisabled: EnableStatus;
  13. roles?: Array<{ name: string }>;
  14. openid?: string;
  15. }
  16. export interface UserService {
  17. getUserByUsername(username: string): Promise<User | null>;
  18. verifyPassword(user: User, password: string): Promise<boolean>;
  19. createUser(userData: Partial<User> & { username: string; password: string }): Promise<User>;
  20. }
  21. export class AuthService {
  22. private userService: UserService;
  23. constructor(userService: UserService) {
  24. this.userService = userService;
  25. }
  26. async login(username: string, password: string): Promise<{ token: string; user: User }> {
  27. try {
  28. const user = await this.userService.getUserByUsername(username);
  29. if (!user) {
  30. throw new Error('用户不存在');
  31. }
  32. // 检查用户是否被禁用
  33. if (user.isDisabled === EnableStatus.DISABLED) {
  34. throw new Error('用户账户已被禁用');
  35. }
  36. const isPasswordValid = await this.userService.verifyPassword(user, password);
  37. if (!isPasswordValid) {
  38. throw new Error('密码错误');
  39. }
  40. const payload: JWTPayload = {
  41. id: user.id,
  42. username: user.username,
  43. roles: user.roles?.map(role => role.name) || [],
  44. openid: user.openid || undefined
  45. };
  46. const token = JWTService.generateToken(payload);
  47. return { token, user };
  48. } catch (error) {
  49. logger.error('登录错误:', error);
  50. throw error;
  51. }
  52. }
  53. generateToken(user: User, expiresIn?: string): string {
  54. const payload: JWTPayload = {
  55. id: user.id,
  56. username: user.username,
  57. roles: user.roles?.map(role => role.name) || [],
  58. openid: user.openid || undefined
  59. };
  60. return JWTService.generateToken(payload, expiresIn);
  61. }
  62. verifyToken(token: string): JWTPayload {
  63. return JWTService.verifyToken(token);
  64. }
  65. async logout(token: string): Promise<void> {
  66. try {
  67. // 验证token有效性
  68. const decoded = this.verifyToken(token);
  69. if (!decoded) {
  70. throw new Error('无效的token');
  71. }
  72. // 实际项目中这里可以添加token黑名单逻辑
  73. // 或者调用Redis等缓存服务使token失效
  74. return Promise.resolve();
  75. } catch (error) {
  76. logger.error('登出失败:', error);
  77. throw error;
  78. }
  79. }
  80. /**
  81. * 验证用户权限
  82. * @param user 用户信息
  83. * @param requiredRole 需要的角色
  84. * @returns 是否有权限
  85. */
  86. hasPermission(user: User, requiredRole: string): boolean {
  87. return user.roles?.some(role => role.name === requiredRole) || false;
  88. }
  89. /**
  90. * 验证用户是否有任意一个权限
  91. * @param user 用户信息
  92. * @param requiredRoles 需要的角色列表
  93. * @returns 是否有权限
  94. */
  95. hasAnyPermission(user: User, requiredRoles: string[]): boolean {
  96. return requiredRoles.some(role => this.hasPermission(user, role));
  97. }
  98. }