From 87c8faaf083e47ce4bf5410369210e338ed0e3d6 Mon Sep 17 00:00:00 2001 From: Sino Date: Fri, 30 Jan 2026 22:27:59 +0800 Subject: [PATCH] Standardize HTTP status codes (#7851) Co-authored-by: Joe Chen --- internal/context/context.go | 4 +-- internal/route/admin/auths.go | 6 ++--- internal/route/admin/users.go | 13 +++++----- internal/route/install.go | 36 +++++++++++++------------- internal/route/org/org.go | 8 +++--- internal/route/org/setting.go | 14 +++++------ internal/route/org/teams.go | 10 ++++---- internal/route/repo/editor.go | 36 +++++++++++++------------- internal/route/repo/issue.go | 10 ++++---- internal/route/repo/pull.go | 12 ++++----- internal/route/repo/release.go | 11 ++++---- internal/route/repo/repo.go | 22 ++++++++-------- internal/route/repo/setting.go | 27 ++++++++++---------- internal/route/repo/webhook.go | 24 +++++++++--------- internal/route/repo/webhook_test.go | 39 +++++++++++++++-------------- internal/route/repo/wiki.go | 7 +++--- internal/route/user/auth.go | 22 ++++++++-------- internal/route/user/setting.go | 27 +++++++++----------- 18 files changed, 165 insertions(+), 163 deletions(-) diff --git a/internal/context/context.go b/internal/context/context.go index 51594a112..454579e73 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -147,13 +147,13 @@ func (c *Context) RedirectSubpath(location string, status ...int) { } // RenderWithErr used for page has form validation but need to prompt error to users. -func (c *Context) RenderWithErr(msg, tpl string, f any) { +func (c *Context) RenderWithErr(msg string, status int, tpl string, f any) { if f != nil { form.Assign(f, c.Data) } c.Flash.ErrorMsg = msg c.Data["Flash"] = c.Flash - c.HTML(http.StatusOK, tpl) + c.HTML(status, tpl) } // NotFound renders the 404 page. diff --git a/internal/route/admin/auths.go b/internal/route/admin/auths.go index 56a9d48e2..dfdf9a4e4 100644 --- a/internal/route/admin/auths.go +++ b/internal/route/admin/auths.go @@ -151,7 +151,7 @@ func NewAuthSourcePost(c *context.Context, f form.Authentication) { c.Data["HasTLS"] = hasTLS if c.HasError() { - c.Success(tmplAdminAuthNew) + c.HTML(http.StatusBadRequest, tmplAdminAuthNew) return } @@ -167,7 +167,7 @@ func NewAuthSourcePost(c *context.Context, f form.Authentication) { if err != nil { if database.IsErrLoginSourceAlreadyExist(err) { c.FormErr("Name") - c.RenderWithErr(c.Tr("admin.auths.login_source_exist", f.Name), tmplAdminAuthNew, f) + c.RenderWithErr(c.Tr("admin.auths.login_source_exist", f.Name), http.StatusUnprocessableEntity, tmplAdminAuthNew, f) } else { c.Error(err, "create login source") } @@ -223,7 +223,7 @@ func EditAuthSourcePost(c *context.Context, f form.Authentication) { c.Data["HasTLS"] = source.Provider.HasTLS() if c.HasError() { - c.Success(tmplAdminAuthEdit) + c.HTML(http.StatusBadRequest, tmplAdminAuthEdit) return } diff --git a/internal/route/admin/users.go b/internal/route/admin/users.go index 75c0dd725..c68861578 100644 --- a/internal/route/admin/users.go +++ b/internal/route/admin/users.go @@ -1,6 +1,7 @@ package admin import ( + "net/http" "strconv" "strings" @@ -68,7 +69,7 @@ func NewUserPost(c *context.Context, f form.AdminCrateUser) { c.Data["CanSendEmail"] = conf.Email.Enabled if c.HasError() { - c.Success(tmplAdminUserNew) + c.HTML(http.StatusBadRequest, tmplAdminUserNew) return } @@ -89,13 +90,13 @@ func NewUserPost(c *context.Context, f form.AdminCrateUser) { switch { case database.IsErrUserAlreadyExist(err): c.Data["Err_UserName"] = true - c.RenderWithErr(c.Tr("form.username_been_taken"), tmplAdminUserNew, &f) + c.RenderWithErr(c.Tr("form.username_been_taken"), http.StatusUnprocessableEntity, tmplAdminUserNew, &f) case database.IsErrEmailAlreadyUsed(err): c.Data["Err_Email"] = true - c.RenderWithErr(c.Tr("form.email_been_used"), tmplAdminUserNew, &f) + c.RenderWithErr(c.Tr("form.email_been_used"), http.StatusUnprocessableEntity, tmplAdminUserNew, &f) case database.IsErrNameNotAllowed(err): c.Data["Err_UserName"] = true - c.RenderWithErr(c.Tr("user.form.name_not_allowed", err.(database.ErrNameNotAllowed).Value()), tmplAdminUserNew, &f) + c.RenderWithErr(c.Tr("user.form.name_not_allowed", err.(database.ErrNameNotAllowed).Value()), http.StatusBadRequest, tmplAdminUserNew, &f) default: c.Error(err, "create user") } @@ -166,7 +167,7 @@ func EditUserPost(c *context.Context, f form.AdminEditUser) { } if c.HasError() { - c.Success(tmplAdminUserEdit) + c.HTML(http.StatusBadRequest, tmplAdminUserEdit) return } @@ -203,7 +204,7 @@ func EditUserPost(c *context.Context, f form.AdminEditUser) { if err != nil { if database.IsErrEmailAlreadyUsed(err) { c.Data["Err_Email"] = true - c.RenderWithErr(c.Tr("form.email_been_used"), tmplAdminUserEdit, &f) + c.RenderWithErr(c.Tr("form.email_been_used"), http.StatusUnprocessableEntity, tmplAdminUserEdit, &f) } else { c.Error(err, "update user") } diff --git a/internal/route/install.go b/internal/route/install.go index cb3b95428..ddbabe401 100644 --- a/internal/route/install.go +++ b/internal/route/install.go @@ -1,6 +1,7 @@ package route import ( + "net/http" "net/mail" "os" "os/exec" @@ -194,13 +195,12 @@ func InstallPost(c *context.Context, f form.Install) { c.HasValue("Err_AdminEmail") { c.FormErr("Admin") } - - c.Success(INSTALL) + c.HTML(http.StatusBadRequest, INSTALL) return } if _, err := exec.LookPath("git"); err != nil { - c.RenderWithErr(c.Tr("install.test_git_failed", err), INSTALL, &f) + c.RenderWithErr(c.Tr("install.test_git_failed", err), http.StatusInternalServerError, INSTALL, &f) return } @@ -222,7 +222,7 @@ func InstallPost(c *context.Context, f form.Install) { if conf.Database.Type == "sqlite3" && conf.Database.Path == "" { c.FormErr("DbPath") - c.RenderWithErr(c.Tr("install.err_empty_db_path"), INSTALL, &f) + c.RenderWithErr(c.Tr("install.err_empty_db_path"), http.StatusBadRequest, INSTALL, &f) return } @@ -230,10 +230,10 @@ func InstallPost(c *context.Context, f form.Install) { if err := database.NewTestEngine(); err != nil { if strings.Contains(err.Error(), `Unknown database type: sqlite3`) { c.FormErr("DbType") - c.RenderWithErr(c.Tr("install.sqlite3_not_available", "https://gogs.io/docs/installation/install_from_binary.html"), INSTALL, &f) + c.RenderWithErr(c.Tr("install.sqlite3_not_available", "https://gogs.io/docs/installation/install_from_binary.html"), http.StatusInternalServerError, INSTALL, &f) } else { c.FormErr("DbSetting") - c.RenderWithErr(c.Tr("install.invalid_db_setting", err), INSTALL, &f) + c.RenderWithErr(c.Tr("install.invalid_db_setting", err), http.StatusBadRequest, INSTALL, &f) } return } @@ -242,7 +242,7 @@ func InstallPost(c *context.Context, f form.Install) { f.RepoRootPath = strings.ReplaceAll(f.RepoRootPath, "\\", "/") if err := os.MkdirAll(f.RepoRootPath, os.ModePerm); err != nil { c.FormErr("RepoRootPath") - c.RenderWithErr(c.Tr("install.invalid_repo_path", err), INSTALL, &f) + c.RenderWithErr(c.Tr("install.invalid_repo_path", err), http.StatusBadRequest, INSTALL, &f) return } @@ -250,21 +250,21 @@ func InstallPost(c *context.Context, f form.Install) { f.LogRootPath = strings.ReplaceAll(f.LogRootPath, "\\", "/") if err := os.MkdirAll(f.LogRootPath, os.ModePerm); err != nil { c.FormErr("LogRootPath") - c.RenderWithErr(c.Tr("install.invalid_log_root_path", err), INSTALL, &f) + c.RenderWithErr(c.Tr("install.invalid_log_root_path", err), http.StatusBadRequest, INSTALL, &f) return } currentUser, match := conf.CheckRunUser(f.RunUser) if !match { c.FormErr("RunUser") - c.RenderWithErr(c.Tr("install.run_user_not_match", f.RunUser, currentUser), INSTALL, &f) + c.RenderWithErr(c.Tr("install.run_user_not_match", f.RunUser, currentUser), http.StatusForbidden, INSTALL, &f) return } // Check host address and port if len(f.SMTPHost) > 0 && !strings.Contains(f.SMTPHost, ":") { c.FormErr("SMTP", "SMTPHost") - c.RenderWithErr(c.Tr("install.smtp_host_missing_port"), INSTALL, &f) + c.RenderWithErr(c.Tr("install.smtp_host_missing_port"), http.StatusBadRequest, INSTALL, &f) return } @@ -273,7 +273,7 @@ func InstallPost(c *context.Context, f form.Install) { _, err := mail.ParseAddress(f.SMTPFrom) if err != nil { c.FormErr("SMTP", "SMTPFrom") - c.RenderWithErr(c.Tr("install.invalid_smtp_from", err), INSTALL, &f) + c.RenderWithErr(c.Tr("install.invalid_smtp_from", err), http.StatusBadRequest, INSTALL, &f) return } } @@ -281,19 +281,19 @@ func InstallPost(c *context.Context, f form.Install) { // Check logic loophole between disable self-registration and no admin account. if f.DisableRegistration && f.AdminName == "" { c.FormErr("Services", "Admin") - c.RenderWithErr(c.Tr("install.no_admin_and_disable_registration"), INSTALL, f) + c.RenderWithErr(c.Tr("install.no_admin_and_disable_registration"), http.StatusUnprocessableEntity, INSTALL, f) return } // Check admin password. if len(f.AdminName) > 0 && f.AdminPasswd == "" { c.FormErr("Admin", "AdminPasswd") - c.RenderWithErr(c.Tr("install.err_empty_admin_password"), INSTALL, f) + c.RenderWithErr(c.Tr("install.err_empty_admin_password"), http.StatusBadRequest, INSTALL, f) return } if f.AdminPasswd != f.AdminConfirmPasswd { c.FormErr("Admin", "AdminPasswd") - c.RenderWithErr(c.Tr("form.password_not_match"), INSTALL, f) + c.RenderWithErr(c.Tr("form.password_not_match"), http.StatusBadRequest, INSTALL, f) return } @@ -367,21 +367,21 @@ func InstallPost(c *context.Context, f form.Install) { cfg.Section("security").Key("INSTALL_LOCK").SetValue("true") secretKey, err := strutil.RandomChars(15) if err != nil { - c.RenderWithErr(c.Tr("install.secret_key_failed", err), INSTALL, &f) + c.RenderWithErr(c.Tr("install.secret_key_failed", err), http.StatusInternalServerError, INSTALL, &f) return } cfg.Section("security").Key("SECRET_KEY").SetValue(secretKey) _ = os.MkdirAll(filepath.Dir(conf.CustomConf), os.ModePerm) if err := cfg.SaveTo(conf.CustomConf); err != nil { - c.RenderWithErr(c.Tr("install.save_config_failed", err), INSTALL, &f) + c.RenderWithErr(c.Tr("install.save_config_failed", err), http.StatusInternalServerError, INSTALL, &f) return } // NOTE: We reuse the current value because this handler does not have access to CLI flags. err = GlobalInit(conf.CustomConf) if err != nil { - c.RenderWithErr(c.Tr("install.init_failed", err), INSTALL, &f) + c.RenderWithErr(c.Tr("install.init_failed", err), http.StatusInternalServerError, INSTALL, &f) return } @@ -401,7 +401,7 @@ func InstallPost(c *context.Context, f form.Install) { if !database.IsErrUserAlreadyExist(err) { conf.Security.InstallLock = false c.FormErr("AdminName", "AdminEmail") - c.RenderWithErr(c.Tr("install.invalid_admin_setting", err), INSTALL, &f) + c.RenderWithErr(c.Tr("install.invalid_admin_setting", err), http.StatusBadRequest, INSTALL, &f) return } diff --git a/internal/route/org/org.go b/internal/route/org/org.go index 3907e292a..a24e266cd 100644 --- a/internal/route/org/org.go +++ b/internal/route/org/org.go @@ -1,6 +1,8 @@ package org import ( + "net/http" + log "unknwon.dev/clog/v2" "gogs.io/gogs/internal/context" @@ -21,7 +23,7 @@ func CreatePost(c *context.Context, f form.CreateOrg) { c.Title("new_org") if c.HasError() { - c.Success(CREATE) + c.HTML(http.StatusBadRequest, CREATE) return } @@ -35,9 +37,9 @@ func CreatePost(c *context.Context, f form.CreateOrg) { c.Data["Err_OrgName"] = true switch { case database.IsErrUserAlreadyExist(err): - c.RenderWithErr(c.Tr("form.org_name_been_taken"), CREATE, &f) + c.RenderWithErr(c.Tr("form.org_name_been_taken"), http.StatusUnprocessableEntity, CREATE, &f) case database.IsErrNameNotAllowed(err): - c.RenderWithErr(c.Tr("org.form.name_not_allowed", err.(database.ErrNameNotAllowed).Value()), CREATE, &f) + c.RenderWithErr(c.Tr("org.form.name_not_allowed", err.(database.ErrNameNotAllowed).Value()), http.StatusBadRequest, CREATE, &f) default: c.Error(err, "create organization") } diff --git a/internal/route/org/setting.go b/internal/route/org/setting.go index 44b54eb97..9597f780c 100644 --- a/internal/route/org/setting.go +++ b/internal/route/org/setting.go @@ -1,6 +1,8 @@ package org import ( + "net/http" + log "unknwon.dev/clog/v2" "gogs.io/gogs/internal/auth" @@ -27,7 +29,7 @@ func SettingsPost(c *context.Context, f form.UpdateOrgSetting) { c.Data["PageIsSettingsOptions"] = true if c.HasError() { - c.Success(tmplOrgSettingsOptions) + c.HTML(http.StatusBadRequest, tmplOrgSettingsOptions) return } @@ -38,18 +40,14 @@ func SettingsPost(c *context.Context, f form.UpdateOrgSetting) { err := database.Handle.Users().ChangeUsername(c.Req.Context(), c.Org.Organization.ID, f.Name) if err != nil { c.Data["OrgName"] = true - var msg string switch { case database.IsErrUserAlreadyExist(err): - msg = c.Tr("form.username_been_taken") + c.RenderWithErr(c.Tr("form.username_been_taken"), http.StatusUnprocessableEntity, tmplOrgSettingsOptions, &f) case database.IsErrNameNotAllowed(err): - msg = c.Tr("user.form.name_not_allowed", err.(database.ErrNameNotAllowed).Value()) + c.RenderWithErr(c.Tr("user.form.name_not_allowed", err.(database.ErrNameNotAllowed).Value()), http.StatusBadRequest, tmplOrgSettingsOptions, &f) default: c.Error(err, "change organization name") - return } - - c.RenderWithErr(msg, tmplOrgSettingsOptions, &f) return } @@ -104,7 +102,7 @@ func SettingsDelete(c *context.Context) { if c.Req.Method == "POST" { if _, err := database.Handle.Users().Authenticate(c.Req.Context(), c.User.Name, c.Query("password"), c.User.LoginSource); err != nil { if auth.IsErrBadCredentials(err) { - c.RenderWithErr(c.Tr("form.enterred_invalid_password"), tmplOrgSettingsDelete, nil) + c.RenderWithErr(c.Tr("form.enterred_invalid_password"), http.StatusUnauthorized, tmplOrgSettingsDelete, nil) } else { c.Error(err, "authenticate user") } diff --git a/internal/route/org/teams.go b/internal/route/org/teams.go index e74f74435..f13e7ba84 100644 --- a/internal/route/org/teams.go +++ b/internal/route/org/teams.go @@ -159,7 +159,7 @@ func NewTeamPost(c *context.Context, f form.CreateTeam) { c.Data["Team"] = t if c.HasError() { - c.Success(tmplOrgTeamNew) + c.HTML(http.StatusBadRequest, tmplOrgTeamNew) return } @@ -167,9 +167,9 @@ func NewTeamPost(c *context.Context, f form.CreateTeam) { c.Data["Err_TeamName"] = true switch { case database.IsErrTeamAlreadyExist(err): - c.RenderWithErr(c.Tr("form.team_name_been_taken"), tmplOrgTeamNew, &f) + c.RenderWithErr(c.Tr("form.team_name_been_taken"), http.StatusUnprocessableEntity, tmplOrgTeamNew, &f) case database.IsErrNameNotAllowed(err): - c.RenderWithErr(c.Tr("org.form.team_name_not_allowed", err.(database.ErrNameNotAllowed).Value()), tmplOrgTeamNew, &f) + c.RenderWithErr(c.Tr("org.form.team_name_not_allowed", err.(database.ErrNameNotAllowed).Value()), http.StatusBadRequest, tmplOrgTeamNew, &f) default: c.Error(err, "new team") } @@ -214,7 +214,7 @@ func EditTeamPost(c *context.Context, f form.CreateTeam) { c.Data["Team"] = t if c.HasError() { - c.Success(tmplOrgTeamNew) + c.HTML(http.StatusBadRequest, tmplOrgTeamNew) return } @@ -245,7 +245,7 @@ func EditTeamPost(c *context.Context, f form.CreateTeam) { c.Data["Err_TeamName"] = true switch { case database.IsErrTeamAlreadyExist(err): - c.RenderWithErr(c.Tr("form.team_name_been_taken"), tmplOrgTeamNew, &f) + c.RenderWithErr(c.Tr("form.team_name_been_taken"), http.StatusUnprocessableEntity, tmplOrgTeamNew, &f) default: c.Error(err, "update team") } diff --git a/internal/route/repo/editor.go b/internal/route/repo/editor.go index 6582d8c87..9e3bb563a 100644 --- a/internal/route/repo/editor.go +++ b/internal/route/repo/editor.go @@ -153,20 +153,20 @@ func editFilePost(c *context.Context, f form.EditRepoFile, isNewFile bool) { c.Data["PreviewableFileModes"] = strings.Join(conf.Repository.Editor.PreviewableFileModes, ",") if c.HasError() { - c.Success(tmplEditorEdit) + c.HTML(http.StatusBadRequest, tmplEditorEdit) return } if f.TreePath == "" { c.FormErr("TreePath") - c.RenderWithErr(c.Tr("repo.editor.filename_cannot_be_empty"), tmplEditorEdit, &f) + c.RenderWithErr(c.Tr("repo.editor.filename_cannot_be_empty"), http.StatusBadRequest, tmplEditorEdit, &f) return } if oldBranchName != branchName { if _, err := c.Repo.Repository.GetBranch(branchName); err == nil { c.FormErr("NewBranchName") - c.RenderWithErr(c.Tr("repo.editor.branch_already_exists", branchName), tmplEditorEdit, &f) + c.RenderWithErr(c.Tr("repo.editor.branch_already_exists", branchName), http.StatusUnprocessableEntity, tmplEditorEdit, &f) return } } @@ -187,18 +187,18 @@ func editFilePost(c *context.Context, f form.EditRepoFile, isNewFile bool) { if index != len(treeNames)-1 { if !entry.IsTree() { c.FormErr("TreePath") - c.RenderWithErr(c.Tr("repo.editor.directory_is_a_file", part), tmplEditorEdit, &f) + c.RenderWithErr(c.Tr("repo.editor.directory_is_a_file", part), http.StatusUnprocessableEntity, tmplEditorEdit, &f) return } } else { // 🚨 SECURITY: Do not allow editing if the target file is a symlink. if entry.IsSymlink() { c.FormErr("TreePath") - c.RenderWithErr(c.Tr("repo.editor.file_is_a_symlink", part), tmplEditorEdit, &f) + c.RenderWithErr(c.Tr("repo.editor.file_is_a_symlink", part), http.StatusUnprocessableEntity, tmplEditorEdit, &f) return } else if entry.IsTree() { c.FormErr("TreePath") - c.RenderWithErr(c.Tr("repo.editor.filename_is_a_directory", part), tmplEditorEdit, &f) + c.RenderWithErr(c.Tr("repo.editor.filename_is_a_directory", part), http.StatusUnprocessableEntity, tmplEditorEdit, &f) return } } @@ -209,7 +209,7 @@ func editFilePost(c *context.Context, f form.EditRepoFile, isNewFile bool) { if err != nil { if gitutil.IsErrRevisionNotExist(err) { c.FormErr("TreePath") - c.RenderWithErr(c.Tr("repo.editor.file_editing_no_longer_exists", oldTreePath), tmplEditorEdit, &f) + c.RenderWithErr(c.Tr("repo.editor.file_editing_no_longer_exists", oldTreePath), http.StatusNotFound, tmplEditorEdit, &f) } else { c.Error(err, "get tree entry") } @@ -219,7 +219,7 @@ func editFilePost(c *context.Context, f form.EditRepoFile, isNewFile bool) { // 🚨 SECURITY: Do not allow editing if the old file is a symlink. if entry.IsSymlink() { c.FormErr("TreePath") - c.RenderWithErr(c.Tr("repo.editor.file_is_a_symlink", oldTreePath), tmplEditorEdit, &f) + c.RenderWithErr(c.Tr("repo.editor.file_is_a_symlink", oldTreePath), http.StatusUnprocessableEntity, tmplEditorEdit, &f) return } @@ -232,7 +232,7 @@ func editFilePost(c *context.Context, f form.EditRepoFile, isNewFile bool) { for _, file := range files { if file == f.TreePath { - c.RenderWithErr(c.Tr("repo.editor.file_changed_while_editing", c.Repo.RepoLink+"/compare/"+lastCommit+"..."+c.Repo.CommitID), tmplEditorEdit, &f) + c.RenderWithErr(c.Tr("repo.editor.file_changed_while_editing", c.Repo.RepoLink+"/compare/"+lastCommit+"..."+c.Repo.CommitID), http.StatusConflict, tmplEditorEdit, &f) return } } @@ -250,7 +250,7 @@ func editFilePost(c *context.Context, f form.EditRepoFile, isNewFile bool) { } if entry != nil { c.FormErr("TreePath") - c.RenderWithErr(c.Tr("repo.editor.file_already_exists", f.TreePath), tmplEditorEdit, &f) + c.RenderWithErr(c.Tr("repo.editor.file_already_exists", f.TreePath), http.StatusUnprocessableEntity, tmplEditorEdit, &f) return } } @@ -280,7 +280,7 @@ func editFilePost(c *context.Context, f form.EditRepoFile, isNewFile bool) { }); err != nil { log.Error("Failed to update repo file: %v", err) c.FormErr("TreePath") - c.RenderWithErr(c.Tr("repo.editor.fail_to_update_file", f.TreePath, errInternalServerError), tmplEditorEdit, &f) + c.RenderWithErr(c.Tr("repo.editor.fail_to_update_file", f.TreePath, errInternalServerError), http.StatusInternalServerError, tmplEditorEdit, &f) return } @@ -358,14 +358,14 @@ func DeleteFilePost(c *context.Context, f form.DeleteRepoFile) { c.Data["new_branch_name"] = branchName if c.HasError() { - c.Success(tmplEditorDelete) + c.HTML(http.StatusBadRequest, tmplEditorDelete) return } if oldBranchName != branchName { if _, err := c.Repo.Repository.GetBranch(branchName); err == nil { c.FormErr("NewBranchName") - c.RenderWithErr(c.Tr("repo.editor.branch_already_exists", branchName), tmplEditorDelete, &f) + c.RenderWithErr(c.Tr("repo.editor.branch_already_exists", branchName), http.StatusUnprocessableEntity, tmplEditorDelete, &f) return } } @@ -388,7 +388,7 @@ func DeleteFilePost(c *context.Context, f form.DeleteRepoFile) { Message: message, }); err != nil { log.Error("Failed to delete repo file: %v", err) - c.RenderWithErr(c.Tr("repo.editor.fail_to_delete_file", c.Repo.TreePath, errInternalServerError), tmplEditorDelete, &f) + c.RenderWithErr(c.Tr("repo.editor.fail_to_delete_file", c.Repo.TreePath, errInternalServerError), http.StatusInternalServerError, tmplEditorDelete, &f) return } @@ -456,14 +456,14 @@ func UploadFilePost(c *context.Context, f form.UploadRepoFile) { c.Data["new_branch_name"] = branchName if c.HasError() { - c.Success(tmplEditorUpload) + c.HTML(http.StatusBadRequest, tmplEditorUpload) return } if oldBranchName != branchName { if _, err := c.Repo.Repository.GetBranch(branchName); err == nil { c.FormErr("NewBranchName") - c.RenderWithErr(c.Tr("repo.editor.branch_already_exists", branchName), tmplEditorUpload, &f) + c.RenderWithErr(c.Tr("repo.editor.branch_already_exists", branchName), http.StatusUnprocessableEntity, tmplEditorUpload, &f) return } } @@ -485,7 +485,7 @@ func UploadFilePost(c *context.Context, f form.UploadRepoFile) { // User can only upload files to a directory. if !entry.IsTree() { c.FormErr("TreePath") - c.RenderWithErr(c.Tr("repo.editor.directory_is_a_file", part), tmplEditorUpload, &f) + c.RenderWithErr(c.Tr("repo.editor.directory_is_a_file", part), http.StatusUnprocessableEntity, tmplEditorUpload, &f) return } } @@ -510,7 +510,7 @@ func UploadFilePost(c *context.Context, f form.UploadRepoFile) { }); err != nil { log.Error("Failed to upload files: %v", err) c.FormErr("TreePath") - c.RenderWithErr(c.Tr("repo.editor.unable_to_upload_files", f.TreePath, errInternalServerError), tmplEditorUpload, &f) + c.RenderWithErr(c.Tr("repo.editor.unable_to_upload_files", f.TreePath, errInternalServerError), http.StatusInternalServerError, tmplEditorUpload, &f) return } diff --git a/internal/route/repo/issue.go b/internal/route/repo/issue.go index f8c19ff7c..1c4ba7b5d 100644 --- a/internal/route/repo/issue.go +++ b/internal/route/repo/issue.go @@ -409,7 +409,7 @@ func NewIssuePost(c *context.Context, f form.NewIssue) { } if c.HasError() { - c.Success(tmplRepoIssueNew) + c.HTML(http.StatusBadRequest, tmplRepoIssueNew) return } @@ -1148,7 +1148,7 @@ func NewMilestonePost(c *context.Context, f form.CreateMilestone) { c.Data["DateLang"] = conf.I18n.DateLang(c.Language()) if c.HasError() { - c.Success(tmplRepoIssueMilestoneNew) + c.HTML(http.StatusBadRequest, tmplRepoIssueMilestoneNew) return } @@ -1158,7 +1158,7 @@ func NewMilestonePost(c *context.Context, f form.CreateMilestone) { deadline, err := time.ParseInLocation("2006-01-02", f.Deadline, time.Local) if err != nil { c.Data["Err_Deadline"] = true - c.RenderWithErr(c.Tr("repo.milestones.invalid_due_date_format"), tmplRepoIssueMilestoneNew, &f) + c.RenderWithErr(c.Tr("repo.milestones.invalid_due_date_format"), http.StatusBadRequest, tmplRepoIssueMilestoneNew, &f) return } @@ -1204,7 +1204,7 @@ func EditMilestonePost(c *context.Context, f form.CreateMilestone) { c.Data["DateLang"] = conf.I18n.DateLang(c.Language()) if c.HasError() { - c.Success(tmplRepoIssueMilestoneNew) + c.HTML(http.StatusBadRequest, tmplRepoIssueMilestoneNew) return } @@ -1214,7 +1214,7 @@ func EditMilestonePost(c *context.Context, f form.CreateMilestone) { deadline, err := time.ParseInLocation("2006-01-02", f.Deadline, time.Local) if err != nil { c.Data["Err_Deadline"] = true - c.RenderWithErr(c.Tr("repo.milestones.invalid_due_date_format"), tmplRepoIssueMilestoneNew, &f) + c.RenderWithErr(c.Tr("repo.milestones.invalid_due_date_format"), http.StatusBadRequest, tmplRepoIssueMilestoneNew, &f) return } diff --git a/internal/route/repo/pull.go b/internal/route/repo/pull.go index c7209eda2..d86effb93 100644 --- a/internal/route/repo/pull.go +++ b/internal/route/repo/pull.go @@ -108,7 +108,7 @@ func ForkPost(c *context.Context, f form.CreateRepo) { c.Data["ContextUser"] = ctxUser if c.HasError() { - c.Success(tmplRepoPullsFork) + c.HTML(http.StatusBadRequest, tmplRepoPullsFork) return } @@ -129,7 +129,7 @@ func ForkPost(c *context.Context, f form.CreateRepo) { // Cannot fork to same owner if ctxUser.ID == baseRepo.OwnerID { - c.RenderWithErr(c.Tr("repo.settings.cannot_fork_to_same_owner"), tmplRepoPullsFork, &f) + c.RenderWithErr(c.Tr("repo.settings.cannot_fork_to_same_owner"), http.StatusUnprocessableEntity, tmplRepoPullsFork, &f) return } @@ -138,11 +138,11 @@ func ForkPost(c *context.Context, f form.CreateRepo) { c.Data["Err_RepoName"] = true switch { case database.IsErrReachLimitOfRepo(err): - c.RenderWithErr(c.Tr("repo.form.reach_limit_of_creation", err.(database.ErrReachLimitOfRepo).Limit), tmplRepoPullsFork, &f) + c.RenderWithErr(c.Tr("repo.form.reach_limit_of_creation", err.(database.ErrReachLimitOfRepo).Limit), http.StatusForbidden, tmplRepoPullsFork, &f) case database.IsErrRepoAlreadyExist(err): - c.RenderWithErr(c.Tr("repo.settings.new_owner_has_same_repo"), tmplRepoPullsFork, &f) + c.RenderWithErr(c.Tr("repo.settings.new_owner_has_same_repo"), http.StatusUnprocessableEntity, tmplRepoPullsFork, &f) case database.IsErrNameNotAllowed(err): - c.RenderWithErr(c.Tr("repo.form.name_not_allowed", err.(database.ErrNameNotAllowed).Value()), tmplRepoPullsFork, &f) + c.RenderWithErr(c.Tr("repo.form.name_not_allowed", err.(database.ErrNameNotAllowed).Value()), http.StatusBadRequest, tmplRepoPullsFork, &f) default: c.Error(err, "fork repository") } @@ -709,7 +709,7 @@ func CompareAndPullRequestPost(c *context.Context, f form.NewIssue) { return } - c.Success(tmplRepoPullsCompare) + c.HTML(http.StatusBadRequest, tmplRepoPullsCompare) return } diff --git a/internal/route/repo/release.go b/internal/route/repo/release.go index c37dc5a1f..4682f5ace 100644 --- a/internal/route/repo/release.go +++ b/internal/route/repo/release.go @@ -1,6 +1,7 @@ package repo import ( + "net/http" "strings" "github.com/cockroachdb/errors" @@ -169,12 +170,12 @@ func NewReleasePost(c *context.Context, f form.NewRelease) { renderReleaseAttachmentSettings(c) if c.HasError() { - c.Success(tmplRepoReleaseNew) + c.HTML(http.StatusBadRequest, tmplRepoReleaseNew) return } if !c.Repo.GitRepo.HasBranch(f.Target) { - c.RenderWithErr(c.Tr("form.target_branch_not_exist"), tmplRepoReleaseNew, &f) + c.RenderWithErr(c.Tr("form.target_branch_not_exist"), http.StatusUnprocessableEntity, tmplRepoReleaseNew, &f) return } @@ -222,9 +223,9 @@ func NewReleasePost(c *context.Context, f form.NewRelease) { c.Data["Err_TagName"] = true switch { case database.IsErrReleaseAlreadyExist(err): - c.RenderWithErr(c.Tr("repo.release.tag_name_already_exist"), tmplRepoReleaseNew, &f) + c.RenderWithErr(c.Tr("repo.release.tag_name_already_exist"), http.StatusUnprocessableEntity, tmplRepoReleaseNew, &f) case database.IsErrInvalidTagName(err): - c.RenderWithErr(c.Tr("repo.release.tag_name_invalid"), tmplRepoReleaseNew, &f) + c.RenderWithErr(c.Tr("repo.release.tag_name_invalid"), http.StatusBadRequest, tmplRepoReleaseNew, &f) default: c.Error(err, "new release") } @@ -280,7 +281,7 @@ func EditReleasePost(c *context.Context, f form.EditRelease) { c.Data["IsDraft"] = rel.IsDraft if c.HasError() { - c.Success(tmplRepoReleaseNew) + c.HTML(http.StatusBadRequest, tmplRepoReleaseNew) return } diff --git a/internal/route/repo/repo.go b/internal/route/repo/repo.go index a30f5e68a..d81971bc4 100644 --- a/internal/route/repo/repo.go +++ b/internal/route/repo/repo.go @@ -86,13 +86,13 @@ func Create(c *context.Context) { func handleCreateError(c *context.Context, err error, name, tpl string, form any) { switch { case database.IsErrReachLimitOfRepo(err): - c.RenderWithErr(c.Tr("repo.form.reach_limit_of_creation", err.(database.ErrReachLimitOfRepo).Limit), tpl, form) + c.RenderWithErr(c.Tr("repo.form.reach_limit_of_creation", err.(database.ErrReachLimitOfRepo).Limit), http.StatusForbidden, tpl, form) case database.IsErrRepoAlreadyExist(err): c.Data["Err_RepoName"] = true - c.RenderWithErr(c.Tr("form.repo_name_been_taken"), tpl, form) + c.RenderWithErr(c.Tr("form.repo_name_been_taken"), http.StatusUnprocessableEntity, tpl, form) case database.IsErrNameNotAllowed(err): c.Data["Err_RepoName"] = true - c.RenderWithErr(c.Tr("repo.form.name_not_allowed", err.(database.ErrNameNotAllowed).Value()), tpl, form) + c.RenderWithErr(c.Tr("repo.form.name_not_allowed", err.(database.ErrNameNotAllowed).Value()), http.StatusBadRequest, tpl, form) default: c.Error(err, name) } @@ -112,7 +112,7 @@ func CreatePost(c *context.Context, f form.CreateRepo) { c.Data["ContextUser"] = ctxUser if c.HasError() { - c.Success(CREATE) + c.HTML(http.StatusBadRequest, CREATE) return } @@ -166,7 +166,7 @@ func MigratePost(c *context.Context, f form.MigrateRepo) { c.Data["ContextUser"] = ctxUser if c.HasError() { - c.Success(MIGRATE) + c.HTML(http.StatusBadRequest, MIGRATE) return } @@ -177,13 +177,13 @@ func MigratePost(c *context.Context, f form.MigrateRepo) { addrErr := err.(database.ErrInvalidCloneAddr) switch { case addrErr.IsURLError: - c.RenderWithErr(c.Tr("repo.migrate.clone_address")+c.Tr("form.url_error"), MIGRATE, &f) + c.RenderWithErr(c.Tr("repo.migrate.clone_address")+c.Tr("form.url_error"), http.StatusBadRequest, MIGRATE, &f) case addrErr.IsPermissionDenied: - c.RenderWithErr(c.Tr("repo.migrate.permission_denied"), MIGRATE, &f) + c.RenderWithErr(c.Tr("repo.migrate.permission_denied"), http.StatusForbidden, MIGRATE, &f) case addrErr.IsInvalidPath: - c.RenderWithErr(c.Tr("repo.migrate.invalid_local_path"), MIGRATE, &f) + c.RenderWithErr(c.Tr("repo.migrate.invalid_local_path"), http.StatusBadRequest, MIGRATE, &f) case addrErr.IsBlockedLocalAddress: - c.RenderWithErr(c.Tr("repo.migrate.clone_address_resolved_to_blocked_local_address"), MIGRATE, &f) + c.RenderWithErr(c.Tr("repo.migrate.clone_address_resolved_to_blocked_local_address"), http.StatusForbidden, MIGRATE, &f) default: c.Error(err, "unexpected error") } @@ -216,11 +216,11 @@ func MigratePost(c *context.Context, f form.MigrateRepo) { if strings.Contains(err.Error(), "Authentication failed") || strings.Contains(err.Error(), "could not read Username") { c.Data["Err_Auth"] = true - c.RenderWithErr(c.Tr("form.auth_failed", database.HandleMirrorCredentials(err.Error(), true)), MIGRATE, &f) + c.RenderWithErr(c.Tr("form.auth_failed", database.HandleMirrorCredentials(err.Error(), true)), http.StatusUnauthorized, MIGRATE, &f) return } else if strings.Contains(err.Error(), "fatal:") { c.Data["Err_CloneAddr"] = true - c.RenderWithErr(c.Tr("repo.migrate.failed", database.HandleMirrorCredentials(err.Error(), true)), MIGRATE, &f) + c.RenderWithErr(c.Tr("repo.migrate.failed", database.HandleMirrorCredentials(err.Error(), true)), http.StatusInternalServerError, MIGRATE, &f) return } diff --git a/internal/route/repo/setting.go b/internal/route/repo/setting.go index 6c36889b8..0adfa3217 100644 --- a/internal/route/repo/setting.go +++ b/internal/route/repo/setting.go @@ -3,6 +3,7 @@ package repo import ( "fmt" "io" + "net/http" "strings" "time" @@ -49,7 +50,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) { switch c.Query("action") { case "update": if c.HasError() { - c.Success(tmplRepoSettingsOptions) + c.HTML(http.StatusBadRequest, tmplRepoSettingsOptions) return } @@ -63,9 +64,9 @@ func SettingsPost(c *context.Context, f form.RepoSetting) { c.FormErr("RepoName") switch { case database.IsErrRepoAlreadyExist(err): - c.RenderWithErr(c.Tr("form.repo_name_been_taken"), tmplRepoSettingsOptions, &f) + c.RenderWithErr(c.Tr("form.repo_name_been_taken"), http.StatusUnprocessableEntity, tmplRepoSettingsOptions, &f) case database.IsErrNameNotAllowed(err): - c.RenderWithErr(c.Tr("repo.form.name_not_allowed", err.(database.ErrNameNotAllowed).Value()), tmplRepoSettingsOptions, &f) + c.RenderWithErr(c.Tr("repo.form.name_not_allowed", err.(database.ErrNameNotAllowed).Value()), http.StatusBadRequest, tmplRepoSettingsOptions, &f) default: c.Error(err, "change repository name") } @@ -175,7 +176,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) { return } if repo.Name != f.RepoName { - c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), tmplRepoSettingsOptions, nil) + c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), http.StatusBadRequest, tmplRepoSettingsOptions, nil) return } @@ -209,7 +210,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) { return } if repo.Name != f.RepoName { - c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), tmplRepoSettingsOptions, nil) + c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), http.StatusBadRequest, tmplRepoSettingsOptions, nil) return } @@ -222,13 +223,13 @@ func SettingsPost(c *context.Context, f form.RepoSetting) { newOwner := c.Query("new_owner_name") if !database.Handle.Users().IsUsernameUsed(c.Req.Context(), newOwner, c.Repo.Owner.ID) { - c.RenderWithErr(c.Tr("form.enterred_invalid_owner_name"), tmplRepoSettingsOptions, nil) + c.RenderWithErr(c.Tr("form.enterred_invalid_owner_name"), http.StatusBadRequest, tmplRepoSettingsOptions, nil) return } if err := database.TransferOwnership(c.User, newOwner, repo); err != nil { if database.IsErrRepoAlreadyExist(err) { - c.RenderWithErr(c.Tr("repo.settings.new_owner_has_same_repo"), tmplRepoSettingsOptions, nil) + c.RenderWithErr(c.Tr("repo.settings.new_owner_has_same_repo"), http.StatusUnprocessableEntity, tmplRepoSettingsOptions, nil) } else { c.Error(err, "transfer ownership") } @@ -244,7 +245,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) { return } if repo.Name != f.RepoName { - c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), tmplRepoSettingsOptions, nil) + c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), http.StatusBadRequest, tmplRepoSettingsOptions, nil) return } @@ -270,7 +271,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) { return } if repo.Name != f.RepoName { - c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), tmplRepoSettingsOptions, nil) + c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), http.StatusBadRequest, tmplRepoSettingsOptions, nil) return } @@ -436,7 +437,7 @@ func SettingsBranches(c *context.Context) { if c.Repo.Repository.IsBare { c.Flash.Info(c.Tr("repo.settings.branches_bare"), true) - c.Success(tmplRepoSettingsBranches) + c.HTML(http.StatusUnprocessableEntity, tmplRepoSettingsBranches) return } @@ -652,7 +653,7 @@ func SettingsDeployKeysPost(c *context.Context, f form.AddSSHKey) { c.Data["Deploykeys"] = keys if c.HasError() { - c.Success(tmplRepoSettingsDeployKeys) + c.HTML(http.StatusBadRequest, tmplRepoSettingsDeployKeys) return } @@ -675,10 +676,10 @@ func SettingsDeployKeysPost(c *context.Context, f form.AddSSHKey) { switch { case database.IsErrKeyAlreadyExist(err): c.Data["Err_Content"] = true - c.RenderWithErr(c.Tr("repo.settings.key_been_used"), tmplRepoSettingsDeployKeys, &f) + c.RenderWithErr(c.Tr("repo.settings.key_been_used"), http.StatusUnprocessableEntity, tmplRepoSettingsDeployKeys, &f) case database.IsErrKeyNameAlreadyUsed(err): c.Data["Err_Title"] = true - c.RenderWithErr(c.Tr("repo.settings.key_name_used"), tmplRepoSettingsDeployKeys, &f) + c.RenderWithErr(c.Tr("repo.settings.key_name_used"), http.StatusUnprocessableEntity, tmplRepoSettingsDeployKeys, &f) default: c.Error(err, "add deploy key") } diff --git a/internal/route/repo/webhook.go b/internal/route/repo/webhook.go index a3f1c5328..a7d628447 100644 --- a/internal/route/repo/webhook.go +++ b/internal/route/repo/webhook.go @@ -116,32 +116,32 @@ func WebhooksNew(c *context.Context, orCtx *orgRepoContext) { c.Success(orCtx.TmplNew) } -func validateWebhook(l macaron.Locale, w *database.Webhook) (field, msg string, ok bool) { +func validateWebhook(l macaron.Locale, w *database.Webhook) (field, msg string, status int) { // 🚨 SECURITY: Local addresses must not be allowed by non-admins to prevent SSRF, // see https://github.com/gogs/gogs/issues/5366 for details. payloadURL, err := url.Parse(w.URL) if err != nil { - return "PayloadURL", l.Tr("repo.settings.webhook.err_cannot_parse_payload_url", err), false + return "PayloadURL", l.Tr("repo.settings.webhook.err_cannot_parse_payload_url", err), http.StatusBadRequest } if netutil.IsBlockedLocalHostname(payloadURL.Hostname(), conf.Security.LocalNetworkAllowlist) { - return "PayloadURL", l.Tr("repo.settings.webhook.url_resolved_to_blocked_local_address"), false + return "PayloadURL", l.Tr("repo.settings.webhook.url_resolved_to_blocked_local_address"), http.StatusForbidden } - return "", "", true + return "", "", http.StatusOK } func validateAndCreateWebhook(c *context.Context, orCtx *orgRepoContext, w *database.Webhook) { c.Data["Webhook"] = w if c.HasError() { - c.Success(orCtx.TmplNew) + c.HTML(http.StatusBadRequest, orCtx.TmplNew) return } - field, msg, ok := validateWebhook(c.Locale, w) - if !ok { + field, msg, status := validateWebhook(c.Locale, w) + if status != http.StatusOK { c.FormErr(field) - c.RenderWithErr(msg, orCtx.TmplNew, nil) + c.RenderWithErr(msg, status, orCtx.TmplNew, nil) return } @@ -338,14 +338,14 @@ func validateAndUpdateWebhook(c *context.Context, orCtx *orgRepoContext, w *data c.Data["Webhook"] = w if c.HasError() { - c.Success(orCtx.TmplNew) + c.HTML(http.StatusBadRequest, orCtx.TmplNew) return } - field, msg, ok := validateWebhook(c.Locale, w) - if !ok { + field, msg, status := validateWebhook(c.Locale, w) + if status != http.StatusOK { c.FormErr(field) - c.RenderWithErr(msg, orCtx.TmplNew, nil) + c.RenderWithErr(msg, status, orCtx.TmplNew, nil) return } diff --git a/internal/route/repo/webhook_test.go b/internal/route/repo/webhook_test.go index 14daa03df..75cf37130 100644 --- a/internal/route/repo/webhook_test.go +++ b/internal/route/repo/webhook_test.go @@ -1,6 +1,7 @@ package repo import ( + "net/http" "testing" "github.com/stretchr/testify/assert" @@ -9,7 +10,7 @@ import ( "gogs.io/gogs/internal/mocks" ) -func Test_validateWebhook(t *testing.T) { +func TestValidateWebhook(t *testing.T) { l := &mocks.Locale{ MockLang: "en", MockTr: func(s string, _ ...any) string { @@ -18,33 +19,33 @@ func Test_validateWebhook(t *testing.T) { } tests := []struct { - name string - actor *database.User - webhook *database.Webhook - expField string - expMsg string - expOK bool + name string + actor *database.User + webhook *database.Webhook + wantField string + wantMsg string + wantStatus int }{ { - name: "admin bypass local address check", - webhook: &database.Webhook{URL: "https://www.google.com"}, - expOK: true, + name: "admin bypass local address check", + webhook: &database.Webhook{URL: "https://www.google.com"}, + wantStatus: http.StatusOK, }, { - name: "local address not allowed", - webhook: &database.Webhook{URL: "http://localhost:3306"}, - expField: "PayloadURL", - expMsg: "repo.settings.webhook.url_resolved_to_blocked_local_address", - expOK: false, + name: "local address not allowed", + webhook: &database.Webhook{URL: "http://localhost:3306"}, + wantField: "PayloadURL", + wantMsg: "repo.settings.webhook.url_resolved_to_blocked_local_address", + wantStatus: http.StatusForbidden, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - field, msg, ok := validateWebhook(l, test.webhook) - assert.Equal(t, test.expOK, ok) - assert.Equal(t, test.expMsg, msg) - assert.Equal(t, test.expField, field) + field, msg, status := validateWebhook(l, test.webhook) + assert.Equal(t, test.wantStatus, status) + assert.Equal(t, test.wantMsg, msg) + assert.Equal(t, test.wantField, field) }) } } diff --git a/internal/route/repo/wiki.go b/internal/route/repo/wiki.go index 7bf92de3a..42626d9c8 100644 --- a/internal/route/repo/wiki.go +++ b/internal/route/repo/wiki.go @@ -1,6 +1,7 @@ package repo import ( + "net/http" "strings" "time" @@ -199,14 +200,14 @@ func NewWikiPost(c *context.Context, f form.NewWiki) { c.Data["RequireSimpleMDE"] = true if c.HasError() { - c.Success(tmplRepoWikiNew) + c.HTML(http.StatusBadRequest, tmplRepoWikiNew) return } if err := c.Repo.Repository.AddWikiPage(c.User, f.Title, f.Content, f.Message); err != nil { if database.IsErrWikiAlreadyExist(err) { c.Data["Err_Title"] = true - c.RenderWithErr(c.Tr("repo.wiki.page_already_exists"), tmplRepoWikiNew, &f) + c.RenderWithErr(c.Tr("repo.wiki.page_already_exists"), http.StatusUnprocessableEntity, tmplRepoWikiNew, &f) } else { c.Error(err, "add wiki page") } @@ -240,7 +241,7 @@ func EditWikiPost(c *context.Context, f form.NewWiki) { c.Data["RequireSimpleMDE"] = true if c.HasError() { - c.Success(tmplRepoWikiNew) + c.HTML(http.StatusBadRequest, tmplRepoWikiNew) return } diff --git a/internal/route/user/auth.go b/internal/route/user/auth.go index e562305fc..75232486f 100644 --- a/internal/route/user/auth.go +++ b/internal/route/user/auth.go @@ -158,7 +158,7 @@ func LoginPost(c *context.Context, f form.SignIn) { c.Data["LoginSources"] = loginSources if c.HasError() { - c.Success(tmplUserAuthLogin) + c.HTML(http.StatusBadRequest, tmplUserAuthLogin) return } @@ -167,10 +167,10 @@ func LoginPost(c *context.Context, f form.SignIn) { switch { case auth.IsErrBadCredentials(err): c.FormErr("UserName", "Password") - c.RenderWithErr(c.Tr("form.username_password_incorrect"), tmplUserAuthLogin, &f) + c.RenderWithErr(c.Tr("form.username_password_incorrect"), http.StatusUnauthorized, tmplUserAuthLogin, &f) case database.IsErrLoginSourceMismatch(err): c.FormErr("LoginSource") - c.RenderWithErr(c.Tr("form.auth_source_mismatch"), tmplUserAuthLogin, &f) + c.RenderWithErr(c.Tr("form.auth_source_mismatch"), http.StatusUnprocessableEntity, tmplUserAuthLogin, &f) default: c.Error(err, "authenticate user") @@ -320,19 +320,19 @@ func SignUpPost(c *context.Context, cpt *captcha.Captcha, f form.Register) { } if c.HasError() { - c.Success(tmplUserAuthSignup) + c.HTML(http.StatusBadRequest, tmplUserAuthSignup) return } if conf.Auth.EnableRegistrationCaptcha && !cpt.VerifyReq(c.Req) { c.FormErr("Captcha") - c.RenderWithErr(c.Tr("form.captcha_incorrect"), tmplUserAuthSignup, &f) + c.RenderWithErr(c.Tr("form.captcha_incorrect"), http.StatusUnauthorized, tmplUserAuthSignup, &f) return } if f.Password != f.Retype { c.FormErr("Password") - c.RenderWithErr(c.Tr("form.password_not_match"), tmplUserAuthSignup, &f) + c.RenderWithErr(c.Tr("form.password_not_match"), http.StatusBadRequest, tmplUserAuthSignup, &f) return } @@ -349,13 +349,13 @@ func SignUpPost(c *context.Context, cpt *captcha.Captcha, f form.Register) { switch { case database.IsErrUserAlreadyExist(err): c.FormErr("UserName") - c.RenderWithErr(c.Tr("form.username_been_taken"), tmplUserAuthSignup, &f) + c.RenderWithErr(c.Tr("form.username_been_taken"), http.StatusUnprocessableEntity, tmplUserAuthSignup, &f) case database.IsErrEmailAlreadyUsed(err): c.FormErr("Email") - c.RenderWithErr(c.Tr("form.email_been_used"), tmplUserAuthSignup, &f) + c.RenderWithErr(c.Tr("form.email_been_used"), http.StatusUnprocessableEntity, tmplUserAuthSignup, &f) case database.IsErrNameNotAllowed(err): c.FormErr("UserName") - c.RenderWithErr(c.Tr("user.form.name_not_allowed", err.(database.ErrNameNotAllowed).Value()), tmplUserAuthSignup, &f) + c.RenderWithErr(c.Tr("user.form.name_not_allowed", err.(database.ErrNameNotAllowed).Value()), http.StatusBadRequest, tmplUserAuthSignup, &f) default: c.Error(err, "create user") } @@ -569,7 +569,7 @@ func ForgotPasswdPost(c *context.Context) { if !u.IsLocal() { c.FormErr("Email") - c.RenderWithErr(c.Tr("auth.non_local_account"), tmplUserAuthForgotPassword, nil) + c.RenderWithErr(c.Tr("auth.non_local_account"), http.StatusForbidden, tmplUserAuthForgotPassword, nil) return } @@ -618,7 +618,7 @@ func ResetPasswdPost(c *context.Context) { if len(password) < 6 { c.Data["IsResetForm"] = true c.Data["Err_Password"] = true - c.RenderWithErr(c.Tr("auth.password_too_short"), tmplUserAuthResetPassword, nil) + c.RenderWithErr(c.Tr("auth.password_too_short"), http.StatusBadRequest, tmplUserAuthResetPassword, nil) return } diff --git a/internal/route/user/setting.go b/internal/route/user/setting.go index 972757f98..14bde8d02 100644 --- a/internal/route/user/setting.go +++ b/internal/route/user/setting.go @@ -8,6 +8,7 @@ import ( "html/template" "image/png" "io" + "net/http" "github.com/cockroachdb/errors" "github.com/pquerna/otp" @@ -72,7 +73,7 @@ func SettingsPost(c *context.Context, f form.UpdateProfile) { c.Data["origin_name"] = c.User.Name if c.HasError() { - c.Success(tmplUserSettingsProfile) + c.HTML(http.StatusBadRequest, tmplUserSettingsProfile) return } @@ -83,18 +84,14 @@ func SettingsPost(c *context.Context, f form.UpdateProfile) { err := database.Handle.Users().ChangeUsername(c.Req.Context(), c.User.ID, f.Name) if err != nil { c.FormErr("Name") - var msg string switch { case database.IsErrUserAlreadyExist(errors.Cause(err)): - msg = c.Tr("form.username_been_taken") + c.RenderWithErr(c.Tr("form.username_been_taken"), http.StatusUnprocessableEntity, tmplUserSettingsProfile, &f) case database.IsErrNameNotAllowed(errors.Cause(err)): - msg = c.Tr("user.form.name_not_allowed", err.(database.ErrNameNotAllowed).Value()) + c.RenderWithErr(c.Tr("user.form.name_not_allowed", err.(database.ErrNameNotAllowed).Value()), http.StatusBadRequest, tmplUserSettingsProfile, &f) default: c.Error(err, "change user name") - return } - - c.RenderWithErr(msg, tmplUserSettingsProfile, &f) return } @@ -203,7 +200,7 @@ func SettingsPasswordPost(c *context.Context, f form.ChangePassword) { c.PageIs("SettingsPassword") if c.HasError() { - c.Success(tmplUserSettingsPassword) + c.HTML(http.StatusBadRequest, tmplUserSettingsPassword) return } @@ -267,14 +264,14 @@ func SettingsEmailPost(c *context.Context, f form.AddEmail) { c.Data["Emails"] = emails if c.HasError() { - c.Success(tmplUserSettingsEmail) + c.HTML(http.StatusBadRequest, tmplUserSettingsEmail) return } err = database.Handle.Users().AddEmail(c.Req.Context(), c.User.ID, f.Email, !conf.Auth.RequireEmailConfirmation) if err != nil { if database.IsErrEmailAlreadyUsed(err) { - c.RenderWithErr(c.Tr("form.email_been_used"), tmplUserSettingsEmail, &f) + c.RenderWithErr(c.Tr("form.email_been_used"), http.StatusUnprocessableEntity, tmplUserSettingsEmail, &f) } else { c.Errorf(err, "add email address") } @@ -344,7 +341,7 @@ func SettingsSSHKeysPost(c *context.Context, f form.AddSSHKey) { c.Data["Keys"] = keys if c.HasError() { - c.Success(tmplUserSettingsSSHKeys) + c.HTML(http.StatusBadRequest, tmplUserSettingsSSHKeys) return } @@ -364,10 +361,10 @@ func SettingsSSHKeysPost(c *context.Context, f form.AddSSHKey) { switch { case database.IsErrKeyAlreadyExist(err): c.FormErr("Content") - c.RenderWithErr(c.Tr("settings.ssh_key_been_used"), tmplUserSettingsSSHKeys, &f) + c.RenderWithErr(c.Tr("settings.ssh_key_been_used"), http.StatusUnprocessableEntity, tmplUserSettingsSSHKeys, &f) case database.IsErrKeyNameAlreadyUsed(err): c.FormErr("Title") - c.RenderWithErr(c.Tr("settings.ssh_key_name_used"), tmplUserSettingsSSHKeys, &f) + c.RenderWithErr(c.Tr("settings.ssh_key_name_used"), http.StatusUnprocessableEntity, tmplUserSettingsSSHKeys, &f) default: c.Errorf(err, "add public key") } @@ -619,7 +616,7 @@ func (h *SettingsHandler) ApplicationsPost() macaron.Handler { } c.Data["Tokens"] = tokens - c.Success(tmplUserSettingsApplications) + c.HTML(http.StatusBadRequest, tmplUserSettingsApplications) return } @@ -661,7 +658,7 @@ func SettingsDelete(c *context.Context) { if c.Req.Method == "POST" { if _, err := database.Handle.Users().Authenticate(c.Req.Context(), c.User.Name, c.Query("password"), c.User.LoginSource); err != nil { if auth.IsErrBadCredentials(err) { - c.RenderWithErr(c.Tr("form.enterred_invalid_password"), tmplUserSettingsDelete, nil) + c.RenderWithErr(c.Tr("form.enterred_invalid_password"), http.StatusUnauthorized, tmplUserSettingsDelete, nil) } else { c.Errorf(err, "authenticate user") }