troles 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/Gemfile.lock +1 -1
  2. data/README.textile +75 -16
  3. data/VERSION +1 -1
  4. data/lib/trole/adapters/active_record/config.rb +3 -3
  5. data/lib/trole/adapters/mongoid/config.rb +5 -5
  6. data/lib/trole/config.rb +2 -2
  7. data/lib/trole_groups.rb +10 -0
  8. data/lib/trole_groups/READ THIS.textile +4 -0
  9. data/lib/trole_groups/Rolegroups design.textile +218 -0
  10. data/lib/trole_groups/adapters/active_record.rb +8 -0
  11. data/lib/trole_groups/adapters/active_record/config.rb +0 -0
  12. data/lib/trole_groups/adapters/active_record/storage.rb +0 -0
  13. data/lib/trole_groups/adapters/active_record/strategy.rb +11 -0
  14. data/lib/trole_groups/adapters/mongoid.rb +8 -0
  15. data/lib/trole_groups/adapters/mongoid/config.rb +0 -0
  16. data/lib/trole_groups/api.rb +29 -0
  17. data/lib/trole_groups/api/cache.rb +13 -0
  18. data/lib/trole_groups/api/config.rb +4 -0
  19. data/lib/trole_groups/api/core.rb +50 -0
  20. data/lib/trole_groups/api/event.rb +29 -0
  21. data/lib/trole_groups/api/read.rb +56 -0
  22. data/lib/trole_groups/api/validation.rb +44 -0
  23. data/lib/trole_groups/api/write.rb +60 -0
  24. data/lib/trole_groups/config.rb +134 -0
  25. data/lib/trole_groups/config/schema.rb +65 -0
  26. data/lib/trole_groups/config/schema/helpers.rb +11 -0
  27. data/lib/trole_groups/config/schema/role_group_helpers.rb +11 -0
  28. data/lib/trole_groups/config/valid_role_groups.rb +21 -0
  29. data/lib/trole_groups/macros.rb +42 -0
  30. data/lib/trole_groups/macros/configuration.rb +89 -0
  31. data/lib/trole_groups/macros/configuration/base_loader.rb +35 -0
  32. data/lib/trole_groups/macros/configuration/config_loader.rb +19 -0
  33. data/lib/trole_groups/macros/configuration/storage_loader.rb +20 -0
  34. data/lib/trole_groups/macros/configuration/strategy_loader.rb +38 -0
  35. data/lib/trole_groups/macros/static_roles.rb +9 -0
  36. data/lib/trole_groups/macros/strategy_options.rb +21 -0
  37. data/lib/trole_groups/operations.rb +25 -0
  38. data/lib/trole_groups/operations/read.rb +36 -0
  39. data/lib/trole_groups/operations/write.rb +42 -0
  40. data/lib/trole_groups/storage.rb +27 -0
  41. data/lib/trole_groups/storage/base_many.rb +93 -0
  42. data/lib/trole_groups/storage/embed_many.rb +58 -0
  43. data/lib/trole_groups/storage/ref_many.rb +47 -0
  44. data/lib/trole_groups/strategy.rb +30 -0
  45. data/lib/troles/adapters/active_record/config.rb +32 -9
  46. data/lib/troles/adapters/mongoid/config.rb +7 -7
  47. data/lib/troles/common/api/core.rb +1 -1
  48. data/lib/troles/common/config.rb +49 -14
  49. data/lib/troles/common/config/schema.rb +17 -23
  50. data/lib/troles/common/config/schema/helpers.rb +77 -0
  51. data/lib/troles/common/config/schema/role_helpers.rb +27 -0
  52. data/lib/troles/common/config/static_roles.rb +4 -4
  53. data/lib/troles/common/macros.rb +4 -4
  54. data/lib/troles/common/macros/configuration.rb +8 -8
  55. data/lib/troles/common/macros/strategy_options.rb +4 -4
  56. data/lib/troles/common/storage.rb +1 -0
  57. data/lib/troles/config.rb +2 -2
  58. data/lib/troles/storage/ref_many.rb +2 -3
  59. data/spec/active_record/models/ref_many.rb +3 -0
  60. data/spec/active_record/strategies/many/ref_many_spec.rb +2 -1
  61. data/spec/generic/models/role.rb +2 -1
  62. data/spec/trole_groups/api/core_api_spec.rb +14 -0
  63. data/spec/trole_groups/api/read_api_spec.rb +36 -0
  64. data/spec/trole_groups/api/write_api_spec.rb +19 -0
  65. data/spec/trole_groups/api_spec.rb +27 -0
  66. data/spec/trole_groups/generic/models.rb +3 -0
  67. data/spec/trole_groups/generic/models/role_group.rb +44 -0
  68. data/spec/trole_groups/generic/models/user.rb +9 -0
  69. data/spec/trole_groups/strategies/ref_many.rb +51 -0
  70. data/spec/trole_groups/strategy_helper.rb +9 -0
  71. data/spec/trole_groups_spec.rb +11 -0
  72. data/spec/trole_spec_helper.rb +9 -0
  73. data/spec/troles/api_spec.rb +12 -18
  74. data/troles.gemspec +52 -4
  75. metadata +85 -37
  76. data/development.sqlite3 +0 -0
  77. data/lib/troles/common/config/schema_helpers.rb +0 -95
