package service_auth import ( "context" "net/url" "nixcn-cms/data" "nixcn-cms/internal/authcode" "nixcn-cms/internal/exception" "nixcn-cms/service/shared" "github.com/google/uuid" "gorm.io/gorm" ) type RedirectData struct { ClientId string `json:"client_id"` RedirectUri string `json:"redirect_uri"` State string `json:"state"` Code string `json:"code"` } type RedirectPayload struct { Context context.Context Data *RedirectData } type RedirectResult struct { Common shared.CommonResult Data string } func (self *AuthServiceImpl) Redirect(payload *RedirectPayload) (result *RedirectResult) { var err error authCode, ok := authcode.VerifyAuthCode(payload.Context, payload.Data.Code) if !ok { exception := new(exception.Builder). SetStatus(exception.StatusUser). SetService(exception.ServiceAuth). SetEndpoint(exception.EndpointAuthServiceRedirect). SetType(exception.TypeSpecific). SetOriginal(exception.AuthRedirectTokenInvalid). Throw(payload.Context) result = &RedirectResult{ Common: shared.CommonResult{ HttpCode: 403, Exception: exception, }, } return } userData, err := new(data.User). GetByEmail(payload.Context, &authCode.Email) if err != nil { if err == gorm.ErrRecordNotFound { userData.UUID = uuid.New() userData.UserId = uuid.New() userData.Email = authCode.Email userData.Username = userData.UserId.String() userData.PermissionLevel = 10 if err := userData.Create(payload.Context); err != nil { exception := new(exception.Builder). SetStatus(exception.StatusServer). SetService(exception.ServiceAuth). SetEndpoint(exception.EndpointAuthServiceRedirect). SetType(exception.TypeCommon). SetOriginal(exception.CommonErrorInternal). SetError(err). Throw(payload.Context) result = &RedirectResult{ Common: shared.CommonResult{ HttpCode: 500, Exception: exception, }, } return } } else { exception := new(exception.Builder). SetStatus(exception.StatusServer). SetService(exception.ServiceAuth). SetEndpoint(exception.EndpointAuthServiceRedirect). SetType(exception.TypeCommon). SetOriginal(exception.CommonErrorInternal). SetError(err). Throw(payload.Context) result = &RedirectResult{ Common: shared.CommonResult{ HttpCode: 500, Exception: exception, }, } return } } clientData := new(data.Client) client, err := clientData.GetClientByClientId(payload.Context, payload.Data.ClientId) if err != nil { exception := new(exception.Builder). SetStatus(exception.StatusUser). SetService(exception.ServiceAuth). SetEndpoint(exception.EndpointAuthServiceRedirect). SetType(exception.TypeSpecific). SetOriginal(exception.AuthRedirectClientNotFound). SetError(err). Throw(payload.Context) result = &RedirectResult{ Common: shared.CommonResult{ HttpCode: 400, Exception: exception, }, } return } if err = client.ValidateRedirectURI(payload.Data.RedirectUri); err != nil { exception := new(exception.Builder). SetStatus(exception.StatusUser). SetService(exception.ServiceAuth). SetEndpoint(exception.EndpointAuthServiceRedirect). SetType(exception.TypeSpecific). SetOriginal(exception.AuthRedirectUriMismatch). SetError(err). Throw(payload.Context) result = &RedirectResult{ Common: shared.CommonResult{ HttpCode: 400, Exception: exception, }, } return } newCode, err := authcode.NewAuthCode(payload.Context, payload.Data.ClientId, authCode.Email) if err != nil { exception := new(exception.Builder). SetStatus(exception.StatusServer). SetService(exception.ServiceAuth). SetEndpoint(exception.EndpointAuthServiceRedirect). SetType(exception.TypeCommon). SetOriginal(exception.CommonErrorInternal). SetError(err). Throw(payload.Context) result = &RedirectResult{ Common: shared.CommonResult{ HttpCode: 500, Exception: exception, }, } return } targetUrl, err := url.Parse(payload.Data.RedirectUri) if err != nil { exception := new(exception.Builder). SetStatus(exception.StatusUser). SetService(exception.ServiceAuth). SetEndpoint(exception.EndpointAuthServiceRedirect). SetType(exception.TypeSpecific). SetOriginal(exception.AuthRedirectInvalidUri). SetError(err). Throw(payload.Context) result = &RedirectResult{ Common: shared.CommonResult{ HttpCode: 400, Exception: exception, }, } return } query := targetUrl.Query() query.Set("code", newCode) if payload.Data.State != "" { query.Set("state", payload.Data.State) } targetUrl.RawQuery = query.Encode() result = &RedirectResult{ Common: shared.CommonResult{ HttpCode: 200, Exception: new(exception.Builder). SetStatus(exception.StatusSuccess). SetService(exception.ServiceAuth). SetEndpoint(exception.EndpointAuthServiceRedirect). SetType(exception.TypeCommon). SetOriginal(exception.CommonSuccess). Throw(payload.Context), }, Data: targetUrl.String(), } return }