admission 0.1.6

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.
@@ -0,0 +1,103 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
4
+ # this file to always be loaded, without a need to explicitly require it in any
5
+ # files.
6
+ #
7
+ # Given that it is always loaded, you are encouraged to keep this file as
8
+ # light-weight as possible. Requiring heavyweight dependencies from this file
9
+ # will add to the boot time of your test suite on EVERY test run, even for an
10
+ # individual file that may not need all of that loaded. Instead, consider making
11
+ # a separate helper file that requires the additional dependencies and performs
12
+ # the additional setup, and require it from the spec files that actually need
13
+ # it.
14
+ #
15
+ # The `.rspec` file also contains a few flags that are not defaults but that
16
+ # users commonly want.
17
+ #
18
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
+ RSpec.configure do |config|
20
+ # rspec-expectations config goes here. You can use an alternate
21
+ # assertion/expectation library such as wrong or the stdlib/minitest
22
+ # assertions if you prefer.
23
+ config.expect_with :rspec do |expectations|
24
+ # This option will default to `true` in RSpec 4. It makes the `description`
25
+ # and `failure_message` of custom matchers include text for helper methods
26
+ # defined using `chain`, e.g.:
27
+ # be_bigger_than(2).and_smaller_than(4).description
28
+ # # => "be bigger than 2 and smaller than 4"
29
+ # ...rather than:
30
+ # # => "be bigger than 2"
31
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
32
+ end
33
+
34
+ # rspec-mocks config goes here. You can use an alternate test double
35
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
36
+ config.mock_with :rspec do |mocks|
37
+ # Prevents you from mocking or stubbing a method that does not exist on
38
+ # a real object. This is generally recommended, and will default to
39
+ # `true` in RSpec 4.
40
+ mocks.verify_partial_doubles = true
41
+ end
42
+
43
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
44
+ # have no way to turn it off -- the option exists only for backwards
45
+ # compatibility in RSpec 3). It causes shared context metadata to be
46
+ # inherited by the metadata hash of host groups and examples, rather than
47
+ # triggering implicit auto-inclusion in groups with matching metadata.
48
+ config.shared_context_metadata_behavior = :apply_to_host_groups
49
+
50
+ # The settings below are suggested to provide a good initial experience
51
+ # with RSpec, but feel free to customize to your heart's content.
52
+ =begin
53
+ # This allows you to limit a spec run to individual examples or groups
54
+ # you care about by tagging them with `:focus` metadata. When nothing
55
+ # is tagged with `:focus`, all examples get run. RSpec also provides
56
+ # aliases for `it`, `describe`, and `context` that include `:focus`
57
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
58
+ config.filter_run_when_matching :focus
59
+
60
+ # Allows RSpec to persist some state between runs in order to support
61
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
62
+ # you configure your source control system to ignore this file.
63
+ config.example_status_persistence_file_path = "spec/examples.txt"
64
+
65
+ # Limits the available syntax to the non-monkey patched syntax that is
66
+ # recommended. For more details, see:
67
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
68
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
69
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
70
+ config.disable_monkey_patching!
71
+
72
+ # This setting enables warnings. It's recommended, but in some cases may
73
+ # be too noisy due to issues in dependencies.
74
+ config.warnings = true
75
+
76
+ # Many RSpec users commonly either run the entire suite or an individual
77
+ # file, and it's useful to allow more verbose output when running an
78
+ # individual spec file.
79
+ if config.files_to_run.one?
80
+ # Use the documentation formatter for detailed output,
81
+ # unless a formatter has already been configured
82
+ # (e.g. via a command-line flag).
83
+ config.default_formatter = 'doc'
84
+ end
85
+
86
+ # Print the 10 slowest examples and example groups at the
87
+ # end of the spec run, to help surface which specs are running
88
+ # particularly slow.
89
+ config.profile_examples = 10
90
+
91
+ # Run specs in random order to surface order dependencies. If you find an
92
+ # order dependency and want to debug it, you can fix the order by providing
93
+ # the seed, which is printed after each run.
94
+ # --seed 1234
95
+ config.order = :random
96
+
97
+ # Seed global randomization in this process using the `--seed` CLI option.
98
+ # Setting this allows you to use `--seed` to deterministically reproduce
99
+ # test failures related to randomization by passing the same `--seed` value
100
+ # as the one that triggered the failure.
101
+ Kernel.srand config.seed
102
+ =end
103
+ end
@@ -0,0 +1,11 @@
1
+ require_relative '../lib/admission'
2
+ require_relative 'rspec_config'
3
+
4
+ require 'byebug'
5
+
6
+ def with_bug
7
+ $bug = true
8
+ yield
9
+ ensure
10
+ $bug = false
11
+ end
@@ -0,0 +1,24 @@
1
+ # COUNTRIES = [
2
+ # :czech,
3
+ # :deutschland,
4
+ # :taiwan,
5
+ # :russia,
6
+ # :australia,
7
+ # :moon
8
+ # ]
9
+ #
10
+ # class << COUNTRIES
11
+ #
12
+ # def europe? country
13
+ # %i[czech deutschland russia].include? country
14
+ # end
15
+ #
16
+ # def safe? country
17
+ # %i[czech deutschland taiwan].include? country
18
+ # end
19
+ #
20
+ # def are_you_dispensable? person
21
+ # not (%i[russia] & person.countries).empty?
22
+ # end
23
+ #
24
+ # end
@@ -0,0 +1,7 @@
1
+ require_relative '../../lib/admission'
2
+
3
+ require_relative 'country'
4
+ require_relative 'person'
5
+
6
+ require_relative 'privileges_and_rules'
7
+ require_relative 'persons_fixtures'
@@ -0,0 +1,31 @@
1
+
2
+ class Person
3
+
4
+ attr_reader :name, :sex, :countries
5
+ attr_reader :privileges, :rules
6
+
7
+ FEMALE = 0
8
+ MALE = 1
9
+ APACHE_HELICOPTER = 2
10
+
11
+ def initialize name, sex, countries
12
+ @name = name
13
+ @sex = sex
14
+ @countries = countries
15
+ end
16
+
17
+
18
+ # privileges per country
19
+
20
+ def not_woman?
21
+ @sex != FEMALE
22
+ end
23
+
24
+ def person
25
+ self
26
+ end
27
+
28
+ # def self.reduce_privileges **per_country
29
+ # end
30
+
31
+ end
@@ -0,0 +1,43 @@
1
+
2
+ fixtures = {
3
+
4
+ peasant_girl: [
5
+ Person::FEMALE,
6
+ []
7
+ ],
8
+
9
+ napoleon: [
10
+ Person::MALE,
11
+ []
12
+ # {all: 'harambe'}
13
+ ],
14
+
15
+ franz_joseph: [
16
+ Person::MALE,
17
+ [:czech, :australia]
18
+ # {czech: 'supernatural-primordial', taiwan: 'supernatural-god'}
19
+ ]
20
+
21
+ }
22
+
23
+ privileges_data_reducer = -> (privileges_data) {
24
+ privileges_data.to_a.reduce [] do |list, per_country_definition|
25
+ country, privileges_names = per_country_definition
26
+ raise "bad country #{country}" unless COUNTRIES.include? country
27
+ privileges_names = [privileges_names] unless privileges_names.is_a? Array
28
+
29
+ privileges = privileges_names.map do |name|
30
+ privilege = Admission::Privilege.get_from_order PRIVILEGES_ORDER, *name.split('-')
31
+ privilege.dup_with_context country
32
+ end
33
+
34
+ list + privileges
35
+ end
36
+ }
37
+
38
+ Person::FIXTURES = ->(name) {
39
+ *attrs, privileges = fixtures[name]
40
+ person = Person.new name, *attrs
41
+ person.instance_variable_set :@privileges, privileges_data_reducer.(privileges)
42
+ person
43
+ }
@@ -0,0 +1,114 @@
1
+
2
+
3
+ PRIVILEGES_ORDER = Admission::Privilege.define_order do
4
+ privilege :vassal, levels: %i[lord]
5
+ privilege :human, levels: %i[count king]
6
+ privilege :emperor, inherits: %i[vassal human]
7
+ end
8
+
9
+
10
+ ACTIONS_RULES = Admission::Arbitration.define_rules PRIVILEGES_ORDER do
11
+
12
+ privilege :human do
13
+ allow_all{ not_woman? }
14
+ forbid :raise_taxes
15
+ forbid :impose_corvee
16
+
17
+ forbid :impose_draft
18
+ forbid :act_as_god
19
+ end
20
+
21
+ privilege :human, :count do
22
+ allow_all do |country|
23
+ countries.include? country
24
+ end
25
+ allow :impose_corvee do |country|
26
+ countries.include? country
27
+ end
28
+ end
29
+
30
+ privilege :human, :king do
31
+ allow_all
32
+ allow :raise_taxes
33
+ end
34
+
35
+ privilege :vassal, :lord do
36
+ allow :impose_draft
37
+ end
38
+
39
+ privilege :emperor do
40
+ allow :act_as_god
41
+ end
42
+
43
+ end
44
+
45
+
46
+ RESOURCE_RULES = Admission::ResourceArbitration.define_rules PRIVILEGES_ORDER do
47
+
48
+ # `allow_all` & inheriting `:forbidden`
49
+
50
+ privilege :human do
51
+ allow_all(:actions){ not_woman? }
52
+ forbid :actions, :raise_taxes
53
+ forbid :actions, :impose_corvee
54
+
55
+ forbid :actions, :impose_draft
56
+ forbid :actions, :act_as_god
57
+ end
58
+
59
+ privilege :human, :count do
60
+ allow_all :actions do |country|
61
+ countries.include? country
62
+ end
63
+ allow :actions, :impose_corvee do |country|
64
+ countries.include? country
65
+ end
66
+ end
67
+
68
+ privilege :human, :king do
69
+ allow_all :actions
70
+ allow :actions, :raise_taxes
71
+ end
72
+
73
+ privilege :vassal, :lord do
74
+ allow :actions, :impose_draft
75
+ end
76
+
77
+ privilege :emperor do
78
+ allow :actions, :act_as_god
79
+ end
80
+
81
+ # `allow_resource` scoping & inheritance
82
+
83
+ privilege :vassal do
84
+
85
+ allow_resource Person, :show do |person, _|
86
+ raise 'person is nil' unless person
87
+ self == person
88
+ end
89
+
90
+ allow :persons, :index do |country|
91
+ countries.include? country
92
+ end
93
+
94
+ end
95
+
96
+ privilege :vassal, :lord do
97
+
98
+ allow_resource(Person, :show){ true }
99
+
100
+ allow_resource Person, %i[index update] do |person, country|
101
+ allowance = countries.include? country
102
+ next allowance unless person
103
+
104
+ allowance && person.countries.include?(country)
105
+ end
106
+
107
+ allow_resource Person, :destroy do |person, country|
108
+ person.countries.include?(country) &&
109
+ person.sex != Person::APACHE_HELICOPTER
110
+ end
111
+
112
+ end
113
+
114
+ end
@@ -0,0 +1 @@
1
+ require_relative '../spec_helper'
@@ -0,0 +1,29 @@
1
+ # require_relative '../spec_helper'
2
+ # require_relative '../test_context/index'
3
+ #
4
+ # RSpec.describe Admission::Ability do
5
+ #
6
+ # let(:nobody_ability){ Admission::Ability.new Person::FIXTURES[:nobody] }
7
+ # let(:haramber_ability){ Admission::Ability.new Person::FIXTURES[:harambe] }
8
+ #
9
+ #
10
+ # describe '#new' do
11
+ #
12
+ # it 'creates instance with no privileges' do
13
+ # expect(nobody_ability.instance_variable_get :@no_privileges).to be
14
+ # end
15
+ #
16
+ # it 'creates instance with some privileges' do
17
+ # expect(haramber_ability.instance_variable_get :@no_privileges).not_to be
18
+ # end
19
+ #
20
+ # end
21
+ #
22
+ # # describe '#process' do
23
+ # #
24
+ # # it '' do
25
+ # # end
26
+ # #
27
+ # # end
28
+ #
29
+ # end
@@ -0,0 +1,184 @@
1
+ require_relative '../_helper'
2
+
3
+ RSpec.describe Admission::Privilege::OrderDefiner do
4
+
5
+ def define_privileges &block
6
+ Admission::Privilege::OrderDefiner.define &block
7
+ end
8
+
9
+ def privilege *args, inherits: nil
10
+ p = Admission::Privilege.new *args
11
+ p.inherits_from inherits if inherits
12
+ p
13
+ end
14
+
15
+ let(:definer){ Admission::Privilege::OrderDefiner.new }
16
+
17
+
18
+ describe '.define' do
19
+
20
+ it 'builds empty index' do
21
+ index = define_privileges{}
22
+ expect(index).to be_a(Hash)
23
+ expect(index).to be_empty
24
+ expect(index).to be_frozen
25
+ end
26
+
27
+ it 'builds single privilege' do
28
+ index = define_privileges{ privilege :man, levels: %i[commoner count] }
29
+ expect(index.keys).to eq(%i[man])
30
+ expect(index[:man].keys).to eq(%i[^ base commoner count])
31
+ expect(index[:man][:base].inherited).to be_nil
32
+ end
33
+
34
+ it 'builds with inheritance' do
35
+ index = define_privileges do
36
+ privilege :man
37
+ privilege :vassal, levels: %i[lord], inherits: :man
38
+ end
39
+
40
+ # structure
41
+ expect(index.keys).to eq(%i[man vassal])
42
+ expect(index[:man].keys).to eq(%i[^ base])
43
+ expect(index[:vassal].keys).to eq(%i[^ base lord])
44
+
45
+ # inheritance
46
+ expect(index[:man][:base].inherited).to be_nil
47
+ expect(index[:vassal][:base].inherited).to eql([privilege(:man)])
48
+ expect(index[:vassal][:lord].inherited).to eql([privilege(:vassal)])
49
+ end
50
+
51
+ end
52
+
53
+
54
+ describe '#privilege' do
55
+
56
+ it 'adds privilege with no levels' do
57
+ definer.privilege :man
58
+ expect(definer.definitions.size).to eq(1)
59
+ expect(definer.definitions[:man][:inherits]).to be_nil
60
+ expect(definer.definitions[:man][:levels]).to eql([privilege(:man)])
61
+ end
62
+
63
+ it 'adds privilege with no levels by string' do
64
+ definer.privilege 'man'
65
+ expect(definer.definitions.size).to eq(1)
66
+ expect(definer.definitions[:man][:inherits]).to be_nil
67
+ expect(definer.definitions[:man][:levels]).to eql([privilege(:man)])
68
+ end
69
+
70
+ it 'adds privilege array of levels' do
71
+ definer.privilege :man, levels: %i[commoner count]
72
+ expect(definer.definitions.size).to eq(1)
73
+ expect(definer.definitions[:man][:inherits]).to be_nil
74
+ expect(definer.definitions[:man][:levels]).to eql([
75
+ privilege(:man), privilege(:man, :commoner), privilege(:man, :count)
76
+ ])
77
+ end
78
+
79
+ it 'adds privilege that inherits single other' do
80
+ definer.privilege :vassal, inherits: :man
81
+ expect(definer.definitions.size).to eq(1)
82
+ expect(definer.definitions[:vassal][:inherits]).to eq([:man])
83
+ end
84
+
85
+ it 'adds privilege that inherits multiple others' do
86
+ definer.privilege :vassal, inherits: %i[man woman apache-helicopter]
87
+ expect(definer.definitions.size).to eq(1)
88
+ expect(definer.definitions[:vassal][:inherits]).to eq([:man, :woman, :'apache-helicopter'])
89
+ end
90
+
91
+ it 'adds multiple privileges' do
92
+ definer.privilege :man
93
+ definer.privilege :vassal
94
+ expect(definer.definitions.keys).to eq(%i[man vassal])
95
+ end
96
+
97
+ end
98
+
99
+
100
+ describe '#setup_inheritance' do
101
+
102
+ it 'sets inheritance' do
103
+ definer.privilege :man
104
+ definer.privilege :vassal, inherits: :man
105
+ definer.send :setup_inheritance
106
+
107
+ vassal = definer.definitions[:vassal]
108
+ expect(vassal[:levels]).to eql([privilege(:vassal)])
109
+ expect(vassal[:levels].first.inherited).to eql([privilege(:man)])
110
+ end
111
+
112
+ it 'sets inheritance to top level' do
113
+ definer.privilege :man, levels: %i[commoner count]
114
+ definer.privilege :vassal, inherits: :man
115
+ definer.send :setup_inheritance
116
+
117
+ vassal = definer.definitions[:vassal]
118
+ expect(vassal[:levels]).to eql([privilege(:vassal)])
119
+ expect(vassal[:levels].first.inherited).to eql([privilege(:man, :count)])
120
+ end
121
+
122
+ it 'sets inheritance throughout levels' do
123
+ definer.privilege :man
124
+ definer.privilege :vassal, inherits: :man, levels: %i[lord]
125
+ definer.send :setup_inheritance
126
+
127
+ vassal = definer.definitions[:vassal]
128
+ expect(vassal[:levels]).to eql([privilege(:vassal), privilege(:vassal, :lord)])
129
+ expect(vassal[:levels][0].inherited).to eql([privilege(:man)])
130
+ expect(vassal[:levels][1].inherited).to eql([privilege(:vassal)])
131
+ end
132
+
133
+ end
134
+
135
+
136
+ describe '#build_index' do
137
+
138
+ it 'returns hash with single privileges' do
139
+ definer.privilege :man
140
+ index = definer.send :build_index
141
+ expect(index).to be_a(Hash)
142
+ expect(index.keys).to eq([:man])
143
+
144
+ man = index.values.first
145
+ expect(man.keys).to eq(%i[^ base])
146
+ expect(man.values).to eql([privilege(:man), privilege(:man)])
147
+ end
148
+
149
+ it 'builds index for privilege with levels' do
150
+ definer.privilege :man, levels: %i[commoner count]
151
+ index = definer.send :build_index
152
+ expect(index).to be_a(Hash)
153
+ expect(index.keys).to eq([:man])
154
+
155
+ man = index[:man]
156
+ expect(man.keys).to eq(%i[^ base commoner count])
157
+ expect(man[:'^']).to eql(privilege :man, :count)
158
+ expect(man[:base]).to eql(privilege :man)
159
+ expect(man[:commoner]).to eql(privilege :man, :commoner)
160
+ expect(man[:count]).to eql(privilege :man, :count)
161
+ end
162
+
163
+ it 'returns hash with more privileges' do
164
+ definer.privilege :man
165
+ definer.privilege :vassal, levels: %i[lord]
166
+ index = definer.send :build_index
167
+ expect(index).to be_a(Hash)
168
+ expect(index.keys).to eq([:man, :vassal])
169
+
170
+ man = index[:man]
171
+ expect(man.keys).to eq(%i[^ base])
172
+ expect(man[:'^']).to eql(privilege :man)
173
+ expect(man[:base]).to eql(privilege :man)
174
+
175
+ vassal = index[:vassal]
176
+ expect(vassal.keys).to eq(%i[^ base lord])
177
+ expect(vassal[:'^']).to eql(privilege :vassal, :lord)
178
+ expect(vassal[:base]).to eql(privilege :vassal)
179
+ expect(vassal[:lord]).to eql(privilege :vassal, :lord)
180
+ end
181
+
182
+ end
183
+
184
+ end