active_model_policy 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +94 -0
- data/Rakefile +12 -0
- data/active_model_policy.gemspec +19 -0
- data/lib/action_controller/policy_context.rb +15 -0
- data/lib/active_model/policy.rb +51 -0
- data/lib/active_model/policy_context.rb +44 -0
- data/lib/active_model/policy_support.rb +26 -0
- data/lib/active_model/version.rb +5 -0
- data/lib/active_model_policy.rb +36 -0
- data/lib/generators/policy/policy_generator.rb +22 -0
- data/lib/generators/policy/templates/policy.rb +7 -0
- data/test/controller_test.rb +16 -0
- data/test/policy_context_test.rb +93 -0
- data/test/policy_support_test.rb +30 -0
- data/test/policy_test.rb +100 -0
- data/test/test_helper.rb +8 -0
- data/test/test_objects.rb +52 -0
- metadata +87 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Marty Zalega
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
# ActiveModel::Policy
|
2
|
+
|
3
|
+
The purpose of *ActiveModel::Policy* is to encapsulate the logic of checking whether an action can be performed on the given object by an actor. By abtracting the this concern into objects permission can be broken into more meaningful and managable parts.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'active_model_policy'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install active_model_policy
|
18
|
+
|
19
|
+
## Creating a Policy
|
20
|
+
|
21
|
+
To create a policy object simply use the Rails generator:
|
22
|
+
|
23
|
+
$ rails generate policy *my_model_name*
|
24
|
+
|
25
|
+
The file will be created in `app/policies/*my_model_name.rb*`.
|
26
|
+
|
27
|
+
To manually create a policy object simply create any standard object subclassing `ActiveModel::Policy`. You should end up with something like this:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
class MyModelNamePolicy < ActiveModel::Policy
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
A policy is nothing more than a series of methods which return true or false based on the state of the model, and optionally scoped. To declare a check, or in policy terms "forming a question", you simply do:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
class PostPolicy < ActiveModel::Policy
|
38
|
+
can :read do |context|
|
39
|
+
model.active?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
```
|
43
|
+
|
44
|
+
The `can` helper underneath simply defines the method `can_read?`. The method returns a truthy or falsy as to whether the action can be performed or not. The idea is that you are asking a question whether the action **can** be performed as the given **context**. The context is not mandatory but it is generally good to use one, even if it is `nil`.
|
45
|
+
|
46
|
+
`can` accepts multiple names, so the same check can be used for multiple actions.
|
47
|
+
|
48
|
+
## Using the Policy
|
49
|
+
|
50
|
+
To use a policy you instantiate it as any Ruby object and pass it the model for which it is to perform checks on. ie. `PostPolicy.new post`.
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
policy = PostPolicy.new post
|
54
|
+
policy.can? :read
|
55
|
+
```
|
56
|
+
|
57
|
+
As a helper to ActiveRecord models, you can simply call `to_policy` which will look for the correct policy based on name and pass itself to the policy.
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
policy = post.to_policy
|
61
|
+
policy.can? :read
|
62
|
+
```
|
63
|
+
|
64
|
+
You can add this behaviour to your own objects by adding `include ActiveModel::PolicySupport` to your class.
|
65
|
+
|
66
|
+
## Policy context
|
67
|
+
|
68
|
+
A context can be anything or nothing, and are very useful to add perspective to your policy. A policy defines rules, or permissions, on what actions can be performed but this might need more context such as who or what. A context is simply passing an argument to the question which responds based on the context. In short, it adds more dimention to checking the permission.
|
69
|
+
|
70
|
+
To make working with context easier, an object can be marked as a context by including the model. ie. `include ActiveModel::PolicyContext`. Then questions can be asked on the context directly:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
user.can? :read, post
|
74
|
+
```
|
75
|
+
|
76
|
+
Controllers and views have the context set by default to `current_user`, so you can use `can?` instead.
|
77
|
+
|
78
|
+
## Customising context
|
79
|
+
|
80
|
+
The context is given to each question asked on the policy to determine whether to grant permission. By default, this is set to `current_user` on the controller but can be changed:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
class ApplicationController < ActionController::Base
|
84
|
+
policy_context :current_user
|
85
|
+
end
|
86
|
+
```
|
87
|
+
|
88
|
+
## Contributing
|
89
|
+
|
90
|
+
1. Fork it
|
91
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
92
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
93
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
94
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/active_model/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Marty Zalega"]
|
6
|
+
gem.email = ["marty@zalega.me"]
|
7
|
+
gem.description = %q{Policy implementation for rails}
|
8
|
+
gem.summary = %q{Policy implementation for rails}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "active_model_policy"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = ActiveModel::Policy::VERSION
|
17
|
+
|
18
|
+
gem.add_development_dependency "rails", ">= 3.0"
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ActionController
|
2
|
+
module PolicyContext
|
3
|
+
def self.included base
|
4
|
+
base.class_eval do
|
5
|
+
include ActiveModel::PolicyContext
|
6
|
+
policy_context :current_user
|
7
|
+
end
|
8
|
+
|
9
|
+
methods = ActiveModel::PolicyContext.instance_methods
|
10
|
+
|
11
|
+
base.hide_action *methods
|
12
|
+
base.helper_method :can?, :cannot?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
class Policy
|
3
|
+
attr_reader :model
|
4
|
+
|
5
|
+
def initialize model
|
6
|
+
@model = model
|
7
|
+
end
|
8
|
+
|
9
|
+
alias_method :to_model, :model
|
10
|
+
|
11
|
+
def to_policy
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def can? action, *args
|
16
|
+
method = "can_#{action}?"
|
17
|
+
respond_to?(method) && !!safe_send(method, args)
|
18
|
+
end
|
19
|
+
|
20
|
+
def can! action, *args
|
21
|
+
can?(action, *args) || raise(ActiveModel::ActionNotAllowed, action)
|
22
|
+
end
|
23
|
+
|
24
|
+
def cannot? *args
|
25
|
+
!can? *args
|
26
|
+
end
|
27
|
+
|
28
|
+
def cannot! action, *args
|
29
|
+
cannot?(action, *args) || raise(ActiveModel::ActionUnexpected, action)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.can *actions, &block
|
33
|
+
raise ArgumentError if actions.empty?
|
34
|
+
actions.flatten.each do |action|
|
35
|
+
define_method "can_#{action}?", &block
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def safe_send method_name, args
|
42
|
+
method = public_method method_name
|
43
|
+
|
44
|
+
if method.arity < args.length && method.arity != -1
|
45
|
+
args = args.take method.arity
|
46
|
+
end
|
47
|
+
|
48
|
+
method.call *args
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "active_support/core_ext/class"
|
2
|
+
|
3
|
+
module ActiveModel
|
4
|
+
module PolicyContext
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
class_attribute :_policy_context
|
9
|
+
end
|
10
|
+
|
11
|
+
def policy_context
|
12
|
+
if _policy_context && respond_to?(_policy_context)
|
13
|
+
send _policy_context
|
14
|
+
else
|
15
|
+
self
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def can? action, object
|
20
|
+
return false if object.nil?
|
21
|
+
|
22
|
+
policy = object.respond_to?(:to_policy) && object.to_policy
|
23
|
+
!policy || policy.can?(action, policy_context)
|
24
|
+
end
|
25
|
+
|
26
|
+
def can! action, object
|
27
|
+
can?(action, object) || raise(ActiveModel::ActionNotAllowed, action)
|
28
|
+
end
|
29
|
+
|
30
|
+
def cannot? *args
|
31
|
+
!can?(*args)
|
32
|
+
end
|
33
|
+
|
34
|
+
def cannot! action, object
|
35
|
+
cannot?(action, object) || raise(ActiveModel::ActionUnexpected, action)
|
36
|
+
end
|
37
|
+
|
38
|
+
module ClassMethods
|
39
|
+
def policy_context context
|
40
|
+
self._policy_context = context
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "active_support"
|
2
|
+
require "active_support/core_ext/string/inflections"
|
3
|
+
|
4
|
+
module ActiveModel::PolicySupport
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def to_policy
|
8
|
+
@policy ||= self.class.active_model_policy.new self
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
if ''.respond_to?(:safe_constantize)
|
13
|
+
def active_model_policy
|
14
|
+
@active_model_policy ||= "#{self.name}Policy".safe_constantize
|
15
|
+
end
|
16
|
+
else
|
17
|
+
def active_model_policy
|
18
|
+
return @active_model_policy if defined? @active_model_policy
|
19
|
+
|
20
|
+
@active_model_policy = "#{self.name}Policy".constantize
|
21
|
+
rescue NameError
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "active_support"
|
2
|
+
require "active_support/core_ext/string/inflections"
|
3
|
+
|
4
|
+
require "active_model"
|
5
|
+
require "active_model/policy"
|
6
|
+
require "active_model/policy_context"
|
7
|
+
require "active_model/policy_support"
|
8
|
+
require "active_model/version"
|
9
|
+
|
10
|
+
require "action_controller/policy_context"
|
11
|
+
|
12
|
+
module ActiveModel
|
13
|
+
class ActionNotAllowed < StandardError; end
|
14
|
+
class ActionUnexpected < StandardError; end
|
15
|
+
|
16
|
+
if defined?(::Rails)
|
17
|
+
class Railtie < Rails::Railtie
|
18
|
+
generators do |app|
|
19
|
+
app ||= Rails.application # Rails 3.0.x does not yield `app`
|
20
|
+
|
21
|
+
::Rails::Generators.configure!(app.config.generators)
|
22
|
+
::Rails::Generators.hidden_namespaces.uniq!
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
ActiveSupport.on_load(:active_record) do
|
29
|
+
include ActiveModel::PolicySupport
|
30
|
+
end
|
31
|
+
|
32
|
+
ActiveSupport.on_load(:action_controller) do
|
33
|
+
include ActionController::PolicyContext
|
34
|
+
end
|
35
|
+
|
36
|
+
ActiveSupport.run_load_hooks(:active_model_policy, ActiveModel::Policy)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Rails
|
2
|
+
module Generators
|
3
|
+
class PolicyGenerator < NamedBase
|
4
|
+
source_root File.expand_path("../templates", __FILE__)
|
5
|
+
check_class_collision :suffix => "Policy"
|
6
|
+
|
7
|
+
def create_serializer_file
|
8
|
+
template 'policy.rb', File.join('app/policies', class_path, "#{file_name}_policy.rb")
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def parent_class_name
|
14
|
+
if defined?(::ApplicationPolicy)
|
15
|
+
"ApplicationPolicy"
|
16
|
+
else
|
17
|
+
"ActiveModel::Policy"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ControllerTest < ActiveModel::TestCase
|
4
|
+
test "#policy_context defaults to :current_user" do
|
5
|
+
assert_equal :current_user, TestContextController._policy_context
|
6
|
+
end
|
7
|
+
|
8
|
+
test "context methods are hidden from controller actions" do
|
9
|
+
actions = TestContextController.actions.sort
|
10
|
+
assert_equal [:can!, :can?, :cannot!, :cannot?, :policy_context], actions
|
11
|
+
end
|
12
|
+
|
13
|
+
test "helper methods are added for view" do
|
14
|
+
assert_equal [:can?, :cannot?], TestContextController.methods
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class PolicyContextTest < ActiveModel::TestCase
|
4
|
+
test ".policy_context sets the context" do
|
5
|
+
refute_equal :test, TestContext._policy_context
|
6
|
+
TestContext.policy_context :test
|
7
|
+
assert_equal :test, TestContext._policy_context
|
8
|
+
end
|
9
|
+
|
10
|
+
test "#policy_context calls the context" do
|
11
|
+
TestContext.policy_context :current_user
|
12
|
+
context = TestContext.new
|
13
|
+
assert_equal :user, context.policy_context
|
14
|
+
end
|
15
|
+
|
16
|
+
test "#policy_context returns itself when context is nil" do
|
17
|
+
TestContext.policy_context nil
|
18
|
+
context = TestContext.new
|
19
|
+
assert_equal context, context.policy_context
|
20
|
+
end
|
21
|
+
|
22
|
+
test "#policy_context returns itself when context is not defined" do
|
23
|
+
TestContext.policy_context :foobar
|
24
|
+
context = TestContext.new
|
25
|
+
refute_respond_to context, :foobar
|
26
|
+
assert_equal context, context.policy_context
|
27
|
+
end
|
28
|
+
|
29
|
+
test "#can? returns true when object doesn't have a policy" do
|
30
|
+
object = Object.new
|
31
|
+
context = TestContext.new
|
32
|
+
assert context.can?(:test, object)
|
33
|
+
end
|
34
|
+
|
35
|
+
test "#can? returns true when object has policy and permits action" do
|
36
|
+
model = TestModel.new
|
37
|
+
policy = model.to_policy
|
38
|
+
context = TestContext.new
|
39
|
+
assert context.can?(:recieve_context, model)
|
40
|
+
assert_equal context, policy.context
|
41
|
+
end
|
42
|
+
|
43
|
+
test "#can? returns false when object has policy but doesn't permit action" do
|
44
|
+
model = TestModel.new
|
45
|
+
context = TestContext.new
|
46
|
+
refute context.can?(:bar, model)
|
47
|
+
end
|
48
|
+
|
49
|
+
test "#can? returns false when object is nil" do
|
50
|
+
context = TestContext.new
|
51
|
+
refute context.can?(:foo, nil)
|
52
|
+
end
|
53
|
+
|
54
|
+
test "#can! raises error when object doesn't permit action" do
|
55
|
+
model = TestModel.new
|
56
|
+
context = TestContext.new
|
57
|
+
assert_raises ActiveModel::ActionNotAllowed do
|
58
|
+
context.can!(:bar, model)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
test "#can! returns true when action permitted" do
|
63
|
+
model = TestModel.new
|
64
|
+
context = TestContext.new
|
65
|
+
assert context.can!(:foo, model)
|
66
|
+
end
|
67
|
+
|
68
|
+
test "#cannot? returns true when action is not allowed" do
|
69
|
+
model = TestModel.new
|
70
|
+
context = TestContext.new
|
71
|
+
assert context.cannot?(:bar, model)
|
72
|
+
end
|
73
|
+
|
74
|
+
test "#cannot? returns false when action is allowed" do
|
75
|
+
model = TestModel.new
|
76
|
+
context = TestContext.new
|
77
|
+
refute context.cannot?(:foo, model)
|
78
|
+
end
|
79
|
+
|
80
|
+
test "#cannot! raises error when action is allowed" do
|
81
|
+
model = TestModel.new
|
82
|
+
context = TestContext.new
|
83
|
+
assert_raises ActiveModel::ActionUnexpected do
|
84
|
+
context.cannot!(:foo, model)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
test "#cannot! returns true when action is not allowed" do
|
89
|
+
model = TestModel.new
|
90
|
+
context = TestContext.new
|
91
|
+
assert context.cannot!(:bar, model)
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class PolicySupportTest < ActiveModel::TestCase
|
4
|
+
class Supporter
|
5
|
+
include ActiveModel::PolicySupport
|
6
|
+
end
|
7
|
+
|
8
|
+
class SupporterPolicy < ActiveModel::Policy
|
9
|
+
end
|
10
|
+
|
11
|
+
class Unsupported
|
12
|
+
include ActiveModel::PolicySupport
|
13
|
+
end
|
14
|
+
|
15
|
+
test ".active_model_policy returns the policy class" do
|
16
|
+
assert_respond_to Supporter, :active_model_policy
|
17
|
+
assert_equal SupporterPolicy, Supporter.active_model_policy
|
18
|
+
end
|
19
|
+
|
20
|
+
test ".active_model_policy returns nil when no policy class can be found" do
|
21
|
+
assert_respond_to Unsupported, :active_model_policy
|
22
|
+
assert_nil Unsupported.active_model_policy
|
23
|
+
end
|
24
|
+
|
25
|
+
test "#to_policy returns the policy instance setting itself as the model" do
|
26
|
+
model = Supporter.new
|
27
|
+
policy = model.to_policy
|
28
|
+
assert_equal model, policy.model
|
29
|
+
end
|
30
|
+
end
|
data/test/policy_test.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class PolicyTest < ActiveModel::TestCase
|
4
|
+
test "#initialize sets the model" do
|
5
|
+
model = Object.new
|
6
|
+
policy = ActiveModel::Policy.new model
|
7
|
+
|
8
|
+
assert_equal model, policy.model
|
9
|
+
end
|
10
|
+
|
11
|
+
test "#to_policy returns itself" do
|
12
|
+
policy = ActiveModel::Policy.new nil
|
13
|
+
assert_equal policy, policy.to_policy
|
14
|
+
end
|
15
|
+
|
16
|
+
test "#can? returns false when method not defined" do
|
17
|
+
policy = ActiveModel::Policy.new nil
|
18
|
+
refute policy.can?(:foobar)
|
19
|
+
end
|
20
|
+
|
21
|
+
test "#can? returns false when method returns false" do
|
22
|
+
policy = TestModelPolicy.new nil
|
23
|
+
refute policy.can_bar?
|
24
|
+
refute policy.can?(:bar)
|
25
|
+
end
|
26
|
+
|
27
|
+
test "#can? returns true when method returns true" do
|
28
|
+
policy = TestModelPolicy.new nil
|
29
|
+
assert policy.can_foo?
|
30
|
+
assert policy.can?(:foo)
|
31
|
+
end
|
32
|
+
|
33
|
+
test "#can? passes arguments to block" do
|
34
|
+
policy = TestModelPolicy.new nil
|
35
|
+
assert_nil policy.args
|
36
|
+
assert policy.can?(:receive_args, :boo, :hoo)
|
37
|
+
assert_equal [:boo, :hoo], policy.args
|
38
|
+
end
|
39
|
+
|
40
|
+
test "#can? culls excessive arguments" do
|
41
|
+
policy = TestModelPolicy.new nil
|
42
|
+
assert_nil policy.args
|
43
|
+
assert policy.can?(:receive_args, :boo, :hoo, :abc)
|
44
|
+
assert_equal [:boo, :hoo], policy.args
|
45
|
+
end
|
46
|
+
|
47
|
+
test "#cannot? returns true when method returns false" do
|
48
|
+
policy = TestModelPolicy.new nil
|
49
|
+
refute policy.can_bar?
|
50
|
+
assert policy.cannot?(:bar)
|
51
|
+
end
|
52
|
+
|
53
|
+
test "#cannot? returns false when method returns true" do
|
54
|
+
policy = TestModelPolicy.new nil
|
55
|
+
assert policy.can_foo?
|
56
|
+
refute policy.cannot?(:foo)
|
57
|
+
end
|
58
|
+
|
59
|
+
test "#can! returns true when method returns true" do
|
60
|
+
policy = TestModelPolicy.new nil
|
61
|
+
assert policy.can_foo?
|
62
|
+
assert policy.can!(:foo)
|
63
|
+
end
|
64
|
+
|
65
|
+
test "#can! raises error when method returns false" do
|
66
|
+
policy = TestModelPolicy.new nil
|
67
|
+
refute policy.can_bar?
|
68
|
+
assert_raises ActiveModel::ActionNotAllowed do
|
69
|
+
policy.can!(:bar)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
test "#cannot! returns true when method returns false" do
|
74
|
+
policy = TestModelPolicy.new nil
|
75
|
+
refute policy.can_bar?
|
76
|
+
assert policy.cannot!(:bar)
|
77
|
+
end
|
78
|
+
|
79
|
+
test "#cannot! raises error when method returns true" do
|
80
|
+
policy = TestModelPolicy.new nil
|
81
|
+
assert policy.can_foo?
|
82
|
+
assert_raises ActiveModel::ActionUnexpected do
|
83
|
+
policy.cannot!(:foo)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
test ".can defines a method" do
|
88
|
+
refute TestModelPolicy.method_defined?(:can_foobar?)
|
89
|
+
TestModelPolicy.can(:foobar){ true }
|
90
|
+
assert TestModelPolicy.method_defined?(:can_foobar?)
|
91
|
+
end
|
92
|
+
|
93
|
+
test ".can defines multiple methods when given multiple arguments" do
|
94
|
+
refute TestModelPolicy.method_defined?(:can_boo?)
|
95
|
+
refute TestModelPolicy.method_defined?(:can_hoo?)
|
96
|
+
TestModelPolicy.can(:boo, :hoo){ true }
|
97
|
+
assert TestModelPolicy.method_defined?(:can_boo?)
|
98
|
+
assert TestModelPolicy.method_defined?(:can_hoo?)
|
99
|
+
end
|
100
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
class TestContext
|
2
|
+
include ActiveModel::PolicyContext
|
3
|
+
|
4
|
+
def current_user
|
5
|
+
:user
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class TestModel
|
10
|
+
include ActiveModel::PolicySupport
|
11
|
+
end
|
12
|
+
|
13
|
+
class TestModelPolicy < ActiveModel::Policy
|
14
|
+
attr_reader :context, :args
|
15
|
+
|
16
|
+
def can_recieve_context? context
|
17
|
+
@context = context
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
def can_foo?
|
22
|
+
true
|
23
|
+
end
|
24
|
+
|
25
|
+
def can_bar?
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
def can_receive_args? arg1, arg2
|
30
|
+
@args = [arg1, arg2]
|
31
|
+
true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class TestContextController
|
36
|
+
class << self
|
37
|
+
attr_reader :actions, :methods
|
38
|
+
def hide_action *actions
|
39
|
+
@actions = actions
|
40
|
+
end
|
41
|
+
|
42
|
+
def helper_method *methods
|
43
|
+
@methods = methods
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
include ActionController::PolicyContext
|
48
|
+
|
49
|
+
def current_user
|
50
|
+
:user
|
51
|
+
end
|
52
|
+
end
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active_model_policy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Marty Zalega
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
version_requirements: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
none: false
|
21
|
+
name: rails
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
requirement: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - ! '>='
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '3.0'
|
29
|
+
none: false
|
30
|
+
description: Policy implementation for rails
|
31
|
+
email:
|
32
|
+
- marty@zalega.me
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- .gitignore
|
38
|
+
- Gemfile
|
39
|
+
- LICENSE
|
40
|
+
- README.md
|
41
|
+
- Rakefile
|
42
|
+
- active_model_policy.gemspec
|
43
|
+
- lib/action_controller/policy_context.rb
|
44
|
+
- lib/active_model/policy.rb
|
45
|
+
- lib/active_model/policy_context.rb
|
46
|
+
- lib/active_model/policy_support.rb
|
47
|
+
- lib/active_model/version.rb
|
48
|
+
- lib/active_model_policy.rb
|
49
|
+
- lib/generators/policy/policy_generator.rb
|
50
|
+
- lib/generators/policy/templates/policy.rb
|
51
|
+
- test/controller_test.rb
|
52
|
+
- test/policy_context_test.rb
|
53
|
+
- test/policy_support_test.rb
|
54
|
+
- test/policy_test.rb
|
55
|
+
- test/test_helper.rb
|
56
|
+
- test/test_objects.rb
|
57
|
+
homepage: ''
|
58
|
+
licenses: []
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
none: false
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
none: false
|
75
|
+
requirements: []
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 1.8.23
|
78
|
+
signing_key:
|
79
|
+
specification_version: 3
|
80
|
+
summary: Policy implementation for rails
|
81
|
+
test_files:
|
82
|
+
- test/controller_test.rb
|
83
|
+
- test/policy_context_test.rb
|
84
|
+
- test/policy_support_test.rb
|
85
|
+
- test/policy_test.rb
|
86
|
+
- test/test_helper.rb
|
87
|
+
- test/test_objects.rb
|