Merge pull request #3551 from tchak/flipflop-for-all

Flipflop for all
This commit is contained in:
Paul Chavard 2019-03-12 14:19:02 +01:00 committed by GitHub
commit ff079d8c27
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 47 additions and 31 deletions

View file

@ -38,7 +38,10 @@ class API::V1::DossiersController < APIController
def fetch_procedure_and_check_token def fetch_procedure_and_check_token
@procedure = Procedure.for_api.find(params[:procedure_id]) @procedure = Procedure.for_api.find(params[:procedure_id])
if !valid_token_for_procedure?(@procedure) administrateur = find_administrateur_for_token(@procedure)
if administrateur
Current.administrateur = administrateur
else
render json: {}, status: :unauthorized render json: {}, status: :unauthorized
end end

View file

@ -10,7 +10,10 @@ class API::V1::ProceduresController < APIController
def fetch_procedure_and_check_token def fetch_procedure_and_check_token
@procedure = Procedure.for_api.find(params[:id]) @procedure = Procedure.for_api.find(params[:id])
if !valid_token_for_procedure?(@procedure) administrateur = find_administrateur_for_token(@procedure)
if administrateur
Current.administrateur = administrateur
else
render json: {}, status: :unauthorized render json: {}, status: :unauthorized
end end

View file

@ -3,8 +3,8 @@ class APIController < ApplicationController
protected protected
def valid_token_for_procedure?(procedure) def find_administrateur_for_token(procedure)
procedure.administrateurs.any? do |administrateur| procedure.administrateurs.find do |administrateur|
administrateur.valid_api_token?(token) administrateur.valid_api_token?(token)
end end
end end

View file

@ -6,6 +6,7 @@ class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception. # Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead. # For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception, if: -> { !Rails.env.test? } protect_from_forgery with: :exception, if: -> { !Rails.env.test? }
before_action :set_current_roles
before_action :load_navbar_left_pannel_partial_url before_action :load_navbar_left_pannel_partial_url
before_action :set_raven_context before_action :set_raven_context
before_action :redirect_if_untrusted before_action :redirect_if_untrusted
@ -79,6 +80,11 @@ class ApplicationController < ActionController::Base
private private
def set_current_roles
Current.administrateur = current_administrateur
Current.gestionnaire = current_gestionnaire
end
def set_active_storage_host def set_active_storage_host
ActiveStorage::Current.host = request.base_url ActiveStorage::Current.host = request.base_url
end end
@ -158,7 +164,7 @@ class ApplicationController < ActionController::Base
def redirect_if_untrusted def redirect_if_untrusted
if gestionnaire_signed_in? && if gestionnaire_signed_in? &&
sensitive_path && sensitive_path &&
current_gestionnaire.feature_enabled?(:enable_email_login_token) && Flipflop.enable_email_login_token? &&
!trusted_device? !trusted_device?
# return at this location # return at this location

View file

@ -9,19 +9,24 @@ module Flipflop::Strategies
end end
def enabled?(feature) def enabled?(feature)
# Can only check features if we have the user's session. find_current_administrateur&.feature_enabled?(feature) ||
if request? find_current_gestionnaire&.feature_enabled?(feature)
find_current_administrateur&.feature_enabled?(feature)
end
end end
private private
def find_current_administrateur def find_current_administrateur
if request.session["warden.user.administrateur.key"] administrateur_id = Current.administrateur&.id
administrateur_id = request.session["warden.user.administrateur.key"][0][0] if administrateur_id
Administrateur.find_by(id: administrateur_id) Administrateur.find_by(id: administrateur_id)
end end
end end
def find_current_gestionnaire
gestionnaire_id = Current.gestionnaire&.id
if gestionnaire_id
Gestionnaire.find_by(id: gestionnaire_id)
end
end
end end
end end

3
app/models/current.rb Normal file
View file

@ -0,0 +1,3 @@
class Current < ActiveSupport::CurrentAttributes
attribute :gestionnaire, :administrateur
end

View file

@ -5,7 +5,7 @@ describe APIController, type: :controller do
let(:procedure) { create(:procedure) } let(:procedure) { create(:procedure) }
let(:admin) { procedure.administrateurs.first } let(:admin) { procedure.administrateurs.first }
subject { controller.send(:'valid_token_for_procedure?', procedure) } subject { !!controller.send(:find_administrateur_for_token, procedure) }
context 'when the admin has not any token' do context 'when the admin has not any token' do
context 'and the token is not given' do context 'and the token is not given' do

View file

