forked from hinterland/hearth
feat: vendor gitea 1.16.2
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package setting
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/models/actions"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
unit_model "code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
shared_actions "code.gitea.io/gitea/routers/web/shared/actions"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
)
|
||||
|
||||
const tplRepoActionsGeneralSettings templates.TplName = "repo/settings/actions"
|
||||
|
||||
func ActionsGeneralSettings(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("actions.general")
|
||||
ctx.Data["PageType"] = "general"
|
||||
ctx.Data["PageIsActionsSettingsGeneral"] = true
|
||||
|
||||
actionsUnit, err := ctx.Repo.Repository.GetUnit(ctx, unit_model.TypeActions)
|
||||
if err != nil && !repo_model.IsErrUnitTypeNotExist(err) {
|
||||
ctx.ServerError("GetUnit", err)
|
||||
return
|
||||
}
|
||||
if actionsUnit == nil { // no actions unit
|
||||
ctx.HTML(http.StatusOK, tplRepoActionsGeneralSettings)
|
||||
return
|
||||
}
|
||||
|
||||
actionsCfg := actionsUnit.ActionsConfig()
|
||||
|
||||
// Token permission settings
|
||||
ctx.Data["TokenPermissionModePermissive"] = repo_model.ActionsTokenPermissionModePermissive
|
||||
ctx.Data["TokenPermissionModeRestricted"] = repo_model.ActionsTokenPermissionModeRestricted
|
||||
|
||||
// Follow owner config (only for repos in orgs)
|
||||
ctx.Data["OverrideOwnerConfig"] = actionsCfg.OverrideOwnerConfig
|
||||
if actionsCfg.OverrideOwnerConfig {
|
||||
ctx.Data["MaxTokenPermissions"] = actionsCfg.GetMaxTokenPermissions()
|
||||
ctx.Data["TokenPermissionMode"] = actionsCfg.TokenPermissionMode
|
||||
ctx.Data["EnableMaxTokenPermissions"] = actionsCfg.MaxTokenPermissions != nil
|
||||
} else {
|
||||
ownerActionsConfig, err := actions.GetOwnerActionsConfig(ctx, ctx.Repo.Repository.OwnerID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetOwnerActionsConfig", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["MaxTokenPermissions"] = ownerActionsConfig.GetMaxTokenPermissions()
|
||||
ctx.Data["TokenPermissionMode"] = ownerActionsConfig.TokenPermissionMode
|
||||
ctx.Data["EnableMaxTokenPermissions"] = ownerActionsConfig.MaxTokenPermissions != nil
|
||||
}
|
||||
|
||||
if ctx.Repo.Repository.IsPrivate {
|
||||
collaborativeOwnerIDs := actionsCfg.CollaborativeOwnerIDs
|
||||
collaborativeOwners, err := user_model.GetUsersByIDs(ctx, collaborativeOwnerIDs)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetUsersByIDs", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["CollaborativeOwners"] = collaborativeOwners
|
||||
}
|
||||
|
||||
ctx.HTML(http.StatusOK, tplRepoActionsGeneralSettings)
|
||||
}
|
||||
|
||||
func ActionsUnitPost(ctx *context.Context) {
|
||||
redirectURL := ctx.Repo.RepoLink + "/settings/actions/general"
|
||||
enableActionsUnit := ctx.FormBool("enable_actions")
|
||||
repo := ctx.Repo.Repository
|
||||
|
||||
var err error
|
||||
if enableActionsUnit && !unit_model.TypeActions.UnitGlobalDisabled() {
|
||||
err = repo_service.UpdateRepositoryUnits(ctx, repo, []repo_model.RepoUnit{newRepoUnit(repo, unit_model.TypeActions, nil)}, nil)
|
||||
} else if !unit_model.TypeActions.UnitGlobalDisabled() {
|
||||
err = repo_service.UpdateRepositoryUnits(ctx, repo, nil, []unit_model.Type{unit_model.TypeActions})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
ctx.ServerError("UpdateRepositoryUnits", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success"))
|
||||
ctx.Redirect(redirectURL)
|
||||
}
|
||||
|
||||
func AddCollaborativeOwner(ctx *context.Context) {
|
||||
collUser, err := user_model.GetUserByName(ctx, ctx.FormString("collaborative_owner"))
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.JSONError(ctx.Tr("form.user_not_exist"))
|
||||
} else {
|
||||
ctx.ServerError("GetUserByName", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
actionsUnit, err := ctx.Repo.Repository.GetUnit(ctx, unit_model.TypeActions)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetUnit", err)
|
||||
return
|
||||
}
|
||||
actionsCfg := actionsUnit.ActionsConfig()
|
||||
actionsCfg.AddCollaborativeOwner(collUser.ID)
|
||||
if err := repo_model.UpdateRepoUnitConfig(ctx, actionsUnit); err != nil {
|
||||
ctx.ServerError("UpdateRepoUnitConfig", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSONOK()
|
||||
}
|
||||
|
||||
func DeleteCollaborativeOwner(ctx *context.Context) {
|
||||
ownerID := ctx.FormInt64("id")
|
||||
|
||||
actionsUnit, err := ctx.Repo.Repository.GetUnit(ctx, unit_model.TypeActions)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetUnit", err)
|
||||
return
|
||||
}
|
||||
actionsCfg := actionsUnit.ActionsConfig()
|
||||
if !actionsCfg.IsCollaborativeOwner(ownerID) {
|
||||
ctx.Flash.Error(ctx.Tr("actions.general.collaborative_owner_not_exist"))
|
||||
ctx.JSONErrorNotFound()
|
||||
return
|
||||
}
|
||||
actionsCfg.RemoveCollaborativeOwner(ownerID)
|
||||
if err := repo_model.UpdateRepoUnitConfig(ctx, actionsUnit); err != nil {
|
||||
ctx.ServerError("UpdateRepoUnitConfig", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSONOK()
|
||||
}
|
||||
|
||||
// UpdateTokenPermissions updates the token permission settings for the repository
|
||||
func UpdateTokenPermissions(ctx *context.Context) {
|
||||
redirectURL := ctx.Repo.RepoLink + "/settings/actions/general"
|
||||
|
||||
actionsUnit, err := ctx.Repo.Repository.GetUnit(ctx, unit_model.TypeActions)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetUnit", err)
|
||||
return
|
||||
}
|
||||
|
||||
actionsCfg := actionsUnit.ActionsConfig()
|
||||
|
||||
// Update Override Owner Config (for repos in orgs)
|
||||
// If checked, it means we WANT to override (opt-out of following)
|
||||
actionsCfg.OverrideOwnerConfig = ctx.FormBool("override_owner_config")
|
||||
|
||||
// Update permission mode (only if overriding owner config)
|
||||
shouldUpdate := actionsCfg.OverrideOwnerConfig
|
||||
|
||||
if shouldUpdate {
|
||||
permissionMode, permissionModeValid := util.EnumValue(repo_model.ActionsTokenPermissionMode(ctx.FormString("token_permission_mode")))
|
||||
if !permissionModeValid {
|
||||
ctx.Flash.Error("Invalid token permission mode")
|
||||
ctx.Redirect(redirectURL)
|
||||
return
|
||||
}
|
||||
actionsCfg.TokenPermissionMode = permissionMode
|
||||
}
|
||||
|
||||
// Update Maximum Permissions (radio buttons: none/read/write)
|
||||
enableMaxPermissions := ctx.FormBool("enable_max_permissions")
|
||||
if shouldUpdate {
|
||||
if enableMaxPermissions {
|
||||
actionsCfg.MaxTokenPermissions = shared_actions.ParseMaxTokenPermissions(ctx)
|
||||
} else {
|
||||
// If not enabled, ensure any sent permissions are ignored and set to nil
|
||||
actionsCfg.MaxTokenPermissions = nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := repo_model.UpdateRepoUnitConfig(ctx, actionsUnit); err != nil {
|
||||
ctx.ServerError("UpdateRepoUnitConfig", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success"))
|
||||
ctx.Redirect(redirectURL)
|
||||
}
|
||||
@@ -208,7 +208,7 @@ func DeleteTeam(ctx *context.Context) {
|
||||
}
|
||||
|
||||
if err = repo_service.RemoveRepositoryFromTeam(ctx, team, ctx.Repo.Repository.ID); err != nil {
|
||||
ctx.ServerError("team.RemoveRepositorys", err)
|
||||
ctx.ServerError("team.RemoveRepositories", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -76,16 +76,16 @@ func DeployKeysPost(ctx *context.Context) {
|
||||
switch {
|
||||
case asymkey_model.IsErrDeployKeyAlreadyExist(err):
|
||||
ctx.Data["Err_Content"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.settings.key_been_used"), tplDeployKeys, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.settings.key_been_used"), tplDeployKeys, &form)
|
||||
case asymkey_model.IsErrKeyAlreadyExist(err):
|
||||
ctx.Data["Err_Content"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("settings.ssh_key_been_used"), tplDeployKeys, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("settings.ssh_key_been_used"), tplDeployKeys, &form)
|
||||
case asymkey_model.IsErrKeyNameAlreadyUsed(err):
|
||||
ctx.Data["Err_Title"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.settings.key_name_used"), tplDeployKeys, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.settings.key_name_used"), tplDeployKeys, &form)
|
||||
case asymkey_model.IsErrDeployKeyNameAlreadyUsed(err):
|
||||
ctx.Data["Err_Title"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.settings.key_name_used"), tplDeployKeys, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.settings.key_name_used"), tplDeployKeys, &form)
|
||||
default:
|
||||
ctx.ServerError("AddDeployKey", err)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/routers/web/repo"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
)
|
||||
|
||||
@@ -41,6 +42,7 @@ func GitHooksEdit(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
ctx.Data["Hook"] = hook
|
||||
ctx.Data["CodeEditorConfig"] = repo.CodeEditorConfig{Filename: name + ".sh", IndentStyle: "tab", TabWidth: 4}
|
||||
ctx.HTML(http.StatusOK, tplGithookEdit)
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/attribute"
|
||||
"code.gitea.io/gitea/modules/git/pipeline"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/lfs"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
repo_module "code.gitea.io/gitea/modules/repository"
|
||||
@@ -53,7 +54,7 @@ func LFSFiles(ctx *context.Context) {
|
||||
}
|
||||
ctx.Data["Total"] = total
|
||||
|
||||
pager := context.NewPagination(int(total), setting.UI.ExplorePagingNum, page, 5)
|
||||
pager := context.NewPagination(total, setting.UI.ExplorePagingNum, page, 5)
|
||||
ctx.Data["Title"] = ctx.Tr("repo.settings.lfs")
|
||||
ctx.Data["PageIsSettingsLFS"] = true
|
||||
lfsMetaObjects, err := git_model.GetLFSMetaObjects(ctx, ctx.Repo.Repository.ID, pager.Paginater.Current(), setting.UI.ExplorePagingNum)
|
||||
@@ -82,7 +83,7 @@ func LFSLocks(ctx *context.Context) {
|
||||
}
|
||||
ctx.Data["Total"] = total
|
||||
|
||||
pager := context.NewPagination(int(total), setting.UI.ExplorePagingNum, page, 5)
|
||||
pager := context.NewPagination(total, setting.UI.ExplorePagingNum, page, 5)
|
||||
ctx.Data["Title"] = ctx.Tr("repo.settings.lfs_locks")
|
||||
ctx.Data["PageIsSettingsLFS"] = true
|
||||
lfsLocks, err := git_model.GetLFSLockByRepoID(ctx, ctx.Repo.Repository.ID, pager.Paginater.Current(), setting.UI.ExplorePagingNum)
|
||||
@@ -112,7 +113,7 @@ func LFSLocks(ctx *context.Context) {
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
if err := git.Clone(ctx, ctx.Repo.Repository.RepoPath(), tmpBasePath, git.CloneRepoOptions{
|
||||
if err := gitrepo.CloneRepoToLocal(ctx, ctx.Repo.Repository, tmpBasePath, git.CloneRepoOptions{
|
||||
Bare: true,
|
||||
Shared: true,
|
||||
}); err != nil {
|
||||
@@ -300,13 +301,13 @@ func LFSFileGet(ctx *context.Context) {
|
||||
if index != len(lines)-1 {
|
||||
line += "\n"
|
||||
}
|
||||
output.WriteString(fmt.Sprintf(`<li class="L%d" rel="L%d">%s</li>`, index+1, index+1, line))
|
||||
fmt.Fprintf(&output, `<li class="L%d" rel="L%d">%s</li>`, index+1, index+1, line)
|
||||
}
|
||||
ctx.Data["FileContent"] = gotemplate.HTML(output.String())
|
||||
|
||||
output.Reset()
|
||||
for i := 0; i < len(lines); i++ {
|
||||
output.WriteString(fmt.Sprintf(`<span id="L%d">%d</span>`, i+1, i+1))
|
||||
fmt.Fprintf(&output, `<span id="L%d">%d</span>`, i+1, i+1)
|
||||
}
|
||||
ctx.Data["LineNums"] = gotemplate.HTML(output.String())
|
||||
|
||||
@@ -406,7 +407,9 @@ func LFSPointerFiles(ctx *context.Context) {
|
||||
err = func() error {
|
||||
pointerChan := make(chan lfs.PointerBlob)
|
||||
errChan := make(chan error, 1)
|
||||
go lfs.SearchPointerBlobs(ctx, ctx.Repo.GitRepo, pointerChan, errChan)
|
||||
go func() {
|
||||
errChan <- lfs.SearchPointerBlobs(ctx, ctx.Repo.GitRepo, pointerChan)
|
||||
}()
|
||||
|
||||
numPointers := 0
|
||||
var numAssociated, numNoExist, numAssociatable int
|
||||
@@ -482,11 +485,6 @@ func LFSPointerFiles(ctx *context.Context) {
|
||||
results = append(results, result)
|
||||
}
|
||||
|
||||
err, has := <-errChan
|
||||
if has {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx.Data["Pointers"] = results
|
||||
ctx.Data["NumPointers"] = numPointers
|
||||
ctx.Data["NumAssociated"] = numAssociated
|
||||
@@ -494,7 +492,8 @@ func LFSPointerFiles(ctx *context.Context) {
|
||||
ctx.Data["NumNoExist"] = numNoExist
|
||||
ctx.Data["NumNotAssociated"] = numPointers - numAssociated
|
||||
|
||||
return nil
|
||||
err := <-errChan
|
||||
return err
|
||||
}()
|
||||
if err != nil {
|
||||
ctx.ServerError("LFSPointerFiles", err)
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/glob"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
"code.gitea.io/gitea/routers/web/repo"
|
||||
@@ -312,10 +313,14 @@ func DeleteProtectedBranchRulePost(ctx *context.Context) {
|
||||
}
|
||||
|
||||
func UpdateBranchProtectionPriories(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.ProtectBranchPriorityForm)
|
||||
repo := ctx.Repo.Repository
|
||||
|
||||
if err := git_model.UpdateProtectBranchPriorities(ctx, repo, form.IDs); err != nil {
|
||||
var form struct {
|
||||
IDs []int64 `json:"ids"`
|
||||
}
|
||||
if err := json.NewDecoder(ctx.Req.Body).Decode(&form); err != nil {
|
||||
ctx.JSONError("invalid argument")
|
||||
return
|
||||
}
|
||||
if err := git_model.UpdateProtectBranchPriorities(ctx, ctx.Repo.Repository, form.IDs); err != nil {
|
||||
ctx.ServerError("UpdateProtectBranchPriorities", err)
|
||||
return
|
||||
}
|
||||
@@ -336,7 +341,7 @@ func RenameBranchPost(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
msg, err := repository.RenameBranch(ctx, ctx.Repo.Repository, ctx.Doer, ctx.Repo.GitRepo, form.From, form.To)
|
||||
msg, err := repository.RenameBranch(ctx, ctx.Repo.Repository, ctx.Doer, form.From, form.To)
|
||||
if err != nil {
|
||||
switch {
|
||||
case repo_model.IsErrUserDoesNotHaveAccessToRepo(err):
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
shared "code.gitea.io/gitea/routers/web/shared/secrets"
|
||||
@@ -46,7 +45,7 @@ func getSecretsCtx(ctx *context.Context) (*secretsCtx, error) {
|
||||
if ctx.Data["PageIsOrgSettings"] == true {
|
||||
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||
ctx.ServerError("RenderUserOrgHeader", err)
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // error is already handled by ctx.ServerError
|
||||
}
|
||||
return &secretsCtx{
|
||||
OwnerID: ctx.ContextUser.ID,
|
||||
@@ -74,7 +73,6 @@ func Secrets(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("actions.actions")
|
||||
ctx.Data["PageType"] = "secrets"
|
||||
ctx.Data["PageIsSharedSettingsSecrets"] = true
|
||||
ctx.Data["UserDisabledFeatures"] = user_model.DisabledFeaturesWithLoginType(ctx.Doer)
|
||||
|
||||
sCtx, err := getSecretsCtx(ctx)
|
||||
if err != nil {
|
||||
|
||||
@@ -28,8 +28,8 @@ import (
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/validation"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
repo_router "code.gitea.io/gitea/routers/web/repo"
|
||||
actions_service "code.gitea.io/gitea/services/actions"
|
||||
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
"code.gitea.io/gitea/services/forms"
|
||||
"code.gitea.io/gitea/services/migrations"
|
||||
@@ -62,7 +62,7 @@ func SettingsCtxData(ctx *context.Context) {
|
||||
ctx.Data["MinimumMirrorInterval"] = setting.Mirror.MinInterval
|
||||
ctx.Data["CanConvertFork"] = ctx.Repo.Repository.IsFork && ctx.Doer.CanCreateRepoIn(ctx.Repo.Repository.Owner)
|
||||
|
||||
signing, _ := asymkey_service.SigningKey(ctx, ctx.Repo.Repository.RepoPath())
|
||||
signing, _ := gitrepo.GetSigningKey(ctx)
|
||||
ctx.Data["SigningKeyAvailable"] = signing != nil
|
||||
ctx.Data["SigningSettings"] = setting.Repository.Signing
|
||||
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
|
||||
@@ -89,6 +89,11 @@ func SettingsCtxData(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
ctx.Data["PushMirrors"] = pushMirrors
|
||||
|
||||
repo_router.PrepareBranchList(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Settings show a repository's settings page
|
||||
@@ -105,7 +110,7 @@ func SettingsPost(ctx *context.Context) {
|
||||
ctx.Data["DefaultMirrorInterval"] = setting.Mirror.DefaultInterval
|
||||
ctx.Data["MinimumMirrorInterval"] = setting.Mirror.MinInterval
|
||||
|
||||
signing, _ := asymkey_service.SigningKey(ctx, ctx.Repo.Repository.RepoPath())
|
||||
signing, _ := gitrepo.GetSigningKey(ctx)
|
||||
ctx.Data["SigningKeyAvailable"] = signing != nil
|
||||
ctx.Data["SigningSettings"] = setting.Repository.Signing
|
||||
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
|
||||
@@ -176,23 +181,23 @@ func handleSettingsPostUpdate(ctx *context.Context) {
|
||||
ctx.Data["Err_RepoName"] = true
|
||||
switch {
|
||||
case repo_model.IsErrRepoAlreadyExist(err):
|
||||
ctx.RenderWithErr(ctx.Tr("form.repo_name_been_taken"), tplSettingsOptions, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.repo_name_been_taken"), tplSettingsOptions, &form)
|
||||
case db.IsErrNameReserved(err):
|
||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(db.ErrNameReserved).Name), tplSettingsOptions, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.form.name_reserved", err.(db.ErrNameReserved).Name), tplSettingsOptions, &form)
|
||||
case repo_model.IsErrRepoFilesAlreadyExist(err):
|
||||
ctx.Data["Err_RepoName"] = true
|
||||
switch {
|
||||
case ctx.IsUserSiteAdmin() || (setting.Repository.AllowAdoptionOfUnadoptedRepositories && setting.Repository.AllowDeleteOfUnadoptedRepositories):
|
||||
ctx.RenderWithErr(ctx.Tr("form.repository_files_already_exist.adopt_or_delete"), tplSettingsOptions, form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.repository_files_already_exist.adopt_or_delete"), tplSettingsOptions, form)
|
||||
case setting.Repository.AllowAdoptionOfUnadoptedRepositories:
|
||||
ctx.RenderWithErr(ctx.Tr("form.repository_files_already_exist.adopt"), tplSettingsOptions, form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.repository_files_already_exist.adopt"), tplSettingsOptions, form)
|
||||
case setting.Repository.AllowDeleteOfUnadoptedRepositories:
|
||||
ctx.RenderWithErr(ctx.Tr("form.repository_files_already_exist.delete"), tplSettingsOptions, form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.repository_files_already_exist.delete"), tplSettingsOptions, form)
|
||||
default:
|
||||
ctx.RenderWithErr(ctx.Tr("form.repository_files_already_exist"), tplSettingsOptions, form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.repository_files_already_exist"), tplSettingsOptions, form)
|
||||
}
|
||||
case db.IsErrNamePatternNotAllowed(err):
|
||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tplSettingsOptions, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tplSettingsOptions, &form)
|
||||
default:
|
||||
ctx.ServerError("ChangeRepositoryName", err)
|
||||
}
|
||||
@@ -208,11 +213,6 @@ func handleSettingsPostUpdate(ctx *context.Context) {
|
||||
repo.Website = form.Website
|
||||
repo.IsTemplate = form.Template
|
||||
|
||||
// Visibility of forked repository is forced sync with base repository.
|
||||
if repo.IsFork {
|
||||
form.Private = repo.BaseRepo.IsPrivate || repo.BaseRepo.Owner.Visibility == structs.VisibleTypePrivate
|
||||
}
|
||||
|
||||
if err := repo_service.UpdateRepository(ctx, repo, false); err != nil {
|
||||
ctx.ServerError("UpdateRepository", err)
|
||||
return
|
||||
@@ -247,7 +247,7 @@ func handleSettingsPostMirror(ctx *context.Context) {
|
||||
interval, err := time.ParseDuration(form.Interval)
|
||||
if err != nil || (interval != 0 && interval < setting.Mirror.MinInterval) {
|
||||
ctx.Data["Err_Interval"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.mirror_interval_invalid"), tplSettingsOptions, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.mirror_interval_invalid"), tplSettingsOptions, &form)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -298,7 +298,7 @@ func handleSettingsPostMirror(ctx *context.Context) {
|
||||
ep := lfs.DetermineEndpoint("", form.LFSEndpoint)
|
||||
if ep == nil {
|
||||
ctx.Data["Err_LFSEndpoint"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.migrate.invalid_lfs_endpoint"), tplSettingsOptions, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.migrate.invalid_lfs_endpoint"), tplSettingsOptions, &form)
|
||||
return
|
||||
}
|
||||
err = migrations.IsMigrateURLAllowed(ep.String(), ctx.Doer)
|
||||
@@ -369,7 +369,7 @@ func handleSettingsPostPushMirrorUpdate(ctx *context.Context) {
|
||||
|
||||
interval, err := time.ParseDuration(form.PushMirrorInterval)
|
||||
if err != nil || (interval != 0 && interval < setting.Mirror.MinInterval) {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.mirror_interval_invalid"), tplSettingsOptions, &forms.RepoSettingForm{})
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.mirror_interval_invalid"), tplSettingsOptions, &forms.RepoSettingForm{})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -445,7 +445,7 @@ func handleSettingsPostPushMirrorAdd(ctx *context.Context) {
|
||||
interval, err := time.ParseDuration(form.PushMirrorInterval)
|
||||
if err != nil || (interval != 0 && interval < setting.Mirror.MinInterval) {
|
||||
ctx.Data["Err_PushMirrorInterval"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.mirror_interval_invalid"), tplSettingsOptions, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.mirror_interval_invalid"), tplSettingsOptions, &form)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -614,12 +614,6 @@ func handleSettingsPostAdvanced(ctx *context.Context) {
|
||||
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypePackages)
|
||||
}
|
||||
|
||||
if form.EnableActions && !unit_model.TypeActions.UnitGlobalDisabled() {
|
||||
units = append(units, newRepoUnit(repo, unit_model.TypeActions, nil))
|
||||
} else if !unit_model.TypeActions.UnitGlobalDisabled() {
|
||||
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeActions)
|
||||
}
|
||||
|
||||
if form.EnablePulls && !unit_model.TypePullRequests.UnitGlobalDisabled() {
|
||||
units = append(units, newRepoUnit(repo, unit_model.TypePullRequests, &repo_model.PullRequestsConfig{
|
||||
IgnoreWhitespaceConflicts: form.PullsIgnoreWhitespace,
|
||||
@@ -634,6 +628,7 @@ func handleSettingsPostAdvanced(ctx *context.Context) {
|
||||
DefaultDeleteBranchAfterMerge: form.DefaultDeleteBranchAfterMerge,
|
||||
DefaultMergeStyle: repo_model.MergeStyle(form.PullsDefaultMergeStyle),
|
||||
DefaultAllowMaintainerEdit: form.DefaultAllowMaintainerEdit,
|
||||
DefaultTargetBranch: strings.TrimSpace(form.DefaultTargetBranch),
|
||||
}))
|
||||
} else if !unit_model.TypePullRequests.UnitGlobalDisabled() {
|
||||
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypePullRequests)
|
||||
@@ -738,7 +733,7 @@ func handleSettingsPostConvert(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
if repo.Name != form.RepoName {
|
||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -772,7 +767,7 @@ func handleSettingsPostConvertFork(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
if repo.Name != form.RepoName {
|
||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -808,14 +803,14 @@ func handleSettingsPostTransfer(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
if repo.Name != form.RepoName {
|
||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil)
|
||||
return
|
||||
}
|
||||
|
||||
newOwner, err := user_model.GetUserByName(ctx, ctx.FormString("new_owner_name"))
|
||||
if err != nil {
|
||||
if user_model.IsErrUserNotExist(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_owner_name"), tplSettingsOptions, nil)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.enterred_invalid_owner_name"), tplSettingsOptions, nil)
|
||||
return
|
||||
}
|
||||
ctx.ServerError("IsUserExist", err)
|
||||
@@ -825,7 +820,7 @@ func handleSettingsPostTransfer(ctx *context.Context) {
|
||||
if newOwner.Type == user_model.UserTypeOrganization {
|
||||
if !ctx.Doer.IsAdmin && newOwner.Visibility == structs.VisibleTypePrivate && !organization.OrgFromUser(newOwner).HasMemberWithUserID(ctx, ctx.Doer.ID) {
|
||||
// The user shouldn't know about this organization
|
||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_owner_name"), tplSettingsOptions, nil)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.enterred_invalid_owner_name"), tplSettingsOptions, nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -839,14 +834,14 @@ func handleSettingsPostTransfer(ctx *context.Context) {
|
||||
oldFullname := repo.FullName()
|
||||
if err := repo_service.StartRepositoryTransfer(ctx, ctx.Doer, newOwner, repo, nil); err != nil {
|
||||
if repo_model.IsErrRepoAlreadyExist(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplSettingsOptions, nil)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplSettingsOptions, nil)
|
||||
} else if repo_model.IsErrRepoTransferInProgress(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.settings.transfer_in_progress"), tplSettingsOptions, nil)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.settings.transfer_in_progress"), tplSettingsOptions, nil)
|
||||
} else if repo_service.IsRepositoryLimitReached(err) {
|
||||
limit := err.(repo_service.LimitReachedError).Limit
|
||||
ctx.RenderWithErr(ctx.TrN(limit, "repo.form.reach_limit_of_creation_1", "repo.form.reach_limit_of_creation_n", limit), tplSettingsOptions, nil)
|
||||
ctx.RenderWithErrDeprecated(ctx.TrN(limit, "repo.form.reach_limit_of_creation_1", "repo.form.reach_limit_of_creation_n", limit), tplSettingsOptions, nil)
|
||||
} else if errors.Is(err, user_model.ErrBlockedUser) {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.settings.transfer.blocked_user"), tplSettingsOptions, nil)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.settings.transfer.blocked_user"), tplSettingsOptions, nil)
|
||||
} else {
|
||||
ctx.ServerError("TransferOwnership", err)
|
||||
}
|
||||
@@ -900,7 +895,7 @@ func handleSettingsPostDelete(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
if repo.Name != form.RepoName {
|
||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -927,7 +922,7 @@ func handleSettingsPostDeleteWiki(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
if repo.Name != form.RepoName {
|
||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1004,39 +999,33 @@ func handleSettingsPostUnarchive(ctx *context.Context) {
|
||||
}
|
||||
|
||||
func handleSettingsPostVisibility(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.RepoSettingForm)
|
||||
repo := ctx.Repo.Repository
|
||||
if repo.IsFork {
|
||||
ctx.Flash.Error(ctx.Tr("repo.settings.visibility.fork_error"))
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/settings")
|
||||
ctx.JSONError(ctx.Tr("repo.settings.visibility.fork_error"))
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
private := ctx.FormOptionalBool("private").ValueOrDefault(true) // default to true for privacy & safety
|
||||
|
||||
// when ForcePrivate enabled, you could change public repo to private, but only admin users can change private to public
|
||||
if setting.Repository.ForcePrivate && repo.IsPrivate && !ctx.Doer.IsAdmin {
|
||||
ctx.RenderWithErr(ctx.Tr("form.repository_force_private"), tplSettingsOptions, form)
|
||||
if !private && setting.Repository.ForcePrivate && !ctx.Doer.IsAdmin {
|
||||
ctx.JSONError(ctx.Tr("form.repository_force_private"))
|
||||
return
|
||||
}
|
||||
if private && repo.FullName() != ctx.FormString("confirm_repo_name") {
|
||||
ctx.JSONError(ctx.Tr("form.enterred_invalid_repo_name"))
|
||||
return
|
||||
}
|
||||
|
||||
if repo.IsPrivate {
|
||||
err = repo_service.MakeRepoPublic(ctx, repo)
|
||||
} else {
|
||||
err = repo_service.MakeRepoPrivate(ctx, repo)
|
||||
}
|
||||
|
||||
err := repo_service.MakeRepoPrivate(ctx, repo, private)
|
||||
if err != nil {
|
||||
log.Error("Tried to change the visibility of the repo: %s", err)
|
||||
ctx.Flash.Error(ctx.Tr("repo.settings.visibility.error"))
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/settings")
|
||||
ctx.JSONError(ctx.Tr("repo.settings.visibility.error"))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("repo.settings.visibility.success"))
|
||||
|
||||
log.Trace("Repository visibility changed: %s/%s", ctx.Repo.Owner.Name, repo.Name)
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/settings")
|
||||
ctx.JSONRedirect(ctx.Repo.RepoLink + "/settings")
|
||||
}
|
||||
|
||||
func handleSettingRemoteAddrError(ctx *context.Context, err error, form *forms.RepoSettingForm) {
|
||||
@@ -1044,21 +1033,21 @@ func handleSettingRemoteAddrError(ctx *context.Context, err error, form *forms.R
|
||||
addrErr := err.(*git.ErrInvalidCloneAddr)
|
||||
switch {
|
||||
case addrErr.IsProtocolInvalid:
|
||||
ctx.RenderWithErr(ctx.Tr("repo.mirror_address_protocol_invalid"), tplSettingsOptions, form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.mirror_address_protocol_invalid"), tplSettingsOptions, form)
|
||||
case addrErr.IsURLError:
|
||||
ctx.RenderWithErr(ctx.Tr("form.url_error", addrErr.Host), tplSettingsOptions, form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.url_error", addrErr.Host), tplSettingsOptions, form)
|
||||
case addrErr.IsPermissionDenied:
|
||||
if addrErr.LocalPath {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.migrate.permission_denied"), tplSettingsOptions, form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.migrate.permission_denied"), tplSettingsOptions, form)
|
||||
} else {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.migrate.permission_denied_blocked"), tplSettingsOptions, form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.migrate.permission_denied_blocked"), tplSettingsOptions, form)
|
||||
}
|
||||
case addrErr.IsInvalidPath:
|
||||
ctx.RenderWithErr(ctx.Tr("repo.migrate.invalid_local_path"), tplSettingsOptions, form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.migrate.invalid_local_path"), tplSettingsOptions, form)
|
||||
default:
|
||||
ctx.ServerError("Unknown error", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
ctx.RenderWithErr(ctx.Tr("repo.mirror_address_url_invalid"), tplSettingsOptions, form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.mirror_address_url_invalid"), tplSettingsOptions, form)
|
||||
}
|
||||
|
||||
@@ -234,6 +234,7 @@ func createWebhook(ctx *context.Context, params webhookParams) {
|
||||
w := &webhook.Webhook{
|
||||
RepoID: orCtx.RepoID,
|
||||
URL: params.URL,
|
||||
Name: strings.TrimSpace(params.WebhookForm.Name),
|
||||
HTTPMethod: params.HTTPMethod,
|
||||
ContentType: params.ContentType,
|
||||
Secret: params.WebhookForm.Secret,
|
||||
@@ -288,6 +289,7 @@ func editWebhook(ctx *context.Context, params webhookParams) {
|
||||
}
|
||||
|
||||
w.URL = params.URL
|
||||
w.Name = strings.TrimSpace(params.WebhookForm.Name)
|
||||
w.ContentType = params.ContentType
|
||||
w.Secret = params.WebhookForm.Secret
|
||||
w.HookEvent = ParseHookEvent(params.WebhookForm)
|
||||
@@ -448,12 +450,21 @@ func MatrixHooksEditPost(ctx *context.Context) {
|
||||
editWebhook(ctx, matrixHookParams(ctx))
|
||||
}
|
||||
|
||||
func matrixRoomIDEncode(roomID string) string {
|
||||
// See https://spec.matrix.org/latest/appendices/#room-ids
|
||||
// Some (unrelated) demo links: https://spec.matrix.org/latest/appendices/#matrixto-navigation
|
||||
// API spec: https://spec.matrix.org/v1.18/client-server-api/#sending-events-to-a-room
|
||||
// Some of their examples show links like: "PUT /rooms/!roomid:domain/state/m.example.event"
|
||||
return strings.NewReplacer("%21", "!", "%3A", ":").Replace(url.PathEscape(roomID))
|
||||
}
|
||||
|
||||
func matrixHookParams(ctx *context.Context) webhookParams {
|
||||
form := web.GetForm(ctx).(*forms.NewMatrixHookForm)
|
||||
|
||||
// TODO: need to migrate to the latest (v3) API: https://spec.matrix.org/v1.18/client-server-api/
|
||||
return webhookParams{
|
||||
Type: webhook_module.MATRIX,
|
||||
URL: fmt.Sprintf("%s/_matrix/client/r0/rooms/%s/send/m.room.message", form.HomeserverURL, url.PathEscape(form.RoomID)),
|
||||
URL: fmt.Sprintf("%s/_matrix/client/r0/rooms/%s/send/m.room.message", form.HomeserverURL, matrixRoomIDEncode(form.RoomID)),
|
||||
ContentType: webhook.ContentTypeJSON,
|
||||
HTTPMethod: http.MethodPut,
|
||||
WebhookForm: form.WebhookForm,
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package setting
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestWebhookMatrix(t *testing.T) {
|
||||
assert.Equal(t, "!roomid:domain", matrixRoomIDEncode("!roomid:domain"))
|
||||
assert.Equal(t, "!room%23id:domain", matrixRoomIDEncode("!room#id:domain")) // maybe it should never really happen in real world
|
||||
}
|
||||
Reference in New Issue
Block a user