permissable 0.2.1 → 0.2.2

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
1
+ 0.2.2
data/lib/permissable.rb CHANGED
@@ -15,6 +15,7 @@
15
15
  require 'permissable/member'
16
16
  require 'permissable/permission'
17
17
  require 'permissable/resource'
18
+ require 'permissable/permissions_cache'
18
19
 
19
20
  module Permissable
20
21
 
@@ -22,7 +23,13 @@ module Permissable
22
23
 
23
24
  def included(base)
24
25
  base.extend ClassMethods
25
- end
26
+ end
27
+
28
+ # Creates a hash from a resource to be used in a where context.
29
+ def flatten_resource(obj)
30
+ return { :resource_id => obj.id, :resource_type => obj.base_class.to_s } unless obj.is_a?(Array)
31
+ { :resource_id => obj.collect{ |o| o.id }, :resource_type => obj.collect{ |o| o.base_class.to_s } }
32
+ end
26
33
 
27
34
  end
28
35
 
@@ -71,21 +78,20 @@ module Permissable
71
78
 
72
79
  # Our association also creates a has_many association on our permissions table.
73
80
  assoc.class_eval do
74
- has_many(:permissions, :as => :member, :conditions => { :member_type => "#{self.to_s}" }), :dependent => :destroy unless respond_to? :permissions
81
+ has_many(:permissions, :as => :member, :dependent => :destroy) unless respond_to? :permissions
75
82
  include Permissable::Member
76
- class_inheritable_accessor :permission_types
77
- write_inheritable_attribute(:permissable_associations, {})
83
+ class_inheritable_accessor :permissable_types
84
+ self.send :permissable_types=, options[:to]
78
85
  write_inheritable_attribute(:permissable_options, {}) if permissable_options.nil?
79
86
  permissable_options[:allow_permission_with_method] = options[:allow_with] if options.has_key?(:allow_with)
80
- permissable_options[:permission_chain] = options[:chain] if options.has_key?(:chain)
81
- self.send :permission_types=, options[:to]
87
+ permissable_options[:permission_chain] = options[:chain] if options.has_key?(:chain)
82
88
  end
83
89
 
84
90
  end
85
91
 
86
92
  # Setup a has_many association of permissions on our resource.
87
93
  resource.constantize.class_eval do
88
- has_many(:permissions, :as => :resource, :conditions => { :resource_type => "#{self.to_s}" }), :dependent => :destroy unless respond_to? :permissions
94
+ has_many(:permissions, :as => :resource, :dependent => :destroy) unless respond_to? :permissions
89
95
  end
90
96
 
91
97
  resource.constantize.instance_eval{ include Permissable::Resource }
@@ -97,11 +103,13 @@ module Permissable
97
103
 
98
104
  # This class becomes a member to resources.
99
105
  include Permissable::Member
100
- class_inheritable_accessor :permission_types
101
- self.send :permission_types=, options[:to]
106
+ class_inheritable_accessor :permissable_types
107
+ class_inheritable_accessor :permissable_resources
108
+ self.send :permissable_types=, options[:to]
109
+ self.send :permissable_resources=, resources
102
110
 
103
111
  # Members create a has_many association on permissions as a member.
104
- has_many(:permissions, :as => :member, :conditions => { :member_type => "#{self.to_s}" }), :dependent => :destroy unless respond_to? :permissions
112
+ has_many(:permissions, :as => :member, :dependent => :destroy) unless respond_to? :permissions
105
113
 
106
114
  end
107
115
 
@@ -5,22 +5,28 @@ module Permissable
5
5
  def self.included(base)
6
6
  base.send :include, InstanceMethods
7
7
  base.send :attr_protected, :member_identifier
8
- base.send :attr_protected, :permissable_lookups
8
+ base.send :attr_protected, :permissions_cache
9
+ base.send :attr_protected, :association_scopes
9
10
  end
10
11
 
11
12
  # This module includes methods that should exist on ALL members.
12
13
  module InstanceMethods
13
14
 
14
15
  # The can? method returns a boolen value specifying whether or not this member can perform the specific method on resource
15
- def can?(methods, resource)
16
+ def can?(methods, resource, chain = true)
16
17
  unless allow_permission_with_method.nil?
17
18
  if self.respond_to? "#{allow_permission_with_method}"
18
19
  return true if (send "#{allow_permission_with_method}")
19
20
  end
20
21
  end
21
- methods = [methods].flatten.collect{ |m| m.to_sym }
22
- methods = find_methods_from_chain(methods)
23
- permissions_for(resource, methods).exists?
22
+
23
+ if chain
24
+ methods = [methods].flatten.collect{ |m| m.to_sym }
25
+ methods = find_methods_from_chain(methods)
26
+ end
27
+
28
+ permissions_for?(resource, methods)
29
+
24
30
  end