@@ -0,0 +1,42 @@
1
+ # @author Kristian Mandrup
2
+ module TroleGroups
3
+ class Operations
4
+ module Write
5
+
6
+ # Test role_groups equality
7
+ # @param [Array<Symbol>] role_groups list to test
8
+ def == *role_groups
9
+ rolegroup_subject.rolegroup_list == role_groups.to_symbols_uniq
10
+ end
11
+ alias_method :equal, :"=="
12
+ alias_method :same_as, :"=="
13
+
14
+ # Add a set of role_groups to the role subject
15
+ # @param [Array<Symbol>] role_groups list to add
16
+ # @return [true, false, Error] true if added, false if static or invalid, Error on some error
17
+ def + *role_groups
18
+ rolegroup_subject.add_role_groups role_groups.to_symbols_uniq
19
+ end
20
+ alias_method :<<, :+
21
+ alias_method :add, :+
22
+ alias_method :add!, :+
23
+
24
+ # Remove a set of role_groups from the role subject
25
+ # @param [Array<Symbol>] role_groups list to add
26
+ # @return [true, false, Error] true if removed, false if static or invalid, Error on some error
27
+ def - *role_groups
28
+ rolegroup_subject.remove_role_groups role_groups.to_symbols_uniq
29
+ end
30
+ alias_method :remove, :-
31
+ alias_method :remove!, :-
32
+
33
+ # Clear all the role_groups from the role subject
34
+ # @param [Array<Symbol>] role_groups list to add
35
+ # @return [true, false, Error] true if removed, false if static or invalid, Error on some error
36
+ def clear
37
+ rolegroup_subject.clear_role_groups!
38
+ end
39
+ alias_method :clear!, :clear
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,27 @@
1
+ module TroleGroups
2
+ module Storage
3
+ autoload :BaseMany, 'trole_groups/storage/base_many'
4
+ # autoload :BitMany, 'trole_groups/storage/bit_many'
5
+ autoload :EmbedMany, 'trole_groups/storage/embed_many'
6
+ autoload :RefMany, 'trole_groups/storage/ref_many'
7
+ # autoload :StringMany, 'trole_groups/storage/string_many'
8
+
9
+ class BaseMany < Troles::Common::Storage
10
+ protected
11
+
12
+ # get matching list of Role instances
13
+ # @param [Array<Symbol>] list of role names to find Roles for
14
+ # @return [Array<Role>] references to Role instances
15
+ def find_rolegroups *rolegroups
16
+ rolegroup_model.where(:name => rolegroups.flatten).all
17
+ end
18
+
19
+ # get list of embedded Role instances
20
+ # @param [Array<Symbol>] list of role names
21
+ # @return [Array<Role>] Role instances generated
22
+ def rolegroups_to_embed *rolegroups
23
+ raise "Must be implemented by embed storage to generate a set of rolegroups to embed"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,93 @@
1
+ # @author Kristian Mandrup
2
+ #
3
+ # Troles base storage for Many roles strategies
4
+ #
5
+ module TroleGroups
6
+ module Storage
7
+ class BaseMany
8
+ attr_reader :rolegroup_subject
9
+
10
+ # initializes storage with reference to role subject
11
+ # @param [Object] the role subject (fx a User or UserAccount)
12
+ def initialize rolegroup_subject
13
+ @rolegroup_subject = rolegroup_subject
14
+ end
15
+
16
+ # valid roles of the role subjects class (fx account - i.e the account rules!)
17
+ # @return [Array<Symbol>] the list of valid roles
18
+ def valid_roles
19
+ rolegroup_subject.class.valid_roles
20
+ end
21
+
22
+ # name/type of storage
23
+ # @return [Symbol]
24
+ def name
25
+ :generic
26
+ end
27
+
28
+ # sets the value of the role field (@trole or @troles) and persists the value (in the data store)
29
+ # @param [Object] the value to set on the role field of the role subject
30
+ def set_ds_field value
31
+ return if ds_field_value == value
32
+ rolegroup_subject.send(:"#{ds_field_name}=", value)
33
+ persist_role_changes!
34
+ end
35
+
36
+ # the name of the role field
37
+ # @return [Symbol] the name
38
+ def ds_field_name
39
+ rolegroup_field
40
+ end
41
+
42
+ # the current value of the role field
43
+ # @return [Object] the value
44
+ def ds_field_value
45
+ rolegroup_subject.send(ds_field_name)
46
+ end
47
+
48
+ # Attempts to persist the role field changes
49
+ # @return [true, false, error] true if saved, false if no save! method, Error on some error
50
+ def persist_role_changes!
51
+ return false if !rolegroup_subject.respond_to? :save!
52
+ rolegroup_subject.save!
53
+ rolegroup_subject.publish_change :role_groups
54
+ end
55
+
56
+ protected
57
+
58
+ def trolegroups_config
59
+ rolegroup_subject.class.trolegroups_config
60
+ end
61
+
62
+ def rolegroup_field
63
+ trolegroups_config.rolegroup_field
64
+ end
65
+
66
+ def rolegroup_model
67
+ trolegroups_config.rolegroup_model
68
+ end
69
+
70
+ def rolegroup_list
71
+ rolegroup_subject.rolegroup_list
72
+ end
73
+
74
+ def role_list
75
+ rolegroup_subject.role_list
76
+ end
77
+
78
+ # get matching list of Role instances
79
+ # @param [Array<Symbol>] list of role names to find Roles for
80
+ # @return [Array<Role>] references to Role instances
81
+ def find_rolegroups *names
82
+ rolegroup_model.where(:name => names.flatten).all
83
+ end
84
+
85
+ # get list of embedded Role instances
86
+ # @param [Array<Symbol>] list of role names
87
+ # @return [Array<Role>] Role instances generated
88
+ def rolegroups_to_embed *roles
89
+ raise "Must be implemented by embed storage to generate a set of roles to embed"
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,58 @@
1
+ # @author Kristian Mandrup
2
+ #
3
+ # Many role storage for storing (embedding) multiple Role instances in a list on the role subject
4
+ #
5
+ # @note all methods potentially operate directly on values in the data store
6
+ #
7
+ module TroleGroups::Storage
8
+ class EmbedMany < BaseMany
9
+
10
+ # constructor
11
+ # @param [Object] the role subject
12
+ def initialize rolegroupsubject
13
+ super
14
+ end
15
+
16
+ def rolegroups_to_embed *rolegroups
17
+ rolegroups.flatten.inject([]) do |res, role|
18
+ res << create_role(role)
19
+ res
20
+ end
21
+ end
22
+
23
+ # display the rolegroups as a list of symbols
24
+ # @return [Array<Symbol>] rolegroups list
25
+ def display_rolegroups
26
+ return [] if !ds_field_value?
27
+ ds_field_value.map{|rolegroup| rolegroup.name.to_sym }
28
+ end
29
+
30
+ # is it set?
31
+ def ds_field_value?
32
+ ds_field_value && !ds_field_value.empty?
33
+ end
34
+
35
+ # saves the rolegroups for the role subject in the data store
36
+ # @param [Array<Symbol>] rolegroups list
37
+ def set_rolegroups *rolegroups
38
+ # creates and embeds new Role instances from symbols
39
+ set_ds_field rolegroups_to_embed(*rolegroups)
40
+ end
41
+
42
+ # clears the role of the user in the data store
43
+ def clear!
44
+ set_ds_field []
45
+ end
46
+
47
+ # sets the role to its default state
48
+ def set_default_role!
49
+ clear!
50
+ end
51
+
52
+ protected
53
+
54
+ def create_role name
55
+ rolegroup_model.create name
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,47 @@
1
+ module TroleGroups::Storage
2
+ class RefMany < BaseMany
3
+ def initialize rolegroup_subject
4
+ super
5
+ end
6
+
7
+ def display_roles
8
+ display_roles_for rolegroup_list
9
+ end
10
+
11
+ def display_roles_for *names
12
+ groups = find_rolegroups names.to_symbols_uniq
13
+ groups.inject([]) {|res, group| res << group.roles }.flat_uniq
14
+ end
15
+
16
+ # display the roles as a list of symbols
17
+ # @return [Array<Symbol>] roles list
18
+ def display_rolegroups
19
+ return [] if !ds_field_value?
20
+ ds_field_value.flatten.map do |rolegroup|
21
+ rolegroup.name.to_sym
22
+ end
23
+ end
24
+
25
+ # is it set?
26
+ def ds_field_value?
27
+ ds_field_value && !ds_field_value.empty?
28
+ end
29
+
30
+ # saves the role for the user in the data store
31
+ def set_rolegroups *rolegroups
32
+ # finds and sets references to existing Role instances from symbols
33
+ found = find_rolegroups(*rolegroups)
34
+ set_ds_field found
35
+ end
36
+
37
+ # clears the role of the user in the data store
38
+ def clear!
39
+ set_ds_field []
40
+ end
41
+
42
+ # sets the role to default setting
43
+ def set_default_role!
44
+ clear!
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,30 @@
1
+ # @author Kristian Mandrup
2
+ #
3
+ # Base module for Many roles strategies
4
+ #
5
+ module TroleGroups
6
+ module Strategy
7
+ module BaseMany
8
+ #
9
+ # a Many role strategy is included by a role subject (fx a UserAccount class)
10
+ # a Many role strategy should always include BaseMany
11
+ # when BaseMany is included, it ensures that the complete
12
+ # Troles API is also included into the role subject
13
+ #
14
+ # @note the Trole::Api also includes the Troles::Common::Api
15
+ #
16
+ # @param [Class] the role subject class for which to include the Role strategy (fx User Account)
17
+ #
18
+ def self.included(base)
19
+ base.send :include, TroleGroups::Api
20
+ end
21
+
22
+ # The storage to use
23
+ # @return [Troles::Storage] a storage subclass instance matching the needs of the strategy
24
+ def group_store
25
+ @group_store ||= group_storage.new self
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -1,9 +1,7 @@
1
1
  module Troles::ActiveRecord
