role_authorization 0.1.6 → 0.2.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.
Files changed (32) hide show
  1. data/Gemfile.lock +1 -1
  2. data/lib/rails/role_authorization.rb +9 -1
  3. data/lib/role_authorization/active_record.rb +7 -0
  4. data/lib/role_authorization/{allow_group.rb → controller/allow_group.rb} +0 -0
  5. data/lib/role_authorization/controller/mapper.rb +44 -0
  6. data/lib/role_authorization/{ruleset.rb → controller/ruleset.rb} +3 -5
  7. data/lib/role_authorization/controller.rb +117 -0
  8. data/lib/role_authorization/roles/manager.rb +84 -0
  9. data/lib/role_authorization/roles/role.rb +66 -0
  10. data/lib/role_authorization/roles/role_group.rb +16 -0
  11. data/lib/role_authorization/roles.rb +14 -0
  12. data/lib/role_authorization/rules/defaults.rb +25 -0
  13. data/lib/role_authorization/rules/rule.rb +33 -0
  14. data/lib/role_authorization/rules.rb +12 -0
  15. data/lib/role_authorization/user.rb +121 -0
  16. data/lib/role_authorization/version.rb +1 -1
  17. data/lib/role_authorization/view_security.rb +114 -0
  18. data/lib/role_authorization.rb +61 -1
  19. metadata +16 -17
  20. data/lib/role_authorization/base.rb +0 -116
  21. data/lib/role_authorization/exts/controller.rb +0 -126
  22. data/lib/role_authorization/exts/model.rb +0 -126
  23. data/lib/role_authorization/exts/session.rb +0 -52
  24. data/lib/role_authorization/exts/user.rb +0 -58
  25. data/lib/role_authorization/exts/view.rb +0 -77
  26. data/lib/role_authorization/mapper.rb +0 -76
  27. data/lib/role_authorization/rules/access.rb +0 -88
  28. data/lib/role_authorization/rules/basic.rb +0 -22
  29. data/lib/role_authorization/rules/custom.rb +0 -32
  30. data/lib/role_authorization/rules/object_role.rb +0 -51
  31. data/lib/role_authorization/rules/resource.rb +0 -106
  32. data/lib/role_authorization/rules/user.rb +0 -70
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- role_authorization (0.1.3)
4
+ role_authorization (0.1.5)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -1,7 +1,15 @@
1
1
  module RoleAuthorization
2
2
  class Railtie < Rails::Railtie
3
3
  initializer "role_authorization.initialize" do |app|
4
- RoleAuthorization.enable
4
+ RoleAuthorization.load_rules
5
+ ::ActiveRecord::Base.send :extend, RoleAuthorization::ActiveRecord if defined?(::ActiveRecord)
6
+ end
7
+
8
+ # runs before every request in development
9
+ # and once in production before serving requests
10
+ # http://www.engineyard.com/blog/2010/extending-rails-3-with-railties
11
+ config.to_prepare do
12
+ RoleAuthorization::Roles.manager.try(:persist!)
5
13
  end
6
14
  end
7
15
  end
@@ -0,0 +1,7 @@
1
+ module RoleAuthorization
2
+ module ActiveRecord
3
+ def acts_as_role_manager
4
+ RoleAuthorization::Roles.manager.setup(self)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,44 @@
1
+ module RoleAuthorization
2
+ class Mapper
3
+ def initialize
4
+ @rules = Hash.new do |h,k|
5
+ h[k] = Array.new
6
+ end
7
+ self
8
+ end
9
+
10
+ def to_s
11
+ output = []
12
+ @rules.each_pair do |action, rules|
13
+ output << "Action :#{action}"
14
+ rules.map {|rule| output << " #{rule.to_s}"}
15
+ output << ""
16
+ output << ""
17
+ end
18
+
19
+ output.join("\n")
20
+ end
21
+
22
+ def add_to_rules(rule_name, *options, &block)
23
+ rule = RoleAuthorization::Rules::Rule.new(*options, &block)
24
+
25
+ actions = ([rule.options[:only] || [:all]]).flatten.map(&:to_sym)
26
+
27
+ actions.map do |action|
28
+ @rules[action] << rule
29
+ end
30
+ end
31
+
32
+ def authorized?(controller_instance, controller, action, id = nil)
33
+ rules = @rules[action]
34
+
35
+ return false if rules.empty?
36
+
37
+ rules.map do |rule|
38
+ return true if rule.authorized?(controller_instance, controller, action, id)
39
+ end
40
+
41
+ return false
42
+ end
43
+ end
44
+ end
@@ -9,22 +9,20 @@ module RoleAuthorization
9
9
  def cattr_ruleset(*syms)
