Skip to content

Commit daffaaf

Browse files
committed
rework delete org and rename org
1 parent 416ff1f commit daffaaf

File tree

7 files changed

+177
-102
lines changed

7 files changed

+177
-102
lines changed

options/locale/locale_en-US.ini

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2831,15 +2831,28 @@ settings.visibility.private_shortname = Private
28312831

28322832
settings.update_settings = Update Settings
28332833
settings.update_setting_success = Organization settings have been updated.
2834-
settings.change_orgname_prompt = Note: Changing the organization name will also change your organization's URL and free the old name.
2835-
settings.change_orgname_redirect_prompt = The old name will redirect until it is claimed.
2834+
2835+
settings.rename = Rename Organization
2836+
settings.rename_desc = Changing the organization name will also change your organization's URL and free the old name.
2837+
settings.rename_success = Organization %s have been renamed to %s successfully.
2838+
settings.rename_no_change = Organization name is no change.
2839+
settings.rename_new_org_name = New Organization Name
2840+
settings.rename_failed = Rename Organization failed because of internal error
2841+
settings.rename_notices_1 = - This operation <strong>CANNOT</strong> be undone.
2842+
settings.rename_notices_2 = - The old name will redirect until it is claimed.
2843+
28362844
settings.update_avatar_success = The organization's avatar has been updated.
28372845
settings.delete = Delete Organization
28382846
settings.delete_account = Delete This Organization
28392847
settings.delete_prompt = The organization will be permanently removed. This <strong>CANNOT</strong> be undone!
2848+
settings.name_confirm = Enter the organization name as confirmation:
2849+
settings.delete_notices_1 = - This operation <strong>CANNOT</strong> be undone.
2850+
settings.delete_notices_2 = - This operation will permanently delete all the <strong>repositories</strong> of <strong>%s</strong> including code, issues, comments, wiki data and collaborator settings.
2851+
settings.delete_notices_3 = - This operation will permanently delete all the <strong>packages</strong> of <strong>%s</strong>.
2852+
settings.delete_notices_4 = - This operation will permanently delete all the <strong>projects</strong> of <strong>%s</strong>.
28402853
settings.confirm_delete_account = Confirm Deletion
2841-
settings.delete_org_title = Delete Organization
2842-
settings.delete_org_desc = This organization will be deleted permanently. Continue?
2854+
settings.delete_failed = Delete Organization failed because of internal error
2855+
settings.delete_successful = Organization <b>%s</b> has been deleted successfully.
28432856
settings.hooks_desc = Add webhooks which will be triggered for <strong>all repositories</strong> under this organization.
28442857

28452858
settings.labels_desc = Add labels which can be used on issues for <strong>all repositories</strong> under this organization.

routers/web/org/setting.go

