Commit ade5ba7

mo <mo.khan@gmail.com>
2018-09-01 22:17:01
tfas -> my/mfa
1 parent 546e1bb
app/controllers/my/mfas_controller.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module My
+  class MfasController < ApplicationController
+    def new
+      return redirect_to edit_my_mfa_path if current_user.tfa.setup?
+      current_user.tfa.build_secret
+    end
+
+    def create
+      current_user.update!(params.require(:user).permit(:tfa_secret))
+      redirect_to dashboard_path, notice: "successfully updated!"
+    end
+
+    def edit; end
+
+    def destroy
+      current_user.tfa.disable!
+      redirect_to dashboard_path
+    end
+  end
+end
app/controllers/tfas_controller.rb
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class TfasController < ApplicationController
-  def new
-    return redirect_to edit_tfa_path if current_user.tfa.setup?
-    current_user.tfa.build_secret
-  end
-
-  def create
-    current_user.update!(params.require(:user).permit(:tfa_secret))
-    redirect_to dashboard_path
-  end
-
-  def edit; end
-
-  def destroy
-    current_user.tfa.disable!
-    redirect_to dashboard_path
-  end
-end
app/views/dashboards/show.html.erb
@@ -3,9 +3,9 @@
     <div class="col">
       <h1>Dashboard</h1>
       <% if current_user.tfa.setup? %>
-        <%= link_to "TFA", edit_tfa_path %>
+        <%= link_to "TFA", edit_my_mfa_path %>
       <% else %>
-        <%= link_to "Setup TFA", new_tfa_path %>
+        <%= link_to "Setup TFA", new_my_mfa_path %>
       <% end %>
       <%= button_to "Logout", session_path, method: :delete %>
       <table class="table">
app/views/tfas/edit.html.erb → app/views/my/mfas/edit.html.erb
File renamed without changes
app/views/tfas/new.html.erb → app/views/my/mfas/new.html.erb
@@ -1,13 +1,13 @@
 <div class="container">
   <div class="row">
     <div class="col">
-      <h1>Two Factor Authentication (TFA) - Setup</h1>
+      <h1>Multi Factor Authentication - Setup</h1>
       <div data-controller="tfa--setup">
         <canvas id="canvas" data-target="tfa--setup.canvas"></canvas>
         <p>Secret: <%= current_user.tfa.secret %></p>
         <p>Provisioning URI: <%= current_user.tfa.provisioning_uri %></p>
 
-        <%= form_for current_user, url: tfa_path, method: :post do |form| %>
+        <%= form_for current_user, url: my_mfa_path, method: :post do |form| %>
           <%= form.hidden_field :tfa_secret, data: { target: 'tfa--setup.secret' } %>
           <%= form.submit "Save", class: 'btn btn-primary', data: { disable_with: 'Saving…' } %>
           <%= link_to "Cancel", dashboard_path, class: 'btn' %>
config/routes.rb
@@ -6,8 +6,9 @@ Rails.application.routes.draw do
   resource :metadata, only: [:show]
   resource :dashboard, only: [:show]
   resources :registrations, only: [:new, :create]
-  resource :tfa, only: [:new, :edit, :create, :destroy]
-
+  namespace :my do
+    resource :mfa, only: [:new, :edit, :create, :destroy]
+  end
   namespace :scim do
     namespace :v2, defaults: { format: :scim } do
       post ".search", to: "search#index"
spec/requests/my/mfas_spec.rb
@@ -0,0 +1,46 @@
+require 'rails_helper'
+
+RSpec.describe '/my/mfa' do
+  context "when logged in" do
+    let(:current_user) { create(:user) }
+    before { http_login(current_user) }
+
+    describe "GET /my/mfa" do
+      context "when mfa has not been set up yet" do
+        before { get '/my/mfa/new' }
+
+        specify { expect(response).to have_http_status(:ok) }
+        specify { expect(response.body).to include('Provisioning URI') }
+      end
+
+      context "when mfa has been set up" do
+        let(:current_user) { create(:user, :mfa_configured) }
+        before { get '/my/mfa/new' }
+
+        specify { expect(response).to redirect_to(edit_my_mfa_path) }
+      end
+    end
+
+    describe "POST /my/mfa" do
+      context "when the secret is valid" do
+        let(:secret) { SecureRandom.hex(20) }
+        before { post '/my/mfa', params: { user: { tfa_secret: secret } } }
+
+        specify { expect(current_user.reload.tfa_secret).to eql(secret) }
+        specify { expect(response).to redirect_to(dashboard_path) }
+        specify { expect(flash[:notice]).to include("successfully updated!") }
+      end
+    end
+
+    describe "DELETE /my/mfa" do
+      context "when mfa is enabled" do
+        let(:current_user) { create(:user, :mfa_configured) }
+
+        before { delete '/my/mfa' }
+
+        specify { expect(current_user.reload.tfa_secret).to be_nil }
+        specify { expect(response).to redirect_to(dashboard_path) }
+      end
+    end
+  end
+end
spec/support/request.rb
@@ -0,0 +1,7 @@
+RSpec.configure do |config|
+  config.include(Module.new do
+    def http_login(user)
+      post '/session', params: { user: { email: user.email, password: user.password } }
+    end
+  end)
+end
spec/support/system.rb
@@ -1,3 +1,5 @@
+require 'capybara-screenshot/rspec'
+
 RSpec.configure do |config|
   config.before(:each, type: :system) do
     driven_by :rack_test
@@ -7,5 +9,3 @@ RSpec.configure do |config|
     driven_by :selenium_chrome_headless
   end
 end
-
-require 'capybara-screenshot/rspec'
spec/factories.rb
@@ -3,5 +3,9 @@ FactoryBot.define do
     email { FFaker::Internet.email }
     uuid { SecureRandom.uuid }
     password { FFaker::Internet.password }
+
+    trait :mfa_configured do
+      tfa_secret { ::ROTP::Base32.random_base32 }
+    end
   end
 end