diff --git a/backend/go-service/app/auth/service/auth_service.go b/backend/go-service/app/auth/service/auth_service.go index 2ba3f54..d481faa 100644 --- a/backend/go-service/app/auth/service/auth_service.go +++ b/backend/go-service/app/auth/service/auth_service.go @@ -180,6 +180,18 @@ func (s *AuthService) Login(ctx context.Context, req *dto.LoginRequest, clientIP return resp, nil } +func (s *AuthService) BuildLoginResponseForUser(ctx context.Context, user *model.User, clientIP, clientType string) (*dto.LoginResponse, error) { + if user == nil { + return nil, ErrUserNotFound + } + if err := s.checkUserStatus(user.Status); err != nil { + return nil, err + } + _ = s.userDAO.UpdateLastLogin(ctx, user.ID, clientIP) + roles, _ := s.roleDAO.GetUserRoleCodes(ctx, user.ID) + return s.buildLoginResponse(ctx, user, roles, clientType) +} + // AdminLogin 管理后台登录 // 与普通登录相同,但额外检查用户是否拥有 admin 或 super_admin 角色 // clientType 固定为 constants.ClientTypeAdmin diff --git a/backend/go-service/app/meeting/controller/meeting_controller.go b/backend/go-service/app/meeting/controller/meeting_controller.go index c0eed45..bfc4292 100644 --- a/backend/go-service/app/meeting/controller/meeting_controller.go +++ b/backend/go-service/app/meeting/controller/meeting_controller.go @@ -6,6 +6,7 @@ import ( "strconv" "strings" + authSvc "github.com/echochat/backend/app/auth/service" "github.com/echochat/backend/app/constants" "github.com/echochat/backend/app/dto" "github.com/echochat/backend/app/meeting/model" @@ -23,11 +24,12 @@ import ( type MeetingController struct { meetingService *service.MeetingService meetingConfig *config.MeetingConfig + authService *authSvc.AuthService } // NewMeetingController 创建 MeetingController 实例 -func NewMeetingController(meetingService *service.MeetingService, meetingConfig *config.MeetingConfig) *MeetingController { - return &MeetingController{meetingService: meetingService, meetingConfig: meetingConfig} +func NewMeetingController(meetingService *service.MeetingService, meetingConfig *config.MeetingConfig, authService *authSvc.AuthService) *MeetingController { + return &MeetingController{meetingService: meetingService, meetingConfig: meetingConfig, authService: authService} } type cloudLawCreateMeetingRequest struct { @@ -49,6 +51,11 @@ type cloudLawJoinMeetingRequest struct { CallID string `json:"callId"` } +type cloudLawSessionRequest struct { + Phone string `json:"phone"` + Name string `json:"name"` +} + func (ctl *MeetingController) requireCloudLawInternalToken(c *gin.Context) bool { expected := "" if ctl.meetingConfig != nil { @@ -278,6 +285,34 @@ func (ctl *MeetingController) CloudLawGetMeeting(c *gin.Context) { utils.ResponseOK(c, cloudLawMeetingPayload(room, onlineCount)) } +func (ctl *MeetingController) CloudLawSession(c *gin.Context) { + if !ctl.requireCloudLawInternalToken(c) { + return + } + var req cloudLawSessionRequest + if err := c.ShouldBindJSON(&req); err != nil { + utils.ResponseBadRequest(c, "参数校验失败: "+err.Error()) + return + } + req.Phone = strings.TrimSpace(req.Phone) + req.Name = strings.TrimSpace(req.Name) + if req.Phone == "" { + utils.ResponseBadRequest(c, "phone不能为空") + return + } + user, _, err := ctl.meetingService.EnsureCloudLawUserByPhone(c.Request.Context(), req.Phone, req.Name) + if err != nil { + ctl.handleError(c, err, "创建云律 EchoChat 用户失败") + return + } + resp, err := ctl.authService.BuildLoginResponseForUser(c.Request.Context(), user, c.ClientIP(), constants.ClientTypeFrontend) + if err != nil { + utils.ResponseError(c, "创建云律 EchoChat 登录态失败") + return + } + utils.ResponseOK(c, resp) +} + func (ctl *MeetingController) CloudLawJoinMeeting(c *gin.Context) { if !ctl.requireCloudLawInternalToken(c) { return diff --git a/backend/go-service/app/meeting/router.go b/backend/go-service/app/meeting/router.go index e4676bd..b623b92 100644 --- a/backend/go-service/app/meeting/router.go +++ b/backend/go-service/app/meeting/router.go @@ -50,6 +50,7 @@ func RegisterRoutes( registerCloudLawRoutes := func(group *gin.RouterGroup) { group.POST("/meetings", ctrl.CloudLawCreateMeeting) group.GET("/meetings/:code", ctrl.CloudLawGetMeeting) + group.POST("/auth/session", ctrl.CloudLawSession) group.POST("/meetings/:code/join", ctrl.CloudLawJoinMeeting) group.POST("/meetings/:code/end", ctrl.CloudLawEndMeeting) } diff --git a/backend/go-service/app/provider/wire_gen.go b/backend/go-service/app/provider/wire_gen.go index 437edd7..da34d33 100644 --- a/backend/go-service/app/provider/wire_gen.go +++ b/backend/go-service/app/provider/wire_gen.go @@ -119,7 +119,7 @@ func InitializeApp(cfg *config.Config) (*App, error) { // admin 会议管理服务在 recording service 构造后再创建,从而支持"强制结束录制"兜底 meetingManageService := service2.NewMeetingManageService(meetingManageDAO, meetingRecordingService) meetingManageController := controller2.NewMeetingManageController(meetingManageService) - meetingController := controller7.NewMeetingController(meetingService, meetingConfig) + meetingController := controller7.NewMeetingController(meetingService, meetingConfig, authService) meetingRecordingController := controller7.NewMeetingRecordingController(meetingRecordingService, meetingConfig) meetingWSHandler := controller7.NewMeetingWSHandler(meetingSignalService, hub) meetingCleanupTask := task2.NewMeetingCleanupTask(meetingLifecycleService, meetingRoomDAO, meetingChatDAO)