package user import ( "fmt" "net/http" "net/url" "gitea.com/texpixel/document_ai/config" model "gitea.com/texpixel/document_ai/internal/model/user" "gitea.com/texpixel/document_ai/internal/service" "gitea.com/texpixel/document_ai/pkg/common" "gitea.com/texpixel/document_ai/pkg/constant" "gitea.com/texpixel/document_ai/pkg/jwt" "gitea.com/texpixel/document_ai/pkg/log" "github.com/gin-gonic/gin" ) type UserEndpoint struct { userService *service.UserService } func NewUserEndpoint() *UserEndpoint { return &UserEndpoint{ userService: service.NewUserService(), } } func (h *UserEndpoint) SendVerificationCode(ctx *gin.Context) { req := model.SmsSendRequest{} if err := ctx.ShouldBindJSON(&req); err != nil { ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeParamError, common.CodeParamErrorMsg)) return } code, err := h.userService.GetSmsCode(ctx, req.Phone) if err != nil { log.Error(ctx, "func", "SendVerificationCode", "msg", "发送验证码失败", "error", err) ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeSystemError, common.CodeSystemErrorMsg)) return } ctx.JSON(http.StatusOK, common.SuccessResponse(ctx, model.SmsSendResponse{Code: code})) } func (h *UserEndpoint) LoginByPhoneCode(ctx *gin.Context) { req := model.PhoneLoginRequest{} if err := ctx.ShouldBindJSON(&req); err != nil { ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeParamError, common.CodeParamErrorMsg)) return } if req.Code == "" || req.Phone == "" { ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeParamError, common.CodeParamErrorMsg)) return } if config.GlobalConfig.Server.IsDebug() { uid := 1 tokenResult, err := jwt.CreateToken(jwt.User{UserId: int64(uid)}) if err != nil { ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeUnauthorized, common.CodeUnauthorizedMsg)) return } ctx.JSON(http.StatusOK, common.SuccessResponse(ctx, model.PhoneLoginResponse{ Token: tokenResult.Token, ExpiresAt: tokenResult.ExpiresAt, })) return } uid, err := h.userService.VerifySmsCode(ctx, req.Phone, req.Code) if err != nil { ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeUnauthorized, common.CodeSmsCodeErrorMsg)) return } tokenResult, err := jwt.CreateToken(jwt.User{UserId: uid}) if err != nil { ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeUnauthorized, common.CodeUnauthorizedMsg)) return } ctx.JSON(http.StatusOK, common.SuccessResponse(ctx, model.PhoneLoginResponse{ Token: tokenResult.Token, ExpiresAt: tokenResult.ExpiresAt, })) } func (h *UserEndpoint) GetUserInfo(ctx *gin.Context) { uid := ctx.GetInt64(constant.ContextUserID) if uid == 0 { ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeUnauthorized, common.CodeUnauthorizedMsg)) return } user, err := h.userService.GetUserInfo(ctx, uid) if err != nil { ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeSystemError, common.CodeSystemErrorMsg)) return } status := 0 if user.ID > 0 { status = 1 } ctx.JSON(http.StatusOK, common.SuccessResponse(ctx, model.UserInfoResponse{ Username: user.Username, Phone: user.Phone, Status: status, })) } func (h *UserEndpoint) RegisterByEmail(ctx *gin.Context) { req := model.EmailRegisterRequest{} if err := ctx.ShouldBindJSON(&req); err != nil { ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeParamError, common.CodeParamErrorMsg)) return } uid, err := h.userService.RegisterByEmail(ctx, req.Email, req.Password) if err != nil { if bizErr, ok := err.(*common.BusinessError); ok { ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, int(bizErr.Code), bizErr.Message)) return } log.Error(ctx, "func", "RegisterByEmail", "msg", "注册失败", "error", err) ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeSystemError, common.CodeSystemErrorMsg)) return } tokenResult, err := jwt.CreateToken(jwt.User{UserId: uid}) if err != nil { ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeSystemError, common.CodeSystemErrorMsg)) return } ctx.JSON(http.StatusOK, common.SuccessResponse(ctx, model.EmailRegisterResponse{ Token: tokenResult.Token, ExpiresAt: tokenResult.ExpiresAt, })) } func (h *UserEndpoint) LoginByEmail(ctx *gin.Context) { req := model.EmailLoginRequest{} if err := ctx.ShouldBindJSON(&req); err != nil { ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeParamError, common.CodeParamErrorMsg)) return } uid, err := h.userService.LoginByEmail(ctx, req.Email, req.Password) if err != nil { if bizErr, ok := err.(*common.BusinessError); ok { ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, int(bizErr.Code), bizErr.Message)) return } log.Error(ctx, "func", "LoginByEmail", "msg", "登录失败", "error", err) ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeSystemError, common.CodeSystemErrorMsg)) return } tokenResult, err := jwt.CreateToken(jwt.User{UserId: uid}) if err != nil { ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeSystemError, common.CodeSystemErrorMsg)) return } ctx.JSON(http.StatusOK, common.SuccessResponse(ctx, model.EmailLoginResponse{ Token: tokenResult.Token, ExpiresAt: tokenResult.ExpiresAt, })) } func (h *UserEndpoint) GetGoogleOAuthUrl(ctx *gin.Context) { req := model.GoogleAuthUrlRequest{} if err := ctx.ShouldBindQuery(&req); err != nil { ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeParamError, common.CodeParamErrorMsg)) return } googleConfig := config.GlobalConfig.Google if googleConfig.ClientID == "" { log.Error(ctx, "func", "GetGoogleOAuthUrl", "msg", "Google OAuth not configured") ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeSystemError, common.CodeSystemErrorMsg)) return } authURL := fmt.Sprintf( "https://accounts.google.com/o/oauth2/v2/auth?client_id=%s&redirect_uri=%s&response_type=code&scope=openid%%20email%%20profile&state=%s", url.QueryEscape(googleConfig.ClientID), url.QueryEscape(req.RedirectURI), url.QueryEscape(req.State), ) ctx.JSON(http.StatusOK, common.SuccessResponse(ctx, model.GoogleAuthUrlResponse{ AuthURL: authURL, })) } func (h *UserEndpoint) GoogleOAuthCallback(ctx *gin.Context) { req := model.GoogleOAuthCallbackRequest{} if err := ctx.ShouldBindJSON(&req); err != nil { ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeParamError, common.CodeParamErrorMsg)) return } googleConfig := config.GlobalConfig.Google if googleConfig.ClientID == "" || googleConfig.ClientSecret == "" { log.Error(ctx, "func", "GoogleOAuthCallback", "msg", "Google OAuth not configured") ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeSystemError, common.CodeSystemErrorMsg)) return } userInfo, err := h.userService.ExchangeGoogleCodeAndGetUserInfo(ctx, googleConfig.ClientID, googleConfig.ClientSecret, req.Code, req.RedirectURI) if err != nil { log.Error(ctx, "func", "GoogleOAuthCallback", "msg", "exchange code failed", "error", err) ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeSystemError, common.CodeSystemErrorMsg)) return } uid, err := h.userService.FindOrCreateGoogleUser(ctx, userInfo) if err != nil { log.Error(ctx, "func", "GoogleOAuthCallback", "msg", "find or create user failed", "error", err) ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeSystemError, common.CodeSystemErrorMsg)) return } tokenResult, err := jwt.CreateToken(jwt.User{UserId: uid}) if err != nil { ctx.JSON(http.StatusOK, common.ErrorResponse(ctx, common.CodeUnauthorized, common.CodeUnauthorizedMsg)) return } ctx.JSON(http.StatusOK, common.SuccessResponse(ctx, model.GoogleOAuthCallbackResponse{ Token: tokenResult.Token, ExpiresAt: tokenResult.ExpiresAt, })) }