authorize_me 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 [name of plugin creator]
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
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,74 @@
1
+ = authorize_me
2
+
3
+ authorize_me is a gem for Rails to handle simple role-based authorization. It is similar in style to can-can.
4
+ The largest difference is that authorization rules are defined in the model they protect rather than one centralized location.
5
+
6
+ == Set up the user model
7
+
8
+ Tell the gem which model to treat as the "user".
9
+
10
+ class User
11
+ authorize_me
12
+ end
13
+
14
+ The following methods are generated:
15
+
16
+ User#can_create?(obj)
17
+ User#can_read?(obj)
18
+ User#can_update?(obj)
19
+ User#can_destroy?(obj)
20
+
21
+ Each of these methods can take a model class, instance, or symbol.
22
+
23
+ The user model is expected to have a role method that returns a string or symbol.
24
+ It could be a DB column or a method you define. Here is an example:
25
+
26
+ def role
27
+ if admin?
28
+ :admin
29
+ else
30
+ user_type
31
+ end
32
+ end
33
+
34
+ == Declare authorization rules
35
+
36
+ Authorization rules are declared in each model where they apply
37
+
38
+ class Article
39
+ authorization do |role|
40
+ role.admin :can => :manage
41
+ role.publisher :can => :manage, :if => :author?
42
+ role.publisher :can => [:read, :create]
43
+ role.any :can => :read
44
+ end
45
+ end
46
+
47
+ In this example a publisher can always read and create articles,
48
+ but they can only manage articles for which they are the author.
49
+ This declaration assumes there is an Article#author? method which
50
+ takes a user argument and returns a boolean.
51
+
52
+ :manage is shorthand for [:create, :read, :update, :destroy]
53
+
54
+ == In your controllers
55
+
56
+ The unauthorized! method simply raises an AuthorizeMe::Unauthorized exception
57
+ for you to handle as you choose.
58
+
59
+ def show
60
+ @article = Article.find(params[:id])
61
+ unauthorized! unless current_user.can_read?(@article)
62
+ end
63
+
64
+ == In your views
65
+
66
+ <% if current_user.can_update?(@article) %>
67
+ <%= link_to 'edit', edit_article_path(@article) %>
68
+ <% end %>
69
+
70
+ Copyright (c) 2010 Adam McCrea, released under the MIT license
71
+
72
+
73
+
74
+
@@ -0,0 +1,6 @@
1
+ require 'authorize_me/model'
2
+ require 'authorize_me/controller'
3
+ require 'authorize_me/ability_checker'
4
+ require 'authorize_me/role_definition'
5
+ require 'authorize_me/exceptions'
6
+
@@ -0,0 +1,53 @@
1
+ module AuthorizeMe
2
+ class AbilityChecker
3
+ def initialize(ability, target, association, user)
4
+ @ability, @target, @association, @user = ability, target, association, user
5
+ @target = @target.to_s if @target.is_a?(Symbol)
6
+ end
7
+
8
+ def check
9
+ return false if access_rule.nil?
10
+
11
+ if_condition_met = access_rule[:if].nil? || call_method(access_rule[:if])
12
+ unless_condition_met = access_rule[:unless].nil? || !call_method(access_rule[:unless])
13
+
14
+ if_condition_met && unless_condition_met
15
+ end
16
+
17
+ protected
18
+
19
+ def object
20
+ @object ||= if @target.is_a?(String)
21
+ build_model_object
22
+ elsif ! @target.class.respond_to?(:authorization_rules)
23
+ raise AuthorizeMe::AuthorizationRuleMissing.new(@target)
24
+ else
25
+ @target
26
+ end
27
+ end
28
+
29
+ def build_model_object
30
+ if @association
31
+ @association.send(@target.pluralize).new
32
+ else
33
+ @target.singularize.camelize.constantize.new
34
+ end
35
+ end
36
+
37
+ def rules
38
+ object.class.authorization_rules[@user.role.to_sym] || {}
39
+ end
40
+
41
+ def access_rule
42
+ rules[@ability.to_sym] || rules[:manage]
43
+ end
44
+
45
+ def call_method(method)
46
+ arity = object.send(:method, method).arity
47
+ case arity.abs
48
+ when 0 then object.send(method)
49
+ when 1 then object.send(method, @user)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,11 @@
1
+ module AuthorizeMe
2
+ module Controller
3
+
4
+ private
5
+
6
+ def unauthorized!
7
+ raise AuthorizeMe::Unauthorized
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ module AuthorizeMe
2
+
3
+ class AuthorizationRuleMissing < Exception
4
+ def initialize(obj)
5
+ @obj = obj
6
+ end
7
+
8
+ def message
9
+ "AuthorizeMe tried to access #{@obj.inspect}, which does not declare authorization rules"
10
+ end
11
+ end
12
+
13
+ class Unauthorized < Exception; end
14
+
15
+ end
16
+
@@ -0,0 +1,70 @@
1
+ require 'active_support/core_ext'
2
+
3
+ module AuthorizeMe
4
+ module Model
5
+
6
+ def self.included(base)
7
+ base.extend ClassMethods
8
+ base.send :include, InstanceMethods
9
+ end
10
+
11
+ module ClassMethods
12
+ # define a bunch of methods on extended class
13
+ # * User#can_create?(obj)
14
+ # * User#can_read?(obj)
15
+ # * User#can_update?(obj)
16
+ # * User#can_destroy?(obj)
17
+ def authorize_me
18
+ %w{ create read update destroy }.each do |ability|
19
+ define_method "can_#{ability}?" do |*args|
20
+ obj = args[0]
21
+ association_options = args[1] || {}
22
+ check_ability_on_object ability, obj, association_options
23
+ end
24
+ end
25
+ end
26
+
27
+ # declare authorization rules on a model. For example
28
+ # authorize do |role|
29
+ # role.owner :can => :manage
30
+ # role.admin :can => :manage
31
+ # role.member :can => :read, :if => :has_application_read_permission?
32
+ # role.member :can => [:create, :update, :destroy], :if => :has_application_write_permission?
33
+ # end
34
+ #
35
+ def authorize
36
+ yield AuthorizeMe::RoleDefinition.new(self)
37
+ end
38
+
39
+ def add_authorization_rule(role, options)
40
+ role = role.to_sym
41
+ abilities = options[:can]
42
+ abilities = [abilities] unless abilities.is_a?(Array)
43
+
44
+ @authorization_rules ||= {}
45
+ @authorization_rules[role] ||= {}
46
+
47
+ abilities.each do |ability|
48
+ @authorization_rules[role][ability.to_sym] = {}
49
+ @authorization_rules[role][ability.to_sym][:if] = options[:if]
50
+ @authorization_rules[role][ability.to_sym][:unless] = options[:unless]
51
+ end
52
+ end
53
+
54
+ def authorization_rules
55
+ @authorization_rules || {}
56
+ end
57
+ end
58
+
59
+ module InstanceMethods
60
+ protected
61
+ def check_ability_on_object(ability, target, association_options)
62
+ association = association_options[:for]
63
+ checker = AuthorizeMe::AbilityChecker.new(ability, target, association, self)
64
+ checker.check
65
+ end
66
+ end
67
+
68
+ end
69
+ end
70
+
@@ -0,0 +1,15 @@
1
+ module AuthorizeMe
2
+ class RoleDefinition
3
+ def initialize(model_class)
4
+ @model_class = model_class
5
+ end
6
+
7
+ def method_missing(name, *args)
8
+ if args.length == 1 && args.first.is_a?(Hash)
9
+ @model_class.add_authorization_rule(name, args.first)
10
+ else
11
+ super
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ module AuthorizeMe
2
+ Version = "0.1.0"
3
+ end
@@ -0,0 +1,2 @@
1
+ ActiveRecord::Base.send(:include, AuthorizeMe::Model)
2
+ ActionController::Base.send(:include, AuthorizeMe::Controller)
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: authorize_me
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Adam McCrea
13
+ - John Andrews
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-12-10 00:00:00 -05:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Simple role-based authorization
23
+ email: adam@edgecase.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - MIT-LICENSE
30
+ - README.rdoc
31
+ files:
32
+ - lib/authorize_me/ability_checker.rb
33
+ - lib/authorize_me/controller.rb
34
+ - lib/authorize_me/exceptions.rb
35
+ - lib/authorize_me/model.rb
36
+ - lib/authorize_me/role_definition.rb
37
+ - lib/authorize_me/version.rb
38
+ - lib/authorize_me.rb
39
+ - rails/init.rb
40
+ - MIT-LICENSE
41
+ - README.rdoc
42
+ has_rdoc: true
43
+ homepage: http://github.com/edgecase/authorize_me
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options: []
48
+
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 0
57
+ version: "0"
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.3.6
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: Simple role-based authorization
72
+ test_files: []
73
+