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

setting.go 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Copyright 2019 The Gitea Authors. All rights reserved.
  3. // SPDX-License-Identifier: MIT
  4. package org
  5. import (
  6. "net/http"
  7. "net/url"
  8. "strings"
  9. "code.gitea.io/gitea/models"
  10. "code.gitea.io/gitea/models/db"
  11. repo_model "code.gitea.io/gitea/models/repo"
  12. user_model "code.gitea.io/gitea/models/user"
  13. "code.gitea.io/gitea/models/webhook"
  14. "code.gitea.io/gitea/modules/base"
  15. "code.gitea.io/gitea/modules/context"
  16. "code.gitea.io/gitea/modules/log"
  17. repo_module "code.gitea.io/gitea/modules/repository"
  18. "code.gitea.io/gitea/modules/setting"
  19. "code.gitea.io/gitea/modules/web"
  20. user_setting "code.gitea.io/gitea/routers/web/user/setting"
  21. "code.gitea.io/gitea/services/forms"
  22. org_service "code.gitea.io/gitea/services/org"
  23. repo_service "code.gitea.io/gitea/services/repository"
  24. user_service "code.gitea.io/gitea/services/user"
  25. )
  26. const (
  27. // tplSettingsOptions template path for render settings
  28. tplSettingsOptions base.TplName = "org/settings/options"
  29. // tplSettingsDelete template path for render delete repository
  30. tplSettingsDelete base.TplName = "org/settings/delete"
  31. // tplSettingsHooks template path for render hook settings
  32. tplSettingsHooks base.TplName = "org/settings/hooks"
  33. // tplSettingsLabels template path for render labels settings
  34. tplSettingsLabels base.TplName = "org/settings/labels"
  35. )
  36. // Settings render the main settings page
  37. func Settings(ctx *context.Context) {
  38. ctx.Data["Title"] = ctx.Tr("org.settings")
  39. ctx.Data["PageIsOrgSettings"] = true
  40. ctx.Data["PageIsSettingsOptions"] = true
  41. ctx.Data["CurrentVisibility"] = ctx.Org.Organization.Visibility
  42. ctx.Data["RepoAdminChangeTeamAccess"] = ctx.Org.Organization.RepoAdminChangeTeamAccess
  43. ctx.Data["ContextUser"] = ctx.ContextUser
  44. ctx.HTML(http.StatusOK, tplSettingsOptions)
  45. }
  46. // SettingsPost response for settings change submitted
  47. func SettingsPost(ctx *context.Context) {
  48. form := web.GetForm(ctx).(*forms.UpdateOrgSettingForm)
  49. ctx.Data["Title"] = ctx.Tr("org.settings")
  50. ctx.Data["PageIsOrgSettings"] = true
  51. ctx.Data["PageIsSettingsOptions"] = true
  52. ctx.Data["CurrentVisibility"] = ctx.Org.Organization.Visibility
  53. if ctx.HasError() {
  54. ctx.HTML(http.StatusOK, tplSettingsOptions)
  55. return
  56. }
  57. org := ctx.Org.Organization
  58. nameChanged := org.Name != form.Name
  59. // Check if organization name has been changed.
  60. if nameChanged {
  61. err := org_service.RenameOrganization(ctx, org, form.Name)
  62. switch {
  63. case user_model.IsErrUserAlreadyExist(err):
  64. ctx.Data["OrgName"] = true
  65. ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), tplSettingsOptions, &form)
  66. return
  67. case db.IsErrNameReserved(err):
  68. ctx.Data["OrgName"] = true
  69. ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(db.ErrNameReserved).Name), tplSettingsOptions, &form)
  70. return
  71. case db.IsErrNamePatternNotAllowed(err):
  72. ctx.Data["OrgName"] = true
  73. ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tplSettingsOptions, &form)
  74. return
  75. case err != nil:
  76. ctx.ServerError("org_service.RenameOrganization", err)
  77. return
  78. }
  79. // reset ctx.org.OrgLink with new name
  80. ctx.Org.OrgLink = setting.AppSubURL + "/org/" + url.PathEscape(form.Name)
  81. log.Trace("Organization name changed: %s -> %s", org.Name, form.Name)
  82. }
  83. // In case it's just a case change.
  84. org.Name = form.Name
  85. org.LowerName = strings.ToLower(form.Name)
  86. if ctx.Doer.IsAdmin {
  87. org.MaxRepoCreation = form.MaxRepoCreation
  88. }
  89. org.FullName = form.FullName
  90. org.Description = form.Description
  91. org.Website = form.Website
  92. org.Location = form.Location
  93. org.RepoAdminChangeTeamAccess = form.RepoAdminChangeTeamAccess
  94. visibilityChanged := form.Visibility != org.Visibility
  95. org.Visibility = form.Visibility
  96. if err := user_model.UpdateUser(ctx, org.AsUser(), false); err != nil {
  97. ctx.ServerError("UpdateUser", err)
  98. return
  99. }
  100. // update forks visibility
  101. if visibilityChanged {
  102. repos, _, err := repo_model.GetUserRepositories(&repo_model.SearchRepoOptions{
  103. Actor: org.AsUser(), Private: true, ListOptions: db.ListOptions{Page: 1, PageSize: org.NumRepos},
  104. })
  105. if err != nil {
  106. ctx.ServerError("GetRepositories", err)
  107. return
  108. }
  109. for _, repo := range repos {
  110. repo.OwnerName = org.Name
  111. if err := repo_service.UpdateRepository(ctx, repo, true); err != nil {
  112. ctx.ServerError("UpdateRepository", err)
  113. return
  114. }
  115. }
  116. }
  117. log.Trace("Organization setting updated: %s", org.Name)
  118. ctx.Flash.Success(ctx.Tr("org.settings.update_setting_success"))
  119. ctx.Redirect(ctx.Org.OrgLink + "/settings")
  120. }
  121. // SettingsAvatar response for change avatar on settings page
  122. func SettingsAvatar(ctx *context.Context) {
  123. form := web.GetForm(ctx).(*forms.AvatarForm)
  124. form.Source = forms.AvatarLocal
  125. if err := user_setting.UpdateAvatarSetting(ctx, form, ctx.Org.Organization.AsUser()); err != nil {
  126. ctx.Flash.Error(err.Error())
  127. } else {
  128. ctx.Flash.Success(ctx.Tr("org.settings.update_avatar_success"))
  129. }
  130. ctx.Redirect(ctx.Org.OrgLink + "/settings")
  131. }
  132. // SettingsDeleteAvatar response for delete avatar on settings page
  133. func SettingsDeleteAvatar(ctx *context.Context) {
  134. if err := user_service.DeleteAvatar(ctx.Org.Organization.AsUser()); err != nil {
  135. ctx.Flash.Error(err.Error())
  136. }
  137. ctx.Redirect(ctx.Org.OrgLink + "/settings")
  138. }
  139. // SettingsDelete response for deleting an organization
  140. func SettingsDelete(ctx *context.Context) {
  141. ctx.Data["Title"] = ctx.Tr("org.settings")
  142. ctx.Data["PageIsOrgSettings"] = true
  143. ctx.Data["PageIsSettingsDelete"] = true
  144. if ctx.Req.Method == "POST" {
  145. if ctx.Org.Organization.Name != ctx.FormString("org_name") {
  146. ctx.Data["Err_OrgName"] = true
  147. ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_org_name"), tplSettingsDelete, nil)
  148. return
  149. }
  150. if err := org_service.DeleteOrganization(ctx.Org.Organization); err != nil {
  151. if models.IsErrUserOwnRepos(err) {
  152. ctx.Flash.Error(ctx.Tr("form.org_still_own_repo"))
  153. ctx.Redirect(ctx.Org.OrgLink + "/settings/delete")
  154. } else if models.IsErrUserOwnPackages(err) {
  155. ctx.Flash.Error(ctx.Tr("form.org_still_own_packages"))
  156. ctx.Redirect(ctx.Org.OrgLink + "/settings/delete")
  157. } else {
  158. ctx.ServerError("DeleteOrganization", err)
  159. }
  160. } else {
  161. log.Trace("Organization deleted: %s", ctx.Org.Organization.Name)
  162. ctx.Redirect(setting.AppSubURL + "/")
  163. }
  164. return
  165. }
  166. ctx.HTML(http.StatusOK, tplSettingsDelete)
  167. }
  168. // Webhooks render webhook list page
  169. func Webhooks(ctx *context.Context) {
  170. ctx.Data["Title"] = ctx.Tr("org.settings")
  171. ctx.Data["PageIsOrgSettings"] = true
  172. ctx.Data["PageIsSettingsHooks"] = true
  173. ctx.Data["BaseLink"] = ctx.Org.OrgLink + "/settings/hooks"
  174. ctx.Data["BaseLinkNew"] = ctx.Org.OrgLink + "/settings/hooks"
  175. ctx.Data["Description"] = ctx.Tr("org.settings.hooks_desc")
  176. ws, err := webhook.ListWebhooksByOpts(ctx, &webhook.ListWebhookOptions{OwnerID: ctx.Org.Organization.ID})
  177. if err != nil {
  178. ctx.ServerError("ListWebhooksByOpts", err)
  179. return
  180. }
  181. ctx.Data["Webhooks"] = ws
  182. ctx.HTML(http.StatusOK, tplSettingsHooks)
  183. }
  184. // DeleteWebhook response for delete webhook
  185. func DeleteWebhook(ctx *context.Context) {
  186. if err := webhook.DeleteWebhookByOwnerID(ctx.Org.Organization.ID, ctx.FormInt64("id")); err != nil {
  187. ctx.Flash.Error("DeleteWebhookByOwnerID: " + err.Error())
  188. } else {
  189. ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success"))
  190. }
  191. ctx.JSON(http.StatusOK, map[string]any{
  192. "redirect": ctx.Org.OrgLink + "/settings/hooks",
  193. })
  194. }
  195. // Labels render organization labels page
  196. func Labels(ctx *context.Context) {
  197. ctx.Data["Title"] = ctx.Tr("repo.labels")
  198. ctx.Data["PageIsOrgSettings"] = true
  199. ctx.Data["PageIsOrgSettingsLabels"] = true
  200. ctx.Data["LabelTemplateFiles"] = repo_module.LabelTemplateFiles
  201. ctx.HTML(http.StatusOK, tplSettingsLabels)
  202. }