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,8 @@
1
+ module TroleGroups
2
+ module ActiveRecord
3
+ autoload :Config, 'trole_groups/adapters/active_record/config'
4
+ # autoload :Api, 'trole_groups/adapters/active_record/api'
5
+ autoload :Storage, 'trole_groups/adapters/active_record/storage'
6
+ autoload :Strategy, 'trole_groups/adapters/active_record/strategy'
7
+ end
8
+ end
File without changes
@@ -0,0 +1,11 @@
1
+ module TroleGroups::ActiveRecord
2
+ module Strategy
3
+ module BaseMany
4
+ # @param [Class] the role subject class for which to include the Role strategy (fx User Account)
5
+ #
6
+ def self.included(base)
7
+ base.send :include, TroleGroups::Strategy::BaseMany
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ module TroleGroups
2
+ module Mongoid
3
+ autoload :Config, 'trole_groups/adapters/mongoid/config'
4
+ # autoload :Api, 'trole_groups/adapters/mongoid/api'
5
+ # autoload :Storage, 'trole_groups/adapters/mongoid/storage'
6
+ # autoload :Strategy, 'trole_groups/adapters/mongoid/strategy'
7
+ end
8
+ end
File without changes
@@ -0,0 +1,29 @@
1
+ module TroleGroups
2
+ module Api
3
+ autoload :Core, 'trole_groups/api/core'
4
+ autoload :Cache, 'trole_groups/api/cache'
5
+ autoload :Config, 'trole_groups/api/config'
6
+ autoload :Event, 'trole_groups/api/event'
7
+ autoload :Read, 'trole_groups/api/read'
8
+ autoload :Write, 'trole_groups/api/write'
9
+ autoload :Validation, 'trole_groups/api/validation'
10
+
11
+
12
+ module ClassMethods
13
+ def apis
14
+ [:core, :cache, :config, :event, :read, :validation, :write]
15
+ end
16
+
17
+ def included(base)
18
+ apis.each do |api|
19
+ begin
20
+ base.include_and_extend :"#{api.to_s.camelize}"
21
+ rescue
22
+ puts "include error: #{api}"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ extend ClassMethods
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ #
2
+ # @author Kristian Mandrup
3
+ #
4
+ # Caching Api to ensure the rolegroup list of a rolegroup subject is cached and invalidated on rolegroup change
5
+ #
6
+ module TroleGroups::Api
7
+ module Cache
8
+ def invalidate_rolegroups_cache!
9
+ @rolegroup_list = nil
10
+ invalidate_role_cache!
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ module TroleGroups::Api
2
+ module Config
3
+ end
4
+ end
@@ -0,0 +1,50 @@
1
+ module TroleGroups::Api
2
+ module Core
3
+ # Access to the Troles operations API
4
+ # @return [Troles::Operations] the operations API object
5
+ def rolegroups
6
+ @rolegroups ||= TroleGroups::Operations.new(self)
7
+ end
8
+
9
+ # Sets the roles of the subject
10
+ # (see #set_roles)
11
+ def rolegroups= *new_rolegroups
12
+ rolegroups.set_rolegroups new_rolegroups
13
+ end
14
+
15
+ # If this role subject instance should have static (immutable) roles
16
+ # @return [true, false] defaults to false so a role subject is allowed to change roles
17
+ def static_roles?
18
+ false
19
+ end
20
+
21
+ def trolegroups_config
22
+ self.class.trolegroups_config
23
+ end
24
+
25
+ module ClassMethods
26
+
27
+ def rolegroup_field
28
+ trolegroups_config.rolegroup_field
29
+ end
30
+
31
+ def valid_rolegroups
32
+ trolegroups_config.valid_roles
33
+ end
34
+
35
+ # # TODO: make sure alphanumeric only
36
+ # def valid_roles= *roles
37
+ # troles_config.valid_roles = *roles
38
+ # end
39
+
40
+ # If all role subjects using this strategy should have static (immutable) roles
41
+ #
42
+ # @note Should also proxy Config object?
43
+ #
44
+ # @return [true, false] if role subjects have static roles or not (default: false)
45
+ def static_roles?
46
+ false # trolegroups_config.static_roles?
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,29 @@
1
+ module TroleGroups::Api
2
+ module Event
3
+ # a change to the roles of the user should be published to an event handler
4
+ # this can be used to update both the Role cache of the user and fx the RolePermit cache.
5
+ # Both (and potentially others, fx for Role Groups) can subscribe to this event!
6
+ def update_role_groups
7
+ publish_change(:role_groups) if field_changed?(rolegroups_field)
8
+ end
9
+
10
+ # check if a field on the model changed
11
+ # See http://api.rubyonrails.org/classes/ActiveModel/Dirty.html
12
+ def field_changed? name
13
+ send :"#{name}_changed?"
14
+ end
15
+
16
+ # can be customized
17
+ # here uses singleton EventManager
18
+ def publish_change event
19
+ send :invalidate_rolegroups_cache! if event == :role_groups
20
+ event_manager.publish_change event, :from => self
21
+ end
22
+
23
+ protected
24
+
25
+ def event_manager
26
+ Troles::Common::EventManager
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,56 @@
1
+ module TroleGroups::Api
2
+ module Read
3
+ def roles_from_rolegroups
4
+ group_store.display_roles
5
+ end
6
+
7
+ def roles_for *names
8
+ group_store.display_roles_for *names
9
+ end
10
+
11
+ # any? on rolegroups_list
12
+ def in_rolegroup? rolegroup
13
+ rolegroup_list.include? rolegroup.to_sym
14
+ end
15
+ alias_method :has_rolegroup?, :in_rolegroup?
16
+
17
+ # rolegroup_list has one element which is rolegroup
18
+ def only_in_rolegroup? rolegroup
19
+ rolegroup_list.first == rolegroup.to_sym && rolegroup_list.size == 1
20
+ end
21
+
22
+ # subtraction of role_groups from rolegroups_list is empty
23
+ def in_rolegroups? *rolegroups
24
+ (rolegroups.to_symbols - rolegroup_list).empty?
25
+ end
26
+ alias_method :has_rolegroups?, :in_rolegroups?
27
+
28
+ # union of rolegroups and rolegroups_list is not empty
29
+ def in_any_rolegroup? *rolegroups
30
+ !(rolegroup_list & rolegroups.to_symbols).empty?
31
+ end
32
+ alias_method :has_any_rolegroup?, :in_any_rolegroup?
33
+
34
+ # return roles of that rolegroup
35
+ def roles_of rolegroup
36
+ raise "Pending"
37
+ end
38
+
39
+ # return Set of symbols,where each symbol is a rolegroup name
40
+ # This set should be cached and only invalidated when the user has a change of roles
41
+ def rolegroup_list
42
+ @rolegroup_list ||= begin
43
+ group_store.display_rolegroups
44
+ end
45
+ end
46
+
47
+ # Ensures that the common API methods always have a common underlying model to work on
48
+ # @note This Set should be cached and only invalidated when the user has a change of roles
49
+ # @return Array<Symbol> Set of role names
50
+ def role_list
51
+ @role_list ||= begin
52
+ (store.display_roles | group_store.display_roles)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,44 @@
1
+ #
2
+ # @author Kristian Mandrup
3
+ #
4
+ # Common Validation API
5
+ #
6
+ module TroleGroups::Api
7
+ module Validation
8
+
9
+ # @return [Symbol, false] returns the role if it's valid, false if not
10
+ def check_valid_rolegroup? rolegroup
11
+ return rolegroup if valid_rolegroups.include? rolegroup.to_sym
12
+ false
13
+ end
14
+
15
+ # @return [Array<Symbol>] returns the valid roles or empty list if no valid roles
16
+ def check_valid_rolegroups? *rolegroups
17
+ valid_rolegroups & rolegroups.to_symbols
18
+ end
19
+
20
+ protected
21
+
22
+ # Ensures the role is valid
23
+ # @param [Symbol] role name
24
+ # @return [Symbol, false, Error] a valid role name, false if invalid, or Error on some error
25
+ def make_valid_rolegroup rolegroup
26
+ raise ArgumentError, "Rolegroup to set must be a Symbol or String" if !rolegroup.kind_of_label?
27
+ check_valid_rolegroup? rolegroup.to_s.alpha_numeric
28
+ end
29
+
30
+ # Ensures the role are valid
31
+ # @param [Symbol] list of roles
32
+ # @return [Array<Symbol>] the valid roles from the list of roles given
33
+ def make_valid_rolegroups *rolegroups
34
+ rolegroups = rolegroups.to_symbols_uniq
35
+ return [] if rolegroups.empty?
36
+ check_valid_rolegroups? rolegroups.map{|r| r.to_s.alpha_numeric}
37
+ end
38
+
39
+ # @return [Array<Symbol>] the valid roles of the role subject
40
+ def valid_rolegroups
41
+ self.class.trolegroups_config.valid_rolegroups
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,60 @@
1
+ module TroleGroups::Api
2
+ module Write
3
+ # Add a single new rolegroup to the rolegroups of the subject
4
+ # @param [Symbol] rolegroup to add
5
+ # @return (see #add_rolegroups)
6
+ def add_rolegroup rolegroup_name
7
+ raise ArgumentError, "Take a single rolegroup name, was: #{rolegroup_name}" if !rolegroup_name || !rolegroup_name.kind_of_label?
8
+ add_rolegroups rolegroup_name
9
+ end
10
+
11
+ # Remove a single rolegroup from the rolegroups of the subject
12
+ # @param [Symbol] rolegroup to remove
13
+ # @return (see #remove_rolegroups)
14
+ def remove_rolegroup rolegroup_name
15
+ raise ArgumentError, "Take a single rolegroup name, was: #{rolegroup_name}" if !rolegroup_name || !rolegroup_name.kind_of_label?
16
+ remove_rolegroups rolegroup_name
17
+ end
18
+
19
+ # Adds a set of new rolegroups to the rolegroups of the subject
20
+ # @param [Array<Symbol>] list of rolegroups to add
21
+ # @return [true, false, Error] true if ok, false if static or invalid, Error on some error
22
+ def add_rolegroups *new_rolegroups
23
+ group_store.set_rolegroups (rolegroup_list | new_rolegroups.to_symbols_uniq) # Set Union (joined set)
24
+ end
25
+
26
+ # Removes a set of new rolegroups to the rolegroups of the subject
27
+ # (see #add_rolegroups)
28
+ def remove_rolegroups *the_rolegroups
29
+ group_store.set_rolegroups (rolegroup_list - the_rolegroups.to_symbols_uniq)
30
+ end
31
+
32
+ # Sets new rolegroups for the subject
33
+ # @param [Array<Symbol>] list of rolegroup names
34
+ # @return [true, false, Error] true if set ok, false if any rolegroups were invalid, Error on some error
35
+ def set_rolegroups *rolegroups
36
+ rolegroups_to_set = make_valid_rolegroups(*rolegroups).flat_uniq
37
+ return false if !rolegroups_to_set || rolegroups_to_set.empty?
38
+ group_store.set_rolegroups(rolegroups_to_set)
39
+ end
40
+
41
+ # Clears all the rolegroups of the subject
42
+ # @return [true, false, Error] true if ok, false if rolegroups are static, Error on some error
43
+ def clear_rolegroups!
44
+ group_store.clear!
45
+ end
46
+
47
+ module ClassMethods
48
+ # Sets which rolegroups are valid for the rolegroup subject class (fx User or UserAccount)
49
+ #
50
+ # @note this in effect limits what rolegroups can be assigned to any instance of the class
51
+ #
52
+ # @param [Array<Symbol>] list of rolegroup names
53
+ def set_valid_rolegroups *rolegroups
54
+ rolegroups = rolegroups.to_symbols_uniq
55
+ raise ArgumentError, "Roles must contain Symbols or Strings" if rolegroups.empty?
56
+ @valid_rolegroups = rolegroups
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,134 @@
1
+ module TroleGroups
2
+ class Config
3
+ autoload :ValidRoleGroups, 'trole_groups/config/valid_role_groups'
4
+ autoload :Schema, 'trole_groups/config/schema'
5
+
6
+ def self.sub_modules
7
+ [:valid_role_groups, :schema] # , :static_roles, ,
8
+ end
9
+
10
+ sub_modules.each do |name|
11
+ begin
12
+ self.send :include, "TroleGroups::Config::#{name.to_s.camelize}".constantize
13
+ rescue Error => e
14
+ puts "include sub-module #{name}, error: #{e}"
15
+ end
16
+ end
17
+
18
+ attr_accessor :subject_class, :strategy, :log_on, :generic, :auto_relations
19
+ attr_writer :orm
20
+
21
+ def initialize subject_class, options = {}
22
+ @subject_class = subject_class
23
+ # set instance var for each pair in options
24
+ apply_options! options
25
+ end
26
+
27
+ def apply_options! options = {}
28
+ options.each_pair do |key, value|
29
+ send("#{key}=", value) if self.respond_to?(:"#{key}")
30
+ end
31
+ end
32
+
33
+ def configure! options = {}
34
+ apply_options! options
35
+ configure_models if auto_config?(:models)
36
+ end
37
+
38
+ class << self
39
+ attr_reader :default_orm, :auto_load
40
+ attr_accessor :log_on
41
+
42
+ def log_on?
43
+ log_on || false
44
+ end
45
+
46
+ def default_orm= orm
47
+ @default_orm ||= orm
48
+ end
49
+
50
+ def auto_load= mode
51
+ raise "Autoload must be set to true or false" if ![true, false].include? mode
52
+ @auto_load = mode
53
+ end
54
+
55
+ def auto_load?
56
+ @auto_load
57
+ end
58
+
59
+ def auto_config
60
+ auto_config_setings
61
+ end
62
+
63
+ def auto_config? name
64
+ auto_config_setings[name]
65
+ end
66
+
67
+ protected
68
+
69
+
70
+ def auto_config_setings
71
+ @auto_config_setings ||= auto_config_defaults
72
+ end
73
+
74
+ # default auto_config settings
75
+ def auto_config_defaults
76
+ {:models => true, :relations => true, :fields => true}
77
+ end
78
+ end
79
+
80
+ def log_on?
81
+ log_on || Troles::Config.log_on
82
+ end
83
+
84
+ def auto_config
85
+ auto_config_setings
86
+ end
87
+
88
+ def auto_config? name
89
+ return auto_config_setings[name] if !auto_config_setings[name].nil?
90
+ Troles::Config.auto_config?(name)
91
+ end
92
+
93
+
94
+ def auto_config_setings
95
+ @auto_config_setings ||= {}
96
+ end
97
+
98
+ def role_field
99
+ @role_field ||= begin
100
+ default_role_field
101
+ end
102
+ end
103
+ alias_method :rolegroup_field, :role_field
104
+
105
+ def role_field= field_name
106
+ name = field_name.to_s.alpha_numeric.to_sym
107
+ raise ArgumentException, "Not a valid role field name: #{field_name}" if !valid_field_name?(name)
108
+ @role_field ||= name
109
+ end
110
+ alias_method :rolegroup_field=, :role_field=
111
+
112
+ def default_role_field
113
+ :trole_groups
114
+ end
115
+
116
+ def orm
117
+ @orm || self.class.default_orm
118
+ end
119
+
120
+ def singularity
121
+ @singularity ||= (strategy =~ /_many$/) ? :many : :one
122
+ end
123
+
124
+ # def singularity= value
125
+ # raise ArgumentError, "Must be :many or :one" if ![:one, :many].include?(value)
126
+ # @singularity ||= value
127
+ # end
128
+
129
+ def generic?
130
+ return true if orm.nil?
131
+ @generic.nil? ? false : @generic
132
+ end
133
+ end
134
+ end