cantango-api 0.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.
Files changed (55) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +36 -0
  4. data/Gemfile.lock +152 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.mdown +19 -0
  7. data/Rakefile +49 -0
  8. data/VERSION +1 -0
  9. data/cantango-api.gemspec +117 -0
  10. data/lib/cantango/api/ability/account.rb +46 -0
  11. data/lib/cantango/api/ability/user.rb +45 -0
  12. data/lib/cantango/api/ability.rb +5 -0
  13. data/lib/cantango/api/account.rb +20 -0
  14. data/lib/cantango/api/attributes.rb +15 -0
  15. data/lib/cantango/api/can/account.rb +32 -0
  16. data/lib/cantango/api/can/user.rb +26 -0
  17. data/lib/cantango/api/can.rb +5 -0
  18. data/lib/cantango/api/common.rb +14 -0
  19. data/lib/cantango/api/model/account.rb +39 -0
  20. data/lib/cantango/api/model/user.rb +39 -0
  21. data/lib/cantango/api/model.rb +5 -0
  22. data/lib/cantango/api/options.rb +19 -0
  23. data/lib/cantango/api/scope/account.rb +26 -0
  24. data/lib/cantango/api/scope/user.rb +26 -0
  25. data/lib/cantango/api/scope.rb +5 -0
  26. data/lib/cantango/api/session/account.rb +38 -0
  27. data/lib/cantango/api/session/user.rb +38 -0
  28. data/lib/cantango/api/session.rb +5 -0
  29. data/lib/cantango/api/user.rb +19 -0
  30. data/lib/cantango/api.rb +26 -0
  31. data/spec/cantango/api/ability/account_spec.rb +34 -0
  32. data/spec/cantango/api/ability/user_spec.rb +57 -0
  33. data/spec/cantango/api/account_spec.rb +0 -0
  34. data/spec/cantango/api/attributes_spec.rb +25 -0
  35. data/spec/cantango/api/can/account_spec.rb +85 -0
  36. data/spec/cantango/api/can/user_spec.rb +113 -0
  37. data/spec/cantango/api/options_spec.rb +0 -0
  38. data/spec/cantango/api/scope/account_spec.rb +0 -0
  39. data/spec/cantango/api/scope/user_spec.rb +73 -0
  40. data/spec/cantango/api/user_spec.rb +0 -0
  41. data/spec/cantango/api_spec.rb +11 -0
  42. data/spec/cantango_api_spec.rb +8 -0
  43. data/spec/fixtures/models/admin.rb +2 -0
  44. data/spec/fixtures/models/admin_account.rb +22 -0
  45. data/spec/fixtures/models/items.rb +8 -0
  46. data/spec/fixtures/models/permission.rb +12 -0
  47. data/spec/fixtures/models/project.rb +2 -0
  48. data/spec/fixtures/models/simple_roles.rb +49 -0
  49. data/spec/fixtures/models/user.rb +52 -0
  50. data/spec/fixtures/models/user_account.rb +21 -0
  51. data/spec/fixtures/models.rb +2 -0
  52. data/spec/helpers/current_user_accounts.rb +20 -0
  53. data/spec/helpers/current_users.rb +10 -0
  54. data/spec/spec_helper.rb +14 -0
  55. metadata +203 -0