2
2
  class Config < Troles::Common::Config
3
-
4
- attr_accessor :role_join_model
5
3
 
6
- def initialize clazz, options = {}
4
+ def initialize subject_class, options = {}
7
5
  super
8
6
  end
9
7
 
@@ -11,7 +9,7 @@ module Troles::ActiveRecord
11
9
  case strategy
12
10
  when :ref_many
13
11
  return configure_join_model if role_join_model
14
- has_and_belongs_many clazz, role_model, :key => :accounts
12
+ has_and_belongs_many subject_class, object_model, :key => :accounts
15
13
  when :embed_many
16
14
  raise "Embed many configuration not yet implemented for ActiveRecord"
17
15
  end
@@ -23,26 +21,51 @@ module Troles::ActiveRecord
23
21
 
24
22
  protected
25
23
 
24
+ def object_model
25
+ role_model
26
+ end
27
+
28
+ def role_join_model
29
+ @join_model_found ||= begin
30
+ models = [@join_model, join_model_best_guess].select do |class_name|
31
+ try_class(class_name.to_s.camelize)
32
+ end.compact
33
+ # puts "role models found: #{models}"
34
+ raise "No #{subject_class} to #{object_model} join class defined, define a #{join_model_best_guess} model class or set which class to use, using the :role_join_model option on configuration" if models.empty?
35
+ models.first.to_s.constantize
36
+ end
37
+ end
38
+
39
+ def join_model_best_guess
40
+ "#{subject_class.to_s.pluralize}#{object_model.to_s.pluralize}"
41
+ end
42
+
43
+ def role_join_model= model_class
44
+ @join_model = model_class and return if model_class.any_kind_of?(Class, String, Symbol)
45
+ raise "The role model must be a Class, was: #{model_class}"
46
+ end
47
+
48
+
26
49
  def join_key
