cantango-api 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/Gemfile +8 -5
  2. data/Gemfile.lock +20 -24
  3. data/README.mdown +73 -0
  4. data/VERSION +1 -1
  5. data/cantango-api.gemspec +42 -23
  6. data/lib/cantango/api/ability/account.rb +6 -6
  7. data/lib/cantango/api/ability/user.rb +1 -0
  8. data/lib/cantango/api/account.rb +9 -11
  9. data/lib/cantango/api/attributes.rb +1 -1
  10. data/lib/cantango/api/can/account.rb +2 -2
  11. data/lib/cantango/api/can/dsl/relation.rb +67 -0
  12. data/lib/cantango/api/can/dsl/scope.rb +24 -0
  13. data/lib/cantango/api/can/dsl.rb +26 -0
  14. data/lib/cantango/api/can/user.rb +1 -1
  15. data/lib/cantango/api/can.rb +1 -1
  16. data/lib/cantango/api/common.rb +16 -3
  17. data/lib/cantango/api/model/account.rb +9 -16
  18. data/lib/cantango/api/model/user.rb +10 -17
  19. data/lib/cantango/api/model.rb +3 -1
  20. data/lib/cantango/api/scope/account.rb +8 -5
  21. data/lib/cantango/api/scope/user.rb +1 -0
  22. data/lib/cantango/api/session/account.rb +1 -1
  23. data/lib/cantango/api/user.rb +9 -11
  24. data/lib/cantango/api.rb +7 -4
  25. data/lib/cantango/api_ext/macros/account.rb +8 -0
  26. data/lib/cantango/api_ext/macros/clazz.rb +17 -0
  27. data/lib/cantango/api_ext/macros/user.rb +8 -0
  28. data/lib/cantango/api_ext/macros.rb +12 -0
  29. data/lib/cantango/api_ext.rb +5 -0
  30. data/spec/cantango/api/ability/account_spec.rb +14 -15
  31. data/spec/cantango/api/ability/user_spec.rb +18 -22
  32. data/spec/cantango/api/account_spec.rb +40 -0
  33. data/spec/cantango/api/attributes_spec.rb +13 -14
  34. data/spec/cantango/api/can/account_spec.rb +40 -47
  35. data/spec/cantango/api/can/user_spec.rb +56 -83
  36. data/spec/cantango/api/common_spec.rb +37 -0
  37. data/spec/cantango/api/model/account_spec.rb +38 -0
  38. data/spec/cantango/api/model/user_spec.rb +35 -0
  39. data/spec/cantango/api/options_spec.rb +23 -0
  40. data/spec/cantango/api/scope/account_spec.rb +43 -0
  41. data/spec/cantango/api/scope/user_spec.rb +19 -51
  42. data/spec/cantango/api/session/account_spec.rb +0 -0
  43. data/spec/cantango/api/session/user_spec.rb +0 -0
  44. data/spec/cantango/api/user_spec.rb +40 -0
  45. data/spec/cantango/api_ext/macros/account_spec.rb +16 -0
  46. data/spec/cantango/api_ext/macros/clazz_spec.rb +26 -0
  47. data/spec/cantango/api_ext/macros/user_spec.rb +17 -0
  48. data/spec/fixtures/models/user_account.rb +1 -15
  49. data/spec/helpers/current_user_accounts.rb +1 -1
  50. data/spec/spec_helper.rb +0 -1
  51. metadata +55 -28
@@ -3,8 +3,8 @@ module CanTango::Api
3
3
  module User
4
4
  attr_writer :active_user, :active_account, :ability_class
5
5
 
6
- def self.included(base)
7
- CanTango.config.users.register base
6
+ def self.included(clazz)
7
+ CanTango.config.users.register_user clazz
8
8
  end
9
9
 
10
10
  def active_user
@@ -17,23 +17,16 @@ module CanTango::Api
17
17
  raise "No account could be found for user: #{self}"
18
18
  end
19
19
 
