aboutsummaryrefslogtreecommitdiff
path: root/internal/route/repo/setting.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/route/repo/setting.go')
-rw-r--r--internal/route/repo/setting.go695
1 files changed, 695 insertions, 0 deletions
diff --git a/internal/route/repo/setting.go b/internal/route/repo/setting.go
new file mode 100644
index 00000000..e0305702
--- /dev/null
+++ b/internal/route/repo/setting.go
@@ -0,0 +1,695 @@
+// Copyright 2014 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package repo
+
+import (
+ "fmt"
+ "io/ioutil"
+ "strings"
+ "time"
+
+ "github.com/gogs/git-module"
+ "github.com/unknwon/com"
+ log "gopkg.in/clog.v1"
+
+ "gogs.io/gogs/internal/context"
+ "gogs.io/gogs/internal/db"
+ "gogs.io/gogs/internal/db/errors"
+ "gogs.io/gogs/internal/form"
+ "gogs.io/gogs/internal/mailer"
+ "gogs.io/gogs/internal/setting"
+ "gogs.io/gogs/internal/tool"
+)
+
+const (
+ SETTINGS_OPTIONS = "repo/settings/options"
+ SETTINGS_REPO_AVATAR = "repo/settings/avatar"
+ SETTINGS_COLLABORATION = "repo/settings/collaboration"
+ SETTINGS_BRANCHES = "repo/settings/branches"
+ SETTINGS_PROTECTED_BRANCH = "repo/settings/protected_branch"
+ SETTINGS_GITHOOKS = "repo/settings/githooks"
+ SETTINGS_GITHOOK_EDIT = "repo/settings/githook_edit"
+ SETTINGS_DEPLOY_KEYS = "repo/settings/deploy_keys"
+)
+
+func Settings(c *context.Context) {
+ c.Title("repo.settings")
+ c.PageIs("SettingsOptions")
+ c.RequireAutosize()
+ c.Success(SETTINGS_OPTIONS)
+}
+
+func SettingsPost(c *context.Context, f form.RepoSetting) {
+ c.Title("repo.settings")
+ c.PageIs("SettingsOptions")
+ c.RequireAutosize()
+
+ repo := c.Repo.Repository
+
+ switch c.Query("action") {
+ case "update":
+ if c.HasError() {
+ c.Success(SETTINGS_OPTIONS)
+ return
+ }
+
+ isNameChanged := false
+ oldRepoName := repo.Name
+ newRepoName := f.RepoName
+ // Check if repository name has been changed.
+ if repo.LowerName != strings.ToLower(newRepoName) {
+ isNameChanged = true
+ if err := db.ChangeRepositoryName(c.Repo.Owner, repo.Name, newRepoName); err != nil {
+ c.FormErr("RepoName")
+ switch {
+ case db.IsErrRepoAlreadyExist(err):
+ c.RenderWithErr(c.Tr("form.repo_name_been_taken"), SETTINGS_OPTIONS, &f)
+ case db.IsErrNameReserved(err):
+ c.RenderWithErr(c.Tr("repo.form.name_reserved", err.(db.ErrNameReserved).Name), SETTINGS_OPTIONS, &f)
+ case db.IsErrNamePatternNotAllowed(err):
+ c.RenderWithErr(c.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), SETTINGS_OPTIONS, &f)
+ default:
+ c.ServerError("ChangeRepositoryName", err)
+ }
+ return
+ }
+
+ log.Trace("Repository name changed: %s/%s -> %s", c.Repo.Owner.Name, repo.Name, newRepoName)
+ }
+ // In case it's just a case change.
+ repo.Name = newRepoName
+ repo.LowerName = strings.ToLower(newRepoName)
+
+ repo.Description = f.Description
+ repo.Website = f.Website
+
+ // Visibility of forked repository is forced sync with base repository.
+ if repo.IsFork {
+ f.Private = repo.BaseRepo.IsPrivate
+ }
+
+ visibilityChanged := repo.IsPrivate != f.Private
+ repo.IsPrivate = f.Private
+ if err := db.UpdateRepository(repo, visibilityChanged); err != nil {
+ c.ServerError("UpdateRepository", err)
+ return
+ }
+ log.Trace("Repository basic settings updated: %s/%s", c.Repo.Owner.Name, repo.Name)
+
+ if isNameChanged {
+ if err := db.RenameRepoAction(c.User, oldRepoName, repo); err != nil {
+ log.Error(2, "RenameRepoAction: %v", err)
+ }
+ }
+
+ c.Flash.Success(c.Tr("repo.settings.update_settings_success"))
+ c.Redirect(repo.Link() + "/settings")
+
+ case "mirror":
+ if !repo.IsMirror {
+ c.NotFound()
+ return
+ }
+
+ if f.Interval > 0 {
+ c.Repo.Mirror.EnablePrune = f.EnablePrune
+ c.Repo.Mirror.Interval = f.Interval
+ c.Repo.Mirror.NextSync = time.Now().Add(time.Duration(f.Interval) * time.Hour)
+ if err := db.UpdateMirror(c.Repo.Mirror); err != nil {
+ c.ServerError("UpdateMirror", err)
+ return
+ }
+ }
+ if err := c.Repo.Mirror.SaveAddress(f.MirrorAddress); err != nil {
+ c.ServerError("SaveAddress", err)
+ return
+ }
+
+ c.Flash.Success(c.Tr("repo.settings.update_settings_success"))
+ c.Redirect(repo.Link() + "/settings")
+
+ case "mirror-sync":
+ if !repo.IsMirror {
+ c.NotFound()
+ return
+ }
+
+ go db.MirrorQueue.Add(repo.ID)
+ c.Flash.Info(c.Tr("repo.settings.mirror_sync_in_progress"))
+ c.Redirect(repo.Link() + "/settings")
+
+ case "advanced":
+ repo.EnableWiki = f.EnableWiki
+ repo.AllowPublicWiki = f.AllowPublicWiki
+ repo.EnableExternalWiki = f.EnableExternalWiki
+ repo.ExternalWikiURL = f.ExternalWikiURL
+ repo.EnableIssues = f.EnableIssues
+ repo.AllowPublicIssues = f.AllowPublicIssues
+ repo.EnableExternalTracker = f.EnableExternalTracker
+ repo.ExternalTrackerURL = f.ExternalTrackerURL
+ repo.ExternalTrackerFormat = f.TrackerURLFormat
+ repo.ExternalTrackerStyle = f.TrackerIssueStyle
+ repo.EnablePulls = f.EnablePulls
+ repo.PullsIgnoreWhitespace = f.PullsIgnoreWhitespace
+ repo.PullsAllowRebase = f.PullsAllowRebase
+
+ if err := db.UpdateRepository(repo, false); err != nil {
+ c.ServerError("UpdateRepository", err)
+ return
+ }
+ log.Trace("Repository advanced settings updated: %s/%s", c.Repo.Owner.Name, repo.Name)
+
+ c.Flash.Success(c.Tr("repo.settings.update_settings_success"))
+ c.Redirect(c.Repo.RepoLink + "/settings")
+
+ case "convert":
+ if !c.Repo.IsOwner() {
+ c.NotFound()
+ return
+ }
+ if repo.Name != f.RepoName {
+ c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
+ return
+ }
+
+ if c.Repo.Owner.IsOrganization() {
+ if !c.Repo.Owner.IsOwnedBy(c.User.ID) {
+ c.NotFound()
+ return
+ }
+ }
+
+ if !repo.IsMirror {
+ c.NotFound()
+ return
+ }
+ repo.IsMirror = false
+
+ if _, err := db.CleanUpMigrateInfo(repo); err != nil {
+ c.ServerError("CleanUpMigrateInfo", err)
+ return
+ } else if err = db.DeleteMirrorByRepoID(c.Repo.Repository.ID); err != nil {
+ c.ServerError("DeleteMirrorByRepoID", err)
+ return
+ }
+ log.Trace("Repository converted from mirror to regular: %s/%s", c.Repo.Owner.Name, repo.Name)
+ c.Flash.Success(c.Tr("repo.settings.convert_succeed"))
+ c.Redirect(setting.AppSubURL + "/" + c.Repo.Owner.Name + "/" + repo.Name)
+
+ case "transfer":
+ if !c.Repo.IsOwner() {
+ c.NotFound()
+ return
+ }
+ if repo.Name != f.RepoName {
+ c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
+ return
+ }
+
+ if c.Repo.Owner.IsOrganization() && !c.User.IsAdmin {
+ if !c.Repo.Owner.IsOwnedBy(c.User.ID) {
+ c.NotFound()
+ return
+ }
+ }
+
+ newOwner := c.Query("new_owner_name")
+ isExist, err := db.IsUserExist(0, newOwner)
+ if err != nil {
+ c.ServerError("IsUserExist", err)
+ return
+ } else if !isExist {
+ c.RenderWithErr(c.Tr("form.enterred_invalid_owner_name"), SETTINGS_OPTIONS, nil)
+ return
+ }
+
+ if err = db.TransferOwnership(c.User, newOwner, repo); err != nil {
+ if db.IsErrRepoAlreadyExist(err) {
+ c.RenderWithErr(c.Tr("repo.settings.new_owner_has_same_repo"), SETTINGS_OPTIONS, nil)
+ } else {
+ c.ServerError("TransferOwnership", err)
+ }
+ return
+ }
+ log.Trace("Repository transfered: %s/%s -> %s", c.Repo.Owner.Name, repo.Name, newOwner)
+ c.Flash.Success(c.Tr("repo.settings.transfer_succeed"))
+ c.Redirect(setting.AppSubURL + "/" + newOwner + "/" + repo.Name)
+
+ case "delete":
+ if !c.Repo.IsOwner() {
+ c.NotFound()
+ return
+ }
+ if repo.Name != f.RepoName {
+ c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
+ return
+ }
+
+ if c.Repo.Owner.IsOrganization() && !c.User.IsAdmin {
+ if !c.Repo.Owner.IsOwnedBy(c.User.ID) {
+ c.NotFound()
+ return
+ }
+ }
+
+ if err := db.DeleteRepository(c.Repo.Owner.ID, repo.ID); err != nil {
+ c.ServerError("DeleteRepository", err)
+ return
+ }
+ log.Trace("Repository deleted: %s/%s", c.Repo.Owner.Name, repo.Name)
+
+ c.Flash.Success(c.Tr("repo.settings.deletion_success"))
+ c.Redirect(c.Repo.Owner.DashboardLink())
+
+ case "delete-wiki":
+ if !c.Repo.IsOwner() {
+ c.NotFound()
+ return
+ }
+ if repo.Name != f.RepoName {
+ c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
+ return
+ }
+
+ if c.Repo.Owner.IsOrganization() && !c.User.IsAdmin {
+ if !c.Repo.Owner.IsOwnedBy(c.User.ID) {
+ c.NotFound()
+ return
+ }
+ }
+
+ repo.DeleteWiki()
+ log.Trace("Repository wiki deleted: %s/%s", c.Repo.Owner.Name, repo.Name)
+
+ repo.EnableWiki = false
+ if err := db.UpdateRepository(repo, false); err != nil {
+ c.ServerError("UpdateRepository", err)
+ return
+ }
+
+ c.Flash.Success(c.Tr("repo.settings.wiki_deletion_success"))
+ c.Redirect(c.Repo.RepoLink + "/settings")
+
+ default:
+ c.NotFound()
+ }
+}
+
+func SettingsAvatar(c *context.Context) {
+ c.Title("settings.avatar")
+ c.PageIs("SettingsAvatar")
+ c.Success(SETTINGS_REPO_AVATAR)
+}
+
+func SettingsAvatarPost(c *context.Context, f form.Avatar) {
+ f.Source = form.AVATAR_LOCAL
+ if err := UpdateAvatarSetting(c, f, c.Repo.Repository); err != nil {
+ c.Flash.Error(err.Error())
+ } else {
+ c.Flash.Success(c.Tr("settings.update_avatar_success"))
+ }
+ c.SubURLRedirect(c.Repo.RepoLink + "/settings")
+}
+
+func SettingsDeleteAvatar(c *context.Context) {
+ if err := c.Repo.Repository.DeleteAvatar(); err != nil {
+ c.Flash.Error(fmt.Sprintf("Failed to delete avatar: %v", err))
+ }
+ c.SubURLRedirect(c.Repo.RepoLink + "/settings")
+}
+
+// FIXME: limit upload size
+func UpdateAvatarSetting(c *context.Context, f form.Avatar, ctxRepo *db.Repository) error {
+ ctxRepo.UseCustomAvatar = true
+ if f.Avatar != nil {
+ r, err := f.Avatar.Open()
+ if err != nil {
+ return fmt.Errorf("open avatar reader: %v", err)
+ }
+ defer r.Close()
+
+ data, err := ioutil.ReadAll(r)
+ if err != nil {
+ return fmt.Errorf("read avatar content: %v", err)
+ }
+ if !tool.IsImageFile(data) {
+ return errors.New(c.Tr("settings.uploaded_avatar_not_a_image"))
+ }
+ if err = ctxRepo.UploadAvatar(data); err != nil {
+ return fmt.Errorf("upload avatar: %v", err)
+ }
+ } else {
+ // No avatar is uploaded and reset setting back.
+ if !com.IsFile(ctxRepo.CustomAvatarPath()) {
+ ctxRepo.UseCustomAvatar = false
+ }
+ }
+
+ if err := db.UpdateRepository(ctxRepo, false); err != nil {
+ return fmt.Errorf("update repository: %v", err)
+ }
+
+ return nil
+}
+
+func SettingsCollaboration(c *context.Context) {
+ c.Data["Title"] = c.Tr("repo.settings")
+ c.Data["PageIsSettingsCollaboration"] = true
+
+ users, err := c.Repo.Repository.GetCollaborators()
+ if err != nil {
+ c.Handle(500, "GetCollaborators", err)
+ return
+ }
+ c.Data["Collaborators"] = users
+
+ c.HTML(200, SETTINGS_COLLABORATION)
+}
+
+func SettingsCollaborationPost(c *context.Context) {
+ name := strings.ToLower(c.Query("collaborator"))
+ if len(name) == 0 || c.Repo.Owner.LowerName == name {
+ c.Redirect(setting.AppSubURL + c.Req.URL.Path)
+ return
+ }
+
+ u, err := db.GetUserByName(name)
+ if err != nil {
+ if errors.IsUserNotExist(err) {
+ c.Flash.Error(c.Tr("form.user_not_exist"))
+ c.Redirect(setting.AppSubURL + c.Req.URL.Path)
+ } else {
+ c.Handle(500, "GetUserByName", err)
+ }
+ return
+ }
+
+ // Organization is not allowed to be added as a collaborator
+ if u.IsOrganization() {
+ c.Flash.Error(c.Tr("repo.settings.org_not_allowed_to_be_collaborator"))
+ c.Redirect(setting.AppSubURL + c.Req.URL.Path)
+ return
+ }
+
+ if err = c.Repo.Repository.AddCollaborator(u); err != nil {
+ c.Handle(500, "AddCollaborator", err)
+ return
+ }
+
+ if setting.Service.EnableNotifyMail {
+ mailer.SendCollaboratorMail(db.NewMailerUser(u), db.NewMailerUser(c.User), db.NewMailerRepo(c.Repo.Repository))
+ }
+
+ c.Flash.Success(c.Tr("repo.settings.add_collaborator_success"))
+ c.Redirect(setting.AppSubURL + c.Req.URL.Path)
+}
+
+func ChangeCollaborationAccessMode(c *context.Context) {
+ if err := c.Repo.Repository.ChangeCollaborationAccessMode(
+ c.QueryInt64("uid"),
+ db.AccessMode(c.QueryInt("mode"))); err != nil {
+ log.Error(2, "ChangeCollaborationAccessMode: %v", err)
+ return
+ }
+
+ c.Status(204)
+}
+
+func DeleteCollaboration(c *context.Context) {
+ if err := c.Repo.Repository.DeleteCollaboration(c.QueryInt64("id")); err != nil {
+ c.Flash.Error("DeleteCollaboration: " + err.Error())
+ } else {
+ c.Flash.Success(c.Tr("repo.settings.remove_collaborator_success"))
+ }
+
+ c.JSON(200, map[string]interface{}{
+ "redirect": c.Repo.RepoLink + "/settings/collaboration",
+ })
+}
+
+func SettingsBranches(c *context.Context) {
+ c.Data["Title"] = c.Tr("repo.settings.branches")
+ c.Data["PageIsSettingsBranches"] = true
+
+ if c.Repo.Repository.IsBare {
+ c.Flash.Info(c.Tr("repo.settings.branches_bare"), true)
+ c.HTML(200, SETTINGS_BRANCHES)
+ return
+ }
+
+ protectBranches, err := db.GetProtectBranchesByRepoID(c.Repo.Repository.ID)
+ if err != nil {
+ c.Handle(500, "GetProtectBranchesByRepoID", err)
+ return
+ }
+
+ // Filter out deleted branches
+ branches := make([]string, 0, len(protectBranches))
+ for i := range protectBranches {
+ if c.Repo.GitRepo.IsBranchExist(protectBranches[i].Name) {
+ branches = append(branches, protectBranches[i].Name)
+ }
+ }
+ c.Data["ProtectBranches"] = branches
+
+ c.HTML(200, SETTINGS_BRANCHES)
+}
+
+func UpdateDefaultBranch(c *context.Context) {
+ branch := c.Query("branch")
+ if c.Repo.GitRepo.IsBranchExist(branch) &&
+ c.Repo.Repository.DefaultBranch != branch {
+ c.Repo.Repository.DefaultBranch = branch
+ if err := c.Repo.GitRepo.SetDefaultBranch(branch); err != nil {
+ if !git.IsErrUnsupportedVersion(err) {
+ c.Handle(500, "SetDefaultBranch", err)
+ return
+ }
+
+ c.Flash.Warning(c.Tr("repo.settings.update_default_branch_unsupported"))
+ c.Redirect(c.Repo.RepoLink + "/settings/branches")
+ return
+ }
+ }
+
+ if err := db.UpdateRepository(c.Repo.Repository, false); err != nil {
+ c.Handle(500, "UpdateRepository", err)
+ return
+ }
+
+ c.Flash.Success(c.Tr("repo.settings.update_default_branch_success"))
+ c.Redirect(c.Repo.RepoLink + "/settings/branches")
+}
+
+func SettingsProtectedBranch(c *context.Context) {
+ branch := c.Params("*")
+ if !c.Repo.GitRepo.IsBranchExist(branch) {
+ c.NotFound()
+ return
+ }
+
+ c.Data["Title"] = c.Tr("repo.settings.protected_branches") + " - " + branch
+ c.Data["PageIsSettingsBranches"] = true
+
+ protectBranch, err := db.GetProtectBranchOfRepoByName(c.Repo.Repository.ID, branch)
+ if err != nil {
+ if !errors.IsErrBranchNotExist(err) {
+ c.Handle(500, "GetProtectBranchOfRepoByName", err)
+ return
+ }
+
+ // No options found, create defaults.
+ protectBranch = &db.ProtectBranch{
+ Name: branch,
+ }
+ }
+
+ if c.Repo.Owner.IsOrganization() {
+ users, err := c.Repo.Repository.GetWriters()
+ if err != nil {
+ c.Handle(500, "Repo.Repository.GetPushers", err)
+ return
+ }
+ c.Data["Users"] = users
+ c.Data["whitelist_users"] = protectBranch.WhitelistUserIDs
+
+ teams, err := c.Repo.Owner.TeamsHaveAccessToRepo(c.Repo.Repository.ID, db.ACCESS_MODE_WRITE)
+ if err != nil {
+ c.Handle(500, "Repo.Owner.TeamsHaveAccessToRepo", err)
+ return
+ }
+ c.Data["Teams"] = teams
+ c.Data["whitelist_teams"] = protectBranch.WhitelistTeamIDs
+ }
+
+ c.Data["Branch"] = protectBranch
+ c.HTML(200, SETTINGS_PROTECTED_BRANCH)
+}
+
+func SettingsProtectedBranchPost(c *context.Context, f form.ProtectBranch) {
+ branch := c.Params("*")
+ if !c.Repo.GitRepo.IsBranchExist(branch) {
+ c.NotFound()
+ return
+ }
+
+ protectBranch, err := db.GetProtectBranchOfRepoByName(c.Repo.Repository.ID, branch)
+ if err != nil {
+ if !errors.IsErrBranchNotExist(err) {
+ c.Handle(500, "GetProtectBranchOfRepoByName", err)
+ return
+ }
+
+ // No options found, create defaults.
+ protectBranch = &db.ProtectBranch{
+ RepoID: c.Repo.Repository.ID,
+ Name: branch,
+ }
+ }
+
+ protectBranch.Protected = f.Protected
+ protectBranch.RequirePullRequest = f.RequirePullRequest
+ protectBranch.EnableWhitelist = f.EnableWhitelist
+ if c.Repo.Owner.IsOrganization() {
+ err = db.UpdateOrgProtectBranch(c.Repo.Repository, protectBranch, f.WhitelistUsers, f.WhitelistTeams)
+ } else {
+ err = db.UpdateProtectBranch(protectBranch)
+ }
+ if err != nil {
+ c.Handle(500, "UpdateOrgProtectBranch/UpdateProtectBranch", err)
+ return
+ }
+
+ c.Flash.Success(c.Tr("repo.settings.update_protect_branch_success"))
+ c.Redirect(fmt.Sprintf("%s/settings/branches/%s", c.Repo.RepoLink, branch))
+}
+
+func SettingsGitHooks(c *context.Context) {
+ c.Data["Title"] = c.Tr("repo.settings.githooks")
+ c.Data["PageIsSettingsGitHooks"] = true
+
+ hooks, err := c.Repo.GitRepo.Hooks()
+ if err != nil {
+ c.Handle(500, "Hooks", err)
+ return
+ }
+ c.Data["Hooks"] = hooks
+
+ c.HTML(200, SETTINGS_GITHOOKS)
+}
+
+func SettingsGitHooksEdit(c *context.Context) {
+ c.Data["Title"] = c.Tr("repo.settings.githooks")
+ c.Data["PageIsSettingsGitHooks"] = true
+ c.Data["RequireSimpleMDE"] = true
+
+ name := c.Params(":name")
+ hook, err := c.Repo.GitRepo.GetHook(name)
+ if err != nil {
+ if err == git.ErrNotValidHook {
+ c.Handle(404, "GetHook", err)
+ } else {
+ c.Handle(500, "GetHook", err)
+ }
+ return
+ }
+ c.Data["Hook"] = hook
+ c.HTML(200, SETTINGS_GITHOOK_EDIT)
+}
+
+func SettingsGitHooksEditPost(c *context.Context) {
+ name := c.Params(":name")
+ hook, err := c.Repo.GitRepo.GetHook(name)
+ if err != nil {
+ if err == git.ErrNotValidHook {
+ c.Handle(404, "GetHook", err)
+ } else {
+ c.Handle(500, "GetHook", err)
+ }
+ return
+ }
+ hook.Content = c.Query("content")
+ if err = hook.Update(); err != nil {
+ c.Handle(500, "hook.Update", err)
+ return
+ }
+ c.Redirect(c.Data["Link"].(string))
+}
+
+func SettingsDeployKeys(c *context.Context) {
+ c.Data["Title"] = c.Tr("repo.settings.deploy_keys")
+ c.Data["PageIsSettingsKeys"] = true
+
+ keys, err := db.ListDeployKeys(c.Repo.Repository.ID)
+ if err != nil {
+ c.Handle(500, "ListDeployKeys", err)
+ return
+ }
+ c.Data["Deploykeys"] = keys
+
+ c.HTML(200, SETTINGS_DEPLOY_KEYS)
+}
+
+func SettingsDeployKeysPost(c *context.Context, f form.AddSSHKey) {
+ c.Data["Title"] = c.Tr("repo.settings.deploy_keys")
+ c.Data["PageIsSettingsKeys"] = true
+
+ keys, err := db.ListDeployKeys(c.Repo.Repository.ID)
+ if err != nil {
+ c.Handle(500, "ListDeployKeys", err)
+ return
+ }
+ c.Data["Deploykeys"] = keys
+
+ if c.HasError() {
+ c.HTML(200, SETTINGS_DEPLOY_KEYS)
+ return
+ }
+
+ content, err := db.CheckPublicKeyString(f.Content)
+ if err != nil {
+ if db.IsErrKeyUnableVerify(err) {
+ c.Flash.Info(c.Tr("form.unable_verify_ssh_key"))
+ } else {
+ c.Data["HasError"] = true
+ c.Data["Err_Content"] = true
+ c.Flash.Error(c.Tr("form.invalid_ssh_key", err.Error()))
+ c.Redirect(c.Repo.RepoLink + "/settings/keys")
+ return
+ }
+ }
+
+ key, err := db.AddDeployKey(c.Repo.Repository.ID, f.Title, content)
+ if err != nil {
+ c.Data["HasError"] = true
+ switch {
+ case db.IsErrKeyAlreadyExist(err):
+ c.Data["Err_Content"] = true
+ c.RenderWithErr(c.Tr("repo.settings.key_been_used"), SETTINGS_DEPLOY_KEYS, &f)
+ case db.IsErrKeyNameAlreadyUsed(err):
+ c.Data["Err_Title"] = true
+ c.RenderWithErr(c.Tr("repo.settings.key_name_used"), SETTINGS_DEPLOY_KEYS, &f)
+ default:
+ c.Handle(500, "AddDeployKey", err)
+ }
+ return
+ }
+
+ log.Trace("Deploy key added: %d", c.Repo.Repository.ID)
+ c.Flash.Success(c.Tr("repo.settings.add_key_success", key.Name))
+ c.Redirect(c.Repo.RepoLink + "/settings/keys")
+}
+
+func DeleteDeployKey(c *context.Context) {
+ if err := db.DeleteDeployKey(c.User, c.QueryInt64("id")); err != nil {
+ c.Flash.Error("DeleteDeployKey: " + err.Error())
+ } else {
+ c.Flash.Success(c.Tr("repo.settings.deploy_key_deletion_success"))
+ }
+
+ c.JSON(200, map[string]interface{}{
+ "redirect": c.Repo.RepoLink + "/settings/keys",
+ })
+}