active_control 0.0.1
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 +4 -0
- data/Gemfile +4 -0
- data/README.rdoc +37 -0
- data/Rakefile +18 -0
- data/active_control.gemspec +24 -0
- data/lib/active_control.rb +29 -0
- data/lib/active_control/ability.rb +47 -0
- data/lib/active_control/authorization.rb +31 -0
- data/lib/active_control/version.rb +3 -0
- data/test/test_active_control.rb +54 -0
- metadata +74 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
= ActiveControl
|
2
|
+
|
3
|
+
<tt>ActiveControl</tt> is a very simple authorization solution with no dependencies. Each rule is stored in the class that grant permission. Other object can then check if they have access to a specific action via the <tt>can?</tt> method (or via <tt>cannot?</tt>).
|
4
|
+
|
5
|
+
== Install
|
6
|
+
|
7
|
+
gem install active_control
|
8
|
+
|
9
|
+
== Usage
|
10
|
+
|
11
|
+
The first thing to do is to <tt>include ActiveControl::Ability</tt> in the object which needs to check if it can perform an action on another object.
|
12
|
+
|
13
|
+
class User
|
14
|
+
include ActiveControl::Ability
|
15
|
+
end
|
16
|
+
|
17
|
+
At the other end <tt>include ActiveControl::Authorization</tt> in the object that will give its "blessing" or not based on some internal rules defined by you. Rules are just normal methods you have to defined at the instance-level with a specific name. E.g. if an instance of the <tt>User:Class</tt> wants to update another object you have to define <tt>authorize_user_to_update?</tt> and make it returns a boolean.
|
18
|
+
|
19
|
+
class Page
|
20
|
+
include ActiveControl::Authorization
|
21
|
+
|
22
|
+
...
|
23
|
+
|
24
|
+
def authorize_user_to_update?(user)
|
25
|
+
user.id == page.user_id
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
Then you can do something like this
|
30
|
+
|
31
|
+
if @user.can? :update, @page
|
32
|
+
@page.update_attributes(params[:page])
|
33
|
+
else
|
34
|
+
...
|
35
|
+
end
|
36
|
+
|
37
|
+
And that's it. Simple uh!
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rake/testtask.rb'
|
5
|
+
Rake::TestTask.new do |t|
|
6
|
+
t.libs << "test"
|
7
|
+
t.test_files = FileList['test/test_*.rb']
|
8
|
+
end
|
9
|
+
|
10
|
+
require File.expand_path("../lib/active_control/version", __FILE__)
|
11
|
+
desc "Build the documentation"
|
12
|
+
task :doc do
|
13
|
+
sh [
|
14
|
+
"rm -rf doc/",
|
15
|
+
"sdoc -N -x test -x pkg -x '(Rake|Gem)file(.lock)?' -x 'active_control.gemspec' -m README.rdoc -t 'ActiveControl #{ActiveControl::VERSION}'",
|
16
|
+
"open doc/index.html"
|
17
|
+
].join(" && ")
|
18
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "active_control/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "active_control"
|
7
|
+
s.version = ActiveControl::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.summary = "Very simple authorization solution."
|
10
|
+
s.description = "Very simple authorization solution with no depedencies. Each permission is stored in its class and authorizations are given through a two methods interface."
|
11
|
+
s.homepage = "https://github.com/robinclart/active_control"
|
12
|
+
|
13
|
+
s.authors = ["Robin Clart"]
|
14
|
+
s.email = ["robin@charlin.be"]
|
15
|
+
|
16
|
+
s.rubyforge_project = s.name
|
17
|
+
|
18
|
+
s.add_development_dependency "sdoc", ">= 0.2.20"
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
23
|
+
s.require_paths = ["lib"]
|
24
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 20011 Robin Clart
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
require 'active_control/version'
|
25
|
+
|
26
|
+
module ActiveControl
|
27
|
+
autoload :Ability, 'active_control/ability'
|
28
|
+
autoload :Authorization, 'active_control/authorization'
|
29
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module ActiveControl
|
2
|
+
# == Active Control Ability
|
3
|
+
#
|
4
|
+
# Creates two methods +can?+ and +cannot?+ to check if a remote object allows
|
5
|
+
# this object to perform a specific action on it.
|
6
|
+
#
|
7
|
+
# To implement, just <tt>include ActiveControl::Ability</tt> in your class:
|
8
|
+
#
|
9
|
+
# class User
|
10
|
+
# include ActiveControl::Ability
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# Those two methods requires that the remote object implements an +authorize?+
|
14
|
+
# method that returns a boolean.
|
15
|
+
#
|
16
|
+
# A minimal implementation could be:
|
17
|
+
#
|
18
|
+
# class User
|
19
|
+
# include ActiveControl::Ability
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# class Post
|
23
|
+
# def authorize?(*args)
|
24
|
+
# true
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# You could then do something like this:
|
29
|
+
#
|
30
|
+
# user = User.new
|
31
|
+
# post = Post.new
|
32
|
+
#
|
33
|
+
# puts user.can?(:update, post)
|
34
|
+
# >> true
|
35
|
+
#
|
36
|
+
# Instead of defining an +authorize?+ method manually you could also implement
|
37
|
+
# ActiveControl::Authorization on the remote object.
|
38
|
+
module Ability
|
39
|
+
def can?(action, remote_object)
|
40
|
+
remote_object.authorize?(self, action)
|
41
|
+
end
|
42
|
+
|
43
|
+
def cannot?(*args)
|
44
|
+
!can?(*args)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ActiveControl
|
2
|
+
# == Active Control Authorization
|
3
|
+
#
|
4
|
+
# Creates an +authorize?+ method.
|
5
|
+
#
|
6
|
+
# To implement, just <tt>include ActiveControl::Authorization</tt> in your
|
7
|
+
# class:
|
8
|
+
#
|
9
|
+
# class User
|
10
|
+
# include ActiveControl::Authorization
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# The +authorize?+ method is responsible for giving authorization to another
|
14
|
+
# object to perform a specific action.
|
15
|
+
#
|
16
|
+
# Internally +authorize?+ will delegate to another method. The name of this
|
17
|
+
# other method is defined during runtime and is based on two things:
|
18
|
+
#
|
19
|
+
# * the class name of the object seeking for permission;
|
20
|
+
# * the action name.
|
21
|
+
#
|
22
|
+
# E.g. if an instance of the <tt>User:Class</tt> wanted to update your object
|
23
|
+
# you'd have to define a +authorize_user_to_update?+ method.
|
24
|
+
module Authorization
|
25
|
+
def authorize?(caller_object, action)
|
26
|
+
caller_name = caller_object.class.name.gsub("::", "_")
|
27
|
+
action = [caller_name, action.to_s].join("_to_").downcase
|
28
|
+
self.send "authorize_#{action}?", caller_object
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require File.expand_path('../../lib/active_control', __FILE__)
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
class User
|
5
|
+
include ActiveControl::Ability
|
6
|
+
end
|
7
|
+
|
8
|
+
module Admin
|
9
|
+
class User
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Comment
|
14
|
+
include ActiveControl::Authorization
|
15
|
+
|
16
|
+
def authorize_admin_user_to_manage?(user)
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def authorize_user_to_manage?(user)
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
def authorize_user_to_destroy?(user)
|
25
|
+
false
|
26
|
+
end
|
27
|
+
|
28
|
+
def authorize_user_to_read?(user)
|
29
|
+
true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class TestActiveControl < MiniTest::Unit::TestCase
|
34
|
+
def setup
|
35
|
+
@user = User.new
|
36
|
+
@comment = Comment.new
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_can?
|
40
|
+
assert @user.can? :manage, @comment
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_cannot?
|
44
|
+
assert @user.cannot? :destroy, @comment
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_authorize?
|
48
|
+
assert @comment.authorize?(@user, :read)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_authorize_in_a_namespace
|
52
|
+
assert @comment.authorize?(Admin::User.new, :manage)
|
53
|
+
end
|
54
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active_control
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Robin Clart
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-06-02 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: sdoc
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.2.20
|
24
|
+
type: :development
|
25
|
+
version_requirements: *id001
|
26
|
+
description: Very simple authorization solution with no depedencies. Each permission is stored in its class and authorizations are given through a two methods interface.
|
27
|
+
email:
|
28
|
+
- robin@charlin.be
|
29
|
+
executables: []
|
30
|
+
|
31
|
+
extensions: []
|
32
|
+
|
33
|
+
extra_rdoc_files: []
|
34
|
+
|
35
|
+
files:
|
36
|
+
- .gitignore
|
37
|
+
- Gemfile
|
38
|
+
- README.rdoc
|
39
|
+
- Rakefile
|
40
|
+
- active_control.gemspec
|
41
|
+
- lib/active_control.rb
|
42
|
+
- lib/active_control/ability.rb
|
43
|
+
- lib/active_control/authorization.rb
|
44
|
+
- lib/active_control/version.rb
|
45
|
+
- test/test_active_control.rb
|
46
|
+
homepage: https://github.com/robinclart/active_control
|
47
|
+
licenses: []
|
48
|
+
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
|
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
|
+
|
68
|
+
rubyforge_project: active_control
|
69
|
+
rubygems_version: 1.8.4
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: Very simple authorization solution.
|
73
|
+
test_files:
|
74
|
+
- test/test_active_control.rb
|