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.
- data/.gemtest +1 -0
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +8 -0
- data/Rakefile +19 -0
- data/lib/rails/role_authorization.rb +8 -0
- data/lib/role_authorization/allow_group.rb +16 -0
- data/lib/role_authorization/base.rb +116 -0
- data/lib/role_authorization/exts/controller.rb +127 -0
- data/lib/role_authorization/exts/model.rb +126 -0
- data/lib/role_authorization/exts/session.rb +52 -0
- data/lib/role_authorization/exts/user.rb +58 -0
- data/lib/role_authorization/exts/view.rb +77 -0
- data/lib/role_authorization/mapper.rb +76 -0
- data/lib/role_authorization/rules/access.rb +88 -0
- data/lib/role_authorization/rules/basic.rb +22 -0
- data/lib/role_authorization/rules/custom.rb +32 -0
- data/lib/role_authorization/rules/logged_in.rb +38 -0
- data/lib/role_authorization/rules/object_role.rb +51 -0
- data/lib/role_authorization/rules/resource.rb +106 -0
- data/lib/role_authorization/rules/user.rb +70 -0
- data/lib/role_authorization/ruleset.rb +39 -0
- data/lib/role_authorization/version.rb +3 -0
- data/lib/role_authorization.rb +3 -0
- data/migrations/01_user_roles.rb +30 -0
- data/role_authorization.gemspec +23 -0
- metadata +106 -0
data/.gemtest
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.2@gems
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 John "asceth" Long
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
'Software'), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
17
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
18
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
19
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
20
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "bundler"
|
2
|
+
Bundler.setup
|
3
|
+
|
4
|
+
require "rspec"
|
5
|
+
require "rspec/core/rake_task"
|
6
|
+
|
7
|
+
Rspec::Core::RakeTask.new(:spec)
|
8
|
+
|
9
|
+
gemspec = eval(File.read(File.join(Dir.pwd, "role_authorization.gemspec")))
|
10
|
+
|
11
|
+
task :build => "#{gemspec.full_name}.gem"
|
12
|
+
|
13
|
+
task :test => :spec
|
14
|
+
|
15
|
+
file "#{gemspec.full_name}.gem" => gemspec.files + ["role_authorization.gemspec"] do
|
16
|
+
system "gem build role_authorization.gemspec"
|
17
|
+
system "gem install role_authorization-#{RoleAuthorization::VERSION}.gem"
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module RoleAuthorization
|
2
|
+
module AllowGroup
|
3
|
+
include RoleAuthorization::Ruleset
|
4
|
+
cattr_ruleset :ruleset
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def define(name, &block)
|
8
|
+
add_to_ruleset(name, &block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def get(*names)
|
12
|
+
ruleset.values_at(names).compact
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module RoleAuthorization
|
2
|
+
class << self
|
3
|
+
# shortcut for <tt>enable_actionpack; enable_activerecord</tt>
|
4
|
+
def enable
|
5
|
+
# load rule mapper
|
6
|
+
load 'role_authorization/mapper.rb'
|
7
|
+
load 'role_authorization/ruleset.rb'
|
8
|
+
load 'role_authorization/allow_group.rb'
|
9
|
+
load 'role_authorization/rules/basic.rb'
|
10
|
+
|
11
|
+
# load default rules
|
12
|
+
Dir.chdir(File.dirname(__FILE__)) do
|
13
|
+
Dir["rules/*.rb"].each do |rule_definition|
|
14
|
+
require "#{File.dirname(__FILE__)}/#{rule_definition}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# load application rules
|
19
|
+
Dir.chdir(Rails.root) do
|
20
|
+
Dir["lib/rules/*.rb"].each do |rule_definition|
|
21
|
+
require "#{Rails.root}/#{rule_definition}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# load allow groups
|
26
|
+
Dir.chdir(Rails.root) do
|
27
|
+
Dir["lib/allow_groups/*.rb"].each do |allow_group|
|
28
|
+
require "#{Rails.root}/#{allow_group}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
enable_actionpack
|
33
|
+
enable_activerecord
|
34
|
+
end
|
35
|
+
|
36
|
+
def enable_actionpack
|
37
|
+
load 'role_authorization/exts/view.rb'
|
38
|
+
unless ActionView::Base.instance_methods.include? :link_to_or_show
|
39
|
+
ActionView::Base.class_eval { include Exts::View }
|
40
|
+
end
|
41
|
+
|
42
|
+
load 'role_authorization/exts/session.rb'
|
43
|
+
load 'role_authorization/exts/controller.rb'
|
44
|
+
unless ActionController::Base.instance_methods.include? :authorized?
|
45
|
+
ActionController::Base.class_eval { include Exts::Session }
|
46
|
+
ActionController::Base.class_eval { include Exts::Controller }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def enable_activerecord
|
51
|
+
load 'role_authorization/exts/model.rb'
|
52
|
+
unless ActiveRecord::Base.instance_methods.include? :roleable
|
53
|
+
ActiveRecord::Base.class_eval { include Exts::Model }
|
54
|
+
end
|
55
|
+
|
56
|
+
load 'role_authorization/exts/user.rb'
|
57
|
+
end
|
58
|
+
|
59
|
+
def load_controller_classes
|
60
|
+
@controller_classes = {}
|
61
|
+
|
62
|
+
maybe_load_framework_controller_parent
|
63
|
+
|
64
|
+
Dir.chdir("#{Rails.root}/app/controllers") do
|
65
|
+
Dir["**/*.rb"].sort.each do |c|
|
66
|
+
next if c.include?("application")
|
67
|
+
rola_load(c)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# if ENV['RAILS_ENV'] != 'production'
|
72
|
+
# if ActiveSupport.const_defined?("Dependencies")
|
73
|
+
# ActiveSupport::Dependencies.clear
|
74
|
+
# else
|
75
|
+
# Dependencies.clear
|
76
|
+
# end
|
77
|
+
# end
|
78
|
+
end
|
79
|
+
|
80
|
+
def maybe_load_framework_controller_parent
|
81
|
+
if ::Rails::VERSION::MAJOR >= 3 || (::Rails::VERSION::MAJOR >= 2 && ::Rails::VERSION::MINOR >= 3)
|
82
|
+
filename = "application_controller.rb"
|
83
|
+
else
|
84
|
+
filename = "application.rb"
|
85
|
+
end
|
86
|
+
require_or_load(filename)
|
87
|
+
end
|
88
|
+
|
89
|
+
def rola_load(filename)
|
90
|
+
klass = class_name_from_file(filename)
|
91
|
+
require_or_load(filename)
|
92
|
+
@controller_classes[klass] = qualified_const_get(klass)
|
93
|
+
end
|
94
|
+
|
95
|
+
def require_or_load(filename)
|
96
|
+
if ActiveSupport.const_defined?("Dependencies")
|
97
|
+
ActiveSupport::Dependencies.require_or_load(filename)
|
98
|
+
else
|
99
|
+
Dependencies.require_or_load(filename)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def class_name_from_file(str)
|
104
|
+
str.split(".")[0].split("/").collect{|s| s.camelize }.join("::")
|
105
|
+
end
|
106
|
+
|
107
|
+
def qualified_const_get(klass)
|
108
|
+
if klass =~ /::/
|
109
|
+
namespace, klass = klass.split("::")
|
110
|
+
eval(namespace).const_get(klass)
|
111
|
+
else
|
112
|
+
const_get(klass)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module RoleAuthorization
|
2
|
+
module Exts
|
3
|
+
module Controller
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
rescue_from SecurityError, :with => proc {|e| access_denied(e)}
|
7
|
+
helper_method :authorized?
|
8
|
+
helper_method :accessible?
|
9
|
+
end
|
10
|
+
base.send :extend, RoleAuthorization::Ruleset::ClassMethods
|
11
|
+
base.send :cattr_ruleset, :ruleset, :allowable_groups
|
12
|
+
base.send :extend, ClassMethods
|
13
|
+
|
14
|
+
base.send :include, InstanceMethods
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
def allow_group(*args)
|
19
|
+
add_to_allowable_groups(self.controller_rule_name, args)
|
20
|
+
add_role_authorization_filter
|
21
|
+
end
|
22
|
+
|
23
|
+
def allow(&block)
|
24
|
+
add_to_ruleset(self.controller_rule_name, &block)
|
25
|
+
add_role_authorization_filter
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_role_authorization_filter
|
29
|
+
callbacks = _process_action_callbacks
|
30
|
+
chain = callbacks.select {|cl| cl.klass.to_s.include?(name)}.collect(&:filter).select {|c| c.is_a?(Symbol)}
|
31
|
+
before_filter :check_request_authorization unless chain.include?(:check_request_authorization)
|
32
|
+
end
|
33
|
+
|
34
|
+
def controller_rule_name
|
35
|
+
@controller_rule_name ||= name.gsub('Controller', '').underscore.downcase
|
36
|
+
end
|
37
|
+
|
38
|
+
def controller_model
|
39
|
+
@controller_model ||= name.gsub('Controller', '').singularize
|
40
|
+
end
|
41
|
+
end # ClassMethods
|
42
|
+
|
43
|
+
module InstanceMethods
|
44
|
+
def check_request_authorization
|
45
|
+
unless authorized_action?(self, self.class.controller_rule_name, action_name.to_sym, params[:id])
|
46
|
+
raise SecurityError, "You do not have the required clearance to access this resource."
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def authorized_action?(controller_klass, controller, action, id = nil)
|
51
|
+
# by default admins see everything
|
52
|
+
return true if current_user_is_admin?
|
53
|
+
|
54
|
+
ruleset = self.class.ruleset[controller]
|
55
|
+
groups = RoleAuthorization::AllowGroup.get(self.class.allowable_groups[controller])
|
56
|
+
|
57
|
+
if defined?(DEBUG_AUTHORIZATION_RULES) == 'constant'
|
58
|
+
Rails.logger.info "#" * 60
|
59
|
+
Rails.logger.info ruleset.to_s
|
60
|
+
Rails.logger.info "#" * 60
|
61
|
+
end
|
62
|
+
|
63
|
+
# we have no ruleset for this controller or any allow groups so deny
|
64
|
+
return false if ruleset.nil? && groups.empty?
|
65
|
+
|
66
|
+
# first check controller ruleset
|
67
|
+
unless ruleset.nil?
|
68
|
+
return true if ruleset.authorized?(controller_klass, controller, :all, id)
|
69
|
+
return true if ruleset.authorized?(controller_klass, controller, action, id)
|
70
|
+
end
|
71
|
+
|
72
|
+
# next check any allow groups
|
73
|
+
unless groups.empty?
|
74
|
+
groups.each do |group|
|
75
|
+
return true if group.authorized?(controller_klass, controller, :all, id)
|
76
|
+
return true if group.authorized?(controller_klass, controller, action, id)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# finally deny if they haven't passed any rules
|
81
|
+
return false
|
82
|
+
end
|
83
|
+
|
84
|
+
def accessible?(access_role)
|
85
|
+
return true if current_user_is_admin?
|
86
|
+
return false if access_role.nil?
|
87
|
+
return true if access_role.name.to_sym == :public
|
88
|
+
return false if session[:access_rights].nil?
|
89
|
+
session[:access_rights].include?(access_role.name.to_sym)
|
90
|
+
end
|
91
|
+
|
92
|
+
def authorized?(url, method = nil)
|
93
|
+
return false unless url
|
94
|
+
return true if current_user_is_admin?
|
95
|
+
|
96
|
+
method ||= (params[:method] || request.method)
|
97
|
+
url_parts = URI::split(url.strip)
|
98
|
+
path = url_parts[5]
|
99
|
+
|
100
|
+
begin
|
101
|
+
hash = Rails.application.routes.recognize_path(path, :method => method)
|
102
|
+
return authorized_action?(self, hash[:controller], hash[:action].to_sym, hash[:id]) if hash
|
103
|
+
rescue Exception => e
|
104
|
+
Rails.logger.error e.inspect
|
105
|
+
Rails.logger.error e.backtrace
|
106
|
+
# continue on
|
107
|
+
end
|
108
|
+
|
109
|
+
# Mailto link
|
110
|
+
return true if url =~ /^mailto:/
|
111
|
+
|
112
|
+
# Public file
|
113
|
+
file = File.join(RAILS_ROOT, 'public', url)
|
114
|
+
return true if File.exists?(file)
|
115
|
+
|
116
|
+
# Passing in different domain
|
117
|
+
return remote_url?(url_parts[2])
|
118
|
+
end
|
119
|
+
|
120
|
+
def remote_url?(domain = nil)
|
121
|
+
return false if domain.nil? || domain.strip.length == 0
|
122
|
+
request.host.downcase != domain.downcase
|
123
|
+
end
|
124
|
+
end # InstanceMethods
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module RoleAuthorization
|
2
|
+
module Exts
|
3
|
+
module Model
|
4
|
+
def self.included(base)
|
5
|
+
base.send :extend, ClassMethods
|
6
|
+
base.send :include, InstanceMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def roleable_options
|
11
|
+
@roleable_options
|
12
|
+
end
|
13
|
+
|
14
|
+
def roleable_options=(options)
|
15
|
+
@roleable_options = options
|
16
|
+
end
|
17
|
+
|
18
|
+
def roleable options = {}
|
19
|
+
has_many :roles, :as => :roleable, :dependent => :delete_all
|
20
|
+
after_create :create_roles
|
21
|
+
|
22
|
+
send(:extend, SpecificClassMethods)
|
23
|
+
|
24
|
+
options[:name] ||= :class
|
25
|
+
|
26
|
+
options[:priority] ||= {}
|
27
|
+
options[:creation_priority] ||= {}
|
28
|
+
options[:roles] ||= [:default]
|
29
|
+
options[:roles].each do |role_name|
|
30
|
+
options[:priority][role_name] ||= 1
|
31
|
+
options[:creation_priority][role_name] ||= 1
|
32
|
+
end
|
33
|
+
|
34
|
+
options[:cache] = {}
|
35
|
+
@roleable_options = options
|
36
|
+
end # roleable
|
37
|
+
|
38
|
+
def enrolled(role_name)
|
39
|
+
roles = Role.all(:conditions => {:roleable_type => self.to_s, :name => role_name.to_s})
|
40
|
+
unless roles.empty?
|
41
|
+
roles.collect(&:users).flatten
|
42
|
+
else
|
43
|
+
[]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end # ClassMethods
|
47
|
+
|
48
|
+
module SpecificClassMethods
|
49
|
+
def reset_roles
|
50
|
+
all.map(&:reset_roles)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
module InstanceMethods
|
55
|
+
|
56
|
+
def reset_roles
|
57
|
+
options = self.class.roleable_options
|
58
|
+
|
59
|
+
mroles = roles.all
|
60
|
+
rejected_roles = mroles.reject {|r| options[:roles].include?(r.name.to_sym)}
|
61
|
+
rejected_roles.map {|rejected_role| rejected_role.destroy}
|
62
|
+
|
63
|
+
valid_roles = mroles - rejected_roles
|
64
|
+
valid_role_names = valid_roles.collect(&:name)
|
65
|
+
new_roles = options[:roles].select {|role| !valid_role_names.include?(role.to_sym)}
|
66
|
+
valid_roles.each do |role|
|
67
|
+
if roles.find_by_name(role.name.to_s).nil?
|
68
|
+
roles.create(:name => role.name.to_s,
|
69
|
+
:display_name => "#{self.send(options[:name])} #{role.name.to_s}",
|
70
|
+
:creation_priority => options[:creation_priority][role.name.to_s],
|
71
|
+
:priority => options[:priority][role.name.to_s])
|
72
|
+
end
|
73
|
+
end
|
74
|
+
new_roles.each do |role|
|
75
|
+
roles.create(:name => role.to_s,
|
76
|
+
:display_name => "#{self.send(options[:name])} #{role.to_s}",
|
77
|
+
:creation_priority => options[:creation_priority][role],
|
78
|
+
:priority => options[:priority][role])
|
79
|
+
end
|
80
|
+
roles(true).all
|
81
|
+
end
|
82
|
+
|
83
|
+
def enroll(user, role)
|
84
|
+
options = self.class.roleable_options
|
85
|
+
role = role.is_a?(Integer) ? roles.find_by_id(role) : roles.find_by_name(role.to_s)
|
86
|
+
user_id = ((user.is_a?(Integer) || user.is_a?(String)) ? user.to_i : user.id)
|
87
|
+
unless role.nil?
|
88
|
+
role.user_roles.create(:user_id => user_id)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
alias_method :assign, :enroll
|
92
|
+
|
93
|
+
def enrolled(role)
|
94
|
+
role = roles.find_by_name(role.to_s)
|
95
|
+
unless role.nil?
|
96
|
+
role.users
|
97
|
+
else
|
98
|
+
[]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def withdraw(user, role = nil)
|
103
|
+
options = self.class.roleable_options
|
104
|
+
role = role.is_a?(Integer) ? roles.find_by_id(role, :include => :user_roles) : roles.find_by_name(role.to_s, :include => :user_roles)
|
105
|
+
user_id = ((user.is_a?(Integer) || user.is_a?(String)) ? user.to_i : user.id)
|
106
|
+
unless role.nil?
|
107
|
+
role.user_roles.first(:conditions => {:user_id => user_id}).try(:destroy)
|
108
|
+
else
|
109
|
+
UserRole.all(:conditions => {:user_id => user_id, :role_id => role_ids}).map(&:destroy)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
def create_roles
|
115
|
+
options = self.class.roleable_options
|
116
|
+
options[:roles].each do |role|
|
117
|
+
roles.create(:name => role.to_s,
|
118
|
+
:display_name => "#{self.send(options[:name])} #{role.to_s}",
|
119
|
+
:creation_priority => options[:creation_priority][role],
|
120
|
+
:priority => options[:priority][role])
|
121
|
+
end
|
122
|
+
end # create_user_roles
|
123
|
+
end # InstanceMethods
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module RoleAuthorization
|
2
|
+
module Exts
|
3
|
+
module Session
|
4
|
+
def self.included(base)
|
5
|
+
base.send :include, InstanceMethods
|
6
|
+
base.class_eval do
|
7
|
+
helper_method :current_user_is_admin?
|
8
|
+
helper_method :admin?
|
9
|
+
helper_method :access_in_role?
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module InstanceMethods
|
14
|
+
protected
|
15
|
+
|
16
|
+
def add_role_authorization_session_values(user = nil)
|
17
|
+
user ||= current_user
|
18
|
+
|
19
|
+
if user
|
20
|
+
roles = user.roles.where({:roleable_id => nil}).all
|
21
|
+
session[:access_rights] = roles.collect {|role| role.name.to_sym}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def current_user_is_admin?
|
26
|
+
!session[:access_rights].nil? && session[:access_rights].include?(:all)
|
27
|
+
end
|
28
|
+
|
29
|
+
def admin?
|
30
|
+
current_user_is_admin?
|
31
|
+
end
|
32
|
+
|
33
|
+
def access_in_role?(role)
|
34
|
+
return true if current_user_is_admin?
|
35
|
+
return true if session_access_rights_include?(role)
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
def session_access_rights_include?(role)
|
40
|
+
return false unless session[:access_rights]
|
41
|
+
session[:access_rights].include?(role)
|
42
|
+
end
|
43
|
+
|
44
|
+
def reset_role_authorization_session
|
45
|
+
[:access_rights].each do |val|
|
46
|
+
session[val] = nil if session[val]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module RoleAuthorization
|
2
|
+
module Exts
|
3
|
+
module User
|
4
|
+
def self.included(base)
|
5
|
+
base.send :extend, ClassMethods
|
6
|
+
base.send :include, InstanceMethods
|
7
|
+
|
8
|
+
base.class_eval do
|
9
|
+
has_many :user_roles, :dependent => :delete_all
|
10
|
+
has_many :roles, :through => :user_roles
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def enroll(user_id, role_name)
|
16
|
+
user = find_by_id(user_id.to_i)
|
17
|
+
user.enroll(role_name) unless user.nil?
|
18
|
+
end # enroll
|
19
|
+
|
20
|
+
def withdraw(user_id, role_name)
|
21
|
+
user = find_by_id(user_id.to_i)
|
22
|
+
user.withdraw(role_name) unless user.nil?
|
23
|
+
end # withdraw
|
24
|
+
end # ClassMethods
|
25
|
+
|
26
|
+
module InstanceMethods
|
27
|
+
# has_object_role? simply needs to return true or false whether a user has a role or not.
|
28
|
+
# It may be a good idea to have "admin" roles return true always
|
29
|
+
# Return false always for anonymous users
|
30
|
+
def has_object_role?(role, object)
|
31
|
+
return false if self.anonymous?
|
32
|
+
|
33
|
+
@object_user_roles ||= roles.all(:conditions => ["roleable_type IS NOT NULL and roleable_id IS NOT NULL"])
|
34
|
+
result = @object_user_roles.detect do |r|
|
35
|
+
r.roleable_type == object.class.to_s && r.roleable_id == object.id && r.name == role.to_s
|
36
|
+
end
|
37
|
+
!result.nil?
|
38
|
+
end
|
39
|
+
|
40
|
+
# adds a role to the user
|
41
|
+
def enroll(role_name)
|
42
|
+
role_id = role_name.is_a?(Integer) ? role_name : Role.find_by_name(role_name.to_s).try(:id)
|
43
|
+
user_roles.create(:role_id => role_id) if !role_id.nil? && self.user_roles.find_by_role_id(role_id).nil?
|
44
|
+
end
|
45
|
+
|
46
|
+
def withdraw(role_name)
|
47
|
+
role_id = role_name.is_a?(Integer) ? role_name : Role.find_by_name(role_name.to_s).try(:id)
|
48
|
+
UserRole.delete_all(["user_id = ? AND role_id = ?", self.id, role_id]) unless role_id.nil?
|
49
|
+
end
|
50
|
+
|
51
|
+
def admin?
|
52
|
+
return true if roles.include?(Role.get(:all))
|
53
|
+
false
|
54
|
+
end
|
55
|
+
end # InstanceMethods
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module RoleAuthorization
|
2
|
+
module Exts
|
3
|
+
module View
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
alias_method :link_to_open, :link_to
|
7
|
+
alias_method :link_to, :link_to_secured
|
8
|
+
|
9
|
+
alias_method :button_to_open, :button_to
|
10
|
+
alias_method :button_to, :button_to_secured
|
11
|
+
|
12
|
+
alias_method :form_for_open, :form_for
|
13
|
+
alias_method :form_for, :form_for_secured
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def form_for_secured(record_or_name_or_array, *args, &proc)
|
18
|
+
options = args.last.is_a?(Hash) ? args.last : {}
|
19
|
+
|
20
|
+
url = url_for(options[:url])
|
21
|
+
|
22
|
+
method = (options[:html] && options[:html].has_key?(:method)) ? options[:html][:method] : :post
|
23
|
+
|
24
|
+
if authorized?(url, method)
|
25
|
+
return form_for_open(record_or_name_or_array, *args, &proc)
|
26
|
+
else
|
27
|
+
return ""
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def link_to_secured(name, options = {}, html_options = nil)
|
32
|
+
url = url_for(options)
|
33
|
+
|
34
|
+
method = (html_options && html_options.has_key?(:method)) ? html_options[:method] : :get
|
35
|
+
|
36
|
+
if authorized?(url, method)
|
37
|
+
return link_to_open(name, url, html_options)
|
38
|
+
else
|
39
|
+
return ""
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def button_to_secured(name, options = {}, html_options = nil)
|
44
|
+
url = url_for(options)
|
45
|
+
|
46
|
+
method = (html_options && html_options.has_key?(:method)) ? html_options[:method] : :post
|
47
|
+
|
48
|
+
if authorized?(url, method)
|
49
|
+
return button_to_open(name, url, html_options)
|
50
|
+
else
|
51
|
+
return ""
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def role(*user_roles, &block)
|
56
|
+
if block_given? && !session[:access_rights].blank? && !(user_roles & session[:access_rights]).empty?
|
57
|
+
capture_haml(&block)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def permitted_to?(url, method, &block)
|
62
|
+
capture_haml(&block) if block_given? && authorized?(url, method)
|
63
|
+
end
|
64
|
+
|
65
|
+
def link_to_or_show(name, options = {}, html_options = nil)
|
66
|
+
lnk = link_to(name, options, html_options)
|
67
|
+
lnk.length == 0 ? name : lnk
|
68
|
+
end
|
69
|
+
|
70
|
+
def links(*lis)
|
71
|
+
rvalue = []
|
72
|
+
lis.each{|link| rvalue << link if link.length > 0 }
|
73
|
+
rvalue.join(' | ')
|
74
|
+
end
|
75
|
+
end # View
|
76
|
+
end
|
77
|
+
end
|