25
31
 
26
32
  # Alias to can? to get the inverse.
@@ -33,7 +39,7 @@ module Permissable
33
39
 
34
40
  # This method should return all of the new permissions that were created, so we build a
35
41
  # response array to return
36
- response = []
42
+ result_response = []
37
43
 
38
44
  [resources].flatten.each do |resource|
39
45
 
@@ -46,19 +52,19 @@ module Permissable
46
52
 
47
53
  [methods].flatten.each do |method|
48
54
  # Permission already exists, continue.
49
- next if can?(method, resource)
55
+ next if can?(method, resource, false)
50
56
 
51
57
  # Create a new permission for each member (once if its self, multiple times if its associated)
52
58
  [identifier[:member_id]].flatten.each do |member_id|
53
59
  perm = Permission.new(:member_id => member_id, :member_type => identifier[:member_type], :permission_type => method.to_s.downcase)
54
60
  perm.resource = resource
55
61
  perm.save
56
- response << perm
62
+ result_response << perm
57
63
  end
58
64
  end
59
65
  end
60
66
 
61
- (response.size == 1) ? response.first : response
67
+ (result_response.size == 1) ? result_response.first : result_response
62
68
 
63
69
  end
64
70
 
@@ -72,20 +78,30 @@ module Permissable
72
78
  return @member_identifier[scope] unless @member_identifier[scope].nil?
73
79
  return { :member_id => self.id, :member_type => self.class.to_s } unless permissable_associations.has_key?(scope)
74
80
 
81
+ @association_scopes ||= {}
75
82
  assoc_key = permissable_associations[scope]
76
- assoc = send "#{assoc_key}".to_sym
83
+ @association_scopes[assoc_key] ||= send("#{assoc_key}".to_sym)
84
+ assoc = @association_scopes[assoc_key]
77
85
 
78
86
  @member_identifier[scope] = { :member_id => (assoc.is_a?(Array) ? assoc.collect{ |a| a.id } : assoc.id ), :member_type => assoc_key.to_s.classify }
79
87
 
80
88
  end
81
89
 
82
90
  # Provide an instance method to our associations
83
- def permissable_associations; self.class.permissable_associations; end
91
+ def permissable_associations; self.class.permissable_associations || {}; end
84
92
  # Find our permission override if available
85
93
  def allow_permission_with_method; self.class.permissable_options[:allow_permission_with_method]; end
86
94
  # See if there is a permissions chain
87
95
  def permission_chain; self.class.permissable_options[:permission_chain] || {}; end
88
96
 
97
+ def permissions_for(resource)
98
+ fetch_permissions_for(resource).all.collect{ |perm| perm.permission_type.to_sym }
99
+ end
100
+
101
+ def lookup_permissions!
102
+ @permissions_cache = PermissionsCache.new(Permission.where(:resource_type => self.class.permissable_resources.collect{ |r| r.to_s.classify }).all)
103
+ end
104
+
89
105
  private
90
106
 
91
107
  def find_methods_from_chain(methods)
@@ -106,12 +122,28 @@ module Permissable
106
122
  end
107
123
 
108
124
  # Looks up permissions for a particular resource.
109
- def permissions_for(resource, methods = nil)
125
+ def fetch_permissions_for(resource, methods = nil)
110
126
  scope = fetch_scope(resource)
111
- return self.permissions.with_permission_to(methods) unless permissable_associations.has_key?(scope)
112
- relation = Permission.where(member_identifier(scope)).for_resource(resource)
127
+
128
+ lookup_with = is_cached? ? @permissions_cache : Permission
129
+ relation = lookup_with.for_member(member_identifier(scope)).for_resource(resource)
113
130
  relation = relation.with_permission_to(methods) unless methods.nil?
114
- relation
131
+ return relation
132
+
133
+ end
134
+
135
+ def fetch_scope(resource)
136
+ return resource if resource.is_a?(String)
137
+ (resource.is_a?(Class)) ? resource.to_s : resource.base_class.to_s.classify
138
+ end
139
+
140
+ # Look to see if we have a permissions cache.
141
+ def is_cached?
142
+ !@permissions_cache.nil?
143
+ end
144
+
145
+ def permissions_for?(resource, methods = nil)
146
+ fetch_permissions_for(resource, methods).exists?
115
147
  end
116
148
 
117
149
  # Returns the member responsible for this resource. This can either be an instance of self, or an instance or
@@ -121,11 +153,6 @@ module Permissable
121
153
  (permissable_associations.has_key?(scope)) ? send("#{permissable_associations[scope]}".to_sym) : self
