pundit_can 0.1.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +102 -0
- data/Rakefile +3 -0
- data/lib/pundit_can/load_and_authorize.rb +145 -0
- data/lib/pundit_can/railtie.rb +4 -0
- data/lib/pundit_can/version.rb +3 -0
- data/lib/pundit_can.rb +12 -0
- data/lib/tasks/pundit_can_tasks.rake +4 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6a70b76f365ad9d949e7db20d9fd1eebc689915d18c835801fb2078d98628b3b
|
4
|
+
data.tar.gz: b30f0f0ce6095d46818f7d47bbe3f95b8e7df58664929d0aa1e1e4a93122ab7e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a96f83508916a9650fe4f14c24f0ff13d0d730cf14558e764070da4ec1eaf215c4ef1e06a91adaf09f0d013fb9e07193243a080b9bc737ea3e48dbcc866ed3c8
|
7
|
+
data.tar.gz: e755108ea59470ed01e17a81a8522657b787032c8a2c7fe50459f1353389f47ba9aa2700f6517ee094788a90771e0777fe630fa3f4d5a375edd7b37af8419758
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2023 candland
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# PunditCan
|
2
|
+
|
3
|
+
[Pundit](https://github.com/varvet/pundit) with [cancan](https://github.com/CanCanCommunity/cancancan)
|
4
|
+
style load_and_authorize functionality.
|
5
|
+
|
6
|
+
## Usage
|
7
|
+
|
8
|
+
Include `PunditCan::LoadAndAuthorize` into `ApplicationController` or in each controller.
|
9
|
+
|
10
|
+
Call `load_resource` in the controller to load and authorize the resource.
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
class UsersController < ApplicationController
|
14
|
+
load_resource
|
15
|
+
end
|
16
|
+
```
|
17
|
+
|
18
|
+
This will load `@user` from `User` using the `UserPolicy` to authorize and scope the loading.
|
19
|
+
|
20
|
+
### Advanced usage
|
21
|
+
|
22
|
+
There is support for loading multiple models. However, there isn't a `:through` option, like cancan,
|
23
|
+
instead loading still goes through Pundit scopes.
|
24
|
+
|
25
|
+
There are options to customize the loaded instance_name, model, and policy classes.
|
26
|
+
|
27
|
+
#### Parent / nested
|
28
|
+
|
29
|
+
This is a example of loading User and Posts.
|
30
|
+
```ruby
|
31
|
+
class PostsController < ApplicationController
|
32
|
+
load_resource model_class: User, parent: true
|
33
|
+
load_resource
|
34
|
+
|
35
|
+
...
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
That will load `@user` from the `UserPolicy` into a `User` class, using `:user_id` to find the user.
|
40
|
+
And it will lost `@post` or `@posts` using the `PostPolicy` with the `:id` param.
|
41
|
+
|
42
|
+
#### Customized loading
|
43
|
+
|
44
|
+
You can customize the loading for cases when the model, controller, and policies don't match up name-wise.
|
45
|
+
```ruby
|
46
|
+
class MisMatchedController < ApplicationController
|
47
|
+
load_resource instance_name: :special_user,
|
48
|
+
model_class: User,
|
49
|
+
policy_class: SpecialUserPolicy,
|
50
|
+
policy_scope_class: SpecialUserPolicy::Scope
|
51
|
+
|
52
|
+
...
|
53
|
+
|
54
|
+
# Pundit method to override the model param key
|
55
|
+
def pundit_params_for(record)
|
56
|
+
params.require(:special_user)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
This will set `@special_user` with the `User` class, using the `SpecialUserPolicy` and
|
62
|
+
`SpecialUserPolicy::Scope` classes to authorize and scope the loading.
|
63
|
+
|
64
|
+
#### Skiping checks
|
65
|
+
|
66
|
+
By default, `verify_authorized` and `verify_policy_scoped` after actions are setup. If
|
67
|
+
you need to skip those for an action, there are `skip_authorized_check` and `skip_scoped_check`
|
68
|
+
methods to skip the verify actions for the given actions.
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
class SkipsController < ApplicationController
|
72
|
+
skip_authorized_check :index, :show
|
73
|
+
skip_scoped_check :index, :show
|
74
|
+
|
75
|
+
...
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
## Installation
|
80
|
+
|
81
|
+
Add this line to your application's Gemfile:
|
82
|
+
```ruby
|
83
|
+
gem "pundit_can"
|
84
|
+
```
|
85
|
+
|
86
|
+
And then execute:
|
87
|
+
```bash
|
88
|
+
$ bundle
|
89
|
+
```
|
90
|
+
|
91
|
+
Or install it yourself as:
|
92
|
+
```bash
|
93
|
+
$ gem install pundit_can
|
94
|
+
```
|
95
|
+
|
96
|
+
## Contributing
|
97
|
+
|
98
|
+
Contribution directions go here.
|
99
|
+
|
100
|
+
## License
|
101
|
+
|
102
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
require "pundit"
|
2
|
+
|
3
|
+
module PunditCan
|
4
|
+
module LoadAndAuthorize
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
include Pundit::Authorization
|
7
|
+
|
8
|
+
included do
|
9
|
+
after_action :verify_authorized, unless: -> { respond_to?(:devise_controller?) && devise_controller? }
|
10
|
+
after_action :verify_policy_scoped, except: [:new, :create], unless: -> { respond_to?(:devise_controller?) && devise_controller? }
|
11
|
+
end
|
12
|
+
|
13
|
+
class_methods do
|
14
|
+
# skip_authorized_check
|
15
|
+
#
|
16
|
+
# Skip the +verify_authorized+ after action for the provided actions
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
#
|
20
|
+
# skip_authorized_check :new, :edit
|
21
|
+
#
|
22
|
+
# @param [*Symbol] actions
|
23
|
+
#
|
24
|
+
def skip_authorized_check *actions
|
25
|
+
if actions.any?
|
26
|
+
skip_after_action :verify_authorized, only: actions
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# skip_scoped_check
|
31
|
+
#
|
32
|
+
# Skip the +verify_policy_scoped+ after action for the provided actions
|
33
|
+
#
|
34
|
+
# @example
|
35
|
+
#
|
36
|
+
# skip_scoped_check :new, :edit
|
37
|
+
#
|
38
|
+
# @param [*Symbol] actions
|
39
|
+
#
|
40
|
+
def skip_scoped_check *actions
|
41
|
+
if actions.any?
|
42
|
+
skip_after_action :verify_policy_scoped, only: actions
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# load_resource
|
47
|
+
#
|
48
|
+
# @example
|
49
|
+
#
|
50
|
+
# load_resource
|
51
|
+
#
|
52
|
+
# @example
|
53
|
+
#
|
54
|
+
# load_resource instance_name: :user, model_class: User, param_key: :user_id, parent: true
|
55
|
+
#
|
56
|
+
# @param [String] instance_name Optional. Defaults from the +model_class+ if
|
57
|
+
# provided, otherwise from the controller name.
|
58
|
+
#
|
59
|
+
# @param [Constant] model_class Optional. Tries to create model from the controller name when missing.
|
60
|
+
#
|
61
|
+
# @param [String] param_key Optional. The key for the Id in params. Defaults to +:id+, otherwise tries
|
62
|
+
# to guess from the +instance_name+ or +model_class+.
|
63
|
+
#
|
64
|
+
# @param [Boolean] parent Optional. Changes the loading for parent classes. Default +false+
|
65
|
+
#
|
66
|
+
# @param [Constant] policy_class Optional. The policy class to use. Defaults from controller name.
|
67
|
+
#
|
68
|
+
# @param [Constant] policy_scope_class Optional. The policy scope class to use. Defaults from controller name.
|
69
|
+
#
|
70
|
+
def load_resource **options
|
71
|
+
before_action(**options.extract!(:only, :except, :if, :unless)) do
|
72
|
+
load_scoped(**options)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def resource_class_name
|
80
|
+
self.class.name[0..-11].singularize.demodulize
|
81
|
+
end
|
82
|
+
|
83
|
+
def load_scoped **options
|
84
|
+
model_class = options[:model_class] || resource_class_name.demodulize.constantize
|
85
|
+
instance_name = (options[:instance_name] || model_instance_name(options) || resource_class_name.underscore).to_s
|
86
|
+
param_key = get_param_key(options, instance_name, model_class)
|
87
|
+
|
88
|
+
loaded = if options[:parent]
|
89
|
+
load_parent_instance_var(model_class, param_key, options.extract!(:policy_class), options.extract!(:policy_scope_class))
|
90
|
+
else
|
91
|
+
load_instance_var(model_class, param_key, options.extract!(:policy_class), options.extract!(:policy_scope_class))
|
92
|
+
end
|
93
|
+
|
94
|
+
instance_name = instance_name.pluralize unless loaded.is_a?(model_class)
|
95
|
+
instance_variable_set("@#{instance_name}", loaded)
|
96
|
+
end
|
97
|
+
|
98
|
+
def get_param_key options, instance_name, model_class
|
99
|
+
if options[:parent]
|
100
|
+
options.fetch(:param_key, :"#{instance_name || model_class&.name&.underscore}_id")
|
101
|
+
else
|
102
|
+
options.fetch(:param_key, :id)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# if a model_name option is given use that otherwise nil
|
107
|
+
# and is parent
|
108
|
+
def model_instance_name options
|
109
|
+
options[:model_class].name.underscore if options[:model_class].present? && options[:parent]
|
110
|
+
end
|
111
|
+
|
112
|
+
def load_instance_var model_class, param_key, policy_kwopts, policy_scope_kwopts
|
113
|
+
case params[:action]
|
114
|
+
when "index"
|
115
|
+
load_scope(model_class, policy_kwopts, policy_scope_kwopts)
|
116
|
+
when "new"
|
117
|
+
authorize(model_class.new, **policy_kwopts)
|
118
|
+
when "create"
|
119
|
+
authorize(model_class.new(permitted_attributes(model_class)), **policy_kwopts)
|
120
|
+
when "edit", "update", "show", "destroy"
|
121
|
+
load_model(model_class, param_key, policy_kwopts, policy_scope_kwopts)
|
122
|
+
else
|
123
|
+
if params[param_key]
|
124
|
+
load_model(model_class, param_key, policy_kwopts, policy_scope_kwopts)
|
125
|
+
else
|
126
|
+
load_scope(model_class, policy_kwopts, policy_scope_kwopts)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def load_parent_instance_var model_class, param_key, policy_kwopts, policy_scope_kwopts
|
132
|
+
if params[param_key]
|
133
|
+
load_model(model_class, param_key, policy_kwopts, policy_scope_kwopts, :show?)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def load_model model_class, param_key, policy_kwopts, policy_scope_kwopts, query = nil
|
138
|
+
authorize(policy_scope(model_class, **policy_scope_kwopts).find(params[param_key]), query, **policy_kwopts)
|
139
|
+
end
|
140
|
+
|
141
|
+
def load_scope model_class, policy_kwopts, policy_scope_kwopts
|
142
|
+
authorize(policy_scope(model_class, **policy_scope_kwopts), **policy_kwopts)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
data/lib/pundit_can.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "pundit_can/version"
|
2
|
+
require "pundit_can/railtie"
|
3
|
+
require "pundit"
|
4
|
+
require "active_support/concern"
|
5
|
+
require "active_support/core_ext/string/inflections"
|
6
|
+
require "active_support/core_ext/object/blank"
|
7
|
+
require "active_support/core_ext/module/introspection"
|
8
|
+
require "active_support/dependencies/autoload"
|
9
|
+
require "pundit_can/load_and_authorize"
|
10
|
+
|
11
|
+
module PunditCan
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pundit_can
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- candland
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-05-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 7.0.4.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 7.0.4.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pundit
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rails-controller-testing
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Add cancan like load and authorize to controllers.
|
56
|
+
email:
|
57
|
+
- candland@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- MIT-LICENSE
|
63
|
+
- README.md
|
64
|
+
- Rakefile
|
65
|
+
- lib/pundit_can.rb
|
66
|
+
- lib/pundit_can/load_and_authorize.rb
|
67
|
+
- lib/pundit_can/railtie.rb
|
68
|
+
- lib/pundit_can/version.rb
|
69
|
+
- lib/tasks/pundit_can_tasks.rake
|
70
|
+
homepage: https://candland.net/pundit_can
|
71
|
+
licenses:
|
72
|
+
- MIT
|
73
|
+
metadata:
|
74
|
+
homepage_uri: https://candland.net/pundit_can
|
75
|
+
source_code_uri: https://github.com/candland/pundit_can
|
76
|
+
changelog_uri: https://github.com/candland/pundit_can/CHANGES.md
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubygems_version: 3.3.7
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: Add cancan like load and authorize to controllers.
|
96
|
+
test_files: []
|