27
50
  make_key role_join_model
28
51
  end
29
52
 
30
- def join_model
53
+ def configure_join_model
31
54
  # UserAccount
32
55
  # has_many :troles, :class_name => 'Role', :through => :users_roles
33
- has_many_for clazz, role_model, :through => join_key
56
+ has_many_for subject_class, role_model, :through => join_key
34
57
  # has_many :user_roles, :class_name => 'UserRole'
35
- has_many_for clazz, role_join_model, :key => join_key
58
+ has_many_for subject_class, role_join_model, :key => join_key
36
59
 
37
60
  # UserRole (custom join class name)
38
61
  # belongs_to :user, :class_name => 'UserAccount'
39
- belongs_to_for role_join_model, clazz
62
+ belongs_to_for role_join_model, subject_class
40
63
  # belongs_to :role, :class_name => 'Role'
41
64
  belongs_to_for role_join_model, role_model
42
65
 
43
66
  # Role
44
67
  # has_many :accounts, :class_name => 'User', :through => :user_roles
45
- has_many_for role, clazz, :through => join_key, :key => :accounts
68
+ has_many_for role, subject_class, :through => join_key, :key => :accounts
46
69
 
47
70
  # has_many :user_roles, :class_name => 'UserRole'
48
71
  has_many_for role, role_join_model, :key => join_key
