third-prestige-rolify 3.3.0.rc5

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.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.travis.yml +17 -0
  4. data/CHANGELOG.rdoc +157 -0
  5. data/Gemfile +21 -0
  6. data/LICENSE +20 -0
  7. data/README.md +220 -0
  8. data/Rakefile +34 -0
  9. data/UPGRADE.rdoc +44 -0
  10. data/gemfiles/Gemfile.rails-3.2 +21 -0
  11. data/gemfiles/Gemfile.rails-4.0 +27 -0
  12. data/lib/generators/active_record/rolify_generator.rb +50 -0
  13. data/lib/generators/active_record/templates/README +8 -0
  14. data/lib/generators/active_record/templates/migration.rb +19 -0
  15. data/lib/generators/mongoid/rolify_generator.rb +51 -0
  16. data/lib/generators/mongoid/templates/README-mongoid +4 -0
  17. data/lib/generators/rolify/rolify_generator.rb +35 -0
  18. data/lib/generators/rolify/templates/README +13 -0
  19. data/lib/generators/rolify/templates/initializer.rb +8 -0
  20. data/lib/generators/rolify/templates/role-active_record.rb +11 -0
  21. data/lib/generators/rolify/templates/role-mongoid.rb +17 -0
  22. data/lib/generators/rolify/user_generator.rb +39 -0
  23. data/lib/rolify.rb +57 -0
  24. data/lib/rolify/adapters/active_record/resource_adapter.rb +26 -0
  25. data/lib/rolify/adapters/active_record/role_adapter.rb +86 -0
  26. data/lib/rolify/adapters/active_record/scopes.rb +27 -0
  27. data/lib/rolify/adapters/base.rb +60 -0
  28. data/lib/rolify/adapters/mongoid/resource_adapter.rb +27 -0
  29. data/lib/rolify/adapters/mongoid/role_adapter.rb +89 -0
  30. data/lib/rolify/adapters/mongoid/scopes.rb +27 -0
  31. data/lib/rolify/configure.rb +56 -0
  32. data/lib/rolify/dynamic.rb +21 -0
  33. data/lib/rolify/finders.rb +40 -0
  34. data/lib/rolify/matchers.rb +13 -0
  35. data/lib/rolify/railtie.rb +20 -0
  36. data/lib/rolify/resource.rb +31 -0
  37. data/lib/rolify/role.rb +85 -0
  38. data/lib/rolify/utils.rb +10 -0
  39. data/lib/rolify/version.rb +3 -0
  40. data/rolify.gemspec +30 -0
  41. data/spec/README.rdoc +24 -0
  42. data/spec/generators/rolify/rolify_activerecord_generator_spec.rb +163 -0
  43. data/spec/generators/rolify/rolify_mongoid_generator_spec.rb +112 -0
  44. data/spec/generators_helper.rb +21 -0
  45. data/spec/rolify/config_spec.rb +191 -0
  46. data/spec/rolify/custom_spec.rb +20 -0
  47. data/spec/rolify/matchers_spec.rb +24 -0
  48. data/spec/rolify/namespace_spec.rb +24 -0
  49. data/spec/rolify/resource_spec.rb +389 -0
  50. data/spec/rolify/resourcifed_and_rolifed_spec.rb +24 -0
  51. data/spec/rolify/role_spec.rb +20 -0
  52. data/spec/rolify/shared_contexts.rb +92 -0
  53. data/spec/rolify/shared_examples/shared_examples_for_add_role.rb +92 -0
  54. data/spec/rolify/shared_examples/shared_examples_for_callbacks.rb +65 -0
  55. data/spec/rolify/shared_examples/shared_examples_for_dynamic.rb +151 -0
  56. data/spec/rolify/shared_examples/shared_examples_for_finders.rb +77 -0
  57. data/spec/rolify/shared_examples/shared_examples_for_has_all_roles.rb +71 -0
  58. data/spec/rolify/shared_examples/shared_examples_for_has_any_role.rb +71 -0
  59. data/spec/rolify/shared_examples/shared_examples_for_has_role.rb +135 -0
  60. data/spec/rolify/shared_examples/shared_examples_for_only_has_role.rb +174 -0
  61. data/spec/rolify/shared_examples/shared_examples_for_remove_role.rb +121 -0
  62. data/spec/rolify/shared_examples/shared_examples_for_roles.rb +102 -0
  63. data/spec/rolify/shared_examples/shared_examples_for_scopes.rb +38 -0
  64. data/spec/spec_helper.rb +30 -0
  65. data/spec/support/adapters/active_record.rb +76 -0
  66. data/spec/support/adapters/mongoid.rb +143 -0
  67. data/spec/support/adapters/mongoid.yml +6 -0
  68. data/spec/support/data.rb +25 -0
  69. data/spec/support/schema.rb +52 -0
  70. metadata +254 -0
