setting.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. package repo
  2. import (
  3. "fmt"
  4. "gitote/gitote/models"
  5. "gitote/gitote/models/errors"
  6. "gitote/gitote/pkg/context"
  7. "gitote/gitote/pkg/form"
  8. "gitote/gitote/pkg/mailer"
  9. "gitote/gitote/pkg/setting"
  10. "gitote/gitote/pkg/tool"
  11. "io/ioutil"
  12. "strings"
  13. "time"
  14. "github.com/Unknwon/com"
  15. raven "github.com/getsentry/raven-go"
  16. "gitlab.com/gitote/git-module"
  17. log "gopkg.in/clog.v1"
  18. )
  19. const (
  20. SETTINGS_OPTIONS = "repo/settings/options"
  21. SETTINGS_REPO_AVATAR = "repo/settings/avatar"
  22. SETTINGS_COLLABORATION = "repo/settings/collaboration"
  23. SETTINGS_BRANCHES = "repo/settings/branches"
  24. SETTINGS_PROTECTED_BRANCH = "repo/settings/protected_branch"
  25. SETTINGS_GITHOOKS = "repo/settings/githooks"
  26. SETTINGS_GITHOOK_EDIT = "repo/settings/githook_edit"
  27. SETTINGS_DEPLOY_KEYS = "repo/settings/deploy_keys"
  28. )
  29. func Settings(c *context.Context) {
  30. c.Title("repo.settings")
  31. c.PageIs("SettingsOptions")
  32. c.RequireAutosize()
  33. c.Success(SETTINGS_OPTIONS)
  34. }
  35. func SettingsPost(c *context.Context, f form.RepoSetting) {
  36. c.Title("repo.settings")
  37. c.PageIs("SettingsOptions")
  38. c.RequireAutosize()
  39. repo := c.Repo.Repository
  40. switch c.Query("action") {
  41. case "update":
  42. if c.HasError() {
  43. c.Success(SETTINGS_OPTIONS)
  44. return
  45. }
  46. isNameChanged := false
  47. oldRepoName := repo.Name
  48. newRepoName := f.RepoName
  49. // Check if repository name has been changed.
  50. if repo.LowerName != strings.ToLower(newRepoName) {
  51. isNameChanged = true
  52. if err := models.ChangeRepositoryName(c.Repo.Owner, repo.Name, newRepoName); err != nil {
  53. c.FormErr("RepoName")
  54. switch {
  55. case models.IsErrRepoAlreadyExist(err):
  56. c.RenderWithErr(c.Tr("form.repo_name_been_taken"), SETTINGS_OPTIONS, &f)
  57. case models.IsErrNameReserved(err):
  58. c.RenderWithErr(c.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), SETTINGS_OPTIONS, &f)
  59. case models.IsErrNamePatternNotAllowed(err):
  60. c.RenderWithErr(c.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), SETTINGS_OPTIONS, &f)
  61. default:
  62. c.ServerError("ChangeRepositoryName", err)
  63. }
  64. return
  65. }
  66. log.Trace("Repository name changed: %s/%s -> %s", c.Repo.Owner.Name, repo.Name, newRepoName)
  67. }
  68. // In case it's just a case change.
  69. repo.Name = newRepoName
  70. repo.LowerName = strings.ToLower(newRepoName)
  71. repo.Description = f.Description
  72. repo.Website = f.Website
  73. repo.DonateURL = f.DonateURL
  74. repo.DonateBadge = f.DonateBadge
  75. // Visibility of forked repository is forced sync with base repository.
  76. if repo.IsFork {
  77. f.Private = repo.BaseRepo.IsPrivate
  78. }
  79. visibilityChanged := repo.IsPrivate != f.Private
  80. repo.IsPrivate = f.Private
  81. if err := models.UpdateRepository(repo, visibilityChanged); err != nil {
  82. c.ServerError("UpdateRepository", err)
  83. return
  84. }
  85. log.Trace("Repository basic settings updated: %s/%s", c.Repo.Owner.Name, repo.Name)
  86. if isNameChanged {
  87. if err := models.RenameRepoAction(c.User, oldRepoName, repo); err != nil {
  88. raven.CaptureErrorAndWait(err, nil)
  89. log.Error(2, "RenameRepoAction: %v", err)
  90. }
  91. }
  92. c.Flash.Success(c.Tr("repo.settings.update_settings_success"))
  93. c.Redirect(repo.Link() + "/settings")
  94. case "mirror":
  95. if !repo.IsMirror {
  96. c.NotFound()
  97. return
  98. }
  99. if f.Interval > 0 {
  100. c.Repo.Mirror.EnablePrune = f.EnablePrune
  101. c.Repo.Mirror.Interval = f.Interval
  102. c.Repo.Mirror.NextSync = time.Now().Add(time.Duration(f.Interval) * time.Hour)
  103. if err := models.UpdateMirror(c.Repo.Mirror); err != nil {
  104. c.ServerError("UpdateMirror", err)
  105. return
  106. }
  107. }
  108. if err := c.Repo.Mirror.SaveAddress(f.MirrorAddress); err != nil {
  109. c.ServerError("SaveAddress", err)
  110. return
  111. }
  112. c.Flash.Success(c.Tr("repo.settings.update_settings_success"))
  113. c.Redirect(repo.Link() + "/settings")
  114. case "mirror-sync":
  115. if !repo.IsMirror {
  116. c.NotFound()
  117. return
  118. }
  119. go models.MirrorQueue.Add(repo.ID)
  120. c.Flash.Info(c.Tr("repo.settings.mirror_sync_in_progress"))
  121. c.Redirect(repo.Link() + "/settings")
  122. case "advanced":
  123. repo.EnableWiki = f.EnableWiki
  124. repo.AllowPublicWiki = f.AllowPublicWiki
  125. repo.EnableExternalWiki = f.EnableExternalWiki
  126. repo.ExternalWikiURL = f.ExternalWikiURL
  127. repo.EnableIssues = f.EnableIssues
  128. repo.AllowPublicIssues = f.AllowPublicIssues
  129. repo.EnableExternalTracker = f.EnableExternalTracker
  130. repo.ExternalTrackerURL = f.ExternalTrackerURL
  131. repo.ExternalTrackerFormat = f.TrackerURLFormat
  132. repo.ExternalTrackerStyle = f.TrackerIssueStyle
  133. repo.EnablePulls = f.EnablePulls
  134. repo.PullsIgnoreWhitespace = f.PullsIgnoreWhitespace
  135. repo.PullsAllowRebase = f.PullsAllowRebase
  136. if err := models.UpdateRepository(repo, false); err != nil {
  137. c.ServerError("UpdateRepository", err)
  138. return
  139. }
  140. log.Trace("Repository advanced settings updated: %s/%s", c.Repo.Owner.Name, repo.Name)
  141. c.Flash.Success(c.Tr("repo.settings.update_settings_success"))
  142. c.Redirect(c.Repo.RepoLink + "/settings")
  143. case "convert":
  144. if !c.Repo.IsOwner() {
  145. c.NotFound()
  146. return
  147. }
  148. if repo.Name != f.RepoName {
  149. c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
  150. return
  151. }
  152. if c.Repo.Owner.IsOrganization() {
  153. if !c.Repo.Owner.IsOwnedBy(c.User.ID) {
  154. c.NotFound()
  155. return
  156. }
  157. }
  158. if !repo.IsMirror {
  159. c.NotFound()
  160. return
  161. }
  162. repo.IsMirror = false
  163. if _, err := models.CleanUpMigrateInfo(repo); err != nil {
  164. c.ServerError("CleanUpMigrateInfo", err)
  165. return
  166. } else if err = models.DeleteMirrorByRepoID(c.Repo.Repository.ID); err != nil {
  167. c.ServerError("DeleteMirrorByRepoID", err)
  168. return
  169. }
  170. log.Trace("Repository converted from mirror to regular: %s/%s", c.Repo.Owner.Name, repo.Name)
  171. c.Flash.Success(c.Tr("repo.settings.convert_succeed"))
  172. c.Redirect(setting.AppSubURL + "/" + c.Repo.Owner.Name + "/" + repo.Name)
  173. case "transfer":
  174. if !c.Repo.IsOwner() {
  175. c.NotFound()
  176. return
  177. }
  178. if repo.Name != f.RepoName {
  179. c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
  180. return
  181. }
  182. if c.Repo.Owner.IsOrganization() && !c.User.IsAdmin {
  183. if !c.Repo.Owner.IsOwnedBy(c.User.ID) {
  184. c.NotFound()
  185. return
  186. }
  187. }
  188. newOwner := c.Query("new_owner_name")
  189. isExist, err := models.IsUserExist(0, newOwner)
  190. if err != nil {
  191. c.ServerError("IsUserExist", err)
  192. return
  193. } else if !isExist {
  194. c.RenderWithErr(c.Tr("form.enterred_invalid_owner_name"), SETTINGS_OPTIONS, nil)
  195. return
  196. }
  197. if err = models.TransferOwnership(c.User, newOwner, repo); err != nil {
  198. if models.IsErrRepoAlreadyExist(err) {
  199. c.RenderWithErr(c.Tr("repo.settings.new_owner_has_same_repo"), SETTINGS_OPTIONS, nil)
  200. } else {
  201. c.ServerError("TransferOwnership", err)
  202. }
  203. return
  204. }
  205. log.Trace("Repository transferred: %s/%s -> %s", c.Repo.Owner.Name, repo.Name, newOwner)
  206. c.Flash.Success(c.Tr("repo.settings.transfer_succeed"))
  207. c.Redirect(setting.AppSubURL + "/" + newOwner + "/" + repo.Name)
  208. case "delete":
  209. if !c.Repo.IsOwner() {
  210. c.NotFound()
  211. return
  212. }
  213. if repo.Name != f.RepoName {
  214. c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
  215. return
  216. }
  217. if c.Repo.Owner.IsOrganization() && !c.User.IsAdmin {
  218. if !c.Repo.Owner.IsOwnedBy(c.User.ID) {
  219. c.NotFound()
  220. return
  221. }
  222. }
  223. if err := models.DeleteRepository(c.Repo.Owner.ID, repo.ID); err != nil {
  224. c.ServerError("DeleteRepository", err)
  225. return
  226. }
  227. log.Trace("Repository deleted: %s/%s", c.Repo.Owner.Name, repo.Name)
  228. c.Flash.Success(c.Tr("repo.settings.deletion_success"))
  229. c.Redirect(c.Repo.Owner.DashboardLink())
  230. case "delete-wiki":
  231. if !c.Repo.IsOwner() {
  232. c.NotFound()
  233. return
  234. }
  235. if repo.Name != f.RepoName {
  236. c.RenderWithErr(c.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
  237. return
  238. }
  239. if c.Repo.Owner.IsOrganization() && !c.User.IsAdmin {
  240. if !c.Repo.Owner.IsOwnedBy(c.User.ID) {
  241. c.NotFound()
  242. return
  243. }
  244. }
  245. repo.DeleteWiki()
  246. log.Trace("Repository wiki deleted: %s/%s", c.Repo.Owner.Name, repo.Name)
  247. repo.EnableWiki = false
  248. if err := models.UpdateRepository(repo, false); err != nil {
  249. c.ServerError("UpdateRepository", err)
  250. return
  251. }
  252. c.Flash.Success(c.Tr("repo.settings.wiki_deletion_success"))
  253. c.Redirect(c.Repo.RepoLink + "/settings")
  254. default:
  255. c.NotFound()
  256. }
  257. }
  258. func SettingsAvatar(c *context.Context) {
  259. c.Title("settings.avatar")
  260. c.PageIs("SettingsAvatar")
  261. c.Success(SETTINGS_REPO_AVATAR)
  262. }
  263. func SettingsAvatarPost(c *context.Context, f form.Avatar) {
  264. f.Source = form.AVATAR_LOCAL
  265. if err := UpdateAvatarSetting(c, f, c.Repo.Repository); err != nil {
  266. c.Flash.Error(err.Error())
  267. } else {
  268. c.Flash.Success(c.Tr("settings.update_avatar_success"))
  269. }
  270. c.SubURLRedirect(c.Repo.RepoLink + "/settings")
  271. }
  272. func SettingsDeleteAvatar(c *context.Context) {
  273. if err := c.Repo.Repository.DeleteAvatar(); err != nil {
  274. c.Flash.Error(fmt.Sprintf("Failed to delete avatar: %v", err))
  275. }
  276. c.SubURLRedirect(c.Repo.RepoLink + "/settings")
  277. }
  278. // FIXME: limit upload size
  279. func UpdateAvatarSetting(c *context.Context, f form.Avatar, ctxRepo *models.Repository) error {
  280. ctxRepo.UseCustomAvatar = true
  281. if f.Avatar != nil {
  282. r, err := f.Avatar.Open()
  283. if err != nil {
  284. return fmt.Errorf("open avatar reader: %v", err)
  285. }
  286. defer r.Close()
  287. data, err := ioutil.ReadAll(r)
  288. if err != nil {
  289. return fmt.Errorf("read avatar content: %v", err)
  290. }
  291. if !tool.IsImageFile(data) {
  292. return errors.New(c.Tr("settings.uploaded_avatar_not_a_image"))
  293. }
  294. if err = ctxRepo.UploadAvatar(data); err != nil {
  295. return fmt.Errorf("upload avatar: %v", err)
  296. }
  297. } else {
  298. // No avatar is uploaded and reset setting back.
  299. if !com.IsFile(ctxRepo.CustomAvatarPath()) {
  300. ctxRepo.UseCustomAvatar = false
  301. }
  302. }
  303. if err := models.UpdateRepository(ctxRepo, false); err != nil {
  304. return fmt.Errorf("update repository: %v", err)
  305. }
  306. return nil
  307. }
  308. func SettingsCollaboration(c *context.Context) {
  309. c.Data["Title"] = c.Tr("repo.settings")
  310. c.Data["PageIsSettingsCollaboration"] = true
  311. users, err := c.Repo.Repository.GetCollaborators()
  312. if err != nil {
  313. c.Handle(500, "GetCollaborators", err)
  314. return
  315. }
  316. c.Data["Collaborators"] = users
  317. c.HTML(200, SETTINGS_COLLABORATION)
  318. }
  319. func SettingsCollaborationPost(c *context.Context) {
  320. name := strings.ToLower(c.Query("collaborator"))
  321. if len(name) == 0 || c.Repo.Owner.LowerName == name {
  322. c.Redirect(setting.AppSubURL + c.Req.URL.Path)
  323. return
  324. }
  325. u, err := models.GetUserByName(name)
  326. if err != nil {
  327. if errors.IsUserNotExist(err) {
  328. c.Flash.Error(c.Tr("form.user_not_exist"))
  329. c.Redirect(setting.AppSubURL + c.Req.URL.Path)
  330. } else {
  331. c.Handle(500, "GetUserByName", err)
  332. }
  333. return
  334. }
  335. // Organization is not allowed to be added as a collaborator
  336. if u.IsOrganization() {
  337. c.Flash.Error(c.Tr("repo.settings.org_not_allowed_to_be_collaborator"))
  338. c.Redirect(setting.AppSubURL + c.Req.URL.Path)
  339. return
  340. }
  341. if err = c.Repo.Repository.AddCollaborator(u); err != nil {
  342. c.Handle(500, "AddCollaborator", err)
  343. return
  344. }
  345. if setting.Service.EnableNotifyMail {
  346. mailer.SendCollaboratorMail(models.NewMailerUser(u), models.NewMailerUser(c.User), models.NewMailerRepo(c.Repo.Repository))
  347. }
  348. c.Flash.Success(c.Tr("repo.settings.add_collaborator_success"))
  349. c.Redirect(setting.AppSubURL + c.Req.URL.Path)
  350. }
  351. func ChangeCollaborationAccessMode(c *context.Context) {
  352. if err := c.Repo.Repository.ChangeCollaborationAccessMode(
  353. c.QueryInt64("uid"),
  354. models.AccessMode(c.QueryInt("mode"))); err != nil {
  355. raven.CaptureErrorAndWait(err, nil)
  356. log.Error(2, "ChangeCollaborationAccessMode: %v", err)
  357. return
  358. }
  359. c.Status(204)
  360. }
  361. func DeleteCollaboration(c *context.Context) {
  362. if err := c.Repo.Repository.DeleteCollaboration(c.QueryInt64("id")); err != nil {
  363. c.Flash.Error("DeleteCollaboration: " + err.Error())
  364. } else {
  365. c.Flash.Success(c.Tr("repo.settings.remove_collaborator_success"))
  366. }
  367. c.JSON(200, map[string]interface{}{
  368. "redirect": c.Repo.RepoLink + "/settings/collaboration",
  369. })
  370. }
  371. func SettingsBranches(c *context.Context) {
  372. c.Data["Title"] = c.Tr("repo.settings.branches")
  373. c.Data["PageIsSettingsBranches"] = true
  374. if c.Repo.Repository.IsBare {
  375. c.Flash.Info(c.Tr("repo.settings.branches_bare"), true)
  376. c.HTML(200, SETTINGS_BRANCHES)
  377. return
  378. }
  379. protectBranches, err := models.GetProtectBranchesByRepoID(c.Repo.Repository.ID)
  380. if err != nil {
  381. c.Handle(500, "GetProtectBranchesByRepoID", err)
  382. return
  383. }
  384. // Filter out deleted branches
  385. branches := make([]string, 0, len(protectBranches))
  386. for i := range protectBranches {
  387. if c.Repo.GitRepo.IsBranchExist(protectBranches[i].Name) {
  388. branches = append(branches, protectBranches[i].Name)
  389. }
  390. }
  391. c.Data["ProtectBranches"] = branches
  392. c.HTML(200, SETTINGS_BRANCHES)
  393. }
  394. func UpdateDefaultBranch(c *context.Context) {
  395. branch := c.Query("branch")
  396. if c.Repo.GitRepo.IsBranchExist(branch) &&
  397. c.Repo.Repository.DefaultBranch != branch {
  398. c.Repo.Repository.DefaultBranch = branch
  399. if err := c.Repo.GitRepo.SetDefaultBranch(branch); err != nil {
  400. if !git.IsErrUnsupportedVersion(err) {
  401. c.Handle(500, "SetDefaultBranch", err)
  402. return
  403. }
  404. c.Flash.Warning(c.Tr("repo.settings.update_default_branch_unsupported"))
  405. c.Redirect(c.Repo.RepoLink + "/settings/branches")
  406. return
  407. }
  408. }
  409. if err := models.UpdateRepository(c.Repo.Repository, false); err != nil {
  410. c.Handle(500, "UpdateRepository", err)
  411. return
  412. }
  413. c.Flash.Success(c.Tr("repo.settings.update_default_branch_success"))
  414. c.Redirect(c.Repo.RepoLink + "/settings/branches")
  415. }
  416. func SettingsProtectedBranch(c *context.Context) {
  417. branch := c.Params("*")
  418. if !c.Repo.GitRepo.IsBranchExist(branch) {
  419. c.NotFound()
  420. return
  421. }
  422. c.Data["Title"] = c.Tr("repo.settings.protected_branches") + " - " + branch
  423. c.Data["PageIsSettingsBranches"] = true
  424. protectBranch, err := models.GetProtectBranchOfRepoByName(c.Repo.Repository.ID, branch)
  425. if err != nil {
  426. if !errors.IsErrBranchNotExist(err) {
  427. c.Handle(500, "GetProtectBranchOfRepoByName", err)
  428. return
  429. }
  430. // No options found, create defaults.
  431. protectBranch = &models.ProtectBranch{
  432. Name: branch,
  433. }
  434. }
  435. if c.Repo.Owner.IsOrganization() {
  436. users, err := c.Repo.Repository.GetWriters()
  437. if err != nil {
  438. c.Handle(500, "Repo.Repository.GetPushers", err)
  439. return
  440. }
  441. c.Data["Users"] = users
  442. c.Data["whitelist_users"] = protectBranch.WhitelistUserIDs
  443. teams, err := c.Repo.Owner.TeamsHaveAccessToRepo(c.Repo.Repository.ID, models.ACCESS_MODE_WRITE)
  444. if err != nil {
  445. c.Handle(500, "Repo.Owner.TeamsHaveAccessToRepo", err)
  446. return
  447. }
  448. c.Data["Teams"] = teams
  449. c.Data["whitelist_teams"] = protectBranch.WhitelistTeamIDs
  450. }
  451. c.Data["Branch"] = protectBranch
  452. c.HTML(200, SETTINGS_PROTECTED_BRANCH)
  453. }
  454. func SettingsProtectedBranchPost(c *context.Context, f form.ProtectBranch) {
  455. branch := c.Params("*")
  456. if !c.Repo.GitRepo.IsBranchExist(branch) {
  457. c.NotFound()
  458. return
  459. }
  460. protectBranch, err := models.GetProtectBranchOfRepoByName(c.Repo.Repository.ID, branch)
  461. if err != nil {
  462. if !errors.IsErrBranchNotExist(err) {
  463. c.Handle(500, "GetProtectBranchOfRepoByName", err)
  464. return
  465. }
  466. // No options found, create defaults.
  467. protectBranch = &models.ProtectBranch{
  468. RepoID: c.Repo.Repository.ID,
  469. Name: branch,
  470. }
  471. }
  472. protectBranch.Protected = f.Protected
  473. protectBranch.RequirePullRequest = f.RequirePullRequest
  474. protectBranch.EnableWhitelist = f.EnableWhitelist
  475. if c.Repo.Owner.IsOrganization() {
  476. err = models.UpdateOrgProtectBranch(c.Repo.Repository, protectBranch, f.WhitelistUsers, f.WhitelistTeams)
  477. } else {
  478. err = models.UpdateProtectBranch(protectBranch)
  479. }
  480. if err != nil {
  481. c.Handle(500, "UpdateOrgProtectBranch/UpdateProtectBranch", err)
  482. return
  483. }
  484. c.Flash.Success(c.Tr("repo.settings.update_protect_branch_success"))
  485. c.Redirect(fmt.Sprintf("%s/settings/branches/%s", c.Repo.RepoLink, branch))
  486. }
  487. func SettingsGitHooks(c *context.Context) {
  488. c.Data["Title"] = c.Tr("repo.settings.githooks")
  489. c.Data["PageIsSettingsGitHooks"] = true
  490. hooks, err := c.Repo.GitRepo.Hooks()
  491. if err != nil {
  492. c.Handle(500, "Hooks", err)
  493. return
  494. }
  495. c.Data["Hooks"] = hooks
  496. c.HTML(200, SETTINGS_GITHOOKS)
  497. }
  498. func SettingsGitHooksEdit(c *context.Context) {
  499. c.Data["Title"] = c.Tr("repo.settings.githooks")
  500. c.Data["PageIsSettingsGitHooks"] = true
  501. c.Data["RequireSimpleMDE"] = true
  502. name := c.Params(":name")
  503. hook, err := c.Repo.GitRepo.GetHook(name)
  504. if err != nil {
  505. if err == git.ErrNotValidHook {
  506. c.Handle(404, "GetHook", err)
  507. } else {
  508. c.Handle(500, "GetHook", err)
  509. }
  510. return
  511. }
  512. c.Data["Hook"] = hook
  513. c.HTML(200, SETTINGS_GITHOOK_EDIT)
  514. }
  515. func SettingsGitHooksEditPost(c *context.Context) {
  516. name := c.Params(":name")
  517. hook, err := c.Repo.GitRepo.GetHook(name)
  518. if err != nil {
  519. if err == git.ErrNotValidHook {
  520. c.Handle(404, "GetHook", err)
  521. } else {
  522. c.Handle(500, "GetHook", err)
  523. }
  524. return
  525. }
  526. hook.Content = c.Query("content")
  527. if err = hook.Update(); err != nil {
  528. c.Handle(500, "hook.Update", err)
  529. return
  530. }
  531. c.Redirect(c.Data["Link"].(string))
  532. }
  533. func SettingsDeployKeys(c *context.Context) {
  534. c.Data["Title"] = c.Tr("repo.settings.deploy_keys")
  535. c.Data["PageIsSettingsKeys"] = true
  536. keys, err := models.ListDeployKeys(c.Repo.Repository.ID)
  537. if err != nil {
  538. c.Handle(500, "ListDeployKeys", err)
  539. return
  540. }
  541. c.Data["Deploykeys"] = keys
  542. c.HTML(200, SETTINGS_DEPLOY_KEYS)
  543. }
  544. func SettingsDeployKeysPost(c *context.Context, f form.AddSSHKey) {
  545. c.Data["Title"] = c.Tr("repo.settings.deploy_keys")
  546. c.Data["PageIsSettingsKeys"] = true
  547. keys, err := models.ListDeployKeys(c.Repo.Repository.ID)
  548. if err != nil {
  549. c.Handle(500, "ListDeployKeys", err)
  550. return
  551. }
  552. c.Data["Deploykeys"] = keys
  553. if c.HasError() {
  554. c.HTML(200, SETTINGS_DEPLOY_KEYS)
  555. return
  556. }
  557. content, err := models.CheckPublicKeyString(f.Content)
  558. if err != nil {
  559. if models.IsErrKeyUnableVerify(err) {
  560. c.Flash.Info(c.Tr("form.unable_verify_ssh_key"))
  561. } else {
  562. c.Data["HasError"] = true
  563. c.Data["Err_Content"] = true
  564. c.Flash.Error(c.Tr("form.invalid_ssh_key", err.Error()))
  565. c.Redirect(c.Repo.RepoLink + "/settings/keys")
  566. return
  567. }
  568. }
  569. key, err := models.AddDeployKey(c.Repo.Repository.ID, f.Title, content)
  570. if err != nil {
  571. c.Data["HasError"] = true
  572. switch {
  573. case models.IsErrKeyAlreadyExist(err):
  574. c.Data["Err_Content"] = true
  575. c.RenderWithErr(c.Tr("repo.settings.key_been_used"), SETTINGS_DEPLOY_KEYS, &f)
  576. case models.IsErrKeyNameAlreadyUsed(err):
  577. c.Data["Err_Title"] = true
  578. c.RenderWithErr(c.Tr("repo.settings.key_name_used"), SETTINGS_DEPLOY_KEYS, &f)
  579. default:
  580. c.Handle(500, "AddDeployKey", err)
  581. }
  582. return
  583. }
  584. log.Trace("Deploy key added: %d", c.Repo.Repository.ID)
  585. c.Flash.Success(c.Tr("repo.settings.add_key_success", key.Name))
  586. c.Redirect(c.Repo.RepoLink + "/settings/keys")
  587. }
  588. func DeleteDeployKey(c *context.Context) {
  589. if err := models.DeleteDeployKey(c.User, c.QueryInt64("id")); err != nil {
  590. c.Flash.Error("DeleteDeployKey: " + err.Error())
  591. } else {
  592. c.Flash.Success(c.Tr("repo.settings.deploy_key_deletion_success"))
  593. }
  594. c.JSON(200, map[string]interface{}{
  595. "redirect": c.Repo.RepoLink + "/settings/keys",
  596. })
  597. }