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,13 @@
1
+ RSpec::Matchers.define :have_role do |*args|
2
+ match do |resource|
3
+ resource.has_role?(*args)
4
+ end
5
+
6
+ failure_message_for_should do |resource|
7
+ "expected to have role #{args.map(&:inspect).join(" ")}"
8
+ end
9
+
10
+ failure_message_for_should_not do |resource|
11
+ "expected not to have role #{args.map(&:inspect).join(" ")}"
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ require 'rolify'
2
+ require 'rails'
3
+
4
+ module Rolify
5
+ class Railtie < Rails::Railtie
6
+ initializer 'rolify.initialize' do
7
+ ActiveSupport.on_load(:active_record) do
8
+ ActiveRecord::Base.send :extend, Rolify
9
+ end
10
+
11
+ config.before_initialize do
12
+ ::Mongoid::Document.module_eval do
13
+ def self.included(base)
14
+ base.extend Rolify
15
+ end
16
+ end
17
+ end if defined?(Mongoid)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,31 @@
1
+ module Rolify
2
+ module Resource
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def find_roles(role_name = nil, user = nil)
9
+ roles = user && (user != :any) ? user.roles : self.role_class
10
+ roles = roles.where(:resource_type => self.to_s)
11
+ roles = roles.where(:name => role_name.to_s) if role_name && (role_name != :any)
12
+ roles
13
+ end
14
+
15
+ def with_role(role_name, user = nil)
16
+ if role_name.is_a? Array
17
+ role_name.map!(&:to_s)
18
+ else
19
+ role_name = role_name.to_s
20
+ end
21
+ resources = self.adapter.resources_find(self.role_table_name, self, role_name)
22
+ user ? self.adapter.in(resources, user, role_name) : resources
23
+ end
24
+ alias :with_roles :with_role
25
+ end
26
+
27
+ def applied_roles
28
+ self.roles + self.class.role_class.where(:resource_type => self.class.to_s, :resource_id => nil)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,85 @@
1
+ require "rolify/finders"
2
+
3
+ module Rolify
4
+ module Role
5
+ extend Utils
6
+
7
+ def self.included(base)
8
+ base.extend Finders
9
+ end
10
+
11
+ def add_role(role_name, resource = nil)
12
+ role = self.class.adapter.find_or_create_by(role_name.to_s,
13
+ (resource.is_a?(Class) ? resource.to_s : resource.class.name if resource),
14
+ (resource.id if resource && !resource.is_a?(Class)))
15
+
16
+ if !roles.include?(role)
17
+ self.class.define_dynamic_method(role_name, resource) if Rolify.dynamic_shortcuts
18
+ self.class.adapter.add(self, role)
19
+ end
20
+ role
21
+ end
22
+ alias_method :grant, :add_role
23
+ deprecate :has_role, :add_role
24
+
25
+ def has_role?(role_name, resource = nil)
26
+ if new_record?
27
+ self.roles.detect { |r| r.name == role_name.to_s && (r.resource == resource || resource.nil?) }.present?
28
+ else
29
+ self.class.adapter.where(self.roles, :name => role_name, :resource => resource).size > 0
30
+ end
31
+ end
32
+
33
+ def has_all_roles?(*args)
34
+ args.each do |arg|
35
+ if arg.is_a? Hash
36
+ return false if !self.has_role?(arg[:name], arg[:resource])
37
+ elsif arg.is_a?(String) || arg.is_a?(Symbol)
38
+ return false if !self.has_role?(arg)
39
+ else
40
+ raise ArgumentError, "Invalid argument type: only hash or string or symbol allowed"
41
+ end
42
+ end
43
+ true
44
+ end
45
+
46
+ def has_any_role?(*args)
47
+ self.class.adapter.where(self.roles, *args).size > 0
48
+ end
49
+
50
+ def only_has_role?(role_name, resource = nil)
51
+ return self.has_role?(role_name,resource) && self.roles.count == 1
52
+ end
53
+
54
+ def remove_role(role_name, resource = nil)
55
+ self.class.adapter.remove(self, role_name.to_s, resource)
56
+ end
57
+
58
+ alias_method :revoke, :remove_role
59
+ deprecate :has_no_role, :remove_role
60
+
61
+ def roles_name
62
+ self.roles.select(:name).map { |r| r.name }
63
+ end
64
+
65
+ def method_missing(method, *args, &block)
66
+ if method.to_s.match(/^is_(\w+)_of[?]$/) || method.to_s.match(/^is_(\w+)[?]$/)
67
+ resource = args.first
68
+ self.class.define_dynamic_method $1, resource
69
+ return has_role?("#{$1}", resource)
70
+ end unless !Rolify.dynamic_shortcuts
71
+ super
72
+ end
73
+
74
+ def respond_to?(method, include_private = false)
75
+ if Rolify.dynamic_shortcuts && (method.to_s.match(/^is_(\w+)_of[?]$/) || method.to_s.match(/^is_(\w+)[?]$/))
76
+ query = self.class.role_class.where(:name => $1)
77
+ query = self.class.adapter.exists?(query, :resource_type) if method.to_s.match(/^is_(\w+)_of[?]$/)
78
+ return true if query.count > 0
79
+ false
80
+ else
81
+ super
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,10 @@
1
+ module Rolify
2
+ module Utils
3
+ def deprecate(old_method, new_method)
4
+ define_method(old_method) do |*args|
5
+ warn "[DEPRECATION] #{caller.first}: `#{old_method}` is deprecated. Please use `#{new_method}` instead."
6
+ send(new_method, *args)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ module Rolify
2
+ VERSION = "3.3.0.rc5"
3
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rolify/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "third-prestige-rolify"
7
+ s.version = Rolify::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Florent Monbillard"]
10
+ s.email = ["f.monbillard@gmail.com"]
11
+ s.homepage = "http://github.com/thirdprestige/rolify/"
12
+ s.summary = %q{Roles library with resource scoping}
13
+ s.description = %q{Very simple Roles library without any authorization enforcement supporting scope on resource objects (instance or class). Supports ActiveRecord and Mongoid ORMs.}
14
+
15
+ s.rubyforge_project = s.name
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- spec/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_development_dependency "ammeter"
23
+ s.add_development_dependency "rake"
24
+ s.add_development_dependency "rspec", ">= 2.0"
25
+ s.add_development_dependency "rspec-rails", ">= 2.0"
26
+ s.add_development_dependency "bundler"
27
+ s.add_development_dependency "fuubar"
28
+ s.add_development_dependency "activerecord", ">= 3.2.0"
29
+ s.add_development_dependency "mongoid", ">= 3.1"
30
+ end
@@ -0,0 +1,24 @@
1
+ = Rolify Specs
2
+
3
+ == Running the specs
4
+
5
+ To run the specs first run the +bundle+ command to install the necessary gems and the +rake+ command to run the specs.
6
+
7
+ bundle
8
+ rake
9
+
10
+ == Model Adapters
11
+
12
+ Rolify currently supports 2 different ORMs: ActiveRecord and Mongoid. By default it will use Active Record but you can change this by setting the +ADAPTER+ environment variable before running the specs. You can run the +bundle+ command with this as well to ensure you have all the required gems.
13
+
14
+ ADAPTER=mongoid bundle
15
+ ADAPTER=mongoid rake
16
+
17
+ The different model adapters you can specify are:
18
+
19
+ * active_record (default)
20
+ * mongoid
21
+
22
+ You can also run the +spec_all+ rake task to run specs for each adapter.
23
+
24
+ rake spec_all
@@ -0,0 +1,163 @@
1
+ require 'generators_helper'
2
+
3
+ require 'rails/all'
4
+ # Generators are not automatically loaded by Rails
5
+ require 'generators/rolify/rolify_generator'
6
+
7
+ describe Rolify::Generators::RolifyGenerator, :if => ENV['ADAPTER'] == 'active_record' do
8
+ # Tell the generator where to put its output (what it thinks of as Rails.root)
9
+ destination File.expand_path("../../../../tmp", __FILE__)
10
+ teardown :cleanup_destination_root
11
+
12
+ before {
13
+ prepare_destination
14
+ }
15
+
16
+ def cleanup_destination_root
17
+ FileUtils.rm_rf destination_root
18
+ end
19
+
20
+ describe 'specifying only Role class name' do
21
+ before(:all) { arguments %w(Role) }
22
+
23
+ before {
24
+ capture(:stdout) {
25
+ generator.create_file "app/models/user.rb" do
26
+ <<-RUBY
27
+ class User < ActiveRecord::Base
28
+ end
29
+ RUBY
30
+ end
31
+ }
32
+ require File.join(destination_root, "app/models/user.rb")
33
+ run_generator
34
+ }
35
+
36
+ describe 'config/initializers/rolify.rb' do
37
+ subject { file('config/initializers/rolify.rb') }
38
+ it { should exist }
39
+ it { should contain "Rolify.configure do |config|"}
40
+ it { should contain "# config.use_dynamic_shortcuts" }
41
+ it { should contain "# config.use_mongoid" }
42
+ end
43
+
44
+ describe 'app/models/role.rb' do
45
+ subject { file('app/models/role.rb') }
46
+ it { should exist }
47
+ it { should contain "class Role < ActiveRecord::Base" }
48
+ it { should contain "has_and_belongs_to_many :users, :join_table => :users_roles" }
49
+ it { should contain "belongs_to :resource, :polymorphic => true" }
50
+ end
51
+
52
+ describe 'app/models/user.rb' do
53
+ subject { file('app/models/user.rb') }
54
+ it { should contain /class User < ActiveRecord::Base\n rolify\n/ }
55
+ end
56
+
57
+ describe 'migration file' do
58
+ subject { migration_file('db/migrate/rolify_create_roles.rb') }
59
+
60
+ it { should be_a_migration }
61
+ it { should contain "create_table(:roles) do" }
62
+ it { should contain "create_table(:users_roles, :id => false) do" }
63
+ end
64
+ end
65
+
66
+ describe 'specifying User and Role class names' do
67
+ before(:all) { arguments %w(AdminRole AdminUser) }
68
+
69
+ before {
70
+ capture(:stdout) {
71
+ generator.create_file "app/models/admin_user.rb" do
72
+ "class AdminUser < ActiveRecord::Base\nend"
73
+ end
74
+ }
75
+ require File.join(destination_root, "app/models/admin_user.rb")
76
+ run_generator
77
+ }
78
+
79
+ describe 'config/initializers/rolify.rb' do
80
+ subject { file('config/initializers/rolify.rb') }
81
+
82
+ it { should exist }
83
+ it { should contain "Rolify.configure(\"AdminRole\") do |config|"}
84
+ it { should contain "# config.use_dynamic_shortcuts" }
85
+ it { should contain "# config.use_mongoid" }
86
+ end
87
+
88
+ describe 'app/models/admin_role.rb' do
89
+ subject { file('app/models/admin_role.rb') }
90
+
91
+ it { should exist }
92
+ it { should contain "class AdminRole < ActiveRecord::Base" }
93
+ it { should contain "has_and_belongs_to_many :admin_users, :join_table => :admin_users_admin_roles" }
94
+ it { should contain "belongs_to :resource, :polymorphic => true" }
95
+ end
96
+
97
+ describe 'app/models/admin_user.rb' do
98
+ subject { file('app/models/admin_user.rb') }
99
+
100
+ it { should contain /class AdminUser < ActiveRecord::Base\n rolify :role_cname => 'AdminRole'\n/ }
101
+ end
102
+
103
+ describe 'migration file' do
104
+ subject { migration_file('db/migrate/rolify_create_admin_roles.rb') }
105
+
106
+ it { should be_a_migration }
107
+ it { should contain "create_table(:admin_roles)" }
108
+ it { should contain "create_table(:admin_users_admin_roles, :id => false) do" }
109
+ end
110
+ end
111
+
112
+ describe 'specifying namespaced User and Role class names' do
113
+ before(:all) { arguments %w(Admin::Role Admin::User) }
114
+
115
+ before {
116
+ capture(:stdout) {
117
+ generator.create_file "app/models/admin/user.rb" do
118
+ <<-RUBY
119
+ module Admin
120
+ class User < ActiveRecord::Base
121
+ self.table_name_prefix = 'admin_'
122
+ end
123
+ end
124
+ RUBY
125
+ end
126
+ }
127
+ require File.join(destination_root, "app/models/admin/user.rb")
128
+ run_generator
129
+ }
130
+
131
+ describe 'config/initializers/rolify.rb' do
132
+ subject { file('config/initializers/rolify.rb') }
133
+
134
+ it { should exist }
135
+ it { should contain "Rolify.configure(\"Admin::Role\") do |config|"}
136
+ it { should contain "# config.use_dynamic_shortcuts" }
137
+ it { should contain "# config.use_mongoid" }
138
+ end
139
+
140
+ describe 'app/models/admin/role.rb' do
141
+ subject { file('app/models/admin/role.rb') }
142
+
143
+ it { should exist }
144
+ it { should contain "class Admin::Role < ActiveRecord::Base" }
145
+ it { should contain "has_and_belongs_to_many :admin_users, :join_table => :admin_users_admin_roles" }
146
+ it { should contain "belongs_to :resource, :polymorphic => true" }
147
+ end
148
+
149
+ describe 'app/models/admin/user.rb' do
150
+ subject { file('app/models/admin/user.rb') }
151
+
152
+ it { should contain /class User < ActiveRecord::Base\n rolify :role_cname => 'Admin::Role'\n/ }
153
+ end
154
+
155
+ describe 'migration file' do
156
+ subject { migration_file('db/migrate/rolify_create_admin_roles.rb') }
157
+
158
+ it { should be_a_migration }
159
+ it { should contain "create_table(:admin_roles)" }
160
+ it { should contain "create_table(:admin_users_admin_roles, :id => false) do" }
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,112 @@
1
+ require 'generators_helper'
2
+
3
+ require 'mongoid'
4
+
5
+ # Generators are not automatically loaded by Rails
6
+ require 'generators/rolify/rolify_generator'
7
+
8
+ describe Rolify::Generators::RolifyGenerator, :if => ENV['ADAPTER'] == 'mongoid' do
9
+ # Tell the generator where to put its output (what it thinks of as Rails.root)
10
+ destination File.expand_path("../../../../tmp", __FILE__)
11
+ teardown :cleanup_destination_root
12
+
13
+ before {
14
+ prepare_destination
15
+ }
16
+
17
+ def cleanup_destination_root
18
+ FileUtils.rm_rf destination_root
19
+ end
20
+
21
+ describe 'specifying ORM adapter' do
22
+ before(:all) { arguments [ "Role", "User", "--orm=mongoid" ] }
23
+
24
+ before {
25
+ capture(:stdout) {
26
+ generator.create_file "app/models/user.rb" do
27
+ <<-RUBY
28
+ class User
29
+ include Mongoid::Document
30
+
31
+ field :login, :type => String
32
+ end
33
+ RUBY
34
+ end
35
+ }
36
+ require File.join(destination_root, "app/models/user.rb")
37
+ run_generator
38
+ }
39
+
40
+ describe 'config/initializers/rolify.rb' do
41
+ subject { file('config/initializers/rolify.rb') }
42
+ it { should exist }
43
+ it { should contain "Rolify.configure do |config|"}
44
+ it { should_not contain "# config.use_mongoid" }
45
+ it { should contain "# config.use_dynamic_shortcuts" }
46
+ end
47
+
48
+ describe 'app/models/role.rb' do
49
+ subject { file('app/models/role.rb') }
50
+ it { should exist }
51
+ it { should contain "class Role\n" }
52
+ it { should contain "has_and_belongs_to_many :users\n" }
53
+ it { should contain "belongs_to :resource, :polymorphic => true" }
54
+ it { should contain "field :name, :type => String" }
55
+ it { should contain " index({\n"
56
+ " { :name => 1 },\n"
57
+ " { :resource_type => 1 },\n"
58
+ " { :resource_id => 1 }\n"
59
+ " },\n"
60
+ " { unique => true })"}
61
+ end
62
+
63
+ describe 'app/models/user.rb' do
64
+ subject { file('app/models/user.rb') }
65
+ it { should contain /class User\n include Mongoid::Document\n rolify\n/ }
66
+ end
67
+ end
68
+
69
+ describe 'specifying namespaced User and Role class names and ORM adapter' do
70
+ before(:all) { arguments %w(Admin::Role Admin::User --orm=mongoid) }
71
+
72
+ before {
73
+ capture(:stdout) {
74
+ generator.create_file "app/models/admin/user.rb" do
75
+ <<-RUBY
76
+ module Admin
77
+ class User
78
+ include Mongoid::Document
79
+ end
80
+ end
81
+ RUBY
82
+ end
83
+ }
84
+ require File.join(destination_root, "app/models/admin/user.rb")
85
+ run_generator
86
+ }
87
+
88
+ describe 'config/initializers/rolify.rb' do
89
+ subject { file('config/initializers/rolify.rb') }
90
+
91
+ it { should exist }
92
+ it { should contain "Rolify.configure(\"Admin::Role\") do |config|"}
93
+ it { should contain "# config.use_dynamic_shortcuts" }
94
+ it { should_not contain "# config.use_mongoid" }
95
+ end
96
+
97
+ describe 'app/models/admin/role.rb' do
98
+ subject { file('app/models/admin/role.rb') }
99
+
100
+ it { should exist }
101
+ it { should contain "class Admin::Role" }
102
+ it { should contain "has_and_belongs_to_many :admin_users" }
103
+ it { should contain "belongs_to :resource, :polymorphic => true" }
104
+ end
105
+
106
+ describe 'app/models/admin/user.rb' do
107
+ subject { file('app/models/admin/user.rb') }
108
+
109
+ it { should contain /class User\n include Mongoid::Document\n rolify :role_cname => 'Admin::Role'\n/ }
110
+ end
111
+ end
112
+ end