10
10
  syms.each do |sym|
11
11
  class_eval(<<-EOS, __FILE__, __LINE__ + 1)
12
- unless defined? @@#{sym}
13
- @@#{sym} = Hash.new
14
- end
15
-
16
12
  def self.#{sym}
13
+ @@#{sym} ||= Hash.new
17
14
  @@#{sym}
18
15
  end
19
16
 
20
17
  def self.#{sym}=(obj)
18
+ @@#{sym} ||= Hash.new
21
19
  @@#{sym} = obj
22
20
  end
23
21
 
24
22
  def self.add_to_#{sym}(name, set = nil, &block)
25
23
  ruleset = self.#{sym}
26
24
  if block_given?
27
- ruleset[name] = RoleAuthorization::Mapper.new(self)
25
+ ruleset[name] = RoleAuthorization::Mapper.new
28
26
  ruleset[name].instance_eval(&block)
29
27
  elsif !set.nil?
30
28
  ruleset[name] = set
@@ -0,0 +1,117 @@
1
+ module RoleAuthorization
2
+ module Controller
3
+ def self.included(base)
4
+ base.class_eval do
5
+ helper_method :authorized?
6
+ helper_method :accessible?
7
+ end
8
+ base.send :extend, RoleAuthorization::Ruleset::ClassMethods
9
+ base.send :cattr_ruleset, :ruleset, :allowable_groups
10
+
11
+ base.send :extend, ClassMethods
12
+ base.send :include, InstanceMethods
13
+ end
14
+
15
+ module ClassMethods
16
+ def allow_group(*args)
17
+ add_to_allowable_groups(self.controller_rule_name, args)
18
+ add_role_authorization_filter
19
+ end
20
+
21
+ def allow(&block)
22
+ add_to_ruleset(self.controller_rule_name, &block)
23
+ add_role_authorization_filter
24
+ end
25
+
26
+ def add_role_authorization_filter
27
+ callbacks = _process_action_callbacks
28
+ chain = callbacks.select {|cl| cl.klass.to_s.include?(name)}.collect(&:filter).select {|c| c.is_a?(Symbol)}
29
+ before_filter :check_request_authorization unless chain.include?(:check_request_authorization)
30
+ end
31
+
32
+ def controller_rule_name
33
+ @controller_rule_name ||= name.gsub('Controller', '').underscore.downcase
34
+ end
35
+
36
+ def controller_model
37
+ @controller_model ||= name.gsub('Controller', '').singularize
38
+ end
39
+ end # ClassMethods
40
+
41
+ module InstanceMethods
42
+ def check_request_authorization
43
+ unless authorized_action?(self, self.class.controller_rule_name, action_name.to_sym, params[:id])
44
+ raise SecurityError, "You do not have the required clearance to access this resource."
45
+ end
46
+ end
47
+
48
+ def authorized_action?(controller_klass, controller, action, id = nil)
49
+ # by default admins see everything
50
+ return true if admin?
51
+
52
+ ruleset = self.class.ruleset[controller]
53
+ groups = RoleAuthorization::AllowGroup.get(self.class.allowable_groups[controller])
54
+
55
+ if defined?(::DEBUG_AUTHORIZATION_RULES) == 'constant'
56
+ Rails.logger.info "#" * 30
57
+ Rails.logger.info controller.to_s
58
+ Rails.logger.info ruleset.to_s
59
+ Rails.logger.info "#" * 30
60
+ end
61
+
62
+ # we have no ruleset for this controller or any allow groups so deny
63
+ return false if ruleset.nil? && groups.empty?
64
+
65
+ # first check controller ruleset
66
+ unless ruleset.nil?
67
+ return true if ruleset.authorized?(controller_klass, controller, :all, id)
68
+ return true if ruleset.authorized?(controller_klass, controller, action, id)
69
+ end
70
+
71
+ # next check any allow groups
72
+ unless groups.empty?
73
+ groups.each do |group|
74
+ return true if group.authorized?(controller_klass, controller, :all, id)
75
+ return true if group.authorized?(controller_klass, controller, action, id)
76
+ end
77
+ end
78
+
79
+ # finally deny if they haven't passed any rules
80
+ return false
81
+ end
82
+
83
+ def authorized?(url, method = nil)
84
+ return false unless url
85
+ return true if admin?
86
+
87
+ method ||= (params[:method] || request.method)
88
+ url_parts = URI::split(url.strip)
89
+ path = url_parts[5]
90
+
91
+ begin
92
+ hash = Rails.application.routes.recognize_path(path, :method => method)
93
+ return authorized_action?(self, hash[:controller], hash[:action].to_sym, hash[:id]) if hash
94
+ rescue Exception => e
95
+ Rails.logger.error e.inspect
96
+ e.backtrace.each {|line| Rails.logger.error line }
97
+ # continue on
98
+ end
99
+
100
+ # Mailto link
101
+ return true if url =~ /^mailto:/
102
+
103
+ # Public file
104
+ file = File.join(Rails.root, 'public', url)
105
+ return true if File.exists?(file)
106
+
107
+ # Passing in different domain
108
+ return remote_url?(url_parts[2])
109
+ end
110
+
111
+ def remote_url?(domain = nil)
112
+ return false if domain.nil? || domain.strip.length == 0
113
+ request.host.downcase != domain.downcase
114
+ end
115
+ end # InstanceMethods
116
+ end
117
+ end
@@ -0,0 +1,84 @@
1
+ module RoleAuthorization
2
+ module Roles
3
+ class Manager
4
+ attr_accessor :global_roles, :object_roles
5
+ attr_accessor :group_definitions, :groups
6
+ attr_accessor :nicknames, :creations
7
+ attr_accessor :klass
8
+
9
+ def initialize
10
+ @global_roles = {}
11
+ @object_roles = []
12
+ @groups = Hash.new
13
+ @creations = Hash.new
14
+ @nicknames = Hash.new {|hash, key| key}
15
+
16
+ self
17
+ end
18
+
19
+ module InstanceMethods
20
+ def setup(klass)
21
+ @klass = klass
22
+ klass.send(:include, RoleAuthorization::Roles::Role)
23
+
24
+ # now that we know what class to use, create our role groups
25
+ @group_definitions.each_pair do |group_name, roles|
26
+ @groups[group_name.to_sym] = RoleAuthorization::Roles::RoleGroup.new(klass, roles)
27
+ end
28
+ end
29
+
30
+ def roles(*options)
31
+ @global_roles, @object_roles = if options.last.is_a?(Hash)
32
+ [options.pop, options].reverse
33
+ else
34
+ [options, {}]
35
+ end
36
+ end
37
+
38
+ def creation_rules(rules)
39
+ rules.each_pair do |key, allowed_roles|
40
+ @creations[key] = allowed_roles.flatten.uniq
41
+ end
42
+ end
43
+
44
+ def group(groups)
45
+ @group_definitions = groups
46
+ end
47
+
48
+ def nickname(nicknames)
49
+ @nicknames = nicknames
50
+ end
51
+
52
+ def any(new_scope = nil)
53
+ case new_scope
54
+ when nil
55
+ [global_roles, object_roles.values].flatten
56
+ when :global
57
+ global_roles
58
+ else
59
+ object_roles[new_scope]
60
+ end
61
+ end
62
+
63
+ # make sure our defined roles are in the database
64
+ # remove any roles taken out
65
+ def persist!
66
+ return if klass.nil?
67
+ return unless klass.new.respond_to?(:nickname)
68
+
69
+ persisted_roles = klass.all.inject({}) {|hash, record| hash[record.name.to_sym] = record; hash}
70
+
71
+ [global_roles, object_roles.values].flatten.map do |role_name|
72
+ if persisted_roles.delete(role_name).nil?
73
+ klass.create(:name => role_name, :nickname => nicknames[role_name])
74
+ end
75
+ end
76
+
77
+ # if we have persisted roles left we delete them
78
+ persisted_roles.values.map(&:destroy)
79
+ end
80
+ end
81
+ include InstanceMethods
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,66 @@
1
+ module RoleAuthorization
2
+ module Roles
3
+ module Role
4
+ def self.included(base)
5
+ base.send :extend, ClassMethods
6
+ base.send :include, InstanceMethods
7
+ base.class_eval do
8
+ validates_uniqueness_of :name
9
+ serialize :user_ids
10
+ end
11
+ end
12
+
13
+ module InstanceMethods
14
+ def users(scope = nil)
15
+ if user_ids.is_a?(Hash)
16
+ User.where(:id => user_ids[scope])
17
+ else
18
+ User.where(:id => user_ids)
19
+ end
20
+ end
21
+
22
+ def add_user(user_id, scope = nil)
23
+ unserialized_user_ids = self.user_ids
24
+
25
+ if scope.nil? || scope.is_a?(Symbol) || scope.is_a?(String) || scope.is_a?(Class)
26
+ unserialized_user_ids ||= Array.new
27
+ unserialized_user_ids << user_id
28
+ unserialized_user_ids.uniq!
29
+ else
30
+ unserialized_user_ids ||= Hash.new
31
+ unserialized_user_ids[scope.id] ||= Array.new
32
+ unserialized_user_ids[scope.id] << user_id
33
+ unserialized_user_ids[scope.id].uniq!
34
+ end
35
+
36
+ self.user_ids = unserialized_user_ids
37
+
38
+ save
39
+ end
40
+
41
+ def remove_user(user_id, scope = nil)
42
+ unserialized_user_ids = self.user_ids
43
+
44
+ if scope.nil? || scope.is_a?(Symbol) || scope.is_a?(String) || scope.is_a?(Class)
45
+ unserialized_user_ids ||= Array.new
46
+ unserialized_user_ids.delete(user_id)
47
+ else
48
+ unserialized_user_ids ||= Hash.new
49
+ unserialized_user_ids[scope.id] ||= Array.new
50
+ unserialized_user_ids[scope.id].delete(user_id)
51
+ end
52
+
53
+ self.user_ids = unserialized_user_ids
54
+
55
+ save
56
+ end
57
+ end
58
+
59
+ module ClassMethods
60
+ def group(group_name)
61
+ RoleAuthorization::Roles.manager.groups[group_name.to_sym]
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,16 @@
1
+ module RoleAuthorization
2
+ module Roles
3
+ class RoleGroup
4
+ attr_accessor :klass, :roles
5
+
6
+ def initialize(klass, roles)
7
+ @klass = klass
8
+ @roles = roles
9
+ end
10
+
11
+ def users
12
+ klass.find_all_by_name(roles).map(&:users)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ module RoleAuthorization
2
+ module Roles
3
+ module ClassMethods
4
+ def configure(&block)
5
+ (@role_manager ||= RoleAuthorization::Roles::Manager.new).instance_eval(&block)
6
+ end
7
+
8
+ def manager
9
+ @role_manager
10
+ end
11
+ end
12
+ extend ClassMethods
13
+ end
14
+ end
@@ -0,0 +1,25 @@
1
+ RoleAuthorization::Rules.define :all do
2
+ true
3
+ end
4
+
5
+ RoleAuthorization::Rules.define :role do
6
+ controller_instance.current_user.roles(options[:scope] || :global).include?(options[:role])
7
+ end
8
+
9
+ RoleAuthorization::Rules.define :user do
10
+ resource = controller_instance.instance_variable_get("@#{options[:resource]}".to_sym)
11
+
12
+ if resource.nil?
13
+ false
14
+ else
15
+ controller_instance.current_user.try(:id) == resource.try(options[:check])
16
+ end
17
+ end
18
+
19
+ RoleAuthorization::Rules.define :custom do
20
+ unless options[:block].nil?
21
+ true if options[:block].call(controller_instance) == true
22
+ else
23
+ false
24
+ end
25
+ end
@@ -0,0 +1,33 @@
1
+ module RoleAuthorization
2
+ module Rules
3
+ class Rule
4
+ attr_accessor :role, :options
5
+ attr_accessor :returning
6
+
7
+ # for calls to authorized?
8
+ attr_accessor :controller_instance, :controller, :action, :id
9
+
10
+ def initialize(*options, &block)
11
+ @returning = block
12
+ @options, @role = if options.is_a?(Hash)
13
+ [options, nil]
14
+ elsif options.last.is_a?(Hash)
15
+ [options.pop, options.first]
16
+ else
17
+ [{}, options.first]
18
+ end
19
+
20
+ self
21
+ end
22
+
23
+ def authorized?(*args)
24
+ @controller_instance, @controller, @action, @id = args
25
+
26
+ instance_eval(&returning)
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+
33
+
@@ -0,0 +1,12 @@
1
+ module RoleAuthorization
2
+ module Rules
3
+ module ClassMethods
4
+ def define(rule_name, &block)
5
+ RoleAuthorization::Mapper.send(:define_method, rule_name) do |*args|
6
+ add_to_rules(rule_name, *args, &block)
7
+ end
8
+ end
9
+ end
10
+ extend ClassMethods
11
+ end
12
+ end
@@ -0,0 +1,121 @@
1
+ module RoleAuthorization
2
+ module User
3
+ def self.included(base)
4
+ base.send :extend, ClassMethods
5
+ base.send :include, InstanceMethods
6
+
7
+ base.class_eval do
8
+ serialize :serialized_roles
9
+ end
10
+ end
11
+
12
+ module ClassMethods
13
+ def enroll(user_id, role_name)
14
+ user = find_by_id(user_id.to_i)
15
+ user.enroll(role_name) unless user.nil?
16
+ end # enroll
17
+
18
+ def withdraw(user_id, role_name)
19
+ user = find_by_id(user_id.to_i)
20
+ user.withdraw(role_name) unless user.nil?
21
+ end # withdraw
22
+ end # ClassMethods
23
+
24
+ module InstanceMethods
25
+ def scope_with(scope = nil)
26
+ return [nil, nil] if scope.nil?
27
+
28
+ if scope.is_a?(Symbol) || scope.is_a?(String)
29
+ [scope, nil]
30
+ elsif scope.is_a?(Class)
31
+ [scope.to_s.downcase.to_sym, nil]
32
+ else
33
+ [scope.class.to_s.downcase.to_sym, scope.id]
34
+ end
35
+ end
36
+
37
+ def roles(scope = nil)
38
+ scope, scope_id = scope_with(scope)
39
+
40
+ (serialized_roles || {}).inject([]) do |array, (key, value)|
41
+ if key == :global && scope.nil?
42
+ array << value
43
+ else
44
+ if scope.nil? || (key == scope.to_sym && scope_id.nil?)
45
+ array << value.values
46
+ else
47
+ array << value[scope_id]
48
+ end
49
+ end
50
+
51
+ array
52
+ end.flatten.uniq
53
+ end
54
+
55
+ def has_role?(role, scope = nil)
56
+ roles(scope).include?(role)
57
+ end
58
+
59
+ # adds a role to the user
60
+ def enroll(role_name, scope = nil)
61
+ return true if has_role?(role_name.to_sym, scope)
62
+
63
+ scope, scope_id = scope_with(scope)
64
+ self.serialized_roles ||= Hash.new
65
+
66
+ if scope.nil?
67
+ self.serialized_roles[:global] ||= Array.new
68
+ self.serialized_roles[:global] << role_name.to_sym
69
+ else
70
+ if scope_id.nil?
71
+ self.serialized_roles[scope] ||= Array.new
72
+ self.serialized_roles[scope] << role_name.to_sym
73
+ else
74
+ self.serialized_roles[scope] ||= Hash.new
75
+ self.serialized_roles[scope][scope_id] ||= Array.new
76
+ self.serialized_roles[scope][scope_id] << role_name.to_sym
77
+ end
78
+ end
79
+
80
+ if save
81
+ RoleAuthorization::Roles.manager.klass.find_by_name(role_name).add_user(self.id, scope)
82
+ true
83
+ else
84
+ false
85
+ end
86
+ end
87
+
88
+ def withdraw(role_name, scope = nil)
89
+ return true unless has_role?(role_name.to_sym, scope)
90
+
91
+ scope, scope_id = scope_with(scope)
92
+ serialized_roles ||= Hash.new
93
+
94
+ if scope.nil?
95
+ self.serialized_roles[:global] ||= Array.new
96
+ self.serialized_roles[:global].delete(role_name.to_sym)
97
+ else
98
+ if scope_id.nil?
99
+ self.serialized_roles[scope] ||= Array.new
100
+ self.serialized_roles[scope].delete(role_name.to_sym)
101
+ else
102
+ self.serialized_roles[scope] ||= Hash.new
103
+ self.serialized_roles[scope][scope_id] ||= Array.new
104
+ self.serialized_roles[scope][scope_id].delete(role_name.to_sym)
105
+ end
106
+ end
107
+
108
+ if save
109
+ RoleAuthorization::Roles.manager.klass.find_by_name(role_name).remove_user(self.id, scope)
110
+ true
111
+ else
112
+ false
113
+ end
114
+ end
115
+
116
+ def admin?
117
+ has_role?(:all, :global)
118
+ end
119
+ end # InstanceMethods
120
+ end
121
+ end
@@ -1,3 +1,3 @@
1
1
  module RoleAuthorization
2
- VERSION = "0.1.6"
2
+ VERSION = "0.2.0"
3
3
  end