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 +1 -1
- data/lib/permissable.rb +18 -10
- data/lib/permissable/member.rb +47 -20
- data/lib/permissable/permission.rb +5 -6
- data/lib/permissable/permissions_cache.rb +68 -0
- data/permissable.gemspec +3 -2
- metadata +5 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
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, :
|
81
|
+
has_many(:permissions, :as => :member, :dependent => :destroy) unless respond_to? :permissions
|
75
82
|
include Permissable::Member
|
76
|
-
class_inheritable_accessor :
|
77
|
-
|
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, :
|
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 :
|
101
|
-
|
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, :
|
112
|
+
has_many(:permissions, :as => :member, :dependent => :destroy) unless respond_to? :permissions
|
105
113
|
|
106
114
|
end
|
107
115
|
|
data/lib/permissable/member.rb
CHANGED
@@ -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, :
|
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
|
-
|
22
|
-
|
23
|
-
|
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
|
-
|
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
|
-
|
62
|
+
result_response << perm
|
57
63
|
end
|
58
64
|
end
|
59
65
|
end
|
60
66
|
|
61
|
-
(
|
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
|
-
|
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
|
125
|
+
def fetch_permissions_for(resource, methods = nil)
|
110
126
|
scope = fetch_scope(resource)
|
111
|
-
|
112
|
-
|
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 =
|
8
|
+
resource = Permissable.flatten_resource(resource)
|
9
9
|
where(resource)
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
where(
|
12
|
+
def for_member(member)
|
13
|
+
where(member)
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
17
|
-
|
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.
|
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-
|
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:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
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-
|
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
|