pragma-operation 0.1.2 → 1.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a0e4b70a6dbf00fc017919c4a20a4fcab1314caf
4
- data.tar.gz: 10bd799eabb43d6f76a9d29f80a737df2c2902e0
3
+ metadata.gz: d1a35deac8b18a13c8f5e7cd9b4ee1372afb6321
4
+ data.tar.gz: 6f2abba3db47e143d06c407fe33a1416f44cffac
5
5
  SHA512:
6
- metadata.gz: ff8e629a189aa67af574569fbf2fa2db77e65e753d553f4d6ae2fc3d8b892693060a223a0f69a6112f8e9ba6ba0479fc44b77550616a9a97e7567f0565ca36a1
7
- data.tar.gz: 5db34e59a55d5251eb05d0f33283bb83f26027afe491c8150094076eee53af092f0d20fd0f345381f1dfa7c879643f2e9868611b4f6b0b6cbe0f827a94bd1418
6
+ metadata.gz: 1af71177cbec88e40273ebc84fd5118d2bf2d894df7823791850e50d12dcd5ca0e2ba649b6c4509ff71708bfdafb3bd13ba78064cdc78709f9a3e59267c1626d
7
+ data.tar.gz: fd674718c93267c02e48e6ce035ff0595a1cb6db79ed047938a762ae4e555ed35e9be6348ec02d5b0aed038fe428f64c738fc10edd7c62498b9c24bec37976bb
data/doc/03-policies.md CHANGED
@@ -1,8 +1,7 @@
1
1
  # Policies
2
2
 
