safety_patrol 0.5.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 +18 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +91 -0
- data/Rakefile +2 -0
- data/lib/safety_patrol.rb +32 -0
- data/lib/safety_patrol/abilities.rb +36 -0
- data/lib/safety_patrol/configuration.rb +22 -0
- data/lib/safety_patrol/user_abilities.rb +19 -0
- data/lib/safety_patrol/version.rb +3 -0
- data/safety_patrol.gemspec +18 -0
- data/spec/safety_patrol/abilities_spec.rb +45 -0
- data/spec/safety_patrol/configuration_spec.rb +12 -0
- data/spec/safety_patrol/user_abilities_spec.rb +47 -0
- data/spec/safety_patrol_spec.rb +33 -0
- data/spec/spec_helper.rb +9 -0
- metadata +77 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Thomas Brewer
|
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,91 @@
|
|
1
|
+
# SafetyPatrol (BETA)
|
2
|
+
Simple framework agnostic Authorization gem. It was heavily (start the copiers) influenced by the Authority gem, but I wanted a core authorization gem that was not tied to a specific web framework.
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
Add this line to your application's Gemfile:
|
7
|
+
|
8
|
+
gem 'safety_patrol'
|
9
|
+
|
10
|
+
And then execute:
|
11
|
+
|
12
|
+
$ bundle
|
13
|
+
|
14
|
+
Or install it yourself as:
|
15
|
+
|
16
|
+
$ gem install safety_patrol
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
#configure it
|
21
|
+
SafetyPatrol.configure |config|
|
22
|
+
#verb #adjective
|
23
|
+
config.abilities[:send] = :sendable
|
24
|
+
|
25
|
+
#the default abilities are:
|
26
|
+
#:create => :creatable
|
27
|
+
#:read => :readable
|
28
|
+
#:update => :updatable
|
29
|
+
#:delete => :deletable
|
30
|
+
end
|
31
|
+
|
32
|
+
#define a User class and include the SafetyPatrol::UserAbilities module
|
33
|
+
class User
|
34
|
+
include SafetyPatrol::UserAbilities
|
35
|
+
attr_accessor :role
|
36
|
+
def admin?
|
37
|
+
role == 'admin'
|
38
|
+
# or whatever logic fits your apps needs
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
#define a class that you want to provide authorization logic for
|
44
|
+
#and include SafetyPatrol::Abilities module and declare the authorizer class
|
45
|
+
class Article
|
46
|
+
include SafetyPatrol::Abilities
|
47
|
+
authorizer 'ArticleAuthorizer'
|
48
|
+
end
|
49
|
+
|
50
|
+
#define you authorizer class that contains the authorization logic
|
51
|
+
class ArticleAuthorizer
|
52
|
+
|
53
|
+
#define methods that follow the convention of adjective_by?(user, resource)
|
54
|
+
|
55
|
+
#these methods with receive the user and resource
|
56
|
+
def creatable_by?(user, article)
|
57
|
+
user.admin?
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
#check for a user's authorization
|
62
|
+
admin = User.new
|
63
|
+
admin.role = 'admin'
|
64
|
+
|
65
|
+
guest = User.new
|
66
|
+
guest.role = 'guest'
|
67
|
+
|
68
|
+
article = Article.new
|
69
|
+
|
70
|
+
guest.can_create?(article) # return false
|
71
|
+
admin.can_create?(article) # return true
|
72
|
+
|
73
|
+
article.creatable_by(admin) #return true
|
74
|
+
article.creatable_by(guest) #return false
|
75
|
+
|
76
|
+
#What everything boils down to is SafetyPatrol is just providing sugar on top of this:
|
77
|
+
authorizer = ArticleAuthorizer.new
|
78
|
+
authorizer.creatable_by?(admin, article) #return true
|
79
|
+
|
80
|
+
|
81
|
+
##Todos
|
82
|
+
1. Add more specs
|
83
|
+
2. Repeat #1
|
84
|
+
|
85
|
+
## Contributing
|
86
|
+
|
87
|
+
1. Fork it
|
88
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
89
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
90
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
91
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require "safety_patrol/version"
|
2
|
+
require "safety_patrol/configuration"
|
3
|
+
|
4
|
+
module SafetyPatrol
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def abilities
|
9
|
+
configuration.abilities.freeze
|
10
|
+
end
|
11
|
+
|
12
|
+
def verbs
|
13
|
+
abilities.keys
|
14
|
+
end
|
15
|
+
|
16
|
+
def adjectives
|
17
|
+
abilities.values
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_accessor :configuration
|
21
|
+
|
22
|
+
def configure
|
23
|
+
self.configuration ||= Configuration.new
|
24
|
+
yield(configuration) if block_given?
|
25
|
+
require 'safety_patrol/user_abilities'
|
26
|
+
require 'safety_patrol/abilities'
|
27
|
+
configuration
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module SafetyPatrol
|
2
|
+
|
3
|
+
module Abilities
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
|
11
|
+
attr_accessor :_authorizer
|
12
|
+
|
13
|
+
def authorizer(object = nil)
|
14
|
+
if object.nil?
|
15
|
+
self._authorizer
|
16
|
+
else
|
17
|
+
self._authorizer = (object.is_a?(String)) ? Kernel.const_get(object).new : object.new
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
SafetyPatrol.adjectives.each do |adjective|
|
24
|
+
define_method(("#{adjective}_by?").intern) do |user|
|
25
|
+
self.authorizer.send(("#{adjective}_by?").intern, user, self)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def authorizer
|
30
|
+
self.class.authorizer
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module SafetyPatrol
|
2
|
+
|
3
|
+
class Configuration
|
4
|
+
|
5
|
+
attr_accessor :abilities
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
|
9
|
+
@abilities = {
|
10
|
+
#verb #adjective
|
11
|
+
:create => :creatable,
|
12
|
+
:read => :readable,
|
13
|
+
:update => :updatable,
|
14
|
+
:delete => :deletable
|
15
|
+
}
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SafetyPatrol
|
2
|
+
|
3
|
+
module UserAbilities
|
4
|
+
|
5
|
+
#define some method on the user for convenience
|
6
|
+
SafetyPatrol.verbs.each do |verb|
|
7
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
8
|
+
def can_#{verb}?(resource)
|
9
|
+
resource.#{SafetyPatrol.abilities[verb]}_by?(self)
|
10
|
+
end
|
11
|
+
RUBY
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/safety_patrol/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Thomas Brewer"]
|
6
|
+
gem.email = ["tom@21purple.com"]
|
7
|
+
gem.description = %q{Simple framework agnostic Authorization gem}
|
8
|
+
gem.summary = gem.description
|
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 = "safety_patrol"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = SafetyPatrol::VERSION
|
17
|
+
gem.add_development_dependency('rspec')
|
18
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class ArticleAuthorizer
|
4
|
+
|
5
|
+
def creatable_by?(user, resource)
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
class Article
|
12
|
+
include SafetyPatrol::Abilities
|
13
|
+
authorizer 'ArticleAuthorizer'
|
14
|
+
end
|
15
|
+
|
16
|
+
describe SafetyPatrol::Abilities do
|
17
|
+
|
18
|
+
it "should define methods on a class based upon the abilities hash" do
|
19
|
+
article = Article.new
|
20
|
+
lambda {
|
21
|
+
article.creatable_by?
|
22
|
+
}.should_not raise_exception(NoMethodError)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should have an associated Authorizer" do
|
26
|
+
Article.authorizer.should be_instance_of(ArticleAuthorizer)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should receive a creatable_by? call and return true or false" do
|
30
|
+
article = Article.new
|
31
|
+
user = double("User")
|
32
|
+
article.creatable_by?(user).should eq(true)
|
33
|
+
end
|
34
|
+
|
35
|
+
describe ArticleAuthorizer do
|
36
|
+
|
37
|
+
it "should receive a creatable_by?" do
|
38
|
+
article = Article.new
|
39
|
+
article.authorizer.should_receive(:creatable_by?)
|
40
|
+
user = double("User")
|
41
|
+
article.creatable_by?(user)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
describe SafetyPatrol::Configuration do
|
5
|
+
|
6
|
+
it "should all you to set abilities" do
|
7
|
+
configuration = SafetyPatrol::Configuration.new
|
8
|
+
configuration.abilities[:send] = 'sendable'
|
9
|
+
configuration.abilities[:send].should eq('sendable')
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class User
|
4
|
+
include SafetyPatrol::UserAbilities
|
5
|
+
end
|
6
|
+
|
7
|
+
class UserItemAuthorizer
|
8
|
+
|
9
|
+
def creatable_by?(user, resource)
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
def deletable_by?(user, resource)
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
class UserItem
|
20
|
+
include SafetyPatrol::Abilities
|
21
|
+
authorizer UserItemAuthorizer
|
22
|
+
end
|
23
|
+
|
24
|
+
describe SafetyPatrol::UserAbilities do
|
25
|
+
|
26
|
+
it "should define methods on a User class based upon the abilities hash" do
|
27
|
+
user = User.new
|
28
|
+
article = double("article")
|
29
|
+
article.should_receive(:creatable_by?)
|
30
|
+
lambda {
|
31
|
+
user.can_create? article
|
32
|
+
}.should_not raise_exception(NoMethodError)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "#can_create? should return true" do
|
36
|
+
user = User.new
|
37
|
+
user_item = UserItem.new
|
38
|
+
user.can_create?(user_item).should eq(true)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "#can_delete? should return false" do
|
42
|
+
user = User.new
|
43
|
+
user_item = UserItem.new
|
44
|
+
user.can_delete?(user_item).should eq(false)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
describe SafetyPatrol do
|
5
|
+
|
6
|
+
it "should present a configuration object via a block" do
|
7
|
+
configuration = nil
|
8
|
+
SafetyPatrol.configure do |config|
|
9
|
+
configuration = config
|
10
|
+
end
|
11
|
+
configuration.should be_instance_of(SafetyPatrol::Configuration)
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
describe "Abilities" do
|
16
|
+
|
17
|
+
before do
|
18
|
+
SafetyPatrol.configure do |config|
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should provide a list of ability verbs" do
|
23
|
+
SafetyPatrol.verbs.should eq([:create, :read, :update, :delete])
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should provide a list of ability verbs" do
|
27
|
+
SafetyPatrol.adjectives.should eq([:creatable, :readable, :updatable, :deletable])
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: safety_patrol
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Thomas Brewer
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &70299455803640 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70299455803640
|
25
|
+
description: Simple framework agnostic Authorization gem
|
26
|
+
email:
|
27
|
+
- tom@21purple.com
|
28
|
+
executables: []
|
29
|
+
extensions: []
|
30
|
+
extra_rdoc_files: []
|
31
|
+
files:
|
32
|
+
- .gitignore
|
33
|
+
- Gemfile
|
34
|
+
- LICENSE
|
35
|
+
- README.md
|
36
|
+
- Rakefile
|
37
|
+
- lib/safety_patrol.rb
|
38
|
+
- lib/safety_patrol/abilities.rb
|
39
|
+
- lib/safety_patrol/configuration.rb
|
40
|
+
- lib/safety_patrol/user_abilities.rb
|
41
|
+
- lib/safety_patrol/version.rb
|
42
|
+
- safety_patrol.gemspec
|
43
|
+
- spec/safety_patrol/abilities_spec.rb
|
44
|
+
- spec/safety_patrol/configuration_spec.rb
|
45
|
+
- spec/safety_patrol/user_abilities_spec.rb
|
46
|
+
- spec/safety_patrol_spec.rb
|
47
|
+
- spec/spec_helper.rb
|
48
|
+
homepage: ''
|
49
|
+
licenses: []
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
requirements: []
|
67
|
+
rubyforge_project:
|
68
|
+
rubygems_version: 1.8.10
|
69
|
+
signing_key:
|
70
|
+
specification_version: 3
|
71
|
+
summary: Simple framework agnostic Authorization gem
|
72
|
+
test_files:
|
73
|
+
- spec/safety_patrol/abilities_spec.rb
|
74
|
+
- spec/safety_patrol/configuration_spec.rb
|
75
|
+
- spec/safety_patrol/user_abilities_spec.rb
|
76
|
+
- spec/safety_patrol_spec.rb
|
77
|
+
- spec/spec_helper.rb
|