troles 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -0
- data/Gemfile +26 -0
- data/Gemfile.lock +161 -0
- data/MIT-LICENSE +20 -0
- data/README.textile +686 -0
- data/Rakefile +48 -0
- data/VERSION +1 -0
- data/config/database.yml +4 -0
- data/development.sqlite3 +0 -0
- data/lib/trole/adapters/active_record/config.rb +23 -0
- data/lib/trole/adapters/active_record/storage.rb +0 -0
- data/lib/trole/adapters/active_record/strategy.rb +0 -0
- data/lib/trole/adapters/active_record.rb +8 -0
- data/lib/trole/adapters/mongoid/config.rb +34 -0
- data/lib/trole/adapters/mongoid/storage.rb +0 -0
- data/lib/trole/adapters/mongoid/strategy.rb +0 -0
- data/lib/trole/adapters/mongoid.rb +0 -0
- data/lib/trole/api/cache.rb +9 -0
- data/lib/trole/api/config.rb +12 -0
- data/lib/trole/api/core.rb +20 -0
- data/lib/trole/api/event.rb +9 -0
- data/lib/trole/api/read.rb +14 -0
- data/lib/trole/api/validation.rb +9 -0
- data/lib/trole/api/write.rb +25 -0
- data/lib/trole/api.rb +41 -0
- data/lib/trole/config.rb +15 -0
- data/lib/trole/macros.rb +5 -0
- data/lib/trole/operations/read.rb +12 -0
- data/lib/trole/operations/write.rb +11 -0
- data/lib/trole/operations.rb +34 -0
- data/lib/trole/storage/base_one.rb +46 -0
- data/lib/trole/storage/bit_one.rb +43 -0
- data/lib/trole/storage/embed_one.rb +36 -0
- data/lib/trole/storage/ref_one.rb +39 -0
- data/lib/trole/storage/string_one.rb +50 -0
- data/lib/trole/storage.rb +14 -0
- data/lib/trole/strategy.rb +35 -0
- data/lib/trole.rb +10 -0
- data/lib/troles/adapters/active_record/Design Notes.textile +4 -0
- data/lib/troles/adapters/active_record/config.rb +51 -0
- data/lib/troles/adapters/active_record/storage/embed_many.rb +8 -0
- data/lib/troles/adapters/active_record/storage.rb +5 -0
- data/lib/troles/adapters/active_record/strategy.rb +11 -0
- data/lib/troles/adapters/active_record.rb +8 -0
- data/lib/troles/adapters/mongoid/Design Notes.textile +3 -0
- data/lib/troles/adapters/mongoid/config.rb +45 -0
- data/lib/troles/adapters/mongoid.rb +8 -0
- data/lib/troles/api/cache.rb +4 -0
- data/lib/troles/api/config.rb +9 -0
- data/lib/troles/api/core.rb +9 -0
- data/lib/troles/api/event.rb +4 -0
- data/lib/troles/api/read.rb +4 -0
- data/lib/troles/api/validation.rb +4 -0
- data/lib/troles/api/write.rb +4 -0
- data/lib/troles/api.rb +40 -0
- data/lib/troles/common/api/cache.rb +12 -0
- data/lib/troles/common/api/config.rb +4 -0
- data/lib/troles/common/api/core.rb +52 -0
- data/lib/troles/common/api/event.rb +39 -0
- data/lib/troles/common/api/read.rb +44 -0
- data/lib/troles/common/api/validation.rb +44 -0
- data/lib/troles/common/api/write.rb +76 -0
- data/lib/troles/common/api.rb +28 -0
- data/lib/troles/common/config/schema.rb +72 -0
- data/lib/troles/common/config/schema_helpers.rb +95 -0
- data/lib/troles/common/config/static_roles.rb +14 -0
- data/lib/troles/common/config/valid_roles.rb +21 -0
- data/lib/troles/common/config.rb +96 -0
- data/lib/troles/common/dependencies.rb +9 -0
- data/lib/troles/common/event_manager.rb +40 -0
- data/lib/troles/common/macros/configuration/base_loader.rb +40 -0
- data/lib/troles/common/macros/configuration/config_loader.rb +19 -0
- data/lib/troles/common/macros/configuration/storage_loader.rb +20 -0
- data/lib/troles/common/macros/configuration/strategy_loader.rb +38 -0
- data/lib/troles/common/macros/configuration.rb +89 -0
- data/lib/troles/common/macros/static_roles.rb +9 -0
- data/lib/troles/common/macros/strategy_options.rb +21 -0
- data/lib/troles/common/macros.rb +38 -0
- data/lib/troles/common/marshaller/bitmask.rb +43 -0
- data/lib/troles/common/marshaller/generic.rb +24 -0
- data/lib/troles/common/marshaller.rb +14 -0
- data/lib/troles/common/operations/read.rb +28 -0
- data/lib/troles/common/operations/write.rb +42 -0
- data/lib/troles/common/operations.rb +33 -0
- data/lib/troles/common/storage.rb +73 -0
- data/lib/troles/common.rb +17 -0
- data/lib/troles/config.rb +15 -0
- data/lib/troles/macros.rb +7 -0
- data/lib/troles/meta.rb +5 -0
- data/lib/troles/operations/read.rb +6 -0
- data/lib/troles/operations/write.rb +6 -0
- data/lib/troles/operations.rb +12 -0
- data/lib/troles/storage/base_many.rb +25 -0
- data/lib/troles/storage/bit_many.rb +56 -0
- data/lib/troles/storage/embed_many.rb +58 -0
- data/lib/troles/storage/ref_many.rb +44 -0
- data/lib/troles/storage/string_many.rb +41 -0
- data/lib/troles/storage.rb +13 -0
- data/lib/troles/strategy.rb +34 -0
- data/lib/troles.rb +11 -0
- data/playbox/old_rake +25 -0
- data/spec/Guide to running specs.textile +16 -0
- data/spec/active_record/migrations/many/bit_many.rb +16 -0
- data/spec/active_record/migrations/many/ref_many.rb +31 -0
- data/spec/active_record/migrations/many/string_many.rb +16 -0
- data/spec/active_record/migrations/one/bit_one.rb +14 -0
- data/spec/active_record/migrations/one/ref_one.rb +20 -0
- data/spec/active_record/migrations/one/string_one.rb +14 -0
- data/spec/active_record/models/ref_many.rb +10 -0
- data/spec/active_record/models/ref_one.rb +10 -0
- data/spec/active_record/models/role.rb +2 -0
- data/spec/active_record/models/user.rb +5 -0
- data/spec/active_record/models.rb +2 -0
- data/spec/active_record/strategies/many/bit_many_spec.rb +41 -0
- data/spec/active_record/strategies/many/ref_many_spec.rb +45 -0
- data/spec/active_record/strategies/many/string_many_spec.rb +39 -0
- data/spec/active_record/strategies/one/bit_one_spec.rb +35 -0
- data/spec/active_record/strategies/one/ref_one_spec.rb +41 -0
- data/spec/active_record/strategies/one/string_one_spec.rb +35 -0
- data/spec/active_record/strategy_helper.rb +4 -0
- data/spec/active_record_helper.rb +50 -0
- data/spec/db/database.yml +4 -0
- data/spec/dummy/Gemfile.lock +108 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/images/rails.png +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +9 -0
- data/spec/dummy/app/assets/stylesheets/application.css +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/controllers/main_controller.rb +16 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/ref_many_user.rb +7 -0
- data/spec/dummy/app/models/ref_one_user.rb +3 -0
- data/spec/dummy/app/models/role.rb +4 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/app/views/main/index.html.erb +3 -0
- data/spec/dummy/config/application.rb +54 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +24 -0
- data/spec/dummy/config/environments/production.rb +52 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/troles.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +12 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +60 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/01_create_roles.rb +14 -0
- data/spec/dummy/db/migrate/02_create_ref_many_users.rb +20 -0
- data/spec/dummy/db/schema.rb +32 -0
- data/spec/dummy/db/seeds.rb +4 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy_spec_helper.rb +33 -0
- data/spec/factories.rb +8 -0
- data/spec/generic/models/accounts/admin_account.rb +7 -0
- data/spec/generic/models/accounts/blogger_account.rb +7 -0
- data/spec/generic/models/accounts/user_account.rb +7 -0
- data/spec/generic/models/accounts.rb +1 -0
- data/spec/generic/models/base_user.rb +27 -0
- data/spec/generic/models/role.rb +37 -0
- data/spec/generic/models/user.rb +7 -0
- data/spec/generic/models.rb +3 -0
- data/spec/integration/navigation_spec.rb +9 -0
- data/spec/integration/troles/Running dummy tests.textile +35 -0
- data/spec/integration/troles/navigation_spec.rb +49 -0
- data/spec/mongoid/models/ref_many.rb +15 -0
- data/spec/mongoid/models/ref_one.rb +15 -0
- data/spec/mongoid/models/role.rb +5 -0
- data/spec/mongoid/models/user.rb +9 -0
- data/spec/mongoid/models.rb +2 -0
- data/spec/mongoid/strategies/many/bit_many_spec.rb +35 -0
- data/spec/mongoid/strategies/many/ref_many_spec.rb +35 -0
- data/spec/mongoid/strategies/many/string_many_spec.rb +30 -0
- data/spec/mongoid/strategies/one/bit_one_spec.rb +26 -0
- data/spec/mongoid/strategies/one/ref_one_spec.rb +31 -0
- data/spec/mongoid/strategies/one/string_one_spec.rb +26 -0
- data/spec/mongoid/strategy_helper.rb +4 -0
- data/spec/mongoid_helper.rb +19 -0
- data/spec/playbox/rspec_examples.rb +381 -0
- data/spec/support/shared_examples.rb +1 -0
- data/spec/trole/Trole Design.textile +4 -0
- data/spec/trole/api/cache_api_spec.rb +2 -0
- data/spec/trole/api/core_api_spec.rb +4 -0
- data/spec/trole/api/event_api.rb +2 -0
- data/spec/trole/api/operations_api_spec.rb +2 -0
- data/spec/trole/api/read_api_spec.rb +5 -0
- data/spec/trole/api/validation_api_spec.rb +2 -0
- data/spec/trole/api/write_api_spec.rb +2 -0
- data/spec/trole/api_spec.rb +60 -0
- data/spec/trole/multi_roles_spec.rb +163 -0
- data/spec/trole/operations/read_spec.rb +18 -0
- data/spec/trole/operations/write_spec.rb +0 -0
- data/spec/trole/playbox/shared_examples.rb +107 -0
- data/spec/trole/strategies/bit_one_spec.rb +22 -0
- data/spec/trole/strategies/embed_one_spec.rb +32 -0
- data/spec/trole/strategies/ref_one_spec.rb +29 -0
- data/spec/trole/strategies/string_one_spec.rb +26 -0
- data/spec/trole/strategy_helper.rb +3 -0
- data/spec/trole/two_roles_spec.rb +76 -0
- data/spec/trole_spec.rb +12 -0
- data/spec/trole_spec_helper.rb +20 -0
- data/spec/troles/api/cache_api_spec.rb +2 -0
- data/spec/troles/api/core_api_spec.rb +4 -0
- data/spec/troles/api/event_api.rb +2 -0
- data/spec/troles/api/read_api_spec.rb +2 -0
- data/spec/troles/api/validation_api_spec.rb +2 -0
- data/spec/troles/api/write_api_spec.rb +2 -0
- data/spec/troles/api_spec.rb +41 -0
- data/spec/troles/common/api/cache_api_spec.rb +31 -0
- data/spec/troles/common/api/config_api.rb +0 -0
- data/spec/troles/common/api/core_api_spec.rb +14 -0
- data/spec/troles/common/api/event_api_spec.rb +9 -0
- data/spec/troles/common/api/operations_api_spec.rb +55 -0
- data/spec/troles/common/api/read_api_spec.rb +23 -0
- data/spec/troles/common/api/validation_api_spec.rb +46 -0
- data/spec/troles/common/api/write_api_spec.rb +81 -0
- data/spec/troles/common/api_spec.rb +101 -0
- data/spec/troles/common/config_spec.rb +11 -0
- data/spec/troles/common/multi_roles_spec.rb +142 -0
- data/spec/troles/marshaller/bitmask_spec.rb +14 -0
- data/spec/troles/operations/read_ops_spec.rb +0 -0
- data/spec/troles/operations/write_ops_spec.rb +0 -0
- data/spec/troles/playbox/shared_examples.rb +68 -0
- data/spec/troles/strategies/bit_many_spec.rb +30 -0
- data/spec/troles/strategies/embed_many_spec.rb +35 -0
- data/spec/troles/strategies/ref_many_spec.rb +36 -0
- data/spec/troles/strategies/string_many_spec.rb +32 -0
- data/spec/troles/strategy_helper.rb +3 -0
- data/spec/troles_spec.rb +10 -0
- data/troles.gemspec +325 -0
- metadata +469 -0
@@ -0,0 +1,95 @@
|
|
1
|
+
module Troles::Common
|
2
|
+
class Config
|
3
|
+
module SchemaHelpers
|
4
|
+
def valid_field_name? name
|
5
|
+
return false if !name || name.empty?
|
6
|
+
raise ArgumentException, "Role field must not be named role or roles as these names are reserved by troles!" if [:role, :roles].include? name.to_sym
|
7
|
+
true
|
8
|
+
end
|
9
|
+
|
10
|
+
def boolean? value
|
11
|
+
[true, false].include? value
|
12
|
+
end
|
13
|
+
|
14
|
+
# TODO: Needs extraction into helper module!
|
15
|
+
|
16
|
+
def belongs_to_for from, to, options = {}
|
17
|
+
make_relationship :belongs_to, from, to, options
|
18
|
+
end
|
19
|
+
|
20
|
+
def has_many_for from, to, options = {}
|
21
|
+
make_relationship :has_many, from, to, options
|
22
|
+
end
|
23
|
+
|
24
|
+
def has_one_for from, to, options = {}
|
25
|
+
make_relationship :has_one, from, to, options
|
26
|
+
end
|
27
|
+
|
28
|
+
# To setup sth like this:
|
29
|
+
#
|
30
|
+
# class UserAccount < ActiveRecord::Base
|
31
|
+
# has_and_belongs_to_many :troles, :class_name => 'Role'
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# class Role < ActiveRecord::Base
|
35
|
+
# has_and_belongs_to_many :user_accounts, :class_name => 'User'
|
36
|
+
# end
|
37
|
+
def has_and_belongs_many from, to, options = {}
|
38
|
+
make_relationship :has_and_belongs_to_many, from, to, :key => role_field
|
39
|
+
make_relationship :has_and_belongs_to_many, to, from, options
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_model_type class_name
|
43
|
+
return :user if class_name == clazz
|
44
|
+
return :role if class_name == role_model
|
45
|
+
raise "Not a known model: #{class_name}"
|
46
|
+
end
|
47
|
+
|
48
|
+
# options:
|
49
|
+
# - :opts, extras options, fx to set the :through relationship
|
50
|
+
# - :key (usually to enforce use of role_field as key name)
|
51
|
+
def make_relationship type, from, to, options = {}
|
52
|
+
# puts "type: #{type}, #{from}, #{to}"
|
53
|
+
from_type = get_model_type from
|
54
|
+
to_type = get_model_type to
|
55
|
+
|
56
|
+
model_key = options[:key] ? options[:key] : send("#{from_type}_key")
|
57
|
+
|
58
|
+
class_name = send "#{to_type}_class_name"
|
59
|
+
|
60
|
+
options = {:class_name => class_name}
|
61
|
+
options.merge!(options[:opts]) if options[:opts]
|
62
|
+
puts "#{from}.#{type} :#{model_key}, #{options.inspect}" if log_on?
|
63
|
+
from.send(type, model_key, options)
|
64
|
+
end
|
65
|
+
|
66
|
+
def user_class_name
|
67
|
+
clazz.to_s
|
68
|
+
end
|
69
|
+
|
70
|
+
def user_key
|
71
|
+
make_key user_class_name
|
72
|
+
end
|
73
|
+
|
74
|
+
def join_class_name
|
75
|
+
join_model.to_s
|
76
|
+
end
|
77
|
+
|
78
|
+
def join_key
|
79
|
+
make_key join_class_name
|
80
|
+
end
|
81
|
+
|
82
|
+
def role_class_name
|
83
|
+
role_model.to_s
|
84
|
+
end
|
85
|
+
|
86
|
+
def role_key
|
87
|
+
make_key role_class_name
|
88
|
+
end
|
89
|
+
|
90
|
+
def make_key name
|
91
|
+
name.gsub(/::/, '__').underscore.pluralize
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Troles::Common
|
2
|
+
class Config
|
3
|
+
module StaticRoles
|
4
|
+
def static_roles_for_class= value
|
5
|
+
raise ArgumentError, "Must be a boolean" if !boolean?(value)
|
6
|
+
@static_roles_for_class = value
|
7
|
+
end
|
8
|
+
|
9
|
+
def static_roles_for_class?
|
10
|
+
@static_roles_for_class || false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Troles::Common
|
2
|
+
class Config
|
3
|
+
module ValidRoles
|
4
|
+
def add_valid_roles *roles
|
5
|
+
valid_roles =valid_roles & roles
|
6
|
+
end
|
7
|
+
|
8
|
+
def valid_roles= *roles
|
9
|
+
vrs = roles.flatten.map{|r| r.to_s.alpha_numeric}.map(&:to_sym).uniq
|
10
|
+
raise ArgumentError, "The #{strategy} strategy can only accept 2 valid roles" if (vrs.size > 2) && strategy == :bit_one
|
11
|
+
raise ArgumentError, "The role names you want to be valid are not valid role names. Must be alphanumeric, was: #{roles.flatten}" if vrs.empty?
|
12
|
+
@valid_roles ||= vrs
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_roles
|
16
|
+
raise "No valid roles defined" if !@valid_roles || @valid_roles.empty?
|
17
|
+
@valid_roles
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Troles::Common
|
2
|
+
class Config
|
3
|
+
autoload :ValidRoles, 'troles/common/config/valid_roles'
|
4
|
+
autoload :StaticRoles, 'troles/common/config/static_roles'
|
5
|
+
autoload :Schema, 'troles/common/config/schema'
|
6
|
+
autoload :SchemaHelpers, 'troles/common/config/schema_helpers'
|
7
|
+
|
8
|
+
def self.sub_modules
|
9
|
+
[:valid_roles, :static_roles, :schema]
|
10
|
+
end
|
11
|
+
|
12
|
+
sub_modules.each do |name|
|
13
|
+
send :include, "Troles::Common::Config::#{name.to_s.camelize}".constantize
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_accessor :clazz, :strategy, :log_on, :generic
|
17
|
+
attr_writer :orm
|
18
|
+
|
19
|
+
def initialize clazz, options = {}
|
20
|
+
@clazz = clazz
|
21
|
+
# set instance var for each pair in options
|
22
|
+
apply_options! options
|
23
|
+
end
|
24
|
+
|
25
|
+
class << self
|
26
|
+
attr_reader :default_orm, :auto_load
|
27
|
+
attr_accessor :log_on
|
28
|
+
|
29
|
+
def log_on?
|
30
|
+
log_on || false
|
31
|
+
end
|
32
|
+
|
33
|
+
def default_orm= orm
|
34
|
+
@default_orm ||= orm
|
35
|
+
end
|
36
|
+
|
37
|
+
def auto_load= mode
|
38
|
+
raise "Autoload must be set to true or false" if ![true, false].include? mode
|
39
|
+
@auto_load = mode
|
40
|
+
end
|
41
|
+
|
42
|
+
def auto_load?
|
43
|
+
@auto_load
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def log_on?
|
48
|
+
log_on || Troles::Config.log_on
|
49
|
+
end
|
50
|
+
|
51
|
+
def role_field
|
52
|
+
@role_field ||= begin
|
53
|
+
default_role_field
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def role_field= field_name
|
58
|
+
name = field_name.to_s.alpha_numeric.to_sym
|
59
|
+
raise ArgumentException, "Not a valid role field name: #{field_name}" if !valid_field_name?(name)
|
60
|
+
@role_field ||= name
|
61
|
+
end
|
62
|
+
|
63
|
+
def default_role_field
|
64
|
+
singularity == :many ? :troles : :trole
|
65
|
+
end
|
66
|
+
|
67
|
+
def orm
|
68
|
+
@orm || self.class.default_orm
|
69
|
+
end
|
70
|
+
|
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
|
+
def singularity
|
78
|
+
@singularity ||= (strategy =~ /_many$/) ? :many : :one
|
79
|
+
end
|
80
|
+
|
81
|
+
# def singularity= value
|
82
|
+
# raise ArgumentError, "Must be :many or :one" if ![:one, :many].include?(value)
|
83
|
+
# @singularity ||= value
|
84
|
+
# end
|
85
|
+
|
86
|
+
def configure! options = {}
|
87
|
+
apply_options! options
|
88
|
+
configure_role_field
|
89
|
+
end
|
90
|
+
|
91
|
+
def generic?
|
92
|
+
return true if orm.nil?
|
93
|
+
@generic.nil? ? false : @generic
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#
|
2
|
+
# @author Kristian Mandrup
|
3
|
+
#
|
4
|
+
# Handles event handlinm/publication for when the roles of a role subject change
|
5
|
+
# This is currently a singleton (class methods only) by design
|
6
|
+
#
|
7
|
+
module Troles::Common
|
8
|
+
module EventManager
|
9
|
+
def self.included(base)
|
10
|
+
base.extend ClassMethods
|
11
|
+
end
|
12
|
+
|
13
|
+
# TODO:
|
14
|
+
module ClassMethods
|
15
|
+
attr_accessor :subscribers
|
16
|
+
|
17
|
+
def subscribers
|
18
|
+
@subscribers ||= []
|
19
|
+
end
|
20
|
+
|
21
|
+
def publish_change event, options
|
22
|
+
# from = options[:from]
|
23
|
+
subscribers.each do |subscriber|
|
24
|
+
subscriber.notify(event) if subscriber.respond_to?(:notify)
|
25
|
+
end
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_subscribers subscribers
|
30
|
+
self.subscribers << subscribers
|
31
|
+
end
|
32
|
+
|
33
|
+
def remove_subscribers subscribers
|
34
|
+
self.subscribers - subscribers
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
extend ClassMethods
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Troles::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 singularity
|
12
|
+
(strategy =~ /_many$/) ? :many : :one
|
13
|
+
end
|
14
|
+
|
15
|
+
def try_module full_name
|
16
|
+
begin
|
17
|
+
full_name.constantize
|
18
|
+
true
|
19
|
+
rescue
|
20
|
+
# puts "module #{full_name} not found!"
|
21
|
+
false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def base_class
|
26
|
+
"Base#{singularity.to_s.camelize}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def namespace
|
30
|
+
singularity == :many ? 'Troles' : 'Trole'
|
31
|
+
end
|
32
|
+
|
33
|
+
def orm_namespace
|
34
|
+
ns = namespace
|
35
|
+
ns << "::#{orm.to_s.camelize}" if orm
|
36
|
+
ns
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Troles::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 Troles::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 Troles::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,89 @@
|
|
1
|
+
module Troles
|
2
|
+
module Macros
|
3
|
+
class Configuration
|
4
|
+
autoload :BaseLoader, 'troles/common/macros/configuration/base_loader'
|
5
|
+
autoload :ConfigLoader, 'troles/common/macros/configuration/config_loader'
|
6
|
+
autoload :StrategyLoader, 'troles/common/macros/configuration/strategy_loader'
|
7
|
+
autoload :StorageLoader, 'troles/common/macros/configuration/storage_loader'
|
8
|
+
|
9
|
+
attr_reader :strategy, :singularity, :orm, :auto_load, :options, :role_subject_class
|
10
|
+
|
11
|
+
def initialize role_subject_class, strategy, options = {}
|
12
|
+
@role_subject_class = role_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
|
+
role_subject_class.troles_config.apply_options! options
|
37
|
+
|
38
|
+
# StrategyOptions.new(clazz)
|
39
|
+
# extract_macros(options).each{|m| apply_macro m}
|
40
|
+
end
|
41
|
+
|
42
|
+
def define_hooks
|
43
|
+
storage_class = storage_loader.storage_class
|
44
|
+
role_subject_class.send :define_method, :storage do
|
45
|
+
@storage ||= storage_class
|
46
|
+
end
|
47
|
+
|
48
|
+
config_class = config_loader.config_class
|
49
|
+
puts "config_class: #{config_class}" if Troles::Config.log_on
|
50
|
+
role_subject_class.singleton_class.class_eval %{
|
51
|
+
def troles_config
|
52
|
+
@troles_config ||= #{config_class}.new #{role_subject_class}, #{options.inspect}
|
53
|
+
end
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
protected
|
58
|
+
|
59
|
+
def namespace
|
60
|
+
singularity == :many ? 'troles' : 'trole'
|
61
|
+
end
|
62
|
+
|
63
|
+
def singularity
|
64
|
+
@singularity ||= (strategy =~ /_many$/) ? :many : :one
|
65
|
+
end
|
66
|
+
|
67
|
+
def storage_loader
|
68
|
+
@storage_loader ||= StorageLoader.new strategy, orm
|
69
|
+
end
|
70
|
+
|
71
|
+
def config_loader
|
72
|
+
@config_loader ||= ConfigLoader.new strategy, orm
|
73
|
+
end
|
74
|
+
|
75
|
+
def strategy_loader
|
76
|
+
@strategy_loader ||= StrategyLoader.new strategy, orm
|
77
|
+
end
|
78
|
+
|
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,21 @@
|
|
1
|
+
module Troles
|
2
|
+
module Macros
|
3
|
+
class StrategyOptions
|
4
|
+
attr_reader :clazz
|
5
|
+
|
6
|
+
def initialize clazz
|
7
|
+
@clazz = clazz
|
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
|
+
clazz.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,38 @@
|
|
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 "Troles macros enabled!"
|
13
|
+
|
14
|
+
module Troles
|
15
|
+
module Macros
|
16
|
+
autoload :Configuration, 'troles/common/macros/configuration'
|
17
|
+
|
18
|
+
def troles_strategy strategy, options = {}, &block
|
19
|
+
configuration = Configuration.new self, strategy, options
|
20
|
+
|
21
|
+
configuration.load_adapter
|
22
|
+
# puts "strategy module: #{configuration.strategy_module}"
|
23
|
+
send :include, configuration.strategy_module
|
24
|
+
|
25
|
+
configuration.define_hooks
|
26
|
+
configuration.apply_strategy_options!
|
27
|
+
|
28
|
+
if strategy == :bit_one
|
29
|
+
troles_config.valid_roles = [:user, :admin] # default binary roles
|
30
|
+
end
|
31
|
+
|
32
|
+
yield troles_config if block_given?
|
33
|
+
troles_config
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Module.send :include, Troles::Macros
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# require 'troles/common/marshaller/generic'
|
2
|
+
|
3
|
+
module Troles::Common
|
4
|
+
module Marshaller
|
5
|
+
class Bitmask < Generic
|
6
|
+
attr_reader :role_subject, :valid_roles
|
7
|
+
|
8
|
+
def initialize role_subject
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def read
|
13
|
+
valid_roles.reject do |r|
|
14
|
+
num = as_number(ds_field_value)
|
15
|
+
((num || 0) & calc_index(r)).zero?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def write *roles
|
20
|
+
roles = roles.uniq.compact
|
21
|
+
return as_number(false) if roles.empty?
|
22
|
+
roles.to_symbols.map { |r| calc_index(r) }.inject { |sum, bitvalue| sum + bitvalue }
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def as_number value
|
28
|
+
case value
|
29
|
+
when TrueClass, FalseClass
|
30
|
+
value ? 2 : 1
|
31
|
+
when Fixnum
|
32
|
+
value
|
33
|
+
else
|
34
|
+
raise ArgumentError, "Cant be converted to a bit index, #{value}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def calc_index(r)
|
39
|
+
2**valid_roles.index(r)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Troles::Common
|
2
|
+
module Marshaller
|
3
|
+
class Generic
|
4
|
+
attr_reader :role_subject, :valid_roles
|
5
|
+
|
6
|
+
def initialize role_subject
|
7
|
+
raise "The roles subject is not valid: #{role_subject}" if !role_subject || !role_subject.respond_to?(:has_role?)
|
8
|
+
@role_subject = role_subject
|
9
|
+
@valid_roles = role_subject.class.valid_roles
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def ds_field_value
|
15
|
+
role_subject.send ds_field_name
|
16
|
+
end
|
17
|
+
|
18
|
+
def ds_field_name
|
19
|
+
@ds_field_name ||= role_subject.class.role_field
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#
|
2
|
+
# @author Kristian Mandrup
|
3
|
+
#
|
4
|
+
# Marshallers can be used by Storages to handle conversion from
|
5
|
+
# between a role list of symbols and the data format stored in the datastore
|
6
|
+
# One example is the Bitmask marshaller, which converts between an Integer and a role list
|
7
|
+
# One could imagine other custom marshallers, such as using encrypted strings etc.
|
8
|
+
#
|
9
|
+
module Troles::Common
|
10
|
+
module Marshaller
|
11
|
+
autoload :Generic, 'troles/common/marshaller/generic'
|
12
|
+
autoload :Bitmask, 'troles/common/marshaller/bitmask'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Troles::Common
|
2
|
+
class Operations
|
3
|
+
module Read
|
4
|
+
# The roles list of the role subject
|
5
|
+
# @return [Array<Symbol>] the list of roles
|
6
|
+
def list
|
7
|
+
role_subject.role_list
|
8
|
+
end
|
9
|
+
|
10
|
+
# Test if the role subject has exactly the given roles
|
11
|
+
# @param [Array<Symbol>] role list to test
|
12
|
+
# @return [true, false] true if role subject has exactly those roles, false otherwise
|
13
|
+
def has? *roles
|
14
|
+
list == roles.to_symbols_uniq
|
15
|
+
end
|
16
|
+
|
17
|
+
# Which of the given roles are used by the role subject
|
18
|
+
# @param [Array<Symbol>] roles to test for inclusion
|
19
|
+
#
|
20
|
+
# Usage:
|
21
|
+
# - user.roles.used(:admin, :editor).include? :editor
|
22
|
+
#
|
23
|
+
def used *roles
|
24
|
+
list & roles.to_symbols_uniq
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|