conversation_access.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. package service
  2. import (
  3. "crypto/subtle"
  4. "errors"
  5. "github.com/2930134478/AI-CS/backend/models"
  6. "github.com/2930134478/AI-CS/backend/utils"
  7. "gorm.io/gorm"
  8. )
  9. // ErrConversationAccessDenied 表示无权访问该会话(如缺少或错误的 access_token)。
  10. var ErrConversationAccessDenied = errors.New("无权限访问该会话")
  11. // EnsureConversationAccessToken 若会话尚无令牌则生成并持久化(兼容历史数据)。
  12. func (s *ConversationService) EnsureConversationAccessToken(conv *models.Conversation) (*models.Conversation, error) {
  13. if conv == nil {
  14. return nil, ErrConversationNotFound
  15. }
  16. if conv.AccessToken != "" {
  17. return conv, nil
  18. }
  19. token, err := utils.GenerateConversationAccessToken()
  20. if err != nil {
  21. return nil, err
  22. }
  23. if err := s.conversations.UpdateFields(conv.ID, map[string]interface{}{
  24. "access_token": token,
  25. }); err != nil {
  26. return nil, err
  27. }
  28. conv.AccessToken = token
  29. return conv, nil
  30. }
  31. // ValidateVisitorAccessToken 校验访客持有的会话 access_token。
  32. func (s *ConversationService) ValidateVisitorAccessToken(conversationID uint, accessToken string) error {
  33. if conversationID == 0 || accessToken == "" {
  34. return ErrConversationAccessDenied
  35. }
  36. conv, err := s.conversations.GetByID(conversationID)
  37. if err != nil {
  38. if errors.Is(err, gorm.ErrRecordNotFound) {
  39. return ErrConversationNotFound
  40. }
  41. return err
  42. }
  43. if conv.ConversationType != "visitor" {
  44. return ErrConversationAccessDenied
  45. }
  46. conv, err = s.EnsureConversationAccessToken(conv)
  47. if err != nil {
  48. return err
  49. }
  50. if subtle.ConstantTimeCompare([]byte(accessToken), []byte(conv.AccessToken)) != 1 {
  51. return ErrConversationAccessDenied
  52. }
  53. return nil
  54. }