@ -151,9 +151,7 @@ describe ApplicationController, type: :controller do
let(:current_gestionnaire) { create(:gestionnaire) } let(:current_gestionnaire) { create(:gestionnaire) }
before do before do
allow(current_gestionnaire).to receive(:feature_enabled?).and_return(feature_enabled)
allow(@controller).to receive(:current_gestionnaire).and_return(current_gestionnaire) allow(@controller).to receive(:current_gestionnaire).and_return(current_gestionnaire)
allow(@controller).to receive(:redirect_to) allow(@controller).to receive(:redirect_to)
allow(@controller).to receive(:trusted_device?).and_return(trusted_device) allow(@controller).to receive(:trusted_device?).and_return(trusted_device)
allow(@controller).to receive(:gestionnaire_signed_in?).and_return(gestionnaire_signed_in) allow(@controller).to receive(:gestionnaire_signed_in?).and_return(gestionnaire_signed_in)
@ -171,7 +169,9 @@ describe ApplicationController, type: :controller do
let(:gestionnaire_signed_in) { true } let(:gestionnaire_signed_in) { true }
context 'when the feature is activated' do context 'when the feature is activated' do
let(:feature_enabled) { true } before do
Flipflop::FeatureSet.current.test!.switch!(:enable_email_login_token, true)
end
context 'when the device is trusted' do context 'when the device is trusted' do
let(:trusted_device) { true } let(:trusted_device) { true }
@ -183,7 +183,9 @@ describe ApplicationController, type: :controller do
end end
context 'when the feature is activated' do context 'when the feature is activated' do
let(:feature_enabled) { true } before do
Flipflop::FeatureSet.current.test!.switch!(:enable_email_login_token, true)
end
context 'when the device is not trusted' do context 'when the device is not trusted' do
let(:trusted_device) { false } let(:trusted_device) { false }

View file

@ -10,12 +10,13 @@ describe Users::SessionsController, type: :controller do
describe '#create' do describe '#create' do
context "when the user is also a gestionnaire and an administrateur" do context "when the user is also a gestionnaire and an administrateur" do
let!(:administrateur) { create(:administrateur, :with_admin_trusted_device, email: email, password: password) } let!(:administrateur) { create(:administrateur, email: email, password: password) }
let(:gestionnaire) { administrateur.gestionnaire } let(:gestionnaire) { administrateur.gestionnaire }
let(:trusted_device) { true } let(:trusted_device) { true }
let(:send_password) { password } let(:send_password) { password }
before do before do
Flipflop::FeatureSet.current.test!.switch!(:enable_email_login_token, true)
allow(controller).to receive(:trusted_device?).and_return(trusted_device) allow(controller).to receive(:trusted_device?).and_return(trusted_device)
allow(GestionnaireMailer).to receive(:send_login_token).and_return(double(deliver_later: true)) allow(GestionnaireMailer).to receive(:send_login_token).and_return(double(deliver_later: true))
end end

View file

@ -9,12 +9,6 @@ FactoryBot.define do
end end
end end
trait :with_admin_trusted_device do
after(:create) do |admin|
admin.gestionnaire.update(features: { "enable_email_login_token" => true })
end
end
trait :with_api_token do trait :with_api_token do
after(:create) do |admin| after(:create) do |admin|
admin.renew_api_token admin.renew_api_token

View file

@ -4,10 +4,4 @@ FactoryBot.define do
email { generate(:gestionnaire_email) } email { generate(:gestionnaire_email) }
password { 'password' } password { 'password' }
end end
trait :with_trusted_device do
after(:create) do |gestionnaire|
gestionnaire.update(features: { "enable_email_login_token" => true })
end
end
end end

View file

@ -5,9 +5,10 @@ feature 'Administrator connection' do
let(:email) { 'admin1@admin.com' } let(:email) { 'admin1@admin.com' }
let(:password) { 'mon chien aime les bananes' } let(:password) { 'mon chien aime les bananes' }
let!(:admin) { create(:administrateur, :with_admin_trusted_device, :with_procedure, email: email, password: password) } let!(:admin) { create(:administrateur, :with_procedure, email: email, password: password) }
before do before do
Flipflop::FeatureSet.current.test!.switch!(:enable_email_login_token, true)
visit new_administrateur_session_path visit new_administrateur_session_path
end end

View file

@ -4,11 +4,15 @@ feature 'The gestionnaire part' do
include ActiveJob::TestHelper include ActiveJob::TestHelper
let(:password) { 'secret_password' } let(:password) { 'secret_password' }
let!(:gestionnaire) { create(:gestionnaire, :with_trusted_device, password: password) } let!(:gestionnaire) { create(:gestionnaire, password: password) }
let!(:procedure) { create(:procedure, :published, gestionnaires: [gestionnaire]) } let!(:procedure) { create(:procedure, :published, gestionnaires: [gestionnaire]) }
let!(:dossier) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure) } let!(:dossier) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure) }
before do
Flipflop::FeatureSet.current.test!.switch!(:enable_email_login_token, true)
end
context 'when the gestionnaire is also a user' do context 'when the gestionnaire is also a user' do
let!(:user) { create(:user, email: gestionnaire.email, password: password) } let!(:user) { create(:user, email: gestionnaire.email, password: password) }