20
- def can? *args
21
- ability.can?(*args)
22
- end
23
-
24
- def cannot? *args
25
- ability.cannot?(*args)
26
- end
20
+ # from sugar-high or Active Support
21
+ delegate :can?, :cannot?, :to => :ability
27
22
 
28
23
  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
24
+
25
+ include CanTango::Api::Common
26
+
27
+ def ability opts = {}
28
+ create_ability active_user, opts = {}
29
+ end
37
30
  end
38
31
  end
39
32
  end
@@ -1,5 +1,7 @@
1
+ require 'sugar-high/delegate'
2
+
1
3
  module CanTango::Api
2
- module Session
4
+ module Model
3
5
  autoload_modules :User, :Account
4
6
  end
5
7
  end
@@ -1,24 +1,27 @@
1
1
  module CanTango::Api
2
2
  module Scope
3
3
  module Account
4
- def account_scope scope, options = {}, &block
4
+ include CanTango::Api::Ability::Account
5
+
6
+ def scope_account scope, options = {}, &block
5
7
  account = scoped_account(scope)
6
- ab_scope = account_ability_scope(account, options)
8
+ ab_scope = account_ability_scope(account, options.merge(:masquerade => true))
7
9
  yield ab_scope if block
8
10
  ab_scope
9
11
  end
12
+ alias_method :account_scope, :scope_account
10
13
 
11
- def as_real_account scope, options = {}, &block
14
+ def real_account scope, options = {}, &block
12
15
  scope_account scope, options.merge(:masquerade => false), &block
13
16
  end
14
17
 
15
18
  protected
16
19
 
17
20
  def account_ability_scope account, options = {}
18
- CanTango::Ability::Scope.new user_account_ability(account, options)
21
+ CanTango::Scope::Ability.new account_ability(account, options)
19
22
  end
20
23
 
21
- def scoped_acount scope
24
+ def scoped_account scope
22
25
  send(:"current_#{scope}_account")
23
26
  end
24
27
  end
@@ -7,6 +7,7 @@ module CanTango::Api
7
7
  yield ab_scope if block
8
8
  ab_scope
9
9
  end
10
+ alias_method :user_scope, :scope_user
10
11
 
11
12
  def real_user scope, options = {}, &block
12
13
  scope_user scope, options.merge(:masquerade => false), &block
@@ -2,7 +2,7 @@ module CanTango::Api
2
2
  module Session
3
3
  module Account
4
4
  def self.included(base)
