forked from hinterland/hearth
feat: vendor gitea 1.16.2
This commit is contained in:
@@ -10,18 +10,20 @@ import (
|
||||
"html"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/auth"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
auth_module "code.gitea.io/gitea/modules/auth"
|
||||
"code.gitea.io/gitea/modules/container"
|
||||
"code.gitea.io/gitea/modules/httplib"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/optional"
|
||||
"code.gitea.io/gitea/modules/session"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/web/middleware"
|
||||
source_service "code.gitea.io/gitea/services/auth/source"
|
||||
"code.gitea.io/gitea/services/auth/source/oauth2"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
@@ -42,10 +44,7 @@ func SignInOAuth(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
redirectTo := ctx.FormString("redirect_to")
|
||||
if len(redirectTo) > 0 {
|
||||
middleware.SetRedirectToCookie(ctx.Resp, redirectTo)
|
||||
}
|
||||
rememberAuthRedirectLink(ctx)
|
||||
|
||||
// try to do a direct callback flow, so we don't authenticate the user again but use the valid accesstoken to get the user
|
||||
user, gothUser, err := oAuth2UserLoginCallback(ctx, authSource, ctx.Req, ctx.Resp)
|
||||
@@ -120,7 +119,7 @@ func SignInOAuthCallback(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
if err, ok := err.(*go_oauth2.RetrieveError); ok {
|
||||
ctx.Flash.Error("OAuth2 RetrieveError: "+err.Error(), true)
|
||||
ctx.Flash.Error("OAuth2 RetrieveError: " + err.Error())
|
||||
ctx.Redirect(setting.AppSubURL + "/user/login")
|
||||
return
|
||||
}
|
||||
@@ -278,7 +277,7 @@ type LinkAccountData struct {
|
||||
}
|
||||
|
||||
func init() {
|
||||
gob.Register(LinkAccountData{})
|
||||
gob.Register(LinkAccountData{}) // TODO: CHI-SESSION-GOB-REGISTER
|
||||
}
|
||||
|
||||
func oauth2GetLinkAccountData(ctx *context.Context) *LinkAccountData {
|
||||
@@ -303,21 +302,42 @@ func showLinkingLogin(ctx *context.Context, authSourceID int64, gothUser goth.Us
|
||||
ctx.Redirect(setting.AppSubURL + "/user/link_account")
|
||||
}
|
||||
|
||||
func oauth2UpdateAvatarIfNeed(ctx *context.Context, url string, u *user_model.User) {
|
||||
if setting.OAuth2Client.UpdateAvatar && len(url) > 0 {
|
||||
resp, err := http.Get(url)
|
||||
if err == nil {
|
||||
defer func() {
|
||||
_ = resp.Body.Close()
|
||||
}()
|
||||
}
|
||||
// ignore any error
|
||||
if err == nil && resp.StatusCode == http.StatusOK {
|
||||
data, err := io.ReadAll(io.LimitReader(resp.Body, setting.Avatar.MaxFileSize+1))
|
||||
if err == nil && int64(len(data)) <= setting.Avatar.MaxFileSize {
|
||||
_ = user_service.UploadAvatar(ctx, u, data)
|
||||
}
|
||||
}
|
||||
var oauth2AvatarHTTPClient = &http.Client{Timeout: 30 * time.Second}
|
||||
|
||||
func oauth2UpdateAvatarIfNeed(ctx *context.Context, avatarURL string, u *user_model.User) {
|
||||
if !setting.OAuth2Client.UpdateAvatar || len(avatarURL) == 0 {
|
||||
return
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, avatarURL, nil)
|
||||
if err != nil {
|
||||
log.Warn("invalid avatar URL %q: %v", avatarURL, err)
|
||||
return
|
||||
}
|
||||
// Some hosts (e.g. Wikimedia) reject Go's default User-Agent.
|
||||
req.Header.Set("User-Agent", "Gitea "+setting.AppVer)
|
||||
|
||||
resp, err := oauth2AvatarHTTPClient.Do(req)
|
||||
if err != nil {
|
||||
log.Warn("fetch %q failed: %v", avatarURL, err)
|
||||
return
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
log.Warn("fetch %q returned status %d", avatarURL, resp.StatusCode)
|
||||
return
|
||||
}
|
||||
data, err := io.ReadAll(io.LimitReader(resp.Body, setting.Avatar.MaxFileSize+1))
|
||||
if err != nil {
|
||||
log.Warn("read body from %q failed: %v", avatarURL, err)
|
||||
return
|
||||
}
|
||||
if int64(len(data)) > setting.Avatar.MaxFileSize {
|
||||
log.Warn("avatar from %q exceeds max size %d", avatarURL, setting.Avatar.MaxFileSize)
|
||||
return
|
||||
}
|
||||
if err := user_service.UploadAvatar(ctx, u, data); err != nil {
|
||||
log.Warn("UploadAvatar for user %q failed: %v", u.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,21 +413,12 @@ func handleOAuth2SignIn(ctx *context.Context, authSource *auth.Source, u *user_m
|
||||
return
|
||||
}
|
||||
|
||||
// force to generate a new CSRF token
|
||||
ctx.Csrf.PrepareForSessionUser(ctx)
|
||||
|
||||
if err := resetLocale(ctx, u); err != nil {
|
||||
ctx.ServerError("resetLocale", err)
|
||||
return
|
||||
}
|
||||
|
||||
if redirectTo := ctx.GetSiteCookie("redirect_to"); len(redirectTo) > 0 {
|
||||
middleware.DeleteRedirectToCookie(ctx.Resp)
|
||||
ctx.RedirectToCurrentSite(redirectTo)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Redirect(setting.AppSubURL + "/")
|
||||
redirectAfterAuth(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -493,7 +504,7 @@ func oAuth2UserLoginCallback(ctx *context.Context, authSource *auth.Source, requ
|
||||
LoginSource: authSource.ID,
|
||||
}
|
||||
|
||||
hasUser, err := user_model.GetUser(ctx, user)
|
||||
hasUser, err := user_model.GetIndividualUser(ctx, user)
|
||||
if err != nil {
|
||||
return nil, goth.User{}, err
|
||||
}
|
||||
@@ -519,3 +530,38 @@ func oAuth2UserLoginCallback(ctx *context.Context, authSource *auth.Source, requ
|
||||
// no user found to login
|
||||
return nil, gothUser, nil
|
||||
}
|
||||
|
||||
// buildOIDCEndSessionURL constructs an OIDC RP-Initiated Logout URL for the
|
||||
// given user. Returns "" if the user's auth source is not OIDC or doesn't
|
||||
// advertise an end_session_endpoint.
|
||||
func buildOIDCEndSessionURL(ctx *context.Context, doer *user_model.User) string {
|
||||
authSource, err := auth.GetSourceByID(ctx, doer.LoginSource)
|
||||
if err != nil {
|
||||
log.Error("Failed to get auth source for OIDC logout (source=%d): %v", doer.LoginSource, err)
|
||||
return ""
|
||||
}
|
||||
|
||||
oauth2Cfg, ok := authSource.Cfg.(*oauth2.Source)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
endSessionEndpoint := oauth2.GetOIDCEndSessionEndpoint(authSource.Name)
|
||||
if endSessionEndpoint == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
endSessionURL, err := url.Parse(endSessionEndpoint)
|
||||
if err != nil {
|
||||
log.Error("Failed to parse end_session_endpoint %q: %v", endSessionEndpoint, err)
|
||||
return ""
|
||||
}
|
||||
|
||||
// RP-Initiated Logout 1.0: use client_id to identify the client to the IdP.
|
||||
// https://openid.net/specs/openid-connect-rpinitiated-1_0.html#RPLogout
|
||||
params := endSessionURL.Query()
|
||||
params.Set("client_id", oauth2Cfg.ClientID)
|
||||
params.Set("post_logout_redirect_uri", httplib.GuessCurrentAppURL(ctx))
|
||||
endSessionURL.RawQuery = params.Encode()
|
||||
return endSessionURL.String()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user