troles 0.5.0
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.
- 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
|