Lines changed: 58 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
repo_module "code.gitea.io/gitea/modules/repository"
1919
"code.gitea.io/gitea/modules/setting"
2020
"code.gitea.io/gitea/modules/templates"
21+
"code.gitea.io/gitea/modules/util"
2122
"code.gitea.io/gitea/modules/web"
2223
shared_user "code.gitea.io/gitea/routers/web/shared/user"
2324
user_setting "code.gitea.io/gitea/routers/web/user/setting"
@@ -31,8 +32,6 @@ import (
3132
const (
3233
// tplSettingsOptions template path for render settings
3334
tplSettingsOptions templates.TplName = "org/settings/options"
34-
// tplSettingsDelete template path for render delete repository
35-
tplSettingsDelete templates.TplName = "org/settings/delete"
3635
// tplSettingsHooks template path for render hook settings
3736
tplSettingsHooks templates.TplName = "org/settings/hooks"
3837
// tplSettingsLabels template path for render labels settings
@@ -71,26 +70,6 @@ func SettingsPost(ctx *context.Context) {
7170

7271
org := ctx.Org.Organization
7372

74-
if org.Name != form.Name {
75-
if err := user_service.RenameUser(ctx, org.AsUser(), form.Name); err != nil {
76-
if user_model.IsErrUserAlreadyExist(err) {
77-
ctx.Data["Err_Name"] = true
78-
ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), tplSettingsOptions, &form)
79-
} else if db.IsErrNameReserved(err) {
80-
ctx.Data["Err_Name"] = true
81-
ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(db.ErrNameReserved).Name), tplSettingsOptions, &form)
82-
} else if db.IsErrNamePatternNotAllowed(err) {
83-
ctx.Data["Err_Name"] = true
84-
ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tplSettingsOptions, &form)
85-
} else {
86-
ctx.ServerError("RenameUser", err)
87-
}
88-
return
89-
}
90-
91-
ctx.Org.OrgLink = setting.AppSubURL + "/org/" + url.PathEscape(org.Name)
92-
}
93-
9473
if form.Email != "" {
9574
if err := user_service.ReplacePrimaryEmailAddress(ctx, org.AsUser(), form.Email); err != nil {
9675
ctx.Data["Err_Email"] = true
@@ -165,40 +144,28 @@ func SettingsDeleteAvatar(ctx *context.Context) {
165144

166145
// SettingsDelete response for deleting an organization
167146
func SettingsDelete(ctx *context.Context) {
168-
ctx.Data["Title"] = ctx.Tr("org.settings")
169-
ctx.Data["PageIsOrgSettings"] = true
170-
ctx.Data["PageIsSettingsDelete"] = true
171-
172-
if ctx.Req.Method == http.MethodPost {
173-
if ctx.Org.Organization.Name != ctx.FormString("org_name") {
174-
ctx.Data["Err_OrgName"] = true
175-
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_org_name"), tplSettingsDelete, nil)
176-
return
177-
}
178-
179-
if err := org_service.DeleteOrganization(ctx, ctx.Org.Organization, false); err != nil {
180-
if repo_model.IsErrUserOwnRepos(err) {
181-
ctx.Flash.Error(ctx.Tr("form.org_still_own_repo"))
182-
ctx.Redirect(ctx.Org.OrgLink + "/settings/delete")
183-
} else if packages_model.IsErrUserOwnPackages(err) {
184-
ctx.Flash.Error(ctx.Tr("form.org_still_own_packages"))
185-
ctx.Redirect(ctx.Org.OrgLink + "/settings/delete")
186-
} else {
187-
ctx.ServerError("DeleteOrganization", err)
188-
}
189-
} else {
190-
log.Trace("Organization deleted: %s", ctx.Org.Organization.Name)
191-
ctx.Redirect(setting.AppSubURL + "/")
192-
}
147+
if ctx.Org.Organization.Name != ctx.FormString("org_name") {
148+
ctx.Flash.Error(ctx.Tr("form.enterred_invalid_org_name"))
149+
ctx.JSONRedirect(ctx.Org.OrgLink + "/settings")
193150
return
194151
}
195152

196-
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
197-
ctx.ServerError("RenderUserOrgHeader", err)
153+
if err := org_service.DeleteOrganization(ctx, ctx.Org.Organization, false); err != nil {
154+
if repo_model.IsErrUserOwnRepos(err) {
155+
ctx.Flash.Error(ctx.Tr("form.org_still_own_repo"))
156+
} else if packages_model.IsErrUserOwnPackages(err) {
157+
ctx.Flash.Error(ctx.Tr("form.org_still_own_packages"))
158+
} else {
159+
log.Error("DeleteOrganization: %v", err)
160+
ctx.Flash.Error(util.Iif(ctx.Doer.IsAdmin, err.Error(), string(ctx.Tr("org.settings.delete_failed"))))
161+
}
162+
ctx.JSONRedirect(ctx.Org.OrgLink + "/settings")
198163
return
199164
}
200165

201-
ctx.HTML(http.StatusOK, tplSettingsDelete)
166+
log.Trace("Organization deleted: %s", ctx.Org.Organization.Name)
167+
ctx.Flash.Success(ctx.Tr("org.settings.delete_successful", ctx.Org.Organization.Name))
168+
ctx.JSONRedirect(setting.AppSubURL + "/")
202169
}
203170

204171
// Webhooks render webhook list page
@@ -250,3 +217,44 @@ func Labels(ctx *context.Context) {
250217

251218
ctx.HTML(http.StatusOK, tplSettingsLabels)
252219
}
220+
221+
// SettingsRename response for renaming organization
222+
func SettingsRename(ctx *context.Context) {
223+
form := web.GetForm(ctx).(*forms.RenameOrgForm)
224+
org := ctx.Org.Organization
225+
226+
if org.Name != form.OrgName {
227+
ctx.Flash.Error(ctx.Tr("form.enterred_invalid_org_name"))
228+
ctx.JSONRedirect(ctx.Org.OrgLink + "/settings")
229+
return
230+
}
231+
232+
if org.Name == form.NewOrgName {
233+
ctx.Flash.Error(ctx.Tr("org.settings.rename_no_change"))
234+
ctx.JSONRedirect(ctx.Org.OrgLink + "/settings")
235+
return
236+
}
237+
238+
oldOrgName := org.Name
239+
240+
if err := user_service.RenameUser(ctx, org.AsUser(), form.NewOrgName); err != nil {
241+
if user_model.IsErrUserAlreadyExist(err) {
242+
ctx.Flash.Error(ctx.Tr("form.username_been_taken"))
243+
} else if db.IsErrNameReserved(err) {
244+
ctx.Flash.Error(ctx.Tr("repo.form.name_reserved"))
245+
} else if db.IsErrNamePatternNotAllowed(err) {
246+
ctx.Flash.Error(ctx.Tr("repo.form.name_pattern_not_allowed"))
247+
} else {
248+
log.Error("RenameOrganization: %v", err)
249+
ctx.Flash.Error(util.Iif(ctx.Doer.IsAdmin, err.Error(), string(ctx.Tr("org.settings.rename_failed"))))
250+
}
251+
ctx.JSONRedirect(ctx.Org.OrgLink + "/settings")
252+
return
253+
}
254+
255+
ctx.Org.OrgLink = setting.AppSubURL + "/org/" + url.PathEscape(org.Name)
256+
257+
log.Trace("Organization renamed to %s", org.Name)
258+
ctx.Flash.Success(ctx.Tr("org.settings.rename_success", oldOrgName, org.Name))
259+
ctx.JSONRedirect(ctx.Org.OrgLink + "/settings")
260+
}

routers/web/web.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -964,7 +964,8 @@ func registerWebRoutes(m *web.Router) {
964964
addSettingsVariablesRoutes()
965965
}, actions.MustEnableActions)
966966

967-
m.Methods("GET,POST", "/delete", org.SettingsDelete)
967+
m.Post("/rename", web.Bind(forms.RenameOrgForm{}), org.SettingsRename)
968+
m.Post("/delete", org.SettingsDelete)
968969

969970
m.Group("/packages", func() {
970971
m.Get("", org.Packages)

services/forms/org.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ func (f *CreateOrgForm) Validate(req *http.Request, errs binding.Errors) binding
3636

3737
// UpdateOrgSettingForm form for updating organization settings
3838
type UpdateOrgSettingForm struct {
39-
Name string `binding:"Required;Username;MaxSize(40)" locale:"org.org_name_holder"`
4039
FullName string `binding:"MaxSize(100)"`
4140
Email string `binding:"MaxSize(255)"`
4241
Description string `binding:"MaxSize(255)"`
@@ -53,6 +52,11 @@ func (f *UpdateOrgSettingForm) Validate(req *http.Request, errs binding.Errors)
5352
return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
5453
}
5554

55+
type RenameOrgForm struct {
56+
OrgName string `binding:"Required;Username;MaxSize(40)"`
57+
NewOrgName string `binding:"Required;Username;MaxSize(40)"`
58+
}
59+
5660
// ___________
5761
// \__ ___/___ _____ _____
5862
// | |_/ __ \\__ \ / \

templates/org/settings/delete.tmpl

Lines changed: 0 additions & 35 deletions
This file was deleted.

templates/org/settings/navbar.tmpl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,5 @@
4141
</div>
4242
</details>
4343
{{end}}
44-
<a class="{{if .PageIsSettingsDelete}}active {{end}}item" href="{{.OrgLink}}/settings/delete">
45-
{{ctx.Locale.Tr "org.settings.delete"}}
46-
</a>
4744
</div>
4845
</div>

templates/org/settings/options.tmpl

Lines changed: 95 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,6 @@
66
<div class="ui attached segment">
77
<form class="ui form" action="{{.Link}}" method="post">
88
{{.CsrfTokenHtml}}
9-
<div class="required field {{if .Err_Name}}error{{end}}">
10-
<label for="org_name">{{ctx.Locale.Tr "org.org_name_holder"}}
11-
<span class="text red tw-hidden" id="org-name-change-prompt">
12-
<br>{{ctx.Locale.Tr "org.settings.change_orgname_prompt"}}<br>{{ctx.Locale.Tr "org.settings.change_orgname_redirect_prompt"}}
13-
</span>
14-
</label>
15-
<input id="org_name" name="name" value="{{.Org.Name}}" data-org-name="{{.Org.Name}}" required maxlength="40">
16-
</div>
179
<div class="field {{if .Err_FullName}}error{{end}}">
1810
<label for="full_name">{{ctx.Locale.Tr "org.org_full_name_holder"}}</label>
1911
<input id="full_name" name="full_name" value="{{.Org.FullName}}" maxlength="100">
@@ -97,5 +89,100 @@
9789
</div>
9890
</form>
9991
</div>
92+
93+
<h4 class="ui top attached error header">
94+
{{ctx.Locale.Tr "repo.settings.danger_zone"}}
95+
</h4>
96+
<div class="ui attached error danger segment">
97+
<div class="flex-list">
98+
<div class="flex-item tw-items-center">
99+
<div class="flex-item-main">
100+
<div class="flex-item-title">{{ctx.Locale.Tr "org.settings.rename"}}</div>
101+
<div class="flex-item-body">{{ctx.Locale.Tr "org.settings.rename_desc"}}</div>
102+
</div>
103+
<div class="flex-item-trailing">
104+
<button class="ui basic red show-modal button" data-modal="#rename-org-modal">{{ctx.Locale.Tr "org.settings.rename"}}</button>
105+
</div>
106+
</div>
107+
108+
<div class="flex-item">
109+
<div class="flex-item-main">
110+
<div class="flex-item-title">{{ctx.Locale.Tr "org.settings.delete_account"}}</div>
111+
<div class="flex-item-body">{{ctx.Locale.Tr "org.settings.delete_prompt"}}</div>
112+
</div>
113+
<div class="flex-item-trailing">
114+
<button class="ui basic red show-modal button" data-modal="#delete-org-modal">{{ctx.Locale.Tr "org.settings.delete_account"}}</button>
115+
</div>
116+
</div>
117+
</div>
118+
</div>
100119
</div>
120+
121+
<div class="ui small modal" id="rename-org-modal">
122+
<div class="header">
123+
{{ctx.Locale.Tr "org.settings.rename"}}
124+
</div>
125+
<div class="content">
126+
<div class="ui warning message">
127+
{{ctx.Locale.Tr "org.settings.rename_notices_1"}}<br>
128+
{{ctx.Locale.Tr "org.settings.rename_notices_2"}}
129+
</div>
130+
<form class="ui form form-fetch-action" action="{{.Link}}/rename" method="post">
131+
{{.CsrfTokenHtml}}
132+
<div class="field">
133+
<label>
134+
{{ctx.Locale.Tr "org.settings.name_confirm"}}
135+
<span class="text red">{{.Org.Name}}</span>
136+
</label>
137+
</div>
138+
<div class="required field">
139+
<label for="org_name_to_rename">{{ctx.Locale.Tr "org.org_name_holder"}}</label>
140+
<input id="org_name_to_rename" name="org_name" required>
141+
</div>
142+
143+
<div class="required field">
144+
<label for="repo_name_to_delete">{{ctx.Locale.Tr "org.settings.rename_new_org_name"}}</label>
145+
<input id="new_org_name" name="new_org_name" required>
146+
</div>
147+
148+
<div class="actions">
149+
<button class="ui cancel button">{{ctx.Locale.Tr "settings.cancel"}}</button>
150+
<button class="ui red button">{{ctx.Locale.Tr "org.settings.rename"}}</button>
151+
</div>
152+
</form>
153+
</div>
154+
</div>
155+
156+
<div class="ui small modal" id="delete-org-modal">
157+
<div class="header">
158+
{{ctx.Locale.Tr "org.settings.delete_account"}}
159+
</div>
160+
<div class="content">
161+
<div class="ui warning message">
162+
{{ctx.Locale.Tr "org.settings.delete_notices_1"}}<br/>
163+
{{ctx.Locale.Tr "org.settings.delete_notices_2" .Org.Name}}<br/>
164+
{{ctx.Locale.Tr "org.settings.delete_notices_3" .Org.Name}}<br/>
165+
{{ctx.Locale.Tr "org.settings.delete_notices_4" .Org.Name}}
166+
</div>
167+
<form class="ui form form-fetch-action" action="{{.Link}}/delete" method="post">
168+
{{.CsrfTokenHtml}}
169+
<div class="field">
170+
<label>
171+
{{ctx.Locale.Tr "org.settings.name_confirm"}}
172+
<span class="text red">{{.Org.Name}}</span>
173+
</label>
174+
</div>
175+
<div class="required field">
176+
<label for="org_name_to_delete">{{ctx.Locale.Tr "org.org_name_holder"}}</label>
177+
<input id="org_name_to_delete" name="org_name" required>
178+
</div>
179+
180+
<div class="actions">
181+
<button class="ui cancel button">{{ctx.Locale.Tr "settings.cancel"}}</button>
182+
<button class="ui red button">{{ctx.Locale.Tr "org.settings.delete_account"}}</button>
183+
</div>
184+
</form>
185+
</div>
186+
</div>
187+
101188
{{template "org/settings/layout_footer" .}}

0 commit comments

Comments
 (0)