You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

setting.go 19 kB

11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package repo
  5. import (
  6. "encoding/json"
  7. "errors"
  8. "fmt"
  9. "strings"
  10. "time"
  11. "github.com/Unknwon/com"
  12. "github.com/gogits/gogs/models"
  13. "github.com/gogits/gogs/modules/auth"
  14. "github.com/gogits/gogs/modules/base"
  15. "github.com/gogits/gogs/modules/git"
  16. "github.com/gogits/gogs/modules/log"
  17. "github.com/gogits/gogs/modules/mailer"
  18. "github.com/gogits/gogs/modules/middleware"
  19. "github.com/gogits/gogs/modules/setting"
  20. )
  21. const (
  22. SETTINGS_OPTIONS base.TplName = "repo/settings/options"
  23. COLLABORATION base.TplName = "repo/settings/collaboration"
  24. HOOKS base.TplName = "repo/settings/hooks"
  25. HOOK_NEW base.TplName = "repo/settings/hook_new"
  26. ORG_HOOK_NEW base.TplName = "org/settings/hook_new"
  27. GITHOOKS base.TplName = "repo/settings/githooks"
  28. GITHOOK_EDIT base.TplName = "repo/settings/githook_edit"
  29. DEPLOY_KEYS base.TplName = "repo/settings/deploy_keys"
  30. )
  31. func Settings(ctx *middleware.Context) {
  32. ctx.Data["Title"] = ctx.Tr("repo.settings")
  33. ctx.Data["PageIsSettingsOptions"] = true
  34. ctx.HTML(200, SETTINGS_OPTIONS)
  35. }
  36. func SettingsPost(ctx *middleware.Context, form auth.RepoSettingForm) {
  37. ctx.Data["Title"] = ctx.Tr("repo.settings")
  38. ctx.Data["PageIsSettingsOptions"] = true
  39. repo := ctx.Repo.Repository
  40. switch ctx.Query("action") {
  41. case "update":
  42. if ctx.HasError() {
  43. ctx.HTML(200, SETTINGS_OPTIONS)
  44. return
  45. }
  46. newRepoName := form.RepoName
  47. // Check if repository name has been changed.
  48. if repo.LowerName != strings.ToLower(newRepoName) {
  49. if err := models.ChangeRepositoryName(ctx.Repo.Owner, repo.Name, newRepoName); err != nil {
  50. ctx.Data["Err_RepoName"] = true
  51. switch {
  52. case models.IsErrRepoAlreadyExist(err):
  53. ctx.RenderWithErr(ctx.Tr("form.repo_name_been_taken"), SETTINGS_OPTIONS, &form)
  54. case models.IsErrNameReserved(err):
  55. ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), SETTINGS_OPTIONS, &form)
  56. case models.IsErrNamePatternNotAllowed(err):
  57. ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), SETTINGS_OPTIONS, &form)
  58. default:
  59. ctx.Handle(500, "ChangeRepositoryName", err)
  60. }
  61. return
  62. }
  63. log.Trace("Repository name changed: %s/%s -> %s", ctx.Repo.Owner.Name, repo.Name, newRepoName)
  64. }
  65. // In case it's just a case change.
  66. repo.Name = newRepoName
  67. repo.LowerName = strings.ToLower(newRepoName)
  68. if ctx.Repo.GitRepo.IsBranchExist(form.Branch) {
  69. repo.DefaultBranch = form.Branch
  70. }
  71. repo.Description = form.Description
  72. repo.Website = form.Website
  73. visibilityChanged := repo.IsPrivate != form.Private
  74. repo.IsPrivate = form.Private
  75. if err := models.UpdateRepository(repo, visibilityChanged); err != nil {
  76. ctx.Handle(404, "UpdateRepository", err)
  77. return
  78. }
  79. log.Trace("Repository updated: %s/%s", ctx.Repo.Owner.Name, repo.Name)
  80. if repo.IsMirror {
  81. if form.Interval > 0 {
  82. ctx.Repo.Mirror.Interval = form.Interval
  83. ctx.Repo.Mirror.NextUpdate = time.Now().Add(time.Duration(form.Interval) * time.Hour)
  84. if err := models.UpdateMirror(ctx.Repo.Mirror); err != nil {
  85. log.Error(4, "UpdateMirror: %v", err)
  86. }
  87. }
  88. }
  89. ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success"))
  90. ctx.Redirect(fmt.Sprintf("%s/%s/%s/settings", setting.AppSubUrl, ctx.Repo.Owner.Name, repo.Name))
  91. case "transfer":
  92. if repo.Name != form.RepoName {
  93. ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
  94. return
  95. }
  96. if ctx.Repo.Owner.IsOrganization() {
  97. if !ctx.Repo.Owner.IsOwnedBy(ctx.User.Id) {
  98. ctx.Error(404)
  99. return
  100. }
  101. }
  102. newOwner := ctx.Query("new_owner_name")
  103. isExist, err := models.IsUserExist(0, newOwner)
  104. if err != nil {
  105. ctx.Handle(500, "IsUserExist", err)
  106. return
  107. } else if !isExist {
  108. ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_owner_name"), SETTINGS_OPTIONS, nil)
  109. return
  110. }
  111. if err = models.TransferOwnership(ctx.User, newOwner, repo); err != nil {
  112. if models.IsErrRepoAlreadyExist(err) {
  113. ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), SETTINGS_OPTIONS, nil)
  114. } else {
  115. ctx.Handle(500, "TransferOwnership", err)
  116. }
  117. return
  118. }
  119. log.Trace("Repository transfered: %s/%s -> %s", ctx.Repo.Owner.Name, repo.Name, newOwner)
  120. ctx.Flash.Success(ctx.Tr("repo.settings.transfer_succeed"))
  121. ctx.Redirect(setting.AppSubUrl + "/" + newOwner + "/" + repo.Name)
  122. case "delete":
  123. if repo.Name != form.RepoName {
  124. ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
  125. return
  126. }
  127. if ctx.Repo.Owner.IsOrganization() {
  128. if !ctx.Repo.Owner.IsOwnedBy(ctx.User.Id) {
  129. ctx.Error(404)
  130. return
  131. }
  132. }
  133. if err := models.DeleteRepository(ctx.Repo.Owner.Id, repo.ID, ctx.Repo.Owner.Name); err != nil {
  134. ctx.Handle(500, "DeleteRepository", err)
  135. return
  136. }
  137. log.Trace("Repository deleted: %s/%s", ctx.Repo.Owner.Name, repo.Name)
  138. ctx.Redirect(ctx.Repo.Owner.DashboardLink())
  139. }
  140. }
  141. func Collaboration(ctx *middleware.Context) {
  142. ctx.Data["Title"] = ctx.Tr("repo.settings")
  143. ctx.Data["PageIsSettingsCollaboration"] = true
  144. if ctx.Req.Method == "POST" {
  145. name := strings.ToLower(ctx.Query("collaborator"))
  146. if len(name) == 0 || ctx.Repo.Owner.LowerName == name {
  147. ctx.Redirect(setting.AppSubUrl + ctx.Req.URL.Path)
  148. return
  149. }
  150. u, err := models.GetUserByName(name)
  151. if err != nil {
  152. if models.IsErrUserNotExist(err) {
  153. ctx.Flash.Error(ctx.Tr("form.user_not_exist"))
  154. ctx.Redirect(setting.AppSubUrl + ctx.Req.URL.Path)
  155. } else {
  156. ctx.Handle(500, "GetUserByName", err)
  157. }
  158. return
  159. }
  160. // Check if user is organization member.
  161. if ctx.Repo.Owner.IsOrganization() && ctx.Repo.Owner.IsOrgMember(u.Id) {
  162. ctx.Flash.Info(ctx.Tr("repo.settings.user_is_org_member"))
  163. ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
  164. return
  165. }
  166. if err = ctx.Repo.Repository.AddCollaborator(u); err != nil {
  167. ctx.Handle(500, "AddCollaborator", err)
  168. return
  169. }
  170. if setting.Service.EnableNotifyMail {
  171. if err = mailer.SendCollaboratorMail(ctx.Render, u, ctx.User, ctx.Repo.Repository); err != nil {
  172. ctx.Handle(500, "SendCollaboratorMail", err)
  173. return
  174. }
  175. }
  176. ctx.Flash.Success(ctx.Tr("repo.settings.add_collaborator_success"))
  177. ctx.Redirect(setting.AppSubUrl + ctx.Req.URL.Path)
  178. return
  179. }
  180. // Delete collaborator.
  181. remove := strings.ToLower(ctx.Query("remove"))
  182. if len(remove) > 0 && remove != ctx.Repo.Owner.LowerName {
  183. u, err := models.GetUserByName(remove)
  184. if err != nil {
  185. ctx.Handle(500, "GetUserByName", err)
  186. return
  187. }
  188. if err := ctx.Repo.Repository.DeleteCollaborator(u); err != nil {
  189. ctx.Handle(500, "DeleteCollaborator", err)
  190. return
  191. }
  192. ctx.Flash.Success(ctx.Tr("repo.settings.remove_collaborator_success"))
  193. ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
  194. return
  195. }
  196. users, err := ctx.Repo.Repository.GetCollaborators()
  197. if err != nil {
  198. ctx.Handle(500, "GetCollaborators", err)
  199. return
  200. }
  201. ctx.Data["Collaborators"] = users
  202. ctx.HTML(200, COLLABORATION)
  203. }
  204. func Webhooks(ctx *middleware.Context) {
  205. ctx.Data["Title"] = ctx.Tr("repo.settings.hooks")
  206. ctx.Data["PageIsSettingsHooks"] = true
  207. ctx.Data["BaseLink"] = ctx.Repo.RepoLink
  208. ctx.Data["Description"] = ctx.Tr("repo.settings.hooks_desc", "http://gogs.io/docs/features/webhook.html")
  209. ws, err := models.GetWebhooksByRepoId(ctx.Repo.Repository.ID)
  210. if err != nil {
  211. ctx.Handle(500, "GetWebhooksByRepoId", err)
  212. return
  213. }
  214. ctx.Data["Webhooks"] = ws
  215. ctx.HTML(200, HOOKS)
  216. }
  217. type OrgRepoCtx struct {
  218. OrgID int64
  219. RepoID int64
  220. Link string
  221. NewTemplate base.TplName
  222. }
  223. // getOrgRepoCtx determines whether this is a repo context or organization context.
  224. func getOrgRepoCtx(ctx *middleware.Context) (*OrgRepoCtx, error) {
  225. if len(ctx.Repo.RepoLink) > 0 {
  226. return &OrgRepoCtx{
  227. RepoID: ctx.Repo.Repository.ID,
  228. Link: ctx.Repo.RepoLink,
  229. NewTemplate: HOOK_NEW,
  230. }, nil
  231. }
  232. if len(ctx.Org.OrgLink) > 0 {
  233. return &OrgRepoCtx{
  234. OrgID: ctx.Org.Organization.Id,
  235. Link: ctx.Org.OrgLink,
  236. NewTemplate: ORG_HOOK_NEW,
  237. }, nil
  238. }
  239. return nil, errors.New("Unable to set OrgRepo context")
  240. }
  241. func checkHookType(ctx *middleware.Context) string {
  242. hookType := strings.ToLower(ctx.Params(":type"))
  243. if !com.IsSliceContainsStr(setting.Webhook.Types, hookType) {
  244. ctx.Handle(404, "checkHookType", nil)
  245. return ""
  246. }
  247. return hookType
  248. }
  249. func WebhooksNew(ctx *middleware.Context) {
  250. ctx.Data["Title"] = ctx.Tr("repo.settings.add_webhook")
  251. ctx.Data["PageIsSettingsHooks"] = true
  252. ctx.Data["PageIsSettingsHooksNew"] = true
  253. ctx.Data["Webhook"] = models.Webhook{HookEvent: &models.HookEvent{}}
  254. orCtx, err := getOrgRepoCtx(ctx)
  255. if err != nil {
  256. ctx.Handle(500, "getOrgRepoCtx", err)
  257. return
  258. }
  259. ctx.Data["HookType"] = checkHookType(ctx)
  260. if ctx.Written() {
  261. return
  262. }
  263. ctx.Data["BaseLink"] = orCtx.Link
  264. ctx.HTML(200, orCtx.NewTemplate)
  265. }
  266. func ParseHookEvent(form auth.WebhookForm) *models.HookEvent {
  267. return &models.HookEvent{
  268. PushOnly: form.PushOnly(),
  269. SendEverything: form.SendEverything(),
  270. ChooseEvents: form.ChooseEvents(),
  271. HookEvents: models.HookEvents{
  272. Create: form.Create,
  273. Push: form.Push,
  274. },
  275. }
  276. }
  277. func WebHooksNewPost(ctx *middleware.Context, form auth.NewWebhookForm) {
  278. ctx.Data["Title"] = ctx.Tr("repo.settings.add_webhook")
  279. ctx.Data["PageIsSettingsHooks"] = true
  280. ctx.Data["PageIsSettingsHooksNew"] = true
  281. ctx.Data["Webhook"] = models.Webhook{HookEvent: &models.HookEvent{}}
  282. ctx.Data["HookType"] = "gogs"
  283. orCtx, err := getOrgRepoCtx(ctx)
  284. if err != nil {
  285. ctx.Handle(500, "getOrgRepoCtx", err)
  286. return
  287. }
  288. ctx.Data["BaseLink"] = orCtx.Link
  289. if ctx.HasError() {
  290. ctx.HTML(200, orCtx.NewTemplate)
  291. return
  292. }
  293. contentType := models.JSON
  294. if models.HookContentType(form.ContentType) == models.FORM {
  295. contentType = models.FORM
  296. }
  297. w := &models.Webhook{
  298. RepoID: orCtx.RepoID,
  299. URL: form.PayloadURL,
  300. ContentType: contentType,
  301. Secret: form.Secret,
  302. HookEvent: ParseHookEvent(form.WebhookForm),
  303. IsActive: form.Active,
  304. HookTaskType: models.GOGS,
  305. OrgID: orCtx.OrgID,
  306. }
  307. if err := w.UpdateEvent(); err != nil {
  308. ctx.Handle(500, "UpdateEvent", err)
  309. return
  310. } else if err := models.CreateWebhook(w); err != nil {
  311. ctx.Handle(500, "CreateWebhook", err)
  312. return
  313. }
  314. ctx.Flash.Success(ctx.Tr("repo.settings.add_hook_success"))
  315. ctx.Redirect(orCtx.Link + "/settings/hooks")
  316. }
  317. func SlackHooksNewPost(ctx *middleware.Context, form auth.NewSlackHookForm) {
  318. ctx.Data["Title"] = ctx.Tr("repo.settings")
  319. ctx.Data["PageIsSettingsHooks"] = true
  320. ctx.Data["PageIsSettingsHooksNew"] = true
  321. ctx.Data["Webhook"] = models.Webhook{HookEvent: &models.HookEvent{}}
  322. orCtx, err := getOrgRepoCtx(ctx)
  323. if err != nil {
  324. ctx.Handle(500, "getOrgRepoCtx", err)
  325. return
  326. }
  327. if ctx.HasError() {
  328. ctx.HTML(200, orCtx.NewTemplate)
  329. return
  330. }
  331. meta, err := json.Marshal(&models.SlackMeta{
  332. Channel: form.Channel,
  333. Username: form.Username,
  334. IconURL: form.IconURL,
  335. Color: form.Color,
  336. })
  337. if err != nil {
  338. ctx.Handle(500, "Marshal", err)
  339. return
  340. }
  341. w := &models.Webhook{
  342. RepoID: orCtx.RepoID,
  343. URL: form.PayloadURL,
  344. ContentType: models.JSON,
  345. HookEvent: ParseHookEvent(form.WebhookForm),
  346. IsActive: form.Active,
  347. HookTaskType: models.SLACK,
  348. Meta: string(meta),
  349. OrgID: orCtx.OrgID,
  350. }
  351. if err := w.UpdateEvent(); err != nil {
  352. ctx.Handle(500, "UpdateEvent", err)
  353. return
  354. } else if err := models.CreateWebhook(w); err != nil {
  355. ctx.Handle(500, "CreateWebhook", err)
  356. return
  357. }
  358. ctx.Flash.Success(ctx.Tr("repo.settings.add_hook_success"))
  359. ctx.Redirect(orCtx.Link + "/settings/hooks")
  360. }
  361. func checkWebhook(ctx *middleware.Context) (*OrgRepoCtx, *models.Webhook) {
  362. ctx.Data["RequireHighlightJS"] = true
  363. orCtx, err := getOrgRepoCtx(ctx)
  364. if err != nil {
  365. ctx.Handle(500, "getOrgRepoCtx", err)
  366. return nil, nil
  367. }
  368. ctx.Data["BaseLink"] = orCtx.Link
  369. w, err := models.GetWebhookByID(ctx.ParamsInt64(":id"))
  370. if err != nil {
  371. if models.IsErrWebhookNotExist(err) {
  372. ctx.Handle(404, "GetWebhookByID", nil)
  373. } else {
  374. ctx.Handle(500, "GetWebhookByID", err)
  375. }
  376. return nil, nil
  377. }
  378. switch w.HookTaskType {
  379. case models.SLACK:
  380. ctx.Data["SlackHook"] = w.GetSlackHook()
  381. ctx.Data["HookType"] = "slack"
  382. default:
  383. ctx.Data["HookType"] = "gogs"
  384. }
  385. ctx.Data["History"], err = w.History(1)
  386. if err != nil {
  387. ctx.Handle(500, "History", err)
  388. }
  389. return orCtx, w
  390. }
  391. func WebHooksEdit(ctx *middleware.Context) {
  392. ctx.Data["Title"] = ctx.Tr("repo.settings.update_webhook")
  393. ctx.Data["PageIsSettingsHooks"] = true
  394. ctx.Data["PageIsSettingsHooksEdit"] = true
  395. orCtx, w := checkWebhook(ctx)
  396. if ctx.Written() {
  397. return
  398. }
  399. ctx.Data["Webhook"] = w
  400. ctx.HTML(200, orCtx.NewTemplate)
  401. }
  402. func WebHooksEditPost(ctx *middleware.Context, form auth.NewWebhookForm) {
  403. ctx.Data["Title"] = ctx.Tr("repo.settings.update_webhook")
  404. ctx.Data["PageIsSettingsHooks"] = true
  405. ctx.Data["PageIsSettingsHooksEdit"] = true
  406. orCtx, w := checkWebhook(ctx)
  407. if ctx.Written() {
  408. return
  409. }
  410. ctx.Data["Webhook"] = w
  411. if ctx.HasError() {
  412. ctx.HTML(200, orCtx.NewTemplate)
  413. return
  414. }
  415. contentType := models.JSON
  416. if models.HookContentType(form.ContentType) == models.FORM {
  417. contentType = models.FORM
  418. }
  419. w.URL = form.PayloadURL
  420. w.ContentType = contentType
  421. w.Secret = form.Secret
  422. w.HookEvent = ParseHookEvent(form.WebhookForm)
  423. w.IsActive = form.Active
  424. if err := w.UpdateEvent(); err != nil {
  425. ctx.Handle(500, "UpdateEvent", err)
  426. return
  427. } else if err := models.UpdateWebhook(w); err != nil {
  428. ctx.Handle(500, "WebHooksEditPost", err)
  429. return
  430. }
  431. ctx.Flash.Success(ctx.Tr("repo.settings.update_hook_success"))
  432. ctx.Redirect(fmt.Sprintf("%s/settings/hooks/%d", orCtx.Link, w.ID))
  433. }
  434. func SlackHooksEditPost(ctx *middleware.Context, form auth.NewSlackHookForm) {
  435. ctx.Data["Title"] = ctx.Tr("repo.settings")
  436. ctx.Data["PageIsSettingsHooks"] = true
  437. ctx.Data["PageIsSettingsHooksEdit"] = true
  438. orCtx, w := checkWebhook(ctx)
  439. if ctx.Written() {
  440. return
  441. }
  442. ctx.Data["Webhook"] = w
  443. if ctx.HasError() {
  444. ctx.HTML(200, orCtx.NewTemplate)
  445. return
  446. }
  447. meta, err := json.Marshal(&models.SlackMeta{
  448. Channel: form.Channel,
  449. Username: form.Username,
  450. IconURL: form.IconURL,
  451. Color: form.Color,
  452. })
  453. if err != nil {
  454. ctx.Handle(500, "Marshal", err)
  455. return
  456. }
  457. w.URL = form.PayloadURL
  458. w.Meta = string(meta)
  459. w.HookEvent = ParseHookEvent(form.WebhookForm)
  460. w.IsActive = form.Active
  461. if err := w.UpdateEvent(); err != nil {
  462. ctx.Handle(500, "UpdateEvent", err)
  463. return
  464. } else if err := models.UpdateWebhook(w); err != nil {
  465. ctx.Handle(500, "UpdateWebhook", err)
  466. return
  467. }
  468. ctx.Flash.Success(ctx.Tr("repo.settings.update_hook_success"))
  469. ctx.Redirect(fmt.Sprintf("%s/settings/hooks/%d", orCtx.Link, w.ID))
  470. }
  471. func DeleteWebhook(ctx *middleware.Context) {
  472. if err := models.DeleteWebhook(ctx.QueryInt64("id")); err != nil {
  473. ctx.Flash.Error("DeleteWebhook: " + err.Error())
  474. } else {
  475. ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success"))
  476. }
  477. ctx.JSON(200, map[string]interface{}{
  478. "redirect": ctx.Repo.RepoLink + "/settings/hooks",
  479. })
  480. }
  481. func TriggerHook(ctx *middleware.Context) {
  482. u, err := models.GetUserByName(ctx.Params(":username"))
  483. if err != nil {
  484. if models.IsErrUserNotExist(err) {
  485. ctx.Handle(404, "GetUserByName", err)
  486. } else {
  487. ctx.Handle(500, "GetUserByName", err)
  488. }
  489. return
  490. }
  491. repo, err := models.GetRepositoryByName(u.Id, ctx.Params(":reponame"))
  492. if err != nil {
  493. if models.IsErrRepoNotExist(err) {
  494. ctx.Handle(404, "GetRepositoryByName", err)
  495. } else {
  496. ctx.Handle(500, "GetRepositoryByName", err)
  497. }
  498. return
  499. }
  500. models.HookQueue.AddRepoID(repo.ID)
  501. ctx.Status(200)
  502. }
  503. func GitHooks(ctx *middleware.Context) {
  504. ctx.Data["Title"] = ctx.Tr("repo.settings.githooks")
  505. ctx.Data["PageIsSettingsGitHooks"] = true
  506. hooks, err := ctx.Repo.GitRepo.Hooks()
  507. if err != nil {
  508. ctx.Handle(500, "Hooks", err)
  509. return
  510. }
  511. ctx.Data["Hooks"] = hooks
  512. ctx.HTML(200, GITHOOKS)
  513. }
  514. func GitHooksEdit(ctx *middleware.Context) {
  515. ctx.Data["Title"] = ctx.Tr("repo.settings.githooks")
  516. ctx.Data["PageIsSettingsGitHooks"] = true
  517. name := ctx.Params(":name")
  518. hook, err := ctx.Repo.GitRepo.GetHook(name)
  519. if err != nil {
  520. if err == git.ErrNotValidHook {
  521. ctx.Handle(404, "GetHook", err)
  522. } else {
  523. ctx.Handle(500, "GetHook", err)
  524. }
  525. return
  526. }
  527. ctx.Data["Hook"] = hook
  528. ctx.HTML(200, GITHOOK_EDIT)
  529. }
  530. func GitHooksEditPost(ctx *middleware.Context) {
  531. name := ctx.Params(":name")
  532. hook, err := ctx.Repo.GitRepo.GetHook(name)
  533. if err != nil {
  534. if err == git.ErrNotValidHook {
  535. ctx.Handle(404, "GetHook", err)
  536. } else {
  537. ctx.Handle(500, "GetHook", err)
  538. }
  539. return
  540. }
  541. hook.Content = ctx.Query("content")
  542. if err = hook.Update(); err != nil {
  543. ctx.Handle(500, "hook.Update", err)
  544. return
  545. }
  546. ctx.Redirect(ctx.Repo.RepoLink + "/settings/hooks/git")
  547. }
  548. func DeployKeys(ctx *middleware.Context) {
  549. ctx.Data["Title"] = ctx.Tr("repo.settings.deploy_keys")
  550. ctx.Data["PageIsSettingsKeys"] = true
  551. keys, err := models.ListDeployKeys(ctx.Repo.Repository.ID)
  552. if err != nil {
  553. ctx.Handle(500, "ListDeployKeys", err)
  554. return
  555. }
  556. ctx.Data["Deploykeys"] = keys
  557. ctx.HTML(200, DEPLOY_KEYS)
  558. }
  559. func DeployKeysPost(ctx *middleware.Context, form auth.AddSSHKeyForm) {
  560. ctx.Data["Title"] = ctx.Tr("repo.settings.deploy_keys")
  561. ctx.Data["PageIsSettingsKeys"] = true
  562. keys, err := models.ListDeployKeys(ctx.Repo.Repository.ID)
  563. if err != nil {
  564. ctx.Handle(500, "ListDeployKeys", err)
  565. return
  566. }
  567. ctx.Data["Deploykeys"] = keys
  568. if ctx.HasError() {
  569. ctx.HTML(200, DEPLOY_KEYS)
  570. return
  571. }
  572. content, err := models.CheckPublicKeyString(form.Content)
  573. if err != nil {
  574. if err == models.ErrKeyUnableVerify {
  575. ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key"))
  576. } else {
  577. ctx.Data["HasError"] = true
  578. ctx.Data["Err_Content"] = true
  579. ctx.Flash.Error(ctx.Tr("form.invalid_ssh_key", err.Error()))
  580. ctx.Redirect(ctx.Repo.RepoLink + "/settings/keys")
  581. return
  582. }
  583. }
  584. if err = models.AddDeployKey(ctx.Repo.Repository.ID, form.Title, content); err != nil {
  585. ctx.Data["HasError"] = true
  586. switch {
  587. case models.IsErrKeyAlreadyExist(err):
  588. ctx.Data["Err_Content"] = true
  589. ctx.RenderWithErr(ctx.Tr("repo.settings.key_been_used"), DEPLOY_KEYS, &form)
  590. case models.IsErrKeyNameAlreadyUsed(err):
  591. ctx.Data["Err_Title"] = true
  592. ctx.RenderWithErr(ctx.Tr("repo.settings.key_name_used"), DEPLOY_KEYS, &form)
  593. default:
  594. ctx.Handle(500, "AddDeployKey", err)
  595. }
  596. return
  597. }
  598. log.Trace("Deploy key added: %d", ctx.Repo.Repository.ID)
  599. ctx.Flash.Success(ctx.Tr("repo.settings.add_key_success", form.Title))
  600. ctx.Redirect(ctx.Repo.RepoLink + "/settings/keys")
  601. }
  602. func DeleteDeployKey(ctx *middleware.Context) {
  603. if err := models.DeleteDeployKey(ctx.QueryInt64("id")); err != nil {
  604. ctx.Flash.Error("DeleteDeployKey: " + err.Error())
  605. } else {
  606. ctx.Flash.Success(ctx.Tr("repo.settings.deploy_key_deletion_success"))
  607. }
  608. ctx.JSON(200, map[string]interface{}{
  609. "redirect": ctx.Repo.RepoLink + "/settings/keys",
  610. })
  611. }