allows 0.2.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/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: []