rolify 3.1.0 → 4.0.0
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.
- checksums.yaml +7 -0
- data/.gitignore +4 -1
- data/.travis.yml +44 -11
- data/CHANGELOG.rdoc +70 -0
- data/CONTRIBUTORS +6 -0
- data/Gemfile +21 -2
- data/README.md +130 -68
- data/Rakefile +29 -4
- data/UPGRADE.rdoc +22 -0
- data/circle.yml +13 -0
- data/gemfiles/Gemfile.rails-3.2 +27 -0
- data/gemfiles/Gemfile.rails-4.0 +33 -0
- data/gemfiles/Gemfile.rails-4.1 +37 -0
- data/lib/generators/active_record/rolify_generator.rb +54 -0
- data/lib/generators/active_record/templates/README +8 -0
- data/lib/generators/active_record/templates/migration.rb +19 -0
- data/lib/generators/mongoid/rolify_generator.rb +55 -0
- data/lib/generators/mongoid/templates/README-mongoid +4 -0
- data/lib/generators/rolify/rolify_generator.rb +35 -0
- data/lib/generators/rolify/{role/templates/README-mongoid → templates/README} +1 -5
- data/lib/generators/rolify/templates/initializer.rb +7 -0
- data/lib/generators/rolify/templates/role-active_record.rb +11 -0
- data/lib/generators/rolify/{role/templates → templates}/role-mongoid.rb +9 -9
- data/lib/generators/rolify/user_generator.rb +39 -0
- data/lib/rolify/adapters/active_record/resource_adapter.rb +36 -6
- data/lib/rolify/adapters/active_record/role_adapter.rb +25 -13
- data/lib/rolify/adapters/active_record/scopes.rb +27 -0
- data/lib/rolify/adapters/base.rb +9 -0
- data/lib/rolify/adapters/mongoid/resource_adapter.rb +27 -6
- data/lib/rolify/adapters/mongoid/role_adapter.rb +35 -11
- data/lib/rolify/adapters/mongoid/scopes.rb +27 -0
- data/lib/rolify/configure.rb +36 -5
- data/lib/rolify/finders.rb +40 -0
- data/lib/rolify/matchers.rb +31 -0
- data/lib/rolify/railtie.rb +1 -1
- data/lib/rolify/resource.rb +19 -10
- data/lib/rolify/role.rb +33 -13
- data/lib/rolify/version.rb +1 -1
- data/lib/rolify.rb +46 -20
- data/rolify.gemspec +18 -24
- data/spec/README.rdoc +24 -0
- data/spec/generators/rolify/rolify_activerecord_generator_spec.rb +165 -0
- data/spec/generators/rolify/rolify_mongoid_generator_spec.rb +113 -0
- data/spec/generators_helper.rb +27 -0
- data/spec/rolify/config_spec.rb +20 -21
- data/spec/rolify/custom_spec.rb +11 -6
- data/spec/rolify/matchers_spec.rb +24 -0
- data/spec/rolify/namespace_spec.rb +24 -0
- data/spec/rolify/resource_spec.rb +135 -37
- data/spec/rolify/resourcifed_and_rolifed_spec.rb +24 -0
- data/spec/rolify/role_spec.rb +8 -9
- data/spec/rolify/shared_contexts.rb +22 -3
- data/spec/rolify/shared_examples/shared_examples_for_add_role.rb +10 -17
- data/spec/rolify/shared_examples/shared_examples_for_callbacks.rb +65 -0
- data/spec/rolify/shared_examples/shared_examples_for_dynamic.rb +64 -27
- data/spec/rolify/shared_examples/shared_examples_for_finders.rb +81 -0
- data/spec/rolify/shared_examples/shared_examples_for_has_all_roles.rb +29 -29
- data/spec/rolify/shared_examples/shared_examples_for_has_any_role.rb +35 -35
- data/spec/rolify/shared_examples/shared_examples_for_has_role.rb +38 -38
- data/spec/rolify/shared_examples/shared_examples_for_only_has_role.rb +174 -0
- data/spec/rolify/shared_examples/shared_examples_for_remove_role.rb +28 -59
- data/spec/rolify/shared_examples/shared_examples_for_roles.rb +58 -32
- data/spec/rolify/shared_examples/shared_examples_for_scopes.rb +38 -0
- data/spec/spec_helper.rb +39 -3
- data/spec/support/adapters/active_record.rb +58 -7
- data/spec/support/adapters/mongoid.rb +110 -17
- data/spec/support/adapters/mongoid.yml +6 -0
- data/spec/support/data.rb +18 -15
- data/spec/support/schema.rb +31 -16
- data/spec/support/stream_helpers.rb +18 -0
- metadata +88 -84
- data/lib/generators/rolify/role/role_generator.rb +0 -41
- data/lib/generators/rolify/role/templates/README +0 -11
- data/lib/generators/rolify/role/templates/README-active_record +0 -21
- data/lib/generators/rolify/role/templates/initializer.rb +0 -7
- data/lib/generators/rolify/role/templates/migration.rb +0 -19
- data/lib/generators/rolify/role/templates/role-active_record.rb +0 -4
- data/spec/generators/rolify/role/role_generator_spec.rb +0 -197
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'rails/generators/active_record'
|
|
2
|
+
require 'active_support/core_ext'
|
|
3
|
+
|
|
4
|
+
module ActiveRecord
|
|
5
|
+
module Generators
|
|
6
|
+
class RolifyGenerator < ActiveRecord::Generators::Base
|
|
7
|
+
source_root File.expand_path("../templates", __FILE__)
|
|
8
|
+
|
|
9
|
+
argument :user_cname, :type => :string, :default => "User", :banner => "User"
|
|
10
|
+
|
|
11
|
+
def generate_model
|
|
12
|
+
invoke "active_record:model", [ name ], :migration => false
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def inject_role_class
|
|
16
|
+
inject_into_class(model_path, class_name, model_content)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def copy_rolify_migration
|
|
20
|
+
migration_template "migration.rb", "db/migrate/rolify_create_#{table_name}.rb"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def join_table
|
|
24
|
+
user_cname.constantize.table_name + "_" + table_name
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def user_reference
|
|
28
|
+
user_cname.demodulize.underscore
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def role_reference
|
|
32
|
+
class_name.demodulize.underscore
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def model_path
|
|
36
|
+
File.join("app", "models", "#{file_path}.rb")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def model_content
|
|
40
|
+
content = <<RUBY
|
|
41
|
+
has_and_belongs_to_many :%{user_cname}, :join_table => :%{join_table}
|
|
42
|
+
belongs_to :resource, :polymorphic => true
|
|
43
|
+
|
|
44
|
+
validates :resource_type,
|
|
45
|
+
:inclusion => { :in => Rolify.resource_types },
|
|
46
|
+
:allow_nil => true
|
|
47
|
+
|
|
48
|
+
scopify
|
|
49
|
+
RUBY
|
|
50
|
+
content % { :user_cname => user_cname.constantize.table_name, :join_table => "#{user_cname.constantize.table_name}_#{table_name}"}
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class RolifyCreate<%= table_name.camelize %> < ActiveRecord::Migration
|
|
2
|
+
def change
|
|
3
|
+
create_table(:<%= table_name %>) do |t|
|
|
4
|
+
t.string :name
|
|
5
|
+
t.references :resource, :polymorphic => true
|
|
6
|
+
|
|
7
|
+
t.timestamps
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
create_table(:<%= join_table %>, :id => false) do |t|
|
|
11
|
+
t.references :<%= user_reference %>
|
|
12
|
+
t.references :<%= role_reference %>
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
add_index(:<%= table_name %>, :name)
|
|
16
|
+
add_index(:<%= table_name %>, [ :name, :resource_type, :resource_id ])
|
|
17
|
+
add_index(:<%= join_table %>, [ :<%= user_reference %>_id, :<%= role_reference %>_id ])
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'rails/generators/mongoid_generator'
|
|
2
|
+
require 'active_support/core_ext'
|
|
3
|
+
|
|
4
|
+
module Mongoid
|
|
5
|
+
module Generators
|
|
6
|
+
class RolifyGenerator < Rails::Generators::NamedBase
|
|
7
|
+
source_root File.expand_path("../templates", __FILE__)
|
|
8
|
+
|
|
9
|
+
argument :user_cname, :type => :string, :default => "User", :banner => "User"
|
|
10
|
+
|
|
11
|
+
def generate_model
|
|
12
|
+
invoke "mongoid:model", [ name ]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def inject_role_class
|
|
16
|
+
inject_into_file(model_path, model_contents, :after => "include Mongoid::Document\n")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def user_reference
|
|
20
|
+
user_cname.demodulize.underscore
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def role_reference
|
|
24
|
+
class_name.demodulize.underscore
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def model_path
|
|
28
|
+
File.join("app", "models", "#{file_path}.rb")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def model_contents
|
|
32
|
+
content = <<RUBY
|
|
33
|
+
has_and_belongs_to_many :%{user_cname}
|
|
34
|
+
belongs_to :resource, :polymorphic => true
|
|
35
|
+
|
|
36
|
+
field :name, :type => String
|
|
37
|
+
|
|
38
|
+
index({
|
|
39
|
+
:name => 1,
|
|
40
|
+
:resource_type => 1,
|
|
41
|
+
:resource_id => 1
|
|
42
|
+
},
|
|
43
|
+
{ :unique => true})
|
|
44
|
+
|
|
45
|
+
validates :resource_type,
|
|
46
|
+
:inclusion => { :in => Rolify.resource_types },
|
|
47
|
+
:allow_nil => true
|
|
48
|
+
|
|
49
|
+
scopify
|
|
50
|
+
RUBY
|
|
51
|
+
content % { :user_cname => user_cname.constantize.collection_name }
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Rolify
|
|
2
|
+
module Generators
|
|
3
|
+
class RolifyGenerator < Rails::Generators::NamedBase
|
|
4
|
+
Rails::Generators::ResourceHelpers
|
|
5
|
+
|
|
6
|
+
source_root File.expand_path('../templates', __FILE__)
|
|
7
|
+
argument :user_cname, :type => :string, :default => "User"
|
|
8
|
+
|
|
9
|
+
namespace :rolify
|
|
10
|
+
hook_for :orm, :required => true
|
|
11
|
+
|
|
12
|
+
desc "Generates a model with the given NAME and a migration file."
|
|
13
|
+
|
|
14
|
+
def self.start(args, config)
|
|
15
|
+
user_cname = args.size > 1 ? args[1] : "User"
|
|
16
|
+
args.insert(1, user_cname) # 0 being the view name
|
|
17
|
+
super
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def inject_user_class
|
|
21
|
+
invoke "rolify:user", [ user_cname, class_name ], :orm => options.orm
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def copy_initializer_file
|
|
25
|
+
template "initializer.rb", "config/initializers/rolify.rb"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def show_readme
|
|
29
|
+
if behavior == :invoke
|
|
30
|
+
readme "README"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -4,14 +4,10 @@ An initializer file has been created here: config/initializers/rolify.rb, you
|
|
|
4
4
|
can change rolify settings to match your needs.
|
|
5
5
|
Defaults values are commented out.
|
|
6
6
|
|
|
7
|
-
A Role class has been
|
|
7
|
+
A Role class has been created in app/models (with the name you gave as
|
|
8
8
|
argument otherwise the default is role.rb), you can add your own business logic
|
|
9
9
|
inside.
|
|
10
10
|
|
|
11
11
|
Inside your User class (or the name you gave as argument otherwise the default
|
|
12
12
|
is user.rb), rolify method has been inserted to provide rolify methods.
|
|
13
13
|
|
|
14
|
-
Now, if you are able to add the resourcify method inside all models you want
|
|
15
|
-
scoped by a role.
|
|
16
|
-
|
|
17
|
-
===============================================================================
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Rolify.configure<%= "(\"#{class_name.camelize.to_s}\")" if class_name != "Role" %> do |config|
|
|
2
|
+
# By default ORM adapter is ActiveRecord. uncomment to use mongoid
|
|
3
|
+
<%= "# " if options.orm == :active_record || !options.orm %>config.use_mongoid
|
|
4
|
+
|
|
5
|
+
# Dynamic shortcuts for User class (user.is_admin? like methods). Default is: false
|
|
6
|
+
# config.use_dynamic_shortcuts
|
|
7
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class <%= role_cname.camelize %> < ActiveRecord::Base
|
|
2
|
+
<% if need_table_prefix?(role_cname) %>
|
|
3
|
+
def self.table_name_prefix
|
|
4
|
+
<%= table_prefix(role_cname) %>_
|
|
5
|
+
end
|
|
6
|
+
<% end %>
|
|
7
|
+
has_and_belongs_to_many :<%= user_cname.tableize %>, :join_table => :<%= "#{table_name(user_cname, true)}_#{table_name(role_cname, true)}" %>
|
|
8
|
+
belongs_to :resource, :polymorphic => true
|
|
9
|
+
|
|
10
|
+
scopify
|
|
11
|
+
end
|
|
@@ -5,13 +5,13 @@ class <%= role_cname.camelize %>
|
|
|
5
5
|
belongs_to :resource, :polymorphic => true
|
|
6
6
|
|
|
7
7
|
field :name, :type => String
|
|
8
|
-
|
|
9
|
-
index(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
|
|
9
|
+
index({
|
|
10
|
+
:name => 1,
|
|
11
|
+
:resource_type => 1,
|
|
12
|
+
:resource_id => 1
|
|
13
|
+
},
|
|
14
|
+
{ :unique => true})
|
|
15
|
+
|
|
16
|
+
scopify
|
|
17
17
|
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'rails/generators/migration'
|
|
2
|
+
require 'active_support/core_ext'
|
|
3
|
+
|
|
4
|
+
module Rolify
|
|
5
|
+
module Generators
|
|
6
|
+
class UserGenerator < Rails::Generators::NamedBase
|
|
7
|
+
argument :role_cname, :type => :string, :default => "Role"
|
|
8
|
+
class_option :orm, :type => :string, :default => "active_record"
|
|
9
|
+
|
|
10
|
+
desc "Inject rolify method in the User class."
|
|
11
|
+
|
|
12
|
+
def inject_user_content
|
|
13
|
+
inject_into_file(model_path, :after => inject_rolify_method) do
|
|
14
|
+
" rolify#{role_association}\n"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def inject_rolify_method
|
|
19
|
+
if options.orm == :active_record
|
|
20
|
+
/class #{class_name.camelize}\n|class #{class_name.camelize} .*\n|class #{class_name.demodulize.camelize}\n|class #{class_name.demodulize.camelize} .*\n/
|
|
21
|
+
else
|
|
22
|
+
/include Mongoid::Document\n|include Mongoid::Document .*\n/
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def model_path
|
|
27
|
+
File.join("app", "models", "#{file_path}.rb")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def role_association
|
|
31
|
+
if role_cname != "Role"
|
|
32
|
+
" :role_cname => '#{role_cname.camelize}'"
|
|
33
|
+
else
|
|
34
|
+
""
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -1,17 +1,47 @@
|
|
|
1
1
|
require 'rolify/adapters/base'
|
|
2
2
|
|
|
3
3
|
module Rolify
|
|
4
|
-
module Adapter
|
|
4
|
+
module Adapter
|
|
5
5
|
class ResourceAdapter < ResourceAdapterBase
|
|
6
|
+
def find_roles(role_name, relation, user)
|
|
7
|
+
roles = user && (user != :any) ? user.roles : self.role_class
|
|
8
|
+
roles = roles.where('resource_type IN (?)', self.relation_types_for(relation))
|
|
9
|
+
roles = roles.where(:name => role_name.to_s) if role_name && (role_name != :any)
|
|
10
|
+
roles
|
|
11
|
+
end
|
|
12
|
+
|
|
6
13
|
def resources_find(roles_table, relation, role_name)
|
|
7
|
-
|
|
8
|
-
|
|
14
|
+
klasses = self.relation_types_for(relation)
|
|
15
|
+
relations = klasses.inject('') do |str, klass|
|
|
16
|
+
str = "#{str}'#{klass.to_s}'"
|
|
17
|
+
str << ', ' unless klass == klasses.last
|
|
18
|
+
str
|
|
19
|
+
end
|
|
20
|
+
resources = relation.joins("INNER JOIN #{quote(roles_table)} ON #{quote(roles_table)}.resource_type IN (#{relations}) AND
|
|
21
|
+
(#{quote(roles_table)}.resource_id IS NULL OR #{quote(roles_table)}.resource_id = #{quote(relation.table_name)}.#{relation.primary_key})")
|
|
22
|
+
resources = resources.where("#{quote(roles_table)}.name IN (?) AND #{quote(roles_table)}.resource_type IN (?)", Array(role_name), klasses)
|
|
23
|
+
resources = resources.select("#{quote(relation.table_name)}.*")
|
|
9
24
|
resources
|
|
10
25
|
end
|
|
11
26
|
|
|
12
|
-
def in(relation,
|
|
13
|
-
|
|
27
|
+
def in(relation, user, role_names)
|
|
28
|
+
roles = user.roles.where(:name => role_names).select("#{quote(role_class.table_name)}.#{role_class.primary_key}")
|
|
29
|
+
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)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def applied_roles(relation, children)
|
|
33
|
+
if children
|
|
34
|
+
relation.role_class.where('resource_type IN (?) AND resource_id IS NULL', self.relation_types_for(relation))
|
|
35
|
+
else
|
|
36
|
+
relation.role_class.where('resource_type = ? AND resource_id IS NULL', relation.to_s)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def quote(column)
|
|
43
|
+
ActiveRecord::Base.connection.quote_column_name column
|
|
14
44
|
end
|
|
15
45
|
end
|
|
16
46
|
end
|
|
17
|
-
end
|
|
47
|
+
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require 'rolify/adapters/base'
|
|
2
2
|
|
|
3
3
|
module Rolify
|
|
4
|
-
module Adapter
|
|
4
|
+
module Adapter
|
|
5
5
|
class RoleAdapter < RoleAdapterBase
|
|
6
6
|
def where(relation, *args)
|
|
7
7
|
conditions, values = build_conditions(relation, args)
|
|
@@ -9,7 +9,7 @@ module Rolify
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def find_or_create_by(role_name, resource_type = nil, resource_id = nil)
|
|
12
|
-
role_class.
|
|
12
|
+
role_class.where(:name => role_name, :resource_type => resource_type, :resource_id => resource_id).first_or_create
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def add(relation, role)
|
|
@@ -17,14 +17,15 @@ module Rolify
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def remove(relation, role_name, resource = nil)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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)
|
|
23
24
|
if roles
|
|
24
25
|
relation.roles.delete(roles)
|
|
25
|
-
roles.each do |role|
|
|
26
|
-
role.destroy if role.send(user_class.
|
|
27
|
-
end
|
|
26
|
+
roles.each do |role|
|
|
27
|
+
role.destroy if role.send(ActiveSupport::Inflector.demodulize(user_class).tableize.to_sym).limit(1).empty?
|
|
28
|
+
end if Rolify.remove_role_if_empty
|
|
28
29
|
end
|
|
29
30
|
roles
|
|
30
31
|
end
|
|
@@ -33,6 +34,17 @@ module Rolify
|
|
|
33
34
|
relation.where("#{column} IS NOT NULL")
|
|
34
35
|
end
|
|
35
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
|
+
|
|
36
48
|
private
|
|
37
49
|
|
|
38
50
|
def build_conditions(relation, args)
|
|
@@ -54,15 +66,15 @@ module Rolify
|
|
|
54
66
|
end
|
|
55
67
|
|
|
56
68
|
def build_query(role, resource = nil)
|
|
57
|
-
return [ "name = ?", [ role ] ] if resource == :any
|
|
58
|
-
query = "((name = ?) AND (resource_type IS NULL) AND (resource_id IS NULL))"
|
|
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))"
|
|
59
71
|
values = [ role ]
|
|
60
72
|
if resource
|
|
61
73
|
query.insert(0, "(")
|
|
62
|
-
query += " OR ((name = ?) AND (resource_type = ?) AND (resource_id IS NULL))"
|
|
74
|
+
query += " OR ((#{role_table}.name = ?) AND (#{role_table}.resource_type = ?) AND (#{role_table}.resource_id IS NULL))"
|
|
63
75
|
values << role << (resource.is_a?(Class) ? resource.to_s : resource.class.name)
|
|
64
76
|
if !resource.is_a? Class
|
|
65
|
-
query += " OR ((name = ?) AND (resource_type = ?) AND (resource_id = ?))"
|
|
77
|
+
query += " OR ((#{role_table}.name = ?) AND (#{role_table}.resource_type = ?) AND (#{role_table}.resource_id = ?))"
|
|
66
78
|
values << role << resource.class.name << resource.id
|
|
67
79
|
end
|
|
68
80
|
query += ")"
|
|
@@ -71,4 +83,4 @@ module Rolify
|
|
|
71
83
|
end
|
|
72
84
|
end
|
|
73
85
|
end
|
|
74
|
-
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
|
data/lib/rolify/adapters/base.rb
CHANGED
|
@@ -14,10 +14,19 @@ module Rolify
|
|
|
14
14
|
@user_cname.constantize
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
def role_table
|
|
18
|
+
role_class.table_name
|
|
19
|
+
end
|
|
20
|
+
|
|
17
21
|
def self.create(adapter, role_cname, user_cname)
|
|
18
22
|
load "rolify/adapters/#{Rolify.orm}/#{adapter}.rb"
|
|
23
|
+
load "rolify/adapters/#{Rolify.orm}/scopes.rb"
|
|
19
24
|
Rolify::Adapter.const_get(adapter.camelize.to_sym).new(role_cname, user_cname)
|
|
20
25
|
end
|
|
26
|
+
|
|
27
|
+
def relation_types_for(relation)
|
|
28
|
+
relation.descendants.map(&:to_s).push(relation.to_s)
|
|
29
|
+
end
|
|
21
30
|
end
|
|
22
31
|
|
|
23
32
|
class RoleAdapterBase < Adapter::Base
|
|
@@ -1,23 +1,44 @@
|
|
|
1
1
|
require 'rolify/adapters/base'
|
|
2
2
|
|
|
3
3
|
module Rolify
|
|
4
|
-
module Adapter
|
|
4
|
+
module Adapter
|
|
5
5
|
class ResourceAdapter < ResourceAdapterBase
|
|
6
|
+
|
|
7
|
+
def find_roles(role_name, relation, user)
|
|
8
|
+
roles = user && (user != :any) ? user.roles : self.role_class
|
|
9
|
+
roles = roles.where(:resource_type.in => self.relation_types_for(relation))
|
|
10
|
+
roles = roles.where(:name => role_name.to_s) if role_name && (role_name != :any)
|
|
11
|
+
roles
|
|
12
|
+
end
|
|
13
|
+
|
|
6
14
|
def resources_find(roles_table, relation, role_name)
|
|
7
|
-
roles = roles_table.classify.constantize.where(:name => role_name, :resource_type => relation
|
|
15
|
+
roles = roles_table.classify.constantize.where(:name.in => Array(role_name), :resource_type.in => self.relation_types_for(relation))
|
|
8
16
|
resources = []
|
|
9
17
|
roles.each do |role|
|
|
10
|
-
|
|
11
|
-
|
|
18
|
+
if role.resource_id.nil?
|
|
19
|
+
resources += relation.all
|
|
20
|
+
else
|
|
21
|
+
resources << role.resource
|
|
22
|
+
end
|
|
12
23
|
end
|
|
13
|
-
resources
|
|
24
|
+
resources.compact.uniq
|
|
14
25
|
end
|
|
15
26
|
|
|
16
|
-
def in(resources,
|
|
27
|
+
def in(resources, user, role_names)
|
|
28
|
+
roles = user.roles.where(:name.in => Array(role_names))
|
|
17
29
|
return [] if resources.empty? || roles.empty?
|
|
18
30
|
resources.delete_if { |resource| (resource.applied_roles & roles).empty? }
|
|
19
31
|
resources
|
|
20
32
|
end
|
|
33
|
+
|
|
34
|
+
def applied_roles(relation, children)
|
|
35
|
+
if children
|
|
36
|
+
relation.role_class.where(:resource_type.in => self.relation_types_for(relation), :resource_id => nil)
|
|
37
|
+
else
|
|
38
|
+
relation.role_class.where(:resource_type => relation.to_s, :resource_id => nil)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
21
42
|
end
|
|
22
43
|
end
|
|
23
44
|
end
|
|
@@ -9,8 +9,8 @@ module Rolify
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
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,
|
|
12
|
+
self.role_class.find_or_create_by(:name => role_name,
|
|
13
|
+
:resource_type => resource_type,
|
|
14
14
|
:resource_id => resource_id)
|
|
15
15
|
end
|
|
16
16
|
|
|
@@ -19,21 +19,45 @@ module Rolify
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
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|
|
|
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|
|
|
27
41
|
relation.roles.delete(role)
|
|
28
|
-
role.
|
|
29
|
-
|
|
30
|
-
|
|
42
|
+
role.send(ActiveSupport::Inflector.demodulize(user_class).tableize.to_sym).delete(relation)
|
|
43
|
+
if Rolify.remove_role_if_empty && role.send(ActiveSupport::Inflector.demodulize(user_class).tableize.to_sym).empty?
|
|
44
|
+
role.destroy
|
|
45
|
+
end
|
|
46
|
+
end if roles
|
|
47
|
+
roles
|
|
31
48
|
end
|
|
32
49
|
|
|
33
50
|
def exists?(relation, column)
|
|
34
51
|
relation.where(column.to_sym.ne => nil)
|
|
35
52
|
end
|
|
36
53
|
|
|
54
|
+
def scope(relation, conditions)
|
|
55
|
+
roles = where(role_class, conditions).map { |role| role.id }
|
|
56
|
+
return [] if roles.size.zero?
|
|
57
|
+
query = relation.any_in(:role_ids => roles)
|
|
58
|
+
query
|
|
59
|
+
end
|
|
60
|
+
|
|
37
61
|
private
|
|
38
62
|
|
|
39
63
|
def build_conditions(relation, args)
|
|
@@ -64,4 +88,4 @@ module Rolify
|
|
|
64
88
|
end
|
|
65
89
|
end
|
|
66
90
|
end
|
|
67
|
-
end
|
|
91
|
+
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
|