cantango-core 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +3 -0
- data/Gemfile +54 -0
- data/Gemfile.lock +231 -0
- data/LICENSE.txt +20 -0
- data/README.mdown +90 -0
- data/Rakefile +48 -0
- data/VERSION +1 -0
- data/cantango-core.gemspec +177 -0
- data/lib/cantango/ability.rb +5 -0
- data/lib/cantango/ability/base.rb +61 -0
- data/lib/cantango/ability/cache.rb +7 -0
- data/lib/cantango/ability/cache/key.rb +38 -0
- data/lib/cantango/ability/cached.rb +28 -0
- data/lib/cantango/ability/executor.rb +7 -0
- data/lib/cantango/ability/executor/base.rb +53 -0
- data/lib/cantango/ability/executor/cache_mode.rb +33 -0
- data/lib/cantango/ability/executor/modes.rb +52 -0
- data/lib/cantango/ability/executor/no_cache_mode.rb +17 -0
- data/lib/cantango/ability/helper.rb +11 -0
- data/lib/cantango/ability/helper/account.rb +13 -0
- data/lib/cantango/ability/helper/engine.rb +32 -0
- data/lib/cantango/ability/helper/role.rb +21 -0
- data/lib/cantango/ability/helper/role_group.rb +21 -0
- data/lib/cantango/ability/helper/user.rb +18 -0
- data/lib/cantango/cancan/rule.rb +6 -0
- data/lib/cantango/core.rb +84 -0
- data/lib/cantango/engine.rb +39 -0
- data/lib/cantango/filter.rb +5 -0
- data/lib/cantango/filter/base.rb +31 -0
- data/lib/cantango/helpers.rb +5 -0
- data/lib/cantango/helpers/debug.rb +10 -0
- data/lib/cantango/loader.rb +5 -0
- data/lib/cantango/loader/yaml.rb +33 -0
- data/lib/cantango/macros.rb +11 -0
- data/lib/cantango/macros/account.rb +14 -0
- data/lib/cantango/macros/user.rb +16 -0
- data/lib/cantango/model.rb +5 -0
- data/lib/cantango/model/guest.rb +25 -0
- data/lib/cantango/rails.rb +7 -0
- data/lib/cantango/rails/engine.rb +63 -0
- data/lib/cantango/rails/helpers/base_helper.rb +29 -0
- data/lib/cantango/rails/helpers/controller_helper.rb +17 -0
- data/lib/cantango/rails/helpers/rest_helper.rb +76 -0
- data/lib/cantango/rails/helpers/view_helper.rb +17 -0
- data/lib/cantango/rails/railtie.rb +7 -0
- data/lib/cantango/rspec.rb +1 -0
- data/lib/cantango/rspec/config.rb +3 -0
- data/lib/cantango/rspec/matchers.rb +1 -0
- data/lib/cantango/rspec/matchers/be_allowed_to.rb +28 -0
- data/lib/cantango/rules.rb +8 -0
- data/lib/cantango/rules/adaptor.rb +37 -0
- data/lib/cantango/rules/adaptor/active_record.rb +10 -0
- data/lib/cantango/rules/adaptor/data_mapper.rb +11 -0
- data/lib/cantango/rules/adaptor/generic.rb +16 -0
- data/lib/cantango/rules/adaptor/mongo.rb +19 -0
- data/lib/cantango/rules/adaptor/mongo_mapper.rb +10 -0
- data/lib/cantango/rules/adaptor/mongoid.rb +9 -0
- data/lib/cantango/rules/adaptor/relational.rb +13 -0
- data/lib/cantango/rules/dsl.rb +24 -0
- data/lib/cantango/rules/relation.rb +67 -0
- data/lib/cantango/rules/rule_class.rb +11 -0
- data/lib/cantango/rules/scope.rb +24 -0
- data/lib/cantango/scope.rb +5 -0
- data/lib/cantango/scope/ability.rb +20 -0
- data/lib/generators/cantango/install/install_generator.rb +37 -0
- data/lib/generators/cantango/install/templates/cantango.rb +4 -0
- data/lib/generators/cantango/install/templates/categories.yml +0 -0
- data/lib/generators/cantango/install/templates/permissions.yml +6 -0
- data/spec/cantango/ability/base_spec.rb +73 -0
- data/spec/cantango/ability/cached_spec.rb +0 -0
- data/spec/cantango/ability/executor/base2.rb +75 -0
- data/spec/cantango/ability/executor/base_spec.rb +67 -0
- data/spec/cantango/ability/executor/cache_mode_spec.rb +77 -0
- data/spec/cantango/ability/executor/modes_spec.rb +68 -0
- data/spec/cantango/ability/executor/no_cache_mode_spec.rb +0 -0
- data/spec/cantango/cancan/rule_spec.rb +0 -0
- data/spec/cantango/core_spec.rb +9 -0
- data/spec/cantango/engine_spec.rb +0 -0
- data/spec/cantango/filter/base_spec.rb +0 -0
- data/spec/cantango/helpers/debug_spec.rb +0 -0
- data/spec/cantango/loader/yaml_spec.rb +0 -0
- data/spec/cantango/macros/account_spec.rb +0 -0
- data/spec/cantango/macros/user_spec.rb +0 -0
- data/spec/cantango/rspec/be_allowed_to_spec.rb +0 -0
- data/spec/cantango/rules/adaptor/active_record_spec.rb +0 -0
- data/spec/cantango/rules/adaptor/data_mapper_spec.rb +0 -0
- data/spec/cantango/rules/adaptor/mongo_mapper_spec.rb +0 -0
- data/spec/cantango/rules/adaptor/mongoid_spec.rb +0 -0
- data/spec/cantango/rules/adaptor_spec.rb +0 -0
- data/spec/cantango/rules/dsl_spec.rb +0 -0
- data/spec/cantango/rules/relation_spec.rb +0 -0
- data/spec/cantango/rules/rule_class_spec.rb +0 -0
- data/spec/cantango/rules/scope_spec.rb +0 -0
- data/spec/cantango/rules_spec.rb +55 -0
- data/spec/cantango/scope/ability_spec.rb +0 -0
- data/spec/cantango_spec.rb +0 -0
- data/spec/generators/cantango/install_generator_spec.rb +42 -0
- data/spec/spec_helper.rb +9 -0
- metadata +310 -0
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
|
3
|
+
module CanTango
|
4
|
+
module Rules
|
5
|
+
class Relation
|
6
|
+
attr_reader :attribute, :permit, :scope, :models
|
7
|
+
|
8
|
+
include CanTango::Rules::Adaptor
|
9
|
+
include CanTango::Rules::RuleClass
|
10
|
+
|
11
|
+
def initialize attribute, permit, scope, *models, &block
|
12
|
+
@attribute = attribute
|
13
|
+
@scope = scope
|
14
|
+
@permit = permit
|
15
|
+
@models = models
|
16
|
+
|
17
|
+
check_models
|
18
|
+
use_adaptor! self, user_scope
|
19
|
+
end
|
20
|
+
|
21
|
+
def can(action)
|
22
|
+
models.each do |model|
|
23
|
+
rules << rule_class.new(true, action, model, nil, condition_block(model))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def cannot(action)
|
28
|
+
models.each do |model|
|
29
|
+
rules << rule_class.new(false, action, model, nil, condition_block(model))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def condition_block model
|
36
|
+
return attribute_condition(attribute, user_scope) if model.new.respond_to?(attribute)
|
37
|
+
return include_condition(plural_attribute, user_scope) if model.new.respond_to?(plural_attribute)
|
38
|
+
end
|
39
|
+
|
40
|
+
def user_scope
|
41
|
+
@user_scope ||= (scope == :account) ? permit.user_account : permit.user
|
42
|
+
end
|
43
|
+
|
44
|
+
def scope_key
|
45
|
+
@scope_key ||= (scope == :account) ? :user_account : :user
|
46
|
+
end
|
47
|
+
|
48
|
+
def ability
|
49
|
+
permit.ability
|
50
|
+
end
|
51
|
+
|
52
|
+
def rules
|
53
|
+
ability.send :rules
|
54
|
+
end
|
55
|
+
|
56
|
+
def plural_attribute
|
57
|
+
:"#{attribute.to_s.pluralize}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def check_models
|
61
|
+
models.each do |model|
|
62
|
+
raise "#{model} has no :#{attribute} or :#{plural_attribute} defined" if !model.new.respond_to?(attribute) && !model.new.respond_to?(plural_attribute)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module CanTango
|
2
|
+
module Rules
|
3
|
+
class Scope
|
4
|
+
attr_reader :name, :permit
|
5
|
+
|
6
|
+
def initialize name, permit, &block
|
7
|
+
@name = name.to_sym
|
8
|
+
@permit = permit
|
9
|
+
end
|
10
|
+
|
11
|
+
::CanTango.config.user.relations.each do |relationship|
|
12
|
+
base.class_eval %{
|
13
|
+
def #{relationship}_of *models, &block
|
14
|
+
options = models.extract_options!
|
15
|
+
scope = options[:scope] || name
|
16
|
+
relation = UserRelation.new :#{relationship}, permit, scope, models, &block
|
17
|
+
yield relation if block
|
18
|
+
relation
|
19
|
+
end
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module CanTango
|
2
|
+
module Scope
|
3
|
+
class Ability
|
4
|
+
attr_accessor :ability
|
5
|
+
|
6
|
+
def initialize ability
|
7
|
+
@ability = ability
|
8
|
+
end
|
9
|
+
|
10
|
+
def can? *args
|
11
|
+
ability.can? *args
|
12
|
+
end
|
13
|
+
|
14
|
+
def cannot? *args
|
15
|
+
ability.cannot? *args
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Cantango
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
desc "Add role strategy to a User model"
|
5
|
+
|
6
|
+
source_root File.expand_path("../templates", __FILE__)
|
7
|
+
|
8
|
+
class_option :categories, :type => :boolean, :default => true, :desc => "Create categories"
|
9
|
+
class_option :permissions, :type => :boolean, :default => true, :desc => "Create yaml permissions store"
|
10
|
+
|
11
|
+
def copy_initializer
|
12
|
+
template "cantango.rb", "config/initializers/cantango.rb"
|
13
|
+
end
|
14
|
+
|
15
|
+
def copy_categories
|
16
|
+
return unless categories?
|
17
|
+
template "categories.yml", "config/categories.yml"
|
18
|
+
end
|
19
|
+
|
20
|
+
def copy_permissions
|
21
|
+
return unless permissions?
|
22
|
+
template "permissions.yml", "config/permissions.yml"
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def permissions?
|
28
|
+
options[:permissions]
|
29
|
+
end
|
30
|
+
|
31
|
+
def categories?
|
32
|
+
options[:categories]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
File without changes
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'cantango'
|
3
|
+
require 'fixtures/models'
|
4
|
+
require 'cantango/rspec'
|
5
|
+
|
6
|
+
def config_folder
|
7
|
+
File.dirname(__FILE__)+ "/../fixtures/config/"
|
8
|
+
end
|
9
|
+
|
10
|
+
CanTango.configure do |config|
|
11
|
+
config.clear!
|
12
|
+
# config.permissions.set :on
|
13
|
+
config.engines.all :on
|
14
|
+
|
15
|
+
config.permission_engine.config_path = config_folder
|
16
|
+
config.categories.register :blog_items => [Article, Post]
|
17
|
+
end
|
18
|
+
|
19
|
+
class PublishersRoleGroupPermit < CanTango::RoleGroupPermit
|
20
|
+
def initialize ability
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def static_rules
|
27
|
+
can :write, category(:blog_items)
|
28
|
+
cannot :write, Post
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class EditorRolePermit < CanTango::RolePermit
|
33
|
+
def initialize ability
|
34
|
+
super
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
|
39
|
+
def static_rules
|
40
|
+
can :read, Comment
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
describe CanTango::Ability do
|
46
|
+
let (:user) do
|
47
|
+
User.new 'krisy', 'krisy@gmail.com'
|
48
|
+
end
|
49
|
+
|
50
|
+
let (:user_account) do
|
51
|
+
ua = UserAccount.new user, :roles => [:editor], :role_groups => [:publishers]
|
52
|
+
user.account = ua
|
53
|
+
end
|
54
|
+
|
55
|
+
before do
|
56
|
+
CanTango.config.clear!
|
57
|
+
@ability = CanTango::Ability.new user_account
|
58
|
+
end
|
59
|
+
|
60
|
+
specify { CanTango.config.roles.excluded.should be_empty }
|
61
|
+
specify { CanTango.config.role_groups.excluded.should be_empty }
|
62
|
+
|
63
|
+
subject { @ability }
|
64
|
+
specify { @ability.should be_allowed_to(:read, Comment) }
|
65
|
+
specify { @ability.should be_allowed_to(:write, Article) }
|
66
|
+
specify { @ability.should_not be_allowed_to(:write, Post) }
|
67
|
+
|
68
|
+
its(:user_account) { should be_a(UserAccount) }
|
69
|
+
its(:user) { should be_a(User) }
|
70
|
+
|
71
|
+
its(:roles) { should_not be_empty }
|
72
|
+
its(:role_groups) { should_not be_empty }
|
73
|
+
end
|
File without changes
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'cantango'
|
3
|
+
# require 'simple_roles'
|
4
|
+
require 'fixtures/models'
|
5
|
+
require 'cantango/rspec'
|
6
|
+
|
7
|
+
def config_folder
|
8
|
+
File.dirname(__FILE__)+ "/../fixtures/config/"
|
9
|
+
end
|
10
|
+
|
11
|
+
CanTango.configure do |config|
|
12
|
+
config.clear!
|
13
|
+
end
|
14
|
+
# CanTango.debug!
|
15
|
+
|
16
|
+
class User
|
17
|
+
tango_user
|
18
|
+
include_and_extend SimpleRoles
|
19
|
+
end
|
20
|
+
|
21
|
+
class AdminRolePermit < CanTango::RolePermit
|
22
|
+
def initialize ability
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def static_rules
|
29
|
+
can :read, Article
|
30
|
+
end
|
31
|
+
|
32
|
+
module Cached
|
33
|
+
def permit_rules
|
34
|
+
can :edit, Article
|
35
|
+
can :delete, Article
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module CanTango
|
41
|
+
class Ability
|
42
|
+
def permit_rules
|
43
|
+
can :read, Post
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe CanTango::AbilityExecutor do
|
49
|
+
context 'non-cached only' do
|
50
|
+
before do
|
51
|
+
CanTango.configure.ability.mode = :no_cache
|
52
|
+
|
53
|
+
@user = User.new 'admin', 'admin@mail.ru', :role => 'admin'
|
54
|
+
@abil = CanTango::AbilityExecutor.new @user
|
55
|
+
end
|
56
|
+
|
57
|
+
subject { CanTango::AbilityExecutor.new @user }
|
58
|
+
|
59
|
+
describe 'config no_cache' do
|
60
|
+
specify { CanTango.configure.ability.modes.should == [:no_cache] }
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'engines_on?' do
|
64
|
+
specify { subject.engines_on?.should be_true }
|
65
|
+
end
|
66
|
+
|
67
|
+
its(:cached_rules) { should be_empty }
|
68
|
+
its(:non_cached_rules) { should_not be_empty }
|
69
|
+
|
70
|
+
describe 'rules contain only non-cached rules' do
|
71
|
+
specify { subject.rules.size.should == @abil.non_cached_rules.size }
|
72
|
+
specify { subject.rules.size.should == 2 }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'cantango'
|
3
|
+
require 'fixtures/models'
|
4
|
+
require 'cantango/rspec'
|
5
|
+
|
6
|
+
def config_folder
|
7
|
+
File.dirname(__FILE__)+ "/../fixtures/config/"
|
8
|
+
end
|
9
|
+
|
10
|
+
CanTango.configure do |config|
|
11
|
+
config.clear!
|
12
|
+
config.ability.mode = :no_cache
|
13
|
+
end
|
14
|
+
|
15
|
+
class MyExecutor
|
16
|
+
include CanTango::Ability::Executor
|
17
|
+
|
18
|
+
attr_reader :ability
|
19
|
+
|
20
|
+
def initialize ability
|
21
|
+
@ability = ability
|
22
|
+
end
|
23
|
+
|
24
|
+
def valid?
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
def cache_key
|
29
|
+
:my_exec
|
30
|
+
end
|
31
|
+
|
32
|
+
def permit_rules
|
33
|
+
ability.permit_rules
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
module CanTango
|
38
|
+
class Ability
|
39
|
+
def permit_rules
|
40
|
+
can :edit, Project
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe CanTango::Ability::Executor do
|
46
|
+
context 'no-cache' do
|
47
|
+
let (:ability) do
|
48
|
+
CanTango::Ability.new @user
|
49
|
+
end
|
50
|
+
|
51
|
+
before do
|
52
|
+
@user = User.new 'kris'
|
53
|
+
end
|
54
|
+
|
55
|
+
subject { MyExecutor.new ability }
|
56
|
+
|
57
|
+
describe '#execute!' do
|
58
|
+
before do
|
59
|
+
subject.execute!
|
60
|
+
end
|
61
|
+
|
62
|
+
specify { subject.ability.send(:rules).should_not be_empty }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'cantango'
|
3
|
+
# require 'simple_roles'
|
4
|
+
require 'fixtures/models'
|
5
|
+
require 'cantango/rspec'
|
6
|
+
|
7
|
+
def config_folder
|
8
|
+
File.dirname(__FILE__)+ "/../fixtures/config/"
|
9
|
+
end
|
10
|
+
|
11
|
+
CanTango.configure do |config|
|
12
|
+
config.clear!
|
13
|
+
config.ability.mode = :cache
|
14
|
+
end
|
15
|
+
# CanTango.debug!
|
16
|
+
|
17
|
+
class User
|
18
|
+
tango_user
|
19
|
+
include_and_extend SimpleRoles
|
20
|
+
end
|
21
|
+
|
22
|
+
class AdminRolePermit < CanTango::Permit::Role
|
23
|
+
def initialize ability
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def static_rules
|
30
|
+
can :read, Article
|
31
|
+
end
|
32
|
+
|
33
|
+
module Cached
|
34
|
+
def permit_rules
|
35
|
+
can :edit, Article
|
36
|
+
can :delete, Article
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
module CanTango
|
42
|
+
class CachedAbility
|
43
|
+
def permit_rules
|
44
|
+
can :read, Post
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe CanTango::Ability::Executor::CacheMode do
|
50
|
+
context 'cached only' do
|
51
|
+
before do
|
52
|
+
CanTango.configure.ability.mode = :cache
|
53
|
+
|
54
|
+
@user = User.new 'admin', 'admin@mail.ru', :role => 'admin'
|
55
|
+
@abil = CanTango::AbilityExecutor.new @user
|
56
|
+
end
|
57
|
+
|
58
|
+
subject { CanTango::AbilityExecutor.new @user }
|
59
|
+
|
60
|
+
describe 'config cache' do
|
61
|
+
specify { CanTango.configure.ability.modes.should == [:cache] }
|
62
|
+
end
|
63
|
+
|
64
|
+
describe 'engines_on?' do
|
65
|
+
specify { subject.engines_on?.should be_true }
|
66
|
+
end
|
67
|
+
|
68
|
+
its(:cached_rules) { should_not be_empty }
|
69
|
+
its(:non_cached_rules) { should be_empty }
|
70
|
+
|
71
|
+
describe 'rules contain only non-cached rules' do
|
72
|
+
specify { subject.rules.size.should == @abil.cached_rules.size }
|
73
|
+
specify { subject.rules.size.should == 4 }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|