troles 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/README.textile +75 -16
- data/VERSION +1 -1
- data/lib/trole/adapters/active_record/config.rb +3 -3
- data/lib/trole/adapters/mongoid/config.rb +5 -5
- data/lib/trole/config.rb +2 -2
- data/lib/trole_groups.rb +10 -0
- data/lib/trole_groups/READ THIS.textile +4 -0
- data/lib/trole_groups/Rolegroups design.textile +218 -0
- data/lib/trole_groups/adapters/active_record.rb +8 -0
- data/lib/trole_groups/adapters/active_record/config.rb +0 -0
- data/lib/trole_groups/adapters/active_record/storage.rb +0 -0
- data/lib/trole_groups/adapters/active_record/strategy.rb +11 -0
- data/lib/trole_groups/adapters/mongoid.rb +8 -0
- data/lib/trole_groups/adapters/mongoid/config.rb +0 -0
- data/lib/trole_groups/api.rb +29 -0
- data/lib/trole_groups/api/cache.rb +13 -0
- data/lib/trole_groups/api/config.rb +4 -0
- data/lib/trole_groups/api/core.rb +50 -0
- data/lib/trole_groups/api/event.rb +29 -0
- data/lib/trole_groups/api/read.rb +56 -0
- data/lib/trole_groups/api/validation.rb +44 -0
- data/lib/trole_groups/api/write.rb +60 -0
- data/lib/trole_groups/config.rb +134 -0
- data/lib/trole_groups/config/schema.rb +65 -0
- data/lib/trole_groups/config/schema/helpers.rb +11 -0
- data/lib/trole_groups/config/schema/role_group_helpers.rb +11 -0
- data/lib/trole_groups/config/valid_role_groups.rb +21 -0
- data/lib/trole_groups/macros.rb +42 -0
- data/lib/trole_groups/macros/configuration.rb +89 -0
- data/lib/trole_groups/macros/configuration/base_loader.rb +35 -0
- data/lib/trole_groups/macros/configuration/config_loader.rb +19 -0
- data/lib/trole_groups/macros/configuration/storage_loader.rb +20 -0
- data/lib/trole_groups/macros/configuration/strategy_loader.rb +38 -0
- data/lib/trole_groups/macros/static_roles.rb +9 -0
- data/lib/trole_groups/macros/strategy_options.rb +21 -0
- data/lib/trole_groups/operations.rb +25 -0
- data/lib/trole_groups/operations/read.rb +36 -0
- data/lib/trole_groups/operations/write.rb +42 -0
- data/lib/trole_groups/storage.rb +27 -0
- data/lib/trole_groups/storage/base_many.rb +93 -0
- data/lib/trole_groups/storage/embed_many.rb +58 -0
- data/lib/trole_groups/storage/ref_many.rb +47 -0
- data/lib/trole_groups/strategy.rb +30 -0
- data/lib/troles/adapters/active_record/config.rb +32 -9
- data/lib/troles/adapters/mongoid/config.rb +7 -7
- data/lib/troles/common/api/core.rb +1 -1
- data/lib/troles/common/config.rb +49 -14
- data/lib/troles/common/config/schema.rb +17 -23
- data/lib/troles/common/config/schema/helpers.rb +77 -0
- data/lib/troles/common/config/schema/role_helpers.rb +27 -0
- data/lib/troles/common/config/static_roles.rb +4 -4
- data/lib/troles/common/macros.rb +4 -4
- data/lib/troles/common/macros/configuration.rb +8 -8
- data/lib/troles/common/macros/strategy_options.rb +4 -4
- data/lib/troles/common/storage.rb +1 -0
- data/lib/troles/config.rb +2 -2
- data/lib/troles/storage/ref_many.rb +2 -3
- data/spec/active_record/models/ref_many.rb +3 -0
- data/spec/active_record/strategies/many/ref_many_spec.rb +2 -1
- data/spec/generic/models/role.rb +2 -1
- data/spec/trole_groups/api/core_api_spec.rb +14 -0
- data/spec/trole_groups/api/read_api_spec.rb +36 -0
- data/spec/trole_groups/api/write_api_spec.rb +19 -0
- data/spec/trole_groups/api_spec.rb +27 -0
- data/spec/trole_groups/generic/models.rb +3 -0
- data/spec/trole_groups/generic/models/role_group.rb +44 -0
- data/spec/trole_groups/generic/models/user.rb +9 -0
- data/spec/trole_groups/strategies/ref_many.rb +51 -0
- data/spec/trole_groups/strategy_helper.rb +9 -0
- data/spec/trole_groups_spec.rb +11 -0
- data/spec/trole_spec_helper.rb +9 -0
- data/spec/troles/api_spec.rb +12 -18
- data/troles.gemspec +52 -4
- metadata +85 -37
- data/development.sqlite3 +0 -0
- 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,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,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
|