diff --git a/integrations/links_test.go b/integrations/links_test.go index bab147bdd9..d9d647f4b9 100644 --- a/integrations/links_test.go +++ b/integrations/links_test.go @@ -71,11 +71,11 @@ func testLinksAsUser(userName string, t *testing.T) { "/user2?tab=activity", "/user/settings", "/user/settings/avatar", - "/user/settings/password", + "/user/settings/security", + "/user/settings/security/two_factor/enroll", "/user/settings/email", "/user/settings/keys", "/user/settings/applications", - "/user/settings/two_factor", "/user/settings/account_link", "/user/settings/organization", "/user/settings/delete", diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index fede39484c..f664827821 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -303,6 +303,7 @@ form.name_pattern_not_allowed = The username pattern '%s' is not allowed. [settings] profile = Profile password = Password +security = Security avatar = Avatar ssh_gpg_keys = SSH / GPG Keys social = Social Accounts diff --git a/routers/routes/routes.go b/routers/routes/routes.go index a6f73aaedd..749f8263f8 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -220,8 +220,8 @@ func RegisterRoutes(m *macaron.Macaron) { m.Combo("/email").Get(user.SettingsEmails). Post(bindIgnErr(auth.AddEmailForm{}), user.SettingsEmailPost) m.Post("/email/delete", user.DeleteEmail) - m.Get("/password", user.SettingsPassword) - m.Post("/password", bindIgnErr(auth.ChangePasswordForm{}), user.SettingsPasswordPost) + m.Get("/security", user.SettingsSecurity) + m.Post("/security", bindIgnErr(auth.ChangePasswordForm{}), user.SettingsSecurityPost) m.Group("/openid", func() { m.Combo("").Get(user.SettingsOpenID). Post(bindIgnErr(auth.AddOpenIDForm{}), user.SettingsOpenIDPost) @@ -238,8 +238,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Combo("/account_link").Get(user.SettingsAccountLinks).Post(user.SettingsDeleteAccountLink) m.Get("/organization", user.SettingsOrganization) m.Get("/repos", user.SettingsRepos) - m.Group("/two_factor", func() { - m.Get("", user.SettingsTwoFactor) + m.Group("/security/two_factor", func() { m.Post("/regenerate_scratch", user.SettingsTwoFactorRegenerateScratch) m.Post("/disable", user.SettingsTwoFactorDisable) m.Get("/enroll", user.SettingsTwoFactorEnroll) diff --git a/routers/user/setting.go b/routers/user/setting.go index b71b29ba21..a00f3f287a 100644 --- a/routers/user/setting.go +++ b/routers/user/setting.go @@ -41,7 +41,7 @@ const ( tplSettingsOrganization base.TplName = "user/settings/organization" tplSettingsRepositories base.TplName = "user/settings/repos" tplSettingsDelete base.TplName = "user/settings/delete" - tplSecurity base.TplName = "user/security" + tplSettingsSecurity base.TplName = "user/settings/security" ) // Settings render user's profile page @@ -191,22 +191,35 @@ func SettingsDeleteAvatar(ctx *context.Context) { ctx.Redirect(setting.AppSubURL + "/user/settings/avatar") } -// SettingsPassword render change user's password page -func SettingsPassword(ctx *context.Context) { +// SettingsSecurity render change user's password page and 2FA +func SettingsSecurity(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings") - ctx.Data["PageIsSettingsPassword"] = true + ctx.Data["PageIsSettingsSecurity"] = true ctx.Data["Email"] = ctx.User.Email - ctx.HTML(200, tplSettingsPassword) + + enrolled := true + _, err := models.GetTwoFactorByUID(ctx.User.ID) + if err != nil { + if models.IsErrTwoFactorNotEnrolled(err) { + enrolled = false + } else { + ctx.Handle(500, "SettingsTwoFactor", err) + return + } + } + + ctx.Data["TwofaEnrolled"] = enrolled + ctx.HTML(200, tplSettingsSecurity) } -// SettingsPasswordPost response for change user's password -func SettingsPasswordPost(ctx *context.Context, form auth.ChangePasswordForm) { +// SettingsSecurityPost response for change user's password +func SettingsSecurityPost(ctx *context.Context, form auth.ChangePasswordForm) { ctx.Data["Title"] = ctx.Tr("settings") - ctx.Data["PageIsSettingsPassword"] = true + ctx.Data["PageIsSettingsSecurity"] = true ctx.Data["PageIsSettingsDelete"] = true if ctx.HasError() { - ctx.HTML(200, tplSettingsPassword) + ctx.HTML(200, tplSettingsSecurity) return } @@ -230,7 +243,7 @@ func SettingsPasswordPost(ctx *context.Context, form auth.ChangePasswordForm) { ctx.Flash.Success(ctx.Tr("settings.change_password_success")) } - ctx.Redirect(setting.AppSubURL + "/user/settings/password") + ctx.Redirect(setting.AppSubURL + "/user/settings/security") } // SettingsEmails render user's emails page @@ -509,30 +522,10 @@ func SettingsDeleteApplication(ctx *context.Context) { }) } -// SettingsTwoFactor renders the 2FA page. -func SettingsTwoFactor(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("settings") - ctx.Data["PageIsSettingsTwofa"] = true - - enrolled := true - _, err := models.GetTwoFactorByUID(ctx.User.ID) - if err != nil { - if models.IsErrTwoFactorNotEnrolled(err) { - enrolled = false - } else { - ctx.Handle(500, "SettingsTwoFactor", err) - return - } - } - - ctx.Data["TwofaEnrolled"] = enrolled - ctx.HTML(200, tplSettingsTwofa) -} - // SettingsTwoFactorRegenerateScratch regenerates the user's 2FA scratch code. func SettingsTwoFactorRegenerateScratch(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings") - ctx.Data["PageIsSettingsTwofa"] = true + ctx.Data["PageIsSettingsSecurity"] = true t, err := models.GetTwoFactorByUID(ctx.User.ID) if err != nil { @@ -551,13 +544,13 @@ func SettingsTwoFactorRegenerateScratch(ctx *context.Context) { } ctx.Flash.Success(ctx.Tr("settings.twofa_scratch_token_regenerated", t.ScratchToken)) - ctx.Redirect(setting.AppSubURL + "/user/settings/two_factor") + ctx.Redirect(setting.AppSubURL + "/user/settings/security") } // SettingsTwoFactorDisable deletes the user's 2FA settings. func SettingsTwoFactorDisable(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings") - ctx.Data["PageIsSettingsTwofa"] = true + ctx.Data["PageIsSettingsSecurity"] = true t, err := models.GetTwoFactorByUID(ctx.User.ID) if err != nil { @@ -571,7 +564,7 @@ func SettingsTwoFactorDisable(ctx *context.Context) { } ctx.Flash.Success(ctx.Tr("settings.twofa_disabled")) - ctx.Redirect(setting.AppSubURL + "/user/settings/two_factor") + ctx.Redirect(setting.AppSubURL + "/user/settings/security") } func twofaGenerateSecretAndQr(ctx *context.Context) bool { @@ -615,7 +608,7 @@ func twofaGenerateSecretAndQr(ctx *context.Context) bool { // SettingsTwoFactorEnroll shows the page where the user can enroll into 2FA. func SettingsTwoFactorEnroll(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings") - ctx.Data["PageIsSettingsTwofa"] = true + ctx.Data["PageIsSettingsSecurity"] = true t, err := models.GetTwoFactorByUID(ctx.User.ID) if t != nil { @@ -638,7 +631,7 @@ func SettingsTwoFactorEnroll(ctx *context.Context) { // SettingsTwoFactorEnrollPost handles enrolling the user into 2FA. func SettingsTwoFactorEnrollPost(ctx *context.Context, form auth.TwoFactorAuthForm) { ctx.Data["Title"] = ctx.Tr("settings") - ctx.Data["PageIsSettingsTwofa"] = true + ctx.Data["PageIsSettingsSecurity"] = true t, err := models.GetTwoFactorByUID(ctx.User.ID) if t != nil { @@ -691,7 +684,7 @@ func SettingsTwoFactorEnrollPost(ctx *context.Context, form auth.TwoFactorAuthFo ctx.Session.Delete("twofaSecret") ctx.Session.Delete("twofaUri") ctx.Flash.Success(ctx.Tr("settings.twofa_enrolled", t.ScratchToken)) - ctx.Redirect(setting.AppSubURL + "/user/settings/two_factor") + ctx.Redirect(setting.AppSubURL + "/user/settings/security") } // SettingsAccountLinks render the account links settings page diff --git a/templates/user/settings/navbar.tmpl b/templates/user/settings/navbar.tmpl index b0a3c9fcc3..a6c497794f 100644 --- a/templates/user/settings/navbar.tmpl +++ b/templates/user/settings/navbar.tmpl @@ -5,8 +5,8 @@ {{.i18n.Tr "settings.avatar"}} - - {{.i18n.Tr "settings.password"}} + + {{.i18n.Tr "settings.security"}} {{.i18n.Tr "settings.emails"}} @@ -22,9 +22,6 @@ {{.i18n.Tr "settings.applications"}} - - {{.i18n.Tr "settings.twofa"}} - {{.i18n.Tr "settings.account_link"}} diff --git a/templates/user/settings/password.tmpl b/templates/user/settings/password.tmpl deleted file mode 100644 index 53872c901d..0000000000 --- a/templates/user/settings/password.tmpl +++ /dev/null @@ -1,41 +0,0 @@ -{{template "base/head" .}} -
- {{template "user/settings/navbar" .}} -
- {{template "base/alert" .}} -

- {{.i18n.Tr "settings.change_password"}} -

-
- {{if or (.SignedUser.IsLocal) (.SignedUser.IsOAuth2)}} -
- {{.CsrfTokenHtml}} - {{if .SignedUser.IsPasswordSet}} -
- - -
- {{end}} -
- - -
-
- - -
- -
- - {{.i18n.Tr "auth.forgot_password"}} -
-
- {{else}} -
-

{{$.i18n.Tr "settings.password_change_disabled"}}

-
- {{end}} -
-
-
-{{template "base/footer" .}} diff --git a/templates/user/settings/security.tmpl b/templates/user/settings/security.tmpl new file mode 100644 index 0000000000..a956a3fcb3 --- /dev/null +++ b/templates/user/settings/security.tmpl @@ -0,0 +1,79 @@ +{{template "base/head" .}} +
+ {{template "user/settings/navbar" .}} +
+ {{template "base/alert" .}} +

+ {{.i18n.Tr "settings.password"}} +

+
+ {{if or (.SignedUser.IsLocal) (.SignedUser.IsOAuth2)}} +
+ {{.CsrfTokenHtml}} + {{if .SignedUser.IsPasswordSet}} +
+ + +
+ {{end}} +
+ + +
+
+ + +
+ +
+ + {{.i18n.Tr "auth.forgot_password"}} +
+
+ {{else}} +
+

{{$.i18n.Tr "settings.password_change_disabled"}}

+
+ {{end}} +
+
+ +

+ {{.i18n.Tr "settings.twofa"}} +

+
+

{{.i18n.Tr "settings.twofa_desc"}}

+ {{if .TwofaEnrolled}} +

{{$.i18n.Tr "settings.twofa_is_enrolled" | Str2html }}

+
+ {{.CsrfTokenHtml}} +

{{.i18n.Tr "settings.regenerate_scratch_token_desc"}}

+ +
+
+ {{.CsrfTokenHtml}} +

{{.i18n.Tr "settings.twofa_disable_note"}}

+
{{$.i18n.Tr "settings.twofa_disable"}}
+
+ {{else}} +

{{.i18n.Tr "settings.twofa_not_enrolled"}}

+ + {{end}} +
+
+
+ + + +{{template "base/footer" .}}