Project

General

Profile

Feature #1237 » 0002-2-factor-authentication-disabled-enabled-required.patch

Felix Schäfer, 2018-01-02 18:42

View differences:

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 + " &#187;".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
(1-1/22)