Feature #1237 » 0002-2-factor-authentication-disabled-enabled-required.patch
| app/controllers/application_controller.rb | ||
|---|---|---|
| 51 | 51 |
end |
| 52 | 52 |
end |
| 53 | 53 | |
| 54 |
before_action :session_expiration, :user_setup, :check_if_login_required, :set_localization, :check_password_change |
|
| 54 |
before_action :session_expiration, :user_setup, :check_if_login_required, :set_localization, :check_password_change, :check_twofa_activation
|
|
| 55 | 55 | |
| 56 | 56 |
rescue_from ::Unauthorized, :with => :deny_access |
| 57 | 57 |
rescue_from ::ActionView::MissingTemplate, :with => :missing_template |
| ... | ... | |
| 83 | 83 |
if user.must_change_password? |
| 84 | 84 |
session[:pwd] = '1' |
| 85 | 85 |
end |
| 86 |
if user.must_activate_twofa? |
|
| 87 |
session[:must_activate_twofa] = '1' |
|
| 88 |
end |
|
| 86 | 89 |
end |
| 87 | 90 | |
| 88 | 91 |
def user_setup |
| ... | ... | |
| 194 | 197 |
end |
| 195 | 198 |
end |
| 196 | 199 | |
| 200 |
def init_twofa_pairing_and_send_code_for(twofa) |
|
| 201 |
twofa.init_pairing! |
|
| 202 |
if twofa.send_code(controller: 'twofa', action: 'activate') |
|
| 203 |
flash[:notice] = l('twofa_code_sent')
|
|
| 204 |
end |
|
| 205 |
redirect_to controller: 'twofa', action: 'activate_confirm', scheme: twofa.scheme_name |
|
| 206 |
end |
|
| 207 | ||
| 208 |
def check_twofa_activation |
|
| 209 |
if session[:must_activate_twofa] |
|
| 210 |
if User.current.must_activate_twofa? |
|
| 211 |
flash[:warning] = l('twofa_warning_require')
|
|
| 212 |
if Redmine::Twofa.available_schemes.length == 1 |
|
| 213 |
twofa_scheme = Redmine::Twofa.for_twofa_scheme(Redmine::Twofa.available_schemes.first) |
|
| 214 |
twofa = twofa_scheme.new(User.current) |
|
| 215 |
init_twofa_pairing_and_send_code_for(twofa) |
|
| 216 |
else |
|
| 217 |
redirect_to controller: 'twofa', action: 'select_scheme' |
|
| 218 |
end |
|
| 219 |
else |
|
| 220 |
session.delete(:must_activate_twofa) |
|
| 221 |
end |
|
| 222 |
end |
|
| 223 |
end |
|
| 224 | ||
| 197 | 225 |
def set_localization(user=User.current) |
| 198 | 226 |
lang = nil |
| 199 | 227 |
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 | ||
|---|---|---|
| 198 | 198 |
s |
| 199 | 199 |
end |
| 200 | 200 | |
| 201 |
def self.twofa_from_params(params) |
|
| 202 |
# unpair all current 2FA pairings when switching off 2FA |
|
| 203 |
Redmine::Twofa.unpair_all! if params == '0' && self.twofa? |
|
| 204 |
params |
|
| 205 |
end |
|
| 206 | ||
| 201 | 207 |
# Helper that returns an array based on per_page_options setting |
| 202 | 208 |
def self.per_page_options_array |
| 203 | 209 |
per_page_options.split(%r{[\s,]}).collect(&:to_i).select {|n| n > 0}.sort
|
| app/models/user.rb | ||
|---|---|---|
| 373 | 373 |
twofa_scheme.present? |
| 374 | 374 |
end |
| 375 | 375 | |
| 376 |
def must_activate_twofa? |
|
| 377 |
Setting.twofa == '2' && !twofa_active? |
|
| 378 |
end |
|
| 379 | ||
| 376 | 380 |
def pref |
| 377 | 381 |
self.preference ||= UserPreference.new(:user => self) |
| 378 | 382 |
end |
| app/views/my/account.html.erb | ||
|---|---|---|
| 27 | 27 |
<% if Setting.openid? %> |
| 28 | 28 |
<p><%= f.text_field :identity_url %></p> |
| 29 | 29 |
<% end %> |
| 30 |
<% if Setting.twofa? -%> |
|
| 30 | 31 |
<p> |
| 31 | 32 |
<label><%=l :setting_twofa -%></label> |
| 32 | 33 |
<% if @user.twofa_active? %> |
| ... | ... | |
| 38 | 39 |
<% end %> |
| 39 | 40 |
<% end %> |
| 40 | 41 |
</p> |
| 42 |
<% end -%> |
|
| 41 | 43 | |
| 42 | 44 |
<% @user.custom_field_values.select(&:editable?).each do |value| %> |
| 43 | 45 |
<p><%= custom_field_tag_with_label :user, value %></p> |
| app/views/settings/_authentication.html.erb | ||
|---|---|---|
| 25 | 25 | |
| 26 | 26 |
<p><%= setting_check_box :lost_password %></p> |
| 27 | 27 | |
| 28 |
<p> |
|
| 29 |
<%= setting_select :twofa, [[l(:label_disabled), "0"], |
|
| 30 |
[l(:label_optional), "1"], |
|
| 31 |
[l(:label_required_lower), "2"]] -%> |
|
| 32 |
<em class="info"> |
|
| 33 |
<%= t 'twofa_hint_disabled_html', label: t(:label_disabled) -%><br/> |
|
| 34 |
<%= t 'twofa_hint_required_html', label: t(:label_required_lower) -%> |
|
| 35 |
</em> |
|
| 36 |
</p> |
|
| 37 | ||
| 28 | 38 |
<p><%= setting_text_field :max_additional_emails, :size => 6 %></p> |
| 29 | 39 | |
| 30 | 40 |
<p><%= setting_check_box :openid, :disabled => !Object.const_defined?(:OpenID) %></p> |
| 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 | ||
|---|---|---|
| 36 | 36 |
<p><%= f.check_box :generate_password %></p> |
| 37 | 37 |
<p><%= f.check_box :must_change_passwd %></p> |
| 38 | 38 |
</div> |
| 39 |
<% if Setting.twofa? -%> |
|
| 39 | 40 |
<p> |
| 40 | 41 |
<label><%=l :setting_twofa -%></label> |
| 41 | 42 |
<% if @user.twofa_active? %> |
| ... | ... | |
| 49 | 50 |
<%=l 'twofa_not_active' %> |
| 50 | 51 |
<% end %> |
| 51 | 52 |
</p> |
| 53 |
<% end -%> |
|
| 52 | 54 |
</fieldset> |
| 53 | 55 |
</div> |
| 54 | 56 | |
| config/locales/de.yml | ||
|---|---|---|
| 713 | 713 |
label_repository_new: Neues Repository |
| 714 | 714 |
label_repository_plural: Repositories |
| 715 | 715 |
label_required: Erforderlich |
| 716 |
label_required_lower: erforderlich |
|
| 716 | 717 |
label_result_plural: Resultate |
| 717 | 718 |
label_reverse_chronological_order: in umgekehrter zeitlicher Reihenfolge |
| 718 | 719 |
label_revision: Revision |
| ... | ... | |
| 1244 | 1245 |
twofa_currently_active: "Aktiv: %{twofa_scheme_name}"
|
| 1245 | 1246 |
twofa_not_active: "Nicht aktiv" |
| 1246 | 1247 |
twofa_label_code: Code |
| 1248 |
twofa_hint_disabled_html: Die Einstellung <strong>%{label}</strong> deaktiviert Zwei-Faktor-Authentifizierung für alle Nutzer und löscht verbundene Apps.
|
|
| 1249 |
twofa_hint_required_html: Die Einstellung <strong>%{label}</strong> fordert alle Nutzer bei ihrem nächsten Login dazu auf Zwei-Faktor-Authentifizierung einzurichten.
|
|
| 1247 | 1250 |
twofa_label_setup: Zwei-Faktor-Authentifizierung einrichten |
| 1248 | 1251 |
twofa_label_deactivation_confirmation: Zwei-Faktor-Authentifizierung abschalten |
| 1252 |
twofa_notice_select: "Bitte wählen Sie Ihr gewünschtes Schema für die Zwei-Faktor-Authentifizierung:" |
|
| 1253 |
twofa_warning_require: Der Administrator fordert Sie dazu auf Zwei-Faktor-Authentifizierung einzurichten. |
|
| 1249 | 1254 |
twofa_activated: Zwei-Faktor-Authentifizierung erfolgreich eingerichtet. |
| 1250 | 1255 |
twofa_deactivated: Zwei-Faktor-Authentifizierung abgeschaltet. |
| 1251 | 1256 |
twofa_mail_body_security_notification_paired: "Zwei-Faktor-Authentifizierung per %{field} eingerichtet."
|
| config/locales/en.yml | ||
|---|---|---|
| 836 | 836 |
label_copied_from: Copied from |
| 837 | 837 |
label_stay_logged_in: Stay logged in |
| 838 | 838 |
label_disabled: disabled |
| 839 |
label_optional: optional |
|
| 839 | 840 |
label_show_completed_versions: Show completed versions |
| 840 | 841 |
label_me: me |
| 841 | 842 |
label_board: Forum |
| ... | ... | |
| 953 | 954 |
label_fields_permissions: Fields permissions |
| 954 | 955 |
label_readonly: Read-only |
| 955 | 956 |
label_required: Required |
| 957 |
label_required_lower: required |
|
| 956 | 958 |
label_hidden: Hidden |
| 957 | 959 |
label_attribute_of_project: "Project's %{name}"
|
| 958 | 960 |
label_attribute_of_issue: "Issue's %{name}"
|
| ... | ... | |
| 1225 | 1227 |
twofa_currently_active: "Currently active: %{twofa_scheme_name}"
|
| 1226 | 1228 |
twofa_not_active: "Not activated" |
| 1227 | 1229 |
twofa_label_code: Code |
| 1230 |
twofa_hint_disabled_html: Setting <strong>%{label}</strong> will deactivate and unpair two-factor authentication devices for all users.
|
|
| 1231 |
twofa_hint_required_html: Setting <strong>%{label}</strong> will require all users to set up two-factor authentication at their next login.
|
|
| 1228 | 1232 |
twofa_label_setup: Enable two-factor authentication |
| 1229 | 1233 |
twofa_label_deactivation_confirmation: Disable two-factor authentication |
| 1234 |
twofa_notice_select: "Please select the two-factor scheme you would like to use:" |
|
| 1235 |
twofa_warning_require: The administrator requires you to enable two-factor authentication. |
|
| 1230 | 1236 |
twofa_activated: Two-factor authentication successfully enabled. |
| 1231 | 1237 |
twofa_deactivated: Two-factor authentication disabled. |
| 1232 | 1238 |
twofa_mail_body_security_notification_paired: "Two-factor authentication successfully enabled using %{field}."
|
| config/routes.rb | ||
|---|---|---|
| 85 | 85 |
match 'my/add_block', :controller => 'my', :action => 'add_block', :via => :post |
| 86 | 86 |
match 'my/remove_block', :controller => 'my', :action => 'remove_block', :via => :post |
| 87 | 87 |
match 'my/order_blocks', :controller => 'my', :action => 'order_blocks', :via => :post |
| 88 |
match 'my/twofa/activate/init', :controller => 'twofa', :action => 'activate_init', :via => :post |
|
| 88 | 89 |
match 'my/twofa/:scheme/activate/init', :controller => 'twofa', :action => 'activate_init', :via => :post |
| 89 | 90 |
match 'my/twofa/:scheme/activate/confirm', :controller => 'twofa', :action => 'activate_confirm', :via => :get |
| 90 | 91 |
match 'my/twofa/:scheme/activate', :controller => 'twofa', :action => 'activate', :via => [:get, :post] |
| 91 | 92 |
match 'my/twofa/:scheme/deactivate/init', :controller => 'twofa', :action => 'deactivate_init', :via => :post |
| 92 | 93 |
match 'my/twofa/:scheme/deactivate/confirm', :controller => 'twofa', :action => 'deactivate_confirm', :via => :get |
| 93 | 94 |
match 'my/twofa/:scheme/deactivate', :controller => 'twofa', :action => 'deactivate', :via => [:get, :post] |
| 95 |
match 'my/twofa/select_scheme', :controller => 'twofa', :action => 'select_scheme', :via => :get |
|
| 94 | 96 |
match 'users/:user_id/twofa/deactivate', :controller => 'twofa', :action => 'admin_deactivate', :via => :post |
| 95 | 97 | |
| 96 | 98 |
resources :users do |
| config/settings.yml | ||
|---|---|---|
| 36 | 36 |
lost_password: |
| 37 | 37 |
default: 1 |
| 38 | 38 |
security_notifications: 1 |
| 39 |
twofa: |
|
| 40 |
default: 1 |
|
| 41 |
security_notifications: 1 |
|
| 39 | 42 |
unsubscribe: |
| 40 | 43 |
default: 1 |
| 41 | 44 |
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 |