mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 09:31:53 +01: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:
		
							parent
							
								
									cea9401634
								
							
						
					
					
						commit
						aab7cb6750
					
				
							
								
								
									
										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() { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user