scram 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +173 -0
  4. data/Rakefile +32 -0
  5. data/app/models/scram/policy.rb +67 -0
  6. data/app/models/scram/target.rb +70 -0
  7. data/lib/scram.rb +11 -0
  8. data/lib/scram/concerns/aggregate_holder.rb +23 -0
  9. data/lib/scram/concerns/holder.rb +38 -0
  10. data/lib/scram/core_ext/symbol_extensions.rb +14 -0
  11. data/lib/scram/dsl/builders.rb +43 -0
  12. data/lib/scram/dsl/definitions.rb +36 -0
  13. data/lib/scram/dsl/model_conditions.rb +50 -0
  14. data/lib/scram/engine.rb +15 -0
  15. data/lib/scram/version.rb +3 -0
  16. data/lib/tasks/scram_tasks.rake +4 -0
  17. data/spec/config/mongoid.yml +6 -0
  18. data/spec/dummy/Rakefile +6 -0
  19. data/spec/dummy/app/assets/config/manifest.js +5 -0
  20. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  21. data/spec/dummy/app/assets/javascripts/cable.js +13 -0
  22. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  23. data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
  24. data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
  25. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  26. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  27. data/spec/dummy/app/jobs/application_job.rb +2 -0
  28. data/spec/dummy/app/mailers/application_mailer.rb +4 -0
  29. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  30. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  31. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  32. data/spec/dummy/bin/bundle +3 -0
  33. data/spec/dummy/bin/rails +4 -0
  34. data/spec/dummy/bin/rake +4 -0
  35. data/spec/dummy/bin/setup +34 -0
  36. data/spec/dummy/bin/update +29 -0
  37. data/spec/dummy/config.ru +5 -0
  38. data/spec/dummy/config/application.rb +23 -0
  39. data/spec/dummy/config/boot.rb +5 -0
  40. data/spec/dummy/config/cable.yml +9 -0
  41. data/spec/dummy/config/environment.rb +5 -0
  42. data/spec/dummy/config/environments/development.rb +51 -0
  43. data/spec/dummy/config/environments/production.rb +83 -0
  44. data/spec/dummy/config/environments/test.rb +42 -0
  45. data/spec/dummy/config/initializers/application_controller_renderer.rb +6 -0
  46. data/spec/dummy/config/initializers/assets.rb +11 -0
  47. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  48. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  49. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  50. data/spec/dummy/config/initializers/inflections.rb +16 -0
  51. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  52. data/spec/dummy/config/initializers/new_framework_defaults.rb +21 -0
  53. data/spec/dummy/config/initializers/session_store.rb +3 -0
  54. data/spec/dummy/config/initializers/wrap_parameters.rb +9 -0
  55. data/spec/dummy/config/locales/en.yml +23 -0
  56. data/spec/dummy/config/mongoid.yml +147 -0
  57. data/spec/dummy/config/puma.rb +47 -0
  58. data/spec/dummy/config/routes.rb +3 -0
  59. data/spec/dummy/config/secrets.yml +22 -0
  60. data/spec/dummy/config/spring.rb +6 -0
  61. data/spec/dummy/log/development.log +11 -0
  62. data/spec/dummy/log/test.log +2321 -0
  63. data/spec/dummy/public/404.html +67 -0
  64. data/spec/dummy/public/422.html +67 -0
  65. data/spec/dummy/public/500.html +66 -0
  66. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  67. data/spec/dummy/public/apple-touch-icon.png +0 -0
  68. data/spec/dummy/public/favicon.ico +0 -0
  69. data/spec/factories/policy.rb +0 -0
  70. data/spec/rails_helper.rb +78 -0
  71. data/spec/scram/concerns/aggregate_holder_spec.rb +58 -0
  72. data/spec/scram/concerns/holder_spec.rb +100 -0
  73. data/spec/scram/dsl_spec.rb +51 -0
  74. data/spec/scram/policy_spec.rb +28 -0
  75. data/spec/scram/target_spec.rb +40 -0
  76. data/spec/scram/test_implementations/simple_aggregate_holder.rb +21 -0
  77. data/spec/scram/test_implementations/simple_holder.rb +21 -0
  78. data/spec/scram/test_implementations/test_model.rb +10 -0
  79. data/spec/scram_spec.rb +11 -0
  80. data/spec/spec_helper.rb +99 -0
  81. data/spec/support/factory_girl.rb +9 -0
  82. metadata +278 -0
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/404.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The page you were looking for doesn't exist.</h1>
62
+ <p>You may have mistyped the address or the page may have moved.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/422.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The change you wanted was rejected.</h1>
62
+ <p>Maybe you tried to change something you didn't have access to.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/500.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>We're sorry, but something went wrong.</h1>
62
+ </div>
63
+ <p>If you are the application owner check the logs for more information.</p>
64
+ </div>
65
+ </body>
66
+ </html>
File without changes
File without changes
File without changes
@@ -0,0 +1,78 @@
1
+ # This file is copied to spec/ when you run 'rails generate rspec:install'
2
+ ENV['RAILS_ENV'] ||= 'test'
3
+ require File.expand_path('../dummy/config/environment', __FILE__)
4
+ # Prevent database truncation if the environment is production
5
+ abort("The Rails environment is running in production mode!") if Rails.env.production?
6
+ require 'spec_helper'
7
+ require 'rspec/rails'
8
+ # Add additional requires below this line. Rails is not loaded until this point!
9
+
10
+ require 'database_cleaner'
11
+ require 'support/factory_girl'
12
+
13
+ require 'coveralls'
14
+ Coveralls.wear!
15
+
16
+ require "scram/test_implementations/simple_holder"
17
+ require "scram/test_implementations/simple_aggregate_holder"
18
+ require "scram/test_implementations/test_model"
19
+
20
+ # Requires supporting ruby files with custom matchers and macros, etc, in
21
+ # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
22
+ # run as spec files by default. This means that files in spec/support that end
23
+ # in _spec.rb will both be required and run as specs, causing the specs to be
24
+ # run twice. It is recommended that you do not name files matching this glob to
25
+ # end with _spec.rb. You can configure this pattern with the --pattern
26
+ # option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
27
+ #
28
+ # The following line is provided for convenience purposes. It has the downside
29
+ # of increasing the boot-up time by auto-requiring all files in the support
30
+ # directory. Alternatively, in the individual `*_spec.rb` files, manually
31
+ # require only the support files necessary.
32
+ #
33
+ # Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
34
+
35
+ # Checks for pending migration and applies them before tests are run.
36
+ # If you are not using ActiveRecord, you can remove this line.
37
+ # ActiveRecord::Migration.maintain_test_schema!
38
+
39
+ RSpec.configure do |config|
40
+ config.before(:suite) do
41
+ DatabaseCleaner.strategy = :truncation
42
+ DatabaseCleaner.clean_with(:truncation)
43
+ end
44
+
45
+ config.around(:each) do |example|
46
+ DatabaseCleaner.cleaning do
47
+ example.run
48
+ end
49
+ end
50
+
51
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
52
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
53
+
54
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
55
+ # examples within a transaction, remove the following line or assign false
56
+ # instead of true.
57
+ # config.use_transactional_fixtures = true
58
+
59
+ # RSpec Rails can automatically mix in different behaviours to your tests
60
+ # based on their file location, for example enabling you to call `get` and
61
+ # `post` in specs under `spec/controllers`.
62
+ #
63
+ # You can disable this behaviour by removing the line below, and instead
64
+ # explicitly tag your specs with their type, e.g.:
65
+ #
66
+ # RSpec.describe UsersController, :type => :controller do
67
+ # # ...
68
+ # end
69
+ #
70
+ # The different available types are documented in the features, such as in
71
+ # https://relishapp.com/rspec/rspec-rails/docs
72
+ config.infer_spec_type_from_file_location!
73
+
74
+ # Filter lines from Rails gems in backtraces.
75
+ config.filter_rails_from_backtrace!
76
+ # arbitrary gems may also be filtered via:
77
+ # config.filter_gems_from_backtrace("gem name")
78
+ end
@@ -0,0 +1,58 @@
1
+ require "rails_helper"
2
+
3
+ module Scram
4
+ describe Scram::AggregateHolder do
5
+
6
+ it "cannot be used without an implementation" do
7
+ expect {UnimplementedAggregateHolder.new.policies}.to raise_error(NotImplementedError)
8
+ expect {UnimplementedAggregateHolder.new.aggregates}.to raise_error(NotImplementedError)
9
+ expect {UnimplementedAggregateHolder.new.scram_compare_value}.to raise_error(NotImplementedError)
10
+ end
11
+
12
+ it "uses permissions from aggregates" do
13
+ target1 = Target.new
14
+ target1.actions << "woot"
15
+ policy1 = Policy.new
16
+ policy1.context = TestModel.name # A misc policy for strings
17
+ policy1.targets << target1
18
+ holder1 = SimpleHolder.new(policies: [policy1])
19
+
20
+ target2 = Target.new
21
+ target2.actions << "donk"
22
+ policy2 = Policy.new
23
+ policy2.context = TestModel.name # A misc policy for strings
24
+ policy2.targets << target2
25
+ holder2 = SimpleHolder.new(policies: [policy2])
26
+
27
+ user = SimpleAggregateHolder.new(aggregates: [holder1, holder2])
28
+ expect(user.can? :woot, TestModel.new).to be true
29
+ expect(user.can? :donk, TestModel.new).to be true
30
+ expect(user.can? :zing, TestModel.new).to be false
31
+ end
32
+
33
+ it "uses the aggregate holder compare value for ownership checking" do
34
+ target = Target.new
35
+ target.actions << "woot"
36
+ target.conditions = {:equals => {:owner => "*holder"}}
37
+
38
+ policy = Policy.new
39
+ policy.context = TestModel.name # A misc policy for strings
40
+ policy.targets << target
41
+ holder = SimpleHolder.new(policies: [policy])
42
+
43
+ user = SimpleAggregateHolder.new(aggregates: [holder])
44
+ expect(user.can? :woot, TestModel.new(owner: "Mr. Aggregate Holder Guy")).to be true
45
+ expect(user.can? :woot, TestModel.new(owner: "Mr. Holder Guy")).to be false
46
+
47
+ another_user = SimpleAggregateHolder.new(aggregates: [])
48
+ class << another_user
49
+ def scram_compare_value
50
+ "Mr. Aggregate Holder Guy Jr."
51
+ end
52
+ end
53
+
54
+ expect(another_user.can? :woot, TestModel.new(owner: "Mr. Aggregate Holder Guy")).to be false
55
+
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,100 @@
1
+ require "rails_helper"
2
+
3
+ module Scram
4
+ describe Scram::Holder do
5
+
6
+ it "cannot be used without an implementation" do
7
+ expect {UnimplementedHolder.new.policies}.to raise_error(NotImplementedError)
8
+ expect {UnimplementedHolder.new.scram_compare_value}.to raise_error(NotImplementedError)
9
+ end
10
+
11
+ it "holds model permissions" do
12
+ target = Target.new
13
+ target.actions << "woot"
14
+
15
+ policy = Policy.new
16
+ policy.context = TestModel.name # A misc policy for strings
17
+ policy.targets << target
18
+ dude = SimpleHolder.new(policies: [policy]) # This is a test holder, his scram_compare_value by default is "Mr. Holder Guy"
19
+
20
+ # Check that it tests a field equals something
21
+ target.conditions = {:equals => { :targetable_int => 3}}
22
+ policy.save
23
+ expect(dude.can? :woot, TestModel.new).to be true
24
+
25
+ # Check that it tests a field is less than something
26
+ target.conditions = {:less_than => { :targetable_int => 4}}
27
+ policy.save
28
+ expect(dude.can? :woot, TestModel.new).to be true
29
+
30
+ # Test that it checks if an array includes something
31
+ target.conditions = {:includes => {:targetable_array => "a"}}
32
+ policy.save
33
+ expect(dude.can? :woot, TestModel.new).to be true
34
+
35
+ # Test that it checks if a document is owned by holder
36
+ target.conditions = {:equals => {:owner => "*holder"}}
37
+ policy.save
38
+ expect(dude.can? :woot, TestModel.new(owner: "Mr. Holder Guy")).to be true
39
+ expect(dude.can? :woot, TestModel.new(owner: "Mr. Holder Dude")).to be false
40
+
41
+ end
42
+
43
+ it "holds string permissions" do
44
+ target = Target.new
45
+ target.conditions = {:equals => { :'*target_name' => "donk"}}
46
+ target.actions << "woot"
47
+
48
+ policy = Policy.new
49
+ policy.name = "globals" # A misc policy for strings, context wil be nil!
50
+ policy.targets << target
51
+
52
+ policy.save
53
+
54
+ dude = SimpleHolder.new(policies: [policy]) # This is a test holder
55
+ expect(dude.can? :woot, :donk).to be true
56
+ expect(dude.can? :woot, :donkers).to be false
57
+ end
58
+
59
+ it "differentiates model and string policies" do
60
+ string_policy = Policy.new
61
+ string_policy.context = "non-existent-model"
62
+ string_policy.save
63
+
64
+ expect(string_policy.model?).to be false
65
+
66
+ model_policy = Policy.new
67
+ model_policy.context = SimpleHolder.name
68
+ model_policy.save
69
+
70
+ expect(model_policy.model?).to be true
71
+ end
72
+
73
+ it "prioritizes policies" do
74
+ # Allow zing and woot
75
+ target1 = Target.new
76
+ target1.actions << "woot"
77
+ target1.actions << "zing"
78
+
79
+ policy1 = Policy.new
80
+ policy1.context = TestModel.name # A misc policy for strings
81
+ policy1.targets << target1
82
+
83
+ # Deny woot in higher priority policy
84
+ target2 = Target.new
85
+ target2.actions << "woot"
86
+ target2.allow = false
87
+
88
+ policy2 = Policy.new
89
+ policy2.context = TestModel.name # A misc policy for strings
90
+ policy2.priority = 1
91
+ policy2.targets << target2
92
+
93
+ user = SimpleHolder.new(policies: [policy1, policy2])
94
+ expect(user.can? :woot, TestModel.new).to be false
95
+ expect(user.can? :donk, TestModel.new).to be false
96
+ expect(user.can? :zing, TestModel.new).to be true
97
+ end
98
+
99
+ end
100
+ end