access_rules 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in access_rules.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 TODO: Write your name
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # AccessRules
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'access_rules'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install access_rules
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,13 @@
1
+ require "access_rules/version"
2
+ require "access_rules/rules"
3
+ require "access_rules/defining"
4
+ require "access_rules/checking"
5
+
6
+ module AccessRules
7
+ # Your code goes here...
8
+ end
9
+
10
+ ActiveRecord::Base.send( :include, AccessRules::Defining )
11
+ ActionController::Base.send( :include, AccessRules::Checking::ControllerMethods )
12
+ # TODO: this should not be included in Object
13
+ Object.send( :include, AccessRules::Checking::InstanceMethods )
@@ -0,0 +1,38 @@
1
+ module AccessRules
2
+ module Checking
3
+
4
+ module ControllerMethods
5
+
6
+ def self.included(klass)
7
+ klass.class_eval do
8
+ helper_method :check_action_rules, :check_current_action_rules
9
+ end
10
+ end
11
+
12
+ # We assume controller here
13
+ def check_current_action_rules( object, user, site = nil )
14
+ check_action_rules( params[:action], object, user, site )
15
+ end
16
+
17
+ # Controller need to respond to action_rules method
18
+ def check_action_rules( action, object, user, site = nil )
19
+ rule = action_rules[action.to_sym] || action_rules[:default]
20
+ if rule
21
+ result = rule.check( object, user, site )
22
+ return result
23
+ else
24
+ return true
25
+ end
26
+ end
27
+ end
28
+
29
+ module InstanceMethods
30
+
31
+ def rule( rule_name )
32
+ return Rules::Base.new( rule_name )
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,28 @@
1
+ module AccessRules
2
+ module Defining
3
+
4
+ def self.included(klass)
5
+ klass.class_eval do
6
+ class_attribute :rules
7
+ self.rules = {}
8
+ end
9
+ klass.extend( ClassMethods )
10
+ end
11
+
12
+ module ClassMethods
13
+
14
+ # Defines rules one by one
15
+ def define_rule( name, rule )
16
+ # class_attribute requires that the var is reassigned to make it override the inherited one
17
+ self.rules = self.rules.merge( name.to_sym => rule )
18
+ end
19
+
20
+ # Defines all rules at once
21
+ def define_rules( rules )
22
+ self.rules = rules
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,112 @@
1
+ module AccessRules::Rules
2
+
3
+ class Base
4
+
5
+ # Creates a rule given its name. Name is a dot-separated string, eg:
6
+ # forum_post.forum_thread.forum.group.member
7
+ # where
8
+ # forum_post - name of initial object class
9
+ # forum_thread.forum.group - associations to traverse: last one is supposed
10
+ # to contain the rule itself. Associations may be omitted - in this case
11
+ # initial object should contain the rule
12
+ # member - name of rule. This may be a rule defined using define_rule(s) or
13
+ # just a name of method in rule class. If it's a method it must accept:
14
+ # TODO: disregard that, now only no-arg methods work
15
+ # 2 arguments - user, site
16
+ # 1 arguments - user
17
+ # 0 arguments
18
+ # and return true/false indicating whether the rules succeeded
19
+ def initialize( rule_name )
20
+ @rule_name = rule_name
21
+ elems = rule_name.split( '.' )
22
+ klass = elems.shift.classify.constantize
23
+ proc_or_method = elems.pop
24
+ @associations = elems.dup
25
+ @associations.each do |assoc|
26
+ reflection = klass.reflect_on_association( assoc.to_sym )
27
+ raise "No rule named #{rule_name}, failed token: #{assoc}" unless reflection
28
+ klass = reflection.class_name.constantize
29
+ end
30
+ @proc = klass.rules[proc_or_method.to_sym]
31
+ unless @proc
32
+ @method_name = proc_or_method
33
+ # TODO: method_defined? fails for attribute accessors
34
+ #raise "No rule named #{rule_name}, failed token: #{@method_name}" unless klass.method_defined?( @method_name )
35
+ end
36
+ end
37
+
38
+ def check( object, user, site = nil )
39
+ # XXX: we assume has_one or belongs_to association here
40
+ object_to_check = @associations.inject( object ) { |obj, assoc| obj.send( assoc ) }
41
+
42
+ if @proc
43
+ result = @proc.call( object_to_check, user, site )
44
+ else
45
+ # TODO: check if object.class matches klass (from initialize)
46
+ result = object_to_check.send( @method_name )
47
+ # TODO: the code below fails eg. for forum.public?
48
+ #method = object_to_check.method( @method_name )
49
+ #result = case method.arity
50
+ #when 0
51
+ # method.call
52
+ #when 1
53
+ # method.call( user )
54
+ #when 2
55
+ # method.call( user, site )
56
+ #else
57
+ # raise "Can't use method #{@method_name} on #{object_to_check} with arity #{method.arity} for access rule #{@rule_name} (arity out of (0..2) range)"
58
+ #end
59
+ end
60
+ Rails.logger.debug( "----------access rule check: #{@rule_name}: #{result}" )
61
+ return result
62
+ end
63
+
64
+ # AND rule
65
+ def & (rule)
66
+ return And.new( self, rule )
67
+ end
68
+
69
+ # OR rule
70
+ def | (rule)
71
+ return Or.new( self, rule )
72
+ end
73
+
74
+ # NOT rule
75
+ def ~
76
+ Not.new( @rule_name )
77
+ end
78
+ end
79
+
80
+ class And < Base
81
+
82
+ def initialize( *rules )
83
+ @rules = rules
84
+ end
85
+
86
+ def check( object, user, site = nil )
87
+ @rules.all? { |rule| rule.check( object, user, site ) }
88
+ end
89
+
90
+ end
91
+
92
+ class Or < Base
93
+
94
+ def initialize( *rules )
95
+ @rules = rules
96
+ end
97
+
98
+ def check( object, user, site = nil )
99
+ @rules.any? { |rule| rule.check( object, user, site ) }
100
+ end
101
+
102
+ end
103
+
104
+ class Not < Base
105
+
106
+ def check( object, user, site = nil )
107
+ ! super
108
+ end
109
+
110
+ end
111
+
112
+ end
@@ -0,0 +1,3 @@
1
+ module AccessRules
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,9 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'test/unit'
3
+
4
+ class AccessRulesTest < Test::Unit::TestCase
5
+ # Replace this with your real tests.
6
+ def test_this_plugin
7
+ flunk
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: access_rules
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Marek Janukowicz
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-07 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Authorization for Rails
15
+ email:
16
+ - marek@janukowicz.net
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - lib/access_rules/checking.rb
22
+ - lib/access_rules/version.rb
23
+ - lib/access_rules/defining.rb
24
+ - lib/access_rules/rules.rb
25
+ - lib/access_rules.rb
26
+ - Gemfile
27
+ - LICENSE.txt
28
+ - Rakefile
29
+ - README.md
30
+ - test/access_rules_test.rb
31
+ homepage: ''
32
+ licenses: []
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubyforge_project:
51
+ rubygems_version: 1.8.24
52
+ signing_key:
53
+ specification_version: 3
54
+ summary: ''
55
+ test_files:
56
+ - test/access_rules_test.rb