law 0.1.3 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e74cd15524ae8f0731bcb351779158496be3fa61a49e7e3553a53a0bfd5fdcff
4
- data.tar.gz: fa7920650d8debe57a1bbcafa2b6cabf1e9b617783a3f22edc9568a9e7eea359
3
+ metadata.gz: 2e2ac1483d7b8253bb52289a1c81727bbfc15f47a60f0f03ab7f7f9c78e38d69
4
+ data.tar.gz: ab18b48276b107552e3335cd8dfc17e98d04a764aef9655ca369d40b5c6fae10
5
5
  SHA512:
6
- metadata.gz: cb1bda1a9cfbbe9205453a318d2ef783e2adc62ce13bdea457e76c93f07194d4531265c0d3284eb866c722aed16853696d6283a7d590de5f8a90145ef441b7bd
7
- data.tar.gz: 866e1524f3d77b29d872ade4758faa389889a114a6a287b68fae0772fa5371658a4be22cc9d5c1cdb87e6f046068c864a4af3838a5ed35cf965d8aadace18de8
6
+ metadata.gz: 259728e11d27c2c78829433b4dcd6e6d6f869533c7637002b6823c498523e5bc8353a2ffcd307556d09b94095ea435cf963bf4ae6fe88234ae1e6fe90fecc437
7
+ data.tar.gz: 6383a6bd485a6ea5ad111095bc8df0e961c570ef54206f5139eb7c8ad2b742501d427656e79a26e2838b3a0ccef224401a9e8c564ceb9eadb55b14d78600f152
@@ -0,0 +1,9 @@
1
+ Description:
2
+ Stub a Law with a test.
3
+
4
+ Example:
5
+ `rails generate law foo`
6
+
7
+ Generates:
8
+ Law: app/laws/foo_law.rb
9
+ Test: spec/laws/foo_law_spec.rb
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Law
4
+ module Generators
5
+ class LawGenerator < Rails::Generators::NamedBase
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ hook_for :test_framework
9
+
10
+ def create_law
11
+ template "law.rb.erb", File.join("app/laws/", class_path, "#{file_name}_law.rb")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ Description:
2
+ Stub a Regulation with a test.
3
+
4
+ Example:
5
+ `rails generate law:regulation foo`
6
+
7
+ Generates:
8
+ Regulation: app/regulations/foo_regulation.rb
9
+ Test: spec/regulations/foo_regulation_spec.rb
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Law
4
+ module Generators
5
+ class RegulationGenerator < Rails::Generators::NamedBase
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ hook_for :test_framework
9
+
10
+ def create_regulation
11
+ template "regulation.rb.erb", File.join("app/regulations/", class_path, "#{file_name}_regulation.rb")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= class_name %>Regulation < ApplicationRegulation
4
+ end
@@ -0,0 +1,9 @@
1
+ Description:
2
+ Stub a Statute with a test.
3
+
4
+ Example:
5
+ `rails generate law:statute foo`
6
+
7
+ Generates:
8
+ Statute: app/statutes/foo_statute.rb
9
+ Test: spec/statutes/foo_statute_spec.rb
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Law
4
+ module Generators
5
+ class StatuteGenerator < Rails::Generators::NamedBase
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ hook_for :test_framework
9
+
10
+ def create_statute
11
+ template "statute.rb.erb", File.join("app/statutes/", class_path, "#{file_name}_statute.rb")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= class_name %>Statute < ApplicationStatute
4
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= class_name %>Law < ApplicationLaw
4
+ end
@@ -0,0 +1,9 @@
1
+
2
+ Description:
3
+ Stub a Law test.
4
+
5
+ Example:
6
+ `rails generate rspec:law foo`
7
+
8
+ Generates:
9
+ Test: spec/laws/foo_law_spec.rb
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rspec
4
+ module Generators
5
+ class LawGenerator < Rails::Generators::NamedBase
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ def create_spec_file
9
+ template "law_spec.rb.erb", File.join("spec/laws/", class_path, "#{file_name}_law_spec.rb")
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails_helper"
4
+
5
+ RSpec.describe <%= class_name %>Law, type: :law do
6
+ it { is_expected.to inherit_from ApplicationLaw }
7
+ end
@@ -0,0 +1,9 @@
1
+
2
+ Description:
3
+ Stub a Regulation test.
4
+
5
+ Example:
6
+ `rails generate rspec:regulation foo`
7
+
8
+ Generates:
9
+ Test: spec/regulations/foo_regulation_spec.rb
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rspec
4
+ module Generators
5
+ class RegulationGenerator < Rails::Generators::NamedBase
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ def create_spec_file
9
+ template "regulation_spec.rb.erb", File.join("spec/regulations/", class_path, "#{file_name}_regulation_spec.rb")
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails_helper"
4
+
5
+ RSpec.describe <%= class_name %>Regulation, type: :regulation do
6
+ it { is_expected.to inherit_from ApplicationRegulation }
7
+ end
@@ -0,0 +1,9 @@
1
+
2
+ Description:
3
+ Stub a Statute test.
4
+
5
+ Example:
6
+ `rails generate rspec:statute foo`
7
+
8
+ Generates:
9
+ Test: spec/statutes/foo_statute_spec.rb
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rspec
4
+ module Generators
5
+ class StatuteGenerator < Rails::Generators::NamedBase
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ def create_spec_file
9
+ template "statute_spec.rb.erb", File.join("spec/statutes/", class_path, "#{file_name}_statute_spec.rb")
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails_helper"
4
+
5
+ RSpec.describe <%= class_name %>Statute, type: :statute do
6
+ it { is_expected.to inherit_from ApplicationStatute }
7
+ end
data/lib/law.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "active_support"
4
4
  require "active_support/core_ext/enumerable"
