]> source.dussan.org Git - gitea.git/commitdiff
Merge password and 2fa page on user settings (#2695)
authorLunny Xiao <xiaolunwen@gmail.com>
Mon, 16 Oct 2017 09:14:12 +0000 (17:14 +0800)
committerKim "BKC" Carlbäcker <kim.carlbacker@gmail.com>
Mon, 16 Oct 2017 09:14:12 +0000 (11:14 +0200)
* merge password and 2fa page on user settings

integrations/links_test.go
options/locale/locale_en-US.ini
routers/routes/routes.go
routers/user/setting.go
templates/user/settings/navbar.tmpl
templates/user/settings/password.tmpl [deleted file]
templates/user/settings/security.tmpl [new file with mode: 0644]

index bab147bdd9b1be07648092b215279b4e2e93fbab..d9d647f4b9da2e1ffa0351f0c02e035263e5ef06 100644 (file)
@@ -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",
index fede39484c811e40cd3baa913778b8ef80f99889..f664827821546595badbcf1072ce81782e9a4500 100644 (file)
@@ -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
index a6f73aaedd9a9f82e19ea6f2a5ef6a32d64bd205..749f8263f8c3c7c5a510a09985c61149c9c78cb9 100644 (file)
@@ -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)
index b71b29ba21cb3211ac4b53b6dee25b86b1140ab7..a00f3f287a7dd7154489a587ad536cf7ba938bd8 100644 (file)
@@ -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
index b0a3c9fcc32529fb1499f37b9b30d34954e2d05d..a6c497794f3f358dce62878aed15bb1403e694ac 100644 (file)
@@ -5,8 +5,8 @@
        <a class="{{if .PageIsSettingsAvatar}}active{{end}} item" href="{{AppSubUrl}}/user/settings/avatar">
                {{.i18n.Tr "settings.avatar"}}
        </a>
-       <a class="{{if .PageIsSettingsPassword}}active{{end}} item" href="{{AppSubUrl}}/user/settings/password">
-               {{.i18n.Tr "settings.password"}}
+       <a class="{{if .PageIsSettingsSecurity}}active{{end}} item" href="{{AppSubUrl}}/user/settings/security">
+               {{.i18n.Tr "settings.security"}}
        </a>
        <a class="{{if .PageIsSettingsEmails}}active{{end}} item" href="{{AppSubUrl}}/user/settings/email">
                {{.i18n.Tr "settings.emails"}}
@@ -22,9 +22,6 @@
        <a class="{{if .PageIsSettingsApplications}}active{{end}} item" href="{{AppSubUrl}}/user/settings/applications">
                {{.i18n.Tr "settings.applications"}}
        </a>
-       <a class="{{if .PageIsSettingsTwofa}}active{{end}} item" href="{{AppSubUrl}}/user/settings/two_factor">
-               {{.i18n.Tr "settings.twofa"}}
-       </a>
        <a class="{{if .PageIsSettingsAccountLink}}active{{end}} item" href="{{AppSubUrl}}/user/settings/account_link">
                {{.i18n.Tr "settings.account_link"}}
        </a>
