Feature #1237 » 0002-adds-a-setting-to-disable-enable-require-2fa-auth.patch
app/controllers/application_controller.rb | ||
---|---|---|
56 | 56 |
end |
57 | 57 |
end |
58 | 58 | |
59 |
before_action :session_expiration, :user_setup, :check_if_login_required, :set_localization, :check_password_change |
|
59 |
before_action :session_expiration, :user_setup, :check_if_login_required, :set_localization, :check_password_change, :check_twofa_activation
|
|
60 | 60 |
after_action :record_project_usage |
61 | 61 | |
62 | 62 |
rescue_from ::Unauthorized, :with => :deny_access |
... | ... | |
89 | 89 |
if user.must_change_password? |
90 | 90 |
session[:pwd] = '1' |
91 | 91 |
end |
92 |
if user.must_activate_twofa? |
|
93 |
session[:must_activate_twofa] = '1' |
|
94 |
end |
|
92 | 95 |
end |
93 | 96 | |
94 | 97 |
def user_setup |
... | ... | |
200 | 203 |
end |
201 | 204 |
end |
202 | 205 | |
206 |
def init_twofa_pairing_and_send_code_for(twofa) |
|
207 |
twofa.init_pairing! |
|
208 |
if twofa.send_code(controller: 'twofa', action: 'activate') |
|
209 |
flash[:notice] = l('twofa_code_sent') |
|
210 |
end |
|
211 |
redirect_to controller: 'twofa', action: 'activate_confirm', scheme: twofa.scheme_name |
|
212 |
end |
|
213 | ||
214 |
def check_twofa_activation |
|
215 |
if session[:must_activate_twofa] |
|
216 |
if User.current.must_activate_twofa? |
|
217 |
flash[:warning] = l('twofa_warning_require') |
|
218 |
if Redmine::Twofa.available_schemes.length == 1 |
|
219 |
twofa_scheme = Redmine::Twofa.for_twofa_scheme(Redmine::Twofa.available_schemes.first) |
|
220 |
twofa = twofa_scheme.new(User.current) |
|
221 |
init_twofa_pairing_and_send_code_for(twofa) |
|
222 |
else |
|
223 |
redirect_to controller: 'twofa', action: 'select_scheme' |
|
224 |
end |
|
225 |
else |
|
226 |
session.delete(:must_activate_twofa) |
|
227 |
end |
|
228 |
end |
|
229 |
end |
|
230 | ||
203 | 231 |
def set_localization(user=User.current) |
204 | 232 |
lang = nil |
205 | 233 |
if user && user.logged? |
app/controllers/twofa_controller.rb | ||
---|---|---|
4 | 4 |
before_action :require_login |
5 | 5 |
before_action :require_admin, only: :admin_deactivate |
6 | 6 | |
7 |
before_action :require_active_twofa |
|
8 | ||
7 | 9 |
require_sudo_mode :activate_init, :deactivate_init |
8 | 10 | |
11 |
skip_before_action :check_twofa_activation, only: [:select_scheme, :activate_init, :activate_confirm, :activate] |
|
12 | ||
13 |
def select_scheme |
|
14 |
@user = User.current |
|
15 |
end |
|
16 | ||
9 | 17 |
before_action :activate_setup, only: [:activate_init, :activate_confirm, :activate] |
10 | 18 | |
11 | 19 |
def activate_init |
12 |
@twofa.init_pairing! |
|
13 |
if @twofa.send_code(controller: 'twofa', action: 'activate') |
|
14 |
flash[:notice] = l('twofa_code_sent') |
|
15 |
end |
|
16 |
redirect_to action: :activate_confirm, scheme: @twofa.scheme_name |
|
20 |
init_twofa_pairing_and_send_code_for(@twofa) |
|
17 | 21 |
end |
18 | 22 | |
19 | 23 |
def activate_confirm |
... | ... | |
84 | 88 |
redirect_to my_account_path |
85 | 89 |
end |
86 | 90 |
end |
91 | ||
92 |
def require_active_twofa |
|
93 |
Setting.twofa? ? true : deny_access |
|
94 |
end |
|
87 | 95 |
end |
app/models/setting.rb | ||
---|---|---|
205 | 205 |
s |
206 | 206 |
end |
207 | 207 | |
208 |
def self.twofa_from_params(params) |
|
209 |
# unpair all current 2FA pairings when switching off 2FA |
|
210 |
Redmine::Twofa.unpair_all! if params == '0' && self.twofa? |
|
211 |
params |
|
212 |
end |
|
213 | ||
208 | 214 |
# Helper that returns an array based on per_page_options setting |
209 | 215 |
def self.per_page_options_array |
210 | 216 |
per_page_options.split(%r{[\s,]}).collect(&:to_i).select {|n| n > 0}.sort |
app/models/user.rb | ||
---|---|---|
381 | 381 |
twofa_scheme.present? |
382 | 382 |
end |
383 | 383 | |
384 |
def must_activate_twofa? |
|
385 |
Setting.twofa == '2' && !twofa_active? |
|
386 |
end |
|
387 | ||
384 | 388 |
def pref |
385 | 389 |
self.preference ||= UserPreference.new(:user => self) |
386 | 390 |
end |
app/views/my/account.html.erb | ||
---|---|---|
28 | 28 |
<% if Setting.openid? %> |
29 | 29 |
<p><%= f.text_field :identity_url %></p> |
30 | 30 |
<% end %> |
31 |
<% if Setting.twofa? -%> |
|
31 | 32 |
<p> |
32 | 33 |
<label><%=l :setting_twofa -%></label> |
33 | 34 |
<% if @user.twofa_active? %> |
... | ... | |
39 | 40 |
<% end %> |
40 | 41 |
<% end %> |
41 | 42 |
</p> |
43 |
<% end -%> |
|
42 | 44 | |
43 | 45 |
<% @user.custom_field_values.select(&:editable?).each do |value| %> |
44 | 46 |
<p><%= custom_field_tag_with_label :user, value %></p> |
app/views/settings/_authentication.html.erb | ||
---|---|---|
26 | 26 | |
27 | 27 |
<p><%= setting_check_box :lost_password %></p> |
28 | 28 | |
29 |
<p> |
|
30 |
<%= setting_select :twofa, [[l(:label_disabled), "0"], |
|
31 |
[l(:label_optional), "1"], |
|
32 |
[l(:label_required_lower), "2"]] -%> |
|
33 |
<em class="info"> |
|
34 |
<%= t 'twofa_hint_disabled_html', label: t(:label_disabled) -%><br/> |
|
35 |
<%= t 'twofa_hint_required_html', label: t(:label_required_lower) -%> |
|
36 |
</em> |
|
37 |
</p> |
|
38 | ||
39 | ||
29 | 40 |
<p><%= setting_check_box :openid, :disabled => !Object.const_defined?(:OpenID) %></p> |
30 | 41 |
</div> |
31 | 42 |
app/views/twofa/activate_confirm.html.erb | ||
---|---|---|
22 | 22 |
<% end %> |
23 | 23 |
</div> |
24 | 24 | |
25 |
<% unless @user.must_activate_twofa? %> |
|
25 | 26 |
<% content_for :sidebar do %> |
26 | 27 |
<%= render :partial => 'my/sidebar' %> |
27 | 28 |
<% end %> |
29 |
<% end %> |
app/views/twofa/select_scheme.html.erb | ||
---|---|---|
1 |
<%= title l('twofa_label_setup') %> |
|
2 | ||
3 |
<%= form_tag({ controller: 'twofa', action: 'activate_init' }, method: :post) do %> |
|
4 |
<div class="box"> |
|
5 |
<p><%=l 'twofa_notice_select' -%></p> |
|
6 |
<p> |
|
7 |
<% Redmine::Twofa.available_schemes.each_with_index do |s, idx| %> |
|
8 |
<label style="display:block;"><%= radio_button_tag 'scheme', s, idx == 0 -%> <%=l "twofa__#{s}__name" -%></label> |
|
9 |
<% end %> |
|
10 |
</p> |
|
11 |
</div> |
|
12 |
<p><%= submit_tag l(:label_next).html_safe + " »".html_safe -%></p> |
|
13 |
<% end %> |
|
14 | ||
15 |
<% unless @user.must_activate_twofa? %> |
|
16 |
<% content_for :sidebar do %> |
|
17 |
<%= render partial: 'my/sidebar' %> |
|
18 |
<% end %> |
|
19 |
<% end %> |
app/views/users/_form.html.erb | ||
---|---|---|
37 | 37 |
<p><%= f.check_box :generate_password %></p> |
38 | 38 |
<p><%= f.check_box :must_change_passwd %></p> |
39 | 39 |
</div> |
40 |
<% if Setting.twofa? -%> |
|
40 | 41 |
<p> |
41 | 42 |
<label><%=l :setting_twofa -%></label> |
42 | 43 |
<% if @user.twofa_active? %> |
... | ... | |
50 | 51 |
<%=l 'twofa_not_active' %> |
51 | 52 |
<% end %> |
52 | 53 |
</p> |
54 |
<% end -%> |
|
53 | 55 |
</fieldset> |
54 | 56 |
</div> |
55 | 57 |
config/locales/de.yml | ||
---|---|---|
718 | 718 |
label_repository_new: Neues Repository |
719 | 719 |
label_repository_plural: Repositories |
720 | 720 |
label_required: Erforderlich |
721 |
label_required_lower: erforderlich |
|
721 | 722 |
label_result_plural: Resultate |
722 | 723 |
label_reverse_chronological_order: in umgekehrter zeitlicher Reihenfolge |
723 | 724 |
label_revision: Revision |
... | ... | |
1297 | 1298 |
twofa_currently_active: "Aktiv: %{twofa_scheme_name}" |
1298 | 1299 |
twofa_not_active: "Nicht aktiv" |
1299 | 1300 |
twofa_label_code: Code |
1301 |
twofa_hint_disabled_html: Die Einstellung <strong>%{label}</strong> deaktiviert Zwei-Faktor-Authentifizierung für alle Nutzer und löscht verbundene Apps. |
|
1302 |
twofa_hint_required_html: Die Einstellung <strong>%{label}</strong> fordert alle Nutzer bei ihrem nächsten Login dazu auf Zwei-Faktor-Authentifizierung einzurichten. |
|
1300 | 1303 |
twofa_label_setup: Zwei-Faktor-Authentifizierung einrichten |
1301 | 1304 |
twofa_label_deactivation_confirmation: Zwei-Faktor-Authentifizierung abschalten |
1305 |
twofa_notice_select: "Bitte wählen Sie Ihr gewünschtes Schema für die Zwei-Faktor-Authentifizierung:" |
|
1306 |
twofa_warning_require: Der Administrator fordert Sie dazu auf Zwei-Faktor-Authentifizierung einzurichten. |
|
1302 | 1307 |
twofa_activated: Zwei-Faktor-Authentifizierung erfolgreich eingerichtet. |
1303 | 1308 |
twofa_deactivated: Zwei-Faktor-Authentifizierung abgeschaltet. |
1304 | 1309 |
twofa_mail_body_security_notification_paired: "Zwei-Faktor-Authentifizierung per %{field} eingerichtet." |
config/locales/en.yml | ||
---|---|---|
853 | 853 |
label_copied_from: Copied from |
854 | 854 |
label_stay_logged_in: Stay logged in |
855 | 855 |
label_disabled: disabled |
856 |
label_optional: optional |
|
856 | 857 |
label_show_completed_versions: Show completed versions |
857 | 858 |
label_me: me |
858 | 859 |
label_board: Forum |
... | ... | |
975 | 976 |
label_fields_permissions: Fields permissions |
976 | 977 |
label_readonly: Read-only |
977 | 978 |
label_required: Required |
979 |
label_required_lower: required |
|
978 | 980 |
label_hidden: Hidden |
979 | 981 |
label_attribute_of_project: "Project's %{name}" |
980 | 982 |
label_attribute_of_issue: "Issue's %{name}" |
... | ... | |
1276 | 1278 |
twofa_currently_active: "Currently active: %{twofa_scheme_name}" |
1277 | 1279 |
twofa_not_active: "Not activated" |
1278 | 1280 |
twofa_label_code: Code |
1281 |
twofa_hint_disabled_html: Setting <strong>%{label}</strong> will deactivate and unpair two-factor authentication devices for all users. |
|
1282 |
twofa_hint_required_html: Setting <strong>%{label}</strong> will require all users to set up two-factor authentication at their next login. |
|
1279 | 1283 |
twofa_label_setup: Enable two-factor authentication |
1280 | 1284 |
twofa_label_deactivation_confirmation: Disable two-factor authentication |
1285 |
twofa_notice_select: "Please select the two-factor scheme you would like to use:" |
|
1286 |
twofa_warning_require: The administrator requires you to enable two-factor authentication. |
|
1281 | 1287 |
twofa_activated: Two-factor authentication successfully enabled. |
1282 | 1288 |
twofa_deactivated: Two-factor authentication disabled. |
1283 | 1289 |
twofa_mail_body_security_notification_paired: "Two-factor authentication successfully enabled using %{field}." |
config/routes.rb | ||
---|---|---|
87 | 87 |
match 'my/add_block', :controller => 'my', :action => 'add_block', :via => :post |
88 | 88 |
match 'my/remove_block', :controller => 'my', :action => 'remove_block', :via => :post |
89 | 89 |
match 'my/order_blocks', :controller => 'my', :action => 'order_blocks', :via => :post |
90 |
match 'my/twofa/activate/init', :controller => 'twofa', :action => 'activate_init', :via => :post |
|
90 | 91 |
match 'my/twofa/:scheme/activate/init', :controller => 'twofa', :action => 'activate_init', :via => :post |
91 | 92 |
match 'my/twofa/:scheme/activate/confirm', :controller => 'twofa', :action => 'activate_confirm', :via => :get |
92 | 93 |
match 'my/twofa/:scheme/activate', :controller => 'twofa', :action => 'activate', :via => [:get, :post] |
93 | 94 |
match 'my/twofa/:scheme/deactivate/init', :controller => 'twofa', :action => 'deactivate_init', :via => :post |
94 | 95 |
match 'my/twofa/:scheme/deactivate/confirm', :controller => 'twofa', :action => 'deactivate_confirm', :via => :get |
95 | 96 |
match 'my/twofa/:scheme/deactivate', :controller => 'twofa', :action => 'deactivate', :via => [:get, :post] |
97 |
match 'my/twofa/select_scheme', :controller => 'twofa', :action => 'select_scheme', :via => :get |
|
96 | 98 |
match 'users/:user_id/twofa/deactivate', :controller => 'twofa', :action => 'admin_deactivate', :via => :post |
97 | 99 | |
98 | 100 |
resources :users do |
config/settings.yml | ||
---|---|---|
34 | 34 |
lost_password: |
35 | 35 |
default: 1 |
36 | 36 |
security_notifications: 1 |
37 |
twofa: |
|
38 |
default: 1 |
|
39 |
security_notifications: 1 |
|
37 | 40 |
unsubscribe: |
38 | 41 |
default: 1 |
39 | 42 |
password_min_length: |
lib/redmine/twofa.rb | ||
---|---|---|
17 | 17 |
for_twofa_scheme(user.twofa_scheme).try(:new, user) |
18 | 18 |
end |
19 | 19 | |
20 |
def self.unpair_all! |
|
21 |
users = User.where.not(twofa_scheme: nil) |
|
22 |
users.each { |u| self.for_user(u).destroy_pairing_without_verify! } |
|
23 |
end |
|
24 | ||
20 | 25 |
private |
21 | 26 | |
22 | 27 |
def self.schemes |