122
154
  end
123
155
 
124
- def fetch_scope(resource)
125
- return resource if resource.is_a?(String)
126
- (resource.is_a?(Class)) ? resource.to_s : resource.class.to_s.classify
127
- end
128
-
129
156
  end
130
157
 
131
158
  end
@@ -5,17 +5,16 @@ class Permission < ActiveRecord::Base
5
5
  class << self
6
6
 
7
7
  def for_resource(resource)
8
- resource = flatten(resource)
8
+ resource = Permissable.flatten_resource(resource)
9
9
  where(resource)
10
10
  end
11
11
 
12
- def with_permission_to(methods)
13
- where(:permission_type => [methods].flatten.uniq.collect{ |m| m.to_s.downcase })
12
+ def for_member(member)
13
+ where(member)
14
14
  end
15
15
 
16
- def flatten(obj)
17
- return { :resource_id => obj, :resource_type => obj.class.to_s } unless obj.is_a?(Array)
18
- { :resource_id => obj.collect{ |o| o.id }, :resource_type => obj.collect{ |o| o.class.to_s } }
16
+ def with_permission_to(methods)
17
+ where(:permission_type => [methods].flatten.uniq.collect{ |m| m.to_s.downcase })
19
18
  end
20
19
 
21
20
  end
@@ -0,0 +1,68 @@
1
+ module Permissable
2
+
3
+ class PermissionsCache
4
+
5
+ attr_accessor :_permissions
6
+ attr_accessor :_query_results
7
+
8
+ def initialize(permission_list)
9
+ @_permissions = permission_list
10
+ @_query_results = nil
11
+ end
12
+
13
+ def for_member(member)
14
+ arr = create_result_array
15
+ @_query_results = arr.find_all do |perm|
16
+ (member.key?(:member_type) ? true : perm.member_type == member[:member_type]) && [member[:member_id]].flatten.uniq.include?(perm.member_id)
17
+ end
18
+
19
+ return self
20
+
21
+ end
22
+
23
+ def for_resource(resource)
24
+ arr = create_result_array
25
+ resource = Permissable.flatten_resource(resource)
26
+ @_query_results = arr.find_all do |perm|
27
+ [resource[:resource_id]].flatten.include?(perm.resource_id) && [resource[:resource_type]].flatten.include?(perm.resource_type)
28
+ end
29
+
30
+ return self
31
+
32
+ end
33
+
34
+ def with_permission_to(methods)
35
+ arr = create_result_array
36
+ @_query_results = arr.find_all do |perm|
37
+ [methods].flatten.collect{ |m| m.to_s }.include?(perm.permission_type)
38
+ end
39
+
40
+ return self
41
+
42
+ end
43
+
44
+ def all
45
+ results = @_query_results || []
46
+ @_query_results = nil
47
+ results
48
+ end
49
+
50
+ def exists?
51
+ results = @_query_results || []
52
+ @_query_results = nil
53
+ !results.empty?
54
+ end
55
+
56
+ private
57
+
58
+ def create_result_array
59
+ (@_query_results.nil?) ? permissions : @_query_results
60
+ end
61
+
62
+ def permissions
63
+ @_permissions
64
+ end
65
+
66
+ end
67
+
68
+ end
data/permissable.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{permissable}
8
- s.version = "0.2.1"
8
+ s.version = "0.2.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Brent Kirby"]
12
- s.date = %q{2010-09-04}
12
+ s.date = %q{2010-09-05}
13
13
  s.description = %q{Permissable lets you set a number of 'permissions' to your database models. By assigning 'members' to 'resources' (models) you can specify various permission states.}
14
14
  s.email = %q{brent@kurbmedia.com}
15
15
  s.extra_rdoc_files = [
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
27
27
  "lib/permissable.rb",
28
28
  "lib/permissable/member.rb",
29
29
  "lib/permissable/permission.rb",
30
+ "lib/permissable/permissions_cache.rb",
30
31
  "lib/permissable/resource.rb",
31
32
  "permissable.gemspec",
32
33
  "test/helper.rb",
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: permissable
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 1
10
- version: 0.2.1
9
+ - 2
10
+ version: 0.2.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Brent Kirby
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-09-04 00:00:00 -04:00
18
+ date: 2010-09-05 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -52,6 +52,7 @@ files:
52
52
  - lib/permissable.rb
53
53
  - lib/permissable/member.rb
54
54
  - lib/permissable/permission.rb
55
+ - lib/permissable/permissions_cache.rb
55
56
  - lib/permissable/resource.rb
56
57
  - permissable.gemspec
57
58
  - test/helper.rb