user_service.go 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. package service
  2. import (
  3. "errors"
  4. "fmt"
  5. "strings"
  6. "github.com/2930134478/AI-CS/backend/models"
  7. "github.com/2930134478/AI-CS/backend/repository"
  8. "golang.org/x/crypto/bcrypt"
  9. "gorm.io/gorm"
  10. )
  11. // UserService 负责用户管理领域的业务编排。
  12. type UserService struct {
  13. users *repository.UserRepository
  14. aiConfigs *repository.AIConfigRepository
  15. }
  16. // NewUserService 创建 UserService 实例。
  17. func NewUserService(users *repository.UserRepository, aiConfigs *repository.AIConfigRepository) *UserService {
  18. return &UserService{
  19. users: users,
  20. aiConfigs: aiConfigs,
  21. }
  22. }
  23. // EffectivePermissions 计算用户“有效权限”。
  24. // - admin:全权限
  25. // - agent:取 user.Permissions(JSON);若为空则兼容默认仅 chat
  26. func (s *UserService) EffectivePermissions(user *models.User) []string {
  27. if user == nil {
  28. return nil
  29. }
  30. if user.Role == "admin" {
  31. return AllPermissionKeys()
  32. }
  33. keys := DecodePermissions(user.Permissions)
  34. if len(keys) == 0 {
  35. return DefaultAgentPermissions()
  36. }
  37. return keys
  38. }
  39. // CheckPermission 校验用户是否拥有指定权限(用于控制器强校验)。
  40. func (s *UserService) CheckPermission(userID uint, perm string) error {
  41. if userID == 0 {
  42. return errors.New("未授权访问,请提供 X-User-Id 请求头")
  43. }
  44. u, err := s.users.GetByID(userID)
  45. if err != nil || u == nil {
  46. return errors.New("用户不存在")
  47. }
  48. if u.Role == "admin" {
  49. return nil
  50. }
  51. for _, p := range s.EffectivePermissions(u) {
  52. if p == perm {
  53. return nil
  54. }
  55. }
  56. return fmt.Errorf("权限不足:缺少功能权限 %s", perm)
  57. }
  58. // ListUsers 获取所有用户列表。
  59. func (s *UserService) ListUsers() ([]UserSummary, error) {
  60. users, err := s.users.ListUsers()
  61. if err != nil {
  62. return nil, err
  63. }
  64. summaries := make([]UserSummary, 0, len(users))
  65. for _, user := range users {
  66. summaries = append(summaries, UserSummary{
  67. ID: user.ID,
  68. Username: user.Username,
  69. Role: user.Role,
  70. Permissions: s.EffectivePermissions(&user),
  71. Nickname: user.Nickname,
  72. Email: user.Email,
  73. AvatarURL: user.AvatarURL,
  74. ReceiveAIConversations: user.ReceiveAIConversations,
  75. CreatedAt: user.CreatedAt,
  76. UpdatedAt: user.UpdatedAt,
  77. })
  78. }
  79. return summaries, nil
  80. }
  81. // GetUser 获取用户详情。
  82. func (s *UserService) GetUser(id uint) (*UserSummary, error) {
  83. user, err := s.users.GetByID(id)
  84. if err != nil {
  85. if errors.Is(err, gorm.ErrRecordNotFound) {
  86. return nil, errors.New("用户不存在")
  87. }
  88. return nil, err
  89. }
  90. return &UserSummary{
  91. ID: user.ID,
  92. Username: user.Username,
  93. Role: user.Role,
  94. Permissions: s.EffectivePermissions(user),
  95. Nickname: user.Nickname,
  96. Email: user.Email,
  97. AvatarURL: user.AvatarURL,
  98. ReceiveAIConversations: user.ReceiveAIConversations,
  99. CreatedAt: user.CreatedAt,
  100. UpdatedAt: user.UpdatedAt,
  101. }, nil
  102. }
  103. // CreateUser 创建新用户。
  104. func (s *UserService) CreateUser(input CreateUserInput) (*UserSummary, error) {
  105. // 验证必填字段
  106. if input.Username == "" || input.Password == "" {
  107. return nil, errors.New("用户名和密码不能为空")
  108. }
  109. // 验证角色
  110. if input.Role != "admin" && input.Role != "agent" {
  111. return nil, errors.New("角色只能是 admin 或 agent")
  112. }
  113. // 检查用户名是否已存在
  114. if _, err := s.users.FindByUsername(input.Username); err == nil {
  115. return nil, ErrUsernameExists
  116. } else if !errors.Is(err, gorm.ErrRecordNotFound) {
  117. return nil, err
  118. }
  119. // 加密密码
  120. hash, err := bcrypt.GenerateFromPassword([]byte(input.Password), bcrypt.DefaultCost)
  121. if err != nil {
  122. return nil, errors.New("密码加密失败")
  123. }
  124. // 创建用户
  125. user := &models.User{
  126. Username: input.Username,
  127. Password: string(hash),
  128. Role: input.Role,
  129. ReceiveAIConversations: true, // 默认接收 AI 对话
  130. }
  131. // 权限:admin 默认全开(不存);agent 默认仅 chat
  132. if input.Role != "admin" {
  133. keys := input.Permissions
  134. if len(keys) == 0 {
  135. keys = DefaultAgentPermissions()
  136. }
  137. encoded, err := EncodePermissions(keys)
  138. if err != nil {
  139. return nil, err
  140. }
  141. user.Permissions = encoded
  142. }
  143. // 设置可选字段
  144. if input.Nickname != nil {
  145. user.Nickname = strings.TrimSpace(*input.Nickname)
  146. }
  147. if input.Email != nil {
  148. user.Email = strings.TrimSpace(*input.Email)
  149. }
  150. if err := s.users.Create(user); err != nil {
  151. return nil, err
  152. }
  153. return &UserSummary{
  154. ID: user.ID,
  155. Username: user.Username,
  156. Role: user.Role,
  157. Permissions: s.EffectivePermissions(user),
  158. Nickname: user.Nickname,
  159. Email: user.Email,
  160. AvatarURL: user.AvatarURL,
  161. ReceiveAIConversations: user.ReceiveAIConversations,
  162. CreatedAt: user.CreatedAt,
  163. UpdatedAt: user.UpdatedAt,
  164. }, nil
  165. }
  166. // UpdateUser 更新用户信息。
  167. func (s *UserService) UpdateUser(input UpdateUserInput) (*UserSummary, error) {
  168. // 检查用户是否存在
  169. currentUser, err := s.users.GetByID(input.UserID)
  170. if err != nil {
  171. if errors.Is(err, gorm.ErrRecordNotFound) {
  172. return nil, errors.New("用户不存在")
  173. }
  174. return nil, err
  175. }
  176. if currentUser == nil {
  177. return nil, errors.New("用户不存在")
  178. }
  179. // 构建更新字段
  180. updates := make(map[string]interface{})
  181. // 记录本次更新后的角色(用于决定 permissions 写入规则)
  182. nextRole := currentUser.Role
  183. // 更新角色
  184. if input.Role != nil {
  185. role := strings.TrimSpace(*input.Role)
  186. if role != "admin" && role != "agent" {
  187. return nil, errors.New("角色只能是 admin 或 agent")
  188. }
  189. updates["role"] = role
  190. nextRole = role
  191. }
  192. // 更新 permissions(仅对 agent 有意义;admin 视为全开,不存权限)
  193. if input.Permissions != nil {
  194. if nextRole == "admin" {
  195. updates["permissions"] = ""
  196. } else {
  197. keys := *input.Permissions
  198. if len(keys) == 0 {
  199. keys = DefaultAgentPermissions()
  200. }
  201. encoded, err := EncodePermissions(keys)
  202. if err != nil {
  203. return nil, err
  204. }
  205. updates["permissions"] = encoded
  206. }
  207. }
  208. // 更新昵称
  209. if input.Nickname != nil {
  210. updates["nickname"] = strings.TrimSpace(*input.Nickname)
  211. }
  212. // 更新邮箱
  213. if input.Email != nil {
  214. updates["email"] = strings.TrimSpace(*input.Email)
  215. }
  216. // 更新 AI 对话接收设置
  217. if input.ReceiveAIConversations != nil {
  218. updates["receive_ai_conversations"] = *input.ReceiveAIConversations
  219. }
  220. // 如果没有需要更新的字段,直接返回
  221. if len(updates) == 0 {
  222. return s.GetUser(input.UserID)
  223. }
  224. // 执行更新
  225. if err := s.users.UpdateFields(input.UserID, updates); err != nil {
  226. return nil, err
  227. }
  228. // 返回更新后的用户信息
  229. return s.GetUser(input.UserID)
  230. }
  231. // DeleteUser 删除用户。
  232. // 说明:为避免“孤儿配置”,删除前会将该用户名下 AI 配置自动转移给当前管理员。
  233. func (s *UserService) DeleteUser(id uint, currentUserID uint) (int64, error) {
  234. // 防止删除当前登录用户
  235. if id == currentUserID {
  236. return 0, errors.New("不能删除当前登录用户")
  237. }
  238. // 检查用户是否存在并获取用户信息
  239. user, err := s.users.GetByID(id)
  240. if err != nil {
  241. if errors.Is(err, gorm.ErrRecordNotFound) {
  242. return 0, errors.New("用户不存在")
  243. }
  244. return 0, err
  245. }
  246. // 演示站安全策略:管理员账号只能通过数据库维护,接口层禁止删除任何管理员。
  247. if user.Role == "admin" {
  248. return 0, errors.New("管理员账号不允许通过前端删除,请使用数据库维护")
  249. }
  250. // 将被删除用户名下 AI 配置转移到当前管理员,避免配置成为“无人维护”的孤儿数据。
  251. transferred := int64(0)
  252. if s.aiConfigs != nil {
  253. configCount, countErr := s.aiConfigs.CountByUserID(id)
  254. if countErr != nil {
  255. return 0, fmt.Errorf("统计用户关联 AI 配置失败: %w", countErr)
  256. }
  257. if configCount > 0 {
  258. moved, moveErr := s.aiConfigs.ReassignUser(id, currentUserID)
  259. if moveErr != nil {
  260. return 0, fmt.Errorf("转移用户关联 AI 配置失败: %w", moveErr)
  261. }
  262. transferred = moved
  263. }
  264. }
  265. // 执行删除
  266. if err := s.users.Delete(id); err != nil {
  267. return 0, err
  268. }
  269. return transferred, nil
  270. }
  271. // UpdateUserPassword 更新用户密码。
  272. func (s *UserService) UpdateUserPassword(input UpdatePasswordInput) error {
  273. // 检查用户是否存在
  274. user, err := s.users.GetByID(input.UserID)
  275. if err != nil {
  276. if errors.Is(err, gorm.ErrRecordNotFound) {
  277. return errors.New("用户不存在")
  278. }
  279. return err
  280. }
  281. // 演示站安全策略:管理员密码固定由环境/数据库维护,前端接口不允许改动。
  282. if user.Role == "admin" {
  283. return errors.New("管理员密码不允许通过前端修改,请使用数据库维护")
  284. }
  285. // 验证新密码
  286. if input.NewPassword == "" {
  287. return errors.New("新密码不能为空")
  288. }
  289. // 如果不是管理员操作,需要验证旧密码
  290. if !input.IsAdmin {
  291. if input.OldPassword == nil || *input.OldPassword == "" {
  292. return errors.New("需要提供旧密码")
  293. }
  294. if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(*input.OldPassword)); err != nil {
  295. return errors.New("旧密码不正确")
  296. }
  297. }
  298. // 加密新密码
  299. hash, err := bcrypt.GenerateFromPassword([]byte(input.NewPassword), bcrypt.DefaultCost)
  300. if err != nil {
  301. return errors.New("密码加密失败")
  302. }
  303. // 更新密码
  304. if err := s.users.UpdateFields(input.UserID, map[string]interface{}{
  305. "password": string(hash),
  306. }); err != nil {
  307. return err
  308. }
  309. return nil
  310. }