arsecurity 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,3 @@
1
+ Changes in version 0.1.0 (2009-03-16)
2
+ -------------------------------------
3
+ initial release
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 [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.
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ PKG_NAME = "arsecurity"
4
+ PKG_VERSION = "0.1.0"
5
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
6
+ PKG_FILES = FileList[
7
+ '[A-Z]*',
8
+ 'lib/**/*',
9
+ 'examples/**/*'
10
+ ]
11
+ spec = Gem::Specification.new do |s|
12
+ s.platform = Gem::Platform::RUBY
13
+ s.summary = "A security component for Activerecord"
14
+ s.name = PKG_NAME
15
+ s.version = PKG_VERSION
16
+ s.require_path = 'lib'
17
+ s.homepage = %q{http://arsecurity.rubyforge.org/}
18
+ s.rubyforge_project = 'Activerecord Security'
19
+ s.has_rdoc = false
20
+ s.authors = ["Leon Li"]
21
+ s.email = "scorpio_leon@hotmail.com"
22
+ s.files = PKG_FILES
23
+ s.description = <<-EOF
24
+ A security component for Activerecord, it can manage CRUD permissions with attribute level by configuration, you can implement RBAC easily with it. It depend on the AOP framework Rinter(Rinterceptor) and the OO query tool Rquerypad(Optinal)
25
+ EOF
26
+ s.add_dependency('rinterceptor', '>= 0.1.0')
27
+ end
28
+ Rake::GemPackageTask.new(spec) do |pkg|
29
+ pkg.need_zip = true
30
+ pkg.need_tar = true
31
+ end
@@ -0,0 +1,37 @@
1
+ ActiveRecord::Base.class_eval do
2
+ include ArsecurityDefault
3
+ def self.rinter_skip?
4
+ !YourContext.security_check
5
+ end
6
+ def rinter_skip?
7
+ !YourContext.security_check
8
+ end
9
+ end
10
+ def free_access(&block)
11
+ old_security_check = YourContext.security_check
12
+ YourContext.security_check = false
13
+ result = yield
14
+ YourContext.security_check = old_security_check
15
+ result
16
+ end
17
+ class YourSecurityHandler < DefaultArsecurityHandler
18
+ class << self
19
+ #override
20
+ def accept?
21
+ current_user && current_user.is_admin?
22
+ end
23
+ #override
24
+ def reject?
25
+ false
26
+ end
27
+ #override
28
+ def permissions
29
+ current_user && current_user.permissions
30
+ end
31
+
32
+ def current_user
33
+ YourContext.your_user
34
+ end
35
+ end
36
+ end
37
+ ArsecurityUtil.handler = YourSecurityHandler
data/lib/arsecurity.rb ADDED
@@ -0,0 +1,58 @@
1
+ require 'rinterceptor'
2
+ module Arsecurity
3
+ CREATE = 'create'
4
+ READ = 'read'
5
+ UPDATE = 'update'
6
+ DELETE = 'delete'
7
+ def rinter_update_around(invocation)
8
+ if ArsecurityUtil.authorized?(UPDATE, invocation.object.class.name, invocation.object, invocation)
9
+ return invocation.invoke
10
+ else
11
+ raise ArsecurityNotAuthorizedException
12
+ end
13
+ end
14
+ def rinter_create_around(invocation)
15
+ if ArsecurityUtil.authorized?(CREATE, invocation.object.class.name, invocation.object, invocation)
16
+ return invocation.invoke
17
+ else
18
+ raise ArsecurityNotAuthorizedException
19
+ end
20
+ end
21
+ def rinter_delete_around(invocation)
22
+ if ArsecurityUtil.authorized?(DELETE, invocation.object.class.name, invocation.object, invocation)
23
+ return invocation.invoke
24
+ else
25
+ raise ArsecurityNotAuthorizedException
26
+ end
27
+ end
28
+ module ClassMethods
29
+ def rinter_update_around(invocation)
30
+ if ArsecurityUtil.authorized?(UPDATE, invocation.object.name, nil, invocation)
31
+ return invocation.invoke
32
+ else
33
+ raise ArsecurityNotAuthorizedException
34
+ end
35
+ end
36
+ def rinter_read_around(invocation)
37
+ if ArsecurityUtil.authorized?(READ, invocation.object.name, nil, invocation)
38
+ return invocation.invoke
39
+ else
40
+ raise ArsecurityNotAuthorizedException
41
+ end
42
+ end
43
+ def rinter_delete_around(invocation)
44
+ if ArsecurityUtil.authorized?(DELETE, invocation.object.name, nil, invocation)
45
+ return invocation.invoke
46
+ else
47
+ raise ArsecurityNotAuthorizedException
48
+ end
49
+ end
50
+ end
51
+ include Rinterceptor
52
+ end
53
+
54
+ class ArsecurityNotAuthorizedException < RuntimeError
55
+ end
56
+
57
+ class ArsecurityIllegalException < RuntimeError
58
+ end
@@ -0,0 +1,53 @@
1
+
2
+
3
+ module ArsecurityDefault
4
+ #value can be regexp, symbol or string
5
+ CLASS_READ_METHOD = ["find_every", "count"]
6
+ CLASS_DELETE_METHOD = "delete_all"
7
+ CLASS_UPDATE_METHOD = "update_all"
8
+ INSTANCE_CREATE = {:create => :create}
9
+ INSTANCE_DELETE = {:delete => /^destroy$/}
10
+ INSTANCE_UPDATE = {:update => :update}
11
+ CLASS_READ = {:read => CLASS_READ_METHOD}
12
+ CLASS_DELETE = {:delete => CLASS_DELETE_METHOD}
13
+ CLASS_UPDATE = {:update => CLASS_UPDATE_METHOD}
14
+ INCLUDE_I_METHODS = INSTANCE_CREATE.merge(INSTANCE_UPDATE).merge(INSTANCE_DELETE)
15
+ INCLUDE_S_METHODS = CLASS_READ.merge(CLASS_UPDATE).merge(CLASS_DELETE)
16
+ def self.rinter_before_include_class(base)
17
+ base.instance_variable_set(:@include_i_methods, INCLUDE_I_METHODS)
18
+ base.instance_variable_set(:@include_s_methods, INCLUDE_S_METHODS)
19
+ end
20
+ include Arsecurity
21
+ end
22
+
23
+ class DefaultArsecurityHandler < ArsecurityHandler
24
+ class << self
25
+ def get_conditions(invocation)
26
+ case invocation.method
27
+ when *ArsecurityDefault::CLASS_READ_METHOD
28
+ args = invocation.args || []
29
+ options = args.extract_options!
30
+ invocation.args = args
31
+ invocation.options = options
32
+ conditions = options[:conditions]
33
+ when ArsecurityDefault::CLASS_DELETE_METHOD
34
+ conditions = invocation.args[0]
35
+ when ArsecurityDefault::CLASS_UPDATE_METHOD
36
+ conditions = invocation.args[1]
37
+ end
38
+ conditions
39
+ end
40
+
41
+ def set_conditions(invocation, conditions)
42
+ case invocation.method
43
+ when *ArsecurityDefault::CLASS_READ_METHOD
44
+ options = invocation.options
45
+ options[:conditions] = conditions
46
+ when ArsecurityDefault::CLASS_DELETE_METHOD
47
+ invocation.args[0] = conditions
48
+ when ArsecurityDefault::CLASS_UPDATE_METHOD
49
+ invocation.args[1] = conditions
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,24 @@
1
+ class ArsecurityHandler
2
+ class << self
3
+ #for customize logic, such as for administrator
4
+ def accept?
5
+ raise ArsecurityIllegalException.new("ArsecurityHandler.accept? should be implemented")
6
+ end
7
+ #for customize logic, such as for time restriction
8
+ def reject?
9
+ raise ArsecurityIllegalException.new("ArsecurityHandler.reject? should be implemented")
10
+ end
11
+ def permissions
12
+ raise ArsecurityIllegalException.new("ArsecurityHandler.permissions should be implemented")
13
+ end
14
+
15
+ #for changing conditions
16
+ def get_conditions(invocation)
17
+ raise ArsecurityIllegalException.new("ArsecurityHandler.get_conditions should be implemented")
18
+ end
19
+
20
+ def set_conditions(invocation, conditions)
21
+ raise ArsecurityIllegalException.new("ArsecurityHandler.set_conditions should be implemented")
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,9 @@
1
+ class ArsecurityPermission
2
+ attr_accessor :type, :method, :instance_condition, :sql_condition
3
+ def initialize(permission)
4
+ @type = permission[:type]
5
+ @method = permission[:method]
6
+ @instance_condition = permission[:instance_condition]
7
+ @sql_condition = permission[:sql_condition]
8
+ end
9
+ end
@@ -0,0 +1,90 @@
1
+ class ArsecurityUtil
2
+ class << self
3
+ attr_accessor :handler
4
+ def authorized?(method, type, instance, invocation)
5
+ return true if handler.accept?
6
+ return false if handler.reject?
7
+ result = false
8
+ permissions = handler.permissions
9
+
10
+ unless permissions.nil? || permissions.empty?
11
+ result = check_permissions(permissions, method, type, instance, invocation)
12
+ end
13
+ result
14
+ end
15
+
16
+ def check_permissions(permissions, method, type, instance, invocation)
17
+
18
+ permissions.each do |permission|
19
+ permission = ArsecurityPermission.new(permission) if permission.is_a?(Hash)
20
+ next if permission.type != type
21
+ unless permission.method.nil?
22
+ next if permission.method != method
23
+ end
24
+ #instance not nil mean persist
25
+
26
+ unless instance.nil?
27
+ if permission.instance_condition.nil? || permission.instance_condition.empty?
28
+ return true
29
+ else
30
+ result = ERB.new("<% result = (#{permission.instance_condition}) ? true : false %><%= result %>").result(permission.send(:binding))
31
+ return true if result == 'true'
32
+ end
33
+ else
34
+ #singleton methods, mean has permission to do this action, but check if there is any restriction need be attached
35
+ unless permission.sql_condition.nil? || permission.sql_condition.empty?
36
+ conditions = handler.get_conditions(invocation)
37
+ if conditions.nil? || conditions.empty?
38
+ conditions = permission.sql_condition
39
+ elsif conditions.is_a?(String)
40
+ conditions = "(" << conditions << ") and (" << permission.sql_condition << ")"
41
+ elsif conditions.is_a?(Array)
42
+ conditions[0] = "(" << conditions[0] << ") and (" << permission.sql_condition << ")"
43
+ elsif conditions.is_a?(Hash)
44
+ new_conditions = []
45
+ new_conditions[0] = ""
46
+ conditions.each do |k, v|
47
+ new_conditions[0] << " #{k} = #{attribute_condition(v)}"
48
+ if v.is_a?(Range)
49
+ new_conditions << v.first
50
+ new_conditions << v.last
51
+ else
52
+ new_conditions << v
53
+ end
54
+ end
55
+ conditions = new_conditions
56
+ conditions[0] = "(" << conditions[0] << ") and (" << permission.sql_condition << ")"
57
+ end
58
+ handler.set_conditions(invocation, conditions)
59
+ end
60
+ return true
61
+ end
62
+ end
63
+ false
64
+ end
65
+
66
+ def has_permission(permission, method, type, instance)
67
+ return false if permission.type != type
68
+
69
+ unless permission.method.nil?
70
+ return false if permission.method != method
71
+ end
72
+
73
+ if permission.instance_condition.blank?
74
+ return true
75
+ else
76
+ result = ERB.new("<% result = (#{permission.instance_condition}) ? true : false %><%= result %>").result(permission.send(:binding))
77
+ return result == 'true'
78
+ end
79
+ end
80
+
81
+ def attribute_condition(argument)
82
+ case argument
83
+ when nil then "IS ?"
84
+ when Array, ActiveRecord::Associations::AssociationCollection then "IN (?)"
85
+ when Range then "BETWEEN ? AND ?"
86
+ else "= ?"
87
+ end
88
+ end
89
+ end
90
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: arsecurity
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Leon Li
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-17 00:00:00 +08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rinterceptor
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.1.0
24
+ version:
25
+ description: A security component for Activerecord, it can manage CRUD permissions with attribute level by configuration, you can implement RBAC easily with it. It depend on the AOP framework Rinter(Rinterceptor) and the OO query tool Rquerypad(Optinal)
26
+ email: scorpio_leon@hotmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - MIT-LICENSE
35
+ - Rakefile
36
+ - CHANGELOG
37
+ - lib/arsecurity.rb
38
+ - lib/arsecurity_permission.rb
39
+ - lib/arsecurity_handler.rb
40
+ - lib/arsecurity_default.rb
41
+ - lib/arsecurity_util.rb
42
+ - examples/initializers
43
+ - examples/initializers/security.rb
44
+ has_rdoc: false
45
+ homepage: http://arsecurity.rubyforge.org/
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
+ version: "0"
56
+ version:
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ requirements: []
64
+
65
+ rubyforge_project: Activerecord Security
66
+ rubygems_version: 1.3.1
67
+ signing_key:
68
+ specification_version: 2
69
+ summary: A security component for Activerecord
70
+ test_files: []
71
+