mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Move some files under repo/setting (#25585)
There are too many files under `routers/web/repo` and the file `routers/web/repo/setting.go` is too big. This PR move all setting related routers' body functions under `routers/web/repo/setting` and also split `routers/web/repo/setting.go`
This commit is contained in:
		
							
								
								
									
										76
									
								
								routers/web/repo/setting/avatar.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								routers/web/repo/setting/avatar.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
// Copyright 2023 The Gitea Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package setting
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/modules/context"
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	"code.gitea.io/gitea/modules/typesniffer"
 | 
			
		||||
	"code.gitea.io/gitea/modules/web"
 | 
			
		||||
	"code.gitea.io/gitea/services/forms"
 | 
			
		||||
	repo_service "code.gitea.io/gitea/services/repository"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// UpdateAvatarSetting update repo's avatar
 | 
			
		||||
func UpdateAvatarSetting(ctx *context.Context, form forms.AvatarForm) error {
 | 
			
		||||
	ctxRepo := ctx.Repo.Repository
 | 
			
		||||
 | 
			
		||||
	if form.Avatar == nil {
 | 
			
		||||
		// No avatar is uploaded and we not removing it here.
 | 
			
		||||
		// No random avatar generated here.
 | 
			
		||||
		// Just exit, no action.
 | 
			
		||||
		if ctxRepo.CustomAvatarRelativePath() == "" {
 | 
			
		||||
			log.Trace("No avatar was uploaded for repo: %d. Default icon will appear instead.", ctxRepo.ID)
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r, err := form.Avatar.Open()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("Avatar.Open: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer r.Close()
 | 
			
		||||
 | 
			
		||||
	if form.Avatar.Size > setting.Avatar.MaxFileSize {
 | 
			
		||||
		return errors.New(ctx.Tr("settings.uploaded_avatar_is_too_big"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data, err := io.ReadAll(r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("io.ReadAll: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	st := typesniffer.DetectContentType(data)
 | 
			
		||||
	if !(st.IsImage() && !st.IsSvgImage()) {
 | 
			
		||||
		return errors.New(ctx.Tr("settings.uploaded_avatar_not_a_image"))
 | 
			
		||||
	}
 | 
			
		||||
	if err = repo_service.UploadAvatar(ctx, ctxRepo, data); err != nil {
 | 
			
		||||
		return fmt.Errorf("UploadAvatar: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SettingsAvatar save new POSTed repository avatar
 | 
			
		||||
func SettingsAvatar(ctx *context.Context) {
 | 
			
		||||
	form := web.GetForm(ctx).(*forms.AvatarForm)
 | 
			
		||||
	form.Source = forms.AvatarLocal
 | 
			
		||||
	if err := UpdateAvatarSetting(ctx, *form); err != nil {
 | 
			
		||||
		ctx.Flash.Error(err.Error())
 | 
			
		||||
	} else {
 | 
			
		||||
		ctx.Flash.Success(ctx.Tr("repo.settings.update_avatar_success"))
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Redirect(ctx.Repo.RepoLink + "/settings")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SettingsDeleteAvatar delete repository avatar
 | 
			
		||||
func SettingsDeleteAvatar(ctx *context.Context) {
 | 
			
		||||
	if err := repo_service.DeleteAvatar(ctx, ctx.Repo.Repository); err != nil {
 | 
			
		||||
		ctx.Flash.Error(fmt.Sprintf("DeleteAvatar: %v", err))
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Redirect(ctx.Repo.RepoLink + "/settings")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										210
									
								
								routers/web/repo/setting/collaboration.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								routers/web/repo/setting/collaboration.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,210 @@
 | 
			
		||||
// Copyright 2023 The Gitea Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package setting
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
	"code.gitea.io/gitea/models/organization"
 | 
			
		||||
	"code.gitea.io/gitea/models/perm"
 | 
			
		||||
	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/context"
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
	repo_module "code.gitea.io/gitea/modules/repository"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	"code.gitea.io/gitea/routers/utils"
 | 
			
		||||
	"code.gitea.io/gitea/services/mailer"
 | 
			
		||||
	org_service "code.gitea.io/gitea/services/org"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Collaboration render a repository's collaboration page
 | 
			
		||||
func Collaboration(ctx *context.Context) {
 | 
			
		||||
	ctx.Data["Title"] = ctx.Tr("repo.settings.collaboration")
 | 
			
		||||
	ctx.Data["PageIsSettingsCollaboration"] = true
 | 
			
		||||
 | 
			
		||||
	users, err := repo_model.GetCollaborators(ctx, ctx.Repo.Repository.ID, db.ListOptions{})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("GetCollaborators", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Data["Collaborators"] = users
 | 
			
		||||
 | 
			
		||||
	teams, err := organization.GetRepoTeams(ctx, ctx.Repo.Repository)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("GetRepoTeams", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Data["Teams"] = teams
 | 
			
		||||
	ctx.Data["Repo"] = ctx.Repo.Repository
 | 
			
		||||
	ctx.Data["OrgID"] = ctx.Repo.Repository.OwnerID
 | 
			
		||||
	ctx.Data["OrgName"] = ctx.Repo.Repository.OwnerName
 | 
			
		||||
	ctx.Data["Org"] = ctx.Repo.Repository.Owner
 | 
			
		||||
	ctx.Data["Units"] = unit_model.Units
 | 
			
		||||
 | 
			
		||||
	ctx.HTML(http.StatusOK, tplCollaboration)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CollaborationPost response for actions for a collaboration of a repository
 | 
			
		||||
func CollaborationPost(ctx *context.Context) {
 | 
			
		||||
	name := utils.RemoveUsernameParameterSuffix(strings.ToLower(ctx.FormString("collaborator")))
 | 
			
		||||
	if len(name) == 0 || ctx.Repo.Owner.LowerName == name {
 | 
			
		||||
		ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	u, err := user_model.GetUserByName(ctx, name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if user_model.IsErrUserNotExist(err) {
 | 
			
		||||
			ctx.Flash.Error(ctx.Tr("form.user_not_exist"))
 | 
			
		||||
			ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.ServerError("GetUserByName", err)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !u.IsActive {
 | 
			
		||||
		ctx.Flash.Error(ctx.Tr("repo.settings.add_collaborator_inactive_user"))
 | 
			
		||||
		ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Organization is not allowed to be added as a collaborator.
 | 
			
		||||
	if u.IsOrganization() {
 | 
			
		||||
		ctx.Flash.Error(ctx.Tr("repo.settings.org_not_allowed_to_be_collaborator"))
 | 
			
		||||
		ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if got, err := repo_model.IsCollaborator(ctx, ctx.Repo.Repository.ID, u.ID); err == nil && got {
 | 
			
		||||
		ctx.Flash.Error(ctx.Tr("repo.settings.add_collaborator_duplicate"))
 | 
			
		||||
		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// find the owner team of the organization the repo belongs too and
 | 
			
		||||
	// check if the user we're trying to add is an owner.
 | 
			
		||||
	if ctx.Repo.Repository.Owner.IsOrganization() {
 | 
			
		||||
		if isOwner, err := organization.IsOrganizationOwner(ctx, ctx.Repo.Repository.Owner.ID, u.ID); err != nil {
 | 
			
		||||
			ctx.ServerError("IsOrganizationOwner", err)
 | 
			
		||||
			return
 | 
			
		||||
		} else if isOwner {
 | 
			
		||||
			ctx.Flash.Error(ctx.Tr("repo.settings.add_collaborator_owner"))
 | 
			
		||||
			ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = repo_module.AddCollaborator(ctx, ctx.Repo.Repository, u); err != nil {
 | 
			
		||||
		ctx.ServerError("AddCollaborator", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if setting.Service.EnableNotifyMail {
 | 
			
		||||
		mailer.SendCollaboratorMail(u, ctx.Doer, ctx.Repo.Repository)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.Flash.Success(ctx.Tr("repo.settings.add_collaborator_success"))
 | 
			
		||||
	ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ChangeCollaborationAccessMode response for changing access of a collaboration
 | 
			
		||||
func ChangeCollaborationAccessMode(ctx *context.Context) {
 | 
			
		||||
	if err := repo_model.ChangeCollaborationAccessMode(
 | 
			
		||||
		ctx,
 | 
			
		||||
		ctx.Repo.Repository,
 | 
			
		||||
		ctx.FormInt64("uid"),
 | 
			
		||||
		perm.AccessMode(ctx.FormInt("mode"))); err != nil {
 | 
			
		||||
		log.Error("ChangeCollaborationAccessMode: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteCollaboration delete a collaboration for a repository
 | 
			
		||||
func DeleteCollaboration(ctx *context.Context) {
 | 
			
		||||
	if err := models.DeleteCollaboration(ctx.Repo.Repository, ctx.FormInt64("id")); err != nil {
 | 
			
		||||
		ctx.Flash.Error("DeleteCollaboration: " + err.Error())
 | 
			
		||||
	} else {
 | 
			
		||||
		ctx.Flash.Success(ctx.Tr("repo.settings.remove_collaborator_success"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.JSON(http.StatusOK, map[string]interface{}{
 | 
			
		||||
		"redirect": ctx.Repo.RepoLink + "/settings/collaboration",
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddTeamPost response for adding a team to a repository
 | 
			
		||||
func AddTeamPost(ctx *context.Context) {
 | 
			
		||||
	if !ctx.Repo.Owner.RepoAdminChangeTeamAccess && !ctx.Repo.IsOwner() {
 | 
			
		||||
		ctx.Flash.Error(ctx.Tr("repo.settings.change_team_access_not_allowed"))
 | 
			
		||||
		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	name := utils.RemoveUsernameParameterSuffix(strings.ToLower(ctx.FormString("team")))
 | 
			
		||||
	if len(name) == 0 {
 | 
			
		||||
		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	team, err := organization.OrgFromUser(ctx.Repo.Owner).GetTeam(ctx, name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if organization.IsErrTeamNotExist(err) {
 | 
			
		||||
			ctx.Flash.Error(ctx.Tr("form.team_not_exist"))
 | 
			
		||||
			ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.ServerError("GetTeam", err)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if team.OrgID != ctx.Repo.Repository.OwnerID {
 | 
			
		||||
		ctx.Flash.Error(ctx.Tr("repo.settings.team_not_in_organization"))
 | 
			
		||||
		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if organization.HasTeamRepo(ctx, ctx.Repo.Repository.OwnerID, team.ID, ctx.Repo.Repository.ID) {
 | 
			
		||||
		ctx.Flash.Error(ctx.Tr("repo.settings.add_team_duplicate"))
 | 
			
		||||
		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = org_service.TeamAddRepository(team, ctx.Repo.Repository); err != nil {
 | 
			
		||||
		ctx.ServerError("TeamAddRepository", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.Flash.Success(ctx.Tr("repo.settings.add_team_success"))
 | 
			
		||||
	ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteTeam response for deleting a team from a repository
 | 
			
		||||
func DeleteTeam(ctx *context.Context) {
 | 
			
		||||
	if !ctx.Repo.Owner.RepoAdminChangeTeamAccess && !ctx.Repo.IsOwner() {
 | 
			
		||||
		ctx.Flash.Error(ctx.Tr("repo.settings.change_team_access_not_allowed"))
 | 
			
		||||
		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	team, err := organization.GetTeamByID(ctx, ctx.FormInt64("id"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("GetTeamByID", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = models.RemoveRepository(team, ctx.Repo.Repository.ID); err != nil {
 | 
			
		||||
		ctx.ServerError("team.RemoveRepositorys", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.Flash.Success(ctx.Tr("repo.settings.remove_team_success"))
 | 
			
		||||
	ctx.JSON(http.StatusOK, map[string]interface{}{
 | 
			
		||||
		"redirect": ctx.Repo.RepoLink + "/settings/collaboration",
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										111
									
								
								routers/web/repo/setting/deploy_key.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								routers/web/repo/setting/deploy_key.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,111 @@
 | 
			
		||||
// Copyright 2023 The Gitea Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package setting
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	asymkey_model "code.gitea.io/gitea/models/asymkey"
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
	"code.gitea.io/gitea/modules/context"
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	"code.gitea.io/gitea/modules/web"
 | 
			
		||||
	asymkey_service "code.gitea.io/gitea/services/asymkey"
 | 
			
		||||
	"code.gitea.io/gitea/services/forms"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DeployKeys render the deploy keys list of a repository page
 | 
			
		||||
func DeployKeys(ctx *context.Context) {
 | 
			
		||||
	ctx.Data["Title"] = ctx.Tr("repo.settings.deploy_keys") + " / " + ctx.Tr("secrets.secrets")
 | 
			
		||||
	ctx.Data["PageIsSettingsKeys"] = true
 | 
			
		||||
	ctx.Data["DisableSSH"] = setting.SSH.Disabled
 | 
			
		||||
 | 
			
		||||
	keys, err := asymkey_model.ListDeployKeys(ctx, &asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("ListDeployKeys", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Data["Deploykeys"] = keys
 | 
			
		||||
 | 
			
		||||
	ctx.HTML(http.StatusOK, tplDeployKeys)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeployKeysPost response for adding a deploy key of a repository
 | 
			
		||||
func DeployKeysPost(ctx *context.Context) {
 | 
			
		||||
	form := web.GetForm(ctx).(*forms.AddKeyForm)
 | 
			
		||||
	ctx.Data["Title"] = ctx.Tr("repo.settings.deploy_keys")
 | 
			
		||||
	ctx.Data["PageIsSettingsKeys"] = true
 | 
			
		||||
	ctx.Data["DisableSSH"] = setting.SSH.Disabled
 | 
			
		||||
 | 
			
		||||
	keys, err := asymkey_model.ListDeployKeys(ctx, &asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("ListDeployKeys", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Data["Deploykeys"] = keys
 | 
			
		||||
 | 
			
		||||
	if ctx.HasError() {
 | 
			
		||||
		ctx.HTML(http.StatusOK, tplDeployKeys)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	content, err := asymkey_model.CheckPublicKeyString(form.Content)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if db.IsErrSSHDisabled(err) {
 | 
			
		||||
			ctx.Flash.Info(ctx.Tr("settings.ssh_disabled"))
 | 
			
		||||
		} else if asymkey_model.IsErrKeyUnableVerify(err) {
 | 
			
		||||
			ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key"))
 | 
			
		||||
		} else if err == asymkey_model.ErrKeyIsPrivate {
 | 
			
		||||
			ctx.Data["HasError"] = true
 | 
			
		||||
			ctx.Data["Err_Content"] = true
 | 
			
		||||
			ctx.Flash.Error(ctx.Tr("form.must_use_public_key"))
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.Data["HasError"] = true
 | 
			
		||||
			ctx.Data["Err_Content"] = true
 | 
			
		||||
			ctx.Flash.Error(ctx.Tr("form.invalid_ssh_key", err.Error()))
 | 
			
		||||
		}
 | 
			
		||||
		ctx.Redirect(ctx.Repo.RepoLink + "/settings/keys")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	key, err := asymkey_model.AddDeployKey(ctx.Repo.Repository.ID, form.Title, content, !form.IsWritable)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.Data["HasError"] = true
 | 
			
		||||
		switch {
 | 
			
		||||
		case asymkey_model.IsErrDeployKeyAlreadyExist(err):
 | 
			
		||||
			ctx.Data["Err_Content"] = true
 | 
			
		||||
			ctx.RenderWithErr(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)
 | 
			
		||||
		case asymkey_model.IsErrKeyNameAlreadyUsed(err):
 | 
			
		||||
			ctx.Data["Err_Title"] = true
 | 
			
		||||
			ctx.RenderWithErr(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)
 | 
			
		||||
		default:
 | 
			
		||||
			ctx.ServerError("AddDeployKey", err)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Trace("Deploy key added: %d", ctx.Repo.Repository.ID)
 | 
			
		||||
	ctx.Flash.Success(ctx.Tr("repo.settings.add_key_success", key.Name))
 | 
			
		||||
	ctx.Redirect(ctx.Repo.RepoLink + "/settings/keys")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteDeployKey response for deleting a deploy key
 | 
			
		||||
func DeleteDeployKey(ctx *context.Context) {
 | 
			
		||||
	if err := asymkey_service.DeleteDeployKey(ctx.Doer, ctx.FormInt64("id")); err != nil {
 | 
			
		||||
		ctx.Flash.Error("DeleteDeployKey: " + err.Error())
 | 
			
		||||
	} else {
 | 
			
		||||
		ctx.Flash.Success(ctx.Tr("repo.settings.deploy_key_deletion_success"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.JSON(http.StatusOK, map[string]interface{}{
 | 
			
		||||
		"redirect": ctx.Repo.RepoLink + "/settings/keys",
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										65
									
								
								routers/web/repo/setting/git_hooks.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								routers/web/repo/setting/git_hooks.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
// Copyright 2023 The Gitea Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package setting
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/modules/context"
 | 
			
		||||
	"code.gitea.io/gitea/modules/git"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GitHooks hooks of a repository
 | 
			
		||||
func GitHooks(ctx *context.Context) {
 | 
			
		||||
	ctx.Data["Title"] = ctx.Tr("repo.settings.githooks")
 | 
			
		||||
	ctx.Data["PageIsSettingsGitHooks"] = true
 | 
			
		||||
 | 
			
		||||
	hooks, err := ctx.Repo.GitRepo.Hooks()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("Hooks", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Data["Hooks"] = hooks
 | 
			
		||||
 | 
			
		||||
	ctx.HTML(http.StatusOK, tplGithooks)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GitHooksEdit render for editing a hook of repository page
 | 
			
		||||
func GitHooksEdit(ctx *context.Context) {
 | 
			
		||||
	ctx.Data["Title"] = ctx.Tr("repo.settings.githooks")
 | 
			
		||||
	ctx.Data["PageIsSettingsGitHooks"] = true
 | 
			
		||||
 | 
			
		||||
	name := ctx.Params(":name")
 | 
			
		||||
	hook, err := ctx.Repo.GitRepo.GetHook(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if err == git.ErrNotValidHook {
 | 
			
		||||
			ctx.NotFound("GetHook", err)
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.ServerError("GetHook", err)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Data["Hook"] = hook
 | 
			
		||||
	ctx.HTML(http.StatusOK, tplGithookEdit)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GitHooksEditPost response for editing a git hook of a repository
 | 
			
		||||
func GitHooksEditPost(ctx *context.Context) {
 | 
			
		||||
	name := ctx.Params(":name")
 | 
			
		||||
	hook, err := ctx.Repo.GitRepo.GetHook(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if err == git.ErrNotValidHook {
 | 
			
		||||
			ctx.NotFound("GetHook", err)
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.ServerError("GetHook", err)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	hook.Content = ctx.FormString("content")
 | 
			
		||||
	if err = hook.Update(); err != nil {
 | 
			
		||||
		ctx.ServerError("hook.Update", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Redirect(ctx.Repo.RepoLink + "/settings/hooks/git")
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// Copyright 2019 The Gitea Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package repo
 | 
			
		||||
package setting
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
							
								
								
									
										17
									
								
								routers/web/repo/setting/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								routers/web/repo/setting/main_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
// Copyright 2017 The Gitea Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package setting
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models/unittest"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestMain(m *testing.M) {
 | 
			
		||||
	unittest.MainTest(m, &unittest.TestOptions{
 | 
			
		||||
		GiteaRootPath: filepath.Join("..", "..", "..", ".."),
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// Copyright 2017 The Gitea Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package repo
 | 
			
		||||
package setting
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// Copyright 2021 The Gitea Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package repo
 | 
			
		||||
package setting
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
@@ -19,8 +19,12 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/services/forms"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	tplTags base.TplName = "repo/settings/tags"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Tags render the page to protect tags
 | 
			
		||||
func Tags(ctx *context.Context) {
 | 
			
		||||
func ProtectedTags(ctx *context.Context) {
 | 
			
		||||
	if setTagsContext(ctx) != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
@@ -2,22 +2,18 @@
 | 
			
		||||
// Copyright 2018 The Gitea Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package repo
 | 
			
		||||
package setting
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
	asymkey_model "code.gitea.io/gitea/models/asymkey"
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
	"code.gitea.io/gitea/models/organization"
 | 
			
		||||
	"code.gitea.io/gitea/models/perm"
 | 
			
		||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
			
		||||
	unit_model "code.gitea.io/gitea/models/unit"
 | 
			
		||||
	user_model "code.gitea.io/gitea/models/user"
 | 
			
		||||
@@ -32,17 +28,13 @@ import (
 | 
			
		||||
	repo_module "code.gitea.io/gitea/modules/repository"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	"code.gitea.io/gitea/modules/structs"
 | 
			
		||||
	"code.gitea.io/gitea/modules/typesniffer"
 | 
			
		||||
	"code.gitea.io/gitea/modules/util"
 | 
			
		||||
	"code.gitea.io/gitea/modules/validation"
 | 
			
		||||
	"code.gitea.io/gitea/modules/web"
 | 
			
		||||
	"code.gitea.io/gitea/routers/utils"
 | 
			
		||||
	asymkey_service "code.gitea.io/gitea/services/asymkey"
 | 
			
		||||
	"code.gitea.io/gitea/services/forms"
 | 
			
		||||
	"code.gitea.io/gitea/services/mailer"
 | 
			
		||||
	"code.gitea.io/gitea/services/migrations"
 | 
			
		||||
	mirror_service "code.gitea.io/gitea/services/mirror"
 | 
			
		||||
	org_service "code.gitea.io/gitea/services/org"
 | 
			
		||||
	repo_service "code.gitea.io/gitea/services/repository"
 | 
			
		||||
	wiki_service "code.gitea.io/gitea/services/wiki"
 | 
			
		||||
)
 | 
			
		||||
@@ -51,7 +43,6 @@ const (
 | 
			
		||||
	tplSettingsOptions base.TplName = "repo/settings/options"
 | 
			
		||||
	tplCollaboration   base.TplName = "repo/settings/collaboration"
 | 
			
		||||
	tplBranches        base.TplName = "repo/settings/branches"
 | 
			
		||||
	tplTags            base.TplName = "repo/settings/tags"
 | 
			
		||||
	tplGithooks        base.TplName = "repo/settings/githooks"
 | 
			
		||||
	tplGithookEdit     base.TplName = "repo/settings/githook_edit"
 | 
			
		||||
	tplDeployKeys      base.TplName = "repo/settings/deploy_keys"
 | 
			
		||||
@@ -895,398 +886,6 @@ func handleSettingRemoteAddrError(ctx *context.Context, err error, form *forms.R
 | 
			
		||||
	ctx.RenderWithErr(ctx.Tr("repo.mirror_address_url_invalid"), tplSettingsOptions, form)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Collaboration render a repository's collaboration page
 | 
			
		||||
func Collaboration(ctx *context.Context) {
 | 
			
		||||
	ctx.Data["Title"] = ctx.Tr("repo.settings.collaboration")
 | 
			
		||||
	ctx.Data["PageIsSettingsCollaboration"] = true
 | 
			
		||||
 | 
			
		||||
	users, err := repo_model.GetCollaborators(ctx, ctx.Repo.Repository.ID, db.ListOptions{})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("GetCollaborators", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Data["Collaborators"] = users
 | 
			
		||||
 | 
			
		||||
	teams, err := organization.GetRepoTeams(ctx, ctx.Repo.Repository)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("GetRepoTeams", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Data["Teams"] = teams
 | 
			
		||||
	ctx.Data["Repo"] = ctx.Repo.Repository
 | 
			
		||||
	ctx.Data["OrgID"] = ctx.Repo.Repository.OwnerID
 | 
			
		||||
	ctx.Data["OrgName"] = ctx.Repo.Repository.OwnerName
 | 
			
		||||
	ctx.Data["Org"] = ctx.Repo.Repository.Owner
 | 
			
		||||
	ctx.Data["Units"] = unit_model.Units
 | 
			
		||||
 | 
			
		||||
	ctx.HTML(http.StatusOK, tplCollaboration)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CollaborationPost response for actions for a collaboration of a repository
 | 
			
		||||
func CollaborationPost(ctx *context.Context) {
 | 
			
		||||
	name := utils.RemoveUsernameParameterSuffix(strings.ToLower(ctx.FormString("collaborator")))
 | 
			
		||||
	if len(name) == 0 || ctx.Repo.Owner.LowerName == name {
 | 
			
		||||
		ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	u, err := user_model.GetUserByName(ctx, name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if user_model.IsErrUserNotExist(err) {
 | 
			
		||||
			ctx.Flash.Error(ctx.Tr("form.user_not_exist"))
 | 
			
		||||
			ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.ServerError("GetUserByName", err)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !u.IsActive {
 | 
			
		||||
		ctx.Flash.Error(ctx.Tr("repo.settings.add_collaborator_inactive_user"))
 | 
			
		||||
		ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Organization is not allowed to be added as a collaborator.
 | 
			
		||||
	if u.IsOrganization() {
 | 
			
		||||
		ctx.Flash.Error(ctx.Tr("repo.settings.org_not_allowed_to_be_collaborator"))
 | 
			
		||||
		ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if got, err := repo_model.IsCollaborator(ctx, ctx.Repo.Repository.ID, u.ID); err == nil && got {
 | 
			
		||||
		ctx.Flash.Error(ctx.Tr("repo.settings.add_collaborator_duplicate"))
 | 
			
		||||
		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// find the owner team of the organization the repo belongs too and
 | 
			
		||||
	// check if the user we're trying to add is an owner.
 | 
			
		||||
	if ctx.Repo.Repository.Owner.IsOrganization() {
 | 
			
		||||
		if isOwner, err := organization.IsOrganizationOwner(ctx, ctx.Repo.Repository.Owner.ID, u.ID); err != nil {
 | 
			
		||||
			ctx.ServerError("IsOrganizationOwner", err)
 | 
			
		||||
			return
 | 
			
		||||
		} else if isOwner {
 | 
			
		||||
			ctx.Flash.Error(ctx.Tr("repo.settings.add_collaborator_owner"))
 | 
			
		||||
			ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = repo_module.AddCollaborator(ctx, ctx.Repo.Repository, u); err != nil {
 | 
			
		||||
		ctx.ServerError("AddCollaborator", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if setting.Service.EnableNotifyMail {
 | 
			
		||||
		mailer.SendCollaboratorMail(u, ctx.Doer, ctx.Repo.Repository)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.Flash.Success(ctx.Tr("repo.settings.add_collaborator_success"))
 | 
			
		||||
	ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ChangeCollaborationAccessMode response for changing access of a collaboration
 | 
			
		||||
func ChangeCollaborationAccessMode(ctx *context.Context) {
 | 
			
		||||
	if err := repo_model.ChangeCollaborationAccessMode(
 | 
			
		||||
		ctx,
 | 
			
		||||
		ctx.Repo.Repository,
 | 
			
		||||
		ctx.FormInt64("uid"),
 | 
			
		||||
		perm.AccessMode(ctx.FormInt("mode"))); err != nil {
 | 
			
		||||
		log.Error("ChangeCollaborationAccessMode: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteCollaboration delete a collaboration for a repository
 | 
			
		||||
func DeleteCollaboration(ctx *context.Context) {
 | 
			
		||||
	if err := models.DeleteCollaboration(ctx.Repo.Repository, ctx.FormInt64("id")); err != nil {
 | 
			
		||||
		ctx.Flash.Error("DeleteCollaboration: " + err.Error())
 | 
			
		||||
	} else {
 | 
			
		||||
		ctx.Flash.Success(ctx.Tr("repo.settings.remove_collaborator_success"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.JSON(http.StatusOK, map[string]interface{}{
 | 
			
		||||
		"redirect": ctx.Repo.RepoLink + "/settings/collaboration",
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddTeamPost response for adding a team to a repository
 | 
			
		||||
func AddTeamPost(ctx *context.Context) {
 | 
			
		||||
	if !ctx.Repo.Owner.RepoAdminChangeTeamAccess && !ctx.Repo.IsOwner() {
 | 
			
		||||
		ctx.Flash.Error(ctx.Tr("repo.settings.change_team_access_not_allowed"))
 | 
			
		||||
		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	name := utils.RemoveUsernameParameterSuffix(strings.ToLower(ctx.FormString("team")))
 | 
			
		||||
	if len(name) == 0 {
 | 
			
		||||
		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	team, err := organization.OrgFromUser(ctx.Repo.Owner).GetTeam(ctx, name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if organization.IsErrTeamNotExist(err) {
 | 
			
		||||
			ctx.Flash.Error(ctx.Tr("form.team_not_exist"))
 | 
			
		||||
			ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.ServerError("GetTeam", err)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if team.OrgID != ctx.Repo.Repository.OwnerID {
 | 
			
		||||
		ctx.Flash.Error(ctx.Tr("repo.settings.team_not_in_organization"))
 | 
			
		||||
		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if organization.HasTeamRepo(ctx, ctx.Repo.Repository.OwnerID, team.ID, ctx.Repo.Repository.ID) {
 | 
			
		||||
		ctx.Flash.Error(ctx.Tr("repo.settings.add_team_duplicate"))
 | 
			
		||||
		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = org_service.TeamAddRepository(team, ctx.Repo.Repository); err != nil {
 | 
			
		||||
		ctx.ServerError("TeamAddRepository", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.Flash.Success(ctx.Tr("repo.settings.add_team_success"))
 | 
			
		||||
	ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteTeam response for deleting a team from a repository
 | 
			
		||||
func DeleteTeam(ctx *context.Context) {
 | 
			
		||||
	if !ctx.Repo.Owner.RepoAdminChangeTeamAccess && !ctx.Repo.IsOwner() {
 | 
			
		||||
		ctx.Flash.Error(ctx.Tr("repo.settings.change_team_access_not_allowed"))
 | 
			
		||||
		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	team, err := organization.GetTeamByID(ctx, ctx.FormInt64("id"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("GetTeamByID", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = models.RemoveRepository(team, ctx.Repo.Repository.ID); err != nil {
 | 
			
		||||
		ctx.ServerError("team.RemoveRepositorys", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.Flash.Success(ctx.Tr("repo.settings.remove_team_success"))
 | 
			
		||||
	ctx.JSON(http.StatusOK, map[string]interface{}{
 | 
			
		||||
		"redirect": ctx.Repo.RepoLink + "/settings/collaboration",
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GitHooks hooks of a repository
 | 
			
		||||
func GitHooks(ctx *context.Context) {
 | 
			
		||||
	ctx.Data["Title"] = ctx.Tr("repo.settings.githooks")
 | 
			
		||||
	ctx.Data["PageIsSettingsGitHooks"] = true
 | 
			
		||||
 | 
			
		||||
	hooks, err := ctx.Repo.GitRepo.Hooks()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("Hooks", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Data["Hooks"] = hooks
 | 
			
		||||
 | 
			
		||||
	ctx.HTML(http.StatusOK, tplGithooks)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GitHooksEdit render for editing a hook of repository page
 | 
			
		||||
func GitHooksEdit(ctx *context.Context) {
 | 
			
		||||
	ctx.Data["Title"] = ctx.Tr("repo.settings.githooks")
 | 
			
		||||
	ctx.Data["PageIsSettingsGitHooks"] = true
 | 
			
		||||
 | 
			
		||||
	name := ctx.Params(":name")
 | 
			
		||||
	hook, err := ctx.Repo.GitRepo.GetHook(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if err == git.ErrNotValidHook {
 | 
			
		||||
			ctx.NotFound("GetHook", err)
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.ServerError("GetHook", err)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Data["Hook"] = hook
 | 
			
		||||
	ctx.HTML(http.StatusOK, tplGithookEdit)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GitHooksEditPost response for editing a git hook of a repository
 | 
			
		||||
func GitHooksEditPost(ctx *context.Context) {
 | 
			
		||||
	name := ctx.Params(":name")
 | 
			
		||||
	hook, err := ctx.Repo.GitRepo.GetHook(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if err == git.ErrNotValidHook {
 | 
			
		||||
			ctx.NotFound("GetHook", err)
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.ServerError("GetHook", err)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	hook.Content = ctx.FormString("content")
 | 
			
		||||
	if err = hook.Update(); err != nil {
 | 
			
		||||
		ctx.ServerError("hook.Update", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Redirect(ctx.Repo.RepoLink + "/settings/hooks/git")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeployKeys render the deploy keys list of a repository page
 | 
			
		||||
func DeployKeys(ctx *context.Context) {
 | 
			
		||||
	ctx.Data["Title"] = ctx.Tr("repo.settings.deploy_keys") + " / " + ctx.Tr("secrets.secrets")
 | 
			
		||||
	ctx.Data["PageIsSettingsKeys"] = true
 | 
			
		||||
	ctx.Data["DisableSSH"] = setting.SSH.Disabled
 | 
			
		||||
 | 
			
		||||
	keys, err := asymkey_model.ListDeployKeys(ctx, &asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("ListDeployKeys", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Data["Deploykeys"] = keys
 | 
			
		||||
 | 
			
		||||
	ctx.HTML(http.StatusOK, tplDeployKeys)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeployKeysPost response for adding a deploy key of a repository
 | 
			
		||||
func DeployKeysPost(ctx *context.Context) {
 | 
			
		||||
	form := web.GetForm(ctx).(*forms.AddKeyForm)
 | 
			
		||||
	ctx.Data["Title"] = ctx.Tr("repo.settings.deploy_keys")
 | 
			
		||||
	ctx.Data["PageIsSettingsKeys"] = true
 | 
			
		||||
	ctx.Data["DisableSSH"] = setting.SSH.Disabled
 | 
			
		||||
 | 
			
		||||
	keys, err := asymkey_model.ListDeployKeys(ctx, &asymkey_model.ListDeployKeysOptions{RepoID: ctx.Repo.Repository.ID})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("ListDeployKeys", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Data["Deploykeys"] = keys
 | 
			
		||||
 | 
			
		||||
	if ctx.HasError() {
 | 
			
		||||
		ctx.HTML(http.StatusOK, tplDeployKeys)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	content, err := asymkey_model.CheckPublicKeyString(form.Content)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if db.IsErrSSHDisabled(err) {
 | 
			
		||||
			ctx.Flash.Info(ctx.Tr("settings.ssh_disabled"))
 | 
			
		||||
		} else if asymkey_model.IsErrKeyUnableVerify(err) {
 | 
			
		||||
			ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key"))
 | 
			
		||||
		} else if err == asymkey_model.ErrKeyIsPrivate {
 | 
			
		||||
			ctx.Data["HasError"] = true
 | 
			
		||||
			ctx.Data["Err_Content"] = true
 | 
			
		||||
			ctx.Flash.Error(ctx.Tr("form.must_use_public_key"))
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.Data["HasError"] = true
 | 
			
		||||
			ctx.Data["Err_Content"] = true
 | 
			
		||||
			ctx.Flash.Error(ctx.Tr("form.invalid_ssh_key", err.Error()))
 | 
			
		||||
		}
 | 
			
		||||
		ctx.Redirect(ctx.Repo.RepoLink + "/settings/keys")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	key, err := asymkey_model.AddDeployKey(ctx.Repo.Repository.ID, form.Title, content, !form.IsWritable)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.Data["HasError"] = true
 | 
			
		||||
		switch {
 | 
			
		||||
		case asymkey_model.IsErrDeployKeyAlreadyExist(err):
 | 
			
		||||
			ctx.Data["Err_Content"] = true
 | 
			
		||||
			ctx.RenderWithErr(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)
 | 
			
		||||
		case asymkey_model.IsErrKeyNameAlreadyUsed(err):
 | 
			
		||||
			ctx.Data["Err_Title"] = true
 | 
			
		||||
			ctx.RenderWithErr(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)
 | 
			
		||||
		default:
 | 
			
		||||
			ctx.ServerError("AddDeployKey", err)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Trace("Deploy key added: %d", ctx.Repo.Repository.ID)
 | 
			
		||||
	ctx.Flash.Success(ctx.Tr("repo.settings.add_key_success", key.Name))
 | 
			
		||||
	ctx.Redirect(ctx.Repo.RepoLink + "/settings/keys")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteDeployKey response for deleting a deploy key
 | 
			
		||||
func DeleteDeployKey(ctx *context.Context) {
 | 
			
		||||
	if err := asymkey_service.DeleteDeployKey(ctx.Doer, ctx.FormInt64("id")); err != nil {
 | 
			
		||||
		ctx.Flash.Error("DeleteDeployKey: " + err.Error())
 | 
			
		||||
	} else {
 | 
			
		||||
		ctx.Flash.Success(ctx.Tr("repo.settings.deploy_key_deletion_success"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.JSON(http.StatusOK, map[string]interface{}{
 | 
			
		||||
		"redirect": ctx.Repo.RepoLink + "/settings/keys",
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateAvatarSetting update repo's avatar
 | 
			
		||||
func UpdateAvatarSetting(ctx *context.Context, form forms.AvatarForm) error {
 | 
			
		||||
	ctxRepo := ctx.Repo.Repository
 | 
			
		||||
 | 
			
		||||
	if form.Avatar == nil {
 | 
			
		||||
		// No avatar is uploaded and we not removing it here.
 | 
			
		||||
		// No random avatar generated here.
 | 
			
		||||
		// Just exit, no action.
 | 
			
		||||
		if ctxRepo.CustomAvatarRelativePath() == "" {
 | 
			
		||||
			log.Trace("No avatar was uploaded for repo: %d. Default icon will appear instead.", ctxRepo.ID)
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r, err := form.Avatar.Open()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("Avatar.Open: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer r.Close()
 | 
			
		||||
 | 
			
		||||
	if form.Avatar.Size > setting.Avatar.MaxFileSize {
 | 
			
		||||
		return errors.New(ctx.Tr("settings.uploaded_avatar_is_too_big"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data, err := io.ReadAll(r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("io.ReadAll: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	st := typesniffer.DetectContentType(data)
 | 
			
		||||
	if !(st.IsImage() && !st.IsSvgImage()) {
 | 
			
		||||
		return errors.New(ctx.Tr("settings.uploaded_avatar_not_a_image"))
 | 
			
		||||
	}
 | 
			
		||||
	if err = repo_service.UploadAvatar(ctx, ctxRepo, data); err != nil {
 | 
			
		||||
		return fmt.Errorf("UploadAvatar: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SettingsAvatar save new POSTed repository avatar
 | 
			
		||||
func SettingsAvatar(ctx *context.Context) {
 | 
			
		||||
	form := web.GetForm(ctx).(*forms.AvatarForm)
 | 
			
		||||
	form.Source = forms.AvatarLocal
 | 
			
		||||
	if err := UpdateAvatarSetting(ctx, *form); err != nil {
 | 
			
		||||
		ctx.Flash.Error(err.Error())
 | 
			
		||||
	} else {
 | 
			
		||||
		ctx.Flash.Success(ctx.Tr("repo.settings.update_avatar_success"))
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Redirect(ctx.Repo.RepoLink + "/settings")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SettingsDeleteAvatar delete repository avatar
 | 
			
		||||
func SettingsDeleteAvatar(ctx *context.Context) {
 | 
			
		||||
	if err := repo_service.DeleteAvatar(ctx, ctx.Repo.Repository); err != nil {
 | 
			
		||||
		ctx.Flash.Error(fmt.Sprintf("DeleteAvatar: %v", err))
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Redirect(ctx.Repo.RepoLink + "/settings")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func selectPushMirrorByForm(ctx *context.Context, form *forms.RepoSettingForm, repo *repo_model.Repository) (*repo_model.PushMirror, error) {
 | 
			
		||||
	id, err := strconv.ParseInt(form.PushMirrorID, 10, 64)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// Copyright 2017 The Gitea Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package repo
 | 
			
		||||
package setting
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
// Copyright 2017 The Gitea Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package repo
 | 
			
		||||
package setting
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
@@ -279,32 +279,32 @@ func registerRoutes(m *web.Route) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	addWebhookAddRoutes := func() {
 | 
			
		||||
		m.Get("/{type}/new", repo.WebhooksNew)
 | 
			
		||||
		m.Post("/gitea/new", web.Bind(forms.NewWebhookForm{}), repo.GiteaHooksNewPost)
 | 
			
		||||
		m.Post("/gogs/new", web.Bind(forms.NewGogshookForm{}), repo.GogsHooksNewPost)
 | 
			
		||||
		m.Post("/slack/new", web.Bind(forms.NewSlackHookForm{}), repo.SlackHooksNewPost)
 | 
			
		||||
		m.Post("/discord/new", web.Bind(forms.NewDiscordHookForm{}), repo.DiscordHooksNewPost)
 | 
			
		||||
		m.Post("/dingtalk/new", web.Bind(forms.NewDingtalkHookForm{}), repo.DingtalkHooksNewPost)
 | 
			
		||||
		m.Post("/telegram/new", web.Bind(forms.NewTelegramHookForm{}), repo.TelegramHooksNewPost)
 | 
			
		||||
		m.Post("/matrix/new", web.Bind(forms.NewMatrixHookForm{}), repo.MatrixHooksNewPost)
 | 
			
		||||
		m.Post("/msteams/new", web.Bind(forms.NewMSTeamsHookForm{}), repo.MSTeamsHooksNewPost)
 | 
			
		||||
		m.Post("/feishu/new", web.Bind(forms.NewFeishuHookForm{}), repo.FeishuHooksNewPost)
 | 
			
		||||
		m.Post("/wechatwork/new", web.Bind(forms.NewWechatWorkHookForm{}), repo.WechatworkHooksNewPost)
 | 
			
		||||
		m.Post("/packagist/new", web.Bind(forms.NewPackagistHookForm{}), repo.PackagistHooksNewPost)
 | 
			
		||||
		m.Get("/{type}/new", repo_setting.WebhooksNew)
 | 
			
		||||
		m.Post("/gitea/new", web.Bind(forms.NewWebhookForm{}), repo_setting.GiteaHooksNewPost)
 | 
			
		||||
		m.Post("/gogs/new", web.Bind(forms.NewGogshookForm{}), repo_setting.GogsHooksNewPost)
 | 
			
		||||
		m.Post("/slack/new", web.Bind(forms.NewSlackHookForm{}), repo_setting.SlackHooksNewPost)
 | 
			
		||||
		m.Post("/discord/new", web.Bind(forms.NewDiscordHookForm{}), repo_setting.DiscordHooksNewPost)
 | 
			
		||||
		m.Post("/dingtalk/new", web.Bind(forms.NewDingtalkHookForm{}), repo_setting.DingtalkHooksNewPost)
 | 
			
		||||
		m.Post("/telegram/new", web.Bind(forms.NewTelegramHookForm{}), repo_setting.TelegramHooksNewPost)
 | 
			
		||||
		m.Post("/matrix/new", web.Bind(forms.NewMatrixHookForm{}), repo_setting.MatrixHooksNewPost)
 | 
			
		||||
		m.Post("/msteams/new", web.Bind(forms.NewMSTeamsHookForm{}), repo_setting.MSTeamsHooksNewPost)
 | 
			
		||||
		m.Post("/feishu/new", web.Bind(forms.NewFeishuHookForm{}), repo_setting.FeishuHooksNewPost)
 | 
			
		||||
		m.Post("/wechatwork/new", web.Bind(forms.NewWechatWorkHookForm{}), repo_setting.WechatworkHooksNewPost)
 | 
			
		||||
		m.Post("/packagist/new", web.Bind(forms.NewPackagistHookForm{}), repo_setting.PackagistHooksNewPost)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	addWebhookEditRoutes := func() {
 | 
			
		||||
		m.Post("/gitea/{id}", web.Bind(forms.NewWebhookForm{}), repo.GiteaHooksEditPost)
 | 
			
		||||
		m.Post("/gogs/{id}", web.Bind(forms.NewGogshookForm{}), repo.GogsHooksEditPost)
 | 
			
		||||
		m.Post("/slack/{id}", web.Bind(forms.NewSlackHookForm{}), repo.SlackHooksEditPost)
 | 
			
		||||
		m.Post("/discord/{id}", web.Bind(forms.NewDiscordHookForm{}), repo.DiscordHooksEditPost)
 | 
			
		||||
		m.Post("/dingtalk/{id}", web.Bind(forms.NewDingtalkHookForm{}), repo.DingtalkHooksEditPost)
 | 
			
		||||
		m.Post("/telegram/{id}", web.Bind(forms.NewTelegramHookForm{}), repo.TelegramHooksEditPost)
 | 
			
		||||
		m.Post("/matrix/{id}", web.Bind(forms.NewMatrixHookForm{}), repo.MatrixHooksEditPost)
 | 
			
		||||
		m.Post("/msteams/{id}", web.Bind(forms.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost)
 | 
			
		||||
		m.Post("/feishu/{id}", web.Bind(forms.NewFeishuHookForm{}), repo.FeishuHooksEditPost)
 | 
			
		||||
		m.Post("/wechatwork/{id}", web.Bind(forms.NewWechatWorkHookForm{}), repo.WechatworkHooksEditPost)
 | 
			
		||||
		m.Post("/packagist/{id}", web.Bind(forms.NewPackagistHookForm{}), repo.PackagistHooksEditPost)
 | 
			
		||||
		m.Post("/gitea/{id}", web.Bind(forms.NewWebhookForm{}), repo_setting.GiteaHooksEditPost)
 | 
			
		||||
		m.Post("/gogs/{id}", web.Bind(forms.NewGogshookForm{}), repo_setting.GogsHooksEditPost)
 | 
			
		||||
		m.Post("/slack/{id}", web.Bind(forms.NewSlackHookForm{}), repo_setting.SlackHooksEditPost)
 | 
			
		||||
		m.Post("/discord/{id}", web.Bind(forms.NewDiscordHookForm{}), repo_setting.DiscordHooksEditPost)
 | 
			
		||||
		m.Post("/dingtalk/{id}", web.Bind(forms.NewDingtalkHookForm{}), repo_setting.DingtalkHooksEditPost)
 | 
			
		||||
		m.Post("/telegram/{id}", web.Bind(forms.NewTelegramHookForm{}), repo_setting.TelegramHooksEditPost)
 | 
			
		||||
		m.Post("/matrix/{id}", web.Bind(forms.NewMatrixHookForm{}), repo_setting.MatrixHooksEditPost)
 | 
			
		||||
		m.Post("/msteams/{id}", web.Bind(forms.NewMSTeamsHookForm{}), repo_setting.MSTeamsHooksEditPost)
 | 
			
		||||
		m.Post("/feishu/{id}", web.Bind(forms.NewFeishuHookForm{}), repo_setting.FeishuHooksEditPost)
 | 
			
		||||
		m.Post("/wechatwork/{id}", web.Bind(forms.NewWechatWorkHookForm{}), repo_setting.WechatworkHooksEditPost)
 | 
			
		||||
		m.Post("/packagist/{id}", web.Bind(forms.NewPackagistHookForm{}), repo_setting.PackagistHooksEditPost)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	addSettingVariablesRoutes := func() {
 | 
			
		||||
@@ -515,8 +515,8 @@ func registerRoutes(m *web.Route) {
 | 
			
		||||
			m.Post("/delete", user_setting.DeleteWebhook)
 | 
			
		||||
			addWebhookAddRoutes()
 | 
			
		||||
			m.Group("/{id}", func() {
 | 
			
		||||
				m.Get("", repo.WebHooksEdit)
 | 
			
		||||
				m.Post("/replay/{uuid}", repo.ReplayWebhook)
 | 
			
		||||
				m.Get("", repo_setting.WebHooksEdit)
 | 
			
		||||
				m.Post("/replay/{uuid}", repo_setting.ReplayWebhook)
 | 
			
		||||
			})
 | 
			
		||||
			addWebhookEditRoutes()
 | 
			
		||||
		}, webhooksEnabled)
 | 
			
		||||
@@ -604,8 +604,8 @@ func registerRoutes(m *web.Route) {
 | 
			
		||||
			m.Get("", admin.DefaultOrSystemWebhooks)
 | 
			
		||||
			m.Post("/delete", admin.DeleteDefaultOrSystemWebhook)
 | 
			
		||||
			m.Group("/{id}", func() {
 | 
			
		||||
				m.Get("", repo.WebHooksEdit)
 | 
			
		||||
				m.Post("/replay/{uuid}", repo.ReplayWebhook)
 | 
			
		||||
				m.Get("", repo_setting.WebHooksEdit)
 | 
			
		||||
				m.Post("/replay/{uuid}", repo_setting.ReplayWebhook)
 | 
			
		||||
			})
 | 
			
		||||
			addWebhookEditRoutes()
 | 
			
		||||
		}, webhooksEnabled)
 | 
			
		||||
@@ -752,8 +752,8 @@ func registerRoutes(m *web.Route) {
 | 
			
		||||
					m.Post("/delete", org.DeleteWebhook)
 | 
			
		||||
					addWebhookAddRoutes()
 | 
			
		||||
					m.Group("/{id}", func() {
 | 
			
		||||
						m.Get("", repo.WebHooksEdit)
 | 
			
		||||
						m.Post("/replay/{uuid}", repo.ReplayWebhook)
 | 
			
		||||
						m.Get("", repo_setting.WebHooksEdit)
 | 
			
		||||
						m.Post("/replay/{uuid}", repo_setting.ReplayWebhook)
 | 
			
		||||
					})
 | 
			
		||||
					addWebhookEditRoutes()
 | 
			
		||||
				}, webhooksEnabled)
 | 
			
		||||
@@ -874,78 +874,78 @@ func registerRoutes(m *web.Route) {
 | 
			
		||||
	m.Group("/{username}/{reponame}", func() {
 | 
			
		||||
		m.Group("/settings", func() {
 | 
			
		||||
			m.Group("", func() {
 | 
			
		||||
				m.Combo("").Get(repo.Settings).
 | 
			
		||||
					Post(web.Bind(forms.RepoSettingForm{}), repo.SettingsPost)
 | 
			
		||||
			}, repo.SettingsCtxData)
 | 
			
		||||
			m.Post("/avatar", web.Bind(forms.AvatarForm{}), repo.SettingsAvatar)
 | 
			
		||||
			m.Post("/avatar/delete", repo.SettingsDeleteAvatar)
 | 
			
		||||
				m.Combo("").Get(repo_setting.Settings).
 | 
			
		||||
					Post(web.Bind(forms.RepoSettingForm{}), repo_setting.SettingsPost)
 | 
			
		||||
			}, repo_setting.SettingsCtxData)
 | 
			
		||||
			m.Post("/avatar", web.Bind(forms.AvatarForm{}), repo_setting.SettingsAvatar)
 | 
			
		||||
			m.Post("/avatar/delete", repo_setting.SettingsDeleteAvatar)
 | 
			
		||||
 | 
			
		||||
			m.Group("/collaboration", func() {
 | 
			
		||||
				m.Combo("").Get(repo.Collaboration).Post(repo.CollaborationPost)
 | 
			
		||||
				m.Post("/access_mode", repo.ChangeCollaborationAccessMode)
 | 
			
		||||
				m.Post("/delete", repo.DeleteCollaboration)
 | 
			
		||||
				m.Combo("").Get(repo_setting.Collaboration).Post(repo_setting.CollaborationPost)
 | 
			
		||||
				m.Post("/access_mode", repo_setting.ChangeCollaborationAccessMode)
 | 
			
		||||
				m.Post("/delete", repo_setting.DeleteCollaboration)
 | 
			
		||||
				m.Group("/team", func() {
 | 
			
		||||
					m.Post("", repo.AddTeamPost)
 | 
			
		||||
					m.Post("/delete", repo.DeleteTeam)
 | 
			
		||||
					m.Post("", repo_setting.AddTeamPost)
 | 
			
		||||
					m.Post("/delete", repo_setting.DeleteTeam)
 | 
			
		||||
				})
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			m.Group("/branches", func() {
 | 
			
		||||
				m.Post("/", repo.SetDefaultBranchPost)
 | 
			
		||||
				m.Post("/", repo_setting.SetDefaultBranchPost)
 | 
			
		||||
			}, repo.MustBeNotEmpty)
 | 
			
		||||
 | 
			
		||||
			m.Group("/branches", func() {
 | 
			
		||||
				m.Get("/", repo.ProtectedBranchRules)
 | 
			
		||||
				m.Combo("/edit").Get(repo.SettingsProtectedBranch).
 | 
			
		||||
					Post(web.Bind(forms.ProtectBranchForm{}), context.RepoMustNotBeArchived(), repo.SettingsProtectedBranchPost)
 | 
			
		||||
				m.Post("/{id}/delete", repo.DeleteProtectedBranchRulePost)
 | 
			
		||||
				m.Get("/", repo_setting.ProtectedBranchRules)
 | 
			
		||||
				m.Combo("/edit").Get(repo_setting.SettingsProtectedBranch).
 | 
			
		||||
					Post(web.Bind(forms.ProtectBranchForm{}), context.RepoMustNotBeArchived(), repo_setting.SettingsProtectedBranchPost)
 | 
			
		||||
				m.Post("/{id}/delete", repo_setting.DeleteProtectedBranchRulePost)
 | 
			
		||||
			}, repo.MustBeNotEmpty)
 | 
			
		||||
 | 
			
		||||
			m.Post("/rename_branch", web.Bind(forms.RenameBranchForm{}), context.RepoMustNotBeArchived(), repo.RenameBranchPost)
 | 
			
		||||
			m.Post("/rename_branch", web.Bind(forms.RenameBranchForm{}), context.RepoMustNotBeArchived(), repo_setting.RenameBranchPost)
 | 
			
		||||
 | 
			
		||||
			m.Group("/tags", func() {
 | 
			
		||||
				m.Get("", repo.Tags)
 | 
			
		||||
				m.Post("", web.Bind(forms.ProtectTagForm{}), context.RepoMustNotBeArchived(), repo.NewProtectedTagPost)
 | 
			
		||||
				m.Post("/delete", context.RepoMustNotBeArchived(), repo.DeleteProtectedTagPost)
 | 
			
		||||
				m.Get("/{id}", repo.EditProtectedTag)
 | 
			
		||||
				m.Post("/{id}", web.Bind(forms.ProtectTagForm{}), context.RepoMustNotBeArchived(), repo.EditProtectedTagPost)
 | 
			
		||||
				m.Get("", repo_setting.ProtectedTags)
 | 
			
		||||
				m.Post("", web.Bind(forms.ProtectTagForm{}), context.RepoMustNotBeArchived(), repo_setting.NewProtectedTagPost)
 | 
			
		||||
				m.Post("/delete", context.RepoMustNotBeArchived(), repo_setting.DeleteProtectedTagPost)
 | 
			
		||||
				m.Get("/{id}", repo_setting.EditProtectedTag)
 | 
			
		||||
				m.Post("/{id}", web.Bind(forms.ProtectTagForm{}), context.RepoMustNotBeArchived(), repo_setting.EditProtectedTagPost)
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			m.Group("/hooks/git", func() {
 | 
			
		||||
				m.Get("", repo.GitHooks)
 | 
			
		||||
				m.Combo("/{name}").Get(repo.GitHooksEdit).
 | 
			
		||||
					Post(repo.GitHooksEditPost)
 | 
			
		||||
				m.Get("", repo_setting.GitHooks)
 | 
			
		||||
				m.Combo("/{name}").Get(repo_setting.GitHooksEdit).
 | 
			
		||||
					Post(repo_setting.GitHooksEditPost)
 | 
			
		||||
			}, context.GitHookService())
 | 
			
		||||
 | 
			
		||||
			m.Group("/hooks", func() {
 | 
			
		||||
				m.Get("", repo.Webhooks)
 | 
			
		||||
				m.Post("/delete", repo.DeleteWebhook)
 | 
			
		||||
				m.Get("", repo_setting.Webhooks)
 | 
			
		||||
				m.Post("/delete", repo_setting.DeleteWebhook)
 | 
			
		||||
				addWebhookAddRoutes()
 | 
			
		||||
				m.Group("/{id}", func() {
 | 
			
		||||
					m.Get("", repo.WebHooksEdit)
 | 
			
		||||
					m.Post("/test", repo.TestWebhook)
 | 
			
		||||
					m.Post("/replay/{uuid}", repo.ReplayWebhook)
 | 
			
		||||
					m.Get("", repo_setting.WebHooksEdit)
 | 
			
		||||
					m.Post("/test", repo_setting.TestWebhook)
 | 
			
		||||
					m.Post("/replay/{uuid}", repo_setting.ReplayWebhook)
 | 
			
		||||
				})
 | 
			
		||||
				addWebhookEditRoutes()
 | 
			
		||||
			}, webhooksEnabled)
 | 
			
		||||
 | 
			
		||||
			m.Group("/keys", func() {
 | 
			
		||||
				m.Combo("").Get(repo.DeployKeys).
 | 
			
		||||
					Post(web.Bind(forms.AddKeyForm{}), repo.DeployKeysPost)
 | 
			
		||||
				m.Post("/delete", repo.DeleteDeployKey)
 | 
			
		||||
				m.Combo("").Get(repo_setting.DeployKeys).
 | 
			
		||||
					Post(web.Bind(forms.AddKeyForm{}), repo_setting.DeployKeysPost)
 | 
			
		||||
				m.Post("/delete", repo_setting.DeleteDeployKey)
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			m.Group("/lfs", func() {
 | 
			
		||||
				m.Get("/", repo.LFSFiles)
 | 
			
		||||
				m.Get("/show/{oid}", repo.LFSFileGet)
 | 
			
		||||
				m.Post("/delete/{oid}", repo.LFSDelete)
 | 
			
		||||
				m.Get("/pointers", repo.LFSPointerFiles)
 | 
			
		||||
				m.Post("/pointers/associate", repo.LFSAutoAssociate)
 | 
			
		||||
				m.Get("/find", repo.LFSFileFind)
 | 
			
		||||
				m.Get("/", repo_setting.LFSFiles)
 | 
			
		||||
				m.Get("/show/{oid}", repo_setting.LFSFileGet)
 | 
			
		||||
				m.Post("/delete/{oid}", repo_setting.LFSDelete)
 | 
			
		||||
				m.Get("/pointers", repo_setting.LFSPointerFiles)
 | 
			
		||||
				m.Post("/pointers/associate", repo_setting.LFSAutoAssociate)
 | 
			
		||||
				m.Get("/find", repo_setting.LFSFileFind)
 | 
			
		||||
				m.Group("/locks", func() {
 | 
			
		||||
					m.Get("/", repo.LFSLocks)
 | 
			
		||||
					m.Post("/", repo.LFSLockFile)
 | 
			
		||||
					m.Post("/{lid}/unlock", repo.LFSUnlock)
 | 
			
		||||
					m.Get("/", repo_setting.LFSLocks)
 | 
			
		||||
					m.Post("/", repo_setting.LFSLockFile)
 | 
			
		||||
					m.Post("/{lid}/unlock", repo_setting.LFSUnlock)
 | 
			
		||||
				})
 | 
			
		||||
			})
 | 
			
		||||
			m.Group("/actions", func() {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user