cancan-permits 0.3.4 → 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +84 -2
- data/VERSION +1 -1
- data/cancan-permits.gemspec +11 -2
- data/lib/cancan-permits/license/base_license.rb +19 -2
- data/lib/cancan-permits/loader/permission_config.rb +41 -0
- data/lib/cancan-permits/loader/permissions_loader.rb +46 -0
- data/lib/cancan-permits/loader/permissions_parser.rb +25 -0
- data/lib/cancan-permits/main.rb +2 -1
- data/lib/cancan-permits/permit/base_permit.rb +19 -0
- data/spec/cancan-permits/license_loader/license_loader_spec.rb +28 -0
- data/spec/cancan-permits/license_loader/licenses.yml +12 -0
- data/spec/cancan-permits/user_permissions_loader/user_permissions.yml +14 -0
- data/spec/cancan-permits/user_permissions_loader/user_permissions_loader.rb +28 -0
- metadata +12 -3
data/README.markdown
CHANGED
@@ -6,7 +6,12 @@ Role specific Permits for use with [CanCan](http://github.com/ryanb/cancan) perm
|
|
6
6
|
|
7
7
|
See Changelog.txt (Major updates as per Nov 24. 2010)
|
8
8
|
|
9
|
-
Nov 28:
|
9
|
+
Nov 28:
|
10
|
+
Added Generators to create individual Permit and License!
|
11
|
+
|
12
|
+
Nov 29:
|
13
|
+
Added ability to specify YAML files with configurations for Permits, Licenses and even Permissions for individual users.
|
14
|
+
Thanks to 'ticktricktrack' for the request and suggestion. (I hope you can use this and move on from here...)
|
10
15
|
|
11
16
|
## Install
|
12
17
|
|
@@ -49,6 +54,84 @@ Modify the User model in 'models/user.rb' (optional)
|
|
49
54
|
end
|
50
55
|
</code>
|
51
56
|
|
57
|
+
### Load Permissions from yml files
|
58
|
+
|
59
|
+
*Individual user permissions:*
|
60
|
+
- config/user_permissions.yml
|
61
|
+
|
62
|
+
Each key at the top level is expected to match an email value for an existing user.
|
63
|
+
|
64
|
+
Example yml config file:
|
65
|
+
<code>
|
66
|
+
abc@mail.ru:
|
67
|
+
can:
|
68
|
+
update: [Comment, Fruit, Car, Friendship]
|
69
|
+
manage:
|
70
|
+
- Article
|
71
|
+
owns:
|
72
|
+
- User
|
73
|
+
mike.shedlock.com:
|
74
|
+
can:
|
75
|
+
read:
|
76
|
+
- all
|
77
|
+
cannot:
|
78
|
+
update:
|
79
|
+
- Post
|
80
|
+
</code>
|
81
|
+
|
82
|
+
Usage in a permit
|
83
|
+
|
84
|
+
<code>
|
85
|
+
class AdminPermit < Permit::Base
|
86
|
+
def initialize(ability, options = {})
|
87
|
+
super
|
88
|
+
end
|
89
|
+
|
90
|
+
def permit?(user, options = {})
|
91
|
+
super
|
92
|
+
return if !role_match? user
|
93
|
+
can :manage, :all
|
94
|
+
load_rules user
|
95
|
+
end
|
96
|
+
end
|
97
|
+
</code>
|
98
|
+
|
99
|
+
|
100
|
+
*License permissions:*
|
101
|
+
- config/licenses.yml
|
102
|
+
|
103
|
+
Each key at the top level is expected to match a license name.
|
104
|
+
|
105
|
+
Example yml config file:
|
106
|
+
<code>
|
107
|
+
blogging:
|
108
|
+
can:
|
109
|
+
manage:
|
110
|
+
- Article
|
111
|
+
- Post
|
112
|
+
admin:
|
113
|
+
can:
|
114
|
+
manage:
|
115
|
+
- all
|
116
|
+
cannot:
|
117
|
+
manage:
|
118
|
+
- User
|
119
|
+
</code>
|
120
|
+
|
121
|
+
Usage in a license
|
122
|
+
|
123
|
+
<code>
|
124
|
+
class UserAdminLicense < License::Base
|
125
|
+
def initialize name
|
126
|
+
super
|
127
|
+
end
|
128
|
+
|
129
|
+
def enforce!
|
130
|
+
can(:manage, User)
|
131
|
+
load_rules
|
132
|
+
end
|
133
|
+
</code>
|
134
|
+
|
52
135
|
### User Roles
|
53
136
|
|
54
137
|
CanCan permits requires that you have some kind of Role system in place and that User#has_role? uses this Role system.
|
@@ -94,7 +177,6 @@ Permit example:
|
|
94
177
|
def permit?(user, options = {})
|
95
178
|
super
|
96
179
|
return if !role_match? user
|
97
|
-
|
98
180
|
can :manage, :all
|
99
181
|
end
|
100
182
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.5
|
data/cancan-permits.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{cancan-permits}
|
8
|
-
s.version = "0.3.
|
8
|
+
s.version = "0.3.5"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Kristian Mandrup"]
|
12
|
-
s.date = %q{2010-11-
|
12
|
+
s.date = %q{2010-11-29}
|
13
13
|
s.description = %q{Role specific Permits for use with CanCan permission system}
|
14
14
|
s.email = %q{kmandrup@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -28,6 +28,9 @@ Gem::Specification.new do |s|
|
|
28
28
|
"development.sqlite3",
|
29
29
|
"lib/cancan-permits.rb",
|
30
30
|
"lib/cancan-permits/license/base_license.rb",
|
31
|
+
"lib/cancan-permits/loader/permission_config.rb",
|
32
|
+
"lib/cancan-permits/loader/permissions_loader.rb",
|
33
|
+
"lib/cancan-permits/loader/permissions_parser.rb",
|
31
34
|
"lib/cancan-permits/main.rb",
|
32
35
|
"lib/cancan-permits/namespaces.rb",
|
33
36
|
"lib/cancan-permits/permit/base_permit.rb",
|
@@ -59,6 +62,10 @@ Gem::Specification.new do |s|
|
|
59
62
|
"spec/active_record/owner_permits_spec.rb",
|
60
63
|
"spec/active_record/permits_spec.rb",
|
61
64
|
"spec/active_record/spec_helper.rb",
|
65
|
+
"spec/cancan-permits/license_loader/license_loader_spec.rb",
|
66
|
+
"spec/cancan-permits/license_loader/licenses.yml",
|
67
|
+
"spec/cancan-permits/user_permissions_loader/user_permissions.yml",
|
68
|
+
"spec/cancan-permits/user_permissions_loader/user_permissions_loader.rb",
|
62
69
|
"spec/data_mapper/models/all_models.rb",
|
63
70
|
"spec/data_mapper/owner_permits_spec.rb",
|
64
71
|
"spec/data_mapper/permits_spec.rb",
|
@@ -111,6 +118,8 @@ Gem::Specification.new do |s|
|
|
111
118
|
"spec/active_record/owner_permits_spec.rb",
|
112
119
|
"spec/active_record/permits_spec.rb",
|
113
120
|
"spec/active_record/spec_helper.rb",
|
121
|
+
"spec/cancan-permits/license_loader/license_loader_spec.rb",
|
122
|
+
"spec/cancan-permits/user_permissions_loader/user_permissions_loader.rb",
|
114
123
|
"spec/data_mapper/models/all_models.rb",
|
115
124
|
"spec/data_mapper/owner_permits_spec.rb",
|
116
125
|
"spec/data_mapper/permits_spec.rb",
|
@@ -1,14 +1,31 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
1
3
|
module License
|
2
4
|
class Base
|
3
|
-
attr_reader :permit
|
5
|
+
attr_reader :permit, :licenses
|
4
6
|
|
5
|
-
def initialize permit
|
7
|
+
def initialize permit, licenses_file = nil
|
6
8
|
@permit = permit
|
9
|
+
@licenses = ::PermissionsLoader.load_licenses licenses_file
|
7
10
|
end
|
8
11
|
|
9
12
|
def enforce!
|
10
13
|
raise "enforce! must be implemented by subclass of License::Base"
|
11
14
|
end
|
15
|
+
|
16
|
+
def load_rules name = nil
|
17
|
+
return if !licenses || licenses.empty?
|
18
|
+
|
19
|
+
name ||= self.class.to_s..gsub(/License$/, "").underscore.to_sym
|
20
|
+
|
21
|
+
licenses[name].can_statement do |permission_statement|
|
22
|
+
instance_eval permission_statement
|
23
|
+
end
|
24
|
+
|
25
|
+
licenses[name].cannot_statement do |permission_statement|
|
26
|
+
instance_eval permission_statement
|
27
|
+
end
|
28
|
+
end
|
12
29
|
|
13
30
|
def can(action, subject, conditions = nil, &block)
|
14
31
|
permit.can action, subject, conditions, &block
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class PermissionConfig
|
2
|
+
attr_accessor :name, :can, :cannot
|
3
|
+
|
4
|
+
def initialize name
|
5
|
+
@name = name
|
6
|
+
end
|
7
|
+
|
8
|
+
# Should take @can={"manage"=>["all"]}, @cannot={"update"=>["User", "Profile"]}
|
9
|
+
# and create string ready to ruby evaluate like:
|
10
|
+
# can(:manage, :all)
|
11
|
+
# cannot(:update, [User, Profile])
|
12
|
+
def can_eval &block
|
13
|
+
statements = [:manage, :read, :update, :create, :write].map do |action|
|
14
|
+
targets = can[action]
|
15
|
+
targets ? "can(:#{action}, #{parse_targets(targets)})" : nil
|
16
|
+
end.compact.join("\n")
|
17
|
+
yield statements if !statements.empty? && block
|
18
|
+
end
|
19
|
+
|
20
|
+
def can_eval &block
|
21
|
+
statements = [:manage, :read, :update, :create, :write].map do |action|
|
22
|
+
targets = cannot[action]
|
23
|
+
targets ? "cannot(:#{action}, #{parse_targets(targets)})" : nil
|
24
|
+
end.compact.join("\n")
|
25
|
+
yield statements if !statements.empty? && block
|
26
|
+
end
|
27
|
+
|
28
|
+
def parse_targets targets
|
29
|
+
targets.map do |target|
|
30
|
+
if target == 'all'
|
31
|
+
':all'
|
32
|
+
else
|
33
|
+
begin
|
34
|
+
"#{target.constantize}"
|
35
|
+
rescue
|
36
|
+
puts "[permission] target #{target} does not have a class so it was skipped"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class PermissionsLoader
|
2
|
+
|
3
|
+
attr_accessor :permissions
|
4
|
+
|
5
|
+
def initialize file_name
|
6
|
+
begin
|
7
|
+
if file_name.nil? || !File.file?(file_name)
|
8
|
+
# raise ArgumentError, "PermissionsLoader Error: The permissions file #{file_name} could not be found"
|
9
|
+
puts "PermissionsLoader Error: The permissions file #{file_name} could not be found"
|
10
|
+
return nil
|
11
|
+
end
|
12
|
+
|
13
|
+
yml_content = YAML.load_file(file_name)
|
14
|
+
parser = PermissionsParser.new
|
15
|
+
|
16
|
+
self.permissions ||= {}
|
17
|
+
yml_content.each do |key, value|
|
18
|
+
parser.parse(key, value) do |permission|
|
19
|
+
permissions[permission.name] = permission
|
20
|
+
end
|
21
|
+
end
|
22
|
+
rescue RuntimeError => e
|
23
|
+
raise "PermissionsLoader Error: The permissions for the file #{file_name} could not be loaded - cause was #{e}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.load_user_permissions name = nil
|
28
|
+
name ||= user_permissions_config_file
|
29
|
+
PermissionsLoader.new name
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.load_licenses name = nil
|
33
|
+
name ||= licenses_config_file
|
34
|
+
PermissionsLoader.new name
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.user_permissions_config_file
|
38
|
+
# raise '#user_permissions_config_file only works in a Rails app enviroment' if !defined? Rails
|
39
|
+
File.join(::Rails.root, 'config', 'user_permissions.yml') if defined? Rails
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.licenses_config_file
|
43
|
+
# raise '#licenses_config_file only works in a Rails app enviroment' if !defined? Rails
|
44
|
+
File.join(::Rails.root, 'config', 'licenses.yml') if defined? Rails
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class PermissionsParser
|
2
|
+
def initialize
|
3
|
+
end
|
4
|
+
|
5
|
+
def parse(key, obj, &blk)
|
6
|
+
license = ::PermissionConfig.new key
|
7
|
+
case obj
|
8
|
+
when Hash
|
9
|
+
parse_permission(obj, license, &blk)
|
10
|
+
else
|
11
|
+
raise "Each key must have a YAML hash that defines its permission configuration"
|
12
|
+
end
|
13
|
+
yield license if blk
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def parse_permission(obj, license, &blk)
|
19
|
+
# Forget keys because I don't know what to do with them
|
20
|
+
obj.each do |key, value|
|
21
|
+
raise ArgumentError, "A CanCan license can only have the keys can: and cannot:" if ![:can, :cannot].include?(key.to_sym)
|
22
|
+
license.send :"#{key}=", value
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/cancan-permits/main.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'cancan-permits/namespaces'
|
2
2
|
require_all File.dirname(__FILE__) + '/permit'
|
3
3
|
require_all File.dirname(__FILE__) + '/permits'
|
4
|
-
require_all File.dirname(__FILE__) + '/license'
|
4
|
+
require_all File.dirname(__FILE__) + '/license'
|
5
|
+
require_all File.dirname(__FILE__) + '/loader'
|
@@ -6,6 +6,8 @@ module Permit
|
|
6
6
|
attr_reader :ability
|
7
7
|
attr_reader :strategy # this can be used to customize the strategy used by owns to determine ownership, fx to support alternative ORMs
|
8
8
|
|
9
|
+
attr_reader :user_permissions
|
10
|
+
|
9
11
|
def licenses *names
|
10
12
|
names.to_strings.each do |name|
|
11
13
|
begin
|
@@ -22,10 +24,27 @@ module Permit
|
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
27
|
+
|
28
|
+
def load_rules user
|
29
|
+
return if !user_permissions || user_permissions.empty?
|
30
|
+
raise "#load_enforcements expects the user to have an email property: #{user.inspect}" if !user || !user.respond_to?(:email)
|
31
|
+
|
32
|
+
id = user.email
|
33
|
+
return nil if id.strip.empty?
|
34
|
+
|
35
|
+
user_permissions[id].can_statement do |permission_statement|
|
36
|
+
instance_eval permission_statement
|
37
|
+
end
|
38
|
+
|
39
|
+
user_permissions[id].cannot_statement do |permission_statement|
|
40
|
+
instance_eval permission_statement
|
41
|
+
end
|
42
|
+
end
|
25
43
|
|
26
44
|
def initialize ability, options = {}
|
27
45
|
@ability = ability
|
28
46
|
@strategy = options[:strategy] || Permits::Ability.strategy || :default
|
47
|
+
@user_permissions = ::PermissionsLoader.load_user_permissions options[:permissions_file]
|
29
48
|
end
|
30
49
|
|
31
50
|
def permit?(user, options = {})
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rspec/core'
|
2
|
+
require 'cancan-permits'
|
3
|
+
|
4
|
+
DIR = File.dirname(__FILE__)
|
5
|
+
|
6
|
+
describe 'Load License permissions' do
|
7
|
+
before :each do
|
8
|
+
@permissions_file = File.join(DIR, 'licenses.yml')
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should load a licenses permission file" do
|
12
|
+
loader = PermissionsLoader.new @permissions_file
|
13
|
+
# puts "loaded permissions #{loader.permissions}"
|
14
|
+
loader.permissions.should_not be_empty
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should be able to instantiate a base license with permission file" do
|
18
|
+
License::Base.new 'x', @permissions_file
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should be able to instantiate a base permit without permission file" do
|
22
|
+
Permit::Base.new 'x'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rspec/core'
|
2
|
+
require 'cancan-permits'
|
3
|
+
|
4
|
+
DIR = File.dirname(__FILE__)
|
5
|
+
|
6
|
+
describe 'User Permissions Loader' do
|
7
|
+
before :each do
|
8
|
+
@permissions_file = File.join(DIR, 'user_permissions.yml')
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should load a user permissions file" do
|
12
|
+
loader = PermissionsLoader.new @permissions_file
|
13
|
+
# puts "loaded permissions #{loader.permissions}"
|
14
|
+
loader.permissions.should_not be_empty
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should be able to instantiate a base permit with permission file" do
|
18
|
+
Permit::Base.new 'x', :permissions_file => @permissions_file
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should be able to instantiate a base permit without permission file" do
|
22
|
+
Permit::Base.new 'x'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
8
|
+
- 5
|
9
|
+
version: 0.3.5
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Kristian Mandrup
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-11-
|
17
|
+
date: 2010-11-29 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -173,6 +173,9 @@ files:
|
|
173
173
|
- development.sqlite3
|
174
174
|
- lib/cancan-permits.rb
|
175
175
|
- lib/cancan-permits/license/base_license.rb
|
176
|
+
- lib/cancan-permits/loader/permission_config.rb
|
177
|
+
- lib/cancan-permits/loader/permissions_loader.rb
|
178
|
+
- lib/cancan-permits/loader/permissions_parser.rb
|
176
179
|
- lib/cancan-permits/main.rb
|
177
180
|
- lib/cancan-permits/namespaces.rb
|
178
181
|
- lib/cancan-permits/permit/base_permit.rb
|
@@ -204,6 +207,10 @@ files:
|
|
204
207
|
- spec/active_record/owner_permits_spec.rb
|
205
208
|
- spec/active_record/permits_spec.rb
|
206
209
|
- spec/active_record/spec_helper.rb
|
210
|
+
- spec/cancan-permits/license_loader/license_loader_spec.rb
|
211
|
+
- spec/cancan-permits/license_loader/licenses.yml
|
212
|
+
- spec/cancan-permits/user_permissions_loader/user_permissions.yml
|
213
|
+
- spec/cancan-permits/user_permissions_loader/user_permissions_loader.rb
|
207
214
|
- spec/data_mapper/models/all_models.rb
|
208
215
|
- spec/data_mapper/owner_permits_spec.rb
|
209
216
|
- spec/data_mapper/permits_spec.rb
|
@@ -283,6 +290,8 @@ test_files:
|
|
283
290
|
- spec/active_record/owner_permits_spec.rb
|
284
291
|
- spec/active_record/permits_spec.rb
|
285
292
|
- spec/active_record/spec_helper.rb
|
293
|
+
- spec/cancan-permits/license_loader/license_loader_spec.rb
|
294
|
+
- spec/cancan-permits/user_permissions_loader/user_permissions_loader.rb
|
286
295
|
- spec/data_mapper/models/all_models.rb
|
287
296
|
- spec/data_mapper/owner_permits_spec.rb
|
288
297
|
- spec/data_mapper/permits_spec.rb
|