diff options
-rw-r--r-- | templates/admin/auth/edit.tmpl | 2 | ||||
-rw-r--r-- | templates/admin/auth/new.tmpl | 1 | ||||
-rw-r--r-- | templates/admin/auth/source/ldap.tmpl | 1 | ||||
-rw-r--r-- | templates/admin/user/edit.tmpl | 2 | ||||
-rw-r--r-- | templates/admin/user/new.tmpl | 2 | ||||
-rw-r--r-- | templates/base/disable_form_autofill.tmpl | 31 | ||||
-rw-r--r-- | templates/repo/migrate/git.tmpl | 2 | ||||
-rw-r--r-- | templates/repo/migrate/onedev.tmpl | 2 | ||||
-rw-r--r-- | templates/repo/settings/options.tmpl | 7 | ||||
-rw-r--r-- | templates/repo/settings/webhook/gitea.tmpl | 2 | ||||
-rw-r--r-- | templates/repo/settings/webhook/gogs.tmpl | 2 | ||||
-rw-r--r-- | templates/user/settings/account.tmpl | 3 | ||||
-rw-r--r-- | web_src/less/_base.less | 9 |
13 files changed, 51 insertions, 15 deletions
diff --git a/templates/admin/auth/edit.tmpl b/templates/admin/auth/edit.tmpl index 2f77e9bd80..e7215e2e1a 100644 --- a/templates/admin/auth/edit.tmpl +++ b/templates/admin/auth/edit.tmpl @@ -8,6 +8,7 @@ </h4> <div class="ui attached segment"> <form class="ui form" action="{{.Link}}" method="post"> + {{template "base/disable_form_autofill"}} {{.CsrfTokenHtml}} <input type="hidden" name="id" value="{{.Source.ID}}"> <div class="inline field"> @@ -55,7 +56,6 @@ <label for="bind_dn">{{.i18n.Tr "admin.auths.bind_dn"}}</label> <input id="bind_dn" name="bind_dn" value="{{$cfg.BindDN}}" placeholder="e.g. cn=Search,dc=mydomain,dc=com"> </div> - <input class="fake" type="password"> <div class="field"> <label for="bind_password">{{.i18n.Tr "admin.auths.bind_password"}}</label> <input id="bind_password" name="bind_password" type="password" value="{{$cfg.BindPassword}}"> diff --git a/templates/admin/auth/new.tmpl b/templates/admin/auth/new.tmpl index 13e1366c87..b8e80dbcaa 100644 --- a/templates/admin/auth/new.tmpl +++ b/templates/admin/auth/new.tmpl @@ -8,6 +8,7 @@ </h4> <div class="ui attached segment"> <form class="ui form" action="{{.Link}}" method="post"> + {{template "base/disable_form_autofill"}} {{.CsrfTokenHtml}} <!-- Types and name --> <div class="inline required field {{if .Err_Type}}error{{end}}"> diff --git a/templates/admin/auth/source/ldap.tmpl b/templates/admin/auth/source/ldap.tmpl index b553502b94..9ea0fdf8c0 100644 --- a/templates/admin/auth/source/ldap.tmpl +++ b/templates/admin/auth/source/ldap.tmpl @@ -30,7 +30,6 @@ <label for="bind_dn">{{.i18n.Tr "admin.auths.bind_dn"}}</label> <input id="bind_dn" name="bind_dn" value="{{.bind_dn}}" placeholder="e.g. cn=Search,dc=mydomain,dc=com"> </div> - <input class="fake" type="password"> <div class="ldap field {{if not (eq .type 2)}}hide{{end}}"> <label for="bind_password">{{.i18n.Tr "admin.auths.bind_password"}}</label> <input id="bind_password" name="bind_password" type="password" autocomplete="off" value="{{.bind_password}}"> diff --git a/templates/admin/user/edit.tmpl b/templates/admin/user/edit.tmpl index 60cd8ad523..fb0ccd22bb 100644 --- a/templates/admin/user/edit.tmpl +++ b/templates/admin/user/edit.tmpl @@ -8,6 +8,7 @@ </h4> <div class="ui attached segment"> <form class="ui form" action="{{.Link}}" method="post"> + {{template "base/disable_form_autofill"}} {{.CsrfTokenHtml}} <div class="field {{if .Err_UserName}}error{{end}}"> <label for="user_name">{{.i18n.Tr "username"}}</label> @@ -67,7 +68,6 @@ <label for="email">{{.i18n.Tr "email"}}</label> <input id="email" name="email" type="email" value="{{.User.Email}}" autofocus required> </div> - <input class="fake" type="password"> <div class="local field {{if .Err_Password}}error{{end}} {{if not (or (.User.IsLocal) (.User.IsOAuth2))}}hide{{end}}"> <label for="password">{{.i18n.Tr "password"}}</label> <input id="password" name="password" type="password" autocomplete="new-password"> diff --git a/templates/admin/user/new.tmpl b/templates/admin/user/new.tmpl index 0de1a5c775..27ad28842a 100644 --- a/templates/admin/user/new.tmpl +++ b/templates/admin/user/new.tmpl @@ -8,6 +8,7 @@ </h4> <div class="ui attached segment"> <form class="ui form" action="{{.Link}}" method="post"> + {{template "base/disable_form_autofill"}} {{.CsrfTokenHtml}} <!-- Types and name --> <div class="inline required field {{if .Err_LoginType}}error{{end}}"> @@ -61,7 +62,6 @@ <label for="email">{{.i18n.Tr "email"}}</label> <input id="email" name="email" type="email" value="{{.email}}" required> </div> - <input class="fake" type="password"> <div class="required local field {{if .Err_Password}}error{{end}} {{if not (eq .login_type "0-0")}}hide{{end}}"> <label for="password">{{.i18n.Tr "password"}}</label> <input id="password" name="password" type="password" autocomplete="new-password" value="{{.password}}" {{if eq .login_type "0-0"}}required{{end}}> diff --git a/templates/base/disable_form_autofill.tmpl b/templates/base/disable_form_autofill.tmpl new file mode 100644 index 0000000000..6f06395bed --- /dev/null +++ b/templates/base/disable_form_autofill.tmpl @@ -0,0 +1,31 @@ +{{/* +Why we need to disable form autofill: +1. Many pages contain different password inputs for different usages, eg: repo setting, autofill will make a mess. +2. We have `areYouSure` confirm dialog if a user leaves a pages without submit. +Autofill will make the form changed even if the user didn't input anything. Then the user keeps seeing annoying confirm dialog. + +In history, Gitea put `<input class="fake" type="password">` in forms to bypass the autofill, +but there were still many forms suffered the autofill problem. + +Now we improve it. + +Solutions which do NOT work: +1. Adding `autocomplete=off` doesn't help. New Chrome completely ignores it. +2. Use a JavaScript to run in a few seconds later after the page is loaded to process the autofilled inputs, it doesn't work. +Because for security reason, the inputs won't be filled before the user makes an interaction in the page. +So we can not predict the correct time to run the JavaScript code. + +Solutions which work: +1. Some hacky methods like: https://github.com/matteobad/detect-autofill +2. This solution: use invisible inputs. Be aware of: +(a) The inputs must be at the beginning of the form, and can not be hidden. +(b) The input for username must have a valid name. +(c) There should be no negative word (eg: fake) in the `name` attribute. +(d) Chrome seems to use a weighted algorithm to choose an input to fill text, so the using "username" as input name is better than using "user". +We make the names of these dummy inputs begin with an underline to indicate it is for special usage, +and these dummy form values won't be used by backend code. +*/}} +<div class="autofill-dummy" aria-hidden="true"> + <input type="text" name="_autofill_dummy_username" class="ays-ignore" tabindex="-1"> + <input type="password" name="_autofill_dummy_password" class="ays-ignore" tabindex="-1"> +</div> diff --git a/templates/repo/migrate/git.tmpl b/templates/repo/migrate/git.tmpl index 6525a9b4f5..39f47b27c7 100644 --- a/templates/repo/migrate/git.tmpl +++ b/templates/repo/migrate/git.tmpl @@ -3,6 +3,7 @@ <div class="ui middle very relaxed page grid"> <div class="column"> <form class="ui form" action="{{.Link}}" method="post"> + {{template "base/disable_form_autofill"}} {{.CsrfTokenHtml}} <h3 class="ui top attached header"> {{.i18n.Tr "repo.migrate.migrate" .service.Title}} @@ -21,7 +22,6 @@ <label for="auth_username">{{.i18n.Tr "username"}}</label> <input id="auth_username" name="auth_username" value="{{.auth_username}}" {{if not .auth_username}}data-need-clear="true"{{end}}> </div> - <input class="fake" type="password"> <div class="inline field {{if .Err_Auth}}error{{end}}"> <label for="auth_password">{{.i18n.Tr "password"}}</label> <input id="auth_password" name="auth_password" type="password" value="{{.auth_password}}"> diff --git a/templates/repo/migrate/onedev.tmpl b/templates/repo/migrate/onedev.tmpl index def366f9d8..3dcc253d2e 100644 --- a/templates/repo/migrate/onedev.tmpl +++ b/templates/repo/migrate/onedev.tmpl @@ -3,6 +3,7 @@ <div class="ui middle very relaxed page grid"> <div class="column"> <form class="ui form" action="{{.Link}}" method="post"> + {{template "base/disable_form_autofill"}} {{.CsrfTokenHtml}} <h3 class="ui top attached header"> {{.i18n.Tr "repo.migrate.migrate" .service.Title}} @@ -22,7 +23,6 @@ <label for="auth_username">{{.i18n.Tr "username"}}</label> <input id="auth_username" name="auth_username" value="{{.auth_username}}" {{if not .auth_username}}data-need-clear="true"{{end}}> </div> - <input class="fake" type="password"> <div class="inline field {{if .Err_Auth}}error{{end}}"> <label for="auth_password">{{.i18n.Tr "password"}}</label> <input id="auth_password" name="auth_password" type="password" value="{{.auth_password}}"> diff --git a/templates/repo/settings/options.tmpl b/templates/repo/settings/options.tmpl index 3a44661123..211b7da8e7 100644 --- a/templates/repo/settings/options.tmpl +++ b/templates/repo/settings/options.tmpl @@ -9,6 +9,7 @@ </h4> <div class="ui attached segment"> <form class="ui form" action="{{.Link}}" method="post"> + {{template "base/disable_form_autofill"}} {{.CsrfTokenHtml}} <input type="hidden" name="action" value="update"> <div class="required field {{if .Err_RepoName}}error{{end}}"> @@ -104,6 +105,7 @@ <tr> <td colspan="4"> <form class="ui form" method="post"> + {{template "base/disable_form_autofill"}} {{.CsrfTokenHtml}} <input type="hidden" name="action" value="mirror"> <div class="inline field {{if .Err_EnablePrune}}error{{end}}"> @@ -132,7 +134,6 @@ <label for="mirror_username">{{.i18n.Tr "username"}}</label> <input id="mirror_username" name="mirror_username" value="{{$address.Username}}" {{if not .mirror_username}}data-need-clear="true"{{end}}> </div> - <input class="fake" type="password"> <div class="inline field {{if .Err_Auth}}error{{end}}"> <label for="mirror_password">{{.i18n.Tr "password"}}</label> <input id="mirror_password" name="mirror_password" type="password" placeholder="{{if $address.Password}}{{.i18n.Tr "repo.mirror_password_placeholder"}}{{else}}{{.i18n.Tr "repo.mirror_password_blank_placeholder"}}{{end}}" value="" {{if not .mirror_password}}data-need-clear="true"{{end}} autocomplete="off"> @@ -195,11 +196,12 @@ <tr> <td colspan="4"> <form class="ui form" method="post"> + {{template "base/disable_form_autofill"}} {{.CsrfTokenHtml}} <input type="hidden" name="action" value="push-mirror-add"> <div class="field {{if .Err_PushMirrorAddress}}error{{end}}"> <label for="push_mirror_address">{{.i18n.Tr "repo.settings.mirror_settings.push_mirror.remote_url"}}</label> - <input id="push_mirror_address" name="push_mirror_address" value="{{.push_mirror_address}}" autocomplete="off" required> + <input id="push_mirror_address" name="push_mirror_address" value="{{.push_mirror_address}}" required> <p class="help">{{.i18n.Tr "repo.mirror_address_desc"}}</p> </div> <details class="ui optional field" {{if or .Err_PushMirrorAuth .push_mirror_username}}open{{end}}> @@ -211,7 +213,6 @@ <label for="push_mirror_username">{{.i18n.Tr "username"}}</label> <input id="push_mirror_username" name="push_mirror_username" value="{{.push_mirror_username}}"> </div> - <input class="fake" type="password"> <div class="inline field {{if .Err_PushMirrorAuth}}error{{end}}"> <label for="push_mirror_password">{{.i18n.Tr "password"}}</label> <input id="push_mirror_password" name="push_mirror_password" type="password" value="{{.push_mirror_password}}" autocomplete="off"> diff --git a/templates/repo/settings/webhook/gitea.tmpl b/templates/repo/settings/webhook/gitea.tmpl index bd91ce9e9c..09c49500a4 100644 --- a/templates/repo/settings/webhook/gitea.tmpl +++ b/templates/repo/settings/webhook/gitea.tmpl @@ -1,6 +1,7 @@ {{if eq .HookType "gitea"}} <p>{{.i18n.Tr "repo.settings.add_webhook_desc" "https://docs.gitea.io/en-us/webhooks/" | Str2html}}</p> <form class="ui form" action="{{.BaseLink}}/gitea/{{or .Webhook.ID "new"}}" method="post"> + {{template "base/disable_form_autofill"}} {{.CsrfTokenHtml}} <div class="required field {{if .Err_PayloadURL}}error{{end}}"> <label for="payload_url">{{.i18n.Tr "repo.settings.payload_url"}}</label> @@ -30,7 +31,6 @@ </div> </div> </div> - <input class="fake" type="password"> <div class="field {{if .Err_Secret}}error{{end}}"> <label for="secret">{{.i18n.Tr "repo.settings.secret"}}</label> <input id="secret" name="secret" type="password" value="{{.Webhook.Secret}}" autocomplete="off"> diff --git a/templates/repo/settings/webhook/gogs.tmpl b/templates/repo/settings/webhook/gogs.tmpl index 05fcbe6a5e..3a833ddbdc 100644 --- a/templates/repo/settings/webhook/gogs.tmpl +++ b/templates/repo/settings/webhook/gogs.tmpl @@ -1,6 +1,7 @@ {{if eq .HookType "gogs"}} <p>{{.i18n.Tr "repo.settings.add_webhook_desc" "https://docs.gitea.io/en-us/webhooks/" | Str2html}}</p> <form class="ui form" action="{{.BaseLink}}/gogs/{{or .Webhook.ID "new"}}" method="post"> + {{template "base/disable_form_autofill"}} {{.CsrfTokenHtml}} <div class="required field {{if .Err_PayloadURL}}error{{end}}"> <label for="payload_url">{{.i18n.Tr "repo.settings.payload_url"}}</label> @@ -18,7 +19,6 @@ </div> </div> </div> - <input class="fake" type="password"> <div class="field {{if .Err_Secret}}error{{end}}"> <label for="secret">{{.i18n.Tr "repo.settings.secret"}}</label> <input id="secret" name="secret" type="password" value="{{.Webhook.Secret}}" autocomplete="off"> diff --git a/templates/user/settings/account.tmpl b/templates/user/settings/account.tmpl index 5be3d5dc51..9ed5d3a6dd 100644 --- a/templates/user/settings/account.tmpl +++ b/templates/user/settings/account.tmpl @@ -9,6 +9,7 @@ <div class="ui attached segment"> {{if or (.SignedUser.IsLocal) (.SignedUser.IsOAuth2)}} <form class="ui form ignore-dirty" action="{{AppSubUrl}}/user/settings/account" method="post"> + {{template "base/disable_form_autofill"}} {{.CsrfTokenHtml}} {{if .SignedUser.IsPasswordSet}} <div class="required field {{if .Err_OldPassword}}error{{end}}"> @@ -178,8 +179,8 @@ {{ end }} </div> <form class="ui form ignore-dirty" id="delete-form" action="{{AppSubUrl}}/user/settings/account/delete" method="post"> + {{template "base/disable_form_autofill"}} {{.CsrfTokenHtml}} - <input class="fake" type="password"> <div class="required field {{if .Err_Password}}error{{end}}"> <label for="password-confirmation">{{.i18n.Tr "password"}}</label> <input id="password-confirmation" name="password" type="password" autocomplete="off" required> diff --git a/web_src/less/_base.less b/web_src/less/_base.less index 4e2782a4c8..59585b39e4 100644 --- a/web_src/less/_base.less +++ b/web_src/less/_base.less @@ -962,10 +962,13 @@ a.ui.card:hover, } .form { - .fake { - display: none !important; + .autofill-dummy { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + z-index: -10000; } - .sub.field { margin-left: 25px; } |