diff --git a/templates/user/settings/password.tmpl b/templates/user/settings/password.tmpl
deleted file mode 100644 (file)
index 53872c9..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-{{template "base/head" .}}
-<div class="user settings password">
-       {{template "user/settings/navbar" .}}
-       <div class="ui container">
-               {{template "base/alert" .}}
-               <h4 class="ui top attached header">
-                       {{.i18n.Tr "settings.change_password"}}
-               </h4>
-               <div class="ui attached segment">
-                       {{if or (.SignedUser.IsLocal) (.SignedUser.IsOAuth2)}}
-                       <form class="ui form" action="{{.Link}}" method="post">
-                               {{.CsrfTokenHtml}}
-                               {{if .SignedUser.IsPasswordSet}}
-                               <div class="required field {{if .Err_OldPassword}}error{{end}}">
-                                       <label for="old_password">{{.i18n.Tr "settings.old_password"}}</label>
-                                       <input id="old_password" name="old_password" type="password" autocomplete="off" autofocus required>
-                               </div>
-                               {{end}}
-                               <div class="required field {{if .Err_Password}}error{{end}}">
-                                       <label for="password">{{.i18n.Tr "settings.new_password"}}</label>
-                                       <input id="password" name="password" type="password" autocomplete="off" required>
-                               </div>
-                               <div class="required field {{if .Err_Password}}error{{end}}">
-                                       <label for="retype">{{.i18n.Tr "settings.retype_new_password"}}</label>
-                                       <input id="retype" name="retype" type="password" autocomplete="off" required>
-                               </div>
-
-                               <div class="field">
-                                       <button class="ui green button">{{$.i18n.Tr "settings.change_password"}}</button>
-                                       <a href="{{AppSubUrl}}/user/forgot_password?email={{.Email}}">{{.i18n.Tr "auth.forgot_password"}}</a>
-                               </div>
-                       </form>
-                       {{else}}
-                       <div class="ui info message">
-                               <p class="text left">{{$.i18n.Tr "settings.password_change_disabled"}}</p>
-                       </div>
-                       {{end}}
-               </div>
-       </div>
-</div>
-{{template "base/footer" .}}
diff --git a/templates/user/settings/security.tmpl b/templates/user/settings/security.tmpl
new file mode 100644 (file)
index 0000000..a956a3f
--- /dev/null
@@ -0,0 +1,79 @@
+{{template "base/head" .}}
+<div class="user settings password">
+       {{template "user/settings/navbar" .}}
+       <div class="ui container">
+               {{template "base/alert" .}}
+               <h4 class="ui top attached header">
+                       {{.i18n.Tr "settings.password"}}
+               </h4>
+               <div class="ui attached segment">
+                       {{if or (.SignedUser.IsLocal) (.SignedUser.IsOAuth2)}}
+                       <form class="ui form" action="{{.Link}}?tp=password" method="post">
+                               {{.CsrfTokenHtml}}
+                               {{if .SignedUser.IsPasswordSet}}
+                               <div class="required field {{if .Err_OldPassword}}error{{end}}">
+                                       <label for="old_password">{{.i18n.Tr "settings.old_password"}}</label>
+                                       <input id="old_password" name="old_password" type="password" autocomplete="off" autofocus required>
+                               </div>
+                               {{end}}
+                               <div class="required field {{if .Err_Password}}error{{end}}">
+                                       <label for="password">{{.i18n.Tr "settings.new_password"}}</label>
+                                       <input id="password" name="password" type="password" autocomplete="off" required>
+                               </div>
+                               <div class="required field {{if .Err_Password}}error{{end}}">
+                                       <label for="retype">{{.i18n.Tr "settings.retype_new_password"}}</label>
+                                       <input id="retype" name="retype" type="password" autocomplete="off" required>
+                               </div>
+
+                               <div class="field">
+                                       <button class="ui green button">{{$.i18n.Tr "settings.change_password"}}</button>
+                                       <a href="{{AppSubUrl}}/user/forgot_password?email={{.Email}}">{{.i18n.Tr "auth.forgot_password"}}</a>
+                               </div>
+                       </form>
+                       {{else}}
+                       <div class="ui info message">
+                               <p class="text left">{{$.i18n.Tr "settings.password_change_disabled"}}</p>
+                       </div>
+                       {{end}}
+               </div>
+        <br/>
+
+        <h4 class="ui top attached header">
+                       {{.i18n.Tr "settings.twofa"}}
+               </h4>
+        <div class="ui attached segment">
+            <p>{{.i18n.Tr "settings.twofa_desc"}}</p>
+            {{if .TwofaEnrolled}}
+            <p>{{$.i18n.Tr "settings.twofa_is_enrolled" | Str2html }}</p>
+            <form class="ui form" action="{{.Link}}/two_factor/regenerate_scratch" method="post" enctype="multipart/form-data">
+                {{.CsrfTokenHtml}}
+                <p>{{.i18n.Tr "settings.regenerate_scratch_token_desc"}}</p>
+                <button class="ui blue button">{{$.i18n.Tr "settings.twofa_scratch_token_regenerate"}}</button>
+            </form>
+            <form class="ui form" action="{{.Link}}/two_factor/disable" method="post" enctype="multipart/form-data" id="disable-form">
+                {{.CsrfTokenHtml}}
+                <p>{{.i18n.Tr "settings.twofa_disable_note"}}</p>
+                <div class="ui red button delete-button" data-type="form" data-form="#disable-form">{{$.i18n.Tr "settings.twofa_disable"}}</div>
+            </form>
+            {{else}}
+            <p>{{.i18n.Tr "settings.twofa_not_enrolled"}}</p>
+            <div class="inline field">
+                <a class="ui green button" href="{{.Link}}/two_factor/enroll">{{$.i18n.Tr "settings.twofa_enroll"}}</a>
+            </div>
+            {{end}}
+        </div>
+       </div>
+</div>
+
+<div class="ui small basic delete modal">
+       <div class="ui icon header">
+               <i class="trash icon"></i>
+               {{.i18n.Tr "settings.twofa_disable"}}
+       </div>
+       <div class="content">
+               <p>{{.i18n.Tr "settings.twofa_disable_desc"}}</p>
+       </div>
+       {{template "base/delete_modal_actions" .}}
+</div>
+
+{{template "base/footer" .}}