1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
- breadcrumb_title _('Two-Factor Authentication')
- page_title _('Two-Factor Authentication'), _('Account')
- add_to_breadcrumbs _('Account'), profile_account_path
- @content_class = "limit-container-width" unless fluid_layout
- webauthn_enabled = Feature.enabled?(:webauthn)
.js-two-factor-auth{ 'data-two-factor-skippable' => "#{two_factor_skippable?}", 'data-two_factor_skip_url' => skip_profile_two_factor_auth_path }
.row.gl-mt-3
.col-lg-4
%h4.gl-mt-0
= _('Register Two-Factor Authenticator')
%p
= _('Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA).')
.col-lg-8
- if current_user.two_factor_otp_enabled?
%p
= _("You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication.")
%p
= _('If you lose your recovery codes you can generate new ones, invalidating all previous codes.')
- if @error
= render Pajamas::AlertComponent.new(title: @error[:message],
variant: :danger,
alert_options: { class: 'gl-mb-3' },
dismissible: false) do |c|
= c.body do
= link_to _('Try the troubleshooting steps here.'), help_page_path('user/profile/account/two_factor_authentication.md', anchor: 'troubleshooting'), target: '_blank', rel: 'noopener noreferrer'
.js-manage-two-factor-form{ data: { webauthn_enabled: webauthn_enabled, current_password_required: current_password_required?.to_s, profile_two_factor_auth_path: profile_two_factor_auth_path, profile_two_factor_auth_method: 'delete', codes_profile_two_factor_auth_path: codes_profile_two_factor_auth_path, codes_profile_two_factor_auth_method: 'post' } }
- else
%p
- register_2fa_token = _('We recommend using cloud-based authenticator applications that can restore access if you lose your hardware device.')
= register_2fa_token.html_safe
= link_to _('What are some examples?'), help_page_path('user/profile/account/two_factor_authentication', anchor: 'enable-one-time-password'), target: '_blank', rel: 'noopener noreferrer'
.row.gl-mb-3
.col-md-4.gl-min-w-fit-content
.gl-p-2.gl-mb-3{ style: 'background: #fff' }
= raw @qr_code
.col-md-8
.gl-card
.gl-card-body
%p.gl-mt-0.gl-mb-3.gl-font-weight-bold
= _("Can't scan the code?")
%p.gl-mt-0.gl-mb-3
= _('To add the entry manually, provide the following details to the application on your phone.')
%p.gl-mt-0.gl-mb-0
= _('Account: %{account}') % { account: @account_string }
%p.gl-mt-0.gl-mb-0{ data: { qa_selector: 'otp_secret_content' } }
= _('Key:')
%code.two-factor-secret= current_user.otp_secret.scan(/.{4}/).join(' ')
%p.gl-mb-0.two-factor-new-manual-content
= _('Time based: Yes')
= form_tag profile_two_factor_auth_path, method: :post do |f|
- if @error
= render Pajamas::AlertComponent.new(title: @error[:message],
variant: :danger,
alert_options: { class: 'gl-mb-3' },
dismissible: false) do |c|
= c.body do
= link_to _('Try the troubleshooting steps here.'), help_page_path('user/profile/account/two_factor_authentication.md', anchor: 'troubleshooting'), target: '_blank', rel: 'noopener noreferrer'
.form-group
= label_tag :pin_code, _('Pin code'), class: "label-bold"
= text_field_tag :pin_code, nil, class: "form-control gl-form-input", required: true, data: { qa_selector: 'pin_code_field' }
- if current_password_required?
.form-group
= label_tag :current_password, _('Current password'), class: 'label-bold'
= password_field_tag :current_password, nil, autocomplete: 'current-password', required: true, class: 'form-control gl-form-input', data: { qa_selector: 'current_password_field' }
%p.form-text.text-muted
= _('Your current password is required to register a two-factor authenticator app.')
.gl-mt-3
= submit_tag _('Register with two-factor app'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'register_2fa_app_button' }
%hr
.row.gl-mt-3
.col-lg-4
%h4.gl-mt-0
- if webauthn_enabled
= _('Register WebAuthn Device')
- else
= _('Register Universal Two-Factor (U2F) Device')
%p
= _('Set up a hardware device as a second factor to sign in.')
%p
- if webauthn_enabled
= _("Not all browsers support WebAuthn. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even from an unsupported browser.")
- else
= _("Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser.")
.col-lg-8
- registration = webauthn_enabled ? @webauthn_registration : @u2f_registration
- if registration.errors.present?
= form_errors(registration)
- if webauthn_enabled
= render "authentication/register", target_path: create_webauthn_profile_two_factor_auth_path
- else
= render "authentication/register", target_path: create_u2f_profile_two_factor_auth_path
%hr
%h5
- if webauthn_enabled
= _('WebAuthn Devices (%{length})') % { length: @registrations.length }
- else
= _('U2F Devices (%{length})') % { length: @registrations.length }
- if @registrations.present?
.table-responsive
%table.table.table-bordered.u2f-registrations
%colgroup
%col{ width: "50%" }
%col{ width: "30%" }
%col{ width: "20%" }
%thead
%tr
%th= _('Name')
%th= s_('2FADevice|Registered On')
%th
%tbody
- @registrations.each do |registration|
%tr
%td
- if registration[:name].present?
= registration[:name]
- else
%span.gl-text-gray-500
= _("no name set")
%td= registration[:created_at].to_date.to_s(:medium)
%td
= render Pajamas::ButtonComponent.new(variant: :danger,
href: registration[:delete_path],
method: :delete,
button_options: { class: 'float-right', data: { confirm: _('Are you sure you want to delete this device? This action cannot be undone.'), confirm_btn_variant: "danger" }, aria: { label: _('Delete') }}) do
= _('Delete')
- else
.settings-message.text-center
- if webauthn_enabled
= _("You don't have any WebAuthn devices registered yet.")
- else
= _("You don't have any U2F devices registered yet.")
|