code.gitea.io/gitea@v1.22.3/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 11 "code.gitea.io/gitea/models" 12 "code.gitea.io/gitea/models/db" 13 repo_model "code.gitea.io/gitea/models/repo" 14 user_model "code.gitea.io/gitea/models/user" 15 "code.gitea.io/gitea/models/webhook" 16 "code.gitea.io/gitea/modules/base" 17 "code.gitea.io/gitea/modules/log" 18 "code.gitea.io/gitea/modules/optional" 19 repo_module "code.gitea.io/gitea/modules/repository" 20 "code.gitea.io/gitea/modules/setting" 21 "code.gitea.io/gitea/modules/web" 22 shared_user "code.gitea.io/gitea/routers/web/shared/user" 23 user_setting "code.gitea.io/gitea/routers/web/user/setting" 24 "code.gitea.io/gitea/services/context" 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 75 if org.Name != form.Name { 76 if err := user_service.RenameUser(ctx, org.AsUser(), form.Name); err != nil { 77 if user_model.IsErrUserAlreadyExist(err) { 78 ctx.Data["Err_Name"] = true 79 ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), tplSettingsOptions, &form) 80 } else if db.IsErrNameReserved(err) { 81 ctx.Data["Err_Name"] = true 82 ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(db.ErrNameReserved).Name), tplSettingsOptions, &form) 83 } else if db.IsErrNamePatternNotAllowed(err) { 84 ctx.Data["Err_Name"] = true 85 ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tplSettingsOptions, &form) 86 } else { 87 ctx.ServerError("RenameUser", err) 88 } 89 return 90 } 91 92 ctx.Org.OrgLink = setting.AppSubURL + "/org/" + url.PathEscape(org.Name) 93 } 94 95 if form.Email != "" { 96 if err := user_service.ReplacePrimaryEmailAddress(ctx, org.AsUser(), form.Email); err != nil { 97 ctx.Data["Err_Email"] = true 98 ctx.RenderWithErr(ctx.Tr("form.email_invalid"), tplSettingsOptions, &form) 99 return 100 } 101 } 102 103 opts := &user_service.UpdateOptions{ 104 FullName: optional.Some(form.FullName), 105 Description: optional.Some(form.Description), 106 Website: optional.Some(form.Website), 107 Location: optional.Some(form.Location), 108 Visibility: optional.Some(form.Visibility), 109 RepoAdminChangeTeamAccess: optional.Some(form.RepoAdminChangeTeamAccess), 110 } 111 if ctx.Doer.IsAdmin { 112 opts.MaxRepoCreation = optional.Some(form.MaxRepoCreation) 113 } 114 115 visibilityChanged := org.Visibility != form.Visibility 116 117 if err := user_service.UpdateUser(ctx, org.AsUser(), opts); err != nil { 118 ctx.ServerError("UpdateUser", err) 119 return 120 } 121 122 // update forks visibility 123 if visibilityChanged { 124 repos, _, err := repo_model.GetUserRepositories(ctx, &repo_model.SearchRepoOptions{ 125 Actor: org.AsUser(), Private: true, ListOptions: db.ListOptions{Page: 1, PageSize: org.NumRepos}, 126 }) 127 if err != nil { 128 ctx.ServerError("GetRepositories", err) 129 return 130 } 131 for _, repo := range repos { 132 repo.OwnerName = org.Name 133 if err := repo_service.UpdateRepository(ctx, repo, true); err != nil { 134 ctx.ServerError("UpdateRepository", err) 135 return 136 } 137 } 138 } 139 140 log.Trace("Organization setting updated: %s", org.Name) 141 ctx.Flash.Success(ctx.Tr("org.settings.update_setting_success")) 142 ctx.Redirect(ctx.Org.OrgLink + "/settings") 143 } 144 145 // SettingsAvatar response for change avatar on settings page 146 func SettingsAvatar(ctx *context.Context) { 147 form := web.GetForm(ctx).(*forms.AvatarForm) 148 form.Source = forms.AvatarLocal 149 if err := user_setting.UpdateAvatarSetting(ctx, form, ctx.Org.Organization.AsUser()); err != nil { 150 ctx.Flash.Error(err.Error()) 151 } else { 152 ctx.Flash.Success(ctx.Tr("org.settings.update_avatar_success")) 153 } 154 155 ctx.Redirect(ctx.Org.OrgLink + "/settings") 156 } 157 158 // SettingsDeleteAvatar response for delete avatar on settings page 159 func SettingsDeleteAvatar(ctx *context.Context) { 160 if err := user_service.DeleteAvatar(ctx, ctx.Org.Organization.AsUser()); err != nil { 161 ctx.Flash.Error(err.Error()) 162 } 163 164 ctx.JSONRedirect(ctx.Org.OrgLink + "/settings") 165 } 166 167 // SettingsDelete response for deleting an organization 168 func SettingsDelete(ctx *context.Context) { 169 ctx.Data["Title"] = ctx.Tr("org.settings") 170 ctx.Data["PageIsOrgSettings"] = true 171 ctx.Data["PageIsSettingsDelete"] = true 172 173 if ctx.Req.Method == "POST" { 174 if ctx.Org.Organization.Name != ctx.FormString("org_name") { 175 ctx.Data["Err_OrgName"] = true 176 ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_org_name"), tplSettingsDelete, nil) 177 return 178 } 179 180 if err := org_service.DeleteOrganization(ctx, ctx.Org.Organization, false); err != nil { 181 if models.IsErrUserOwnRepos(err) { 182 ctx.Flash.Error(ctx.Tr("form.org_still_own_repo")) 183 ctx.Redirect(ctx.Org.OrgLink + "/settings/delete") 184 } else if models.IsErrUserOwnPackages(err) { 185 ctx.Flash.Error(ctx.Tr("form.org_still_own_packages")) 186 ctx.Redirect(ctx.Org.OrgLink + "/settings/delete") 187 } else { 188 ctx.ServerError("DeleteOrganization", err) 189 } 190 } else { 191 log.Trace("Organization deleted: %s", ctx.Org.Organization.Name) 192 ctx.Redirect(setting.AppSubURL + "/") 193 } 194 return 195 } 196 197 err := shared_user.LoadHeaderCount(ctx) 198 if err != nil { 199 ctx.ServerError("LoadHeaderCount", err) 200 return 201 } 202 203 ctx.HTML(http.StatusOK, tplSettingsDelete) 204 } 205 206 // Webhooks render webhook list page 207 func Webhooks(ctx *context.Context) { 208 ctx.Data["Title"] = ctx.Tr("org.settings") 209 ctx.Data["PageIsOrgSettings"] = true 210 ctx.Data["PageIsSettingsHooks"] = true 211 ctx.Data["BaseLink"] = ctx.Org.OrgLink + "/settings/hooks" 212 ctx.Data["BaseLinkNew"] = ctx.Org.OrgLink + "/settings/hooks" 213 ctx.Data["Description"] = ctx.Tr("org.settings.hooks_desc") 214 215 ws, err := db.Find[webhook.Webhook](ctx, webhook.ListWebhookOptions{OwnerID: ctx.Org.Organization.ID}) 216 if err != nil { 217 ctx.ServerError("ListWebhooksByOpts", err) 218 return 219 } 220 221 err = shared_user.LoadHeaderCount(ctx) 222 if err != nil { 223 ctx.ServerError("LoadHeaderCount", err) 224 return 225 } 226 227 ctx.Data["Webhooks"] = ws 228 ctx.HTML(http.StatusOK, tplSettingsHooks) 229 } 230 231 // DeleteWebhook response for delete webhook 232 func DeleteWebhook(ctx *context.Context) { 233 if err := webhook.DeleteWebhookByOwnerID(ctx, ctx.Org.Organization.ID, ctx.FormInt64("id")); err != nil { 234 ctx.Flash.Error("DeleteWebhookByOwnerID: " + err.Error()) 235 } else { 236 ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success")) 237 } 238 239 ctx.JSONRedirect(ctx.Org.OrgLink + "/settings/hooks") 240 } 241 242 // Labels render organization labels page 243 func Labels(ctx *context.Context) { 244 ctx.Data["Title"] = ctx.Tr("repo.labels") 245 ctx.Data["PageIsOrgSettings"] = true 246 ctx.Data["PageIsOrgSettingsLabels"] = true 247 ctx.Data["LabelTemplateFiles"] = repo_module.LabelTemplateFiles 248 249 err := shared_user.LoadHeaderCount(ctx) 250 if err != nil { 251 ctx.ServerError("LoadHeaderCount", err) 252 return 253 } 254 255 ctx.HTML(http.StatusOK, tplSettingsLabels) 256 }