troles 0.5.0 → 0.5.1

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 (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?