pragma-policy 2.0.0 → 2.1.0

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
- SHA1:
3
- metadata.gz: 92f9cd653b6f54508780a68f79ccaa83c923780c
4
- data.tar.gz: 12813e8504acfcade966bf450a4bd0c3f76db4be
2
+ SHA256:
3
+ metadata.gz: b95479afa5f162950fb8f7a10376007a75eb01b08ac65579fd2fead9992b9d71
4
+ data.tar.gz: 83af353d6ed1d854b786ac0fd294ef3342c8124e1010caf20933283e55bca731
5
5
  SHA512:
6
- metadata.gz: 45f33ffbbc876b4a386841e819e8ce85d315039bad4d5644e999d527c88fa97153217f689c99dfb987481a0b6f1483775c7e0bb75ab568a8af4f0fe58caddcea
7
- data.tar.gz: f7cd7b953b894075e7fe636c314509c3d8d9972b865312aa7afc758cce36180eda3ed1f30bb710e7d8ea763521e7a9cda0ee401f9786483940b8d5c9c0d740e2
6
+ metadata.gz: b6abf9d86dc35152ed38e6c68bcee14ad465491b54c86bef35250c94485a8553f277533b902e76bb07062d9a4183a0743e08d421915d6b25662564eae64b4f55
7
+ data.tar.gz: eae004c5e795d38f8741ff3b85ef4c931b85b072e5783c1a348c2da6527214ad242c4fdc3dfe7c048565d821758ae7006d280411e9ebed0e46b7b981f9619a62
@@ -1,10 +1,7 @@
1
1
  require: rubocop-rspec
2
2
 
3
3
  AllCops:
4
- TargetRubyVersion: 2.3
5
- Include:
6
- - '**/Gemfile'
7
- - '**/Rakefile'
4
+ TargetRubyVersion: 2.5
8
5
  Exclude:
9
6
  - 'bin/*'
10
7
  - 'db/**/*'
@@ -53,7 +50,7 @@ Style/SignalException:
53
50
  Style/BracesAroundHashParameters:
54
51
  EnforcedStyle: context_dependent
55
52
 
56
- Lint/EndAlignment:
53
+ Layout/EndAlignment:
57
54
  EnforcedStyleAlignWith: variable
58
55
  AutoCorrect: true
59
56
 
@@ -2,4 +2,6 @@ sudo: false
2
2
  language: ruby
3
3
  rvm:
4
4
  - 2.3.1
5
+ - 2.4.2
6
+ - 2.5.1
5
7
  before_install: gem install bundler -v 1.13.3
@@ -0,0 +1,32 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
6
+ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [2.1.0]
11
+
12
+ ### Added
13
+
14
+ - Added `Pragma::Policy::Pundit` for policies that just delegate to Pundit
15
+ - Implemented `#context` as an alias of `#user`
16
+
17
+ ### Changed
18
+
19
+ - `Pragma::Policy::Base::Scope` has been moved to `Pragma::Policy::Scope` (alias provided for BC)
20
+ - `Pragma::Policy::UnauthorizedError` no longer inherits from `Pundit::UnauthorizedError`
21
+
22
+ ### Removed
23
+
24
+ - Dropped Pundit dependency
25
+
26
+ ## [2.0.0]
27
+
28
+ First Pragma 2 release.
29
+
30
+ [Unreleased]: https://github.com/pragmarb/pragma-policy/compare/v2.1.0...HEAD
31
+ [2.1.0]: https://github.com/pragmarb/pragma-policy/compare/v2.0.0...v2.1.0
32
+ [2.0.0]: https://github.com/pragmarb/pragma-policy/compare/v0.1.0...v2.0.0
data/README.md CHANGED
@@ -1,14 +1,11 @@
1
1
  # Pragma::Policy
2
2
 
