permit_yo 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/config/locales/en.yml +4 -0
- data/lib/permit_yo.rb +1 -0
- data/lib/permit_yo/base.rb +160 -0
- data/lib/permit_yo/default.rb +45 -0
- data/lib/permit_yo/engine.rb +29 -0
- data/lib/permit_yo/exceptions.rb +43 -0
- data/lib/permit_yo/parser.rb +210 -0
- metadata +70 -0
data/lib/permit_yo.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'permit_yo/engine' if defined?(Rails)
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'permit_yo/exceptions'
|
2
|
+
require 'permit_yo/parser'
|
3
|
+
|
4
|
+
module PermitYo
|
5
|
+
module Base
|
6
|
+
def self.included(recipient)
|
7
|
+
recipient.extend ControllerClassMethods
|
8
|
+
recipient.class_eval do
|
9
|
+
include ControllerInstanceMethods
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module ControllerClassMethods
|
14
|
+
|
15
|
+
# Allow class-level authorization check.
|
16
|
+
# permit is used in a before_filter fashion and passes arguments to the before_filter.
|
17
|
+
def permit(authorization_expression, *args)
|
18
|
+
filter_keys = [:only, :except]
|
19
|
+
filter_args, eval_args = {}, {}
|
20
|
+
if args.last.is_a? Hash
|
21
|
+
filter_args.merge!(args.last.reject {|k,v| not filter_keys.include? k })
|
22
|
+
eval_args.merge!(args.last.reject {|k,v| filter_keys.include? k })
|
23
|
+
end
|
24
|
+
before_filter(filter_args) do |controller|
|
25
|
+
controller.permit(authorization_expression, eval_args)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module ControllerInstanceMethods
|
31
|
+
include PermitYo::Base::EvalParser # RecursiveDescentParser is another option
|
32
|
+
|
33
|
+
# Permit? turns off redirection by default and takes no blocks
|
34
|
+
def permit?(authorization_expression, *args)
|
35
|
+
@options = { :allow_guests => false, :redirect => false }
|
36
|
+
@options.merge!(args.last.is_a?(Hash) ? args.last : {})
|
37
|
+
|
38
|
+
has_permission?(authorization_expression)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Allow method-level authorization checks.
|
42
|
+
# permit (without a question mark ending) calls redirect on denial by default.
|
43
|
+
# Specify :redirect => false to turn off redirection.
|
44
|
+
def permit(authorization_expression, *args)
|
45
|
+
@options = { :allow_guests => false, :redirect => true }
|
46
|
+
@options.merge!(args.last.is_a?(Hash) ? args.last : {})
|
47
|
+
|
48
|
+
if has_permission?(authorization_expression)
|
49
|
+
yield if block_given?
|
50
|
+
elsif @options[:redirect]
|
51
|
+
handle_redirection
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def has_permission?(authorization_expression)
|
58
|
+
@current_user = get_user
|
59
|
+
if not @options[:allow_guests]
|
60
|
+
# We aren't logged in, or an exception has already been raised.
|
61
|
+
# Test for both nil and :false symbol as restful_authentication plugin
|
62
|
+
# will set current user to ':false' on a failed login (patch by Ho-Sheng Hsiao).
|
63
|
+
# Latest incarnations of restful_authentication plugin set current user to false.
|
64
|
+
if @current_user.nil? || @current_user == :false || @current_user == false
|
65
|
+
return false
|
66
|
+
elsif not @current_user.respond_to? :id
|
67
|
+
raise(UserDoesntImplementID, "User doesn't implement #id")
|
68
|
+
elsif not @current_user.respond_to? :has_role?
|
69
|
+
raise(UserDoesntImplementRoles, "User doesn't implement #has_role?")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
parse_authorization_expression(authorization_expression)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Handle redirection within permit if authorization is denied.
|
76
|
+
def handle_redirection
|
77
|
+
return if not self.respond_to?(:redirect_to)
|
78
|
+
# Store url in session for return if this is available from authentication
|
79
|
+
send(Rails.application.config.permit_yo.store_location_method) if respond_to?(Rails.application.config.permit_yo.store_location_method)
|
80
|
+
if @current_user && @current_user != :false
|
81
|
+
respond_to do |format|
|
82
|
+
format.html do
|
83
|
+
if self.respond_to? :handle_permission_denied_redirection_for_html
|
84
|
+
handle_permission_denied_redirection_for_html
|
85
|
+
else
|
86
|
+
flash[Rails.application.config.permit_yo.permission_denied_flash] = @options[:permission_denied_message] || t('permit_yo.permission_denied')
|
87
|
+
redirect_to @options[:permission_denied_redirection] || (self.respond_to?(:permission_denied_redirection) ? permission_denied_redirection : Rails.application.config.permit_yo.permission_denied_redirection)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
format.all do
|
91
|
+
if self.respond_to? :"handle_permission_denied_redirection_for_#{params[:format]}"
|
92
|
+
self.send :"handle_permission_denied_redirection_for_#{params[:format]}"
|
93
|
+
else
|
94
|
+
render :text => nil, :status => :forbidden
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
else
|
99
|
+
respond_to do |format|
|
100
|
+
format.html do
|
101
|
+
if self.respond_to? :handle_require_user_redirection_for_html
|
102
|
+
handle_require_user_redirection_for_html
|
103
|
+
else
|
104
|
+
flash[Rails.application.config.permit_yo.require_user_flash] = @options[:require_user_message] || t('permit_yo.require_user')
|
105
|
+
redirect_to @options[:require_user_redirection] || (self.respond_to?(:require_user_redirection) ? require_user_redirection : Rails.application.config.permit_yo.require_user_redirection)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
format.all do
|
109
|
+
if self.respond_to? :"handle_require_user_redirection_for_#{params[:format]}"
|
110
|
+
self.send :"handle_require_user_redirection_for_#{params[:format]}"
|
111
|
+
else
|
112
|
+
render :text => nil, :status => :unauthorized
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
false # Want to short-circuit the filters
|
118
|
+
end
|
119
|
+
|
120
|
+
# Try to find current user by checking options hash and instance method in that order.
|
121
|
+
def get_user
|
122
|
+
if @options[:user]
|
123
|
+
@options[:user]
|
124
|
+
elsif @options[:get_user_method]
|
125
|
+
send(@options[:get_user_method])
|
126
|
+
elsif self.respond_to? Rails.application.config.permit_yo.current_user_method
|
127
|
+
self.send Rails.application.config.permit_yo.current_user_method
|
128
|
+
elsif not @options[:allow_guests]
|
129
|
+
raise(CannotObtainUserObject, "Couldn't find ##{Rails.application.config.permit_yo.current_user_method} or @user, and nothing appropriate found in hash")
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Try to find a model to query for permissions
|
134
|
+
def get_model(str)
|
135
|
+
if str =~ /\s*([A-Z]+\w*)\s*/
|
136
|
+
# Handle model class
|
137
|
+
begin
|
138
|
+
Module.const_get(str)
|
139
|
+
rescue
|
140
|
+
raise CannotObtainModelClass, "Couldn't find model class: #{str}"
|
141
|
+
end
|
142
|
+
elsif str =~ /\s*:*(\w+)\s*/
|
143
|
+
# Handle model instances
|
144
|
+
model_name = $1
|
145
|
+
model_symbol = model_name.to_sym
|
146
|
+
if @options[model_symbol]
|
147
|
+
@options[model_symbol]
|
148
|
+
elsif instance_variables.include?('@'+model_name)
|
149
|
+
instance_variable_get('@'+model_name)
|
150
|
+
elsif respond_to?(model_symbol)
|
151
|
+
send(model_symbol)
|
152
|
+
else
|
153
|
+
raise CannotObtainModelObject, "Couldn't find model (#{str}) in hash or as an instance variable"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module PermitYo
|
2
|
+
module Default
|
3
|
+
module UserExtensions
|
4
|
+
def self.included(recipient)
|
5
|
+
recipient.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def acts_as_authorized_user
|
10
|
+
include PermitYo::Default::UserExtensions::InstanceMethods
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module InstanceMethods
|
15
|
+
def has_role?(role)
|
16
|
+
self.send(:"#{role}?") if self.respond_to?(:"#{role}?")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module ModelExtensions
|
22
|
+
def self.included(recipient)
|
23
|
+
recipient.extend ClassMethods
|
24
|
+
end
|
25
|
+
|
26
|
+
module ClassMethods
|
27
|
+
def acts_as_authorizable
|
28
|
+
include PermitYo::Default::ModelExtensions::InstanceMethods
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module InstanceMethods
|
33
|
+
def accepts_role?(role, user)
|
34
|
+
if self.respond_to? role
|
35
|
+
self.send(role) == user
|
36
|
+
elsif self.respond_to? role.pluralize
|
37
|
+
self.send(role.pluralize).include?(user)
|
38
|
+
else
|
39
|
+
false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'permit_yo'
|
2
|
+
require 'rails'
|
3
|
+
require 'action_controller'
|
4
|
+
require 'action_view'
|
5
|
+
|
6
|
+
module PermitYo
|
7
|
+
class Engine < Rails::Engine
|
8
|
+
config.permit_yo = ActiveSupport::OrderedOptions.new
|
9
|
+
config.permit_yo.root = __FILE__.gsub('/lib/permit_yo/engine.rb', '')
|
10
|
+
config.permit_yo.implementation = :default
|
11
|
+
config.permit_yo.require_user_redirection = { :controller => 'user_sessions', :action => 'new' }
|
12
|
+
config.permit_yo.permission_denied_redirection = ''
|
13
|
+
config.permit_yo.store_location_method = :store_location
|
14
|
+
config.permit_yo.current_user_method = :current_user
|
15
|
+
config.permit_yo.require_user_flash = :notice
|
16
|
+
config.permit_yo.permission_denied_flash = :notice
|
17
|
+
|
18
|
+
initializer "permit_yo.default" do |app|
|
19
|
+
ActionController::Base.send :include, PermitYo::Base
|
20
|
+
ActionView::Base.send :include, PermitYo::Base::ControllerInstanceMethods
|
21
|
+
if app.config.permit_yo.implementation == :default
|
22
|
+
require 'active_record'
|
23
|
+
ActiveRecord::Base.send :include,
|
24
|
+
PermitYo::Default::UserExtensions,
|
25
|
+
PermitYo::Default::ModelExtensions
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module PermitYo #: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
|
+
|
41
|
+
class CannotGetAuthorizables < AuthorizationError
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
module PermitYo
|
2
|
+
module Base
|
3
|
+
|
4
|
+
VALID_PREPOSITIONS = ['of', 'for', 'in', 'on', 'to', 'at', 'by']
|
5
|
+
BOOLEAN_OPS = ['not', 'or', 'and']
|
6
|
+
VALID_PREPOSITIONS_PATTERN = VALID_PREPOSITIONS.join('|')
|
7
|
+
|
8
|
+
module EvalParser
|
9
|
+
# Parses and evaluates an authorization expression and returns <tt>true</tt> or <tt>false</tt>.
|
10
|
+
#
|
11
|
+
# The authorization expression is defined by the following grammar:
|
12
|
+
# <expr> ::= (<expr>) | not <expr> | <term> or <expr> | <term> and <expr> | <term>
|
13
|
+
# <term> ::= <role> | <role> <preposition> <model>
|
14
|
+
# <preposition> ::= of | for | in | on | to | at | by
|
15
|
+
# <model> ::= /:*\w+/
|
16
|
+
# <role> ::= /\w+/ | /'.*'/
|
17
|
+
#
|
18
|
+
# Instead of doing recursive descent parsing (not so fun when we support nested parentheses, etc),
|
19
|
+
# we let Ruby do the work for us by inserting the appropriate permission calls and using eval.
|
20
|
+
# This would not be a good idea if you were getting authorization expressions from the outside,
|
21
|
+
# so in that case (e.g. somehow letting users literally type in permission expressions) you'd
|
22
|
+
# be better off using the recursive descent parser in Module RecursiveDescentParser.
|
23
|
+
#
|
24
|
+
# We search for parts of our authorization evaluation that match <role> or <role> <preposition> <model>
|
25
|
+
# and we ignore anything terminal in our grammar.
|
26
|
+
#
|
27
|
+
# 1) Replace all <role> <preposition> <model> matches.
|
28
|
+
# 2) Replace all <role> matches that aren't one of our other terminals ('not', 'or', 'and', or preposition)
|
29
|
+
# 3) Eval
|
30
|
+
|
31
|
+
def parse_authorization_expression( str )
|
32
|
+
if str =~ /[^A-Za-z0-9_:'\(\)\s]/
|
33
|
+
raise AuthorizationExpressionInvalid, "Invalid authorization expression (#{str})"
|
34
|
+
return false
|
35
|
+
end
|
36
|
+
@replacements = []
|
37
|
+
expr = replace_temporarily_role_of_model( str )
|
38
|
+
expr = replace_role( expr )
|
39
|
+
expr = replace_role_of_model( expr )
|
40
|
+
begin
|
41
|
+
instance_eval( expr )
|
42
|
+
rescue Exception => error
|
43
|
+
raise AuthorizationExpressionInvalid, "Cannot parse authorization (#{str}): #{error.message}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def replace_temporarily_role_of_model( str )
|
48
|
+
role_regex = '\s*(\'\s*(.+?)\s*\'|(\w+))\s+'
|
49
|
+
model_regex = '\s+(:*\w+)'
|
50
|
+
parse_regex = Regexp.new(role_regex + '(' + VALID_PREPOSITIONS.join('|') + ')' + model_regex)
|
51
|
+
str.gsub(parse_regex) do |match|
|
52
|
+
@replacements.push " process_role_of_model('#{$2 || $3}', '#{$5}') "
|
53
|
+
" <#{@replacements.length-1}> "
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def replace_role( str )
|
58
|
+
role_regex = '\s*(\'\s*(.+?)\s*\'|([A-Za-z]\w*))\s*'
|
59
|
+
parse_regex = Regexp.new(role_regex)
|
60
|
+
str.gsub(parse_regex) do |match|
|
61
|
+
if BOOLEAN_OPS.include?($3)
|
62
|
+
" #{match} "
|
63
|
+
else
|
64
|
+
" process_role('#{$2 || $3}') "
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def replace_role_of_model( str )
|
70
|
+
str.gsub(/<(\d+)>/) do |match|
|
71
|
+
@replacements[$1.to_i]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def process_role_of_model( role_name, model_name )
|
76
|
+
model = get_model( model_name )
|
77
|
+
raise( ModelDoesntImplementRoles, "Model (#{model_name}) doesn't implement #accepts_role?" ) if not model.respond_to? :accepts_role?
|
78
|
+
model.send( :accepts_role?, role_name, @current_user )
|
79
|
+
end
|
80
|
+
|
81
|
+
def process_role( role_name )
|
82
|
+
return false if @current_user.nil? || @current_user == :false
|
83
|
+
raise( UserDoesntImplementRoles, "User doesn't implement #has_role?" ) if not @current_user.respond_to? :has_role?
|
84
|
+
@current_user.has_role?( role_name )
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
# Parses and evaluates an authorization expression and returns <tt>true</tt> or <tt>false</tt>.
|
90
|
+
# This recursive descent parses uses two instance variables:
|
91
|
+
# @stack --> a stack with the top holding the boolean expression resulting from the parsing
|
92
|
+
#
|
93
|
+
# The authorization expression is defined by the following grammar:
|
94
|
+
# <expr> ::= (<expr>) | not <expr> | <term> or <expr> | <term> and <expr> | <term>
|
95
|
+
# <term> ::= <role> | <role> <preposition> <model>
|
96
|
+
# <preposition> ::= of | for | in | on | to | at | by
|
97
|
+
# <model> ::= /:*\w+/
|
98
|
+
# <role> ::= /\w+/ | /'.*'/
|
99
|
+
#
|
100
|
+
# There are really two values we must track:
|
101
|
+
# (1) whether the expression is valid according to the grammar
|
102
|
+
# (2) the evaluated results --> true/false on the permission queries
|
103
|
+
# The first is embedded in the control logic because we want short-circuiting. If an expression
|
104
|
+
# has been parsed and the permission is false, we don't want to try different ways of parsing.
|
105
|
+
# Note that this implementation of a recursive descent parser is meant to be simple
|
106
|
+
# and doesn't allow arbitrary nesting of parentheses. It supports up to 5 levels of nesting.
|
107
|
+
# It also won't handle some types of expressions (A or B) and C, which has to be rewritten as
|
108
|
+
# C and (A or B) so the parenthetical expressions are in the tail.
|
109
|
+
module RecursiveDescentParser
|
110
|
+
|
111
|
+
OPT_PARENTHESES_PATTERN = '(([^()]|\(([^()]|\(([^()]|\(([^()]|\(([^()]|\(([^()])*\))*\))*\))*\))*\))*)'
|
112
|
+
PARENTHESES_PATTERN = '\(' + OPT_PARENTHESES_PATTERN + '\)'
|
113
|
+
NOT_PATTERN = '^\s*not\s+' + OPT_PARENTHESES_PATTERN + '$'
|
114
|
+
AND_PATTERN = '^\s*' + OPT_PARENTHESES_PATTERN + '\s+and\s+' + OPT_PARENTHESES_PATTERN + '\s*$'
|
115
|
+
OR_PATTERN = '^\s*' + OPT_PARENTHESES_PATTERN + '\s+or\s+' + OPT_PARENTHESES_PATTERN + '\s*$'
|
116
|
+
ROLE_PATTERN = '(\'\s*(.+)\s*\'|(\w+))'
|
117
|
+
MODEL_PATTERN = '(:*\w+)'
|
118
|
+
|
119
|
+
PARENTHESES_REGEX = Regexp.new('^\s*' + PARENTHESES_PATTERN + '\s*$')
|
120
|
+
NOT_REGEX = Regexp.new(NOT_PATTERN)
|
121
|
+
AND_REGEX = Regexp.new(AND_PATTERN)
|
122
|
+
OR_REGEX = Regexp.new(OR_PATTERN)
|
123
|
+
ROLE_REGEX = Regexp.new('^\s*' + ROLE_PATTERN + '\s*$')
|
124
|
+
ROLE_OF_MODEL_REGEX = Regexp.new('^\s*' + ROLE_PATTERN + '\s+(' + VALID_PREPOSITIONS_PATTERN + ')\s+' + MODEL_PATTERN + '\s*$')
|
125
|
+
|
126
|
+
def parse_authorization_expression( str )
|
127
|
+
@stack = []
|
128
|
+
raise AuthorizationExpressionInvalid, "Cannot parse authorization (#{str})" if not parse_expr( str )
|
129
|
+
return @stack.pop
|
130
|
+
end
|
131
|
+
|
132
|
+
def parse_expr( str )
|
133
|
+
parse_parenthesis( str ) or
|
134
|
+
parse_not( str ) or
|
135
|
+
parse_or( str ) or
|
136
|
+
parse_and( str ) or
|
137
|
+
parse_term( str )
|
138
|
+
end
|
139
|
+
|
140
|
+
def parse_not( str )
|
141
|
+
if str =~ NOT_REGEX
|
142
|
+
can_parse = parse_expr( $1 )
|
143
|
+
@stack.push( !@stack.pop ) if can_parse
|
144
|
+
end
|
145
|
+
false
|
146
|
+
end
|
147
|
+
|
148
|
+
def parse_or( str )
|
149
|
+
if str =~ OR_REGEX
|
150
|
+
can_parse = parse_expr( $1 ) and parse_expr( $8 )
|
151
|
+
@stack.push( @stack.pop | @stack.pop ) if can_parse
|
152
|
+
return can_parse
|
153
|
+
end
|
154
|
+
false
|
155
|
+
end
|
156
|
+
|
157
|
+
def parse_and( str )
|
158
|
+
if str =~ AND_REGEX
|
159
|
+
can_parse = parse_expr( $1 ) and parse_expr( $8 )
|
160
|
+
@stack.push(@stack.pop & @stack.pop) if can_parse
|
161
|
+
return can_parse
|
162
|
+
end
|
163
|
+
false
|
164
|
+
end
|
165
|
+
|
166
|
+
# Descend down parenthesis (allow up to 5 levels of nesting)
|
167
|
+
def parse_parenthesis( str )
|
168
|
+
str =~ PARENTHESES_REGEX ? parse_expr( $1 ) : false
|
169
|
+
end
|
170
|
+
|
171
|
+
def parse_term( str )
|
172
|
+
parse_role_of_model( str ) or
|
173
|
+
parse_role( str )
|
174
|
+
end
|
175
|
+
|
176
|
+
# Parse <role> of <model>
|
177
|
+
def parse_role_of_model( str )
|
178
|
+
if str =~ ROLE_OF_MODEL_REGEX
|
179
|
+
role_name = $2 || $3
|
180
|
+
model_name = $5
|
181
|
+
model_obj = get_model( model_name )
|
182
|
+
raise( ModelDoesntImplementRoles, "Model (#{model_name}) doesn't implement #accepts_role?" ) if not model_obj.respond_to? :accepts_role?
|
183
|
+
|
184
|
+
has_permission = model_obj.send( :accepts_role?, role_name, @current_user )
|
185
|
+
@stack.push( has_permission )
|
186
|
+
true
|
187
|
+
else
|
188
|
+
false
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# Parse <role> of the User-like object
|
193
|
+
def parse_role( str )
|
194
|
+
if str =~ ROLE_REGEX
|
195
|
+
role_name = $1
|
196
|
+
if @current_user.nil? || @current_user == :false
|
197
|
+
@stack.push(false)
|
198
|
+
else
|
199
|
+
raise( UserDoesntImplementRoles, "User doesn't implement #has_role?" ) if not @current_user.respond_to? :has_role?
|
200
|
+
@stack.push( @current_user.has_role?(role_name) )
|
201
|
+
end
|
202
|
+
true
|
203
|
+
else
|
204
|
+
false
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: permit_yo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 2
|
7
|
+
- 1
|
8
|
+
version: "2.1"
|
9
|
+
platform: ruby
|
10
|
+
authors:
|
11
|
+
- Bill Katz
|
12
|
+
- Ian Terrell
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-07-25 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: An engine that provides authorization for Rails 3 apps.
|
22
|
+
email: ian.terrell@gmail.com
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- lib/permit_yo/base.rb
|
31
|
+
- lib/permit_yo/default.rb
|
32
|
+
- lib/permit_yo/engine.rb
|
33
|
+
- lib/permit_yo/exceptions.rb
|
34
|
+
- lib/permit_yo/parser.rb
|
35
|
+
- lib/permit_yo.rb
|
36
|
+
- config/locales/en.yml
|
37
|
+
has_rdoc: true
|
38
|
+
homepage: http://github.com/ianterrell/permityo
|
39
|
+
licenses: []
|
40
|
+
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
segments:
|
60
|
+
- 0
|
61
|
+
version: "0"
|
62
|
+
requirements: []
|
63
|
+
|
64
|
+
rubyforge_project:
|
65
|
+
rubygems_version: 1.3.7
|
66
|
+
signing_key:
|
67
|
+
specification_version: 3
|
68
|
+
summary: A Rails 3 engine for managing authorization.
|
69
|
+
test_files: []
|
70
|
+
|