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,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