5
- ::CanTango.config.user_accounts.registered.each do |type|
5
+ ::CanTango.config.accounts.registered.each do |type|
6
6
  base.class_eval %{
7
7
  def session_#{type}_account
8
8
  current_#{type}_account if respond_to? :current_#{type}_account
@@ -1,19 +1,17 @@
1
1
  module CanTango::Api
2
2
  module User
3
- module All
4
- def self.included base
5
- apis.each do |api|
6
- base.send :include, clazz(api)
7
- end
3
+ def self.included base
4
+ apis.each do |api|
5
+ base.send :include, clazz(api)
8
6
  end
7
+ end
9
8
 
10
- def self.apis
11
- [:ability, :can, :scope, :session]
12
- end
9
+ def self.apis
10
+ [:ability, :can, :scope, :session]
11
+ end
13
12
 
14
- def clazz api
15
- "CanTango::Api::#{api.to_s.camelize}::User".constantize
16
- end
13
+ def self.clazz api
14
+ "CanTango::Api::#{api.to_s.camelize}::User".constantize
17
15
  end
18
16
  end
19
17
  end
data/lib/cantango/api.rb CHANGED
@@ -3,12 +3,13 @@ require 'sugar-high/blank'
3
3
  require 'hashie'
4
4
  require 'sweetloader'
5
5
 
6
- AutoLoader.namespaces = {:CanTango => 'cantango'}
6
+ SweetLoader.namespaces = {:CanTango => 'cantango'}
7
+ SweetLoader.mode = :require
7
8
 
8
9
  module CanTango
9
10
  module Api
10
- autoload_modules :Ability, :Account, :Attributes, :Can
11
- autoload_modules :Common, :Options, :Model, :Scope, :Session, :User
11
+ sweetload :Attributes, :Options, :Common, :Ability, :Account, :Can
12
+ sweetload :Model, :Scope, :Session, :User
12
13
 
13
14
  def self.apis
14
15
  [:ability, :can, :scope, :session]
@@ -21,6 +22,8 @@ module CanTango
21
22
  end
22
23
 
23
24
  # FIX - sweetloader, camelize there!
24
- autoload_modules *apis.map{|api| api.to_s.camelize}
25
+ sweetload *apis.map{|api| api.to_s.camelize}
25
26
  end
26
27
  end
28
+
29
+ require 'cantango/api_ext'
@@ -0,0 +1,8 @@
1
+ module CanTango::Macros
2
+ module Account
3
+ def tango_account options = {}
4
+ self.send :include, CanTango::Api::Model::Account
5
+ end
6
+ alias_method :cantango_account, :tango_account
7
+ end
8
+ end
@@ -0,0 +1,17 @@
1
+ module CanTango::Macros
2
+ module Clazz
3
+ include CanTango::Macros::Account
4
+ include CanTango::Macros::User
5
+
6
+ def cantango type = nil
7
+ # determine if user or account
8
+ if !type
9
+ (name =~ /.+Account$/) ? tango_account : tango_user
10
+ else
11
+ tango_account and return if type.to_s == 'account'
12
+ tango_user and return if type.to_s == 'user'
13
+ raise ArgumentError, "Unable to determine type of class to register; Please specify :user or :account as argument"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,8 @@
1
+ module CanTango::Macros
2
+ module User
3
+ def tango_user options = {}
4
+ self.send :include, CanTango::Api::Model::User
5
+ end
6
+ alias_method :cantango_user, :tango_user
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ module CanTango
2
+ module Macros
3
+ sweet_scope :ns => {:CanTango => 'cantango/api_ext'} do
4
+ autoload_modules :Account, :User, :Clazz
5
+ end
6
+ end
7
+ end
8
+
9
+ class Class
10
+ include CanTango::Macros::Clazz
11
+ end
12
+
@@ -0,0 +1,5 @@
1
+ module CanTango
2
+ sweet_scope :ns => {:CanTango => 'cantango/api_ext'} do
3
+ sweetload :Macros
4
+ end
5
+ end
@@ -1,34 +1,33 @@
1
- require 'spec_helper'
2
-
3
- # require 'cantango/configuration/engines/store_engine_shared'
1
+ require 'cantango/config'
2
+ require 'fixtures/models'
4
3
 
5
4
  CanTango.configure do |config|
6
- config.users.register :user, User
5
+ config.users.register :user, User
7
6
  config.users.register :admin, Admin
8
7
 
9
- config.accounts.register :user, UserAccount
8
+ config.accounts.register :user, UserAccount
10
9
  config.accounts.register :admin, AdminAccount
11
-
12
- # config.cache_engine.set :off
13
- # config.permit_engine.set :on
14
10
  end
15
11
 
12
+ require 'spec_helper'
13
+ require 'helpers/current_user_accounts'
14
+
16
15
  class Context
17
- include CanTango::Api::Account::Ability
16
+ include CanTango::Api::Ability::Account
18
17
 
19
18
  include_and_extend ::CurrentUserAccounts
20
19
  end
21
20
 
22
- describe CanTango::Api::UserAccount::Ability do
21
+ describe CanTango::Api::Ability::Account do
23
22
  subject { Context.new }
24
23
 
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 }
24
+ describe 'account_ability' do
25
+ specify { subject.account_ability(subject.current_user_account).should be_a CanTango::Ability::Executor }
26
+ specify { subject.account_ability(subject.current_admin_account).should be_a CanTango::Ability::Executor }
28
27
  end
29
28
 
