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.
@@ -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: Added Generators to create individual Permit and License!
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.4
1
+ 0.3.5
@@ -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.4"
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-28}
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
@@ -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,12 @@
1
+ blogging:
2
+ can:
3
+ manage:
4
+ - Article
5
+ - Post
6
+ admin:
7
+ can:
8
+ manage:
9
+ - all
10
+ cannot:
11
+ manage:
12
+ - User
@@ -0,0 +1,14 @@
1
+ abc@mail.ru:
2
+ can:
3
+ update: [Comment, Fruit, Car, Friendship]
4
+ manage:
5
+ - Article
6
+ owns:
7
+ - User
8
+ mike.shedlock.com:
9
+ can:
10
+ read:
11
+ - all
12
+ cannot:
13
+ update:
14
+ - Post
@@ -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
- - 4
9
- version: 0.3.4
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-28 00:00:00 +01:00
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