shamu 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +26 -0
- data/.gitignore +2 -1
- data/.rubocop.yml +89 -30
- data/.yardopts +4 -5
- data/Gemfile +24 -12
- data/Guardfile +5 -0
- data/LABELS.md +22 -0
- data/README.md +41 -0
- data/Rakefile +12 -0
- data/circle.yml +7 -3
- data/config.ru +7 -0
- data/lib/shamu/active_record.rb +7 -0
- data/lib/shamu/attributes/assignment.rb +114 -0
- data/lib/shamu/attributes/equality.rb +40 -0
- data/lib/shamu/attributes/fluid_assignment.rb +49 -0
- data/lib/shamu/attributes/validation.rb +74 -0
- data/lib/shamu/attributes.rb +255 -0
- data/lib/shamu/auditing/README.md +0 -0
- data/lib/shamu/auditing/audit_record.rb +32 -0
- data/lib/shamu/auditing/auditing_service.rb +32 -0
- data/lib/shamu/auditing/list_scope.rb +22 -0
- data/lib/shamu/auditing/logging_auditing_service.rb +16 -0
- data/lib/shamu/auditing/support.rb +75 -0
- data/lib/shamu/auditing/transaction.rb +58 -0
- data/lib/shamu/auditing.rb +12 -0
- data/lib/shamu/entities/README.md +1 -0
- data/lib/shamu/entities/active_record.rb +123 -0
- data/lib/shamu/entities/active_record_soft_destroy.rb +91 -0
- data/lib/shamu/entities/entity.rb +196 -0
- data/lib/shamu/entities/entity_path.rb +87 -0
- data/lib/shamu/entities/identity_cache.rb +64 -0
- data/lib/shamu/entities/list.rb +54 -0
- data/lib/shamu/entities/list_scope/dates.rb +57 -0
- data/lib/shamu/entities/list_scope/paging.rb +51 -0
- data/lib/shamu/entities/list_scope/scoped_paging.rb +65 -0
- data/lib/shamu/entities/list_scope/sorting.rb +76 -0
- data/lib/shamu/entities/list_scope.rb +105 -0
- data/lib/shamu/entities/null_entity.rb +88 -0
- data/lib/shamu/entities.rb +11 -0
- data/lib/shamu/error.rb +23 -5
- data/lib/shamu/events/README.md +0 -0
- data/lib/shamu/events/active_record/channel.rb +36 -0
- data/lib/shamu/events/active_record/message.rb +52 -0
- data/lib/shamu/events/active_record/migration.rb +49 -0
- data/lib/shamu/events/active_record/runner.rb +28 -0
- data/lib/shamu/events/active_record/service.rb +174 -0
- data/lib/shamu/events/active_record.rb +13 -0
- data/lib/shamu/events/channel_stats.rb +23 -0
- data/lib/shamu/events/error.rb +24 -0
- data/lib/shamu/events/events_service.rb +136 -0
- data/lib/shamu/events/in_memory/async_service.rb +48 -0
- data/lib/shamu/events/in_memory/service.rb +97 -0
- data/lib/shamu/events/in_memory.rb +10 -0
- data/lib/shamu/events/message.rb +38 -0
- data/lib/shamu/events/support.rb +60 -0
- data/lib/shamu/events.rb +12 -0
- data/lib/shamu/features/README.md +0 -0
- data/lib/shamu/features/conditions/condition.rb +39 -0
- data/lib/shamu/features/conditions/env.rb +37 -0
- data/lib/shamu/features/conditions/hosts.rb +25 -0
- data/lib/shamu/features/conditions/matching.rb +16 -0
- data/lib/shamu/features/conditions/not_matching.rb +16 -0
- data/lib/shamu/features/conditions/percentage.rb +44 -0
- data/lib/shamu/features/conditions/proc.rb +54 -0
- data/lib/shamu/features/conditions/roles.rb +23 -0
- data/lib/shamu/features/conditions/schedule_at.rb +27 -0
- data/lib/shamu/features/conditions.rb +18 -0
- data/lib/shamu/features/config_service.rb +10 -0
- data/lib/shamu/features/context.rb +80 -0
- data/lib/shamu/features/env_store.rb +88 -0
- data/lib/shamu/features/errors.rb +29 -0
- data/lib/shamu/features/features_service.rb +168 -0
- data/lib/shamu/features/list_scope.rb +30 -0
- data/lib/shamu/features/selector.rb +50 -0
- data/lib/shamu/features/support.rb +51 -0
- data/lib/shamu/features/toggle.rb +149 -0
- data/lib/shamu/features/toggle_codec.rb +69 -0
- data/lib/shamu/features.rb +16 -0
- data/lib/shamu/locale/en.yml +22 -2
- data/lib/shamu/logger.rb +13 -0
- data/lib/shamu/rack/README.md +0 -0
- data/lib/shamu/rack/cookies.rb +115 -0
- data/lib/shamu/rack/cookies_middleware.rb +26 -0
- data/lib/shamu/rack/query_params.rb +41 -0
- data/lib/shamu/rack/query_params_middleware.rb +24 -0
- data/lib/shamu/rack.rb +12 -0
- data/lib/shamu/rails/controller.rb +131 -0
- data/lib/shamu/rails/entity.rb +168 -0
- data/lib/shamu/rails/features.rb +13 -0
- data/lib/shamu/rails/railtie.rb +30 -0
- data/lib/shamu/rails.rb +10 -0
- data/lib/shamu/rspec/matchers.rb +44 -0
- data/lib/shamu/rspec.rb +1 -0
- data/lib/shamu/security/README.md +0 -0
- data/lib/shamu/security/active_record_policy.rb +106 -0
- data/lib/shamu/security/error.rb +65 -0
- data/lib/shamu/security/hashed_value.rb +71 -0
- data/lib/shamu/security/no_policy.rb +15 -0
- data/lib/shamu/security/policy.rb +289 -0
- data/lib/shamu/security/policy_refinement.rb +50 -0
- data/lib/shamu/security/policy_rule.rb +59 -0
- data/lib/shamu/security/principal.rb +72 -0
- data/lib/shamu/security/roles.rb +62 -0
- data/lib/shamu/security/roles_service.rb +30 -0
- data/lib/shamu/security/support.rb +83 -0
- data/lib/shamu/security.rb +43 -0
- data/lib/shamu/services/README.md +2 -0
- data/lib/shamu/services/active_record.rb +58 -0
- data/lib/shamu/services/active_record_crud.rb +378 -0
- data/lib/shamu/services/error.rb +24 -0
- data/lib/shamu/services/lazy_association.rb +31 -0
- data/lib/shamu/services/lazy_transform.rb +97 -0
- data/lib/shamu/services/request.rb +122 -0
- data/lib/shamu/services/request_support.rb +124 -0
- data/lib/shamu/services/result.rb +75 -0
- data/lib/shamu/services/service.rb +355 -0
- data/lib/shamu/services.rb +12 -0
- data/lib/shamu/sessions/README.md +2 -0
- data/lib/shamu/sessions/cookie_store.rb +79 -0
- data/lib/shamu/sessions/session_store.rb +42 -0
- data/lib/shamu/sessions.rb +8 -0
- data/lib/shamu/to_bool_extension.rb +57 -0
- data/lib/shamu/to_model_id_extension.rb +50 -0
- data/lib/shamu/version.rb +10 -4
- data/lib/shamu.rb +18 -6
- data/shamu.gemspec +21 -10
- data/spec/internal/README.md +4 -0
- data/spec/internal/config/database.yml +3 -0
- data/spec/internal/config/routes.rb +3 -0
- data/spec/internal/db/schema.rb +3 -0
- data/spec/internal/log/.gitignore +1 -0
- data/spec/internal/public/favicon.ico +0 -0
- data/spec/lib/shamu/active_record_support.rb +32 -0
- data/spec/lib/shamu/attributes/assignment_spec.rb +129 -0
- data/spec/lib/shamu/attributes/equality_spec.rb +63 -0
- data/spec/lib/shamu/attributes/fluid_assignment_spec.rb +31 -0
- data/spec/lib/shamu/attributes/validation_spec.rb +53 -0
- data/spec/lib/shamu/attributes_spec.rb +331 -0
- data/spec/lib/shamu/auditing/logging_auditing_service_spec.rb +18 -0
- data/spec/lib/shamu/auditing/support_spec.rb +41 -0
- data/spec/lib/shamu/entities/active_record_soft_destroy_spec.rb +82 -0
- data/spec/lib/shamu/entities/active_record_spec.rb +66 -0
- data/spec/lib/shamu/entities/entity_path_spec.rb +40 -0
- data/spec/lib/shamu/entities/entity_spec.rb +56 -0
- data/spec/lib/shamu/entities/identity_cache_spec.rb +69 -0
- data/spec/lib/shamu/entities/list_scope/dates_spec.rb +47 -0
- data/spec/lib/shamu/entities/list_scope/paging_spec.rb +41 -0
- data/spec/lib/shamu/entities/list_scope/scoped_paging_spec.rb +40 -0
- data/spec/lib/shamu/entities/list_scope/sorting_spec.rb +59 -0
- data/spec/lib/shamu/entities/list_scope_spec.rb +127 -0
- data/spec/lib/shamu/entities/list_spec.rb +60 -0
- data/spec/lib/shamu/entities/null_entity_spec.rb +94 -0
- data/spec/lib/shamu/events/active_record/migration_spec.rb +11 -0
- data/spec/lib/shamu/events/active_record/service_spec.rb +139 -0
- data/spec/lib/shamu/events/events_service_spec.rb +57 -0
- data/spec/lib/shamu/events/in_memory/async_service_spec.rb +37 -0
- data/spec/lib/shamu/events/in_memory/service_spec.rb +36 -0
- data/spec/lib/shamu/events/message_spec.rb +7 -0
- data/spec/lib/shamu/events/support_spec.rb +44 -0
- data/spec/lib/shamu/features/conditions/condition_spec.rb +8 -0
- data/spec/lib/shamu/features/conditions/env_spec.rb +29 -0
- data/spec/lib/shamu/features/conditions/hosts_spec.rb +21 -0
- data/spec/lib/shamu/features/conditions/matching_spec.rb +23 -0
- data/spec/lib/shamu/features/conditions/percentage_spec.rb +71 -0
- data/spec/lib/shamu/features/conditions/proc_spec.rb +28 -0
- data/spec/lib/shamu/features/env_store_spec.rb +48 -0
- data/spec/lib/shamu/features/features.yml +34 -0
- data/spec/lib/shamu/features/features_service_spec.rb +109 -0
- data/spec/lib/shamu/features/secondary.yml +5 -0
- data/spec/lib/shamu/features/selector_spec.rb +17 -0
- data/spec/lib/shamu/features/support_spec.rb +45 -0
- data/spec/lib/shamu/features/toggle_codec_spec.rb +28 -0
- data/spec/lib/shamu/features/toggle_spec.rb +42 -0
- data/spec/lib/shamu/rack/cookies_middleware_spec.rb +33 -0
- data/spec/lib/shamu/rack/cookies_spec.rb +43 -0
- data/spec/lib/shamu/rack/query_params_middleware_spec.rb +33 -0
- data/spec/lib/shamu/rack/query_params_spec.rb +23 -0
- data/spec/lib/shamu/rails/controller_spec.rb +74 -0
- data/spec/lib/shamu/rails/entity_spec.rb +150 -0
- data/spec/lib/shamu/rails/features.yml +13 -0
- data/spec/lib/shamu/rails/features_spec.rb +45 -0
- data/spec/lib/shamu/security/active_record_policy_spec.rb +38 -0
- data/spec/lib/shamu/security/hashed_value_spec.rb +41 -0
- data/spec/lib/shamu/security/policy_refinement_spec.rb +61 -0
- data/spec/lib/shamu/security/policy_rule_spec.rb +60 -0
- data/spec/lib/shamu/security/policy_spec.rb +158 -0
- data/spec/lib/shamu/security/roles_spec.rb +46 -0
- data/spec/lib/shamu/services/active_record_crud_spec.rb +460 -0
- data/spec/lib/shamu/services/active_record_spec.rb +92 -0
- data/spec/lib/shamu/services/lazy_association_spec.rb +31 -0
- data/spec/lib/shamu/services/lazy_transform_spec.rb +96 -0
- data/spec/lib/shamu/services/request_spec.rb +58 -0
- data/spec/lib/shamu/services/request_support_spec.rb +129 -0
- data/spec/lib/shamu/services/result_spec.rb +37 -0
- data/spec/lib/shamu/services/service_spec.rb +307 -0
- data/spec/lib/shamu/sessions/cookie_store_spec.rb +44 -0
- data/spec/lib/shamu/to_bool_extension_spec.rb +67 -0
- data/spec/lib/shamu/to_model_id_extension_spec.rb +54 -0
- data/spec/rails_helper.rb +13 -0
- data/spec/spec_helper.rb +17 -12
- data/spec/support/active_record.rb +17 -0
- data/spec/support/database.rb +14 -0
- data/spec/support/logger.rb +0 -0
- metadata +383 -9
- data/spec/lib/shamu_spec.rb +0 -5
- /data/{spec/internal/log/test.log → lib/shamu/attributes/README.md} +0 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "shamu/rack"
|
3
|
+
|
4
|
+
describe Shamu::Rack::Cookies do
|
5
|
+
let( :headers ) { {} }
|
6
|
+
let( :env ) { {} }
|
7
|
+
let( :cookies ) { Shamu::Rack::Cookies.new( env ) }
|
8
|
+
|
9
|
+
it "sets a cookie" do
|
10
|
+
cookies.set( :id, "123" )
|
11
|
+
expect( cookies.get( "id" ) ).to eq "123"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "gets a cookie" do
|
15
|
+
env[ "HTTP_COOKIE" ] = "remember_me=true; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"
|
16
|
+
expect( cookies.get( "remember_me" ) ).to eq "true"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "overwrites existing cookie" do
|
20
|
+
env[ "HTTP_COOKIE" ] = "favorite=batman"
|
21
|
+
cookies.set( "favorite", "superman" )
|
22
|
+
|
23
|
+
expect( cookies.get( "favorite" ) ).to eq "superman"
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#apply" do
|
27
|
+
it "adds new cookies" do
|
28
|
+
cookies.set( "name", "phallguy" )
|
29
|
+
cookies.apply!( headers )
|
30
|
+
|
31
|
+
expect( headers[ "Set-Cookie" ] ).to match /phallguy/
|
32
|
+
end
|
33
|
+
|
34
|
+
it "removes old cookies" do
|
35
|
+
env[ "HTTP_COOKIE" ] = "remember_me=true"
|
36
|
+
|
37
|
+
cookies.delete( "remember_me" )
|
38
|
+
cookies.apply!( headers )
|
39
|
+
|
40
|
+
expect( headers[ "Set-Cookie" ] ).to match /remember_me=;/
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "shamu/rack"
|
3
|
+
|
4
|
+
module QueryParamsMiddlewareSpec
|
5
|
+
class App
|
6
|
+
include Scorpion::Rack
|
7
|
+
attr_accessor :next
|
8
|
+
|
9
|
+
def call( env )
|
10
|
+
@next ||= proc { [ 200, {}, [ "Sting!" ] ] }
|
11
|
+
@next.call( env, self )
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe Shamu::Rack::QueryParamsMiddleware do
|
17
|
+
let(:app) { QueryParamsMiddlewareSpec::App.new }
|
18
|
+
let(:scorpion_middleware) { Scorpion::Rack::Middleware.new( query_parmas_middleware ) }
|
19
|
+
let(:query_parmas_middleware) { Shamu::Rack::QueryParamsMiddleware.new( app ) }
|
20
|
+
let(:request) { Rack::MockRequest.new( scorpion_middleware ) }
|
21
|
+
let(:response) { request.get( "/" ) }
|
22
|
+
|
23
|
+
it "prepares it with the environment" do
|
24
|
+
|
25
|
+
app.next = proc do |env, app|
|
26
|
+
query_parmas = app.send( :scorpion, env ).fetch Shamu::Rack::QueryParams
|
27
|
+
expect( query_parmas ).to be_a Shamu::Rack::QueryParams
|
28
|
+
[ 200, {}, [ "Yum!" ] ]
|
29
|
+
end
|
30
|
+
|
31
|
+
request.get "/"
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "shamu/rack"
|
3
|
+
|
4
|
+
describe Shamu::Rack::QueryParams do
|
5
|
+
let( :headers ) { {} }
|
6
|
+
let( :env ) { { "rack.input" => StringIO.new } }
|
7
|
+
let( :query_params ) { Shamu::Rack::QueryParams.new( env ) }
|
8
|
+
|
9
|
+
it "gets a cookie" do
|
10
|
+
env[ "QUERY_STRING" ] = "toggles=yep"
|
11
|
+
expect( query_params.get( "toggles" ) ).to eq "yep"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "handles array parameters" do
|
15
|
+
env[ "QUERY_STRING" ] = "level[]=one&level[]=two"
|
16
|
+
expect( query_params.get( "level" ) ).to eq [ "one", "two" ]
|
17
|
+
end
|
18
|
+
|
19
|
+
it "handles hash parameters" do
|
20
|
+
env[ "QUERY_STRING" ] = "option[save]=yes&option[method]=tail"
|
21
|
+
expect( query_params.get( "option" ) ).to eq "save" => "yes", "method" => "tail"
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require "rails_helper"
|
2
|
+
|
3
|
+
module ControllerSpec
|
4
|
+
|
5
|
+
class Service < Shamu::Services::Service
|
6
|
+
end
|
7
|
+
|
8
|
+
class SecureService < Shamu::Services::Service
|
9
|
+
include Shamu::Security::Support
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe Shamu::Rails::Controller, type: :controller do
|
14
|
+
controller ActionController::Base do
|
15
|
+
service :example_service, ControllerSpec::Service
|
16
|
+
service :secure_service, ControllerSpec::SecureService
|
17
|
+
|
18
|
+
public :services, :secure_services, :permit?
|
19
|
+
|
20
|
+
def show
|
21
|
+
render text: ""
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe ".service" do
|
26
|
+
it "makes the service available" do
|
27
|
+
expect( controller.respond_to?( :example_service, true ) ).to be_truthy
|
28
|
+
expect( controller.send( :example_service ) ).to be_a ControllerSpec::Service
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#services" do
|
33
|
+
it "includes all the services" do
|
34
|
+
expect( controller.services ).to include kind_of( ControllerSpec::Service )
|
35
|
+
expect( controller.services ).to include kind_of( ControllerSpec::SecureService )
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#secure_services" do
|
40
|
+
it "includes only the secure services" do
|
41
|
+
expect( controller.secure_services ).not_to include kind_of( ControllerSpec::Service )
|
42
|
+
expect( controller.secure_services ).to include kind_of( ControllerSpec::SecureService )
|
43
|
+
end
|
44
|
+
|
45
|
+
it "gets security context from current_user" do
|
46
|
+
expect( controller ).to receive( :current_user ).at_least( :once ).and_return( OpenStruct.new( id: 945 ) )
|
47
|
+
|
48
|
+
expect( controller ).to receive( :show ) do
|
49
|
+
expect( scorpion.fetch( Shamu::Security::Principal ).user_id ).to eq 945
|
50
|
+
controller.render( text: "" )
|
51
|
+
end
|
52
|
+
|
53
|
+
get :show, id: 5
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe ".services" do
|
58
|
+
it "includes all the service names" do
|
59
|
+
expect( controller.class.services ).to match [ :example_service, :secure_service ]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "#permit?" do
|
64
|
+
it "is true if any of the secure_services permit the requested behavior" do
|
65
|
+
expect( controller.send( :secure_service ) ).to receive( :permit? ).and_return :yes
|
66
|
+
expect( controller ).to be_permitted_to :read, :something
|
67
|
+
end
|
68
|
+
|
69
|
+
it "is false if none of the secure_services permit the requested behavior" do
|
70
|
+
expect( controller.send( :secure_service ) ).to receive( :permit? ).and_return false
|
71
|
+
expect( controller ).not_to be_permitted_to :read, :something
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require "rails_helper"
|
2
|
+
|
3
|
+
module LoadEntitySpec
|
4
|
+
class Service < Shamu::Services::Service
|
5
|
+
include Shamu::Security::Support
|
6
|
+
include Shamu::Services::RequestSupport
|
7
|
+
|
8
|
+
def find( id )
|
9
|
+
scorpion.fetch ExampleEntity, { id: id }, {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def list( params = nil )
|
13
|
+
Shamu::Entities::List.new [ find( 1 ) ]
|
14
|
+
end
|
15
|
+
|
16
|
+
def authorize!( * )
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
class ExampleEntity < Shamu::Entities::Entity
|
23
|
+
attribute :id
|
24
|
+
end
|
25
|
+
|
26
|
+
module Request
|
27
|
+
class Change < Shamu::Services::Request
|
28
|
+
attribute :id
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe Shamu::Rails::Entity, type: :controller do
|
34
|
+
hunt( :example_service, LoadEntitySpec::Service ) { scorpion.new LoadEntitySpec::Service }
|
35
|
+
|
36
|
+
controller ActionController::Base do
|
37
|
+
service :example_service, LoadEntitySpec::Service
|
38
|
+
entity LoadEntitySpec::ExampleEntity
|
39
|
+
|
40
|
+
def show
|
41
|
+
render text: ""
|
42
|
+
end
|
43
|
+
|
44
|
+
def index
|
45
|
+
render text: ""
|
46
|
+
end
|
47
|
+
|
48
|
+
def new
|
49
|
+
example_request
|
50
|
+
render text: ""
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
before( :each ) do
|
56
|
+
controller.params[:action] = "show"
|
57
|
+
end
|
58
|
+
|
59
|
+
it "adds an #example method" do
|
60
|
+
expect( controller.respond_to?( :example, true ) ).to be_truthy
|
61
|
+
end
|
62
|
+
|
63
|
+
it "loads the entity from the service" do
|
64
|
+
expect( example_service ).to receive( :find )
|
65
|
+
controller.send :example
|
66
|
+
end
|
67
|
+
|
68
|
+
it "adds an #example_request method" do
|
69
|
+
expect( controller.respond_to?( :example_request, true ) ).to be_truthy
|
70
|
+
end
|
71
|
+
|
72
|
+
it "builds a request from the service" do
|
73
|
+
expect( example_service ).to receive( :request_for )
|
74
|
+
controller.send :example_request
|
75
|
+
end
|
76
|
+
|
77
|
+
it "gets params from example_params" do
|
78
|
+
expect( example_service ).to receive( :request_for ).and_return Shamu::Services::Request.new
|
79
|
+
expect( controller ).to receive( :example_params )
|
80
|
+
|
81
|
+
controller.send :example_request
|
82
|
+
end
|
83
|
+
|
84
|
+
it "loads the entity before the request" do
|
85
|
+
expect( controller ).to receive( :example ).and_call_original
|
86
|
+
get :show, id: 1
|
87
|
+
end
|
88
|
+
|
89
|
+
it "invokes list for index types" do
|
90
|
+
expect( controller ).to receive( :examples ).and_call_original
|
91
|
+
get :index
|
92
|
+
end
|
93
|
+
|
94
|
+
it "authorizes action for entity request" do
|
95
|
+
expect( example_service ).to receive( :authorize! )
|
96
|
+
|
97
|
+
get :new
|
98
|
+
end
|
99
|
+
|
100
|
+
context "only some actions" do
|
101
|
+
controller ActionController::Base do
|
102
|
+
service :example_service, LoadEntitySpec::Service
|
103
|
+
entity LoadEntitySpec::ExampleEntity, only: :show
|
104
|
+
|
105
|
+
def show
|
106
|
+
render text: ""
|
107
|
+
end
|
108
|
+
|
109
|
+
def new
|
110
|
+
render text: ""
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
it "loads on show" do
|
115
|
+
expect( controller ).to receive( :example )
|
116
|
+
get :show, id: 1
|
117
|
+
end
|
118
|
+
|
119
|
+
it "doesn't load on new" do
|
120
|
+
expect( controller ).not_to receive( :example )
|
121
|
+
get :new
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "except some actions" do
|
126
|
+
controller ActionController::Base do
|
127
|
+
service :example_service, LoadEntitySpec::Service
|
128
|
+
entity LoadEntitySpec::ExampleEntity, except: :show
|
129
|
+
|
130
|
+
def show
|
131
|
+
render text: ""
|
132
|
+
end
|
133
|
+
|
134
|
+
def new
|
135
|
+
render text: ""
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
it "loads on show" do
|
140
|
+
expect( controller ).not_to receive( :example )
|
141
|
+
get :show, id: 1
|
142
|
+
end
|
143
|
+
|
144
|
+
it "doesn't load on new" do
|
145
|
+
expect( controller ).to receive( :example )
|
146
|
+
get :new
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "rails_helper"
|
2
|
+
|
3
|
+
describe Shamu::Rails::Features, type: :controller do
|
4
|
+
controller ActionController::Base do
|
5
|
+
|
6
|
+
public :feature_enabled?
|
7
|
+
|
8
|
+
def show
|
9
|
+
render text: ""
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
hunt( :features_service, Shamu::Features::FeaturesService ) do
|
14
|
+
scorpion.new Shamu::Features::FeaturesService, File.expand_path( "../features.yml", __FILE__ ), {}
|
15
|
+
end
|
16
|
+
|
17
|
+
hunt( :session_store, Shamu::Sessions::CookieStore )
|
18
|
+
|
19
|
+
it "resolves toggles" do
|
20
|
+
expect( session_store ).to receive( :fetch ).and_return nil
|
21
|
+
allow( session_store ).to receive( :set )
|
22
|
+
|
23
|
+
expect( controller ).to receive( :show ) do
|
24
|
+
expect( controller.feature_enabled?( "shopping/nux" ) ).to be_truthy
|
25
|
+
controller.render text: ""
|
26
|
+
end
|
27
|
+
|
28
|
+
get :show, id: 1
|
29
|
+
end
|
30
|
+
|
31
|
+
it "allows toggles to be overridden by query param" do
|
32
|
+
expect( session_store ).to receive( :fetch ).and_return nil
|
33
|
+
allow( session_store ).to receive( :set )
|
34
|
+
|
35
|
+
override = features_service.toggle_codec.pack( "shopping/discounts" => true )
|
36
|
+
|
37
|
+
expect( controller ).to receive( :show ) do
|
38
|
+
expect( controller.feature_enabled?( "shopping/discounts" ) ).to be_truthy
|
39
|
+
controller.render text: ""
|
40
|
+
end
|
41
|
+
|
42
|
+
get :show, id: 1, Shamu::Features::EnvStore::RACK_PARAMS_KEY => override
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "shamu/active_record"
|
3
|
+
|
4
|
+
describe Shamu::Security::ActiveRecordPolicy do
|
5
|
+
use_active_record
|
6
|
+
|
7
|
+
let( :policy ) { Shamu::Security::ActiveRecordPolicy.new }
|
8
|
+
|
9
|
+
describe "#refine_relation" do
|
10
|
+
before( :each ) do
|
11
|
+
ActiveRecordSpec::Favorite.create! name: "Example"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "returns empty relation if there are no refinements" do
|
15
|
+
relation = policy.refine_relation( :read, ActiveRecordSpec::Favorite.all )
|
16
|
+
expect( relation ).to be_empty
|
17
|
+
end
|
18
|
+
|
19
|
+
it "applies matching refinements" do
|
20
|
+
refinement = double( Shamu::Security::PolicyRefinement )
|
21
|
+
allow( policy ).to receive( :refinements ).and_return [ refinement ]
|
22
|
+
|
23
|
+
expect( refinement ).to receive( :match? ).and_return true
|
24
|
+
expect( refinement ).to receive( :apply ).and_return ActiveRecordSpec::Favorite.all
|
25
|
+
|
26
|
+
relation = policy.refine_relation( :read, ActiveRecordSpec::Favorite.all )
|
27
|
+
expect( relation ).not_to be_empty
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#refine" do
|
32
|
+
it "adds a new refinement" do
|
33
|
+
expect do
|
34
|
+
policy.send( :refine, :read, ActiveRecordSpec::Favorite )
|
35
|
+
end.to change { policy.send( :refinements ).length }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module HashedValueSpec
|
4
|
+
class Codec
|
5
|
+
include Shamu::Security::HashedValue
|
6
|
+
|
7
|
+
def initialize( private_key )
|
8
|
+
@private_key = private_key
|
9
|
+
end
|
10
|
+
|
11
|
+
public :hash_value, :verify_hash
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe Shamu::Security::HashedValue do
|
16
|
+
let( :codec ) { HashedValueSpec::Codec.new( SecureRandom.random_bytes( 64 ) ) }
|
17
|
+
|
18
|
+
describe "#pack" do
|
19
|
+
subject { codec.hash_value( "example" ) }
|
20
|
+
|
21
|
+
it { is_expected.to match /$/ }
|
22
|
+
it { is_expected.to match /example/ }
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#unpack" do
|
26
|
+
it "gets original value" do
|
27
|
+
hashed = codec.hash_value( "example" )
|
28
|
+
expect( codec.verify_hash( hashed ) ).to eq "example"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "handles an empty feature value" do
|
32
|
+
hashed = codec.hash_value( "" )
|
33
|
+
expect( codec.verify_hash( hashed ) ).to eq ""
|
34
|
+
end
|
35
|
+
|
36
|
+
it "handles an nil feature hash" do
|
37
|
+
hashed = codec.hash_value( nil )
|
38
|
+
expect( codec.verify_hash( hashed ) ).to eq nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "shamu/active_record"
|
3
|
+
|
4
|
+
describe Shamu::Security::PolicyRefinement do
|
5
|
+
use_active_record
|
6
|
+
|
7
|
+
describe "#match?" do
|
8
|
+
let( :relation ) { ActiveRecordSpec::Favorite.all }
|
9
|
+
let( :refinement ) do
|
10
|
+
Shamu::Security::PolicyRefinement.new( [ :read ], ActiveRecordSpec::Favorite, nil )
|
11
|
+
end
|
12
|
+
|
13
|
+
it "is true for matching action" do
|
14
|
+
expect( refinement ).to be_match :read, relation, nil
|
15
|
+
end
|
16
|
+
|
17
|
+
it "is false for mismatched action" do
|
18
|
+
expect( refinement ).not_to be_match :update, relation, nil
|
19
|
+
end
|
20
|
+
|
21
|
+
it "is true for matching relation" do
|
22
|
+
expect( refinement ).to be_match :read, relation, nil
|
23
|
+
end
|
24
|
+
|
25
|
+
it "is false for mismatched relation" do
|
26
|
+
klass = Class.new( ActiveRecord::Base )
|
27
|
+
expect( refinement ).not_to be_match :read, klass.all, nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#apply" do
|
32
|
+
it "returns block result" do
|
33
|
+
refinement = Shamu::Security::PolicyRefinement.new(
|
34
|
+
[ :read ],
|
35
|
+
ActiveRecordSpec::Favorite,
|
36
|
+
->( _, _ ) { :refined }
|
37
|
+
)
|
38
|
+
expect( refinement.apply( :read, ActiveRecordSpec::Favorite.all ) ).to eq :refined
|
39
|
+
end
|
40
|
+
|
41
|
+
it "returns original if no block" do
|
42
|
+
refinement = Shamu::Security::PolicyRefinement.new(
|
43
|
+
[ :read ],
|
44
|
+
ActiveRecordSpec::Favorite,
|
45
|
+
nil
|
46
|
+
)
|
47
|
+
relation = ActiveRecordSpec::Favorite.all
|
48
|
+
expect( refinement.apply( relation, nil ) ).to be relation
|
49
|
+
end
|
50
|
+
|
51
|
+
it "returns original if block returns falsy value" do
|
52
|
+
refinement = Shamu::Security::PolicyRefinement.new(
|
53
|
+
[ :read ],
|
54
|
+
ActiveRecordSpec::Favorite,
|
55
|
+
->( _, _ ) {}
|
56
|
+
)
|
57
|
+
relation = ActiveRecordSpec::Favorite.all
|
58
|
+
expect( refinement.apply( relation, nil ) ).to be relation
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Shamu::Security::PolicyRule do
|
4
|
+
describe "#match?" do
|
5
|
+
let( :klass ) { Class.new }
|
6
|
+
let( :instance ) { klass.new }
|
7
|
+
|
8
|
+
let( :rule ) do
|
9
|
+
Shamu::Security::PolicyRule.new( [ :read, :write ], klass, :yes, nil )
|
10
|
+
end
|
11
|
+
|
12
|
+
it "is true for matching action" do
|
13
|
+
expect( rule ).to be_match :read, instance, nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it "is false for unmatched action" do
|
17
|
+
expect( rule ).not_to be_match :examine, instance, nil
|
18
|
+
end
|
19
|
+
|
20
|
+
it "is true for Class match" do
|
21
|
+
expect( rule ).to be_match :read, klass, nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it "is true for instance of Class match" do
|
25
|
+
expect( rule ).to be_match :read, instance, nil
|
26
|
+
end
|
27
|
+
|
28
|
+
it "is true for instance match" do
|
29
|
+
rule = Shamu::Security::PolicyRule.new( [ :read, :write ], instance, :yes, nil )
|
30
|
+
expect( rule ).to be_match :read, instance, nil
|
31
|
+
end
|
32
|
+
|
33
|
+
it "is false for Class mismatch" do
|
34
|
+
expect( rule ).not_to be_match :read, Class.new, nil
|
35
|
+
end
|
36
|
+
|
37
|
+
it "is false for instance of Class mismatch" do
|
38
|
+
expect( rule ).not_to be_match :read, Class.new.new, nil
|
39
|
+
end
|
40
|
+
|
41
|
+
it "is false for instance mismatch" do
|
42
|
+
rule = Shamu::Security::PolicyRule.new( [ :read, :write ], instance, :yes, nil )
|
43
|
+
expect( rule ).not_to be_match :read, klass.new, nil
|
44
|
+
end
|
45
|
+
|
46
|
+
context "with block" do
|
47
|
+
it "invokes block if present" do
|
48
|
+
expect do |b|
|
49
|
+
Shamu::Security::PolicyRule.new( [ :read, :write ], klass, :yes, b.to_proc ).match?( :read, instance, nil )
|
50
|
+
end.to yield_control
|
51
|
+
end
|
52
|
+
|
53
|
+
it "does not invoke block if resource is a Module" do
|
54
|
+
expect do |b|
|
55
|
+
Shamu::Security::PolicyRule.new( [ :read, :write ], klass, :yes, b.to_proc ).match?( :read, klass, nil )
|
56
|
+
end.not_to yield_control
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|