30
29
  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 }
30
+ specify { subject.current_account_ability(:user).should be_a CanTango::Ability::Executor }
31
+ specify { subject.current_account_ability(:admin).should be_a CanTango::Ability::Executor }
33
32
  end
34
33
  end
@@ -1,9 +1,5 @@
1
- require 'rspec'
2
- require 'cantango'
3
- require 'simple_roles'
1
+ require 'cantango/config'
4
2
  require 'fixtures/models'
5
- require 'cantango/api/current_users'
6
- # require 'cantango/configuration/engines/store_engine_shared'
7
3
 
8
4
  class User
9
5
  include_and_extend SimpleRoles
@@ -13,44 +9,44 @@ class Admin < User
13
9
  end
14
10
 
15
11
  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
12
+ config.users.register :user, User
13
+ config.users.register :admin, Admin
21
14
  end
22
15
 
16
+ require 'spec_helper'
17
+ require 'helpers/current_user_accounts'
18
+
23
19
  class Context
24
- include CanTango::Api::User::Ability
20
+ include CanTango::Api::Ability::User
25
21
 
26
22
  include_and_extend ::CurrentUsers
27
23
  end
28
24
 
29
- describe CanTango::Api::User::Ability do
25
+ describe CanTango::Api::Ability::User do
30
26
  subject { Context.new }
31
27
 
32
28
  describe 'user_ability user' do
33
- specify { subject.user_ability(subject.current_user).should be_a CanTango::Ability }
29
+ specify { subject.user_ability(subject.current_user).should be_a CanTango::Ability::Executor }
34
30
  end
35
31
 
36
32
  describe 'user_ability admin' do
37
- specify { subject.user_ability(subject.current_admin).should be_a CanTango::Ability }
33
+ specify { subject.user_ability(subject.current_admin).should be_a CanTango::Ability::Executor }
38
34
  end
39
35
 
40
36
  describe 'current_user_ability :user' do
41
- specify { subject.current_user_ability(:user).should be_a CanTango::Ability }
37
+ specify { subject.current_user_ability(:user).should be_a CanTango::Ability::Executor }
42
38
 
43
- it 'should set the :user user correctly on ability' do
44
- subject.current_user_ability(:user).user.should == subject.current_user
45
- end
39
+ # it 'should set the :user user correctly on ability' do
40
+ # subject.current_user_ability(:user).user.should == subject.current_user
41
+ # end
46
42
  end
47
43
 
48
44
  describe 'current_user_ability :admin' do
49
- specify { subject.current_user_ability(:admin).should be_a CanTango::Ability }
45
+ specify { subject.current_user_ability(:admin).should be_a CanTango::Ability::Executor }
50
46
 
51
- it 'should set the :admin user correctly on ability' do
52
- subject.current_user_ability(:admin).user.should == subject.current_admin
53
- end
47
+ # it 'should set the :admin user correctly on ability' do
48
+ # subject.current_user_ability(:admin).user.should == subject.current_admin
49
+ # end
54
50
  end
55
51
  end
56
52
 
@@ -0,0 +1,40 @@
1
+ require 'cantango/config'
2
+ require 'fixtures/models'
3
+
4
+ CanTango.configure do |config|
5
+ config.accounts.register :user, UserAccount
6
+ end
7
+
8
+ require 'spec_helper'
9
+
10
+ class AccountContext
11
+ include CanTango::Api::Account
12
+ end
13
+
14
+ describe CanTango::Api::Account do
15
+ subject { AccountContext.new }
16
+
17
+ describe 'Ability API included' do
18
+ [:account_ability, :current_account_ability].each do |name|
19
+ specify { subject.should respond_to name }
20
+ end
21
+ end
22
+
23
+ describe 'Can API included' do
24
+ [:user_account_can?, :user_account_cannot?].each do |name|
25
+ specify { subject.should respond_to name }
26
+ end
27
+ end
28
+
29
+ describe 'Scope API included' do
30
+ [:scope_account, :account_scope, :real_account].each do |name|
31
+ specify { subject.should respond_to name }
32
+ end
33
+ end
34
+
35
+ describe 'Session API included' do
36
+ [:any_account, :active_account, :active_account=].each do |name|
37
+ specify { subject.should respond_to name }
38
+ end
39
+ end
40
+ end
@@ -1,25 +1,24 @@
1
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
2
 