@@ -0,0 +1,26 @@
1
+ require 'rolify/adapters/base'
2
+
3
+ module Rolify
4
+ module Adapter
5
+ class ResourceAdapter < ResourceAdapterBase
6
+ def resources_find(roles_table, relation, role_name)
7
+ resources = relation.joins("INNER JOIN #{quote(roles_table)} ON #{quote(roles_table)}.resource_type = '#{relation.to_s}' AND
8
+ (#{quote(roles_table)}.resource_id IS NULL OR #{quote(roles_table)}.resource_id = #{quote(relation.table_name)}.#{relation.primary_key})")
9
+ resources = resources.where("#{quote(roles_table)}.name IN (?) AND #{quote(roles_table)}.resource_type = ?", Array(role_name), relation.to_s)
10
+ resources = resources.select("#{quote(relation.table_name)}.*")
11
+ resources
12
+ end
13
+
14
+ def in(relation, user, role_names)
15
+ roles = user.roles.where(:name => role_names)
16
+ relation.where("#{quote(role_class.table_name)}.#{role_class.primary_key} IN (?) AND ((resource_id = #{quote(relation.table_name)}.#{relation.primary_key}) OR (resource_id IS NULL))", roles)
17
+ end
18
+
19
+ private
20
+
21
+ def quote(column)
22
+ ActiveRecord::Base.connection.quote_column_name column
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,86 @@
1
+ require 'rolify/adapters/base'
2
+
3
+ module Rolify
4
+ module Adapter
5
+ class RoleAdapter < RoleAdapterBase
6
+ def where(relation, *args)
7
+ conditions, values = build_conditions(relation, args)
8
+ relation.where(conditions, *values)
9
+ end
10
+
11
+ def find_or_create_by(role_name, resource_type = nil, resource_id = nil)
12
+ role_class.where(:name => role_name, :resource_type => resource_type, :resource_id => resource_id).first_or_create
13
+ end
14
+
15
+ def add(relation, role)
16
+ relation.role_ids |= [role.id]
17
+ end
18
+
19
+ def remove(relation, role_name, resource = nil)
20
+ cond = { :name => role_name }
21
+ cond[:resource_type] = (resource.is_a?(Class) ? resource.to_s : resource.class.name) if resource
22
+ cond[:resource_id] = resource.id if resource && !resource.is_a?(Class)
23
+ roles = relation.roles.where(cond)
24
+ if roles
25
+ relation.roles.delete(roles)
26
+ roles.each do |role|
27
+ role.destroy if role.send(ActiveSupport::Inflector.demodulize(user_class).tableize.to_sym).empty?
28
+ end
29
+ end
30
+ roles
31
+ end
32
+
33
+ def exists?(relation, column)
34
+ relation.where("#{column} IS NOT NULL")
35
+ end
36
+
37
+ def scope(relation, conditions)
38
+ if Rails.version < "4.0"
39
+ query = relation.scoped
40
+ else
41
+ query = relation.all
42
+ end
43
+ query = query.joins(:roles)
44
+ query = where(query, conditions)
45
+ query
46
+ end
47
+
48
+ private
49
+
50
+ def build_conditions(relation, args)
51
+ conditions = []
52
+ values = []
53
+ args.each do |arg|
54
+ if arg.is_a? Hash
55
+ a, v = build_query(arg[:name], arg[:resource])
56
+ elsif arg.is_a?(String) || arg.is_a?(Symbol)
57
+ a, v = build_query(arg.to_s)
58
+ else
59
+ raise ArgumentError, "Invalid argument type: only hash or string or a symbol allowed"
60
+ end
61
+ conditions << a
62
+ values += v
63
+ end
64
+ conditions = conditions.join(' OR ')
65
+ [ conditions, values ]
66
+ end
67
+
68
+ def build_query(role, resource = nil)
69
+ return [ "#{role_table}.name = ?", [ role ] ] if resource == :any
70
+ query = "((#{role_table}.name = ?) AND (#{role_table}.resource_type IS NULL) AND (#{role_table}.resource_id IS NULL))"
71
+ values = [ role ]
72
+ if resource
73
+ query.insert(0, "(")
74
+ query += " OR ((#{role_table}.name = ?) AND (#{role_table}.resource_type = ?) AND (#{role_table}.resource_id IS NULL))"
75
+ values << role << (resource.is_a?(Class) ? resource.to_s : resource.class.name)
76
+ if !resource.is_a? Class
77
+ query += " OR ((#{role_table}.name = ?) AND (#{role_table}.resource_type = ?) AND (#{role_table}.resource_id = ?))"
78
+ values << role << resource.class.name << resource.id
79
+ end
80
+ query += ")"
81
+ end
82
+ [ query, values ]
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,27 @@
1
+ module Rolify
2
+ module Adapter
3
+ module Scopes
4
+ def global
5
+ where(:resource_type => nil, :resource_id => nil)
6
+ end
7
+
8
+ def class_scoped(resource_type = nil)
9
+ where_conditions = "resource_type IS NOT NULL AND resource_id IS NULL"
10
+ where_conditions = [ "resource_type = ? AND resource_id IS NULL", resource_type.name ] if resource_type
11
+ where(where_conditions)
12
+ end
13
+
14
+ def instance_scoped(resource_type = nil)
15
+ where_conditions = "resource_type IS NOT NULL AND resource_id IS NOT NULL"
16
+ if resource_type
17
+ if resource_type.is_a? Class
18
+ where_conditions = [ "resource_type = ? AND resource_id IS NOT NULL", resource_type.name ]
19
+ else
20
+ where_conditions = [ "resource_type = ? AND resource_id = ?", resource_type.class.name, resource_type.id ]
21
+ end
22
+ end
23
+ where(where_conditions)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,60 @@
1
+ module Rolify
2
+ module Adapter
3
+ class Base
4
+ def initialize(role_cname, user_cname)
5
+ @role_cname = role_cname
6
+ @user_cname = user_cname
7
+ end
8
+
9
+ def role_class
10
+ @role_cname.constantize
11
+ end
12
+
13
+ def user_class
14
+ @user_cname.constantize
15
+ end
16
+
17
+ def role_table
18
+ role_class.table_name
19
+ end
20
+
21
+ def self.create(adapter, role_cname, user_cname)
22
+ load "rolify/adapters/#{Rolify.orm}/#{adapter}.rb"
23
+ load "rolify/adapters/#{Rolify.orm}/scopes.rb"
24
+ Rolify::Adapter.const_get(adapter.camelize.to_sym).new(role_cname, user_cname)
25
+ end
26
+ end
27
+
28
+ class RoleAdapterBase < Adapter::Base
29
+ def where(relation, args)
30
+ raise NotImplementedError.new("You must implement where")
31
+ end
32
+
33
+ def find_or_create_by(role_name, resource_type = nil, resource_id = nil)
34
+ raise NotImplementedError.new("You must implement find_or_create_by")
35
+ end
36
+
37
+ def add(relation, role_name, resource = nil)
38
+ raise NotImplementedError.new("You must implement add")
39
+ end
40
+
41
+ def remove(relation, role_name, resource = nil)
42
+ raise NotImplementedError.new("You must implement delete")
43
+ end
44
+
45
+ def exists?(relation, column)
46
+ raise NotImplementedError.new("You must implement exists?")
47
+ end
48
+ end
49
+
50
+ class ResourceAdapterBase < Adapter::Base
51
+ def resources_find(roles_table, relation, role_name)
52
+ raise NotImplementedError.new("You must implement resources_find")
53
+ end
54
+
55
+ def in(resources, roles)
56
+ raise NotImplementedError.new("You must implement in")
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,27 @@
1
+ require 'rolify/adapters/base'
2
+
3
+ module Rolify
4
+ module Adapter
5
+ class ResourceAdapter < ResourceAdapterBase
6
+ def resources_find(roles_table, relation, role_name)
7
+ roles = roles_table.classify.constantize.where(:name.in => Array(role_name), :resource_type => relation.to_s)
8
+ resources = []
9
+ roles.each do |role|
10
+ if role.resource_id.nil?
11
+ resources += relation.all
12
+ else
13
+ resources << role.resource
14
+ end
15
+ end
16
+ resources.compact.uniq
17
+ end
18
+
19
+ def in(resources, user, role_names)
20
+ roles = user.roles.where(:name.in => Array(role_names))
21
+ return [] if resources.empty? || roles.empty?
22
+ resources.delete_if { |resource| (resource.applied_roles & roles).empty? }
23
+ resources
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,89 @@
1
+ require 'rolify/adapters/base'
2
+
3
+ module Rolify
4
+ module Adapter
5
+ class RoleAdapter < RoleAdapterBase
6
+ def where(relation, *args)
7
+ conditions = build_conditions(relation, args)
8
+ relation.any_of(*conditions)
9
+ end
10
+
11
+ def find_or_create_by(role_name, resource_type = nil, resource_id = nil)
12
+ self.role_class.find_or_create_by(:name => role_name,
13
+ :resource_type => resource_type,
14
+ :resource_id => resource_id)
15
+ end
16
+
17
+ def add(relation, role)
18
+ relation.roles << role
19
+ end
20
+
21
+ def remove(relation, role_name, resource = nil)
22
+ #roles = { :name => role_name }
23
+ #roles.merge!({:resource_type => (resource.is_a?(Class) ? resource.to_s : resource.class.name)}) if resource
24
+ #roles.merge!({ :resource_id => resource.id }) if resource && !resource.is_a?(Class)
25
+ #roles_to_remove = relation.roles.where(roles)
26
+ #roles_to_remove.each do |role|
27
+ # # Deletion in n-n relations is unreliable. Sometimes it works, sometimes not.
28
+ # # So, this does not work all the time: `relation.roles.delete(role)`
29
+ # # @see http://stackoverflow.com/questions/9132596/rails3-mongoid-many-to-many-relation-and-delete-operation
30
+ # # We instead remove ids from the Role object and the relation object.
31
+ # relation.role_ids.delete(role.id)
32
+ # role.send((user_class.to_s.underscore + '_ids').to_sym).delete(relation.id)
33
+ #
34
+ # role.destroy if role.send(user_class.to_s.tableize.to_sym).empty?
35
+ #end
36
+ cond = { :name => role_name }
37
+ cond[:resource_type] = (resource.is_a?(Class) ? resource.to_s : resource.class.name) if resource
38
+ cond[:resource_id] = resource.id if resource && !resource.is_a?(Class)
39
+ roles = relation.roles.where(cond)
40
+ roles.each do |role|
41
+ relation.roles.delete(role)
42
+ role.send(ActiveSupport::Inflector.demodulize(user_class).tableize.to_sym).delete(relation)
43
+ role.destroy if role.send(ActiveSupport::Inflector.demodulize(user_class).tableize.to_sym).empty?
44
+ end if roles
45
+ roles
46
+ end
47
+
48
+ def exists?(relation, column)
49
+ relation.where(column.to_sym.ne => nil)
50
+ end
51
+
52
+ def scope(relation, conditions)
53
+ roles = where(role_class, conditions).map { |role| role.id }
54
+ return [] if roles.size.zero?
55
+ query = relation.any_in(:role_ids => roles)
56
+ query
57
+ end
58
+
59
+ private
60
+
61
+ def build_conditions(relation, args)
62
+ conditions = []
63
+ args.each do |arg|
64
+ if arg.is_a? Hash
65
+ query = build_query(arg[:name], arg[:resource])
66
+ elsif arg.is_a?(String) || arg.is_a?(Symbol)
67
+ query = build_query(arg)
68
+ else
69
+ raise ArgumentError, "Invalid argument type: only hash or string or symbol allowed"
70
+ end
71
+ conditions += query
72
+ end
73
+ conditions
74
+ end
75
+
76
+ def build_query(role, resource = nil)
77
+ return [{ :name => role }] if resource == :any
78
+ query = [{ :name => role, :resource_type => nil, :resource_id => nil }]
79
+ if resource
80
+ query << { :name => role, :resource_type => (resource.is_a?(Class) ? resource.to_s : resource.class.name), :resource_id => nil }
81
+ if !resource.is_a? Class
82
+ query << { :name => role, :resource_type => resource.class.name, :resource_id => resource.id }
83
+ end
84
+ end
85
+ query
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,27 @@
1
+ module Rolify
2
+ module Adapter
3
+ module Scopes
4
+ def global
5
+ where(:resource_type => nil, :resource_id => nil)
6
+ end
7
+
8
+ def class_scoped(resource_type = nil)
9
+ where_conditions = { :resource_type.ne => nil, :resource_id => nil }
10
+ where_conditions = { :resource_type => resource_type.name, :resource_id => nil } if resource_type
11
+ where(where_conditions)
12
+ end
13
+
14
+ def instance_scoped(resource_type = nil)
15
+ where_conditions = { :resource_type.ne => nil, :resource_id.ne => nil }
16
+ if resource_type
17
+ if resource_type.is_a? Class
18
+ where_conditions = { :resource_type => resource_type.name, :resource_id.ne => nil }
19
+ else
20
+ where_conditions = { :resource_type => resource_type.class.name, :resource_id => resource_type.id }
21
+ end
22
+ end
23
+ where(where_conditions)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,56 @@
1
+ module Rolify
2
+ module Configure
3
+ @@dynamic_shortcuts = false
4
+ @@orm = "active_record"
5
+
6
+ def configure(*role_cnames)
7
+ return if !sanity_check(role_cnames)
8
+ yield self if block_given?
9
+ end
10
+
11
+ def dynamic_shortcuts
12
+ @@dynamic_shortcuts
13
+ end
14
+
15
+ def dynamic_shortcuts=(is_dynamic)
16
+ @@dynamic_shortcuts = is_dynamic
17
+ end
18
+
19
+ def orm
20
+ @@orm
21
+ end
22
+
23
+ def orm=(orm)
24
+ @@orm = orm
25
+ end
26
+
27
+ def use_mongoid
28
+ self.orm = "mongoid"
29
+ end
30
+
31
+ def use_dynamic_shortcuts
32
+ self.dynamic_shortcuts = true #if defined?(Rails::Server) || defined?(Rails::Console)
33
+ end
34
+
35
+ def use_defaults
36
+ configure do |config|
37
+ config.dynamic_shortcuts = false
38
+ config.orm = "active_record"
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def sanity_check(role_cnames)
45
+ role_cnames = [ "Role" ] if role_cnames.empty?
46
+ role_cnames.each do |role_cname|
47
+ role_class = role_cname.constantize
48
+ if role_class.superclass.to_s == "ActiveRecord" && !role_class.table_exists?
49
+ warn "[WARN] table '#{role_cname}' doesn't exist. Did you run the migration ? Ignoring rolify config."
50
+ return false
51
+ end
52
+ end
53
+ true
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,21 @@
1
+ module Rolify
2
+ module Dynamic
3
+ def load_dynamic_methods
4
+ self.role_class.all.each do |r|
5
+ define_dynamic_method(r.name, r.resource)
6
+ end
7
+ end
8
+
9
+ def define_dynamic_method(role_name, resource)
10
+ class_eval do
11
+ define_method("is_#{role_name}?".to_sym) do
12
+ has_role?("#{role_name}")
13
+ end if !method_defined?("is_#{role_name}?".to_sym)
14
+
15
+ define_method("is_#{role_name}_of?".to_sym) do |arg|
16
+ has_role?("#{role_name}", arg)
17
+ end if !method_defined?("is_#{role_name}_of?".to_sym) && resource
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,40 @@
1
+ module Rolify
2
+ module Finders
3
+ def with_role(role_name, resource = nil)
4
+ self.adapter.scope(self, :name => role_name, :resource => resource)
5
+ end
6
+
7
+ def with_all_roles(*args)
8
+ users = []
9
+ parse_args(args, users) do |users_to_add|
10
+ users = users_to_add if users.empty?
11
+ users &= users_to_add
12
+ return [] if users.empty?
13
+ end
14
+ users
15
+ end
16
+
17
+ def with_any_role(*args)
18
+ users = []
19
+ parse_args(args, users) do |users_to_add|
20
+ users += users_to_add
21
+ end
22
+ users.uniq
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def parse_args(args, users, &block)
29
+ args.each do |arg|
30
+ if arg.is_a? Hash
31
+ users_to_add = self.with_role(arg[:name], arg[:resource])
32
+ elsif arg.is_a?(String) || arg.is_a?(Symbol)
33
+ users_to_add = self.with_role(arg)
34
+ else
35
+ raise ArgumentError, "Invalid argument type: only hash or string or symbol allowed"
36
+ end
37
+ block.call(users_to_add)
38
+ end
39
+ end
40
+ end