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 20 kB

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