Fingertips-authorization-san 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ (c) 2009 Fingertips, Manfred Stienstra <m.stienstra@fngtps.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to
5
+ deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ sell copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,21 @@
1
+ = Authorization-San
2
+
3
+ Authorization-san allows you to specify access policies in your controllers. The plugin assumes a number of things about the application.
4
+
5
+ * If a user has authenticated with the application, it's stored in <tt>@authenticated</tt>. The method of authentication doesn't matter.
6
+ * <tt>@authenticated</tt> has either a <tt>role</tt> attribute or a number of methods to query for the role: <tt>admin?</tt>, <tt>editor?</tt>, <tt>guest?</tt>. When the <tt>@authenticated</tt> object doesn't have role methods it's
7
+
8
+ == What does it look like?
9
+
10
+ class BooksController < ActionController::Base
11
+ # Visitors can see list of books and book pages
12
+ allow_access :all, :only => [:index, :show]
13
+ # An editor can create new books, but…
14
+ allow_access :editor, :only => [:new, :create]
15
+ # …she can only update her own books.
16
+ allow_access(:editor, :only => [:edit, :update]) { @book = @authenticated.books.find(params[:id]) }
17
+ # Admin users can do it all.
18
+ allow_access :admin
19
+ end
20
+
21
+ The best place to start learning more is the <tt>examples</tt> directory in the source.
@@ -0,0 +1,2 @@
1
+ require 'authorization/allow_access'
2
+ require 'authorization/block_access'
@@ -0,0 +1,78 @@
1
+ module Authorization
2
+ module AllowAccess
3
+ # By default you block all access to the controller with <tt>block_access</tt>, with <tt>allow_access</tt> you
4
+ # specify who can access the actions on the controller under certain conditions. <tt>allow_access</tt> can deal
5
+ # with accounts with and without roles.
6
+ #
7
+ # *Examples*
8
+ #
9
+ # Everyone can access all actions on the controller.
10
+ # allow_access
11
+ # allow_access :all
12
+ # Everyone with the admin role can access the controller.
13
+ # allow_access :admin
14
+ # Everyone with the admin and editor role can access the controller.
15
+ # allow_access :admin, :editor
16
+ # Everyone with the editor role can access the index. show, edit and update actions.
17
+ # allow_access :editor, :only => [:index, :show, :edit, :update]
18
+ # A coordinator can do anything the admin can, except for delete
19
+ # allow_access :coordinator, :except => :destroy
20
+ # Everyone with the admin and editor role can access the show action.
21
+ # allow_access :admin, :editor, :action => :show
22
+ # A guest can view all resources if he has view permissions. The block is evaltuated in the controller's instance.
23
+ # Note that rules are evaluated when <tt>block_access</tt> is run.
24
+ # allow_access(:guest, :only => [:index, :show]) { @authenticated.view_permission? }
25
+ # Specifying a role is optional, if you don't specify a role the rule is added for the default role <tt>:all</tt>.
26
+ # allow_access(:only => :unsubscribe) { @authenticated.subscribed? }
27
+ # Only allow authenticated users, :authenticated is a special role meaning all authenticated users.
28
+ # allow_access :authenticated
29
+ # You need to be authenticated for the secret action
30
+ # allow_access :all, :except => :secret
31
+ # allow_access :authenticated, :only => :secret
32
+ #
33
+ # The following special directives might be a little hard to explain, I will give the equivalent rule with the
34
+ # block access.
35
+ #
36
+ # Imagine we have a user controller, every user has an organization association. The users resource is nested
37
+ # in the organization resource like this.
38
+ # map.resources :organizations { |org| org.resources :users }
39
+ # Now we want the user to edit his own resource (for instance to update the password).
40
+ # allow_access :only => [:index, :show, :edit, :update], :user_resource => true
41
+ # allow_access(:only => [:index, :show, :edit, :update]) do
42
+ # @authenticated.id == params[:id].to_i
43
+ # end
44
+ # We could also specify that a user can edit everything in his own organization.
45
+ # allow_access :only => [:index, :show, :edit, :update], :scope => :organization
46
+ # allow_access(:only => [:index, :show, :edit, :update]) do
47
+ # @authenticated.organization.id == params[:organization_id].to_i
48
+ # end
49
+ def allow_access(*args, &block)
50
+ unless self.respond_to?(:access_allowed_for)
51
+ self.class_inheritable_accessor(:access_allowed_for)
52
+ send(:protected, :access_allowed_for, :access_allowed_for=)
53
+ end
54
+ self.access_allowed_for ||= HashWithIndifferentAccess.new
55
+ if args.first.kind_of?(Hash) || args.empty?
56
+ self.access_allowed_for[:all] ||= []
57
+ self.access_allowed_for[:all] << {
58
+ :directives => args.first || {},
59
+ :block => block
60
+ }
61
+ else
62
+ directives = args.last.kind_of?(Hash) ? args.pop : {}
63
+ roles = args.flatten
64
+ if roles.delete(:authenticated) or roles.delete('authenticated')
65
+ roles = [:all] if roles.empty?
66
+ directives[:authenticated] = true
67
+ end
68
+ roles.each do |role|
69
+ self.access_allowed_for[role.to_s] ||= []
70
+ self.access_allowed_for[role.to_s] << {
71
+ :directives => directives,
72
+ :block => block
73
+ }
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,133 @@
1
+ module Authorization
2
+ module BlockAccess
3
+ protected
4
+
5
+ # Block access to all actions in the controller, designed to be used as a <tt>before_filter</tt>.
6
+ # class ApplicationController < ActionController::Base
7
+ # before_filter :block_access
8
+ # end
9
+ def block_access
10
+ die_if_undefined
11
+ unless @authenticated.nil?
12
+ # Find the user's roles
13
+ roles = []
14
+ roles << @authenticated.role if @authenticated.respond_to?(:role)
15
+ access_allowed_for.keys.each do |role|
16
+ roles << role.to_s if @authenticated.respond_to?("#{role}?") and @authenticated.__send__("#{role}?")
17
+ end
18
+ # Check if any of the roles give her access
19
+ roles.each do |role|
20
+ return true if access_allowed?(params, role, @authenticated)
21
+ end
22
+ end
23
+ return true if access_allowed?(params, :all, @authenticated)
24
+ access_forbidden
25
+ end
26
+
27
+ # Checks if access is allowed for the params, role and authenticated user.
28
+ # access_allowed?({:action => :show, :id => 1}, :admin, @authenticated)
29
+ def access_allowed?(params, role, authenticated=nil)
30
+ die_if_undefined
31
+ if (rules = access_allowed_for[role]).nil?
32
+ logger.debug(" \e[31mCan't find rules for `#{role}'\e[0m")
33
+ return false
34
+ end
35
+ !rules.detect do |rule|
36
+ if !action_allowed_by_rule?(rule, params, role) or !resource_allowed_by_rule?(rule, params, role, authenticated) or !block_allowed_by_rule?(rule)
37
+ logger.debug(" \e[31mAccess DENIED by RULE #{rule.inspect} FOR `#{role}'\e[0m")
38
+ false
39
+ else
40
+ logger.debug(" \e[32mAccess GRANTED by RULE #{rule.inspect} FOR `#{role}'\e[0m")
41
+ true
42
+ end
43
+ end.nil?
44
+ end
45
+
46
+ # <tt>access_forbidden</tt> is called by <tt>block_access</tt> when access is forbidden. This method does
47
+ # nothing by default. Make sure you return <tt>false</tt> from the method if you want to halt the filter
48
+ # chain.
49
+ def access_forbidden
50
+ false
51
+ end
52
+
53
+ # Checks if a certain action can be accessed by the role.
54
+ # If you want to check for <tt>action_allowed?</tt>, <tt>resource_allowed?</tt> and <tt>block_allowed?</tt>
55
+ # use <tt>access_allowed?</tt>.
56
+ # action_allowed?({:action => :show, :id => 1}, :editor)
57
+ def action_allowed?(params, role=:all)
58
+ die_if_undefined
59
+ return false if (rules = access_allowed_for[role]).nil?
60
+ !rules.detect { |rule| action_allowed_by_rule?(rule, params, role) }.nil?
61
+ end
62
+
63
+ def action_allowed_by_rule?(rule, params, role) #:nodoc:
64
+ return false if (action = params[:action]).nil?
65
+ directives = rule[:directives]
66
+ return false if directives[:only].kind_of?(Array) and !directives[:only].include?(action.to_sym)
67
+ return false if directives[:only].kind_of?(Symbol) and directives[:only] != action.to_sym
68
+ return false if directives[:except].kind_of?(Array) and directives[:except].include?(action.to_sym)
69
+ return false if directives[:except].kind_of?(Symbol) and directives[:except] == action.to_sym
70
+ true
71
+ end
72
+
73
+ # Checks if the resource indicated by the params can be accessed by user.
74
+ # If you want to check for <tt>action_allowed?</tt>, <tt>resource_allowed?</tt> and <tt>block_allowed?</tt>
75
+ # use <tt>access_allowed?</tt>.
76
+ # resource_allowed?({:id => 1, :organization_id => 12}, :guest, @authenticated)
77
+ def resource_allowed?(params, role=:all, user=nil)
78
+ user ||= @authenticated
79
+ die_if_undefined
80
+ return false if (rules = access_allowed_for[role]).nil?
81
+ !rules.detect { |rule| resource_allowed_by_rule?(rule, params, role, user) }.nil?
82
+ end
83
+
84
+ def resource_allowed_by_rule?(rule, params, role, user) #:nodoc:
85
+ directives = rule[:directives]
86
+ if directives[:authenticated]
87
+ return false unless user
88
+ end
89
+ begin
90
+ if directives[:user_resource]
91
+ return false if params[:id].nil? or user.id.nil?
92
+ return false if params[:id].to_i != user.id.to_i
93
+ end
94
+ rescue NoMethodError
95
+ end
96
+ begin
97
+ if scope = directives[:scope]
98
+ assoc_id = params["#{scope}_id"].to_i
99
+ begin
100
+ object_id = user.__send__(scope).id.to_i
101
+ rescue NoMethodError
102
+ return false
103
+ end
104
+ return false if assoc_id.nil? or object_id.nil?
105
+ return false if assoc_id != object_id
106
+ end
107
+ rescue NoMethodError
108
+ end
109
+ true
110
+ end
111
+
112
+ # Checks if the blocks associated with the rules doesn't stop the user from acessing the resource.
113
+ # If you want to check for <tt>action_allowed?</tt>, <tt>resource_allowed?</tt> and <tt>block_allowed?</tt>
114
+ # use <tt>access_allowed?</tt>.
115
+ # block_allowed?(:guest)
116
+ def block_allowed?(role)
117
+ die_if_undefined
118
+ return false if (rules = access_allowed_for[role]).nil?
119
+ !rules.detect { |rule| block_allowed_by_rule?(rule) }.nil?
120
+ end
121
+
122
+ def block_allowed_by_rule?(rule) #:nodoc:
123
+ return false if !rule[:block].nil? and !rule[:block].bind(self).call
124
+ true
125
+ end
126
+
127
+ def die_if_undefined #:nodoc:
128
+ if !self.respond_to?(:access_allowed_for) or access_allowed_for.nil?
129
+ raise ArgumentError, "Please specify access control using `allow_access' in the controller"
130
+ end
131
+ end
132
+ end
133
+ end
data/rails/init.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'authorization'
2
+
3
+ ActionController::Base.send(:include, Authorization::BlockAccess)
4
+ ActionController::Base.send(:extend, Authorization::AllowAccess)
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: Fingertips-authorization-san
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Manfred Stienstra
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-09 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: A plugin for authorization in a ReSTful application.
17
+ email: manfred@fngtps.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ - LICENSE
25
+ files:
26
+ - lib/authorization.rb
27
+ - lib/authorization/allow_access.rb
28
+ - lib/authorization/block_access.rb
29
+ - rails/init.rb
30
+ - README.rdoc
31
+ - LICENSE
32
+ has_rdoc: true
33
+ homepage: http://fingertips.github.com
34
+ post_install_message:
35
+ rdoc_options:
36
+ - --inline-source
37
+ - --charset=UTF-8
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ version:
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ requirements: []
53
+
54
+ rubyforge_project:
55
+ rubygems_version: 1.2.0
56
+ signing_key:
57
+ specification_version: 2
58
+ summary: A plugin for authorization in a ReSTful application.
59
+ test_files: []
60
+