refactor: rename ExternalInfo to ExternalUser and update related functions for consistency
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -28,9 +28,9 @@ func NewServer() (*iris.Application, error) {
|
||||
app := iris.New()
|
||||
corsHandler := cors.New().
|
||||
AllowOrigin("*").
|
||||
AllowHeaders("Origin", "Content-Type", "Accept", "Authorization", "X-Requested-With", "X-Guest-Id", "X-Channel-Id", "X-External-Source", "X-External-Id", "X-External-Name").
|
||||
AllowHeaders("Origin", "Content-Type", "Accept", "Authorization", "X-Requested-With", "X-Guest-Id", "X-Channel-Id", "X-External-Id", "X-External-Name").
|
||||
MaxAge(600).
|
||||
ExposeHeaders("Content-Length", "Content-Type", "Authorization", "X-Guest-Id", "X-Channel-Id", "X-External-Source", "X-External-Id", "X-External-Name").
|
||||
ExposeHeaders("Content-Length", "Content-Type", "Authorization", "X-Guest-Id", "X-Channel-Id", "X-External-Id", "X-External-Name").
|
||||
Handler()
|
||||
app.UseRouter(func(ctx iris.Context) {
|
||||
// WebSocket upgrade is validated by the upgrader's origin policy.
|
||||
@@ -95,8 +95,8 @@ func addRouter(app *iris.Application) {
|
||||
mvc.Configure(app.Party("/api"), func(m *mvc.Application) {
|
||||
m.Party("/auth").Handle(new(api.AuthController))
|
||||
m.Party("/channel").Handle(new(api.ChannelController))
|
||||
m.Party("/conversation", middleware.ExternalInfoMiddleware).Handle(new(api.ConversationController))
|
||||
m.Party("/message", middleware.ExternalInfoMiddleware).Handle(new(api.MessageController))
|
||||
m.Party("/conversation", middleware.ExternalUserMiddleware).Handle(new(api.ConversationController))
|
||||
m.Party("/message", middleware.ExternalUserMiddleware).Handle(new(api.MessageController))
|
||||
})
|
||||
|
||||
mvc.Configure(app.Party("/api/ws"), func(m *mvc.Application) {
|
||||
|
||||
@@ -20,7 +20,7 @@ func (c *ConversationController) GetBy(id int64) *web.JsonResult {
|
||||
if services.ChannelService.GetEnabledChannel(c.Ctx) == nil {
|
||||
return web.JsonErrorMsg("接入渠道未初始化")
|
||||
}
|
||||
external := irisx.GetExternalInfo(c.Ctx)
|
||||
external := irisx.GetExternalUser(c.Ctx)
|
||||
if external == nil {
|
||||
return web.JsonErrorMsg("外部身份未初始化")
|
||||
}
|
||||
@@ -45,7 +45,7 @@ func (c *ConversationController) PostCreate_or_match() *web.JsonResult {
|
||||
if channel == nil {
|
||||
return web.JsonErrorMsg("接入渠道未初始化")
|
||||
}
|
||||
external := irisx.GetExternalInfo(c.Ctx)
|
||||
external := irisx.GetExternalUser(c.Ctx)
|
||||
if external == nil {
|
||||
return web.JsonErrorMsg("外部身份未初始化")
|
||||
}
|
||||
@@ -61,7 +61,7 @@ func (c *ConversationController) PostClose() *web.JsonResult {
|
||||
if services.ChannelService.GetEnabledChannel(c.Ctx) == nil {
|
||||
return web.JsonErrorMsg("接入渠道未初始化")
|
||||
}
|
||||
external := irisx.GetExternalInfo(c.Ctx)
|
||||
external := irisx.GetExternalUser(c.Ctx)
|
||||
if external == nil {
|
||||
return web.JsonErrorMsg("外部身份未初始化")
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ func (c *MessageController) AnyList() *web.JsonResult {
|
||||
if services.ChannelService.GetEnabledChannel(c.Ctx) == nil {
|
||||
return web.JsonErrorMsg("接入渠道未初始化")
|
||||
}
|
||||
external := irisx.GetExternalInfo(c.Ctx)
|
||||
external := irisx.GetExternalUser(c.Ctx)
|
||||
if external == nil {
|
||||
return web.JsonErrorMsg("外部身份未初始化")
|
||||
}
|
||||
@@ -57,7 +57,7 @@ func (c *MessageController) PostSend() *web.JsonResult {
|
||||
if services.ChannelService.GetEnabledChannel(c.Ctx) == nil {
|
||||
return web.JsonErrorMsg("接入渠道未初始化")
|
||||
}
|
||||
external := irisx.GetExternalInfo(c.Ctx)
|
||||
external := irisx.GetExternalUser(c.Ctx)
|
||||
if external == nil {
|
||||
return web.JsonErrorMsg("外部身份未初始化")
|
||||
}
|
||||
@@ -78,7 +78,7 @@ func (c *MessageController) PostRead() *web.JsonResult {
|
||||
if services.ChannelService.GetEnabledChannel(c.Ctx) == nil {
|
||||
return web.JsonErrorMsg("接入渠道未初始化")
|
||||
}
|
||||
external := irisx.GetExternalInfo(c.Ctx)
|
||||
external := irisx.GetExternalUser(c.Ctx)
|
||||
if external == nil {
|
||||
return web.JsonErrorMsg("外部身份未初始化")
|
||||
}
|
||||
@@ -97,7 +97,7 @@ func (c *MessageController) PostUpload_image() *web.JsonResult {
|
||||
if services.ChannelService.GetEnabledChannel(c.Ctx) == nil {
|
||||
return web.JsonErrorMsg("接入渠道未初始化")
|
||||
}
|
||||
external := irisx.GetExternalInfo(c.Ctx)
|
||||
external := irisx.GetExternalUser(c.Ctx)
|
||||
if external == nil {
|
||||
return web.JsonErrorMsg("外部身份未初始化")
|
||||
}
|
||||
@@ -142,7 +142,7 @@ func (c *MessageController) PostUpload_attachment() *web.JsonResult {
|
||||
if services.ChannelService.GetEnabledChannel(c.Ctx) == nil {
|
||||
return web.JsonErrorMsg("接入渠道未初始化")
|
||||
}
|
||||
external := irisx.GetExternalInfo(c.Ctx)
|
||||
external := irisx.GetExternalUser(c.Ctx)
|
||||
if external == nil {
|
||||
return web.JsonErrorMsg("外部身份未初始化")
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/mlogclub/simple/web"
|
||||
)
|
||||
|
||||
func ExternalInfoMiddleware(ctx iris.Context) {
|
||||
func ExternalUserMiddleware(ctx iris.Context) {
|
||||
channel := services.ChannelService.GetEnabledChannel(ctx)
|
||||
if channel == nil {
|
||||
ctx.StopExecution()
|
||||
@@ -17,12 +17,12 @@ func ExternalInfoMiddleware(ctx iris.Context) {
|
||||
return
|
||||
}
|
||||
secret := services.ChannelService.GetUserTokenSecret(channel)
|
||||
ext, err := openidentity.GetExternalInfo(ctx, secret)
|
||||
ext, err := openidentity.GetExternalUser(ctx, secret)
|
||||
if err != nil {
|
||||
ctx.StopExecution()
|
||||
_ = ctx.JSON(web.JsonError(err))
|
||||
return
|
||||
}
|
||||
irisx.SetExternalInfo(ctx, ext)
|
||||
irisx.SetExternalUser(ctx, ext)
|
||||
ctx.Next()
|
||||
}
|
||||
|
||||
@@ -23,13 +23,3 @@ func GetExternalSourceLabel(v ExternalSource) string {
|
||||
}
|
||||
return string(v)
|
||||
}
|
||||
|
||||
// IsAllowedOpenImExternalSource 开放 IM 入口允许的外部来源(闭集校验)。
|
||||
func IsAllowedOpenImExternalSource(s ExternalSource) bool {
|
||||
switch s {
|
||||
case ExternalSourceGuest, ExternalSourceUser:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,16 +9,16 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
ctxKeyExternalInfo = "externalInfo"
|
||||
ctxKeyExternalUser = "externalUser"
|
||||
)
|
||||
|
||||
func SetExternalInfo(ctx iris.Context, ext *openidentity.ExternalInfo) {
|
||||
ctx.Values().Set(ctxKeyExternalInfo, ext)
|
||||
func SetExternalUser(ctx iris.Context, ext *openidentity.ExternalUser) {
|
||||
ctx.Values().Set(ctxKeyExternalUser, ext)
|
||||
}
|
||||
|
||||
func GetExternalInfo(ctx iris.Context) *openidentity.ExternalInfo {
|
||||
v := ctx.Values().Get(ctxKeyExternalInfo)
|
||||
ext, _ := v.(*openidentity.ExternalInfo)
|
||||
func GetExternalUser(ctx iris.Context) *openidentity.ExternalUser {
|
||||
v := ctx.Values().Get(ctxKeyExternalUser)
|
||||
ext, _ := v.(*openidentity.ExternalUser)
|
||||
return ext
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Package openidentity 解析开放 IM 场景下的外部访客身份(HTTP Header / Query),与 JSON 请求体 DTO 解耦。
|
||||
package openidentity
|
||||
|
||||
import (
|
||||
@@ -14,8 +13,8 @@ import (
|
||||
"github.com/mlogclub/simple/web/params"
|
||||
)
|
||||
|
||||
// ExternalInfo 外部访客身份(IM 客户),与站内 AuthPrincipal 区分。
|
||||
type ExternalInfo struct {
|
||||
// ExternalUser 外部访客身份(IM 客户),与站内 AuthPrincipal 区分。
|
||||
type ExternalUser struct {
|
||||
ExternalSource enums.ExternalSource `json:"externalSource"`
|
||||
ExternalID string `json:"externalId"`
|
||||
ExternalName string `json:"externalName"`
|
||||
@@ -27,37 +26,19 @@ type UserTokenClaims struct {
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
func GetExternalInfo(ctx iris.Context, secret string) (*ExternalInfo, error) {
|
||||
func GetExternalUser(ctx iris.Context, secret string) (*ExternalUser, error) {
|
||||
if userToken := getUserToken(ctx); strs.IsNotBlank(userToken) {
|
||||
claims, err := verifyUserToken(userToken, secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ExternalInfo{
|
||||
return &ExternalUser{
|
||||
ExternalSource: enums.ExternalSourceUser,
|
||||
ExternalID: claims.UserID,
|
||||
ExternalName: claims.Name,
|
||||
}, nil
|
||||
}
|
||||
externalSource, err := getExternalSource(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !enums.IsAllowedOpenImExternalSource(externalSource) {
|
||||
return nil, errorsx.InvalidParam("不支持的外部来源")
|
||||
}
|
||||
if externalSource == enums.ExternalSourceUser {
|
||||
return nil, errorsx.Unauthorized("用户身份不能为空")
|
||||
}
|
||||
externalID, err := getExternalID(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ExternalInfo{
|
||||
ExternalSource: externalSource,
|
||||
ExternalID: externalID,
|
||||
ExternalName: getExternalName(ctx),
|
||||
}, nil
|
||||
return getGuestUser(ctx)
|
||||
}
|
||||
|
||||
func verifyUserToken(userToken, secret string) (*UserTokenClaims, error) {
|
||||
@@ -113,26 +94,24 @@ func getUserToken(ctx iris.Context) string {
|
||||
return strings.TrimSpace(userToken)
|
||||
}
|
||||
|
||||
func getExternalSource(ctx iris.Context) (enums.ExternalSource, error) {
|
||||
externalSource := ctx.GetHeader("X-External-Source")
|
||||
if strs.IsBlank(externalSource) {
|
||||
externalSource, _ = params.Get(ctx, "externalSource")
|
||||
func getGuestUser(ctx iris.Context) (*ExternalUser, error) {
|
||||
externalID := getExternalID(ctx)
|
||||
if strs.IsBlank(externalID) {
|
||||
return nil, errorsx.Unauthorized("用户标识不能为空")
|
||||
}
|
||||
if strs.IsBlank(externalSource) {
|
||||
return "", errorsx.Unauthorized("用户来源不能为空")
|
||||
}
|
||||
return enums.ExternalSource(strings.TrimSpace(externalSource)), nil
|
||||
return &ExternalUser{
|
||||
ExternalSource: enums.ExternalSourceGuest,
|
||||
ExternalID: externalID,
|
||||
ExternalName: getExternalName(ctx),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getExternalID(ctx iris.Context) (string, error) {
|
||||
func getExternalID(ctx iris.Context) string {
|
||||
externalID := ctx.GetHeader("X-External-Id")
|
||||
if strs.IsBlank(externalID) {
|
||||
externalID, _ = params.Get(ctx, "externalId")
|
||||
}
|
||||
if strs.IsBlank(externalID) {
|
||||
return "", errorsx.Unauthorized("用户标识不能为空")
|
||||
}
|
||||
return strings.TrimSpace(externalID), nil
|
||||
return externalID
|
||||
}
|
||||
|
||||
func getExternalName(ctx iris.Context) string {
|
||||
@@ -140,11 +119,12 @@ func getExternalName(ctx iris.Context) string {
|
||||
if strs.IsBlank(externalName) {
|
||||
externalName, _ = params.Get(ctx, "externalName")
|
||||
}
|
||||
return decodeExternalDisplayName(externalName)
|
||||
if strs.IsNotBlank(externalName) {
|
||||
externalName, _ = url.QueryUnescape(externalName)
|
||||
}
|
||||
return externalName
|
||||
}
|
||||
|
||||
// decodeExternalDisplayName 将客户端对 X-External-Name / externalName 做的 encodeURIComponent 还原为 UTF-8。
|
||||
// 无百分号编码时 QueryUnescape 原样返回,解码失败则保留原串(兼容异常或旧客户端明文)。
|
||||
func decodeExternalDisplayName(s string) string {
|
||||
s = strings.TrimSpace(s)
|
||||
if s == "" {
|
||||
|
||||
@@ -69,12 +69,12 @@ func (s *conversationParticipantService) Delete(id int64) {
|
||||
repositories.ConversationParticipantRepository.Delete(sqls.DB(), id)
|
||||
}
|
||||
|
||||
func (s *conversationParticipantService) CreateCustomerParticipant(ctx *sqls.TxContext, conversationID int64, externalInfo openidentity.ExternalInfo) error {
|
||||
func (s *conversationParticipantService) CreateCustomerParticipant(ctx *sqls.TxContext, conversationID int64, externalUser openidentity.ExternalUser) error {
|
||||
return repositories.ConversationParticipantRepository.Create(ctx.Tx, &models.ConversationParticipant{
|
||||
ConversationID: conversationID,
|
||||
ParticipantType: string(enums.IMParticipantTypeCustomer),
|
||||
ParticipantID: 0,
|
||||
ExternalParticipantID: externalInfo.ExternalID,
|
||||
ExternalParticipantID: externalUser.ExternalID,
|
||||
JoinedAt: new(time.Now()),
|
||||
Status: enums.StatusOk,
|
||||
AuditFields: utils.BuildAuditFields(nil),
|
||||
|
||||
@@ -47,7 +47,7 @@ func agentReaderCursor(operator *dto.AuthPrincipal) (readerCursor, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func customerReaderCursor(external *openidentity.ExternalInfo) (readerCursor, error) {
|
||||
func customerReaderCursor(external *openidentity.ExternalUser) (readerCursor, error) {
|
||||
if external == nil || strings.TrimSpace(external.ExternalID) == "" {
|
||||
return readerCursor{}, errorsx.Unauthorized("外部用户标识不能为空")
|
||||
}
|
||||
@@ -126,7 +126,7 @@ func (s *conversationReadStateService) GetByAgentReader(conversationID int64, op
|
||||
}
|
||||
|
||||
// GetByCustomerReader 查询 IM 客户侧已读游标(按 ExternalID)。
|
||||
func (s *conversationReadStateService) GetByCustomerReader(conversationID int64, external *openidentity.ExternalInfo) *models.ConversationReadState {
|
||||
func (s *conversationReadStateService) GetByCustomerReader(conversationID int64, external *openidentity.ExternalUser) *models.ConversationReadState {
|
||||
if external == nil || strings.TrimSpace(external.ExternalID) == "" {
|
||||
return nil
|
||||
}
|
||||
@@ -181,7 +181,7 @@ func (s *conversationReadStateService) MarkAgentRead(ctx *sqls.TxContext, conver
|
||||
}
|
||||
|
||||
// MarkCustomerRead 在事务内更新/创建 IM 客户已读游标。
|
||||
func (s *conversationReadStateService) MarkCustomerRead(ctx *sqls.TxContext, conversation *models.Conversation, external *openidentity.ExternalInfo, message *models.Message, now time.Time) (*models.ConversationReadState, error) {
|
||||
func (s *conversationReadStateService) MarkCustomerRead(ctx *sqls.TxContext, conversation *models.Conversation, external *openidentity.ExternalUser, message *models.Message, now time.Time) (*models.ConversationReadState, error) {
|
||||
c, err := customerReaderCursor(external)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -100,7 +100,7 @@ func (s *conversationService) getLatestNotFinishedByCustomerID(db *gorm.DB, cust
|
||||
return repositories.ConversationRepository.FindOne(db, cnd)
|
||||
}
|
||||
|
||||
func (s *conversationService) Create(externalInfo openidentity.ExternalInfo, channelID, aiAgentID int64) (*models.Conversation, error) {
|
||||
func (s *conversationService) Create(externalUser openidentity.ExternalUser, channelID, aiAgentID int64) (*models.Conversation, error) {
|
||||
aiAgent := AIAgentService.Get(aiAgentID)
|
||||
if aiAgent == nil || aiAgent.Status != enums.StatusOk {
|
||||
return nil, errorsx.InvalidParam("AI Agent not found")
|
||||
@@ -109,7 +109,7 @@ func (s *conversationService) Create(externalInfo openidentity.ExternalInfo, cha
|
||||
var conversation *models.Conversation
|
||||
created := false
|
||||
if err := sqls.WithTransaction(func(ctx *sqls.TxContext) error {
|
||||
customerID, err := CustomerService.EnsureExternalCustomer(ctx.Tx, externalInfo)
|
||||
customerID, err := CustomerService.EnsureExternalCustomer(ctx.Tx, externalUser)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -146,7 +146,7 @@ func (s *conversationService) Create(externalInfo openidentity.ExternalInfo, cha
|
||||
if err := ctx.Tx.Create(conversation).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ConversationParticipantService.CreateCustomerParticipant(ctx, conversation.ID, externalInfo); err != nil {
|
||||
if err := ConversationParticipantService.CreateCustomerParticipant(ctx, conversation.ID, externalUser); err != nil {
|
||||
return err
|
||||
}
|
||||
return ConversationEventLogService.CreateEvent(ctx, conversation.ID, enums.IMEventTypeCreate, enums.IMSenderTypeCustomer, 0, "用户创建会话", "")
|
||||
@@ -378,12 +378,12 @@ func (s *conversationService) CloseConversation(conversationID int64, closeReaso
|
||||
return s.closeConversation(conversationID, enums.IMSenderTypeAgent, closeReason, operator)
|
||||
}
|
||||
|
||||
func (s *conversationService) CloseCustomerConversation(conversationID int64, externalInfo openidentity.ExternalInfo) error {
|
||||
func (s *conversationService) CloseCustomerConversation(conversationID int64, externalUser openidentity.ExternalUser) error {
|
||||
conversation := s.Get(conversationID)
|
||||
if conversation == nil {
|
||||
return errorsx.InvalidParam("会话不存在")
|
||||
}
|
||||
if !s.IsCustomerConversationOwner(conversation, externalInfo) {
|
||||
if !s.IsCustomerConversationOwner(conversation, externalUser) {
|
||||
return errorsx.Forbidden("无权访问该会话")
|
||||
}
|
||||
return s.closeConversation(conversationID, enums.IMSenderTypeCustomer, "", nil)
|
||||
@@ -477,7 +477,7 @@ func (s *conversationService) MarkAgentConversationReadToMessage(conversationID,
|
||||
}
|
||||
|
||||
// MarkCustomerConversationReadToMessage IM 客户将会话已读推进到指定消息(需为会话归属外部身份)。
|
||||
func (s *conversationService) MarkCustomerConversationReadToMessage(conversationID, messageID int64, external *openidentity.ExternalInfo) error {
|
||||
func (s *conversationService) MarkCustomerConversationReadToMessage(conversationID, messageID int64, external *openidentity.ExternalUser) error {
|
||||
if external == nil || strings.TrimSpace(external.ExternalID) == "" {
|
||||
return errorsx.Unauthorized("外部用户标识不能为空")
|
||||
}
|
||||
@@ -500,7 +500,7 @@ func (s *conversationService) MarkCustomerConversationReadToMessage(conversation
|
||||
return nil
|
||||
}
|
||||
|
||||
func displayExternalName(ext *openidentity.ExternalInfo) string {
|
||||
func displayExternalName(ext *openidentity.ExternalUser) string {
|
||||
if ext == nil {
|
||||
return ""
|
||||
}
|
||||
@@ -541,7 +541,7 @@ func (a agentConversationReadActor) conversationUpdateAudit() (int64, string) {
|
||||
}
|
||||
|
||||
type customerConversationReadActor struct {
|
||||
external *openidentity.ExternalInfo
|
||||
external *openidentity.ExternalUser
|
||||
}
|
||||
|
||||
func (a customerConversationReadActor) isAgentSide() bool { return false }
|
||||
@@ -651,15 +651,15 @@ func (s *conversationService) countUnreadByState(ctx *sqls.TxContext, conversati
|
||||
return int(count), err
|
||||
}
|
||||
|
||||
func (s *conversationService) IsCustomerConversationOwner(conversation *models.Conversation, externalInfo openidentity.ExternalInfo) bool {
|
||||
func (s *conversationService) IsCustomerConversationOwner(conversation *models.Conversation, externalUser openidentity.ExternalUser) bool {
|
||||
if conversation == nil {
|
||||
return false
|
||||
}
|
||||
extID := strings.TrimSpace(externalInfo.ExternalID)
|
||||
if extID == "" || strings.TrimSpace(string(externalInfo.ExternalSource)) == "" || conversation.CustomerID <= 0 {
|
||||
extID := strings.TrimSpace(externalUser.ExternalID)
|
||||
if extID == "" || strings.TrimSpace(string(externalUser.ExternalSource)) == "" || conversation.CustomerID <= 0 {
|
||||
return false
|
||||
}
|
||||
identity := repositories.CustomerIdentityRepository.GetBy(sqls.DB(), externalInfo.ExternalSource, extID)
|
||||
identity := repositories.CustomerIdentityRepository.GetBy(sqls.DB(), externalUser.ExternalSource, extID)
|
||||
if identity == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -113,9 +113,9 @@ func (s *customerService) CountByCompanyIDs(companyIDs []int64) map[int64]int64
|
||||
return repositories.CustomerRepository.CountByCompanyIDs(sqls.DB(), companyIDs, int(enums.StatusDeleted))
|
||||
}
|
||||
|
||||
func (s *customerService) EnsureExternalCustomer(db *gorm.DB, externalInfo openidentity.ExternalInfo) (int64, error) {
|
||||
externalSource := externalInfo.ExternalSource
|
||||
externalID := strings.TrimSpace(externalInfo.ExternalID)
|
||||
func (s *customerService) EnsureExternalCustomer(db *gorm.DB, externalUser openidentity.ExternalUser) (int64, error) {
|
||||
externalSource := externalUser.ExternalSource
|
||||
externalID := strings.TrimSpace(externalUser.ExternalID)
|
||||
if strings.TrimSpace(string(externalSource)) == "" || externalID == "" {
|
||||
return 0, errorsx.Unauthorized("外部用户标识不能为空")
|
||||
}
|
||||
@@ -129,7 +129,7 @@ func (s *customerService) EnsureExternalCustomer(db *gorm.DB, externalInfo openi
|
||||
}
|
||||
|
||||
customer := &models.Customer{
|
||||
Name: buildExternalCustomerName(externalInfo),
|
||||
Name: buildExternalCustomerName(externalUser),
|
||||
LastActiveAt: &now,
|
||||
Status: enums.StatusOk,
|
||||
AuditFields: utils.BuildAuditFields(nil),
|
||||
@@ -149,11 +149,11 @@ func (s *customerService) EnsureExternalCustomer(db *gorm.DB, externalInfo openi
|
||||
return customer.ID, nil
|
||||
}
|
||||
|
||||
func buildExternalCustomerName(externalInfo openidentity.ExternalInfo) string {
|
||||
if strs.IsNotBlank(externalInfo.ExternalName) {
|
||||
return externalInfo.ExternalName
|
||||
func buildExternalCustomerName(externalUser openidentity.ExternalUser) string {
|
||||
if strs.IsNotBlank(externalUser.ExternalName) {
|
||||
return externalUser.ExternalName
|
||||
}
|
||||
return "访客" + hashUUID(externalInfo.ExternalID)
|
||||
return "访客" + hashUUID(externalUser.ExternalID)
|
||||
}
|
||||
|
||||
func hashUUID(uuid string) string {
|
||||
|
||||
@@ -127,7 +127,7 @@ func (s *messageService) GetConversationReadTarget(conversationID, messageID int
|
||||
return s.FindOne(sqls.NewCnd().Eq("conversation_id", conversationID).Desc("seq_no").Desc("id")), nil
|
||||
}
|
||||
|
||||
func (s *messageService) SendMessage(conversationID int64, senderType enums.IMSenderType, reqSenderID int64, clientMsgID string, messageType enums.IMMessageType, content, payload string, operator *dto.AuthPrincipal, external *openidentity.ExternalInfo) (*models.Message, error) {
|
||||
func (s *messageService) SendMessage(conversationID int64, senderType enums.IMSenderType, reqSenderID int64, clientMsgID string, messageType enums.IMMessageType, content, payload string, operator *dto.AuthPrincipal, external *openidentity.ExternalUser) (*models.Message, error) {
|
||||
switch senderType {
|
||||
case enums.IMSenderTypeAgent:
|
||||
return s.sendMessage(conversationID, enums.IMSenderTypeAgent, reqSenderID, clientMsgID, messageType, content, payload, operator, nil)
|
||||
@@ -243,13 +243,13 @@ func (s *messageService) SendAIMessage(conversationID int64, aiAgentID int64, cl
|
||||
return s.sendMessage(conversationID, enums.IMSenderTypeAI, aiAgentID, clientMsgID, messageType, content, payload, operator, nil)
|
||||
}
|
||||
|
||||
func (s *messageService) SendCustomerMessage(conversationID int64, clientMsgID string, messageType enums.IMMessageType, content, payload string, external openidentity.ExternalInfo) (*models.Message, error) {
|
||||
func (s *messageService) SendCustomerMessage(conversationID int64, clientMsgID string, messageType enums.IMMessageType, content, payload string, external openidentity.ExternalUser) (*models.Message, error) {
|
||||
ext := external
|
||||
return s.sendMessage(conversationID, enums.IMSenderTypeCustomer, 0, clientMsgID, messageType, content, payload, nil, &ext)
|
||||
}
|
||||
|
||||
func (s *messageService) sendMessage(conversationID int64, senderType enums.IMSenderType, reqSenderID int64, clientMsgID string,
|
||||
messageType enums.IMMessageType, content, payload string, operator *dto.AuthPrincipal, external *openidentity.ExternalInfo) (*models.Message, error) {
|
||||
messageType enums.IMMessageType, content, payload string, operator *dto.AuthPrincipal, external *openidentity.ExternalUser) (*models.Message, error) {
|
||||
|
||||
if senderType == enums.IMSenderTypeCustomer {
|
||||
if external == nil || strings.TrimSpace(external.ExternalID) == "" {
|
||||
@@ -493,7 +493,7 @@ func (s *messageService) normalizeMessageContent(conversationID int64, messageTy
|
||||
}
|
||||
}
|
||||
|
||||
func (s *messageService) ValidateConversationSender(conversationID int64, senderType enums.IMSenderType, operator *dto.AuthPrincipal, external *openidentity.ExternalInfo) (*models.Conversation, error) {
|
||||
func (s *messageService) ValidateConversationSender(conversationID int64, senderType enums.IMSenderType, operator *dto.AuthPrincipal, external *openidentity.ExternalUser) (*models.Conversation, error) {
|
||||
conversation := ConversationService.Get(conversationID)
|
||||
if conversation == nil {
|
||||
return nil, errorsx.InvalidParam("会话不存在")
|
||||
|
||||
@@ -229,7 +229,7 @@ type ClientSession struct {
|
||||
ID string
|
||||
Conn *websocket.Conn
|
||||
Principal *dto.AuthPrincipal
|
||||
External *openidentity.ExternalInfo
|
||||
External *openidentity.ExternalUser
|
||||
Role string
|
||||
TerminalType string
|
||||
Topics map[string]struct{}
|
||||
|
||||
@@ -63,10 +63,10 @@ func (s *wsService) HandleOpenWS(ctx iris.Context) {
|
||||
|
||||
var (
|
||||
principal = AuthService.GetAuthPrincipal(ctx)
|
||||
external *openidentity.ExternalInfo
|
||||
external *openidentity.ExternalUser
|
||||
)
|
||||
if principal == nil {
|
||||
ext, err := openidentity.GetExternalInfoWithUserTokenSecret(ctx, ChannelService.GetUserTokenSecret(channel))
|
||||
ext, err := openidentity.GetExternalUser(ctx, ChannelService.GetUserTokenSecret(channel))
|
||||
if err != nil {
|
||||
_ = ctx.StopWithJSON(iris.StatusUnauthorized, web.JsonError(err))
|
||||
return
|
||||
@@ -80,7 +80,7 @@ func (s *wsService) HandleOpenWS(ctx iris.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *wsService) upgradeConnection(ctx iris.Context, principal *dto.AuthPrincipal, external *openidentity.ExternalInfo, role string) error {
|
||||
func (s *wsService) upgradeConnection(ctx iris.Context, principal *dto.AuthPrincipal, external *openidentity.ExternalUser, role string) error {
|
||||
conn, err := s.upgrader.Upgrade(ctx.ResponseWriter().Naive(), ctx.Request(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -119,7 +119,7 @@ func (s *wxWorkKFInboundService) handleTextMessage(item syncmsg.Message) error {
|
||||
enums.IMMessageTypeText,
|
||||
strings.TrimSpace(payload.Text.Content),
|
||||
"",
|
||||
s.buildExternalInfo(payload.ExternalUserID),
|
||||
s.buildExternalUser(payload.ExternalUserID),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -149,7 +149,7 @@ func (s *wxWorkKFInboundService) handleImageMessage(item syncmsg.Message) error
|
||||
enums.IMMessageTypeImage,
|
||||
content,
|
||||
canonicalPayload,
|
||||
s.buildExternalInfo(payload.ExternalUserID),
|
||||
s.buildExternalUser(payload.ExternalUserID),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -179,7 +179,7 @@ func (s *wxWorkKFInboundService) handleFileMessage(item syncmsg.Message) error {
|
||||
enums.IMMessageTypeAttachment,
|
||||
content,
|
||||
canonicalPayload,
|
||||
s.buildExternalInfo(payload.ExternalUserID),
|
||||
s.buildExternalUser(payload.ExternalUserID),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -203,7 +203,7 @@ func (s *wxWorkKFInboundService) handleUnsupportedMessage(item syncmsg.Message)
|
||||
enums.IMMessageTypeText,
|
||||
content,
|
||||
string(item.OriginData),
|
||||
s.buildExternalInfo(base.ExternalUserID),
|
||||
s.buildExternalUser(base.ExternalUserID),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -376,7 +376,7 @@ func (s *wxWorkKFInboundService) ensureConversation(base syncmsg.BaseMessage, pr
|
||||
return nil, err
|
||||
}
|
||||
|
||||
external := s.buildExternalInfo(externalID)
|
||||
external := s.buildExternalUser(externalID)
|
||||
conversation, err := ConversationService.Create(external, channel.ID, channel.AIAgentID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -558,8 +558,8 @@ func (s *wxWorkKFInboundService) getChannelByOpenKfID(openKfID string) (*models.
|
||||
return channel, nil
|
||||
}
|
||||
|
||||
func (s *wxWorkKFInboundService) buildExternalInfo(externalUserID string) openidentity.ExternalInfo {
|
||||
return openidentity.ExternalInfo{
|
||||
func (s *wxWorkKFInboundService) buildExternalUser(externalUserID string) openidentity.ExternalUser {
|
||||
return openidentity.ExternalUser{
|
||||
ExternalSource: enums.ExternalSourceWxWorkKF,
|
||||
ExternalID: strings.TrimSpace(externalUserID),
|
||||
ExternalName: strings.TrimSpace(externalUserID),
|
||||
|
||||
Reference in New Issue
Block a user