diff options
| author | Alban Peignier | 2017-12-19 19:42:52 +0100 |
|---|---|---|
| committer | Alban Peignier | 2017-12-20 17:23:47 +0100 |
| commit | f31a79c5bc3678949b7334486daa196a17a5db92 (patch) | |
| tree | 49cbd986ede79cc5a3ec6811bf07db87320f99f8 | |
| parent | 86bdefb0483a8409810715c3cdc65b9a178a2667 (diff) | |
| download | chouette-core-f31a79c5bc3678949b7334486daa196a17a5db92.tar.bz2 | |
Create Organisation#features and FeatureChecker controller concerns. Refs #5339
| -rw-r--r-- | app/controllers/application_controller.rb | 1 | ||||
| -rw-r--r-- | app/controllers/concerns/feature_checker.rb | 41 | ||||
| -rw-r--r-- | app/controllers/workbenches_controller.rb | 3 | ||||
| -rw-r--r-- | app/models/organisation.rb | 5 | ||||
| -rw-r--r-- | config/application.rb | 4 | ||||
| -rw-r--r-- | db/migrate/20171219170128_add_features_to_organisations.rb | 5 | ||||
| -rw-r--r-- | db/schema.rb | 3 | ||||
| -rw-r--r-- | spec/controllers/concerns/feature_checker_spec.rb | 36 | ||||
| -rw-r--r-- | spec/models/organisation_spec.rb | 22 |
9 files changed, 119 insertions, 1 deletions
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 97f5548ae..474277da1 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,6 +1,7 @@ class ApplicationController < ActionController::Base include PaperTrailSupport include Pundit + include FeatureChecker rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized diff --git a/app/controllers/concerns/feature_checker.rb b/app/controllers/concerns/feature_checker.rb new file mode 100644 index 000000000..c23e672cf --- /dev/null +++ b/app/controllers/concerns/feature_checker.rb @@ -0,0 +1,41 @@ +# Check availability of optional features +# +# In your controller, use : +# +# requires_feature :test +# requires_feature :test, only: [:show] +# +# In your view, use : +# +# has_feature? :test +# +module FeatureChecker + extend ActiveSupport::Concern + + module ClassMethods + def requires_feature(feature, options = {}) + before_action options do + check_feature! feature + end + end + end + + included do + helper_method :has_feature? + end + + protected + + def has_feature?(*features) + features.all? do |feature| + current_organisation.has_feature? feature + end + end + + def check_feature!(*features) + authorized = has_feature? *features + raise NotAuthorizedError, "Feature not autorized" unless authorized + end + + class NotAuthorizedError < StandardError; end +end diff --git a/app/controllers/workbenches_controller.rb b/app/controllers/workbenches_controller.rb index b2dac9e67..4da95df7a 100644 --- a/app/controllers/workbenches_controller.rb +++ b/app/controllers/workbenches_controller.rb @@ -5,6 +5,9 @@ class WorkbenchesController < ChouetteController defaults resource_class: Workbench respond_to :html, only: [:show, :index] + include FeatureChecker + requires_feature :test, only: :index + def index redirect_to dashboard_path end diff --git a/app/models/organisation.rb b/app/models/organisation.rb index 4343c87af..da7d1fcf3 100644 --- a/app/models/organisation.rb +++ b/app/models/organisation.rb @@ -1,3 +1,4 @@ +# coding: utf-8 class Organisation < ActiveRecord::Base include DataFormatEnumerations @@ -75,4 +76,8 @@ class Organisation < ActiveRecord::Base STIF::CodifligneLineId.lines_set_from_functional_scope( functional_scope ) end + def has_feature?(feature) + features && features.include?(feature.to_s) + end + end diff --git a/config/application.rb b/config/application.rb index 169c13e10..bda582610 100644 --- a/config/application.rb +++ b/config/application.rb @@ -35,6 +35,10 @@ module ChouetteIhm config.active_job.queue_adapter = :sidekiq + config.action_dispatch.rescue_responses.merge!( + 'FeatureChecker::NotAuthorizedError' => :unauthorized + ) + unless Rails.env.production? # Work around sprockets+teaspoon mismatch: Rails.application.config.assets.precompile += %w(spec_helper.js) diff --git a/db/migrate/20171219170128_add_features_to_organisations.rb b/db/migrate/20171219170128_add_features_to_organisations.rb new file mode 100644 index 000000000..bbec3297b --- /dev/null +++ b/db/migrate/20171219170128_add_features_to_organisations.rb @@ -0,0 +1,5 @@ +class AddFeaturesToOrganisations < ActiveRecord::Migration + def change + add_column :organisations, :features, :string, array: true, default: [] + end +end diff --git a/db/schema.rb b/db/schema.rb index f2642f8fc..2e35bfd62 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20171214130636) do +ActiveRecord::Schema.define(version: 20171219170128) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -552,6 +552,7 @@ ActiveRecord::Schema.define(version: 20171214130636) do t.datetime "synced_at" t.hstore "sso_attributes" t.string "custom_view" + t.string "features", default: [], array: true end add_index "organisations", ["code"], name: "index_organisations_on_code", unique: true, using: :btree diff --git a/spec/controllers/concerns/feature_checker_spec.rb b/spec/controllers/concerns/feature_checker_spec.rb new file mode 100644 index 000000000..0ffee0dfd --- /dev/null +++ b/spec/controllers/concerns/feature_checker_spec.rb @@ -0,0 +1,36 @@ +require "rails_helper" + +RSpec.describe "FeatureChecker", type: :controller do + + controller do + include FeatureChecker + requires_feature :test, only: :protected + + def protected; render :text => "protected"; end + def not_protected; render :text => "not protected"; end + + def current_organisation + @organisation ||= Organisation.new + end + end + + before do + routes.draw do + get "protected" => "anonymous#protected" + get "not_protected" => "anonymous#not_protected" + end + end + + it "refuse access when organisation has not the feature" do + expect{ get(:protected) }.to raise_error(FeatureChecker::NotAuthorizedError) + end + + it "accept access on unprotected action" do + get :not_protected + end + + it 'accept access when organisation has feature' do + controller.current_organisation.features << "test" + get :protected + end +end diff --git a/spec/models/organisation_spec.rb b/spec/models/organisation_spec.rb index 359417d88..0d54ed143 100644 --- a/spec/models/organisation_spec.rb +++ b/spec/models/organisation_spec.rb @@ -62,4 +62,26 @@ describe Organisation, :type => :model do expect{Organisation.portail_sync}.to change{ Organisation.count }.by(4) end end + + describe "#has_feature?" do + + let(:organisation) { Organisation.new } + + it 'return false if Organisation features is nil' do + organisation.features = nil + expect(organisation.has_feature?(:dummy)).to be_falsy + end + + it 'return true if Organisation features contains given feature' do + organisation.features = %w{present} + expect(organisation.has_feature?(:present)).to be_truthy + end + + it "return true if Organisation features doesn't contains given feature" do + organisation.features = %w{other} + expect(organisation.has_feature?(:absent)).to be_falsy + end + + end + end |