7
3
  class Context
8
- include CanTango::Api::User::Ability
9
-
10
- include CurrentUsers
11
- extend ::CurrentUsers
4
+ include CanTango::Api::Attributes
12
5
  end
13
6
 
14
- describe CanTango::Api::User::Ability do
7
+ describe CanTango::Api::Attributes do
15
8
  subject { Context.new }
16
9
 
17
- describe 'user_ability user' do
18
- specify { subject.user_ability(subject.current_user).should be_a CanTango::Ability }
19
- end
10
+ [:read, :edit].each do |action|
11
+ describe ":#{action} attribute" do
12
+ specify do
13
+ subject.send(:"#{action}_attribute", :post).should == :"#{action}_attr_post"
14
+ end
15
+ end
20
16
 
21
- describe 'user_ability admin' do
22
- specify { subject.user_ability(subject.current_admin).should be_a CanTango::Ability }
17
+ describe ":#{action} attributes" do
18
+ specify do
19
+ subject.send(:"#{action}_attributes", :post, :project).should include(:"#{action}_attr_post")
20
+ end
21
+ end
23
22
  end
24
23
  end
25
24
 
@@ -1,51 +1,59 @@
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
1
+ require 'cantango/config'
2
+ require 'fixtures/models'
9
3
 
10
4
  CanTango.configure do |config|
11
- config.users.register :user, User
5
+ config.users.register :user, User
12
6
  config.users.register :admin, Admin
13
7
 
14
- config.accounts.register :user, UserAccount
8
+ config.accounts.register :user, UserAccount
15
9
  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
10
+
11
+ config.modes.register :no_cache, CanTango::Ability::Mode::NoCache
12
+ config.ability.mode = :no_cache
33
13
  end
34
14
 
35
- class User
36
- include CanTango::Users::Masquerade
37
- end
15
+ require 'spec_helper'
16
+ require 'helpers/current_user_accounts'
38
17
 
39
18
  class Context
40
- include CanTango::Api::UserAccount::Can
19
+ include CanTango::Api::Can::Account
41
20
 
42
21
  include_and_extend ::CurrentUserAccounts
43
22
  end
44
23
 
45
- describe "CanTango::Api::Can::Account" do
24
+ module CanTango::Ability::Mode
25
+ class NoCache
26
+ def calculate_rules
27
+ can :edit, Article
28
+ cannot :edit, User
29
+ end
30
+ end
31
+ end
32
+
33
+ describe CanTango::Api::Can::Account do
46
34
  subject { Context.new }
47
35
 
48
36
  describe 'user_account' do
37
+ specify do
38
+ subject.current_account_ability(:user).should be_a CanTango::Ability::Executor::Modal
39
+ end
40
+
41
+ specify do
42
+ subject.current_account_ability(:user).modes.should == [:no_cache]
43
+ end
44
+
45
+ specify do
46
+ subject.current_account_ability(:user).should respond_to(:can?)
47
+ end
48
+
49
+ specify do
50
+ subject.current_account_ability(:user).rules.should_not be_empty
51
+ end
52
+
53
+ specify do
54
+ subject.current_account_ability(:user).can?(:edit, Article).should be_true
55
+ end
56
+
49
57
  # user can edit Article, not Admin
50
58
  specify do
51
59
  subject.user_account_can?(:edit, Article).should be_true
@@ -65,21 +73,6 @@ describe "CanTango::Api::Can::Account" do
65
73
  subject.admin_account_cannot?(:edit, Article).should be_false
66
74
  end
67
75
  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
76
  end
84
77
 
85
78