3
- [![Build Status](https://img.shields.io/travis/pragmarb/pragma-policy.svg?maxAge=3600&style=flat-square)](https://travis-ci.org/pragmarb/pragma-policy)
4
- [![Dependency Status](https://img.shields.io/gemnasium/pragmarb/pragma-policy.svg?maxAge=3600&style=flat-square)](https://gemnasium.com/github.com/pragmarb/pragma-policy)
5
- [![Code Climate](https://img.shields.io/codeclimate/github/pragmarb/pragma-policy.svg?maxAge=3600&style=flat-square)](https://codeclimate.com/github/pragmarb/pragma-policy)
6
- [![Coveralls](https://img.shields.io/coveralls/pragmarb/pragma-policy.svg?maxAge=3600&style=flat-square)](https://coveralls.io/github/pragmarb/pragma-policy)
3
+ [![Build Status](https://travis-ci.org/pragmarb/pragma-policy.svg?branch=master)](https://travis-ci.org/pragmarb/pragma-policy)
4
+ [![Coverage Status](https://coveralls.io/repos/github/pragmarb/pragma-policy/badge.svg?branch=master)](https://coveralls.io/github/pragmarb/pragma-policy?branch=master)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/e51e8d7489eb72ab97ba/maintainability)](https://codeclimate.com/github/pragmarb/pragma-policy/maintainability)
7
6
 
8
7
  Policies provide fine-grained access control for your API resources.
9
8
 
10
- They are built on top of the [Pundit](https://github.com/elabs/pundit) gem.
11
-
12
9
  ## Installation
13
10
 
14
11
  Add this line to your application's Gemfile:
@@ -78,7 +75,7 @@ end
78
75
 
79
76
  You are ready to use your policy!
80
77
 
81
- ### Retrieving Records
78
+ ### Retrieving records
82
79
 
83
80
  To retrieve all the records accessible by a user, use the `.accessible_by` class method:
84
81
 
@@ -86,7 +83,7 @@ To retrieve all the records accessible by a user, use the `.accessible_by` class
86
83
  posts = API::V1::Article::Policy::Scope.new(user, Article.all).resolve
87
84
  ```
88
85
 
89
- ### Authorizing Operations
86
+ ### Authorizing operations
90
87
 
91
88
  To authorize an operation, first instantiate the policy, then use the predicate methods:
92
89
 
@@ -103,6 +100,88 @@ policy = API::V1::Article::Policy.new(user, post)
103
100
  policy.update! # raises if the user cannot update the post
104
101
  ```
105
102
 
103
+ ### Reusing Pundit policies
104
+
105
+ If you already use [Pundit](https://github.com/varvet/pundit), there's no need to copy-paste
106
+ policies for your API. You can use `Pragma::Policy::Pundit` to delegate to your existing policies
107
+ and scopes:
108
+
109
+ ```ruby
110
+ module API
111
+ module V1
112
+ module Article
113
+ class Policy < Pragma::Pundit::Policy
114
+ # This is optional: the inferred default would be ArticlePolicy.
115
+ self.pundit_klass = CustomArticlePolicy
116
+ end
117
+ end
118
+ end
119
+ end
120
+ ```
121
+
122
+ Note that you can still override specific methods if you want, and we'll keep delegating the rest
123
+ to Pundit:
124
+
125
+ ```ruby
126
+ module API
127
+ module V1
128
+ module Article
129
+ class Policy < Pragma::Pundit::Policy
130
+ def create?
131
+ # Your custom create policy here
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ ```
138
+
139
+ ### Passing additional context
140
+
141
+ If you want to pass additional context to the policy, just pass it instead of the user object.
142
+ Pragma::Policy never uses your context in any way, so you can pass whatever you want:
143
+
144
+ ```ruby
145
+ policy = API::V1::Article::Policy.new(OpenStruct.new(ip: request.remote_ip, user: user), post)
146
+ policy.update!
147
+ ```
148
+
149
+ In your policy, you can use `#context` as an alias for `#user` for convenience:
150
+
151
+ ```ruby
152
+ module API
153
+ module V1
154
+ module Article
155
+ class Policy < Pragma::Pundit::Policy
156
+ def update?
157
+ record.author_id == context.user.id || context.ip == '127.0.0.1'
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
163
+ ```
164
+
165
+ If you are using [pragma-rails](https://github.com/pragmarb/pragma-rails), you may change the
166
+ context passed to the policy by defining a `#policy_context` method on your controller. This way you
167
+ are not forced to override `#current_user` or `#pragma_user`:
168
+
169
+ ```ruby
170
+ module API
171
+ module V1
172
+ class PostsController < ApplicationController
173
+ # ...
174
+
175
+ private
176
+
177
+ def policy_context
178
+ OpenStruct.new(ip: request.remote_ip, user: current_user)
179
+ end
180
+ end
181
+ end
182
+ end
183
+ ```
184
+
106
185
  ## Contributing
107
186
 
108
187
  Bug reports and pull requests are welcome on GitHub at https://github.com/pragmarb/pragma-policy.
@@ -1,15 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pundit'
4
-
5
3
  require 'pragma/policy/version'
4
+ require 'pragma/policy/scope'
6
5
  require 'pragma/policy/base'
6
+ require 'pragma/policy/pundit'
7
7
  require 'pragma/policy/errors'
8
8
 
9
9
  module Pragma
10
10
  # Fine-grained access control for your API resources.
11
- #
12
- # @author Alessandro Desantis
13
11
  module Policy
14
12
  end
15
13
  end
@@ -7,40 +7,9 @@ module Pragma
7
7
  # A policy provides predicate methods for determining whether a user can perform a specific
8
8
  # action on a record.
9
9
  #
10
- # @author Alessandro Desantis
11
- #
12
10
  # @abstract Subclass and implement action methods to create a policy.
13
11
  class Base
14
- # Authorizes AR scopes and other relations by only returning the records accessible by the
15
- # current user. Used, for instance, in index operations.
16
- #
17
- # @author Alessandro Desantis
18
- class Scope
19
- # @!attribute [r] user
20
- # @return [Object] the user accessing the records
21
- #
22
- # @!attribute [r] scope
23
- # @return [Object] the relation to use as a base
24
- attr_reader :user, :scope
25
-
26
- # Initializes the scope.
27
- #
28
- # @param user [Object] the user accessing the records
29
- # @param scope [Object] the relation to use as a base
30
- def initialize(user, scope)
31
- @user = user
32
- @scope = scope
33
- end
34
-
35
- # Returns the records accessible by the given user.
36
- #
37
- # @return [Object]
38
- #
39
- # @abstract Override to implement retrieving the accessible records
40
- def resolve
41
- fail NotImplementedError
42
- end
43
- end
12
+ Scope = ::Pragma::Policy::Scope
44
13
 
45
14
  # @!attribute [r] user
46
15
  # @return [Object] the user operating on the record
@@ -48,6 +17,7 @@ module Pragma
48
17
  # @!attribute [r] record
49
18
  # @return [Object] the record being operated on
50
19
  attr_reader :user, :record
20
+ alias context user
51
21
 
52
22
  # Initializes the policy.
53
23
  #
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Pragma
4
4
  module Policy
5
- class NotAuthorizedError < Pundit::NotAuthorizedError
5
+ class NotAuthorizedError < StandardError
6
6
  end
7
7
  end
8
8
  end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pragma
4
+ module Policy
5
+ # Provides a simple way for Pragma policies to delegate to Pundit policies/scopes.
6
+ #
7
+ # @example
8
+ # class API::V1::Article::Policy < Pragma::Policy::Pundit
9
+ # # The default would be ArticlePolicy.
10
+ # self.pundit_klass = CustomArticlePolicy
11
+ # end
12
+ class Pundit < Base
13
+ class << self
14
+ attr_writer :pundit_klass
15
+
16
+ def pundit_klass
17
+ @pundit_klass ||= Object.const_get("#{self.class.name.split('::')[-2]}Policy")
18
+ end
19
+
20
+ def inherited(base)
21
+ base.class_eval <<~RUBY, __FILE__, __LINE__ + 1
22
+ class Scope < Pragma::Policy::Scope
23
+ def initialize(user, scope)
24
+ super
25
+ @pundit_scope = pundit_scope_klass.new(user, scope)
26
+ end
27
+
28
+ def resolve
29
+ @pundit_scope.resolve
30
+ end
31
+
32
+ private
33
+
34
+ def pundit_scope_klass
35
+ policy_klass.pundit_klass.const_get('Scope')
36
+ end
37
+ end
38
+ RUBY
39
+ end
40
+ end
41
+
42
+ def initialize(user, record)
43
+ super
44
+ @pundit_policy = self.class.pundit_klass.new(user, record)
45
+ end
46
+
47
+ def respond_to_missing?(method_name, include_private = false)
48
+ super || @pundit_policy.respond_to?("#{method_name[0..-2]}?", include_private)
49
+ end
50
+
51
+ def method_missing(method_name, *args, &block)
52
+ return super unless @pundit_policy.respond_to?(method_name)
53
+ @pundit_policy.send(method_name, *args, &block)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pragma
4
+ module Policy
5
+ # Authorizes AR scopes and other relations by only returning the records accessible by the
6
+ # current user. Used, for instance, in index operations.
7
+ class Scope
8
+ # @!attribute [r] user
9
+ # @return [Object] the user accessing the records
10
+ #
11
+ # @!attribute [r] scope
12
+ # @return [Object] the relation to use as a base
13
+ attr_reader :user, :scope
14
+ alias context user
15
+
16
+ # Initializes the scope.
17
+ #
18
+ # @param user [Object] the user accessing the records
19
+ # @param scope [Object] the relation to use as a base
20
+ def initialize(user, scope)
21
+ @user = user
22
+ @scope = scope
23
+ end
24
+
25
+ # Returns the records accessible by the given user.
26
+ #
27
+ # @return [Object]
28
+ #
29
+ # @abstract Override to implement retrieving the accessible records
30
+ def resolve
31
+ fail NotImplementedError
32
+ end
33
+
34
+ private
35
+
36
+ def policy_klass
37
+ Object.const_get(self.class.name.split('::')[0..-2].join('::'))
38
+ end
39
+ end
40
+ end
41
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Pragma
4
4
  module Policy
5
- VERSION = '2.0.0'
5
+ VERSION = '2.1.0'
6
6
  end
7
7
  end
@@ -21,8 +21,6 @@ Gem::Specification.new do |spec|
21
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
22
  spec.require_paths = ['lib']
23
23
 
24
- spec.add_dependency 'pundit', '~> 1.1'
25
-
26
24
  spec.add_development_dependency 'bundler'
27
25
  spec.add_development_dependency 'rake'
28
26
  spec.add_development_dependency 'rspec'
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pragma-policy
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.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: 2017-09-27 00:00:00.000000000 Z
11
+ date: 2018-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: pundit
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.1'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '1.1'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: bundler
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -119,6 +105,7 @@ files:
119
105
  - ".rspec"
120
106
  - ".rubocop.yml"
121
107
  - ".travis.yml"
108
+ - CHANGELOG.md
122
109
  - Gemfile
123
110
  - LICENSE.txt
124
111
  - README.md
@@ -128,6 +115,8 @@ files:
128
115
  - lib/pragma/policy.rb
129
116
  - lib/pragma/policy/base.rb
130
117
  - lib/pragma/policy/errors.rb
118
+ - lib/pragma/policy/pundit.rb
119
+ - lib/pragma/policy/scope.rb
131
120
  - lib/pragma/policy/version.rb
132
121
  - pragma-policy.gemspec
133
122
  homepage: https://github.com/pragmarb/pragma-policy
@@ -150,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
139
  version: '0'
151
140
  requirements: []
152
141
  rubyforge_project:
153
- rubygems_version: 2.6.13
142
+ rubygems_version: 2.7.7
154
143
  signing_key:
155
144
  specification_version: 4
156
145
  summary: Fine-grained access control for your API resources.