Merge branch 'main' into allow-force-push-protected-branches

This commit is contained in:
Henry Goodman
2023-12-19 20:36:12 +11:00
committed by GitHub
146 changed files with 907 additions and 1091 deletions
+21 -11
View File
@@ -93,18 +93,28 @@ func CreateUser(ctx *context.APIContext) {
if ctx.Written() {
return
}
if !password.IsComplexEnough(form.Password) {
err := errors.New("PasswordComplexity")
ctx.Error(http.StatusBadRequest, "PasswordComplexity", err)
return
}
pwned, err := password.IsPwned(ctx, form.Password)
if pwned {
if err != nil {
log.Error(err.Error())
if u.LoginType == auth.Plain {
if len(form.Password) < setting.MinPasswordLength {
err := errors.New("PasswordIsRequired")
ctx.Error(http.StatusBadRequest, "PasswordIsRequired", err)
return
}
if !password.IsComplexEnough(form.Password) {
err := errors.New("PasswordComplexity")
ctx.Error(http.StatusBadRequest, "PasswordComplexity", err)
return
}
pwned, err := password.IsPwned(ctx, form.Password)
if pwned {
if err != nil {
log.Error(err.Error())
}
ctx.Error(http.StatusBadRequest, "PasswordPwned", errors.New("PasswordPwned"))
return
}
ctx.Error(http.StatusBadRequest, "PasswordPwned", errors.New("PasswordPwned"))
return
}
overwriteDefault := &user_model.CreateUserOverwriteOptions{
+7 -9
View File
@@ -29,10 +29,9 @@ func NodeInfo(ctx *context.APIContext) {
nodeInfoUsage := structs.NodeInfoUsage{}
if setting.Federation.ShareUserStatistics {
cached := false
if setting.CacheService.Enabled {
nodeInfoUsage, cached = ctx.Cache.Get(cacheKeyNodeInfoUsage).(structs.NodeInfoUsage)
}
var cached bool
nodeInfoUsage, cached = ctx.Cache.Get(cacheKeyNodeInfoUsage).(structs.NodeInfoUsage)
if !cached {
usersTotal := int(user_model.CountUsers(ctx, nil))
now := time.Now()
@@ -53,11 +52,10 @@ func NodeInfo(ctx *context.APIContext) {
LocalPosts: int(allIssues),
LocalComments: int(allComments),
}
if setting.CacheService.Enabled {
if err := ctx.Cache.Put(cacheKeyNodeInfoUsage, nodeInfoUsage, 180); err != nil {
ctx.InternalServerError(err)
return
}
if err := ctx.Cache.Put(cacheKeyNodeInfoUsage, nodeInfoUsage, 180); err != nil {
ctx.InternalServerError(err)
return
}
}
}
+12 -12
View File
@@ -242,18 +242,18 @@ func CreateUserRepo(ctx *context.APIContext, owner *user_model.User, opt api.Cre
}
repo, err := repo_service.CreateRepository(ctx, ctx.Doer, owner, repo_service.CreateRepoOptions{
Name: opt.Name,
Description: opt.Description,
IssueLabels: opt.IssueLabels,
Gitignores: opt.Gitignores,
License: opt.License,
Readme: opt.Readme,
IsPrivate: opt.Private,
AutoInit: opt.AutoInit,
DefaultBranch: opt.DefaultBranch,
TrustModel: repo_model.ToTrustModel(opt.TrustModel),
IsTemplate: opt.Template,
ObjectFormat: git.ObjectFormatFromID(git.Sha1),
Name: opt.Name,
Description: opt.Description,
IssueLabels: opt.IssueLabels,
Gitignores: opt.Gitignores,
License: opt.License,
Readme: opt.Readme,
IsPrivate: opt.Private,
AutoInit: opt.AutoInit,
DefaultBranch: opt.DefaultBranch,
TrustModel: repo_model.ToTrustModel(opt.TrustModel),
IsTemplate: opt.Template,
ObjectFormatName: git.Sha1ObjectFormat.Name(),
})
if err != nil {
if repo_model.IsErrRepoAlreadyExist(err) {
+2 -2
View File
@@ -73,7 +73,7 @@ func searchRefCommitByType(ctx *context.APIContext, refType, filter string) (str
func ConvertToObjectID(ctx gocontext.Context, repo *context.Repository, commitID string) (git.ObjectID, error) {
objectFormat, _ := repo.GitRepo.GetObjectFormat()
if len(commitID) == objectFormat.FullLength() && objectFormat.IsValid(commitID) {
sha, err := objectFormat.NewIDFromString(commitID)
sha, err := git.NewIDFromString(commitID)
if err == nil {
return sha, nil
}
@@ -81,7 +81,7 @@ func ConvertToObjectID(ctx gocontext.Context, repo *context.Repository, commitID
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.Repository.RepoPath())
if err != nil {
return objectFormat.Empty(), fmt.Errorf("RepositoryFromContextOrOpen: %w", err)
return objectFormat.EmptyObjectID(), fmt.Errorf("RepositoryFromContextOrOpen: %w", err)
}
defer closer.Close()
+1 -1
View File
@@ -118,7 +118,7 @@ func InitWebInstalled(ctx context.Context) {
mustInit(storage.Init)
mailer.NewContext(ctx)
mustInit(cache.NewContext)
mustInit(cache.Init)
mustInit(feed_service.Init)
mustInit(uinotification.Init)
mustInitCtx(ctx, archiver.Init)
+3 -3
View File
@@ -147,7 +147,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
gitRepo := ctx.Repo.GitRepo
objectFormat, _ := gitRepo.GetObjectFormat()
if branchName == repo.DefaultBranch && newCommitID == objectFormat.Empty().String() {
if branchName == repo.DefaultBranch && newCommitID == objectFormat.EmptyObjectID().String() {
log.Warn("Forbidden: Branch: %s is the default branch in %-v and cannot be deleted", branchName, repo)
ctx.JSON(http.StatusForbidden, private.Response{
UserMsg: fmt.Sprintf("branch %s is the default branch and cannot be deleted", branchName),
@@ -175,7 +175,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
// First of all we need to enforce absolutely:
//
// 1. Detect and prevent deletion of the branch
if newCommitID == objectFormat.Empty().String() {
if newCommitID == objectFormat.EmptyObjectID().String() {
log.Warn("Forbidden: Branch: %s in %-v is protected from deletion", branchName, repo)
ctx.JSON(http.StatusForbidden, private.Response{
UserMsg: fmt.Sprintf("branch %s is protected from deletion", branchName),
@@ -186,7 +186,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
isForcePush := false
// 2. Disallow force pushes to protected branches
if oldCommitID != objectFormat.Empty().String() {
if oldCommitID != objectFormat.EmptyObjectID().String() {
output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1").AddDynamicArguments(oldCommitID, "^"+newCommitID).RunStdString(&git.RunOpts{Dir: repo.RepoPath(), Env: ctx.env})
if err != nil {
log.Error("Unable to detect force push between: %s and %s in %-v Error: %v", oldCommitID, newCommitID, repo, err)
+3 -3
View File
@@ -30,7 +30,7 @@ func verifyCommits(oldCommitID, newCommitID string, repo *git.Repository, env []
var command *git.Command
objectFormat, _ := repo.GetObjectFormat()
if oldCommitID == objectFormat.Empty().String() {
if oldCommitID == objectFormat.EmptyObjectID().String() {
// When creating a new branch, the oldCommitID is empty, by using "newCommitID --not --all":
// List commits that are reachable by following the newCommitID, exclude "all" existing heads/tags commits
// So, it only lists the new commits received, doesn't list the commits already present in the receiving repository
@@ -83,8 +83,8 @@ func readAndVerifyCommit(sha string, repo *git.Repository, env []string) error {
_ = stdoutReader.Close()
_ = stdoutWriter.Close()
}()
objectFormat, _ := repo.GetObjectFormat()
commitID := objectFormat.MustIDFromString(sha)
commitID := git.MustIDFromString(sha)
return git.NewCommand(repo.Ctx, "cat-file", "commit").AddDynamicArguments(sha).
Run(&git.RunOpts{
+2 -2
View File
@@ -30,9 +30,9 @@ func TestVerifyCommits(t *testing.T) {
verified bool
}{
{"72920278f2f999e3005801e5d5b8ab8139d3641c", "d766f2917716d45be24bfa968b8409544941be32", true},
{objectFormat.Empty().String(), "93eac826f6188f34646cea81bf426aa5ba7d3bfe", true}, // New branch with verified commit
{objectFormat.EmptyObjectID().String(), "93eac826f6188f34646cea81bf426aa5ba7d3bfe", true}, // New branch with verified commit
{"9779d17a04f1e2640583d35703c62460b2d86e0a", "72920278f2f999e3005801e5d5b8ab8139d3641c", false},
{objectFormat.Empty().String(), "9ce3f779ae33f31fce17fac3c512047b75d7498b", false}, // New branch with unverified commit
{objectFormat.EmptyObjectID().String(), "9ce3f779ae33f31fce17fac3c512047b75d7498b", false}, // New branch with unverified commit
}
for _, tc := range testCases {
+6 -10
View File
@@ -622,10 +622,8 @@ func handleUserCreated(ctx *context.Context, u *user_model.User, gothUser *goth.
ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale)
ctx.HTML(http.StatusOK, TplActivate)
if setting.CacheService.Enabled {
if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
log.Error("Set cache(MailResendLimit) fail: %v", err)
}
if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
log.Error("Set cache(MailResendLimit) fail: %v", err)
}
return false
}
@@ -645,16 +643,14 @@ func Activate(ctx *context.Context) {
}
// Resend confirmation email.
if setting.Service.RegisterEmailConfirm {
if setting.CacheService.Enabled && ctx.Cache.IsExist("MailResendLimit_"+ctx.Doer.LowerName) {
if ctx.Cache.IsExist("MailResendLimit_" + ctx.Doer.LowerName) {
ctx.Data["ResendLimited"] = true
} else {
ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale)
mailer.SendActivateAccountMail(ctx.Locale, ctx.Doer)
if setting.CacheService.Enabled {
if err := ctx.Cache.Put("MailResendLimit_"+ctx.Doer.LowerName, ctx.Doer.LowerName, 180); err != nil {
log.Error("Set cache(MailResendLimit) fail: %v", err)
}
if err := ctx.Cache.Put("MailResendLimit_"+ctx.Doer.LowerName, ctx.Doer.LowerName, 180); err != nil {
log.Error("Set cache(MailResendLimit) fail: %v", err)
}
}
} else {
@@ -789,7 +785,7 @@ func ActivateEmail(ctx *context.Context) {
if u, err := user_model.GetUserByID(ctx, email.UID); err != nil {
log.Warn("GetUserByID: %d", email.UID)
} else if setting.CacheService.Enabled {
} else {
// Allow user to validate more emails
_ = ctx.Cache.Delete("MailResendLimit_" + u.LowerName)
}
+3 -5
View File
@@ -79,7 +79,7 @@ func ForgotPasswdPost(ctx *context.Context) {
return
}
if setting.CacheService.Enabled && ctx.Cache.IsExist("MailResendLimit_"+u.LowerName) {
if ctx.Cache.IsExist("MailResendLimit_" + u.LowerName) {
ctx.Data["ResendLimited"] = true
ctx.HTML(http.StatusOK, tplForgotPassword)
return
@@ -87,10 +87,8 @@ func ForgotPasswdPost(ctx *context.Context) {
mailer.SendResetPasswordMail(u)
if setting.CacheService.Enabled {
if err = ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
log.Error("Set cache(MailResendLimit) fail: %v", err)
}
if err = ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
log.Error("Set cache(MailResendLimit) fail: %v", err)
}
ctx.Data["ResetPwdCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale)
-4
View File
@@ -121,10 +121,6 @@ func checkDatabase(ctx context.Context, checks checks) status {
// cache checks gitea cache status
func checkCache(checks checks) status {
if !setting.CacheService.Enabled {
return pass
}
st := componentStatus{}
if err := cache.GetCache().Ping(); err != nil {
st.Status = fail
+3 -1
View File
@@ -18,6 +18,7 @@ import (
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/web/repo"
"code.gitea.io/gitea/services/convert"
@@ -77,6 +78,7 @@ func List(ctx *context.Context) {
// Get all runner labels
runners, err := db.Find[actions_model.ActionRunner](ctx, actions_model.FindRunnerOptions{
RepoID: ctx.Repo.Repository.ID,
IsOnline: util.OptionalBoolTrue,
WithAvailable: true,
})
if err != nil {
@@ -113,7 +115,7 @@ func List(ctx *context.Context) {
continue
}
if !allRunnerLabels.Contains(ro) {
workflow.ErrMsg = ctx.Locale.Tr("actions.runs.no_matching_runner_helper", ro)
workflow.ErrMsg = ctx.Locale.Tr("actions.runs.no_matching_online_runner_helper", ro)
break
}
}
+1 -2
View File
@@ -315,8 +315,7 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m
lexerName = lexerNameForLine
}
br.EscapeStatus, line = charset.EscapeControlHTML(line, ctx.Locale)
br.Code = gotemplate.HTML(line)
br.EscapeStatus, br.Code = charset.EscapeControlHTML(line, ctx.Locale)
rows = append(rows, br)
escapeStatus = escapeStatus.Or(br.EscapeStatus)
}
+1 -1
View File
@@ -158,7 +158,7 @@ func RestoreBranchPost(ctx *context.Context) {
if err := repo_service.PushUpdate(
&repo_module.PushUpdateOptions{
RefFullName: git.RefNameFromBranch(deletedBranch.Name),
OldCommitID: objectFormat.Empty().String(),
OldCommitID: objectFormat.EmptyObjectID().String(),
NewCommitID: deletedBranch.CommitID,
PusherID: ctx.Doer.ID,
PusherName: ctx.Doer.Name,
+1 -1
View File
@@ -317,7 +317,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
ci.BaseBranch = baseCommit.ID.String()
ctx.Data["BaseBranch"] = ci.BaseBranch
baseIsCommit = true
} else if ci.BaseBranch == objectFormat.Empty().String() {
} else if ci.BaseBranch == objectFormat.EmptyObjectID().String() {
if isSameRepo {
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ci.HeadBranch))
} else {
+1 -1
View File
@@ -329,7 +329,7 @@ func dummyInfoRefs(ctx *context.Context) {
}
}()
if err := git.InitRepository(ctx, tmpDir, true, git.ObjectFormatFromID(git.Sha1)); err != nil {
if err := git.InitRepository(ctx, tmpDir, true, git.Sha1ObjectFormat.Name()); err != nil {
log.Error("Failed to init bare repo for git-receive-pack cache: %v", err)
return
}
+12 -12
View File
@@ -278,18 +278,18 @@ func CreatePost(ctx *context.Context) {
}
} else {
repo, err = repo_service.CreateRepository(ctx, ctx.Doer, ctxUser, repo_service.CreateRepoOptions{
Name: form.RepoName,
Description: form.Description,
Gitignores: form.Gitignores,
IssueLabels: form.IssueLabels,
License: form.License,
Readme: form.Readme,
IsPrivate: form.Private || setting.Repository.ForcePrivate,
DefaultBranch: form.DefaultBranch,
AutoInit: form.AutoInit,
IsTemplate: form.Template,
TrustModel: repo_model.ToTrustModel(form.TrustModel),
ObjectFormat: form.ObjectFormat,
Name: form.RepoName,
Description: form.Description,
Gitignores: form.Gitignores,
IssueLabels: form.IssueLabels,
License: form.License,
Readme: form.Readme,
IsPrivate: form.Private || setting.Repository.ForcePrivate,
DefaultBranch: form.DefaultBranch,
AutoInit: form.AutoInit,
IsTemplate: form.Template,
TrustModel: repo_model.ToTrustModel(form.TrustModel),
ObjectFormatName: form.ObjectFormatName,
})
if err == nil {
log.Trace("Repository created [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
+1 -1
View File
@@ -395,7 +395,7 @@ func LFSFileFind(ctx *context.Context) {
objectID = git.ComputeBlobHash(objectFormat, []byte(pointer.StringContent()))
sha = objectID.String()
} else {
objectID = objectFormat.MustIDFromString(sha)
objectID = git.MustIDFromString(sha)
}
ctx.Data["LFSFilesLink"] = ctx.Repo.RepoLink + "/settings/lfs"
ctx.Data["Oid"] = oid
+1 -1
View File
@@ -662,7 +662,7 @@ func TestWebhook(ctx *context.Context) {
return
}
commit = &git.Commit{
ID: objectFormat.NewEmptyID(),
ID: objectFormat.EmptyObjectID(),
Author: ghost.NewGitSig(),
Committer: ghost.NewGitSig(),
CommitMessage: "This is a fake commit",
+14 -14
View File
@@ -9,6 +9,7 @@ import (
gocontext "context"
"encoding/base64"
"fmt"
"html/template"
"image"
"io"
"net/http"
@@ -317,19 +318,18 @@ func renderReadmeFile(ctx *context.Context, subfolder string, readmeFile *git.Tr
}, rd)
if err != nil {
log.Error("Render failed for %s in %-v: %v Falling back to rendering source", readmeFile.Name(), ctx.Repo.Repository, err)
buf := &bytes.Buffer{}
ctx.Data["EscapeStatus"], _ = charset.EscapeControlStringReader(rd, buf, ctx.Locale)
ctx.Data["FileContent"] = buf.String()
}
} else {
ctx.Data["IsPlainText"] = true
buf := &bytes.Buffer{}
ctx.Data["EscapeStatus"], err = charset.EscapeControlStringReader(rd, buf, ctx.Locale)
if err != nil {
log.Error("Read failed: %v", err)
delete(ctx.Data, "IsMarkup")
}
}
ctx.Data["FileContent"] = buf.String()
if ctx.Data["IsMarkup"] != true {
ctx.Data["IsPlainText"] = true
content, err := io.ReadAll(rd)
if err != nil {
log.Error("Read readme content failed: %v", err)
}
contentEscaped := template.HTMLEscapeString(util.UnsafeBytesToString(content))
ctx.Data["EscapeStatus"], ctx.Data["FileContent"] = charset.EscapeControlHTML(template.HTML(contentEscaped), ctx.Locale)
}
if !fInfo.isLFSFile && ctx.Repo.CanEnableEditor(ctx, ctx.Doer) {
@@ -493,7 +493,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
buf, _ := io.ReadAll(rd)
// The Open Group Base Specification: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html
// empty: 0 lines; "a": 1 line, 1 incomplete-line; "a\n": 1 line; "a\nb": 1 line, 1 incomplete-line;
// empty: 0 lines; "a": 1 incomplete-line; "a\n": 1 line; "a\nb": 1 line, 1 incomplete-line;
// Gitea uses the definition (like most modern editors):
// empty: 0 lines; "a": 1 line; "a\n": 2 lines; "a\nb": 2 lines;
// When rendering, the last empty line is not rendered in UI, while the line-number is still counted, to tell users that the file contains a trailing EOL.
@@ -620,7 +620,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
}
}
func markupRender(ctx *context.Context, renderCtx *markup.RenderContext, input io.Reader) (escaped *charset.EscapeStatus, output string, err error) {
func markupRender(ctx *context.Context, renderCtx *markup.RenderContext, input io.Reader) (escaped *charset.EscapeStatus, output template.HTML, err error) {
markupRd, markupWr := io.Pipe()
defer markupWr.Close()
done := make(chan struct{})
@@ -628,7 +628,7 @@ func markupRender(ctx *context.Context, renderCtx *markup.RenderContext, input i
sb := &strings.Builder{}
// We allow NBSP here this is rendered
escaped, _ = charset.EscapeControlReader(markupRd, sb, ctx.Locale, charset.RuneNBSP)
output = sb.String()
output = template.HTML(sb.String())
close(done)
}()
err = markup.Render(renderCtx, input, markupWr)
+8 -10
View File
@@ -105,7 +105,7 @@ func EmailPost(ctx *context.Context) {
// Send activation Email
if ctx.FormString("_method") == "SENDACTIVATION" {
var address string
if setting.CacheService.Enabled && ctx.Cache.IsExist("MailResendLimit_"+ctx.Doer.LowerName) {
if ctx.Cache.IsExist("MailResendLimit_" + ctx.Doer.LowerName) {
log.Error("Send activation: activation still pending")
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
return
@@ -141,11 +141,10 @@ func EmailPost(ctx *context.Context) {
}
address = email.Email
if setting.CacheService.Enabled {
if err := ctx.Cache.Put("MailResendLimit_"+ctx.Doer.LowerName, ctx.Doer.LowerName, 180); err != nil {
log.Error("Set cache(MailResendLimit) fail: %v", err)
}
if err := ctx.Cache.Put("MailResendLimit_"+ctx.Doer.LowerName, ctx.Doer.LowerName, 180); err != nil {
log.Error("Set cache(MailResendLimit) fail: %v", err)
}
ctx.Flash.Info(ctx.Tr("settings.add_email_confirmation_sent", address, timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale)))
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
return
@@ -204,11 +203,10 @@ func EmailPost(ctx *context.Context) {
// Send confirmation email
if setting.Service.RegisterEmailConfirm {
mailer.SendActivateEmailMail(ctx.Doer, email)
if setting.CacheService.Enabled {
if err := ctx.Cache.Put("MailResendLimit_"+ctx.Doer.LowerName, ctx.Doer.LowerName, 180); err != nil {
log.Error("Set cache(MailResendLimit) fail: %v", err)
}
if err := ctx.Cache.Put("MailResendLimit_"+ctx.Doer.LowerName, ctx.Doer.LowerName, 180); err != nil {
log.Error("Set cache(MailResendLimit) fail: %v", err)
}
ctx.Flash.Info(ctx.Tr("settings.add_email_confirmation_sent", email.Email, timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale)))
} else {
ctx.Flash.Success(ctx.Tr("settings.add_email_success"))
@@ -276,7 +274,7 @@ func loadAccountData(ctx *context.Context) {
user_model.EmailAddress
CanBePrimary bool
}
pendingActivation := setting.CacheService.Enabled && ctx.Cache.IsExist("MailResendLimit_"+ctx.Doer.LowerName)
pendingActivation := ctx.Cache.IsExist("MailResendLimit_" + ctx.Doer.LowerName)
emails := make([]*UserEmail, len(emlist))
for i, em := range emlist {
var email UserEmail