authorization3.0 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/.gitignore +8 -0
- data/.idea/.rakeTasks +7 -0
- data/.idea/authorization.iml +13 -0
- data/.idea/inspectionProfiles/Project_Default.xml +6 -0
- data/.idea/misc.xml +7 -0
- data/.idea/modules.xml +8 -0
- data/.idea/vcs.xml +6 -0
- data/.idea/workspace.xml +227 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +20 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/Rakefile +2 -0
- data/authorization.gemspec +29 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/authorization.rb +172 -0
- data/lib/authorization/publishare/exceptions.rb +40 -0
- data/lib/authorization/publishare/hardwired_roles.rb +81 -0
- data/lib/authorization/publishare/identity.rb +125 -0
- data/lib/authorization/publishare/object_roles_table.rb +118 -0
- data/lib/authorization/publishare/parser.rb +210 -0
- data/lib/authorization/version.rb +3 -0
- metadata +102 -0
data/Rakefile
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
lib = File.expand_path("../lib", __FILE__)
|
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
|
+
require "authorization/version"
|
|
6
|
+
|
|
7
|
+
Gem::Specification.new do |spec|
|
|
8
|
+
spec.name = "authorization3.0"
|
|
9
|
+
spec.version = Authorization::VERSION
|
|
10
|
+
spec.authors = ["Pavan Agrawal"]
|
|
11
|
+
spec.email = ["pavan.agrawala@gmail.com"]
|
|
12
|
+
|
|
13
|
+
spec.summary = %q{Converted plugin to gem which will work with association as well.}
|
|
14
|
+
spec.description = %q{Converted plugin to gem which will work with association as well.}
|
|
15
|
+
spec.homepage = "https://github.com/pavanagrawal/authorization"
|
|
16
|
+
spec.license = "MIT"
|
|
17
|
+
|
|
18
|
+
# Specify which files should be added to the gem when it is released.
|
|
19
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
20
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
|
21
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
22
|
+
end
|
|
23
|
+
spec.bindir = "exe"
|
|
24
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
25
|
+
spec.require_paths = ["lib"]
|
|
26
|
+
|
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.17"
|
|
28
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
|
29
|
+
end
|
data/bin/console
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
require "authorization"
|
|
5
|
+
|
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
+
|
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
+
# require "pry"
|
|
11
|
+
# Pry.start
|
|
12
|
+
|
|
13
|
+
require "irb"
|
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
require "authorization/version"
|
|
2
|
+
require File.dirname(__FILE__) + '/authorization/publishare/exceptions'
|
|
3
|
+
require File.dirname(__FILE__) + '/authorization/publishare/parser'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
module Authorization
|
|
8
|
+
module Base
|
|
9
|
+
|
|
10
|
+
# Modify these constants in your environment.rb to tailor the plugin to your authentication system
|
|
11
|
+
if not Object.constants.include? "DEFAULT_REDIRECTION_HASH"
|
|
12
|
+
DEFAULT_REDIRECTION_HASH = { :controller => 'account', :action => 'login' }
|
|
13
|
+
end
|
|
14
|
+
if not Object.constants.include? "STORE_LOCATION_METHOD"
|
|
15
|
+
STORE_LOCATION_METHOD = :store_return_location
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.included( recipient )
|
|
19
|
+
recipient.extend( ControllerClassMethods )
|
|
20
|
+
recipient.class_eval do
|
|
21
|
+
include ControllerInstanceMethods
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module ControllerClassMethods
|
|
26
|
+
|
|
27
|
+
# Allow class-level authorization check.
|
|
28
|
+
# permit is used in a before_filter fashion and passes arguments to the before_filter.
|
|
29
|
+
def permit( authorization_expression, *args )
|
|
30
|
+
filter_keys = [ :only, :except ]
|
|
31
|
+
filter_args, eval_args = {}, {}
|
|
32
|
+
if args.last.is_a? Hash
|
|
33
|
+
filter_args.merge!( args.last.reject {|k,v| not filter_keys.include? k } )
|
|
34
|
+
eval_args.merge!( args.last.reject {|k,v| filter_keys.include? k } )
|
|
35
|
+
end
|
|
36
|
+
before_filter( filter_args ) do |controller|
|
|
37
|
+
controller.permit( authorization_expression, eval_args )
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
module ControllerInstanceMethods
|
|
43
|
+
include Authorization::Base::EvalParser # RecursiveDescentParser is another option
|
|
44
|
+
|
|
45
|
+
# Permit? turns off redirection by default and takes no blocks
|
|
46
|
+
def permit?( authorization_expression, *args )
|
|
47
|
+
@options = { :allow_guests => false, :redirect => false }
|
|
48
|
+
@options.merge!( args.last.is_a?( Hash ) ? args.last : {} )
|
|
49
|
+
|
|
50
|
+
has_permission?( authorization_expression )
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Allow method-level authorization checks.
|
|
54
|
+
# permit (without a question mark ending) calls redirect on denial by default.
|
|
55
|
+
# Specify :redirect => false to turn off redirection.
|
|
56
|
+
def permit( authorization_expression, *args )
|
|
57
|
+
@options = { :allow_guests => false, :redirect => true }
|
|
58
|
+
@options.merge!( args.last.is_a?( Hash ) ? args.last : {} )
|
|
59
|
+
|
|
60
|
+
if has_permission?( authorization_expression )
|
|
61
|
+
yield if block_given?
|
|
62
|
+
elsif @options[:redirect]
|
|
63
|
+
handle_redirection
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def has_permission?( authorization_expression )
|
|
70
|
+
@current_user = get_user
|
|
71
|
+
if not @options[:allow_guests]
|
|
72
|
+
if @current_user.nil? # We aren't logged in, or an exception has already been raised
|
|
73
|
+
return false
|
|
74
|
+
elsif not @current_user.respond_to? :id
|
|
75
|
+
raise( UserDoesntImplementID, "User doesn't implement #id")
|
|
76
|
+
elsif not @current_user.respond_to? :has_role?
|
|
77
|
+
raise( UserDoesntImplementRoles, "User doesn't implement #has_role?" )
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
parse_authorization_expression( authorization_expression )
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Handle redirection within permit if authorization is denied.
|
|
84
|
+
def handle_redirection
|
|
85
|
+
return if not self.respond_to?( :redirect_to )
|
|
86
|
+
redirection = DEFAULT_REDIRECTION_HASH
|
|
87
|
+
redirection[:controller] = @options[:redirect_controller] if @options[:redirect_controller]
|
|
88
|
+
redirection[:action] = @options[:redirect_action] if @options[:redirect_action]
|
|
89
|
+
|
|
90
|
+
# Store url in session for return if this is available from authentication
|
|
91
|
+
send( STORE_LOCATION_METHOD ) if respond_to? STORE_LOCATION_METHOD
|
|
92
|
+
if @current_user
|
|
93
|
+
flash[:notice] = "Permission denied. Your account cannot access the requested page."
|
|
94
|
+
else
|
|
95
|
+
flash[:notice] = @options[:redirect_message] ? @options[:redirect_message] : "Login is required"
|
|
96
|
+
end
|
|
97
|
+
redirect_to redirection
|
|
98
|
+
false # Want to short-circuit the filters
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Try to find current user by checking options hash and instance method in that order.
|
|
102
|
+
def get_user
|
|
103
|
+
if @options[:user]
|
|
104
|
+
@options[:user]
|
|
105
|
+
elsif @options[:get_user_method]
|
|
106
|
+
send( @options[:get_user_method] )
|
|
107
|
+
elsif self.respond_to? :current_user
|
|
108
|
+
current_user
|
|
109
|
+
elsif not @options[:allow_guests]
|
|
110
|
+
raise( CannotObtainUserObject, "Couldn't find #current_user or @user, and nothing appropriate found in hash" )
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Try to find a model to query for permissions
|
|
115
|
+
def get_model( str )
|
|
116
|
+
if str =~ /\s*([A-Z]+\w*)\s*/
|
|
117
|
+
# Handle model class
|
|
118
|
+
begin
|
|
119
|
+
Module.const_get( str )
|
|
120
|
+
rescue
|
|
121
|
+
raise CannotObtainModelClass, "Couldn't find model class: #{str}"
|
|
122
|
+
end
|
|
123
|
+
elsif str =~ /\s*:*(\w+)\s*/
|
|
124
|
+
# Handle model instances
|
|
125
|
+
model_name = $1
|
|
126
|
+
model_symbol = model_name.to_sym
|
|
127
|
+
if @options[model_symbol]
|
|
128
|
+
@options[model_symbol]
|
|
129
|
+
elsif instance_variables.include?( '@'+model_name )
|
|
130
|
+
instance_variable_get( '@'+model_name )
|
|
131
|
+
# Note -- while the following code makes autodiscovery more convenient, it's a little too much side effect & security question
|
|
132
|
+
# elsif self.params[:id]
|
|
133
|
+
# eval_str = model_name.camelize + ".find(#{self.params[:id]})"
|
|
134
|
+
# eval eval_str
|
|
135
|
+
else
|
|
136
|
+
raise CannotObtainModelObject, "Couldn't find model (#{str}) in hash or as an instance variable"
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
ActionController::Base.send( :include, Authorization::Base )
|
|
147
|
+
ActionView::Base.send( :include, Authorization::Base::ControllerInstanceMethods )
|
|
148
|
+
|
|
149
|
+
# You can perform authorization at varying degrees of complexity.
|
|
150
|
+
# Choose a style of authorization below (see README) and the appropriate
|
|
151
|
+
# mixin will be used for your app.
|
|
152
|
+
|
|
153
|
+
# When used with the auth_test app, we define this in config/environment.rb
|
|
154
|
+
# AUTHORIZATION_MIXIN = "hardwired"
|
|
155
|
+
if not Object.constants.include? "AUTHORIZATION_MIXIN"
|
|
156
|
+
AUTHORIZATION_MIXIN = "object roles"
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
case AUTHORIZATION_MIXIN
|
|
160
|
+
when "hardwired"
|
|
161
|
+
require "authorization/publishare/hardwired_roles"
|
|
162
|
+
ActiveRecord::Base.send( :include,
|
|
163
|
+
Authorization::HardwiredRoles::UserExtensions,
|
|
164
|
+
Authorization::HardwiredRoles::ModelExtensions
|
|
165
|
+
)
|
|
166
|
+
when "object roles"
|
|
167
|
+
require "authorization/publishare/object_roles_table"
|
|
168
|
+
ActiveRecord::Base.send( :include,
|
|
169
|
+
Authorization::ObjectRolesTable::UserExtensions,
|
|
170
|
+
Authorization::ObjectRolesTable::ModelExtensions
|
|
171
|
+
)
|
|
172
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module Authorization #:nodoc:
|
|
2
|
+
|
|
3
|
+
# Base error class for Authorization module
|
|
4
|
+
class AuthorizationError < StandardError
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
# Raised when the authorization expression is invalid (cannot be parsed)
|
|
8
|
+
class AuthorizationExpressionInvalid < AuthorizationError
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Raised when we can't find the current user
|
|
12
|
+
class CannotObtainUserObject < AuthorizationError
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Raised when an authorization expression contains a model class that doesn't exist
|
|
16
|
+
class CannotObtainModelClass < AuthorizationError
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Raised when an authorization expression contains a model reference that doesn't exist
|
|
20
|
+
class CannotObtainModelObject < AuthorizationError
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Raised when the obtained user object doesn't implement #id
|
|
24
|
+
class UserDoesntImplementID < AuthorizationError
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Raised when the obtained user object doesn't implement #has_role?
|
|
28
|
+
class UserDoesntImplementRoles < AuthorizationError
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Raised when the obtained model doesn't implement #accepts_role?
|
|
32
|
+
class ModelDoesntImplementRoles < AuthorizationError
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
class CannotSetRoleWhenHardwired < AuthorizationError
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class CannotSetObjectRoleWhenSimpleRoleTable < AuthorizationError
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/exceptions'
|
|
2
|
+
|
|
3
|
+
# In order to use this mixin, you'll need to define roles by overriding the
|
|
4
|
+
# following functions:
|
|
5
|
+
#
|
|
6
|
+
# User#has_role?(role)
|
|
7
|
+
# Return true or false depending on the roles (strings) passed in.
|
|
8
|
+
#
|
|
9
|
+
# Model#accepts_role?(role, user)
|
|
10
|
+
# Return true or false depending on the roles (strings) this particular user has for
|
|
11
|
+
# this particular model object.
|
|
12
|
+
#
|
|
13
|
+
# See http://www.writertopia.com/developers/authorization
|
|
14
|
+
|
|
15
|
+
module Authorization
|
|
16
|
+
module HardwiredRoles
|
|
17
|
+
|
|
18
|
+
module UserExtensions
|
|
19
|
+
def self.included( recipient )
|
|
20
|
+
recipient.extend( ClassMethods )
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module ClassMethods
|
|
24
|
+
def acts_as_authorized_user
|
|
25
|
+
include Authorization::HardwiredRoles::UserExtensions::InstanceMethods
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
module InstanceMethods
|
|
30
|
+
# If roles aren't explicitly defined in user class then return false
|
|
31
|
+
def has_role?( role, authorizable_object = nil )
|
|
32
|
+
false
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def has_role( role, authorizable_object = nil )
|
|
36
|
+
raise( CannotSetRoleWhenHardwired,
|
|
37
|
+
"Hardwired mixin: Cannot set user to role #{role}. Don't use #has_role, use code in models."
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def has_no_role( role, authorizable_object = nil )
|
|
42
|
+
raise( CannotSetRoleWhenHardwired,
|
|
43
|
+
"Hardwired mixin: Cannot remove user role #{role}. Don't use #has_no_role, use code in models."
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
module ModelExtensions
|
|
50
|
+
def self.included( recipient )
|
|
51
|
+
recipient.extend( ClassMethods )
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
module ClassMethods
|
|
55
|
+
def acts_as_authorizable
|
|
56
|
+
include Authorization::HardwiredRoles::ModelExtensions::InstanceMethods
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
module InstanceMethods
|
|
61
|
+
def accepts_role?( role, user )
|
|
62
|
+
return false
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def accepts_role( role, user )
|
|
66
|
+
raise( CannotSetRoleWhenHardwired,
|
|
67
|
+
"Hardwired mixin: Cannot set user to role #{role}. Don't use #accepts_role, use code in models."
|
|
68
|
+
)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def accepts_no_role( role, user )
|
|
72
|
+
raise( CannotSetRoleWhenHardwired,
|
|
73
|
+
"Hardwired mixin: Cannot set user to role #{role}. Don't use #accepts_no_role, use code in models."
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/exceptions'
|
|
2
|
+
|
|
3
|
+
# Provides the appearance of dynamically generated methods on the roles database.
|
|
4
|
+
#
|
|
5
|
+
# Examples:
|
|
6
|
+
# user.is_member? --> Returns true if user has any role of "member"
|
|
7
|
+
# user.is_member_of? this_workshop --> Returns true/false. Must have authorizable object after query.
|
|
8
|
+
# user.is_eligible_for [this_award] --> Gives user the role "eligible" for "this_award"
|
|
9
|
+
# user.is_moderator --> Gives user the general role "moderator" (not tied to any class or object)
|
|
10
|
+
# user.is_candidate_of_what --> Returns array of objects for which this user is a "candidate"
|
|
11
|
+
#
|
|
12
|
+
# model.has_members --> Returns array of users which have role "member" on that model
|
|
13
|
+
# model.has_members? --> Returns true/false
|
|
14
|
+
#
|
|
15
|
+
module Authorization
|
|
16
|
+
module Identity
|
|
17
|
+
|
|
18
|
+
module UserExtensions
|
|
19
|
+
module InstanceMethods
|
|
20
|
+
|
|
21
|
+
def method_missing( method_sym, *args )
|
|
22
|
+
method_name = method_sym.to_s
|
|
23
|
+
authorizable_object = args.empty? ? nil : args[0]
|
|
24
|
+
|
|
25
|
+
base_regex = "is_(\\w+)"
|
|
26
|
+
fancy_regex = base_regex + "_(#{Authorization::Base::VALID_PREPOSITIONS_PATTERN})"
|
|
27
|
+
is_either_regex = '^((' + fancy_regex + ')|(' + base_regex + '))'
|
|
28
|
+
base_not_regex = "is_no[t]?_(\\w+)"
|
|
29
|
+
fancy_not_regex = base_not_regex + "_(#{Authorization::Base::VALID_PREPOSITIONS_PATTERN})"
|
|
30
|
+
is_not_either_regex = '^((' + fancy_not_regex + ')|(' + base_not_regex + '))'
|
|
31
|
+
|
|
32
|
+
if method_name =~ Regexp.new(is_either_regex + '_what$')
|
|
33
|
+
role_name = $3 || $6
|
|
34
|
+
has_role_for_objects(role_name)
|
|
35
|
+
elsif method_name =~ Regexp.new(is_not_either_regex + '\?$')
|
|
36
|
+
role_name = $3 || $6
|
|
37
|
+
not is_role?( role_name, authorizable_object )
|
|
38
|
+
elsif method_name =~ Regexp.new(is_either_regex + '\?$')
|
|
39
|
+
role_name = $3 || $6
|
|
40
|
+
is_role?( role_name, authorizable_object )
|
|
41
|
+
elsif method_name =~ Regexp.new(is_not_either_regex + '$')
|
|
42
|
+
role_name = $3 || $6
|
|
43
|
+
is_no_role( role_name, authorizable_object )
|
|
44
|
+
elsif method_name =~ Regexp.new(is_either_regex + '$')
|
|
45
|
+
role_name = $3 || $6
|
|
46
|
+
is_role( role_name, authorizable_object )
|
|
47
|
+
else
|
|
48
|
+
super
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def is_role?( role_name, authorizable_object )
|
|
55
|
+
if authorizable_object.nil?
|
|
56
|
+
return self.has_role?(role_name)
|
|
57
|
+
elsif authorizable_object.respond_to?(:accepts_role?)
|
|
58
|
+
return self.has_role?(role_name, authorizable_object)
|
|
59
|
+
end
|
|
60
|
+
false
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def is_no_role( role_name, authorizable_object = nil )
|
|
64
|
+
if authorizable_object.nil?
|
|
65
|
+
self.has_no_role role_name
|
|
66
|
+
else
|
|
67
|
+
self.has_no_role role_name, authorizable_object
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def is_role( role_name, authorizable_object = nil )
|
|
72
|
+
if authorizable_object.nil?
|
|
73
|
+
self.has_role role_name
|
|
74
|
+
else
|
|
75
|
+
self.has_role role_name, authorizable_object
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def has_role_for_objects(role_name)
|
|
80
|
+
roles = self.roles.find_all_by_name( role_name )
|
|
81
|
+
roles.collect do |role|
|
|
82
|
+
if role.authorizable_id.nil?
|
|
83
|
+
role.authorizable_type.nil? ?
|
|
84
|
+
nil : Module.const_get( role.authorizable_type ) # Returns class
|
|
85
|
+
else
|
|
86
|
+
role.authorizable
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
module ModelExtensions
|
|
94
|
+
module InstanceMethods
|
|
95
|
+
|
|
96
|
+
def method_missing( method_sym, *args )
|
|
97
|
+
method_name = method_sym.to_s
|
|
98
|
+
if method_name =~ /^has_(\w+)\?$/
|
|
99
|
+
role_name = $1.singularize
|
|
100
|
+
self.accepted_roles.find_all_by_name(role_name).any? { |role| role.users }
|
|
101
|
+
elsif method_name =~ /^has_(\w+)$/
|
|
102
|
+
role_name = $1.singularize
|
|
103
|
+
users = self.accepted_roles.find_all_by_name(role_name).collect { |role| role.users }
|
|
104
|
+
users.flatten.uniq if users
|
|
105
|
+
else
|
|
106
|
+
super
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def respond_to? method_sym
|
|
111
|
+
method_name = method_sym.to_s
|
|
112
|
+
if method_name =~ /^has_(\w+)\?$/
|
|
113
|
+
true
|
|
114
|
+
elsif method_name =~ /^has_(\w+)$/
|
|
115
|
+
true
|
|
116
|
+
else
|
|
117
|
+
super
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
end
|
|
125
|
+
end
|