5
+ require "active_support/hash_with_indifferent_access"
5
6
 
6
7
  require "spicery"
7
8
 
@@ -27,4 +28,5 @@ module Law
27
28
 
28
29
  class NotAuthorizedError < Error; end
29
30
  class InjunctionError < NotAuthorizedError; end
31
+ class ComplianceError < NotAuthorizedError; end
30
32
  end
data/lib/law/judgement.rb CHANGED
@@ -15,7 +15,7 @@ module Law
15
15
 
16
16
  attr_reader :petition, :violations, :applied_regulations
17
17
 
18
- delegate :statute, :applicable_regulations, to: :petition
18
+ delegate :statute, :applicable_regulations, :compliant?, to: :petition, allow_nil: true
19
19
 
20
20
  def initialize(petition)
21
21
  @petition = petition
@@ -39,20 +39,30 @@ module Law
39
39
  end
40
40
 
41
41
  def judge!
42
- if statute.unregulated?
42
+ raise AlreadyJudgedError if adjudicated?
43
+
44
+ if statute&.unregulated?
43
45
  @applied_regulations = [ nil ]
44
46
  return true
45
47
  end
46
48
 
49
+ ensure_jurisdiction
50
+ reckon!
51
+
52
+ true
53
+ end
54
+
55
+ private
56
+
57
+ def ensure_jurisdiction
47
58
  raise InjunctionError if applicable_regulations.blank?
48
- raise AlreadyJudgedError if adjudicated?
59
+ raise ComplianceError unless compliant?
60
+ end
49
61
 
62
+ def reckon!
50
63
  @applied_regulations = applicable_regulations.map { |regulation| regulation.new(petition: petition) }
51
64
  @violations = applied_regulations.reject(&:valid?)
52
-
53
65
  raise NotAuthorizedError unless authorized?
54
-
55
- true
56
66
  end
57
67
  end
58
68
  end
@@ -8,22 +8,32 @@ module Law
8
8
 
9
9
  included do
10
10
  class_attribute :actions, instance_writer: false, default: HashWithIndifferentAccess.new
11
+ class_attribute :revoked_actions, instance_writer: false, default: HashWithIndifferentAccess.new
11
12
 
12
- delegate :statute_for_action?, to: :class
13
+ delegate :statute_for_action?, :revoked_action?, to: :class
13
14
  end
14
15
 
15
16
  class_methods do
16
17
  def inherited(base)
17
18
  base.actions = actions.dup
19
+ base.revoked_actions = revoked_actions.dup
18
20
  super
19
21
  end
20
22
 
23
+ def revoked_action?(action)
24
+ revoked_actions[action].present?
25
+ end
26
+
21
27
  def statute_for_action?(action)
22
28
  actions[action].present?
23
29
  end
24
30
 
25
31
  private
26
32
 
33
+ def revoke_action(*input_actions)
34
+ input_actions.each { |action| revoked_actions[action] = true }
35
+ end
36
+
27
37
  def define_action(*input_actions, enforces: nil)
28
38
  raise ArgumentError, "invalid statute: #{enforces}" unless enforceable?(enforces)
29
39
 
@@ -14,6 +14,8 @@ module Law
14
14
  end
15
15
 
16
16
  def petition_for_action(action)
