Skip to content

Commit 47faa79

Browse files
committed
combined password change, email and account deletion into account settings page
1 parent 7392584 commit 47faa79

File tree

11 files changed

+222
-239
lines changed

11 files changed

+222
-239
lines changed

integrations/delete_user_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ func TestUserDeleteAccount(t *testing.T) {
4343
prepareTestEnv(t)
4444

4545
session := loginUser(t, "user8")
46-
csrf := GetCSRF(t, session, "/user/settings/delete")
47-
urlStr := fmt.Sprintf("/user/settings/delete?password=%s", userPassword)
46+
csrf := GetCSRF(t, session, "/user/settings/account")
47+
urlStr := fmt.Sprintf("/user/settings/account/delete?password=%s", userPassword)
4848
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
4949
"_csrf": csrf,
5050
})
@@ -58,8 +58,8 @@ func TestUserDeleteAccountStillOwnRepos(t *testing.T) {
5858
prepareTestEnv(t)
5959

6060
session := loginUser(t, "user2")
61-
csrf := GetCSRF(t, session, "/user/settings/delete")
62-
urlStr := fmt.Sprintf("/user/settings/delete?password=%s", userPassword)
61+
csrf := GetCSRF(t, session, "/user/settings/account")
62+
urlStr := fmt.Sprintf("/user/settings/account/delete?password=%s", userPassword)
6363
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
6464
"_csrf": csrf,
6565
})

integrations/links_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,13 @@ func testLinksAsUser(userName string, t *testing.T) {
9393
"/user2?tab=stars",
9494
"/user2?tab=activity",
9595
"/user/settings",
96+
"/user/settings/account",
9697
"/user/settings/security",
9798
"/user/settings/security/two_factor/enroll",
98-
"/user/settings/email",
9999
"/user/settings/keys",
100100
"/user/settings/applications",
101101
"/user/settings/account_link",
102102
"/user/settings/organization",
103-
"/user/settings/delete",
104103
}
105104

106105
session := loginUser(t, userName)

options/locale/locale_en-US.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ form.name_pattern_not_allowed = The pattern '%s' is not allowed in a username.
305305
306306
[settings]
307307
profile = Profile
308+
account = Account
308309
password = Password
309310
security = Security
310311
avatar = Avatar