3
3
  Operations integrate with [Pragma::Policy](https://github.com/pragmarb/pragma-policy). All you have
4
- to do is specify the policy class with `#policy`. This will give you access to `#authorize` and
5
- `#authorize!`:
4
+ to do is specify the policy class with `#policy`:
6
5
 
7
6
  ```ruby
8
7
  module API
@@ -92,3 +91,28 @@ module API
92
91
  end
93
92
  end
94
93
  ```
94
+
95
+ ## Authorizing collections
96
+
97
+ To authorize a collection, use `#authorize_collection`. This will call `.accessible_by` on the
98
+ policy class with the current user and the provided collection and return an authorized collection
99
+ containing only records accessible by the user.
100
+
101
+ ```ruby
102
+ module API
103
+ module V1
104
+ module Post
105
+ module Operation
106
+ class Index < Pragma::Operation::Base
107
+ policy API::V1::Post::Policy
108
+
109
+ def call
110
+ posts = authorize_collection Post.all
111
+ respond_with status: :ok, resource: posts
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ ```
@@ -0,0 +1,26 @@
1
+ # Decorators
2
+
3
+ Operations integrate with [Pragma::Decorator](https://github.com/pragmarb/pragma-decorator). All you
4
+ have to do is specify the policy class with `#decorator`. This will give you access to `#decorate`:
5
+
6
+ ```ruby
7
+ module API
8
+ module V1
9
+ module Post
10
+ module Operation
11
+ class Show < Pragma::Operation::Base
12
+ policy API::V1::Post::Policy
13
+
14
+ def call
15
+ post = Post.find(params[:id])
16
+ respond_with status: :ok, resource: decorate(post)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ ```
24
+
25
+ Note that `#decorate` works with both singular resources and collections, as it uses the decorator's
26
+ [`.represent`](http://trailblazer.to/gems/representable/3.0/api.html) method.
@@ -18,6 +18,13 @@ module Pragma
18
18
  @policy = klass
19
19
  end
20
20
 
21
+ # Returns the policy class.
22
+ #
23
+ # @return [Class]
24
+ def policy_klass
25
+ @policy
26
+ end
27
+
21
28
  # Builds the policy for the given user and resource, using the previous defined policy
22
29
  # class.
23
30
  #
@@ -28,7 +35,7 @@ module Pragma
28
35
  #
29
36
  # @see #policy
30
37
  def build_policy(user:, resource:)
31
- @policy.new(user: user, resource: resource)
38
+ policy_klass.new(user: user, resource: resource)
32
39
  end
33
40
  end
34
41
 
@@ -48,11 +55,15 @@ module Pragma
48
55
 
49
56
  # Authorizes this operation on the provided resource or policy.
50
57
  #
58
+ # If no policy was defined, simply returns true.
59
+ #
51
60
  # @param authorizable [Pragma::Policy::Base|Object] resource or policy
52
61
  #
53
62
  # @return [Boolean] whether the operation is authorized
54
63
  def authorize(authorizable)
55
- policy = if defined?(Pragma::Policy::Base) && authorizable.is_a?(Pragma::Policy::Base)
64
+ return true unless self.class.policy_klass
65
+
66
+ policy = if authorizable.is_a?(self.class.policy_klass)
56
67
  authorizable
57
68
  else
58
69
  build_policy(authorizable)
@@ -77,6 +88,22 @@ module Pragma
77
88
  }
78
89
  )
79
90
  end
91
+
92
+ # Scopes the provided collection.
93
+ #
94
+ # If no policy class is defined, simply returns the collection.
95
+ #
96
+ # @param collection [Enumerable]
97
+ #
98
+ # @return [Pragma::Decorator::Base|Enumerable]
99
+ def authorize_collection(collection)
100
+ return collection unless self.class.policy_klass
101
+
102
+ self.class.policy_klass.accessible_by(
103
+ user: current_user,
104
+ scope: collection
105
+ )
106
+ end
80
107
  end
81
108
  end
82
109
  end
@@ -9,6 +9,10 @@ module Pragma
9
9
  class Base
10
10
  include Interactor
11
11
 
12
+ include Authorization
13
+ include Validation
14
+ include Decoration
15
+
12
16
  STATUSES = {
13
17
  200 => :ok,
14
18
  201 => :created,
@@ -70,9 +74,6 @@ module Pragma
70
74
  class << self
71
75
  def inherited(child)
72
76
  child.class_eval do
73
- include Authorization
74
- include Validation
75
-
76
77
  before :setup_context
77
78
  around :handle_halt
78
79
  after :mark_result, :consolidate_status, :validate_status, :set_default_status
@@ -0,0 +1,70 @@
1
+ module Pragma
2
+ module Operation
3
+ # Provides integration with {https://github.com/pragmarb/pragma-decorator Pragma::Decorator}.
4
+ #
5
+ # @author Alessandro Desantis
6
+ module Decoration
7
+ def self.included(base)
8
+ base.extend ClassMethods
9
+ base.include InstanceMethods
10
+ end
11
+
12
+ module ClassMethods # :nodoc:
13
+ # Sets the decorator to use for validating this operation.
14
+ #
15
+ # @param klass [Class] a subclass of +Pragma::Decorator::Base+
16
+ def decorator(klass)
17
+ @decorator = klass
18
+ end
19
+
20
+ # Returns the decorator class.
21
+ #
22
+ # @return [Class]
23
+ def decorator_klass
24
+ @decorator
25
+ end
26
+
27
+ # Builds the decorator for the given resource, using the previously defined decorator class.
28
+ #
29
+ # Works with both singular resources and collections.
30
+ #
31
+ # @param resource [Object]
32
+ #
33
+ # @return [Pragma::Decorator::Base]
34
+ #
35
+ # @see #decorator
36
+ def build_decorator(resource)
37
+ decorator_klass.represent(resource)
38
+ end
39
+ end
40
+
41
+ module InstanceMethods # :nodoc:
42
+ # Builds the decorator for the given resource, using the previously defined decorator class.
43
+ #
44
+ # This is just an instance-level alias of {.build_decorator}. You should use this from
45
+ # inside the operation.
46
+ #
47
+ # @param resource [Object]
48
+ #
49
+ # @return [Pragma::Decorator::Base]
50
+ #
51
+ # @see #decorate
52
+ def build_decorator(resource)
53
+ self.class.build_decorator(resource)
54
+ end
55
+
56
+ # If a decorator is defined, acts as an alias for {#build_decorator}. If not, simply returns
57
+ # the provided resource.
58
+ # @param decoratable [Object]
59
+ #
60
+ # @return [Pragma::Decorator::Base|Object]
61
+ #
62
+ # @see #build_decorator
63
+ def decorate(decoratable)
64
+ return decoratable unless self.class.decorator_klass
65
+ build_decorator(decoratable)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -18,6 +18,13 @@ module Pragma
18
18
  @contract = klass
19
19
  end
20
20
 
21
+ # Returns the contract class.
22
+ #
23
+ # @return [Class]
24
+ def contract_klass
25
+ @contract
26
+ end
27
+
21
28
  # Builds the contract for the given resource, using the previous defined contract class.
22
29
  #
23
30
  # @param resource [Object]
@@ -26,7 +33,7 @@ module Pragma
26
33
  #
27
34
  # @see #contract
28
35
  def build_contract(resource)
29
- @contract.new(resource)
36
+ contract_klass.new(resource)
30
37
  end
31
38
  end
32
39
 
@@ -53,7 +60,7 @@ module Pragma
53
60
  # @return [Boolean] whether the operation is valid
54
61
  def validate(validatable)
55
62
  # rubocop:disable Metrics/LineLength
56
- contract = if defined?(Pragma::Contract::Base) && validatable.is_a?(Pragma::Contract::Base)
63
+ contract = if validatable.is_a?(self.class.contract_klass)
57
64
  validatable
58
65
  else
59
66
  build_contract(validatable)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Pragma
3
3
  module Operation
4
- VERSION = '0.1.2'
4
+ VERSION = '1.0.0'
5
5
  end
6
6
  end
@@ -2,9 +2,10 @@
2
2
  require 'interactor'
3
3
 
4
4
  require 'pragma/operation/version'
5
- require 'pragma/operation/base'
6
5
  require 'pragma/operation/authorization'
7
6
  require 'pragma/operation/validation'
7
+ require 'pragma/operation/decoration'
8
+ require 'pragma/operation/base'
8
9
 
9
10
  module Pragma
10
11
  # Operations provide business logic encapsulation for your JSON API.
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_development_dependency 'pragma-policy', '~> 0.1.0'
26
26
  spec.add_development_dependency 'pragma-contract', '~> 0.1.0'
27
+ spec.add_development_dependency 'pragma-decorator', '~> 0.1.0'
27
28
 
28
29
  spec.add_development_dependency "bundler"
29
30
  spec.add_development_dependency "rake"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pragma-operation
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alessandro Desantis
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-12-26 00:00:00.000000000 Z
11
+ date: 2016-12-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: interactor
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.1.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: pragma-decorator
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.1.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.1.0
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: bundler
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -156,9 +170,11 @@ files:
156
170
  - doc/01-basic-usage.md
157
171
  - doc/02-contracts.md
158
172
  - doc/03-policies.md
173
+ - doc/04-decorators.md
159
174
  - lib/pragma/operation.rb
160
175
  - lib/pragma/operation/authorization.rb
161
176
  - lib/pragma/operation/base.rb
177
+ - lib/pragma/operation/decoration.rb
162
178
  - lib/pragma/operation/validation.rb
163
179
  - lib/pragma/operation/version.rb
164
180
  - pragma-operation.gemspec