summaryrefslogtreecommitdiff
path: root/app/controllers/otp_enrollments_controller.rb
blob: 82fc98dc42451e1dcb9ee4df2e0b61af43e13b8c (plain)
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
# Self-service TOTP enrollment, deliberately scoped to current_user only:
# an administrator must never hold another account's secret -- admins get
# the witnessed reset on the user page instead.
class OtpEnrollmentsController < ApplicationController
  include PinnedToDefaultLocale

  before_action :login_required

  layout 'admin'

  # QR plus confirmation form; only meaningful while a pending secret exists.
  def show
    redirect_to edit_user_path(current_user) if current_user.otp_pending_secret.blank?
  end

  # Begins (or restarts) enrollment. Requires the current password so an
  # unattended logged-in session cannot be enrolled onto a stranger's phone.
  def create
    unless User.authenticate(current_user.login, params[:current_password].to_s)
      flash[:error] = t("flash.otp.wrong_password")
      return redirect_to edit_user_path(current_user)
    end
    current_user.begin_otp_enrollment!
    redirect_to otp_enrollment_path
  end

  # Confirms with the first generated code.
  def update
    if current_user.confirm_otp_enrollment!(params[:code])
      flash[:notice] = t("flash.otp.enabled")
      redirect_to edit_user_path(current_user)
    else
      flash.now[:error] = t("flash.otp.code_mismatch_rescan")
      render :show
    end
  end

  # Self-service disable: password AND a current code.
  def destroy
    unless User.authenticate(current_user.login, params[:current_password].to_s) &&
           current_user.verify_otp!(params[:code])
      flash[:error] = t("flash.otp.wrong_credentials")
      return redirect_to edit_user_path(current_user)
    end
    current_user.disable_otp!(:actor => current_user)
    flash[:notice] = t("flash.otp.disabled")
    redirect_to edit_user_path(current_user)
  end
end