allowy 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.
- data/.gitignore +5 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Guardfile +13 -0
- data/README.md +202 -0
- data/Rakefile +1 -0
- data/allowy.gemspec +27 -0
- data/lib/allowy.rb +20 -0
- data/lib/allowy/access_control.rb +29 -0
- data/lib/allowy/controller_extensions.rb +37 -0
- data/lib/allowy/matchers.rb +44 -0
- data/lib/allowy/registry.rb +33 -0
- data/lib/allowy/rspec.rb +20 -0
- data/lib/allowy/version.rb +3 -0
- data/spec/access_control_spec.rb +49 -0
- data/spec/registry_spec.rb +36 -0
- data/spec/spec_helper.rb +24 -0
- metadata +122 -0
data/.rspec
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'rspec', :version => 2 do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
|
9
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
10
|
+
|
11
|
+
callback([:start_begin, :reload_begin, :run_all_begin, :run_on_change_begin]) { system "clear" }
|
12
|
+
end
|
13
|
+
|
data/README.md
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
# Allowy - the simple authorization for Ruby (and/or Rails)
|
2
|
+
|
3
|
+
Allowy is the authorization library that doesn't enforce tight DSL on you.
|
4
|
+
It is very simple yet powerful.
|
5
|
+
|
6
|
+
If you have any questions please contact me [@dnagir](http://www.ApproachE.com).
|
7
|
+
|
8
|
+
## Why another one?
|
9
|
+
|
10
|
+
I've been using really great [cancan](https://github.com/ryanb/cancan) gem by Ryan Bates for a long time.
|
11
|
+
It does its job amazingly well.
|
12
|
+
|
13
|
+
CanCan doesn't work very well for me when Ability definitions grow above 20 lines or so:
|
14
|
+
|
15
|
+
- it becomes **really** hard to track down why something was (or not) allowed.
|
16
|
+
- DSL enforces you to use ActiveRecord-like scopes or block to fall back. Those grow and it gets hard to maintain.
|
17
|
+
- The Ability class contains all the definitions for everything. Hard to test, hard to maintain.
|
18
|
+
- Implicit permission - CanCan tries to be very smart (and is indeed) using aliases such as `:manage` but it makes even harder to maintain.
|
19
|
+
- Implicit permission - you can use any symbol to check permissions. `:love_people` will do, even if you never defined it.
|
20
|
+
- A little bit tight to ORM. When using with database such as neo4j, some smalish things don't work. So I prefer to be explicit.
|
21
|
+
|
22
|
+
So I decided to put up allowy to solve those issue for me.
|
23
|
+
|
24
|
+
[Allowy](https://github.com/dnagir/allowy) better suites if you want more control over your authorization. It is inspired by CanCan, but was implemented with simplicity and explicitness in mind.
|
25
|
+
|
26
|
+
|
27
|
+
# Install
|
28
|
+
|
29
|
+
Add it to your Rails application's `Gemfile`:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
gem 'alowy'
|
33
|
+
```
|
34
|
+
|
35
|
+
Then `bundle install`.
|
36
|
+
|
37
|
+
Or use `allowy` gem any other way you are not in Rails.
|
38
|
+
|
39
|
+
# Usage
|
40
|
+
|
41
|
+
I will be assuming a CMS-like system in the examples below.
|
42
|
+
The `Page` class may be ActiveRecord, Mongoid or any other model of your choise. Doesn't matter.
|
43
|
+
|
44
|
+
|
45
|
+
## Minimal setup
|
46
|
+
|
47
|
+
You define a set of permissions per class.
|
48
|
+
If you want to safeguard `Page` class then define `PageAccess` class:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
class PageAccess
|
52
|
+
include Allowy::AccessControl
|
53
|
+
|
54
|
+
# This will allow you to ask: can? :view, page
|
55
|
+
# The truthy result of this function will grant access, otherwise not.
|
56
|
+
def view?(page)
|
57
|
+
page and page.published?
|
58
|
+
end
|
59
|
+
|
60
|
+
def edit?(page)
|
61
|
+
page and page.wiki?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Then, in rails, you would use it:
|
66
|
+
can? :view, page
|
67
|
+
cannot? :edit, page
|
68
|
+
authorize! :view, page # raises Allowy::AccessDenied if can?(:view, page) return false
|
69
|
+
can? :love_people, page # Will fail because `love_people` is not defined on the Access Control class
|
70
|
+
```
|
71
|
+
|
72
|
+
## Context
|
73
|
+
|
74
|
+
You can access current user, request data etc using the `context` method.
|
75
|
+
In Rails, the context is set to the current controller, so you have full access to it (not only the current user!).
|
76
|
+
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
class PageAccess
|
80
|
+
include Allowy::AccessControl
|
81
|
+
|
82
|
+
def view?(page)
|
83
|
+
context.user_signed_in? and page.published?
|
84
|
+
end
|
85
|
+
end
|
86
|
+
```
|
87
|
+
|
88
|
+
If you want to change the context in Rails then just override it on a single controller or globally on the `ApplicationController`:
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
class DefaultAccess
|
92
|
+
include Allowy::AccessControl
|
93
|
+
# This will give you methods without the need to go to context object
|
94
|
+
delegate :current_user, :to => :context
|
95
|
+
delegate :current_company, :to => :context
|
96
|
+
end
|
97
|
+
```
|
98
|
+
|
99
|
+
## More comprehensive example
|
100
|
+
|
101
|
+
You probably have multiple classes that you want to protect.
|
102
|
+
I recommend creating your own base class to provide common context and maybe some utility methods:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
class DefaultAccess
|
106
|
+
include Allowy::AccessControl
|
107
|
+
end
|
108
|
+
```
|
109
|
+
|
110
|
+
Then you can create multiple access control classes much easier:
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
class PageAccess < DefaultAccess
|
114
|
+
# can? :view, page
|
115
|
+
def view?(page)
|
116
|
+
page and page.published?
|
117
|
+
end
|
118
|
+
|
119
|
+
# can? :edit, page
|
120
|
+
def edit?(page)
|
121
|
+
view?(page) and page.wiki? # Notice how we can reuse other definitions!
|
122
|
+
end
|
123
|
+
|
124
|
+
# can? :create, WikiPage
|
125
|
+
def create?(page_class)
|
126
|
+
# We can do something with WikiPage here if we need to
|
127
|
+
# but can just ignore it and authorize based on current context only
|
128
|
+
current_user and current_user.admin?
|
129
|
+
end
|
130
|
+
|
131
|
+
# can? :search, Page, 'Ruby rocks!'
|
132
|
+
def search?(clazz, phrase)
|
133
|
+
# Apart from context, we can require to pass additional parameters
|
134
|
+
create?(Page) and (phrase || '').match /rocks/i
|
135
|
+
end
|
136
|
+
end
|
137
|
+
```
|
138
|
+
|
139
|
+
|
140
|
+
# Testing with RSpec
|
141
|
+
|
142
|
+
To test the access control classes you can just instantiate those passing context as a parameter.
|
143
|
+
Most of the times you will stub out the context, so more isolated is a piece of cake.
|
144
|
+
|
145
|
+
You need to `require 'allowy/rspec'` to enable the RSpec matchers and Rails controller extensions.
|
146
|
+
It will give you RSpec matcher `be_able_to` and `ignore_authorization!` macro for controller specs.
|
147
|
+
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
# spec/models/page_access.rb
|
151
|
+
# Example spec for the PageAccess
|
152
|
+
describe PageAccess do
|
153
|
+
subject { PageAccess.new double(current_user: User.new.or_whatever) }
|
154
|
+
let(:page) { Page.new }
|
155
|
+
|
156
|
+
describe "#view" do
|
157
|
+
it { should_not be_able_to :view, page }
|
158
|
+
|
159
|
+
context "when published" do
|
160
|
+
before { page.publish! }
|
161
|
+
it { should be_able_to :view, page }
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# and so on
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
# Example of a controller specs
|
170
|
+
describe PagesController do
|
171
|
+
# This will always grant access, so you don't have to create too many objects
|
172
|
+
# But make sure you test PageAccess separately as in the example above
|
173
|
+
ignore_authorization!
|
174
|
+
|
175
|
+
it "will always allow no matter what" do
|
176
|
+
post(:create).should be_success
|
177
|
+
end
|
178
|
+
end
|
179
|
+
```
|
180
|
+
|
181
|
+
# Development
|
182
|
+
|
183
|
+
|
184
|
+
- Source hosted at [GitHub](https://github.com/dnagir/allowy)
|
185
|
+
- Report issues and feature requests to [GitHub Issues](https://github.com/dnagir/allowy/issues)
|
186
|
+
- Ping me on Twitter [@dnagir](https://twitter.com/#!/dnagir)
|
187
|
+
|
188
|
+
|
189
|
+
To start contributing (assuming you already cloned the repo in cd-d into it):
|
190
|
+
|
191
|
+
```bash
|
192
|
+
bundle install
|
193
|
+
# Now run the Ruby specs
|
194
|
+
bundle exec rspec spec/
|
195
|
+
```
|
196
|
+
|
197
|
+
|
198
|
+
Pull requests are very welcome, but please include the specs.
|
199
|
+
|
200
|
+
# License
|
201
|
+
|
202
|
+
[MIT] (http://www.opensource.org/licenses/mit-license.php)
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/allowy.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "allowy/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "allowy"
|
7
|
+
s.version = Allowy::VERSION
|
8
|
+
s.authors = ["Dmytrii Nagirniak"]
|
9
|
+
s.email = ["dnagir@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Authorization with simplicity and explicitness in mind}
|
12
|
+
s.description = %q{Allowy provides CanCan-like way of checking permission but doesn't enforce a tight DSL giving you more control}
|
13
|
+
|
14
|
+
s.rubyforge_project = "allowy"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_runtime_dependency "activesupport"
|
22
|
+
|
23
|
+
s.add_development_dependency "rspec"
|
24
|
+
s.add_development_dependency "pry"
|
25
|
+
s.add_development_dependency "guard"
|
26
|
+
s.add_development_dependency "guard-rspec"
|
27
|
+
end
|
data/lib/allowy.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require "allowy/version"
|
3
|
+
require "allowy/access_control"
|
4
|
+
require "allowy/registry"
|
5
|
+
require "allowy/controller_extensions"
|
6
|
+
|
7
|
+
module Allowy
|
8
|
+
class UndefinedAccessControl < StandardError; end
|
9
|
+
class UndefinedAction < StandardError; end
|
10
|
+
|
11
|
+
class AccessDenied < StandardError
|
12
|
+
attr_reader :action, :subject
|
13
|
+
|
14
|
+
def initialize(message, action, subject)
|
15
|
+
@message = message
|
16
|
+
@action = action
|
17
|
+
@subject = subject
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Allowy
|
2
|
+
module AccessControl
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
attr_reader :context
|
6
|
+
end
|
7
|
+
|
8
|
+
module InstanceMethods
|
9
|
+
def initialize(ctx)
|
10
|
+
@context = ctx
|
11
|
+
end
|
12
|
+
|
13
|
+
def can?(action, *args)
|
14
|
+
m = "#{action}?"
|
15
|
+
raise UndefinedAction.new("The #{self.class.name} needs to have #{m} method. Please define it.") unless self.respond_to? m
|
16
|
+
send(m, *args)
|
17
|
+
end
|
18
|
+
|
19
|
+
def cannot?(*args)
|
20
|
+
not can?(*args)
|
21
|
+
end
|
22
|
+
|
23
|
+
def authorize!(*args)
|
24
|
+
raise AccessDenied.new("Not authorized", args.first, args[1]) unless can?(*args)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Allowy
|
2
|
+
|
3
|
+
module ControllerExtensions
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
included do
|
6
|
+
helper_method :can?, :cannot?
|
7
|
+
end
|
8
|
+
|
9
|
+
module InstanceMethods
|
10
|
+
|
11
|
+
def allowy_context
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def current_allowy
|
16
|
+
@current_allowy ||= ::Allowy::Registry.new(allowy_context)
|
17
|
+
end
|
18
|
+
|
19
|
+
def can?(action, subject, *args)
|
20
|
+
current_allowy.access_control_for!(subject).can?(action, subject, *args)
|
21
|
+
end
|
22
|
+
|
23
|
+
def cannot?(*args)
|
24
|
+
current_allowy.access_control_for!(subject).cannot?(action, subject, *args)
|
25
|
+
end
|
26
|
+
|
27
|
+
def authorize!(action, subject, *args)
|
28
|
+
current_allowy.access_control_for!(subject).authorize!(action, subject, *args)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
if defined? ActionController
|
36
|
+
ActionController::Base.send(:include, Allowy::ControllerExtensions)
|
37
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Allowy
|
2
|
+
module Matchers
|
3
|
+
|
4
|
+
class AbleToMatcher
|
5
|
+
def initialize(action, subject=nil)
|
6
|
+
@action, @subject = action, subject
|
7
|
+
end
|
8
|
+
|
9
|
+
def say msg
|
10
|
+
"#{msg} #{@action} #{@subject.inspect}" + if @context
|
11
|
+
' with ' + @context.inspect
|
12
|
+
else
|
13
|
+
''
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def matches?(access_control)
|
18
|
+
@context = access_control.context
|
19
|
+
access_control.can?(@action, @subject)
|
20
|
+
end
|
21
|
+
|
22
|
+
def description
|
23
|
+
say "be able to"
|
24
|
+
end
|
25
|
+
|
26
|
+
def failure_message
|
27
|
+
say "expected to be able to"
|
28
|
+
end
|
29
|
+
|
30
|
+
def negative_failure_message
|
31
|
+
say "expected NOT to be able to"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
::RSpec::Matchers.define :be_able_to do |*args|
|
36
|
+
m = AbleToMatcher.new(*args)
|
37
|
+
match {|a| m.matches?(a) }
|
38
|
+
failure_message_for_should { m.failure_message }
|
39
|
+
failure_message_for_should_not { m.negative_failure_message }
|
40
|
+
description { m.description }
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Allowy
|
2
|
+
class Registry
|
3
|
+
def initialize(ctx)
|
4
|
+
@context = ctx
|
5
|
+
@registry = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def access_control_for!(subject)
|
9
|
+
ac = access_control_for subject
|
10
|
+
raise UndefinedAccessControl.new("Please define Access Control class for #{subject.inspect}") unless ac
|
11
|
+
ac
|
12
|
+
end
|
13
|
+
|
14
|
+
def access_control_for(subject)
|
15
|
+
return unless subject
|
16
|
+
# Try subject as an object
|
17
|
+
clazz = class_for "#{subject.class.name}Access"
|
18
|
+
|
19
|
+
# Try subject as a class
|
20
|
+
clazz = class_for "#{subject.name}Access" if !clazz && subject.is_a?(Class)
|
21
|
+
|
22
|
+
return unless clazz # No luck this time
|
23
|
+
# create a new instance or return existing
|
24
|
+
@registry[clazz] ||= clazz.new(@context)
|
25
|
+
end
|
26
|
+
|
27
|
+
def class_for(name)
|
28
|
+
# TODO: Namespace it
|
29
|
+
return ::Object.const_get(name) if ::Object.const_defined?(name)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
data/lib/allowy/rspec.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'allowy/matchers'
|
2
|
+
|
3
|
+
module Allowy
|
4
|
+
|
5
|
+
module ControllerAuthorizationMacros
|
6
|
+
def ignore_authorization!
|
7
|
+
before(:each) do
|
8
|
+
registry = double 'Registry'
|
9
|
+
registry.stub(:can? => true, :cannot? => false, :authorize! => nil, access_control_for!: registry)
|
10
|
+
@controller.stub(:current_allowy).and_return registry
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
RSpec.configure do |config|
|
18
|
+
config.extend Allowy::ControllerAuthorizationMacros, :type => :controller
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Allowy
|
4
|
+
describe "checking permissions" do
|
5
|
+
|
6
|
+
let(:access) { SampleAccess.new(123) }
|
7
|
+
subject { access }
|
8
|
+
|
9
|
+
describe "#context as an arbitrary object" do
|
10
|
+
subject { access.context }
|
11
|
+
its(:to_s) { should == '123' }
|
12
|
+
its(:zero?) { should be_false }
|
13
|
+
it "should be able to access the context" do
|
14
|
+
access.should be_able_to :context_is_123
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should allow" do
|
19
|
+
subject.should be_able_to :read, 'allow'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should deny" do
|
23
|
+
subject.should_not be_able_to :read, 'deny'
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should raise if no permission defined" do
|
27
|
+
lambda { subject.can? :write, 'allow' }.should raise_error(UndefinedAction) {|err|
|
28
|
+
err.message.should include 'write?'
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
describe "#authorize!" do
|
34
|
+
it "shuold raise error" do
|
35
|
+
expect { subject.authorize! :read, 'deny' }.to raise_error AccessDenied do |err|
|
36
|
+
err.message.should_not be_blank
|
37
|
+
err.action.should == :read
|
38
|
+
err.subject.should == 'deny'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should not raise error" do
|
43
|
+
expect { subject.authorize! :read, 'allow' }.not_to raise_error AccessDenied
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Allowy
|
4
|
+
describe Registry do
|
5
|
+
let(:context) { 123 }
|
6
|
+
subject { Registry.new context }
|
7
|
+
|
8
|
+
describe "#access_control_for!" do
|
9
|
+
|
10
|
+
it "should find AC by appending Access to the subject" do
|
11
|
+
subject.access_control_for!(Sample.new).should be_a SampleAccess
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should find AC when the subject is a class" do
|
15
|
+
subject.access_control_for!(Sample).should be_a SampleAccess
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should raise when AC is not found by the subject" do
|
19
|
+
lambda { subject.access_control_for!(123) }.should raise_error(UndefinedAccessControl) {|err|
|
20
|
+
err.message.should include '123'
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should raise when subject is nil" do
|
25
|
+
lambda { subject.access_control_for!(nil) }.should raise_error UndefinedAccessControl
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should return the same AC instance" do
|
29
|
+
first = subject.access_control_for!(Sample)
|
30
|
+
secnd = subject.access_control_for!(Sample)
|
31
|
+
first.should === secnd
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'pry'
|
2
|
+
require 'allowy'
|
3
|
+
require 'allowy/matchers'
|
4
|
+
|
5
|
+
RSpec.configure do |c|
|
6
|
+
c.treat_symbols_as_metadata_keys_with_true_values = true
|
7
|
+
c.run_all_when_everything_filtered = true
|
8
|
+
end
|
9
|
+
|
10
|
+
class SampleAccess
|
11
|
+
include Allowy::AccessControl
|
12
|
+
|
13
|
+
def read?(str)
|
14
|
+
str == 'allow'
|
15
|
+
end
|
16
|
+
|
17
|
+
def context_is_123?(*whatever)
|
18
|
+
context === 123
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Sample
|
23
|
+
attr_accessor :name
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: allowy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Dmytrii Nagirniak
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-01-07 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: &70137337531820 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70137337531820
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &70137337531300 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70137337531300
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: pry
|
38
|
+
requirement: &70137337530860 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70137337530860
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: guard
|
49
|
+
requirement: &70137337530240 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70137337530240
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: guard-rspec
|
60
|
+
requirement: &70137337529580 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70137337529580
|
69
|
+
description: Allowy provides CanCan-like way of checking permission but doesn't enforce
|
70
|
+
a tight DSL giving you more control
|
71
|
+
email:
|
72
|
+
- dnagir@gmail.com
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- .gitignore
|
78
|
+
- .rspec
|
79
|
+
- Gemfile
|
80
|
+
- Guardfile
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- allowy.gemspec
|
84
|
+
- lib/allowy.rb
|
85
|
+
- lib/allowy/access_control.rb
|
86
|
+
- lib/allowy/controller_extensions.rb
|
87
|
+
- lib/allowy/matchers.rb
|
88
|
+
- lib/allowy/registry.rb
|
89
|
+
- lib/allowy/rspec.rb
|
90
|
+
- lib/allowy/version.rb
|
91
|
+
- spec/access_control_spec.rb
|
92
|
+
- spec/registry_spec.rb
|
93
|
+
- spec/spec_helper.rb
|
94
|
+
homepage: ''
|
95
|
+
licenses: []
|
96
|
+
post_install_message:
|
97
|
+
rdoc_options: []
|
98
|
+
require_paths:
|
99
|
+
- lib
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ! '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ! '>='
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
requirements: []
|
113
|
+
rubyforge_project: allowy
|
114
|
+
rubygems_version: 1.8.10
|
115
|
+
signing_key:
|
116
|
+
specification_version: 3
|
117
|
+
summary: Authorization with simplicity and explicitness in mind
|
118
|
+
test_files:
|
119
|
+
- spec/access_control_spec.rb
|
120
|
+
- spec/registry_spec.rb
|
121
|
+
- spec/spec_helper.rb
|
122
|
+
has_rdoc:
|