diff options
Diffstat (limited to 'app/controllers/elevations_controller.rb')
| -rw-r--r-- | app/controllers/elevations_controller.rb | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/app/controllers/elevations_controller.rb b/app/controllers/elevations_controller.rb new file mode 100644 index 00000000..804b8f95 --- /dev/null +++ b/app/controllers/elevations_controller.rb | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | # Step-up authentication for janitorial work. Mirrors the two-step login's | ||
| 2 | # attempt cap: verify_otp! guards replay but not rate, and an attacker with a | ||
| 3 | # stolen cookie would otherwise have unlimited tries at a six-digit code. | ||
| 4 | class ElevationsController < ApplicationController | ||
| 5 | include RoleRequired | ||
| 6 | |||
| 7 | layout 'admin' | ||
| 8 | |||
| 9 | before_action :login_required | ||
| 10 | before_action :require_admin | ||
| 11 | |||
| 12 | MAX_ATTEMPTS = 5 | ||
| 13 | |||
| 14 | def new | ||
| 15 | redirect_to admin_path if elevated? | ||
| 16 | end | ||
| 17 | |||
| 18 | def create | ||
| 19 | return render(:new) unless current_user.otp_enrolled? | ||
| 20 | |||
| 21 | session[:elevation_attempts] = session[:elevation_attempts].to_i + 1 | ||
| 22 | if session[:elevation_attempts] > MAX_ATTEMPTS | ||
| 23 | logout_killing_session! | ||
| 24 | flash[:error] = t("flash.otp.too_many_attempts") | ||
| 25 | return redirect_to(login_path) | ||
| 26 | end | ||
| 27 | |||
| 28 | if current_user.verify_otp!(params[:code]) | ||
| 29 | session.delete(:elevation_attempts) | ||
| 30 | elevate! | ||
| 31 | redirect_to safe_return_to(session.delete(:elevation_return_to), | ||
| 32 | :default => users_path) | ||
| 33 | else | ||
| 34 | flash.now[:error] = t("flash.otp.code_mismatch") | ||
| 35 | render :new | ||
| 36 | end | ||
| 37 | end | ||
| 38 | |||
| 39 | def destroy | ||
| 40 | drop_elevation! | ||
| 41 | flash[:notice] = t("flash.elevation.dropped") | ||
| 42 | redirect_to admin_path | ||
| 43 | end | ||
| 44 | end | ||