@@ -1,7 +1,7 @@
1
1
  module Troles::Mongoid
2
2
  class Config < Troles::Common::Config
3
3
 
4
- def initialize clazz, options = {}
4
+ def initialize subject_class, options = {}
5
5
  super
6
6
  end
7
7
 
@@ -9,15 +9,15 @@ module Troles::Mongoid
9
9
  def configure_relation
10
10
  case strategy
11
11
  when :ref_many
12
- has_many_for clazz, :role, :through => join_key
12
+ has_many_for subject_class, :role, :through => join_key
13
13
 
14
- belongs_to_for join_model, :user
15
- belongs_to_for join_model, :role
14
+ belongs_to_for join_model, subject_class
15
+ belongs_to_for join_model, object_model
16
16
 
17
- has_many_for role, :user, :through => join_key
17
+ has_many_for role, subject_class, :through => join_key
18
18
 
19
19
  when :embed_many
20
- embeds_many clazz, :role
20
+ embeds_many subject_class, object_model
21
21
  end
22
22
  end
23
23
 
@@ -29,7 +29,7 @@ module Troles::Mongoid
29
29
  String
30
30
  end
31
31
  # field :name, :type => String
32
- clazz.send(:field, role_field, type_opts(type)) if type
32
+ subject_class.send(:field, role_field, type_opts(type)) if type
33
33
  end
