cancan-permits 0.3.4 → 0.3.5
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/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
|