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,65 @@
1
+ module TroleGroups
2
+ class Config
3
+ module Schema
4
+ autoload :Helpers, 'trole_groups/config/schema/helpers'
5
+ autoload :RoleGroupHelpers, 'trole_groups/config/schema/role_group_helpers'
6
+
7
+ def configure_models
8
+ configure_generic
9
+ configure_field if auto_config?(:fields)
10
+ configure_relation if auto_config?(:relations)
11
+ end
12
+
13
+ def configure_generic
14
+ subject_class.send(:attr_accessor, role_field) if generic? || orm == :generic # create troles accessor
15
+ end
16
+
17
+ # Adapter should customize this as needed
18
+ def configure_field
19
+ end
20
+
21
+ # Adapter should customize this as needed
22
+ def configure_relation
23
+ end
24
+
25
+ # Sets the role model to use
26
+ # allows different role subject classes (fx User Accounts) to have different role schemas
27
+ # @param [Class] the model class
28
+ def rolegroup_model= model_class
29
+ @rolegroup_model = model_class.to_s and return if model_class.any_kind_of?(Class, String, Symbol)
30
+ raise "The rolegroup model must be a Class, was: #{model_class}"
31
+ end
32
+
33
+ # Gets the role model to be used
34
+ # see (#role_model=)
35
+ # @return [Class] the model class (defaults to Role)
36
+ def rolegroup_model
37
+ @rolegroup_model_found ||= begin
38
+ models = [@rolegroup_model, role_group_class_name].select do |class_name|
39
+ try_class(class_name.to_s.camelize)
40
+ end.compact
41
+ raise "No #{role_group_class_name} class defined, define a #{role_group_class_name} class or set which class to use, using the :rolegroup_model option on configuration" if models.empty?
42
+ models.first.to_s.constantize
43
+ end
44
+ end
45
+
46
+ protected
47
+
48
+ def role_group_class_name
49
+ 'RoleGroup'
50
+ end
51
+
52
+ def try_class clazz
53
+ begin
54
+ clazz = clazz.constantize if clazz.kind_of?(String)
55
+ clazz
56
+ rescue
57
+ false
58
+ end
59
+ end
60
+
61
+ include Helpers
62
+ include RoleGroupHelpers
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,11 @@
1
+ module TroleGroups
2
+ class Config
3
+ module Schema
4
+ module Helpers
5
+ def self.included(base)
6
+ # base.send :include, Troles::Common::Config::Schema::Helpers
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module TroleGroups
2
+ class Config
3
+ module Schema
4
+ module RoleGroupHelpers
5
+ def rolegroup_class_name
6
+ rolegroup_model.to_s
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ module TroleGroups
2
+ class Config
3
+ module ValidRoleGroups
4
+ def add_valid_rolegroups *rolegroups
5
+ valid_rolegroups =valid_rolegroups & rolegroups
6
+ end
7
+
8
+ def valid_rolegroups= *rolegroups
9
+ vrs = rolegroups.flatten.map{|r| r.to_s.alpha_numeric}.map(&:to_sym).uniq
10
+ raise ArgumentError, "The #{strategy} strategy can only accept 2 valid rolegroups" if (vrs.size > 2) && strategy == :bit_one
11
+ raise ArgumentError, "The rolegroup names you want to be valid are not valid rolegroup names. Must be alphanumeric, was: #{rolegroups.flatten}" if vrs.empty?
12
+ @valid_rolegroups ||= vrs
13
+ end
14
+
15
+ def valid_rolegroups
16
+ raise "No valid rolegroups defined" if !@valid_rolegroups || @valid_rolegroups.empty?
17
+ @valid_rolegroups
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,42 @@
1
+ #
2
+ # @author Kristian Mandrup
3
+ #
4
+ # Macros that can be used directly on the role subject class
5
+ # These methods are added to the ruby core 'Module' module
6
+ #
7
+ # Usage:
8
+ # class User
9
+ # troles_strategy :bit_many
10
+ #
11
+
12
+ # puts "TroleGroups macros enabled!"
13
+
14
+ module TroleGroups
15
+ module Macros
16
+ autoload :Configuration, 'trole_groups/macros/configuration'
17
+
18
+ def trolegroups_strategy strategy, options = {}, &block
19
+ configuration = Configuration.new self, strategy, options
20
+
21
+ configuration.load_adapter
22
+ # puts "strategy module: #{configuration.strategy_module}"
23
+ begin
24
+ self.send :include, configuration.strategy_module
25
+ rescue
26
+ puts "error loading strategy: #{configuration.strategy_module}"
27
+ end
28
+
29
+ configuration.define_hooks
30
+ configuration.apply_strategy_options!
31
+
32
+ if strategy == :bit_one
33
+ trolegroups_config.valid_roles = [:user, :admin] # default binary roles
34
+ end
35
+
36
+ yield trolegroups_config if block_given?
37
+ trolegroups_config
38
+ end
39
+ end
40
+ end
41
+
42
+ Module.send :include, TroleGroups::Macros
@@ -0,0 +1,89 @@
1
+ module TroleGroups
2
+ module Macros
3
+ class Configuration
4
+ autoload :BaseLoader, 'trole_groups/macros/configuration/base_loader'
5
+ autoload :ConfigLoader, 'trole_groups/macros/configuration/config_loader'
6
+ autoload :StrategyLoader, 'trole_groups/macros/configuration/strategy_loader'
7
+ autoload :StorageLoader, 'trole_groups/macros/configuration/storage_loader'
8
+
9
+ attr_reader :strategy, :singularity, :orm, :auto_load, :options, :subject_class
10
+
11
+ def initialize subject_class, strategy, options = {}
12
+ @subject_class = subject_class
13
+ @strategy = strategy
14
+ @orm = options[:orm] || Troles::Config.default_orm
15
+ @auto_load = options[:auto_load] || Troles::Config.auto_load?
16
+ options[:strategy] = strategy
17
+ @options = options
18
+ end
19
+
20
+ def strategy_module
21
+ strategy_loader.strategy_module
22
+ end
23
+
24
+ def load_adapter
25
+ return false if !auto_load?
26
+
27
+ path = "#{namespace}/adapters/#{orm.to_s.underscore}"
28
+ begin
29
+ require path
30
+ rescue
31
+ raise "Adapter for :#{orm} could not be found at: #{path}"
32
+ end
33
+ end
34
+
35
+ def apply_strategy_options!
36
+ trolegroups_config.apply_options! options
37
+
38
+ # StrategyOptions.new(subject_class)
39
+ # extract_macros(options).each{|m| apply_macro m}
40
+ end
41
+
42
+ def trolegroups_config
43
+ subject_class.trolegroups_config
44
+ end
45
+
46
+ def define_hooks
47
+ storage_class = storage_loader.storage_class
48
+ # puts "storage_class: #{storage_class}"
49
+ subject_class.send :define_method, :group_storage do
50
+ @group_storage ||= storage_class
51
+ end
52
+
53
+ config_class = config_loader.config_class
54
+ puts "config_class: #{config_class}" if Troles::Config.log_on
55
+ subject_class.singleton_class.class_eval %{
56
+ def trolegroups_config
57
+ @trolegroups_config ||= #{config_class}.new #{subject_class}, #{options.inspect}
58
+ end
59
+ }
60
+ end
61
+
62
+ protected
63
+
64
+ def namespace
65
+ 'trole_groups'
66
+ end
67
+
68
+ def storage_loader
69
+ @storage_loader ||= StorageLoader.new strategy, orm
70
+ end
71
+
72
+ def config_loader
73
+ @config_loader ||= ConfigLoader.new strategy, orm
74
+ end
75
+
76
+ def strategy_loader
77
+ @strategy_loader ||= StrategyLoader.new strategy, orm
78
+ end
79
+
80
+ def auto_load?
81
+ (auto_load && orm) || false
82
+ end
83
+
84
+ # def extract_macros options = {}
85
+ # [:static_role].select {|o| options[o]}
86
+ # end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,35 @@
1
+ module TroleGroups::Macros
2
+ class Configuration
3
+ class BaseLoader
4
+ attr_reader :strategy, :orm
5
+
6
+ def initialize strategy, orm
7
+ @strategy = strategy
8
+ @orm = orm || Troles::Config.default_orm
9
+ end
10
+
11
+ def try_module full_name
12
+ begin
13
+ full_name.constantize
14
+ true
15
+ rescue
16
+ false
17
+ end
18
+ end
19
+
20
+ def base_class
21
+ "BaseMany"
22
+ end
23
+
24
+ def namespace
25
+ 'TroleGroups'
26
+ end
27
+
28
+ def orm_namespace
29
+ ns = namespace
30
+ ns << "::#{orm.to_s.camelize}" if orm
31
+ ns
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,19 @@
1
+ module TroleGroups::Macros
2
+ class Configuration
3
+ class ConfigLoader < BaseLoader
4
+
5
+ def initialize strategy, orm
6
+ super
7
+ end
8
+
9
+ def config_class
10
+ begin
11
+ "#{orm_namespace}::Config".constantize
12
+ rescue
13
+ # use generic if no ORM specific strategy found!
14
+ "#{namespace}::Config".constantize
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ module TroleGroups::Macros
2
+ class Configuration
3
+ class StorageLoader < BaseLoader
4
+
5
+ def initialize strategy, orm
6
+ super
7
+ end
8
+
9
+ def storage_class
10
+ begin
11
+ "#{orm_namespace}::Storage::#{strategy.to_s.camelize}".constantize
12
+ rescue
13
+ # use generic if no ORM specific strategy found!
14
+ "#{namespace}::Storage::#{strategy.to_s.camelize}".constantize
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,38 @@
1
+ module TroleGroups::Macros
2
+ class Configuration
3
+ class StrategyLoader < BaseLoader
4
+
5
+ def initialize strategy, orm
6
+ super
7
+ end
8
+
9
+ def strategy_module
10
+ @strategy_module ||= orm_strategy_module || generic_strategy_module
11
+ end
12
+
13
+ protected
14
+
15
+ def orm_strategy_module
16
+ @orm_strategy_module ||= begin
17
+ mods_found = ["#{orm_namespace}::Strategy::#{strategy.to_s.camelize}", "#{namespace}::Strategy::#{base_class}"].select do |full_name|
18
+ try_module(full_name)
19
+ end
20
+ !mods_found.empty? ? mods_found.first.constantize : nil
21
+ end
22
+ end
23
+
24
+ def generic_strategy_module strategy_name, options
25
+ @generic_module ||= begin
26
+ base_class = base_name(strategy_name)
27
+
28
+ # use generic if no ORM specific strategy found!
29
+ ns = namespace(strategy_name, options)
30
+ mods_found = ["#{namespace}::Strategy::#{strategy.to_s.camelize}", "#{namespace}::Strategy::#{base_class}"].select do |full_name|
31
+ try_module(full_name)
32
+ end
33
+ !mods_found.empty? ? mods_found.first.constantize : nil
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,9 @@
1
+ module TroleGroups
2
+ module Macros
3
+ module StaticRoleGroups
4
+ def static_rolegroups?
5
+ true
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ module Troles
2
+ module Macros
3
+ class StrategyOptions
4
+ attr_reader :subject_class
5
+
6
+ def initialize subject_class
7
+ @subject_class = subject_class
8
+ end
9
+
10
+ # @param [Symbol] name of the macro to run
11
+ def apply_macro name
12
+ # overrides default method that returns false
13
+ begin
14
+ subject_class.send :include, "Troles::Macros::#{strategy_name.to_s.camelize}".constantize
15
+ rescue
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,25 @@
1
+ module TroleGroups
2
+ class Operations # < Troles::Common::Operations
3
+ autoload :Read, 'trole_groups/operations/read'
4
+ autoload :Write, 'trole_groups/operations/write'
5
+
6
+ include Read
7
+ include Write
8
+
9
+ include Enumerable
10
+
11
+ attr_reader :rolegroup_subject
12
+
13
+ # constructor
14
+ # @param [Object] the role subject, fx a User or UserAccount
15
+ def initialize rolegroup_subject
16
+ @rolegroup_subject = rolegroup_subject
17
+ end
18
+
19
+ # required method to act as enumerable
20
+ # iterates and yields all roles in the role list (Symbols)
21
+ def each
22
+ list.each { |rolegroup| yield rolegroup }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ module TroleGroups
2
+ class Operations
3
+ module Read
4
+ def roles
5
+
6
+ end
7
+
8
+ def roles_for *names
9
+ rolegroup_subject.roles_for *names
10
+ end
11
+
12
+ # The roles list of the role subject
13
+ # @return [Array<Symbol>] the list of roles
14
+ def list
15
+ rolegroup_subject.rolegroup_list
16
+ end
17
+
18
+ # Test if the role subject has exactly the given roles
19
+ # @param [Array<Symbol>] role list to test
20
+ # @return [true, false] true if role subject has exactly those roles, false otherwise
21
+ def has? *rolegroups
22
+ list == rolegroups.to_symbols_uniq
23
+ end
24
+
25
+ # Which of the given roles are used by the role subject
26
+ # @param [Array<Symbol>] roles to test for inclusion
27
+ #
28
+ # Usage:
29
+ # - user.roles.used(:admin, :editor).include? :editor
30
+ #
31
+ def used *rolegroups
32
+ list & rolegroups.to_symbols_uniq
33
+ end
34
+ end
35
+ end
36
+ end