cantango-core 0.1.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.
Files changed (100) hide show
  1. data/.document +5 -0
  2. data/.rspec +3 -0
  3. data/Gemfile +54 -0
  4. data/Gemfile.lock +231 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.mdown +90 -0
  7. data/Rakefile +48 -0
  8. data/VERSION +1 -0
  9. data/cantango-core.gemspec +177 -0
  10. data/lib/cantango/ability.rb +5 -0
  11. data/lib/cantango/ability/base.rb +61 -0
  12. data/lib/cantango/ability/cache.rb +7 -0
  13. data/lib/cantango/ability/cache/key.rb +38 -0
  14. data/lib/cantango/ability/cached.rb +28 -0
  15. data/lib/cantango/ability/executor.rb +7 -0
  16. data/lib/cantango/ability/executor/base.rb +53 -0
  17. data/lib/cantango/ability/executor/cache_mode.rb +33 -0
  18. data/lib/cantango/ability/executor/modes.rb +52 -0
  19. data/lib/cantango/ability/executor/no_cache_mode.rb +17 -0
  20. data/lib/cantango/ability/helper.rb +11 -0
  21. data/lib/cantango/ability/helper/account.rb +13 -0
  22. data/lib/cantango/ability/helper/engine.rb +32 -0
  23. data/lib/cantango/ability/helper/role.rb +21 -0
  24. data/lib/cantango/ability/helper/role_group.rb +21 -0
  25. data/lib/cantango/ability/helper/user.rb +18 -0
  26. data/lib/cantango/cancan/rule.rb +6 -0
  27. data/lib/cantango/core.rb +84 -0
  28. data/lib/cantango/engine.rb +39 -0
  29. data/lib/cantango/filter.rb +5 -0
  30. data/lib/cantango/filter/base.rb +31 -0
  31. data/lib/cantango/helpers.rb +5 -0
  32. data/lib/cantango/helpers/debug.rb +10 -0
  33. data/lib/cantango/loader.rb +5 -0
  34. data/lib/cantango/loader/yaml.rb +33 -0
  35. data/lib/cantango/macros.rb +11 -0
  36. data/lib/cantango/macros/account.rb +14 -0
  37. data/lib/cantango/macros/user.rb +16 -0
  38. data/lib/cantango/model.rb +5 -0
  39. data/lib/cantango/model/guest.rb +25 -0
  40. data/lib/cantango/rails.rb +7 -0
  41. data/lib/cantango/rails/engine.rb +63 -0
  42. data/lib/cantango/rails/helpers/base_helper.rb +29 -0
  43. data/lib/cantango/rails/helpers/controller_helper.rb +17 -0
  44. data/lib/cantango/rails/helpers/rest_helper.rb +76 -0
  45. data/lib/cantango/rails/helpers/view_helper.rb +17 -0
  46. data/lib/cantango/rails/railtie.rb +7 -0
  47. data/lib/cantango/rspec.rb +1 -0
  48. data/lib/cantango/rspec/config.rb +3 -0
  49. data/lib/cantango/rspec/matchers.rb +1 -0
  50. data/lib/cantango/rspec/matchers/be_allowed_to.rb +28 -0
  51. data/lib/cantango/rules.rb +8 -0
  52. data/lib/cantango/rules/adaptor.rb +37 -0
  53. data/lib/cantango/rules/adaptor/active_record.rb +10 -0
  54. data/lib/cantango/rules/adaptor/data_mapper.rb +11 -0
  55. data/lib/cantango/rules/adaptor/generic.rb +16 -0
  56. data/lib/cantango/rules/adaptor/mongo.rb +19 -0
  57. data/lib/cantango/rules/adaptor/mongo_mapper.rb +10 -0
  58. data/lib/cantango/rules/adaptor/mongoid.rb +9 -0
  59. data/lib/cantango/rules/adaptor/relational.rb +13 -0
  60. data/lib/cantango/rules/dsl.rb +24 -0
  61. data/lib/cantango/rules/relation.rb +67 -0
  62. data/lib/cantango/rules/rule_class.rb +11 -0
  63. data/lib/cantango/rules/scope.rb +24 -0
  64. data/lib/cantango/scope.rb +5 -0
  65. data/lib/cantango/scope/ability.rb +20 -0
  66. data/lib/generators/cantango/install/install_generator.rb +37 -0
  67. data/lib/generators/cantango/install/templates/cantango.rb +4 -0
  68. data/lib/generators/cantango/install/templates/categories.yml +0 -0
  69. data/lib/generators/cantango/install/templates/permissions.yml +6 -0
  70. data/spec/cantango/ability/base_spec.rb +73 -0
  71. data/spec/cantango/ability/cached_spec.rb +0 -0
  72. data/spec/cantango/ability/executor/base2.rb +75 -0
  73. data/spec/cantango/ability/executor/base_spec.rb +67 -0
  74. data/spec/cantango/ability/executor/cache_mode_spec.rb +77 -0
  75. data/spec/cantango/ability/executor/modes_spec.rb +68 -0
  76. data/spec/cantango/ability/executor/no_cache_mode_spec.rb +0 -0
  77. data/spec/cantango/cancan/rule_spec.rb +0 -0
  78. data/spec/cantango/core_spec.rb +9 -0
  79. data/spec/cantango/engine_spec.rb +0 -0
  80. data/spec/cantango/filter/base_spec.rb +0 -0
  81. data/spec/cantango/helpers/debug_spec.rb +0 -0
  82. data/spec/cantango/loader/yaml_spec.rb +0 -0
  83. data/spec/cantango/macros/account_spec.rb +0 -0
  84. data/spec/cantango/macros/user_spec.rb +0 -0
  85. data/spec/cantango/rspec/be_allowed_to_spec.rb +0 -0
  86. data/spec/cantango/rules/adaptor/active_record_spec.rb +0 -0
  87. data/spec/cantango/rules/adaptor/data_mapper_spec.rb +0 -0
  88. data/spec/cantango/rules/adaptor/mongo_mapper_spec.rb +0 -0
  89. data/spec/cantango/rules/adaptor/mongoid_spec.rb +0 -0
  90. data/spec/cantango/rules/adaptor_spec.rb +0 -0
  91. data/spec/cantango/rules/dsl_spec.rb +0 -0
  92. data/spec/cantango/rules/relation_spec.rb +0 -0
  93. data/spec/cantango/rules/rule_class_spec.rb +0 -0
  94. data/spec/cantango/rules/scope_spec.rb +0 -0
  95. data/spec/cantango/rules_spec.rb +55 -0
  96. data/spec/cantango/scope/ability_spec.rb +0 -0
  97. data/spec/cantango_spec.rb +0 -0
  98. data/spec/generators/cantango/install_generator_spec.rb +42 -0
  99. data/spec/spec_helper.rb +9 -0
  100. 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,11 @@
1
+ module CanTango
2
+ module Rules
3
+ module RuleClass
4
+ # CanCan 1.5 compatibility
5
+ def rule_class
6
+ return CanCan::Rule if defined? CanCan::Rule
7
+ CanCan::CanDefinition
8
+ end
9
+ end
10
+ end
11
+ 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,5 @@
1
+ module CanTango
2
+ module Scope
3
+ autoload_modules :Ability
4
+ end
5
+ 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
+
@@ -0,0 +1,4 @@
1
+ CanTango.config do |config|
2
+ config.engines.all :on
3
+ # more configuration here...
4
+ end
@@ -0,0 +1,6 @@
1
+ account_types:
2
+ user_types:
3
+ roles:
4
+ role_groups:
5
+ licenses:
6
+ users:
@@ -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
+