diff options
| -rw-r--r-- | app/views/elevations/new.html.erb | 3 | ||||
| -rw-r--r-- | app/views/otp_challenges/new.html.erb | 9 | ||||
| -rw-r--r-- | app/views/otp_enrollments/show.html.erb | 5 | ||||
| -rw-r--r-- | app/views/users/edit.html.erb | 5 | ||||
| -rw-r--r-- | config/locales/de.yml | 1 | ||||
| -rw-r--r-- | config/locales/en.yml | 1 | ||||
| -rw-r--r-- | public/javascripts/admin_interface.js | 9 | ||||
| -rw-r--r-- | public/stylesheets/admin.css | 18 |
8 files changed, 43 insertions, 8 deletions
diff --git a/app/views/elevations/new.html.erb b/app/views/elevations/new.html.erb index 8dd64e78..8e1b59c2 100644 --- a/app/views/elevations/new.html.erb +++ b/app/views/elevations/new.html.erb | |||
| @@ -10,7 +10,8 @@ | |||
| 10 | <div class="layout_row_label"><%= t(".code") %></div> | 10 | <div class="layout_row_label"><%= t(".code") %></div> |
| 11 | <div class="layout_row_content"> | 11 | <div class="layout_row_content"> |
| 12 | <%= text_field_tag :code, nil, :autocomplete => "one-time-code", | 12 | <%= text_field_tag :code, nil, :autocomplete => "one-time-code", |
| 13 | :inputmode => "numeric", :autofocus => true %> | 13 | :inputmode => "numeric", :autofocus => true, :maxlength => 6, |
| 14 | :pattern => "[0-9]{6}", :class => "otp_code" %> | ||
| 14 | </div> | 15 | </div> |
| 15 | </div> | 16 | </div> |
| 16 | 17 | ||
diff --git a/app/views/otp_challenges/new.html.erb b/app/views/otp_challenges/new.html.erb index 8247b262..ff7df222 100644 --- a/app/views/otp_challenges/new.html.erb +++ b/app/views/otp_challenges/new.html.erb | |||
| @@ -6,10 +6,13 @@ | |||
| 6 | <div class="layout_row_content"> | 6 | <div class="layout_row_content"> |
| 7 | <%= form_tag otp_challenge_path, :method => :post, :class => "otp_form" do %> | 7 | <%= form_tag otp_challenge_path, :method => :post, :class => "otp_form" do %> |
| 8 | <%= text_field_tag :code, nil, :autofocus => true, | 8 | <%= text_field_tag :code, nil, :autofocus => true, |
| 9 | :autocomplete => "one-time-code", :inputmode => "numeric" %> | 9 | :autocomplete => "one-time-code", :inputmode => "numeric", |
| 10 | <%= submit_tag t(".log_in") %> | 10 | :maxlength => 6, :pattern => "[0-9]{6}", :class => "otp_code" %> |
| 11 | <span class="field_hint"> <%= t(".hint") %> </span> | ||
| 12 | <%= button_tag :type => "submit", :class => "action_button" do %> | ||
| 13 | <%= icon("shield-check", library: "tabler", "aria-hidden": true) %> <%= t(".log_in") %> | ||
| 14 | <% end %> | ||
| 11 | <% end %> | 15 | <% end %> |
| 12 | <span class="field_hint"> <%= t(".hint") %> </span> | ||
| 13 | </div> | 16 | </div> |
| 14 | </div> | 17 | </div> |
| 15 | </div> | 18 | </div> |
diff --git a/app/views/otp_enrollments/show.html.erb b/app/views/otp_enrollments/show.html.erb index 16addb5b..a7604dd2 100644 --- a/app/views/otp_enrollments/show.html.erb +++ b/app/views/otp_enrollments/show.html.erb | |||
| @@ -18,12 +18,13 @@ | |||
| 18 | <div class="layout_row_content"> | 18 | <div class="layout_row_content"> |
| 19 | <%= form_tag otp_enrollment_path, :method => :put, :class => "otp_form" do %> | 19 | <%= form_tag otp_enrollment_path, :method => :put, :class => "otp_form" do %> |
| 20 | <%= text_field_tag :code, nil, :autofocus => true, | 20 | <%= text_field_tag :code, nil, :autofocus => true, |
| 21 | :autocomplete => "one-time-code", :inputmode => "numeric" %> | 21 | :autocomplete => "one-time-code", :inputmode => "numeric", |
| 22 | :maxlength => 6, :pattern => "[0-9]{6}", :class => "otp_code" %> | ||
| 23 | <span class="field_hint"> <%= t(".app_hint", :issuer => OTP_ISSUER) %></span> | ||
| 22 | <%= button_tag :type => "submit", :class => "action_button" do %> | 24 | <%= button_tag :type => "submit", :class => "action_button" do %> |
| 23 | <%= icon("shield-check", library: "tabler", "aria-hidden": true) %> <%= t(".confirm") %> | 25 | <%= icon("shield-check", library: "tabler", "aria-hidden": true) %> <%= t(".confirm") %> |
| 24 | <% end %> | 26 | <% end %> |
| 25 | <% end %> | 27 | <% end %> |
| 26 | <span class="field_hint"> <%= t(".app_hint", :issuer => OTP_ISSUER) %></span> | ||
| 27 | </div> | 28 | </div> |
| 28 | </div> | 29 | </div> |
| 29 | </div> | 30 | </div> |
diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb index 2cf5a07c..14e19e39 100644 --- a/app/views/users/edit.html.erb +++ b/app/views/users/edit.html.erb | |||
| @@ -59,8 +59,9 @@ | |||
| 59 | <p><%= t(".enabled") %></p> | 59 | <p><%= t(".enabled") %></p> |
| 60 | <%= form_tag otp_enrollment_path, :method => :delete, :class => "otp_form" do %> | 60 | <%= form_tag otp_enrollment_path, :method => :delete, :class => "otp_form" do %> |
| 61 | <%= password_field_tag :current_password, nil, :placeholder => t(".current_password"), :autocomplete => "current-password" %> | 61 | <%= password_field_tag :current_password, nil, :placeholder => t(".current_password"), :autocomplete => "current-password" %> |
| 62 | <%= text_field_tag :code, nil, :placeholder => t(".current_code"), | 62 | <%= text_field_tag :code, nil, :autocomplete => "one-time-code", :inputmode => "numeric", |
| 63 | :autocomplete => "one-time-code", :inputmode => "numeric" %> | 63 | :maxlength => 6, :pattern => "[0-9]{6}", :class => "otp_code" %> |
| 64 | <span class="field_hint"> <%= t(".reset_hint") %> </span> | ||
| 64 | <%= button_tag :type => "submit", :class => "action_button" do %> | 65 | <%= button_tag :type => "submit", :class => "action_button" do %> |
| 65 | <%= icon("shield-off", library: "tabler", "aria-hidden": true) %> <%= t(".disable_second_factor") %> | 66 | <%= icon("shield-off", library: "tabler", "aria-hidden": true) %> <%= t(".disable_second_factor") %> |
| 66 | <% end %> | 67 | <% end %> |
diff --git a/config/locales/de.yml b/config/locales/de.yml index c6082bcd..ed263f6e 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml | |||
| @@ -303,6 +303,7 @@ de: | |||
| 303 | enable_second_factor: "Zweiten Faktor aktivieren" | 303 | enable_second_factor: "Zweiten Faktor aktivieren" |
| 304 | disable_second_factor: "Zweiten Faktor entfernen" | 304 | disable_second_factor: "Zweiten Faktor entfernen" |
| 305 | reset_second_factor: "Zweiten Faktor zurücksetzen" | 305 | reset_second_factor: "Zweiten Faktor zurücksetzen" |
| 306 | reset_hint: "Gib den sechsstelligen Code aus deiner Authenticator-App ein." | ||
| 306 | reset_confirm: "Zweiten Faktor von %{login} zurücksetzen? Die Anmeldung ist danach nur mit Passwort möglich." | 307 | reset_confirm: "Zweiten Faktor von %{login} zurücksetzen? Die Anmeldung ist danach nur mit Passwort möglich." |
| 307 | labels: | 308 | labels: |
| 308 | login: "Anmeldename" | 309 | login: "Anmeldename" |
diff --git a/config/locales/en.yml b/config/locales/en.yml index 5aafb612..78414dc5 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml | |||
| @@ -255,6 +255,7 @@ en: | |||
| 255 | enable_second_factor: "Enable second factor" | 255 | enable_second_factor: "Enable second factor" |
| 256 | disable_second_factor: "Disable second factor" | 256 | disable_second_factor: "Disable second factor" |
| 257 | reset_second_factor: "Reset second factor" | 257 | reset_second_factor: "Reset second factor" |
| 258 | reset_hint: "Enter the six-digit code from your authenticator app." | ||
| 258 | reset_confirm: "Reset %{login}'s second factor? They will log in with password only afterwards." | 259 | reset_confirm: "Reset %{login}'s second factor? They will log in with password only afterwards." |
| 259 | labels: | 260 | labels: |
| 260 | login: "login" | 261 | login: "login" |
diff --git a/public/javascripts/admin_interface.js b/public/javascripts/admin_interface.js index b7cb1964..8fe105a7 100644 --- a/public/javascripts/admin_interface.js +++ b/public/javascripts/admin_interface.js | |||
| @@ -90,6 +90,15 @@ $(document).ready(function () { | |||
| 90 | initialize_revision_diff_picker.initialize(); | 90 | initialize_revision_diff_picker.initialize(); |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | if (document.querySelector('.otp_code')) { | ||
| 94 | document.querySelectorAll('.otp_code').forEach(function (field) { | ||
| 95 | field.addEventListener('input', function () { | ||
| 96 | var digits = field.value.replace(/\D/g, '').slice(0, 6); | ||
| 97 | if (field.value !== digits) { field.value = digits; } | ||
| 98 | }); | ||
| 99 | }); | ||
| 100 | } | ||
| 101 | |||
| 93 | var metadata_details = document.getElementById('metadata_details'); | 102 | var metadata_details = document.getElementById('metadata_details'); |
| 94 | if (metadata_details) { | 103 | if (metadata_details) { |
| 95 | var desktop_mq = window.matchMedia('(min-width: 1016px)'); | 104 | var desktop_mq = window.matchMedia('(min-width: 1016px)'); |
diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css index 9d96acd0..0dc1a048 100644 --- a/public/stylesheets/admin.css +++ b/public/stylesheets/admin.css | |||
| @@ -2245,6 +2245,24 @@ form.otp_form input[type=text] { | |||
| 2245 | margin-bottom: 0.5rem; | 2245 | margin-bottom: 0.5rem; |
| 2246 | } | 2246 | } |
| 2247 | 2247 | ||
| 2248 | input[type=text].otp_code { | ||
| 2249 | font-family: monospace; | ||
| 2250 | font-weight: 800; | ||
| 2251 | font-variant-numeric: tabular-nums; | ||
| 2252 | font-size: 2rem; | ||
| 2253 | letter-spacing: 0.75em; | ||
| 2254 | text-align: left; | ||
| 2255 | |||
| 2256 | padding: 0.75rem 0 0.75rem 1.75rem; | ||
| 2257 | box-sizing: border-box; | ||
| 2258 | max-width: 18.5rem; | ||
| 2259 | background-color: var(--surface); | ||
| 2260 | background-image: repeating-linear-gradient(to right, var(--surface) 0 1ch, var(--surface-tint) 1ch calc(1ch + 0.75em)); | ||
| 2261 | background-repeat: no-repeat; | ||
| 2262 | background-position: 0.45rem; | ||
| 2263 | background-size: calc(6ch + 4.5em) calc(100% - 1.25rem); | ||
| 2264 | } | ||
| 2265 | |||
| 2248 | .otp_qr svg { | 2266 | .otp_qr svg { |
| 2249 | width: 220px; | 2267 | width: 220px; |
| 2250 | height: auto; | 2268 | height: auto; |