34
34
 
35
35
  def type_opts type
@@ -45,7 +45,7 @@ module Troles::Common::Api
45
45
  #
46
46
  # @return [true, false] if role subjects have static roles or not (default: false)
47
47
  def static_roles?
48
- troles_config.static_roles_for_class?
48
+ troles_config.static_roles?
49
49
  end
50
50
  end
51
51
  end
@@ -13,11 +13,11 @@ module Troles::Common
13
13
  send :include, "Troles::Common::Config::#{name.to_s.camelize}".constantize
14
14
  end
15
15
 
16
- attr_accessor :clazz, :strategy, :log_on, :generic
16
+ attr_accessor :subject_class, :strategy, :log_on, :generic, :auto_relations
17
17
  attr_writer :orm
18
18
 
19
- def initialize clazz, options = {}
20
- @clazz = clazz
19
+ def initialize subject_class, options = {}
20
+ @subject_class = subject_class
21
21
  # set instance var for each pair in options
22
22
  apply_options! options
23
23
  end
@@ -42,12 +42,58 @@ module Troles::Common
42
42
  def auto_load?
43
43
  @auto_load
44
44
  end
45
+
46
+ def auto_config
47
+ auto_config_setings
48
+ end
49
+
50
+ def auto_config? name
51
+ auto_config_setings[name]
52
+ end
53
+
54
+ protected
55
+
56
+
57
+ def auto_config_setings
58
+ @auto_config_setings ||= auto_config_defaults
59
+ end
60
+
61
+ # default auto_config settings
62
+ def auto_config_defaults
63
+ {:models => true, :relations => true, :fields => true}
64
+ end
45
65
  end
46
66
 
47
67
  def log_on?
48
68
  log_on || Troles::Config.log_on
49
69
  end
50
70
 
71
+ def auto_config
72
+ auto_config_setings
73
+ end
74
+
75
+ def auto_config? name
76
+ return auto_config_setings[name] if !auto_config_setings[name].nil?
77
+ Troles::Config.auto_config?(name)
78
+ end
79
+
80
+ def apply_options! options = {}
81
+ options.each_pair do |key, value|
82
+ send("#{key}=", value) if self.respond_to?(:"#{key}")
83
+ end
84
+ end
85
+
86
+ def configure! options = {}
87
+ apply_options! options
88
+ configure_models if auto_config?(:models)
89
+ end
90
+
91
+ # protected
92
+
93
+ def auto_config_setings
94
+ @auto_config_setings ||= {}
95
+ end
96
+
51
97
  def role_field
52
98
  @role_field ||= begin
53
99
  default_role_field
@@ -68,12 +114,6 @@ module Troles::Common
68
114
  @orm || self.class.default_orm
69
115
  end
70
116
 
71
- def apply_options! options = {}
72
- options.each_pair do |key, value|
73
- send("#{key}=", value) if self.respond_to?(:"#{key}")
74
- end
75
- end
76
-
77
117
  def singularity
78
118
  @singularity ||= (strategy =~ /_many$/) ? :many : :one
79
119
  end
@@ -82,11 +122,6 @@ module Troles::Common
82
122
  # raise ArgumentError, "Must be :many or :one" if ![:one, :many].include?(value)
83
123
  # @singularity ||= value
84
124
  # end
85
-
86
- def configure! options = {}
87
- apply_options! options
88
- configure_role_field
89
- end
90
125
 
91
126
  def generic?
92
127
  return true if orm.nil?