allows 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,6 @@
1
+ [![Build Status](https://secure.travis-ci.org/zeto/allows.png)](http://travis-ci.org/zeto/allows)
2
+
3
+ allows
4
+ ======
5
+
6
+ Simple authorization library
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ task :default => [:test_units]
5
+
6
+ desc "Run tests"
7
+ Rake::TestTask.new("test_units") do |t|
8
+ t.pattern = 'test/*_test.rb'
9
+ t.verbose = true
10
+ t.warning = false
11
+ end
12
+
13
+
14
+ desc "Open an irb session"
15
+ task :console do
16
+ sh "irb -I lib -r allows.rb"
17
+ end
18
+
data/allows.gemspec ADDED
@@ -0,0 +1,17 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'allows'
3
+ s.version = '0.2.1'
4
+ s.date = '2012-09-24'
5
+ s.summary = "Simple Authorization library"
6
+ s.description = "Simple Authorization for Rails"
7
+ s.authors = ["Jose Goncalves"]
8
+ s.email = 'zetoeu@gmail.com'
9
+ s.homepage = 'http://github.com/zeto/allows'
10
+ s.files = Dir["**/*"] - Dir["*.gem"] - ["Gemfile.lock"]
11
+
12
+ s.require_paths = ["lib"]
13
+ s.add_dependency 'actionpack'
14
+ s.add_development_dependency "turn"
15
+ s.add_development_dependency "debugger"
16
+ s.add_development_dependency "rake"
17
+ end
data/lib/allows.rb ADDED
@@ -0,0 +1,121 @@
1
+ require 'action_controller'
2
+ require 'exceptions'
3
+
4
+ module Allows
5
+
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+
9
+ base.send :before_filter, :set_permissions
10
+ base.send :before_filter, :check_permissions
11
+
12
+ class << base
13
+ attr_accessor :permissions
14
+ cattr_accessor :permission_checker
15
+ end
16
+
17
+ # set default permission_checker
18
+ base.permission_checker = :current_user
19
+ end
20
+
21
+ public
22
+
23
+ def check_permissions
24
+ im_allowed = false
25
+
26
+ klass = self.class
27
+ if klass.permission_checker && respond_to?(klass.permission_checker)
28
+ if klass.permissions
29
+ permissions_for_action = klass.permissions[action_name.to_sym]
30
+ if permissions_for_action
31
+ permissions_for_action.each do |permission|
32
+ if assert_permission(permission)
33
+ im_allowed = true
34
+ end
35
+ end
36
+ else
37
+ # Can execute the action. No "allow" rule affects this action.
38
+ im_allowed = true
39
+ end
40
+ else
41
+ # Can execute any action. Controller does not declare any "allow" rule
42
+ im_allowed = true
43
+ end
44
+ else
45
+ raise NoPermissionChecker # Permission checker isnt defined, so no permissions can be validated
46
+ end
47
+ raise Unauthorized unless im_allowed
48
+ end
49
+
50
+ protected
51
+
52
+ def set_permissions
53
+ self.class.set_permissions # Call class method instead
54
+ end
55
+
56
+ private
57
+
58
+ def assert_permission(permission)
59
+ targetted_permission = /(?<method>.+)_of_(?<target>.+)/.match(permission.to_s)
60
+
61
+ # Permission is something like: allow reader_of_post (<permission>_of_<target>)
62
+ if targetted_permission && targetted_permission.captures.size == 2
63
+ raise NoInstanceVariable unless instance_variable_get("@#{targetted_permission[:target]}")
64
+ (self.send self.class.permission_checker).send "#{targetted_permission[:method]}?", instance_variable_get("@#{targetted_permission[:target]}")
65
+ else
66
+ (self.send self.class.permission_checker).send "#{permission.to_s}?"
67
+ end
68
+ end
69
+
70
+ module ClassMethods
71
+ def allow(*options, &block)
72
+ @allows ||= Array.new
73
+ @allows << options
74
+ end
75
+
76
+ def set_permissions
77
+ # Permissions are calculated only once per class for performance considerations
78
+ # This behaviour is overridden in development so permissions are always calculated
79
+ if (!@permissions && @allows) || (defined?(RAILS_ENV) && RAILS_ENV == 'development')
80
+ @permissions = Hash.new
81
+
82
+ if @allows
83
+ @allows.each do |p|
84
+ allowed = Hash.new
85
+ hash = p.select{|o| o.is_a?(Hash)}
86
+
87
+ allowed[:permissions] = p - hash
88
+
89
+ actions = hash.first
90
+ if hash.first
91
+ allowed[:except] = actions[:except]
92
+ allowed[:only] = actions[:only]
93
+ end
94
+
95
+ if allowed[:only] # Only for the specified actions
96
+ allowed_actions = Array(allowed[:only])
97
+ elsif allowed[:except] # All available actions EXCEPT the ones specified
98
+ allowed_actions = controller_actions - Array(allowed[:except])
99
+ else # All available actions
100
+ allowed_actions = controller_actions
101
+ end
102
+
103
+ allowed_actions.each do |action|
104
+ @permissions[action.to_sym] = (Array(@permissions[action.to_sym]) + allowed[:permissions]).uniq
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+
111
+ def clear_permissions
112
+ @permissions = nil
113
+ end
114
+
115
+ private
116
+
117
+ def controller_actions
118
+ (self.new.action_methods - ActionController::Base.new.action_methods).map {|am| am.to_sym} - [:check_permissions]
119
+ end
120
+ end
121
+ end
data/lib/exceptions.rb ADDED
@@ -0,0 +1,14 @@
1
+ class NoPermissionChecker < Exception
2
+ end
3
+
4
+ class NoDefinedPermissions < Exception
5
+ end
6
+
7
+ class NoPermissionDefinedForAction < Exception
8
+ end
9
+
10
+ class NoInstanceVariable < Exception
11
+ end
12
+
13
+ class Unauthorized < Exception
14
+ end
@@ -0,0 +1,154 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'minitest/autorun'
4
+ require 'turn'
5
+ require 'allows'
6
+ require 'rubygems'
7
+ #require 'action_pack'
8
+ require 'action_controller'
9
+
10
+ class AllowsTest < MiniTest::Unit::TestCase
11
+ def test_simple_permissions
12
+ TestController.set_permissions
13
+
14
+ assert TestController.permissions.count == 5
15
+
16
+ assert TestController.permissions[:index].include? :admin
17
+ refute TestController.permissions[:show].include? :gpd
18
+ assert TestController.permissions[:index].include? :dds
19
+ end
20
+
21
+ def test_complex_permissions
22
+ TestController.set_permissions
23
+
24
+ assert TestController.permissions.count == 5
25
+
26
+ assert TestController.permissions[:index].include? :a
27
+ assert TestController.permissions[:create].include? :b
28
+ assert TestController.permissions[:update].include? :c
29
+
30
+ assert TestController.permissions[:create].include? :d
31
+ refute TestController.permissions[:index].include? :d
32
+ refute TestController.permissions[:new].include? :d
33
+ refute TestController.permissions[:show].include? :d
34
+
35
+ assert TestController.permissions[:create].include? :e
36
+ refute TestController.permissions[:index].include? :f
37
+ end
38
+
39
+ def test_must_not_include_nonexistant_action
40
+ TestController.set_permissions
41
+
42
+ refute TestController.permissions[:showw]
43
+ refute TestController.permissions[:accao_que_nao_existe]
44
+ end
45
+
46
+ def test_all_actions
47
+ TestController.set_permissions
48
+
49
+ assert TestController.permissions.count == 5
50
+
51
+ assert TestController.permissions.keys.include? :index
52
+ assert TestController.permissions.keys.include? :show
53
+ assert TestController.permissions.keys.include? :update
54
+ assert TestController.permissions.keys.include? :new
55
+ assert TestController.permissions.keys.include? :create
56
+ end
57
+
58
+ def test_generate_unauthorized
59
+ TestControllerNone.set_permissions
60
+
61
+ assert_raises Unauthorized do
62
+ TestControllerNone.new.check_permissions
63
+ end
64
+ end
65
+
66
+ def test_allow_that_depends_on_instance_variable
67
+ TestControllerComplex.set_permissions
68
+
69
+ assert TestControllerComplex.permissions.count == 1
70
+
71
+ tcc = TestControllerComplex.new
72
+ tcc.instance_variable_set(:@requirement,RequirementStub.new)
73
+ tcc.instance_variable_set(:@post,3)
74
+
75
+ tcc.check_permissions
76
+ end
77
+
78
+ end
79
+
80
+ class TestController < ActionController::Base
81
+ include Allows
82
+
83
+ allow :admin
84
+ allow :gpd, :only => :index
85
+ allow :dds, :except => :show
86
+
87
+ allow :a, :b, :c
88
+ allow :d, :only => :create
89
+ allow :e, :f, :except => [:index, :update, :show]
90
+
91
+ def index; end
92
+ def show; end
93
+ def update; end
94
+ def new; end
95
+ def create; end
96
+
97
+ protected
98
+
99
+ def action_name; :show; end
100
+ def current_user; PermissionCheckerDeluxe.new; end
101
+
102
+ end
103
+
104
+ class PermissionCheckerDeluxe
105
+ def admin?; true; end
106
+ def gpd?; true; end
107
+ def dds?; false; end
108
+ def a?; false; end
109
+ def b?; true; end
110
+ def c?; false; end
111
+ def d?; true; end
112
+ def e?; false; end
113
+ def f?; true; end
114
+ end
115
+
116
+ class TestControllerComplex < ActionController::Base
117
+ include Allows
118
+
119
+ allow :reader_of_requirement, :editor_of_post
120
+
121
+ def show; end
122
+
123
+ protected
124
+
125
+ def action_name; :show; end
126
+ def current_user; PermissionCheckerForRequirement.new; end
127
+ end
128
+
129
+ class PermissionCheckerForRequirement
130
+ def reader?(requirement); requirement.message == 'testing'; end
131
+ def editor?(post); post == 3; end
132
+ end
133
+
134
+ class RequirementStub
135
+ def message; 'testing'; end
136
+ end
137
+
138
+ class TestControllerNone < ActionController::Base
139
+ include Allows
140
+
141
+ allow :admin
142
+
143
+ def show; end
144
+
145
+ protected
146
+
147
+ def action_name; :show; end
148
+ def current_user; PermissionCheckerNone.new; end
149
+
150
+ end
151
+
152
+ class PermissionCheckerNone
153
+ def admin?; false; end
154
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: allows
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jose Goncalves
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: actionpack
16
+ requirement: !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: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: turn
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: debugger
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: Simple Authorization for Rails
79
+ email: zetoeu@gmail.com
80
+ executables: []
81
+ extensions: []
82
+ extra_rdoc_files: []
83
+ files:
84
+ - README.md
85
+ - lib/allows.rb
86
+ - lib/exceptions.rb
87
+ - test/allows_test.rb
88
+ - Gemfile
89
+ - allows.gemspec
90
+ - Rakefile
91
+ homepage: http://github.com/zeto/allows
92
+ licenses: []
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubyforge_project:
111
+ rubygems_version: 1.8.24
112
+ signing_key:
113
+ specification_version: 3
114
+ summary: Simple Authorization library
115
+ test_files: []