1
0
Fork 0
mirror of https://github.com/varvet/pundit.git synced 2022-11-09 12:30:11 -05:00

Add permitted attributes helper, closes #141

See discussion in #141. This provides a convenient helper which aids in permitting attributes in the controller.
This commit is contained in:
Jonas Nicklas 2015-03-27 10:14:09 +01:00
parent 3bd1d74c7f
commit 68372c9c17
5 changed files with 53 additions and 8 deletions

View file

@ -481,10 +481,9 @@ end
In Rails 4 (or Rails 3.2 with the
[strong_parameters](https://github.com/rails/strong_parameters) gem),
mass-assignment protection is handled in the controller.
Pundit helps you permit different users to set different attributes. Don't
forget to provide your policy an instance of object or a class so correct
permissions could be loaded.
mass-assignment protection is handled in the controller. With Pundit you can
control which attributes a user has access to update via your policies. You can
set up a `permitted_attributes` method in your policy like this:
```ruby
# app/policies/post_policy.rb
@ -497,12 +496,16 @@ class PostPolicy < ApplicationPolicy
end
end
end
```
You can now retrieve these attributes from the policy:
```ruby
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
def update
@post = Post.find(params[:id])
if @post.update(post_params)
if @post.update_attributes(post_params)
redirect_to @post
else
render :edit
@ -512,7 +515,23 @@ class PostsController < ApplicationController
private
def post_params
params.require(:post).permit(*policy(@post || Post).permitted_attributes)
params.require(:post).permit(policy(@post).permitted_attributes)
end
end
```
However, this is a bit cumbersome, so Pundit provides a convenient helper method:
```ruby
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
def update
@post = Post.find(params[:id])
if @post.update_attributes(permitted_attributes(@post))
redirect_to @post
else
render :edit
end
end
end
```

View file

@ -77,6 +77,7 @@ module Pundit
hide_action :authorize
hide_action :verify_authorized
hide_action :verify_policy_scoped
hide_action :permitted_attributes
hide_action :pundit_user
end
end
@ -115,6 +116,11 @@ module Pundit
policies[record] ||= Pundit.policy!(pundit_user, record)
end
def permitted_attributes(record)
name = record.class.to_s.demodulize.underscore
params.require(name).permit(policy(record).permitted_attributes)
end
def policies
@_pundit_policies ||= {}
end

View file

@ -20,6 +20,7 @@ Gem::Specification.new do |gem|
gem.add_dependency "activesupport", ">= 3.0.0"
gem.add_development_dependency "activemodel", ">= 3.0.0"
gem.add_development_dependency "actionpack", ">= 3.0.0"
gem.add_development_dependency "bundler", "~> 1.3"
gem.add_development_dependency "rspec", ">=2.0.0"
gem.add_development_dependency "pry"

View file

@ -271,7 +271,7 @@ describe Pundit do
end
end
describe ".policy" do
describe "#policy" do
it "returns an instantiated policy" do
policy = controller.policy(post)
expect(policy.user).to eq user
@ -290,7 +290,7 @@ describe Pundit do
end
end
describe ".policy_scope" do
describe "#policy_scope" do
it "returns an instantiated policy scope" do
expect(controller.policy_scope(Post)).to eq :published
end
@ -306,4 +306,13 @@ describe Pundit do
expect(controller.policy_scope(Post)).to eq new_scope
end
end
describe "#permitted_attributes" do
it "checks policy for permitted attributes" do
params = ActionController::Parameters.new({ action: 'update', post: { title: 'Hello', votes: 5, admin: true } })
expect(Controller.new(user, params).permitted_attributes(post)).to eq({ 'title' => 'Hello', 'votes' => 5 })
expect(Controller.new(double, params).permitted_attributes(post)).to eq({ 'votes' => 5 })
end
end
end

View file

@ -1,10 +1,13 @@
require "pundit"
require "pundit/rspec"
require "rack"
require "rack/test"
require "pry"
require "active_support"
require "active_support/core_ext"
require "active_model/naming"
require "action_controller/metal/strong_parameters"
I18n.enforce_available_locales = false
@ -32,6 +35,13 @@ class PostPolicy < Struct.new(:user, :post)
def show?
true
end
def permitted_attributes
if post.user == user
[:title, :votes]
else
[:votes]
end
end
end
class PostPolicy::Scope < Struct.new(:user, :scope)
def resolve