pragma-operation 0.1.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/doc/03-policies.md +26 -2
- data/doc/04-decorators.md +26 -0
- data/lib/pragma/operation/authorization.rb +29 -2
- data/lib/pragma/operation/base.rb +4 -3
- data/lib/pragma/operation/decoration.rb +70 -0
- data/lib/pragma/operation/validation.rb +9 -2
- data/lib/pragma/operation/version.rb +1 -1
- data/lib/pragma/operation.rb +2 -1
- data/pragma-operation.gemspec +1 -0
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d1a35deac8b18a13c8f5e7cd9b4ee1372afb6321
|
4
|
+
data.tar.gz: 6f2abba3db47e143d06c407fe33a1416f44cffac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
63
|
+
contract = if validatable.is_a?(self.class.contract_klass)
|
57
64
|
validatable
|
58
65
|
else
|
59
66
|
build_contract(validatable)
|
data/lib/pragma/operation.rb
CHANGED
@@ -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.
|
data/pragma-operation.gemspec
CHANGED
@@ -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.
|
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-
|
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
|