@@ -0,0 +1,39 @@
1
+ module CanTango::Api
2
+ module Model
3
+ module User
4
+ attr_writer :active_user, :active_account, :ability_class
5
+
6
+ def self.included(base)
7
+ CanTango.config.users.register base
8
+ end
9
+
10
+ def active_user
11
+ @active_user || self
12
+ end
13
+
14
+ def active_account
15
+ return @active_account if @active_account
16
+ return send(:account) if respond_to? :account
17
+ raise "No account could be found for user: #{self}"
18
+ end
19
+
20
+ def can? *args
21
+ ability.can?(*args)
22
+ end
23
+
24
+ def cannot? *args
25
+ ability.cannot?(*args)
26
+ end
27
+
28
+ protected
29
+
30
+ def ability
31
+ ability_class.new(active_user)
32
+ end
33
+
34
+ def ability_class
35
+ CanTango::Ability::Executor::Modes
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,5 @@
1
+ module CanTango::Api
2
+ module Session
3
+ autoload_modules :User, :Account
4
+ end
5
+ end
@@ -0,0 +1,19 @@
1
+ module CanTango::Api
2
+ module Options
3
+ def ability_options
4
+ opts = {}
5
+ options_list.each do |option|
6
+ opts.merge!(option => send(option)) if respond_to? option, true
7
+ end
8
+ opts
9
+ end
10
+
11
+ def self.options_list
12
+ [:session, :request, :params, :controller, :domain, :cookies]
13
+ end
14
+
15
+ def options_list
16
+ CanTango::Api::Options.options_list
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ module CanTango::Api
2
+ module Scope
3
+ module Account
4
+ def account_scope scope, options = {}, &block
5
+ account = scoped_account(scope)
6
+ ab_scope = account_ability_scope(account, options)
7
+ yield ab_scope if block
8
+ ab_scope
9
+ end
10
+
11
+ def as_real_account scope, options = {}, &block
12
+ scope_account scope, options.merge(:masquerade => false), &block
13
+ end
14
+
15
+ protected
16
+
17
+ def account_ability_scope account, options = {}
18
+ CanTango::Ability::Scope.new user_account_ability(account, options)
19
+ end
20
+
21
+ def scoped_acount scope
22
+ send(:"current_#{scope}_account")
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module CanTango::Api
2
+ module Scope
3
+ module User
4
+ def scope_user scope, options = {}, &block
5
+ user = scoped_user(scope)
6
+ ab_scope = user_ability_scope(user, options)
7
+ yield ab_scope if block
8
+ ab_scope
9
+ end
10
+
11
+ def real_user scope, options = {}, &block
12
+ scope_user scope, options.merge(:masquerade => false), &block
13
+ end
14
+
15
+ protected
16
+
17
+ def user_ability_scope user, options = {}
18
+ CanTango::Ability::Scope.new user_ability(user, options)
19
+ end
20
+
21
+ def scoped_user scope
22
+ send(:"current_#{scope}")
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ module CanTango::Api
2
+ module Scope
3
+ autoload_modules :User, :Account
4
+ end
5
+ end
@@ -0,0 +1,38 @@
1
+ module CanTango::Api
2
+ module Session
3
+ module Account
4
+ def self.included(base)
5
+ ::CanTango.config.user_accounts.registered.each do |type|
6
+ base.class_eval %{
7
+ def session_#{type}_account
8
+ current_#{type}_account if respond_to? :current_#{type}_account
9
+ guest_account
10
+ end
11
+ }
12
+ end
13
+ end
14
+
15
+ # give me any logged in user or the guest user
16
+ def any_account *types
17
+ types = types.flatten.select_labels.map(&:to_sym)
18
+ c_account = ::CanTango.config.user_accounts.registered.each do |type|
19
+ meth = :"current_#{type}_account"
20
+ send(meth) if respond_to?(meth) && (types.empty? || types.include?(user))
21
+ end.compact.first
22
+ c_account || guest_account
23
+ end
24
+
25
+ def guest_account
26
+ CanTango.config.guest.account
27
+ end
28
+
29
+ def active_account
30
+ session[:active_account]
31
+ end
32
+
33
+ def active_account= account
34
+ session[:active_account] = account
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,38 @@
1
+ module CanTango::Api
2
+ module Session
3
+ module User
4
+ def self.included(base)
5
+ ::CanTango.config.users.registered.each do |user|
6
+ base.class_eval %{
7
+ def session_#{user}
8
+ current_#{user} if respond_to? :current_#{user}
9
+ guest_user
10
+ end
11
+ }
12
+ end
13
+ end
14
+
15
+ # give me any logged in user or the guest user
16
+ def any_user *types
17
+ types = types.flatten.select_labels.map(&:to_sym)
18
+ c_user = ::CanTango.config.users.registered.each do |user|
19
+ meth = :"current_#{user}"
20
+ send(meth) if respond_to?(meth) && (types.empty? || types.include?(user))
21
+ end.compact.first
22
+ c_user || guest_user
23
+ end
24
+
25
+ def guest_user
26
+ CanTango.config.guest.user
27
+ end
28
+
29
+ def active_user
30
+ session[:active_user]
31
+ end
32
+
33
+ def active_user= user
34
+ session[:active_user] = user
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,5 @@
1
+ module CanTango::Api
2
+ module Session
3
+ autoload_modules :User, :Account
4
+ end
5
+ end
@@ -0,0 +1,19 @@
1
+ module CanTango::Api
2
+ module User
3
+ module All
4
+ def self.included base
5
+ apis.each do |api|
6
+ base.send :include, clazz(api)
7
+ end
8
+ end
9
+
10
+ def self.apis
11
+ [:ability, :can, :scope, :session]
12
+ end
13
+
14
+ def clazz api
15
+ "CanTango::Api::#{api.to_s.camelize}::User".constantize
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ require 'sugar-high/array'
2
+ require 'sugar-high/blank'
3
+ require 'hashie'
4
+ require 'sweetloader'
5
+
6
+ AutoLoader.namespaces = {:CanTango => 'cantango'}
7
+
8
+ module CanTango
9
+ module Api
10
+ autoload_modules :Ability, :Account, :Attributes, :Can
11
+ autoload_modules :Common, :Options, :Model, :Scope, :Session, :User
12
+
13
+ def self.apis
14
+ [:ability, :can, :scope, :session]
15
+ end
16
+
17
+ apis.each do |api|
18
+ clazz = api.to_s.camelize
19
+ self.extend "CanTango::Api::#{clazz}::User".constantize
20
+ self.extend "CanTango::Api::#{clazz}::Account".constantize
21
+ end
22
+
23
+ # FIX - sweetloader, camelize there!
24
+ autoload_modules *apis.map{|api| api.to_s.camelize}
25
+ end
26
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ # require 'cantango/configuration/engines/store_engine_shared'
4
+
5
+ CanTango.configure do |config|
6
+ config.users.register :user, User
7
+ config.users.register :admin, Admin
8
+
9
+ config.accounts.register :user, UserAccount
10
+ config.accounts.register :admin, AdminAccount
11
+
12
+ # config.cache_engine.set :off
13
+ # config.permit_engine.set :on
14
+ end
15
+
16
+ class Context
17
+ include CanTango::Api::Account::Ability
18
+
19
+ include_and_extend ::CurrentUserAccounts
20
+ end
21
+
22
+ describe CanTango::Api::UserAccount::Ability do
23
+ subject { Context.new }
24
+
25
+ describe 'user_account_ability' do
26
+ specify { subject.user_account_ability(subject.current_user_account).should be_a CanTango::Ability }
27
+ specify { subject.user_account_ability(subject.current_admin_account).should be_a CanTango::Ability }
28
+ end
29
+
30
+ describe 'current_account_ability' do
31
+ specify { subject.current_account_ability(:user).should be_a CanTango::Ability }
32
+ specify { subject.current_account_ability(:admin).should be_a CanTango::Ability }
33
+ end
34
+ end
@@ -0,0 +1,57 @@
1
+ require 'rspec'
2
+ require 'cantango'
3
+ require 'simple_roles'
4
+ require 'fixtures/models'
5
+ require 'cantango/api/current_users'
6
+ # require 'cantango/configuration/engines/store_engine_shared'
7
+
8
+ class User
9
+ include_and_extend SimpleRoles
10
+ end
11
+
12
+ class Admin < User
13
+ end
14
+
15
+ CanTango.configure do |config|
16
+ config.users.register :user, User
17
+ config.users.register :admin, Admin
18
+
19
+ config.cache_engine.set :off
20
+ config.permit_engine.set :on
21
+ end
22
+
23
+ class Context
24
+ include CanTango::Api::User::Ability
25
+
26
+ include_and_extend ::CurrentUsers
27
+ end
28
+
29
+ describe CanTango::Api::User::Ability do
30
+ subject { Context.new }
31
+
32
+ describe 'user_ability user' do
33
+ specify { subject.user_ability(subject.current_user).should be_a CanTango::Ability }
34
+ end
35
+
36
+ describe 'user_ability admin' do
37
+ specify { subject.user_ability(subject.current_admin).should be_a CanTango::Ability }
38
+ end
39
+
40
+ describe 'current_user_ability :user' do
41
+ specify { subject.current_user_ability(:user).should be_a CanTango::Ability }
42
+
43
+ it 'should set the :user user correctly on ability' do
44
+ subject.current_user_ability(:user).user.should == subject.current_user
45
+ end
46
+ end
47
+
48
+ describe 'current_user_ability :admin' do
49
+ specify { subject.current_user_ability(:admin).should be_a CanTango::Ability }
50
+
51
+ it 'should set the :admin user correctly on ability' do
52
+ subject.current_user_ability(:admin).user.should == subject.current_admin
53
+ end
54
+ end
55
+ end
56
+
57
+
File without changes
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+ require 'helpers/current_users'
3
+
4
+ CanTango.config.users.register :user, User
5
+ CanTango.config.users.register :admin, Admin
6
+
7
+ class Context
8
+ include CanTango::Api::User::Ability
9
+
10
+ include CurrentUsers
11
+ extend ::CurrentUsers
12
+ end
13
+
14
+ describe CanTango::Api::User::Ability do
15
+ subject { Context.new }
16
+
17
+ describe 'user_ability user' do
18
+ specify { subject.user_ability(subject.current_user).should be_a CanTango::Ability }
19
+ end
20
+
21
+ describe 'user_ability admin' do
22
+ specify { subject.user_ability(subject.current_admin).should be_a CanTango::Ability }
23
+ end
24
+ end
25
+
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ require 'helpers/current_user_accounts'
4
+ # require 'cantango/configuration/engines/store_engine_shared'
5
+
6
+ class User
7
+ include_and_extend SimpleRoles
8
+ end
9
+
10
+ CanTango.configure do |config|
11
+ config.users.register :user, User
12
+ config.users.register :admin, Admin
13
+
14
+ config.accounts.register :user, UserAccount
15
+ config.accounts.register :admin, AdminAccount
16
+
17
+ #config.cache_engine.set :off
18
+ #config.permit_engine.set :on
19
+ end
20
+
21
+ class UserRolePermit < CanTango::RolePermit
22
+ def permit_rules
23
+ can :edit, Article
24
+ cannot :edit, User
25
+ end
26
+ end
27
+
28
+ class AdminRolePermit < CanTango::RolePermit
29
+ def permit_rules
30
+ can :edit, Article
31
+ cannot :edit, User
32
+ end
33
+ end
34
+
35
+ class User
36
+ include CanTango::Users::Masquerade
37
+ end
38
+
39
+ class Context
40
+ include CanTango::Api::UserAccount::Can
41
+
42
+ include_and_extend ::CurrentUserAccounts
43
+ end
44
+
45
+ describe "CanTango::Api::Can::Account" do
46
+ subject { Context.new }
47
+
48
+ describe 'user_account' do
49
+ # user can edit Article, not Admin
50
+ specify do
51
+ subject.user_account_can?(:edit, Article).should be_true
52
+ subject.user_account_can?(:edit, User).should be_false
53
+
54
+ subject.user_account_cannot?(:edit, User).should be_true
55
+ subject.user_account_cannot?(:edit, Article).should be_false
56
+ end
57
+ end
58
+
59
+ describe 'admin_account' do
60
+ specify do
61
+ subject.admin_account_can?(:edit, Article).should be_true
62
+ subject.admin_account_can?(:edit, User).should be_false
63
+
64
+ subject.admin_account_cannot?(:edit, User).should be_true
65
+ subject.admin_account_cannot?(:edit, Article).should be_false
66
+ end
67
+ end
68
+
69
+ describe 'admin masquerades as user' do
70
+ before do
71
+ Context.current_admin.masquerade_as Context.current_user
72
+ end
73
+
74
+ # admin masquerading as user can do same as user
75
+ specify do
76
+ subject.admin_account_can?(:edit, Article).should be_true
77
+ subject.admin_account_can?(:edit, User).should be_false
78
+
79
+ subject.admin_account_cannot?(:edit, User).should be_true
80
+ subject.admin_account_cannot?(:edit, Article).should be_false
81
+ end
82
+ end
83
+ end
84
+
85
+
@@ -0,0 +1,113 @@
1
+ require 'rspec'
2
+ require 'cantango'
3
+ require 'simple_roles'
4
+ require 'fixtures/models'
5
+ require 'cantango/api/current_users'
6
+ # require 'cantango/configuration/engines/store_engine_shared'
7
+
8
+ class User
9
+ include CanTango::Users::Masquerade
10
+ include_and_extend SimpleRoles
11
+
12
+ tango_user
13
+ end
14
+
15
+ class Admin < User
16
+ tango_user
17
+ end
18
+
19
+ CanTango.configure do |config|
20
+ config.cache_engine.set :off
21
+ config.permit_engine.set :on
22
+ end
23
+
24
+ # puts "#{CanTango.config.users.registered_classes} : #{CanTango.config.users.registered}"
25
+
26
+ class UserRolePermit < CanTango::RolePermit
27
+ def initialize ability
28
+ super
29
+ end
30
+
31
+ def permit_rules
32
+ can :edit, Article
33
+ cannot :edit, User
34
+ end
35
+ end
36
+
37
+ class AdminRolePermit < CanTango::RolePermit
38
+ def initialize ability
39
+ super
40
+ end
41
+
42
+ def permit_rules
43
+ can :edit, Article
44
+ cannot :edit, User
45
+ end
46
+ end
47
+
48
+ class Context
49
+ include CanTango::Api::User::Can
50
+
51
+ include_and_extend ::CurrentUsers
52
+ end
53
+
54
+ describe CanTango::Api::User::Can do
55
+ subject { Context.new }
56
+
57
+ describe 'user_ability' do
58
+ specify { subject.user_ability(subject.current_user).should be_a CanTango::Ability }
59
+ specify { subject.user_ability(subject.current_admin).should be_a CanTango::Ability }
60
+ end
61
+
62
+ describe 'current_user_ability :user' do
63
+ specify { subject.current_user_ability(:user).should be_a CanTango::Ability }
64
+
65
+ it 'should set the :user user correctly on ability' do
66
+ subject.current_user_ability(:user).user.should == subject.current_user
67
+ end
68
+ end
69
+
70
+ describe 'current_user_ability :admin' do
71
+ specify { subject.current_user_ability(:admin).should be_a CanTango::Ability }
72
+
73
+ it 'should set the :admin user correctly on ability' do
74
+ subject.current_user_ability(:admin).user.should == subject.current_admin
75
+ end
76
+ end
77
+
78
+ describe 'user' do
79
+ specify { subject.current_user.role.should == 'user' }
80
+
81
+ # user can edit Article, not Admin
82
+ specify { subject.user_can?(:edit, Article).should be_true }
83
+ specify { subject.user_can?(:edit, User).should be_false }
84
+
85
+ specify { subject.user_cannot?(:edit, User).should be_true }
86
+ specify { subject.user_cannot?(:edit, Article).should be_false }
87
+ end
88
+
89
+ describe 'admin' do
90
+ specify { subject.current_admin.role.should == 'admin' }
91
+
92
+ specify { subject.admin_can?(:edit, Article).should be_true }
93
+ specify { subject.admin_can?(:edit, User).should be_false }
94
+
95
+ specify { subject.admin_cannot?(:edit, User).should be_true }
96
+ specify { subject.admin_cannot?(:edit, Article).should be_false }
97
+ end
98
+
99
+ describe 'admin masquerades as user' do
100
+ before do
101
+ Context.new.current_admin.masquerade_as Context.new.current_user
102
+ end
103
+
104
+ # admin masquerading as user can do same as user
105
+ specify { subject.admin_can?(:edit, Article).should be_true }
106
+
107
+ specify { subject.admin_can?(:edit, User).should be_false }
108
+
109
+ specify { subject.admin_cannot?(:edit, User).should be_true }
110
+ specify { subject.admin_cannot?(:edit, Article).should be_false }
111
+ end
112
+ end
113
+
File without changes
File without changes
@@ -0,0 +1,73 @@
1
+ require 'rspec'
2
+ require 'cantango'
3
+ require 'simple_roles'
4
+ require 'fixtures/models'
5
+ require 'cantango/api/current_users'
6
+ # require 'cantango/configuration/engines/store_engine_shared'
7
+
8
+ CanTango.configure do |config|
9
+ config.users.register :user, User
10
+ config.users.register :admin, Admin
11
+
12
+ config.cache_engine.set :off
13
+ config.permit_engine.set :on
14
+ end
15
+
16
+ # puts "#{CanTango.config.users.registered_classes} : #{CanTango.config.users.registered}"
17
+
18
+ class User
19
+ include CanTango::Users::Masquerade
20
+ include_and_extend ::SimpleRoles
21
+ end
22
+
23
+ class Context
24
+ include CanTango::Api::User::Ability
25
+ include CanTango::Api::User::Scope
26
+
27
+ include_and_extend ::CurrentUsers
28
+ end
29
+
30
+ describe CanTango::Api::User::Scope do
31
+ subject { Context.new }
32
+
33
+ describe 'scope_user' do
34
+ before do
35
+ subject.current_admin.masquerade_as subject.current_user
36
+ end
37
+
38
+ specify do
39
+ subject.scope_user(:admin) do |user|
40
+ user.should be_a CanTango::Ability::Scope
41
+ user.ability.user.name.should == 'admin'
42
+ end
43
+ end
44
+
45
+ specify do
46
+ admin = subject.scope_user(:user)
47
+ admin.should be_a CanTango::Ability::Scope
48
+ admin.ability.user.name.should == 'stan'
49
+ end
50
+ end
51
+
52
+ describe 'real_user' do
53
+ before do
54
+ subject.current_user.masquerade_as subject.current_admin
55
+ end
56
+
57
+ specify do
58
+ subject.real_user(:user) do |user|
59
+ user.should be_a CanTango::Ability::Scope
60
+ user.ability.user.name.should == 'stan'
61
+ end
62
+ end
63
+
64
+ specify do
65
+ admin = subject.real_user(:admin)
66
+ admin.should be_a CanTango::Ability::Scope
67
+ admin.ability.user.name.should == 'admin'
68
+ end
69
+ end
70
+ end
71
+
72
+
73
+
File without changes
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ def config_folder
4
+ File.dirname(__FILE__)+ "/../fixtures/config/"
5
+ end
6
+
7
+ describe CanTango::Api do
8
+ subject { CanTango::Api }
9
+
10
+ specify { subject.methods.should include(:current_user_ability) }
11
+ end
@@ -0,0 +1,8 @@
1
+ require 'rspec'
2
+ require 'cantango/api'
3
+
4
+ describe 'cantango/api' do
5
+ specify do
6
+ lambda { CanTango::Api }.should_not raise_error
7
+ end
8
+ end
@@ -0,0 +1,2 @@
1
+ class Admin < User
2
+ end