feat: vendor gitea 1.16.2

This commit is contained in:
2026-06-02 08:36:01 +00:00
parent 247cd60f69
commit 54798b4615
2145 changed files with 162965 additions and 126447 deletions
+79 -33
View File
@@ -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()
}