routers/routes/routes.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,13 @@ func RegisterRoutes(m *macaron.Macaron) {
219219
m.Post("", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost)
220220
m.Post("/avatar", binding.MultipartForm(auth.AvatarForm{}), user.SettingsAvatarPost)
221221
m.Post("/avatar/delete", user.SettingsDeleteAvatar)
222-
m.Combo("/email").Get(user.SettingsEmails).
223-
Post(bindIgnErr(auth.AddEmailForm{}), user.SettingsEmailPost)
224-
m.Post("/email/delete", user.DeleteEmail)
222+
m.Group("/account", func() {
223+
m.Combo("").Get(user.SettingsAccount).Post(bindIgnErr(auth.ChangePasswordForm{}), user.SettingsAccountPost)
224+
m.Post("/email", bindIgnErr(auth.AddEmailForm{}), user.SettingsEmailPost)
225+
m.Post("/email/delete", user.DeleteEmail)
226+
m.Post("/delete", user.SettingsDelete)
227+
})
225228
m.Get("/security", user.SettingsSecurity)
226-
m.Post("/security", bindIgnErr(auth.ChangePasswordForm{}), user.SettingsSecurityPost)
227229
m.Group("/openid", func() {
228230
m.Combo("").Get(user.SettingsOpenID).
229231
Post(bindIgnErr(auth.AddOpenIDForm{}), user.SettingsOpenIDPost)
@@ -236,7 +238,6 @@ func RegisterRoutes(m *macaron.Macaron) {
236238
m.Combo("/applications").Get(user.SettingsApplications).
237239
Post(bindIgnErr(auth.NewAccessTokenForm{}), user.SettingsApplicationsPost)
238240
m.Post("/applications/delete", user.SettingsDeleteApplication)
239-
m.Route("/delete", "GET,POST", user.SettingsDelete)
240241
m.Combo("/account_link").Get(user.SettingsAccountLinks).Post(user.SettingsDeleteAccountLink)
241242
m.Get("/organization", user.SettingsOrganization)
242243
m.Get("/repos", user.SettingsRepos)

routers/user/setting.go

Lines changed: 71 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import (
3030

3131
const (
3232
tplSettingsProfile base.TplName = "user/settings/profile"
33-
tplSettingsEmails base.TplName = "user/settings/email"
33+
tplSettingsAccount base.TplName = "user/settings/account"
3434
tplSettingsKeys base.TplName = "user/settings/keys"
3535
tplSettingsSocial base.TplName = "user/settings/social"
3636
tplSettingsApplications base.TplName = "user/settings/applications"
@@ -39,7 +39,6 @@ const (
3939
tplSettingsAccountLink base.TplName = "user/settings/account_link"
4040
tplSettingsOrganization base.TplName = "user/settings/organization"
4141
tplSettingsRepositories base.TplName = "user/settings/repos"
42-
tplSettingsDelete base.TplName = "user/settings/delete"
4342
tplSettingsSecurity base.TplName = "user/settings/security"
4443
)
4544

@@ -187,35 +186,29 @@ func SettingsDeleteAvatar(ctx *context.Context) {
187186
ctx.Redirect(setting.AppSubURL + "/user/settings")
188187
}
189188

190-
// SettingsSecurity render change user's password page and 2FA
191-
func SettingsSecurity(ctx *context.Context) {
189+
// SettingsAccount renders change user's password, user's email and user suicide page
190+
func SettingsAccount(ctx *context.Context) {
192191
ctx.Data["Title"] = ctx.Tr("settings")
193-
ctx.Data["PageIsSettingsSecurity"] = true
192+
ctx.Data["PageIsSettingsAccount"] = true
194193
ctx.Data["Email"] = ctx.User.Email
195194

196-
enrolled := true
197-
_, err := models.GetTwoFactorByUID(ctx.User.ID)
195+
emails, err := models.GetEmailAddresses(ctx.User.ID)
198196
if err != nil {
199-
if models.IsErrTwoFactorNotEnrolled(err) {
200-
enrolled = false
201-
} else {
202-
ctx.ServerError("SettingsTwoFactor", err)
203-
return
204-
}
197+
ctx.ServerError("GetEmailAddresses", err)
198+
return
205199
}
200+
ctx.Data["Emails"] = emails
206201

207-
ctx.Data["TwofaEnrolled"] = enrolled
208-
ctx.HTML(200, tplSettingsSecurity)
202+
ctx.HTML(200, tplSettingsAccount)
209203
}
210204

211-
// SettingsSecurityPost response for change user's password
212-
func SettingsSecurityPost(ctx *context.Context, form auth.ChangePasswordForm) {
205+
// SettingsAccountPost response for change user's password
206+
func SettingsAccountPost(ctx *context.Context, form auth.ChangePasswordForm) {
213207
ctx.Data["Title"] = ctx.Tr("settings")
214-
ctx.Data["PageIsSettingsSecurity"] = true
215-
ctx.Data["PageIsSettingsDelete"] = true
208+
ctx.Data["PageIsSettingsAccount"] = true
216209

217210
if ctx.HasError() {
218-
ctx.HTML(200, tplSettingsSecurity)
211+
ctx.HTML(200, tplSettingsAccount)
219212
return
220213
}
221214

@@ -240,28 +233,13 @@ func SettingsSecurityPost(ctx *context.Context, form auth.ChangePasswordForm) {
240233
ctx.Flash.Success(ctx.Tr("settings.change_password_success"))
241234
}
242235

243-
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
244-
}
245-
246-
// SettingsEmails render user's emails page
247-
func SettingsEmails(ctx *context.Context) {
248-
ctx.Data["Title"] = ctx.Tr("settings")
249-
ctx.Data["PageIsSettingsEmails"] = true
250-
251-
emails, err := models.GetEmailAddresses(ctx.User.ID)
252-
if err != nil {
253-
ctx.ServerError("GetEmailAddresses", err)
254-
return
255-
}
256-
ctx.Data["Emails"] = emails
257-
258-
ctx.HTML(200, tplSettingsEmails)
236+
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
259237
}
260238

261239
// SettingsEmailPost response for change user's email
262240
func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) {
263241
ctx.Data["Title"] = ctx.Tr("settings")
264-
ctx.Data["PageIsSettingsEmails"] = true
242+
ctx.Data["PageIsSettingsAccount"] = true
265243

266244
// Make emailaddress primary.
267245
if ctx.Query("_method") == "PRIMARY" {
@@ -271,7 +249,7 @@ func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) {
271249
}
272250

273251
log.Trace("Email made primary: %s", ctx.User.Name)
274-
ctx.Redirect(setting.AppSubURL + "/user/settings/email")
252+
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
275253
return
276254
}
277255

@@ -284,7 +262,7 @@ func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) {
284262
ctx.Data["Emails"] = emails
285263

286264
if ctx.HasError() {
287-
ctx.HTML(200, tplSettingsEmails)
265+
ctx.HTML(200, tplSettingsAccount)
288266
return
289267
}
290268

@@ -295,7 +273,7 @@ func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) {
295273
}
296274
if err := models.AddEmailAddress(email); err != nil {
297275
if models.IsErrEmailAlreadyUsed(err) {
298-
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplSettingsEmails, &form)
276+
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplSettingsAccount, &form)
299277
return
300278
}
301279
ctx.ServerError("AddEmailAddress", err)
@@ -315,7 +293,7 @@ func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) {
315293
}
316294

317295
log.Trace("Email address added: %s", email.Email)
318-
ctx.Redirect(setting.AppSubURL + "/user/settings/email")
296+
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
319297
}
320298

321299
// DeleteEmail response for delete user's email
@@ -328,10 +306,61 @@ func DeleteEmail(ctx *context.Context) {
328306

329307
ctx.Flash.Success(ctx.Tr("settings.email_deletion_success"))
330308
ctx.JSON(200, map[string]interface{}{
331-
"redirect": setting.AppSubURL + "/user/settings/email",
309+
"redirect": setting.AppSubURL + "/user/settings/account",
332310
})
333311
}
334312

313+
// SettingsDelete render user suicide page and response for delete user himself
314+
func SettingsDelete(ctx *context.Context) {
315+
ctx.Data["Title"] = ctx.Tr("settings")
316+
ctx.Data["PageIsSettingsAccount"] = true
317+
318+
if _, err := models.UserSignIn(ctx.User.Name, ctx.Query("password")); err != nil {
319+
if models.IsErrUserNotExist(err) {
320+
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_password"), tplSettingsAccount, nil)
321+
} else {
322+
ctx.ServerError("UserSignIn", err)
323+
}
324+
return
325+
}
326+
327+
if err := models.DeleteUser(ctx.User); err != nil {
328+
switch {
329+
case models.IsErrUserOwnRepos(err):
330+
ctx.Flash.Error(ctx.Tr("form.still_own_repo"))
331+
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
332+
case models.IsErrUserHasOrgs(err):
333+
ctx.Flash.Error(ctx.Tr("form.still_has_org"))
334+
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
335+
default:
336+
ctx.ServerError("DeleteUser", err)
337+
}
338+
} else {
339+
log.Trace("Account deleted: %s", ctx.User.Name)
340+
ctx.Redirect(setting.AppSubURL + "/")
341+
}
342+
}
343+
344+
// SettingsSecurity render change user's password page and 2FA
345+
func SettingsSecurity(ctx *context.Context) {
346+
ctx.Data["Title"] = ctx.Tr("settings")
347+
ctx.Data["PageIsSettingsSecurity"] = true
348+
349+
enrolled := true
350+
_, err := models.GetTwoFactorByUID(ctx.User.ID)
351+
if err != nil {
352+
if models.IsErrTwoFactorNotEnrolled(err) {
353+
enrolled = false
354+
} else {
355+
ctx.ServerError("SettingsTwoFactor", err)
356+
return
357+
}
358+
}
359+
360+
ctx.Data["TwofaEnrolled"] = enrolled
361+
ctx.HTML(200, tplSettingsSecurity)
362+
}
363+
335364
// SettingsKeys render user's SSH/GPG public keys page
336365
func SettingsKeys(ctx *context.Context) {
337366
ctx.Data["Title"] = ctx.Tr("settings")
@@ -730,43 +759,6 @@ func SettingsDeleteAccountLink(ctx *context.Context) {
730759
})
731760
}
732761

733-
// SettingsDelete render user suicide page and response for delete user himself
734-
func SettingsDelete(ctx *context.Context) {
735-
ctx.Data["Title"] = ctx.Tr("settings")
736-
ctx.Data["PageIsSettingsDelete"] = true
737-
ctx.Data["Email"] = ctx.User.Email
738-
739-
if ctx.Req.Method == "POST" {
740-
if _, err := models.UserSignIn(ctx.User.Name, ctx.Query("password")); err != nil {
741-
if models.IsErrUserNotExist(err) {
742-
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_password"), tplSettingsDelete, nil)
743-
} else {
744-
ctx.ServerError("UserSignIn", err)
745-
}
746-
return
747-
}
748-
749-
if err := models.DeleteUser(ctx.User); err != nil {
750-
switch {
751-
case models.IsErrUserOwnRepos(err):
752-
ctx.Flash.Error(ctx.Tr("form.still_own_repo"))
753-
ctx.Redirect(setting.AppSubURL + "/user/settings/delete")
754-
case models.IsErrUserHasOrgs(err):
755-
ctx.Flash.Error(ctx.Tr("form.still_has_org"))
756-
ctx.Redirect(setting.AppSubURL + "/user/settings/delete")
757-
default:
758-
ctx.ServerError("DeleteUser", err)
759-
}
760-
} else {
761-
log.Trace("Account deleted: %s", ctx.User.Name)
762-
ctx.Redirect(setting.AppSubURL + "/")
763-
}
764-
return
765-
}
766-
767-
ctx.HTML(200, tplSettingsDelete)
768-
}
769-
770762
// SettingsOrganization render all the organization of the user
771763
func SettingsOrganization(ctx *context.Context) {
772764
ctx.Data["Title"] = ctx.Tr("settings")

routers/user/setting_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func TestChangePassword(t *testing.T) {
5656
test.LoadUser(t, ctx, 2)
5757
test.LoadRepo(t, ctx, 1)
5858

59-
SettingsSecurityPost(ctx, auth.ChangePasswordForm{
59+
SettingsAccountPost(ctx, auth.ChangePasswordForm{
6060
OldPassword: req.OldPassword,
6161
Password: req.NewPassword,
6262
Retype: req.Retype,

0 commit comments

Comments
 (0)