shamu 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (207) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +26 -0
  3. data/.gitignore +2 -1
  4. data/.rubocop.yml +89 -30
  5. data/.yardopts +4 -5
  6. data/Gemfile +24 -12
  7. data/Guardfile +5 -0
  8. data/LABELS.md +22 -0
  9. data/README.md +41 -0
  10. data/Rakefile +12 -0
  11. data/circle.yml +7 -3
  12. data/config.ru +7 -0
  13. data/lib/shamu/active_record.rb +7 -0
  14. data/lib/shamu/attributes/assignment.rb +114 -0
  15. data/lib/shamu/attributes/equality.rb +40 -0
  16. data/lib/shamu/attributes/fluid_assignment.rb +49 -0
  17. data/lib/shamu/attributes/validation.rb +74 -0
  18. data/lib/shamu/attributes.rb +255 -0
  19. data/lib/shamu/auditing/README.md +0 -0
  20. data/lib/shamu/auditing/audit_record.rb +32 -0
  21. data/lib/shamu/auditing/auditing_service.rb +32 -0
  22. data/lib/shamu/auditing/list_scope.rb +22 -0
  23. data/lib/shamu/auditing/logging_auditing_service.rb +16 -0
  24. data/lib/shamu/auditing/support.rb +75 -0
  25. data/lib/shamu/auditing/transaction.rb +58 -0
  26. data/lib/shamu/auditing.rb +12 -0
  27. data/lib/shamu/entities/README.md +1 -0
  28. data/lib/shamu/entities/active_record.rb +123 -0
  29. data/lib/shamu/entities/active_record_soft_destroy.rb +91 -0
  30. data/lib/shamu/entities/entity.rb +196 -0
  31. data/lib/shamu/entities/entity_path.rb +87 -0
  32. data/lib/shamu/entities/identity_cache.rb +64 -0
  33. data/lib/shamu/entities/list.rb +54 -0
  34. data/lib/shamu/entities/list_scope/dates.rb +57 -0
  35. data/lib/shamu/entities/list_scope/paging.rb +51 -0
  36. data/lib/shamu/entities/list_scope/scoped_paging.rb +65 -0
  37. data/lib/shamu/entities/list_scope/sorting.rb +76 -0
  38. data/lib/shamu/entities/list_scope.rb +105 -0
  39. data/lib/shamu/entities/null_entity.rb +88 -0
  40. data/lib/shamu/entities.rb +11 -0
  41. data/lib/shamu/error.rb +23 -5
  42. data/lib/shamu/events/README.md +0 -0
  43. data/lib/shamu/events/active_record/channel.rb +36 -0
  44. data/lib/shamu/events/active_record/message.rb +52 -0
  45. data/lib/shamu/events/active_record/migration.rb +49 -0
  46. data/lib/shamu/events/active_record/runner.rb +28 -0
  47. data/lib/shamu/events/active_record/service.rb +174 -0
  48. data/lib/shamu/events/active_record.rb +13 -0
  49. data/lib/shamu/events/channel_stats.rb +23 -0
  50. data/lib/shamu/events/error.rb +24 -0
  51. data/lib/shamu/events/events_service.rb +136 -0
  52. data/lib/shamu/events/in_memory/async_service.rb +48 -0
  53. data/lib/shamu/events/in_memory/service.rb +97 -0
  54. data/lib/shamu/events/in_memory.rb +10 -0
  55. data/lib/shamu/events/message.rb +38 -0
  56. data/lib/shamu/events/support.rb +60 -0
  57. data/lib/shamu/events.rb +12 -0
  58. data/lib/shamu/features/README.md +0 -0
  59. data/lib/shamu/features/conditions/condition.rb +39 -0
  60. data/lib/shamu/features/conditions/env.rb +37 -0
  61. data/lib/shamu/features/conditions/hosts.rb +25 -0
  62. data/lib/shamu/features/conditions/matching.rb +16 -0
  63. data/lib/shamu/features/conditions/not_matching.rb +16 -0
  64. data/lib/shamu/features/conditions/percentage.rb +44 -0
  65. data/lib/shamu/features/conditions/proc.rb +54 -0
  66. data/lib/shamu/features/conditions/roles.rb +23 -0
  67. data/lib/shamu/features/conditions/schedule_at.rb +27 -0
  68. data/lib/shamu/features/conditions.rb +18 -0
  69. data/lib/shamu/features/config_service.rb +10 -0
  70. data/lib/shamu/features/context.rb +80 -0
  71. data/lib/shamu/features/env_store.rb +88 -0
  72. data/lib/shamu/features/errors.rb +29 -0
  73. data/lib/shamu/features/features_service.rb +168 -0
  74. data/lib/shamu/features/list_scope.rb +30 -0
  75. data/lib/shamu/features/selector.rb +50 -0
  76. data/lib/shamu/features/support.rb +51 -0
  77. data/lib/shamu/features/toggle.rb +149 -0
  78. data/lib/shamu/features/toggle_codec.rb +69 -0
  79. data/lib/shamu/features.rb +16 -0
  80. data/lib/shamu/locale/en.yml +22 -2
  81. data/lib/shamu/logger.rb +13 -0
  82. data/lib/shamu/rack/README.md +0 -0
  83. data/lib/shamu/rack/cookies.rb +115 -0
  84. data/lib/shamu/rack/cookies_middleware.rb +26 -0
  85. data/lib/shamu/rack/query_params.rb +41 -0
  86. data/lib/shamu/rack/query_params_middleware.rb +24 -0
  87. data/lib/shamu/rack.rb +12 -0
  88. data/lib/shamu/rails/controller.rb +131 -0
  89. data/lib/shamu/rails/entity.rb +168 -0
  90. data/lib/shamu/rails/features.rb +13 -0
  91. data/lib/shamu/rails/railtie.rb +30 -0
  92. data/lib/shamu/rails.rb +10 -0
  93. data/lib/shamu/rspec/matchers.rb +44 -0
  94. data/lib/shamu/rspec.rb +1 -0
  95. data/lib/shamu/security/README.md +0 -0
  96. data/lib/shamu/security/active_record_policy.rb +106 -0
  97. data/lib/shamu/security/error.rb +65 -0
  98. data/lib/shamu/security/hashed_value.rb +71 -0
  99. data/lib/shamu/security/no_policy.rb +15 -0
  100. data/lib/shamu/security/policy.rb +289 -0
  101. data/lib/shamu/security/policy_refinement.rb +50 -0
  102. data/lib/shamu/security/policy_rule.rb +59 -0
  103. data/lib/shamu/security/principal.rb +72 -0
  104. data/lib/shamu/security/roles.rb +62 -0
  105. data/lib/shamu/security/roles_service.rb +30 -0
  106. data/lib/shamu/security/support.rb +83 -0
  107. data/lib/shamu/security.rb +43 -0
  108. data/lib/shamu/services/README.md +2 -0
  109. data/lib/shamu/services/active_record.rb +58 -0
  110. data/lib/shamu/services/active_record_crud.rb +378 -0
  111. data/lib/shamu/services/error.rb +24 -0
  112. data/lib/shamu/services/lazy_association.rb +31 -0
  113. data/lib/shamu/services/lazy_transform.rb +97 -0
  114. data/lib/shamu/services/request.rb +122 -0
  115. data/lib/shamu/services/request_support.rb +124 -0
  116. data/lib/shamu/services/result.rb +75 -0
  117. data/lib/shamu/services/service.rb +355 -0
  118. data/lib/shamu/services.rb +12 -0
  119. data/lib/shamu/sessions/README.md +2 -0
  120. data/lib/shamu/sessions/cookie_store.rb +79 -0
  121. data/lib/shamu/sessions/session_store.rb +42 -0
  122. data/lib/shamu/sessions.rb +8 -0
  123. data/lib/shamu/to_bool_extension.rb +57 -0
  124. data/lib/shamu/to_model_id_extension.rb +50 -0
  125. data/lib/shamu/version.rb +10 -4
  126. data/lib/shamu.rb +18 -6
  127. data/shamu.gemspec +21 -10
  128. data/spec/internal/README.md +4 -0
  129. data/spec/internal/config/database.yml +3 -0
  130. data/spec/internal/config/routes.rb +3 -0
  131. data/spec/internal/db/schema.rb +3 -0
  132. data/spec/internal/log/.gitignore +1 -0
  133. data/spec/internal/public/favicon.ico +0 -0
  134. data/spec/lib/shamu/active_record_support.rb +32 -0
  135. data/spec/lib/shamu/attributes/assignment_spec.rb +129 -0
  136. data/spec/lib/shamu/attributes/equality_spec.rb +63 -0
  137. data/spec/lib/shamu/attributes/fluid_assignment_spec.rb +31 -0
  138. data/spec/lib/shamu/attributes/validation_spec.rb +53 -0
  139. data/spec/lib/shamu/attributes_spec.rb +331 -0
  140. data/spec/lib/shamu/auditing/logging_auditing_service_spec.rb +18 -0
  141. data/spec/lib/shamu/auditing/support_spec.rb +41 -0
  142. data/spec/lib/shamu/entities/active_record_soft_destroy_spec.rb +82 -0
  143. data/spec/lib/shamu/entities/active_record_spec.rb +66 -0
  144. data/spec/lib/shamu/entities/entity_path_spec.rb +40 -0
  145. data/spec/lib/shamu/entities/entity_spec.rb +56 -0
  146. data/spec/lib/shamu/entities/identity_cache_spec.rb +69 -0
  147. data/spec/lib/shamu/entities/list_scope/dates_spec.rb +47 -0
  148. data/spec/lib/shamu/entities/list_scope/paging_spec.rb +41 -0
  149. data/spec/lib/shamu/entities/list_scope/scoped_paging_spec.rb +40 -0
  150. data/spec/lib/shamu/entities/list_scope/sorting_spec.rb +59 -0
  151. data/spec/lib/shamu/entities/list_scope_spec.rb +127 -0
  152. data/spec/lib/shamu/entities/list_spec.rb +60 -0
  153. data/spec/lib/shamu/entities/null_entity_spec.rb +94 -0
  154. data/spec/lib/shamu/events/active_record/migration_spec.rb +11 -0
  155. data/spec/lib/shamu/events/active_record/service_spec.rb +139 -0
  156. data/spec/lib/shamu/events/events_service_spec.rb +57 -0
  157. data/spec/lib/shamu/events/in_memory/async_service_spec.rb +37 -0
  158. data/spec/lib/shamu/events/in_memory/service_spec.rb +36 -0
  159. data/spec/lib/shamu/events/message_spec.rb +7 -0
  160. data/spec/lib/shamu/events/support_spec.rb +44 -0
  161. data/spec/lib/shamu/features/conditions/condition_spec.rb +8 -0
  162. data/spec/lib/shamu/features/conditions/env_spec.rb +29 -0
  163. data/spec/lib/shamu/features/conditions/hosts_spec.rb +21 -0
  164. data/spec/lib/shamu/features/conditions/matching_spec.rb +23 -0
  165. data/spec/lib/shamu/features/conditions/percentage_spec.rb +71 -0
  166. data/spec/lib/shamu/features/conditions/proc_spec.rb +28 -0
  167. data/spec/lib/shamu/features/env_store_spec.rb +48 -0
  168. data/spec/lib/shamu/features/features.yml +34 -0
  169. data/spec/lib/shamu/features/features_service_spec.rb +109 -0
  170. data/spec/lib/shamu/features/secondary.yml +5 -0
  171. data/spec/lib/shamu/features/selector_spec.rb +17 -0
  172. data/spec/lib/shamu/features/support_spec.rb +45 -0
  173. data/spec/lib/shamu/features/toggle_codec_spec.rb +28 -0
  174. data/spec/lib/shamu/features/toggle_spec.rb +42 -0
  175. data/spec/lib/shamu/rack/cookies_middleware_spec.rb +33 -0
  176. data/spec/lib/shamu/rack/cookies_spec.rb +43 -0
  177. data/spec/lib/shamu/rack/query_params_middleware_spec.rb +33 -0
  178. data/spec/lib/shamu/rack/query_params_spec.rb +23 -0
  179. data/spec/lib/shamu/rails/controller_spec.rb +74 -0
  180. data/spec/lib/shamu/rails/entity_spec.rb +150 -0
  181. data/spec/lib/shamu/rails/features.yml +13 -0
  182. data/spec/lib/shamu/rails/features_spec.rb +45 -0
  183. data/spec/lib/shamu/security/active_record_policy_spec.rb +38 -0
  184. data/spec/lib/shamu/security/hashed_value_spec.rb +41 -0
  185. data/spec/lib/shamu/security/policy_refinement_spec.rb +61 -0
  186. data/spec/lib/shamu/security/policy_rule_spec.rb +60 -0
  187. data/spec/lib/shamu/security/policy_spec.rb +158 -0
  188. data/spec/lib/shamu/security/roles_spec.rb +46 -0
  189. data/spec/lib/shamu/services/active_record_crud_spec.rb +460 -0
  190. data/spec/lib/shamu/services/active_record_spec.rb +92 -0
  191. data/spec/lib/shamu/services/lazy_association_spec.rb +31 -0
  192. data/spec/lib/shamu/services/lazy_transform_spec.rb +96 -0
  193. data/spec/lib/shamu/services/request_spec.rb +58 -0
  194. data/spec/lib/shamu/services/request_support_spec.rb +129 -0
  195. data/spec/lib/shamu/services/result_spec.rb +37 -0
  196. data/spec/lib/shamu/services/service_spec.rb +307 -0
  197. data/spec/lib/shamu/sessions/cookie_store_spec.rb +44 -0
  198. data/spec/lib/shamu/to_bool_extension_spec.rb +67 -0
  199. data/spec/lib/shamu/to_model_id_extension_spec.rb +54 -0
  200. data/spec/rails_helper.rb +13 -0
  201. data/spec/spec_helper.rb +17 -12
  202. data/spec/support/active_record.rb +17 -0
  203. data/spec/support/database.rb +14 -0
  204. data/spec/support/logger.rb +0 -0
  205. metadata +383 -9
  206. data/spec/lib/shamu_spec.rb +0 -5
  207. /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,13 @@
1
+ ---
2
+ shopping:
3
+ nux:
4
+ retire_at: 2055-10-1
5
+ type: release
6
+ select:
7
+ - percentage: 100
8
+
9
+ discounts:
10
+ retire_at: 2055-10-1
11
+ type: release
12
+ select:
13
+ - percentage: 0
@@ -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