Project

General

Profile

Feature #1237 » 0002-adds-a-setting-to-disable-enable-require-2fa-auth.patch

Jens Krämer, 2019-08-17 16:05

View differences:

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 + " &#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
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
(14-14/22)