diff --git a/handler/tool.go b/handler/tool.go index 84bc2b8..78303b4 100644 --- a/handler/tool.go +++ b/handler/tool.go @@ -838,6 +838,14 @@ func GetThirdPartyAuthUrl(c *gin.Context) { //params.Add("scope", "") params.Add("state", stateBase64Str) respUrl = fmt.Sprintf("%s?%s", proto.StackOverflowAuthorizeBaseUrl, params.Encode()) + case "my_gitea": + params := url.Values{} + params.Add("client_id", worker.MyGiteaClientID) + params.Add("redirect_uri", "https://pm.ljsea.top/tool/third_party_callback") + params.Add("response_type", "code") //返回code + params.Add("state", stateID) + params.Add("scope", "user") + respUrl = fmt.Sprintf("%s?%s", proto.MyGiteaAuthorizeBaseUrl, params.Encode()) default: log.Println("platform not support:", platform) } diff --git a/proto/status.go b/proto/status.go index e120d9f..de4f95d 100644 --- a/proto/status.go +++ b/proto/status.go @@ -195,4 +195,5 @@ const ( GoogleAuthorizeBaseUrl = "https://accounts.google.com/o/oauth2/v2/auth" FacebookAuthorizeBaseUrl = "https://www.facebook.com/v22.0/dialog/oauth" StackOverflowAuthorizeBaseUrl = "https://stackoverflow.com/oauth" + MyGiteaAuthorizeBaseUrl = "https://gogs.ljsea.top/login/oauth/authorize" ) diff --git a/proto/tool.go b/proto/tool.go index 295b52a..3d1108a 100644 --- a/proto/tool.go +++ b/proto/tool.go @@ -318,3 +318,27 @@ type QQUserInfoResponse struct { Level string `json:"level"` IsYellowYearVip string `json:"is_yellow_year_vip"` } + +/**************************gitea***********************/ +type GiteaOAuthResponse struct { + AccessToken string `json:"access_token"` + TokenType string `json:"token_type"` + ExpiresIn int `json:"expires_in"` + RefreshToken string `json:"refresh_token"` +} + +type GiteaOAuthRequest struct { + ClientID string `json:"client_id"` + ClientSecret string `json:"client_secret"` + Code string `json:"code"` + RedirectURI string `json:"redirect_uri"` + Scope string `json:"scope"` +} +type GiteaUserInfo struct { + Sub string `json:"sub"` + Name string `json:"name"` + PreferredUsername string `json:"preferred_username"` + Email string `json:"email"` + Picture string `json:"picture"` + Groups interface{} `json:"groups"` +} diff --git a/service/toolService.go b/service/toolService.go index d32498a..c8d4104 100644 --- a/service/toolService.go +++ b/service/toolService.go @@ -489,6 +489,8 @@ func DoThirdPartyCallBack(state *proto.ThirdPartyLoginState, code string) { DoFaceBookCallBack(state, code) case "stackoverflow": DoStackoverflowCallBack(state, code) + case "my_gitea", "gitea": + DoGiteeCallBack(state, code) default: log.Println("DoThirdPartyCallBack platform error:", state.Platform) } @@ -659,3 +661,46 @@ func DoRequestToForeignServer(req *proto.OnlineServerReq) (proto.OutlineServerRe return resp, nil } + +func DoGiteaCallBack(state *proto.ThirdPartyLoginState, code string) { + var thirdPartyLoginStatus proto.ThirdPartyLoginStatus + thirdPartyLoginStatus.Type = state.Platform + //根据code获取Access Token + var baseDomain string + var clientID string + var clientSecret string + if state.Platform == "my_gitea" { + baseDomain = "https://gogs.ljsea.top" + clientID, clientSecret = worker.MyGiteaClientID, worker.MyGiteaClientSecret + } else { + baseDomain = "https://gitea.com" + clientID, clientSecret = worker.GiteaClientID, worker.GiteaClientSecret + } + tokenResp, _ := worker.GetGiteaAccessTokenByCode(baseDomain, code, "https://pm.ljsea.top/tool/third_party_callback", clientID, clientSecret) + //if err != nil { + // log.Printf("get %s access token error:%v\n", state.Platform, err) + // thirdPartyLoginStatus.Status = proto.ParameterError + // return + //} + if tokenResp.AccessToken == "" { + log.Printf("get %s access token is empty\n", state.Platform) + thirdPartyLoginStatus.Status = proto.ParameterError + } else { + log.Printf("get %s access token:%v\n", state.Platform, tokenResp.AccessToken) + //获取用户信息 + userInfoResp, err2 := worker.GetGiteaUserInfo(baseDomain, tokenResp.AccessToken) + if err2 != nil { + log.Printf("get %s user info error:%v\n", state.Platform, err2) + thirdPartyLoginStatus.Status = proto.ParameterError + } else { + log.Printf("get %s user info:%v\n", state.Platform, userInfoResp) + thirdPartyUserInfo := proto.ThirdPartyUserInfo{UserID: userInfoResp.Sub, Name: userInfoResp.Name, Avatar: userInfoResp.Picture, Email: userInfoResp.Email} + HandleThirdPartyLoginStatusV2(state, &thirdPartyLoginStatus, &thirdPartyUserInfo) + thirdPartyLoginStatus.Status = proto.SuccessCode + } + } + //更新redis中的第三方登录状态 + thirdPartyLoginStatusStr, _ := json.Marshal(thirdPartyLoginStatus) + log.Printf("do handle %s callback success, third party login status: %v\n", state.Platform, thirdPartyLoginStatus) + worker.SetRedisWithExpire(state.UUID, string(thirdPartyLoginStatusStr), time.Minute*10) +} diff --git a/worker/thirdParty.go b/worker/thirdParty.go index 9337fc0..5b347e6 100644 --- a/worker/thirdParty.go +++ b/worker/thirdParty.go @@ -513,3 +513,55 @@ func GetQQUserInfo(accessToken string) (proto.QQUserInfoResponse, error) { return resp, nil } + +// 我的自部署gitea +const ( + MyGiteaClientID = "812f4f39-8b98-426e-a542-3115ff4fb2be" + MyGiteaClientSecret = "gto_uw3p6sy3cutbmfmndgtajschm6vqaxasyaxmjfzsrsgjx32wawwq" + + //官方版本 + GiteaClientID = "035b79b8-ba9a-4c4b-bb41-ede796d168c8" + GiteaClientSecret = "gto_djia2zwamyvj6pashr24ifhj2nor52i5kphgice5rfwon2vqjpma" +) + +// 由于gitea有自部署与官方区别, +func GetGiteaAccessTokenByCode(baseUrl, code string, redirectURI string, clientID string, clientSecret string) (proto.GiteaOAuthResponse, error) { + var resp proto.GiteaOAuthResponse + + url := baseUrl + "/login/oauth/access_token" + req := proto.GiteaOAuthRequest{ + ClientID: clientID, + ClientSecret: clientSecret, + Code: code, + RedirectURI: redirectURI, + Scope: "user", + } + reqData, err := json.Marshal(req) + err2, respBytes := DoPostRequestJSON(url, reqData, nil) + if err2 != nil { + return resp, err2 + } + err = json.Unmarshal(respBytes, &resp) + if err != nil { + return resp, err + } + return resp, nil +} + +func GetGiteaUserInfo(baseDomain, accessToken string) (proto.GiteaUserInfo, error) { + url := baseDomain + "/login/oauth/userinfo" + headers := map[string]string{ + "Authorization": "bearer " + accessToken, + } + var resp proto.GiteaUserInfo + err2, respBytes := DoGetRequest(url, headers) + if err2 != nil { + return resp, err2 + } + err := json.Unmarshal(respBytes, &resp) + if err != nil { + return resp, err + } + return resp, nil + +}