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