17
+ return if revoked_action?(action)
18
+
17
19
  Law::Petition.new(
18
20
  statute: actions[action] || _default_statute,
19
21
  source: source,
data/lib/law/legalize.rb CHANGED
@@ -23,7 +23,7 @@ module Law
23
23
  end
24
24
 
25
25
  def law(object = nil, petitioner = nil, permissions: nil, parameters: nil, law_class: nil)
26
- object ||= try(:controller_name)&.singularize&.camelize&.safe_constantize
26
+ object ||= @record || try(:controller_name)&.singularize&.camelize&.safe_constantize
27
27
  petitioner ||= try(:current_user)
28
28
  permissions ||= petitioner.try(:permissions)
29
29
  law_class ||= object.try(:conjugate, Law::LawBase)
data/lib/law/petition.rb CHANGED
@@ -18,5 +18,11 @@ module Law
18
18
  statute.regulations.select { |regulation| permission_list.include? regulation.key }
19
19
  end
20
20
  memoize :applicable_regulations
21
+
22
+ def compliant?
23
+ return applicable_regulations.any? unless statute.full_compliance_required?
24
+
25
+ statute.regulations == applicable_regulations
26
+ end
21
27
  end
22
28
  end
@@ -6,3 +6,4 @@ require_relative "custom_matchers/be_imposed_by"
6
6
  require_relative "custom_matchers/define_action"
7
7
  require_relative "custom_matchers/have_default_statute"
8
8
  require_relative "custom_matchers/impose_regulations"
9
+ require_relative "custom_matchers/revoke_action"
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ # RSpec matcher that tests revoking of statutes in laws.
4
+ #
5
+ # class ExampleStatute < ApplicationStatute
6
+ # end
7
+ #
8
+ # class CommonLaw < ApplicationStatute
9
+ # define_action :new, enforces: ExampleRegulation
10
+ # define_action :create, enforces: ExampleRegulation
11
+ # define_action :edit
12
+ # end
13
+ #
14
+ # class ExampleLaw < CommonLaw
15
+ # revoke_action :new, :edit
16
+ # end
17
+ #
18
+ # RSpec.describe ExampleLaw, type: :law do
19
+ # it { is_expected.to revoke_action :new, :edit }
20
+ # end
21
+
22
+ RSpec::Matchers.define :revoke_action do |*actions|
23
+ match do
24
+ actions.each { |action| expect(test_subject.revoked_action?(action)).to eq true }
25
+ end
26
+ description { "revoke #{"action".pluralize(actions.length)} #{actions.join(", ")}" }
27
+ failure_message { "expected #{test_subject} to revoke #{"action".pluralize(actions.length)} #{actions.join(", ")}" }
28
+ failure_message_when_negated do
29
+ "expected #{test_subject} not to revoke #{"action".pluralize(actions.length)} #{actions.join(", ")}"
30
+ end
31
+
32
+ def test_subject
33
+ subject.is_a?(Class) ? subject : subject.class
34
+ end
35
+ end
@@ -2,11 +2,13 @@
2
2
 
3
3
  require_relative "statutes/regulations"
4
4
  require_relative "statutes/laws"
5
+ require_relative "statutes/compliance"
5
6
 
6
7
  # A **Statute** restricts actions to **Actors** by enforcing a collection of **Permissions**.
7
8
  module Law
8
9
  class StatuteBase < Spicerack::RootObject
9
10
  include Law::Statutes::Regulations
10
11
  include Law::Statutes::Laws
12
+ include Law::Statutes::Compliance
11
13
  end
12
14
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A **Statute** is a collection of imposed **Regulations** with some **Compliance** rules.
4
+ module Law
5
+ module Statutes
6
+ module Compliance
7
+ extend ActiveSupport::Concern
8
+
9
+ class_methods do
10
+ def full_compliance_required?
11
+ @require_full_compliance.present?
12
+ end
13
+
14
+ def inherited(base)
15
+ base.require_full_compliance if full_compliance_required?
16
+ super
17
+ end
18
+
19
+ protected
20
+
21
+ def require_full_compliance
22
+ @require_full_compliance = true
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
data/lib/law/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Law
4
- VERSION = "0.1.3"
4
+ VERSION = "0.1.8"
5
5
  end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: law
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Garside
8
+ - Brandon Trumpold
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2020-03-04 00:00:00.000000000 Z
12
+ date: 2021-06-09 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: activesupport
@@ -16,21 +17,21 @@ dependencies:
16
17
  requirements:
17
18
  - - ">="
18
19
  - !ruby/object:Gem::Version
19
- version: 5.2.1
20
+ version: 6.0.3.7
20
21
  type: :runtime
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
25
  - - ">="
25
26
  - !ruby/object:Gem::Version
26
- version: 5.2.1
27
+ version: 6.0.3.7
27
28
  - !ruby/object:Gem::Dependency
28
29
  name: spicery
29
30
  requirement: !ruby/object:Gem::Requirement
30
31
  requirements:
31
32
  - - ">="
32
33
  - !ruby/object:Gem::Version
33
- version: 0.22.3.1
34
+ version: 0.26.0.4
34
35
  - - "<"
35
36
  - !ruby/object:Gem::Version
36
37
  version: '1.0'
@@ -40,7 +41,7 @@ dependencies:
40
41
  requirements:
41
42
  - - ">="
42
43
  - !ruby/object:Gem::Version
43
- version: 0.22.3.1
44
+ version: 0.26.0.4
44
45
  - - "<"
45
46
  - !ruby/object:Gem::Version
46
47
  version: '1.0'
@@ -134,7 +135,7 @@ dependencies:
134
135
  requirements:
135
136
  - - ">="
136
137
  - !ruby/object:Gem::Version
137
- version: 0.22.3.1
138
+ version: 0.26.0.4
138
139
  - - "<"
139
140
  - !ruby/object:Gem::Version
140
141
  version: '1.0'
@@ -144,7 +145,7 @@ dependencies:
144
145
  requirements:
145
146
  - - ">="
146
147
  - !ruby/object:Gem::Version
147
- version: 0.22.3.1
148
+ version: 0.26.0.4
148
149
  - - "<"
149
150
  - !ruby/object:Gem::Version
150
151
  version: '1.0'
@@ -154,7 +155,7 @@ dependencies:
154
155
  requirements:
155
156
  - - ">="
156
157
  - !ruby/object:Gem::Version
157
- version: 0.22.3.1
158
+ version: 0.26.0.4
158
159
  - - "<"
159
160
  - !ruby/object:Gem::Version
160
161
  version: '1.0'
@@ -164,7 +165,7 @@ dependencies:
164
165
  requirements:
165
166
  - - ">="
166
167
  - !ruby/object:Gem::Version
167
- version: 0.22.3.1
168
+ version: 0.26.0.4
168
169
  - - "<"
169
170
  - !ruby/object:Gem::Version
170
171
  version: '1.0'
@@ -172,12 +173,31 @@ description: Enforce the laws of your Rails application with highly extensible a
172
173
  policies
173
174
  email:
174
175
  - garside@gmail.com
176
+ - brandon.trumpold@gmail.com
175
177
  executables: []
176
178
  extensions: []
177
179
  extra_rdoc_files: []
178
180
  files:
179
181
  - LICENSE.txt
180
182
  - README.md
183
+ - lib/generators/law/USAGE
184
+ - lib/generators/law/law_generator.rb
185
+ - lib/generators/law/regulation/USAGE
186
+ - lib/generators/law/regulation/regulation_generator.rb
187
+ - lib/generators/law/regulation/templates/regulation.rb.erb
188
+ - lib/generators/law/statute/USAGE
189
+ - lib/generators/law/statute/statute_generator.rb
190
+ - lib/generators/law/statute/templates/statute.rb.erb
191
+ - lib/generators/law/templates/law.rb.erb
192
+ - lib/generators/rspec/law/USAGE
193
+ - lib/generators/rspec/law/law_generator.rb
194
+ - lib/generators/rspec/law/templates/law_spec.rb.erb
195
+ - lib/generators/rspec/regulation/USAGE
196
+ - lib/generators/rspec/regulation/regulation_generator.rb
197
+ - lib/generators/rspec/regulation/templates/regulation_spec.rb.erb
198
+ - lib/generators/rspec/statute/USAGE
199
+ - lib/generators/rspec/statute/statute_generator.rb
200
+ - lib/generators/rspec/statute/templates/statute_spec.rb.erb
181
201
  - lib/law.rb
182
202
  - lib/law/judgement.rb
183
203
  - lib/law/law_base.rb
@@ -198,9 +218,11 @@ files:
198
218
  - lib/law/rspec/custom_matchers/define_action.rb
199
219
  - lib/law/rspec/custom_matchers/have_default_statute.rb
200
220
  - lib/law/rspec/custom_matchers/impose_regulations.rb
221
+ - lib/law/rspec/custom_matchers/revoke_action.rb
201
222
  - lib/law/rspec/shoulda_matcher_helper.rb
202
223
  - lib/law/spec_helper.rb
203
224
  - lib/law/statute_base.rb
225
+ - lib/law/statutes/compliance.rb
204
226
  - lib/law/statutes/laws.rb
205
227
  - lib/law/statutes/regulations.rb
206
228
  - lib/law/version.rb
@@ -226,7 +248,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
226
248
  - !ruby/object:Gem::Version
227
249
  version: '0'
228
250
  requirements: []
229
- rubygems_version: 3.0.3
251
+ rubygems_version: 3.1.4
230
252
  signing_key:
231
253
  specification_version: 4
232
254
  summary: Give illegal operations a whole new meaning with this policy enforcement