pundit_can 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,3 @@
1
+ require "bundler/setup"
2
+
3
+ require "bundler/gem_tasks"
@@ -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
@@ -0,0 +1,4 @@
1
+ module PunditCan
2
+ class Railtie < ::Rails::Railtie
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module PunditCan
2
+ VERSION = "0.1.0"
3
+ 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
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :pundit_can do
3
+ # # Task goes here
4
+ # 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: []