role_authorization 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.
@@ -0,0 +1,76 @@
1
+ module RoleAuthorization
2
+ class Mapper
3
+ def initialize(controller_klass)
4
+ @controller_klass = controller_klass
5
+ @rules = Hash.new do |h,k|
6
+ h[k] = Hash.new do |h1,k1|
7
+ h1[k1] = Array.new
8
+ end
9
+ end
10
+ self
11
+ end
12
+
13
+ def to_s
14
+ output = []
15
+ @rules.each_pair do |action, rules|
16
+ output << "Action :#{action}"
17
+ output << " allow roles #{rules[:roles].inspect}" unless rules[:roles].nil? || rules[:roles].empty?
18
+ rules[:rules].map {|rule| output << " #{rule.to_s}"} if rules.has_key?(:rules)
19
+ output << ""
20
+ output << ""
21
+ end
22
+
23
+ output.join("\n")
24
+ end
25
+
26
+ # special role rules
27
+ def all(options={}, &block)
28
+ options.assert_valid_keys(:only)
29
+ rule(:all, :role, options, &block)
30
+ end
31
+
32
+ def role(user_role, options={}, &block)
33
+ options.assert_valid_keys(:check, :only)
34
+ rule(user_role, :role, options, &block)
35
+ end
36
+
37
+ def authorized?(controller_instance, controller, action, id = nil)
38
+ rules = @rules[action]
39
+
40
+ return false if rules.empty?
41
+ return true if rules[:roles].include?(:all)
42
+ unless controller_instance.session[:access_rights].nil?
43
+ return true if !(rules[:roles] & controller_instance.session[:access_rights]).empty?
44
+ end
45
+
46
+ if rules.has_key?(:rules)
47
+ rules[:rules].each do |rule|
48
+ return true if rule.authorized?(controller_instance, controller, action, id)
49
+ end
50
+ end
51
+
52
+ return false
53
+ end
54
+
55
+ private
56
+
57
+ # rule method
58
+ def rule(user_role, type, options={}, &block)
59
+ actions = [options.delete(:only) || [:all]].flatten.collect {|v| v.to_sym}
60
+
61
+ case type
62
+ when :role
63
+ irule = nil
64
+ role_or_type = user_role
65
+ else
66
+ irule = "RoleAuthorization::Rules::#{type.to_s.camelize}".constantize.new(@controller_klass, options.merge(:role => user_role), &block)
67
+ role_or_type = type
68
+ end
69
+
70
+ actions.each do |action|
71
+ @rules[action][:roles] << role_or_type if irule.nil?
72
+ @rules[action][:rules] << irule unless irule.nil?
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,88 @@
1
+ module RoleAuthorization
2
+ # define our rule helper in Mapper
3
+ class Mapper
4
+ def access(options={}, &block)
5
+ options.assert_valid_keys(:resource, :only, :no_send)
6
+ rule(:access, :access, options, &block)
7
+ end
8
+ end
9
+
10
+ module Rules
11
+ class Access < Basic
12
+ def initialize(controller, options, &block)
13
+ @controller_klass = controller
14
+ @options = {:no_send => false}.merge(options)
15
+ @block = block
16
+ @mapper = nil
17
+
18
+ unless @block.nil?
19
+ @mapper = RoleAuthorization::Mapper.new(@controller_klass)
20
+ @mapper.instance_eval(&@block)
21
+ end
22
+ self
23
+ end
24
+
25
+ def to_s
26
+ output = ["allow current_user with access role of requested #{[controller_name.singularize, @options[:check]].compact.join('.')}"]
27
+ output << @mapper.to_s
28
+ end
29
+
30
+ def authorized?(controller_instance, controller, action, id)
31
+ object = find_object(controller_instance, controller, action, id)
32
+ unless object.nil?
33
+ return true if controller_instance.accessible?(object.access_role)
34
+ end
35
+
36
+ if !@mapper.nil? && object.try(:access_role).nil?
37
+ return true if @mapper.authorized?(controller_instance, controller, action, object)
38
+ end
39
+ return false
40
+ end
41
+
42
+ def find_object(controller_instance, controller, action, id)
43
+ object = nil
44
+ instance_found = false
45
+
46
+ if id.is_a?(Integer) || id.is_a?(String)
47
+ # id is a parameter passed in
48
+ # we use the :resource option to find the right instance variable
49
+ object = controller_instance.instance_variable_get('@' + @options[:resource].to_s) rescue nil
50
+ instance_found = true unless object.nil?
51
+
52
+ if object.nil? && controller_instance.instance_variable_get('@' + controller)
53
+ collection = controller_instance.instance_variable_get('@' + controller)
54
+ object = collection.detect {|item| item.andand.id == id.to_i}
55
+ end
56
+
57
+ if object.nil?
58
+ model = controller.singularize.camelize.constantize
59
+ if model.respond_to?(:to_param_column)
60
+ finder = "find_by_#{model.to_param_column}".to_sym
61
+ else
62
+ finder = :find_by_id
63
+ id = id.to_i
64
+ end
65
+
66
+ object = model.send(finder, id)
67
+ end
68
+
69
+ unless object.nil?
70
+ if @options.has_key?(:resource) && !@options[:no_send] && !instance_found && object.respond_to?(@options[:resource])
71
+ object = object.send(@options[:resource])
72
+ end
73
+ end
74
+ elsif id.is_a?(ActiveRecord::Base) && @options.has_key?(:resource)
75
+ # id is already a model record so this is a nested rule
76
+
77
+ # first try to find it as an instance variable
78
+ object = controller_instance.instance_variable_get('@' + @options[:resource].to_s) rescue nil
79
+
80
+ # next we call id's method to find it
81
+ object = id.send(@options[:resource]) if object.nil?
82
+ end
83
+
84
+ return object
85
+ end
86
+ end # Access
87
+ end
88
+ end
@@ -0,0 +1,22 @@
1
+ module RoleAuthorization
2
+ module Rules
3
+ class Basic
4
+ def initialize(controller, options, &block)
5
+ @controller_klass = controller
6
+ self
7
+ end
8
+
9
+ def to_s
10
+ "deny all (basic rule)"
11
+ end
12
+
13
+ def controller_name
14
+ @controller_klass.to_s.gsub('Controller', '')
15
+ end
16
+
17
+ def authorized?(controller_instance, controller, action, id)
18
+ return false
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,32 @@
1
+ module RoleAuthorization
2
+ # define our rule helper in Mapper
3
+ class Mapper
4
+ def custom(options={}, &block)
5
+ options.assert_valid_keys(:only, :description)
6
+ rule(:custom, :custom, options, &block)
7
+ end
8
+ end
9
+
10
+ module Rules
11
+ class Custom < Basic
12
+ def initialize(controller, options, &block)
13
+ @controller_klass = controller
14
+ @options = options
15
+ @block = block
16
+ self
17
+ end
18
+
19
+ def to_s
20
+ "allow when custom rule (#{@options[:description]}) returns true"
21
+ end
22
+
23
+ def authorized?(controller_instance, controller, action, id)
24
+ unless @block.nil?
25
+ result = @block.call(controller_instance)
26
+ return true unless result == false || result.nil?
27
+ end
28
+ return false
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,38 @@
1
+ module RoleAuthorization
2
+ # define our rule helper in Mapper
3
+ class Mapper
4
+ def logged_in(options={}, &block)
5
+ options.assert_valid_keys(:only)
6
+ rule(:logged_in, :logged_in, options, &block)
7
+ end
8
+ end
9
+
10
+ module Exts
11
+ module View
12
+ def logged_in(&block)
13
+ if block_given? && !current_user.anonymous?
14
+ capture_haml(&block)
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ module Rules
21
+ class LoggedIn < Basic
22
+ def initialize(controller, options, &block)
23
+ @controller_klass = controller
24
+ @options = options
25
+ self
26
+ end
27
+
28
+ def to_s
29
+ "allow when current_user is logged in (not anonymous)"
30
+ end
31
+
32
+ def authorized?(controller_instance, controller, action, id)
33
+ return true unless controller_instance.current_user.anonymous?
34
+ return false
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,51 @@
1
+ module RoleAuthorization
2
+ # define our rule helper in Mapper
3
+ class Mapper
4
+ def object_role(user_role, options={}, &block)
5
+ options.assert_valid_keys(:only, :resource, :type)
6
+ rule(user_role, :object_role, options, &block)
7
+ end
8
+ end
9
+
10
+ module Rules
11
+ class ObjectRole < Basic
12
+ def initialize(controller, options, &block)
13
+ @controller_klass = controller
14
+ @options = options
15
+ self
16
+ end
17
+
18
+ def to_s
19
+ if @options[:resource]
20
+ "allow when current_user has the role (#{@options[:role]}) for a specific object (#{@options[:resource]})"
21
+ else
22
+ "allow when current_user has the role (#{@options[:role]}) for any object of type #{@options[:type]}"
23
+ end
24
+ end
25
+
26
+ def authorized?(controller_instance, controller, action, id)
27
+ object = @options[:resource].nil? ? nil : find_object(controller_instance) if @options[:resource]
28
+
29
+ if object
30
+ return true if controller_instance.current_user.has_object_role?(object, @options[:role])
31
+ elsif @options[:type].constantize.respond_to?(:enrolled)
32
+ return true if @options[:type].constantize.enrolled(@options[:role]).include?(controller_instance.current_user)
33
+ end
34
+
35
+ return false
36
+ end
37
+
38
+ def find_object(controller_instance)
39
+ # try to find as instance variable
40
+ object = controller_instance.instance_variable_get("@#{@options[:resource]}".to_sym) rescue nil
41
+
42
+ # try to find based on params
43
+ if object.nil? && !controller_instance.params["#{@options[:resource]}_id"].blank?
44
+ object = @options[:type].constantize.find_by_id(controller_instance.params["#{@options[:resource]}_id"])
45
+ end
46
+
47
+ object
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,106 @@
1
+ module RoleAuthorization
2
+ # define our rule helper in Mapper
3
+ class Mapper
4
+ def resource(user_role, options={}, &block)
5
+ options.assert_valid_keys(:resource, :only, :no_send)
6
+ rule(user_role, :resource, options, &block)
7
+ end
8
+ end
9
+
10
+ module Rules
11
+ class Resource < Basic
12
+ def initialize(controller, options, &block)
13
+ @controller_klass = controller
14
+ @options = {:no_send => false}.merge(options)
15
+ @block = block
16
+ @mapper = nil
17
+
18
+ unless @block.nil?
19
+ @mapper = RoleAuthorization::Mapper.new(@controller_klass)
20
+ @mapper.instance_eval(&@block)
21
+ end
22
+ self
23
+ end
24
+
25
+ def to_s
26
+ output = ["allow current_user with role :#{@options[:role]} of requested resource #{@options[:resource]}"]
27
+ output << @mapper.to_s
28
+ end
29
+
30
+ def authorized?(controller_instance, controller, action, id)
31
+ object = find_object(controller_instance, controller, action, id)
32
+ return true if controller_instance.current_user.has_object_role?(@options[:role], object) unless object.nil?
33
+
34
+ unless @mapper.nil?
35
+ return true if @mapper.authorized?(controller_instance, controller, action, object)
36
+ end
37
+
38
+ return false
39
+ end
40
+
41
+ def find_object(controller_instance, controller, action, id)
42
+ object = nil
43
+ instance_found = false
44
+
45
+ if id.is_a?(Integer) || id.is_a?(String)
46
+ # id is a parameter passed in
47
+ # we use the :resource option to find the right instance variable
48
+ object = controller_instance.instance_variable_get('@' + @options[:resource].to_s) rescue nil
49
+ instance_found = true unless object.nil?
50
+
51
+ if controller_instance.instance_variable_defined?('@' + controller)
52
+ collection = controller_instance.instance_variable_get('@' + controller)
53
+ object = collection.detect {|item| item.andand.id == id.to_i}
54
+ end
55
+
56
+ if object.nil?
57
+ model = controller.singularize.camelize.constantize
58
+ if model.respond_to?(:to_param_column)
59
+ finder = "find_by_#{model.to_param_column}".to_sym
60
+ else
61
+ finder = :find_by_id
62
+ id = id.to_i
63
+ end
64
+
65
+ object = model.send(finder, id)
66
+ end
67
+
68
+ unless object.nil?
69
+ if @options.has_key?(:resource) && !@options[:no_send] && !instance_found && object.respond_to?(@options[:resource])
70
+ object = object.send(@options[:resource])
71
+ end
72
+ end
73
+ elsif id.is_a?(ActiveRecord::Base) && @options.has_key?(:resource)
74
+ # id is already a model record so this is a nested rule
75
+
76
+ # first try to find it as an instance variable
77
+ object = controller_instance.instance_variable_get('@' + @options[:resource].to_s) rescue nil
78
+
79
+ if id.respond_to?("#{@options[:resource]}_id") && controller_instance.instance_variable_defined?('@' + @options[:resource].to_s.pluralize)
80
+ collection = controller_instance.instance_variable_get('@' + @options[:resource].to_s.pluralize)
81
+ object = collection.detect {|item| item.andand.id == id.send("#{@options[:resource]}_id")}
82
+ end
83
+
84
+ # next we call id's method to find it
85
+ object = id.send(@options[:resource]) if object.nil?
86
+ elsif id.nil?
87
+ # no id means we must be using an association or parent resource for this rule
88
+
89
+ if @options.has_key?(:resource)
90
+ object_base = @options[:resource].to_s
91
+ object_id = controller_instance.params["#{object_base}_id".to_sym]
92
+
93
+ unless object_id.nil?
94
+ object = controller_instance.instance_variable_get('@' + object_base) rescue nil
95
+ object = nil unless object.id == object_id
96
+
97
+ object = object_base.to_s.camelize.constantize.find_by_id(object_id.to_i) if object.nil?
98
+ end
99
+ end
100
+ end
101
+
102
+ return object
103
+ end # find object
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,70 @@
1
+ module RoleAuthorization
2
+ # define our rule helper in Mapper
3
+ class Mapper
4
+ def user(options={}, &block)
5
+ options.assert_valid_keys(:check, :only, :resource, :association)
6
+ rule(:user, :user, options, &block)
7
+ end
8
+ end
9
+
10
+ module Rules
11
+ class User < Basic
12
+ def initialize(controller, options, &block)
13
+ @controller_klass = controller
14
+ @options = options
15
+ self
16
+ end
17
+
18
+ def to_s
19
+ "allow when current_user.id == #{[@options[:resource], @options[:association], @options[:check]].compact.join('.')}"
20
+ end
21
+
22
+ def authorized?(controller_instance, controller, action, id)
23
+ object = find_object(controller_instance, controller, action, id)
24
+
25
+ unless object.nil?
26
+ [object].flatten.each do |obj|
27
+ return true if controller_instance.current_user.owns?(obj.send(@options[:check]))
28
+ end
29
+ end
30
+
31
+ return false
32
+ end
33
+
34
+ def find_object(controller_instance, controller, action, id)
35
+ object = nil
36
+
37
+ if id.nil? && !@options[:resource].nil?
38
+ if controller_instance.instance_variable_defined?('@' + @options[:resource].to_s)
39
+ object = controller_instance.instance_variable_get('@' + @options[:resource].to_s)
40
+ end
41
+ model = @options[:resource].to_s.camelize.constantize
42
+ elsif id.is_a?(Integer) || id.is_a?(String)
43
+ if controller_instance.instance_variable_defined?('@' + controller)
44
+ collection = controller_instance.instance_variable_get('@' + controller)
45
+ object = collection.detect {|item| item.andand.id == id.to_i}
46
+ end
47
+ model = controller.singularize.camelize.constantize
48
+ elsif id.is_a?(ActiveRecord::Base) && @options.has_key?(:check)
49
+ object = id
50
+ end
51
+
52
+ if object.nil?
53
+ if model.respond_to?(:to_param_column)
54
+ finder = "find_by_#{model.to_param_column}".to_sym
55
+ else
56
+ finder = :find_by_id
57
+ id = id.to_i
58
+ end
59
+ object = model.send(finder, id)
60
+ end
61
+
62
+ unless object.nil? || @options[:check].nil?
63
+ object = @options[:association].nil? ? object : object.send(@options[:association])
64
+ end
65
+
66
+ object
67
+ end
68
+ end # User
69
+ end
70
+ end
@@ -0,0 +1,39 @@
1
+ module RoleAuthorization
2
+ module Ruleset
3
+ def self.included(base)
4
+ base.send :extend, ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+
9
+ def cattr_ruleset(*syms)
10
+ syms.each do |sym|
11
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
12
+ unless defined? @@#{sym}
13
+ @@#{sym} = Hash.new
14
+ end
15
+
16
+ def self.#{sym}
17
+ @@#{sym}
18
+ end
19
+
20
+ def self.#{sym}=(obj)
21
+ @@#{sym} = obj
22
+ end
23
+
24
+ def self.add_to_#{sym}(name, set = nil, &block)
25
+ ruleset = self.#{sym}
26
+ if block_given?
27
+ ruleset[name] = RoleAuthorization::Mapper.new(self)
28
+ ruleset[name].instance_eval(&block)
29
+ elsif !set.nil?
30
+ ruleset[name] = set
31
+ end
32
+ self.#{sym} = ruleset
33
+ end
34
+ EOS
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ module RoleAuthorization
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,3 @@
1
+ require 'role_authorization/base'
2
+ require 'rails/role_authorization' if defined?(Rails)
3
+
@@ -0,0 +1,30 @@
1
+ class UserRoles < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :user_roles do |t|
4
+ t.string :name
5
+ t.string :display_name
6
+ t.integer :priority
7
+
8
+ t.references :roleable, :polymorphic => true
9
+ t.timestamps
10
+ end
11
+
12
+ create_table :user_role_mappings do |t|
13
+ t.belongs_to :user
14
+ t.belongs_to :user_role
15
+ t.timestamps
16
+ end
17
+
18
+ add_index :user_roles, [:roleable_id, :roleable_type]
19
+ add_index :user_roles, [:roleable_id, :roleable_type, :name]
20
+ add_index :user_role_mappings, [:user_id]
21
+ add_index :user_role_mappings, [:user_role_id]
22
+
23
+ public_access = UserRole.create(:name => "public", :display_name => "Public Access", :priority => 600)
24
+ end
25
+
26
+ def self.down
27
+ drop_table :user_roles
28
+ drop_table :user_role_mappings
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "role_authorization/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "role_authorization"
6
+ s.version = RoleAuthorization::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["John 'asceth' Long"]
9
+ s.email = ["machinist@asceth.com"]
10
+ s.homepage = "http://github.com/asceth/role_authorization"
11
+ s.summary = "Role Authorization gem for Rails"
12
+ s.description = "A gem for handling authorization in rails using roles"
13
+
14
+ s.rubyforge_project = "role_authorization"
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_development_dependency 'rspec'
22
+ s.add_development_dependency 'rr'
23
+ end