foobara 0.0.82 → 0.0.85
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/projects/builtin_types/src/datetime/casters/seconds_since_epoch.rb +2 -2
- data/projects/command/src/transformed_command.rb +26 -7
- data/projects/command_connectors/src/command_connector.rb +10 -2
- data/projects/command_connectors/src/command_registry/exposed_command.rb +19 -20
- data/projects/command_connectors/src/command_registry/exposed_domain.rb +8 -13
- data/projects/command_connectors/src/command_registry/exposed_organization.rb +7 -12
- data/projects/command_connectors/src/command_registry.rb +25 -6
- data/projects/command_connectors/src/serializers/aggregate_serializer.rb +1 -1
- data/projects/detached_entity/lib/foobara/detached_entity.rb +1 -0
- data/projects/detached_entity/src/sensitive_value_removers/detached_entity.rb +8 -0
- data/projects/entity/lib/foobara/entity.rb +1 -0
- data/projects/entity/src/sensitive_value_removers/entity.rb +20 -0
- data/projects/manifest/src/foobara/manifest/type_declaration.rb +5 -1
- data/projects/model/lib/foobara/model.rb +5 -0
- data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/model_class_desugarizer.rb +4 -0
- data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/to_type_transformer.rb +42 -11
- data/projects/model/src/sensitive_value_removers/model.rb +23 -0
- data/projects/namespace/src/is_namespace.rb +5 -3
- data/projects/persistence/src/entity_base/transaction.rb +1 -1
- data/projects/type_declarations/lib/foobara/type_declarations.rb +2 -0
- data/projects/type_declarations/src/remove_sensitive_values_transformer.rb +45 -0
- data/projects/type_declarations/src/sensitive_value_removers/array.rb +30 -0
- data/projects/type_declarations/src/sensitive_value_removers/attributes.rb +35 -0
- data/projects/type_declarations/src/type_declarations.rb +22 -0
- data/projects/type_declarations/src/with_registries.rb +5 -0
- data/projects/types/src/type.rb +18 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3447ac0c4910cce965172cfdeaa22c16558bde49b0b0bcd533e2d5dba7b27188
|
4
|
+
data.tar.gz: 67797d30549979ba6ef227d8c61bae996408d598b77edac19b4210a6e4e0edc6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c1b45ecd837fe9f66bb5dcd7d97d3f07dcbb8876a2c913386837378197b4ba0f33fac885283806adf9afea80cef65e3445ce13aff0e491005add424353e2475
|
7
|
+
data.tar.gz: 4270856b98fb68dd813b3bde8e7284995f1293ec0f310122a4d136da4e2c02c094e5110c8e1363b80a8a6d699d0efec49148d4284302494f714e11edbbdd84b6
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
# [0.0.85] - 2025-03-22
|
2
|
+
|
3
|
+
- Add Manifest::TypeDeclaration#sensitive?
|
4
|
+
|
5
|
+
# [0.0.84] - 2025-03-22
|
6
|
+
|
7
|
+
- Remove sensitive values from command connector results
|
8
|
+
- Allow creating models in two different namespace trees and use this is the command connector
|
9
|
+
- Use real domains/orgs in command connectors, eliminating ExposedDomain/Org concept
|
10
|
+
- Allow Datetime to be cast from a float
|
11
|
+
|
1
12
|
# [0.0.82] - 2025-03-21
|
2
13
|
|
3
14
|
- Fix bug incorrectly creating model classes in Foobara::GlobalDomain module
|
@@ -4,11 +4,11 @@ module Foobara
|
|
4
4
|
module Casters
|
5
5
|
class SecondsSinceEpoch < Value::Caster
|
6
6
|
def applicable?(value)
|
7
|
-
value.is_a?(::Integer)
|
7
|
+
value.is_a?(::Integer) || value.is_a?(::Float)
|
8
8
|
end
|
9
9
|
|
10
10
|
def applies_message
|
11
|
-
"be a an integer representing seconds since epoch"
|
11
|
+
"be a an integer or float representing seconds since epoch"
|
12
12
|
end
|
13
13
|
|
14
14
|
def cast(seconds_since_epoch)
|
@@ -19,6 +19,7 @@ module Foobara
|
|
19
19
|
|
20
20
|
def subclass(
|
21
21
|
command_class,
|
22
|
+
scoped_namespace:,
|
22
23
|
full_command_name:,
|
23
24
|
command_name:,
|
24
25
|
inputs_transformers:,
|
@@ -32,6 +33,22 @@ module Foobara
|
|
32
33
|
suffix: nil,
|
33
34
|
capture_unknown_error: false
|
34
35
|
)
|
36
|
+
result_type = command_class.result_type
|
37
|
+
|
38
|
+
if result_type&.has_sensitive_types?
|
39
|
+
remover_class = Foobara::TypeDeclarations.sensitive_value_remover_class_for_type(result_type)
|
40
|
+
|
41
|
+
remover = Namespace.use scoped_namespace do
|
42
|
+
transformed_result_type = result_type_from_transformers(result_type, result_transformers)
|
43
|
+
|
44
|
+
remover_class.new(transformed_result_type).tap do |r|
|
45
|
+
r.scoped_path = ["SensitiveValueRemover", *transformed_result_type.scoped_full_path]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
result_transformers = [*result_transformers, remover]
|
50
|
+
end
|
51
|
+
|
35
52
|
Class.new(self).tap do |klass|
|
36
53
|
klass.command_class = command_class
|
37
54
|
klass.command_name = command_name
|
@@ -67,18 +84,20 @@ module Foobara
|
|
67
84
|
type
|
68
85
|
end
|
69
86
|
|
70
|
-
def result_type
|
71
|
-
|
72
|
-
|
73
|
-
result_transformers.each do |transformer|
|
87
|
+
def result_type_from_transformers(result_type, transformers)
|
88
|
+
Util.array(transformers).each do |transformer|
|
74
89
|
if transformer.is_a?(Class) && transformer < TypeDeclarations::TypedTransformer
|
75
|
-
new_type = transformer.type(
|
90
|
+
new_type = transformer.type(result_type)
|
76
91
|
|
77
|
-
|
92
|
+
result_type = new_type if new_type
|
78
93
|
end
|
79
94
|
end
|
80
95
|
|
81
|
-
|
96
|
+
result_type
|
97
|
+
end
|
98
|
+
|
99
|
+
def result_type
|
100
|
+
result_type_from_transformers(command_class.result_type, result_transformers)
|
82
101
|
end
|
83
102
|
|
84
103
|
def error_context_type_map
|
@@ -357,7 +357,11 @@ module Foobara
|
|
357
357
|
# Drive all of this off of the list of exposed commands...
|
358
358
|
to_include = Set.new
|
359
359
|
|
360
|
-
command_registry.
|
360
|
+
to_include << command_registry.global_organization
|
361
|
+
to_include << command_registry.global_domain
|
362
|
+
|
363
|
+
# ABSOLUTE lets us get all of the children but not include dependent domains (GlobalDomain)
|
364
|
+
command_registry.foobara_each(mode: Namespace::LookupMode::ABSOLUTE) do |exposed_whatever|
|
361
365
|
to_include << exposed_whatever
|
362
366
|
end
|
363
367
|
|
@@ -408,7 +412,11 @@ module Foobara
|
|
408
412
|
|
409
413
|
category_symbol = command_registry.foobara_category_symbol_for(object)
|
410
414
|
|
411
|
-
|
415
|
+
unless category_symbol
|
416
|
+
# :nocov:
|
417
|
+
raise "no category symbol for #{object}"
|
418
|
+
# :nocov:
|
419
|
+
end
|
412
420
|
|
413
421
|
namespace = if object.is_a?(Types::Type)
|
414
422
|
object.created_in_namespace
|
@@ -94,26 +94,7 @@ module Foobara
|
|
94
94
|
@full_command_symbol ||= Util.underscore_sym(full_command_name)
|
95
95
|
end
|
96
96
|
|
97
|
-
def root_registry
|
98
|
-
parent = scoped_namespace
|
99
|
-
parent = parent.scoped_namespace while parent.scoped_namespace
|
100
|
-
parent
|
101
|
-
end
|
102
|
-
|
103
97
|
def foobara_manifest(to_include: Set.new, remove_sensitive: true)
|
104
|
-
# A bit of a hack here. We don't have an exposed type class to encapsulate including exposed domains/orgs
|
105
|
-
# which leads to a bug when a global command is exposed that depends on a type in a non-global domain
|
106
|
-
# but there being no other reason to include that non-global domain.
|
107
|
-
transformed_command_class.types_depended_on(remove_sensitive:).select(&:registered?).each do |type|
|
108
|
-
full_domain_name = type.foobara_domain.scoped_full_name
|
109
|
-
|
110
|
-
unless root_registry.foobara_lookup_domain(full_domain_name)
|
111
|
-
exposed_domain = root_registry.build_and_register_exposed_domain(full_domain_name)
|
112
|
-
to_include << exposed_domain
|
113
|
-
to_include << exposed_domain.foobara_organization
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
98
|
transformed_command_class.foobara_manifest(to_include:, remove_sensitive:).merge(super).merge(
|
118
99
|
Util.remove_blank(
|
119
100
|
scoped_category: :command,
|
@@ -133,13 +114,15 @@ module Foobara
|
|
133
114
|
serializers,
|
134
115
|
allowed_rule,
|
135
116
|
requires_authentication,
|
136
|
-
authenticator
|
117
|
+
authenticator,
|
118
|
+
result_has_sensitive_types?
|
137
119
|
]
|
138
120
|
) && scoped_path == command_class.scoped_path
|
139
121
|
command_class
|
140
122
|
else
|
141
123
|
Foobara::TransformedCommand.subclass(
|
142
124
|
command_class,
|
125
|
+
scoped_namespace:,
|
143
126
|
full_command_name:,
|
144
127
|
command_name:,
|
145
128
|
capture_unknown_error:,
|
@@ -154,6 +137,22 @@ module Foobara
|
|
154
137
|
)
|
155
138
|
end
|
156
139
|
end
|
140
|
+
|
141
|
+
# TODO: what to do if the whole return type is sensitive? return nil?
|
142
|
+
def result_has_sensitive_types?
|
143
|
+
result_type = command_class.result_type
|
144
|
+
|
145
|
+
if result_type.nil?
|
146
|
+
false
|
147
|
+
elsif result_type.sensitive?
|
148
|
+
# :nocov:
|
149
|
+
# TODO: we should convert it to nil I suppose
|
150
|
+
raise "Not sure yet how to handle a sensitive result type hmmmm..."
|
151
|
+
# :nocov:
|
152
|
+
else
|
153
|
+
command_class.result_type.has_sensitive_types?
|
154
|
+
end
|
155
|
+
end
|
157
156
|
end
|
158
157
|
end
|
159
158
|
end
|
@@ -1,23 +1,18 @@
|
|
1
1
|
module Foobara
|
2
2
|
class CommandRegistry
|
3
|
-
|
4
|
-
|
3
|
+
module ExposedDomain
|
4
|
+
attr_reader :unexposed_domain
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
attr_accessor :domain_module
|
10
|
-
|
11
|
-
def initialize(domain_module)
|
12
|
-
self.domain_module = domain_module
|
13
|
-
self.scoped_path = domain_module.scoped_path
|
6
|
+
def unexposed_domain=(unexposed_domain)
|
7
|
+
@unexposed_domain = unexposed_domain
|
8
|
+
self.scoped_path = unexposed_domain.scoped_path
|
14
9
|
end
|
15
10
|
|
16
11
|
# TODO: unable to address types here so it is handled as a hack higher up...
|
17
12
|
def foobara_manifest(to_include: Set.new, remove_sensitive: true)
|
18
13
|
to_include << foobara_organization
|
19
14
|
|
20
|
-
domain_manifest =
|
15
|
+
domain_manifest = unexposed_domain.foobara_manifest(to_include: Set.new, remove_sensitive:)
|
21
16
|
mode = Foobara::Namespace::LookupMode::DIRECT
|
22
17
|
commands = foobara_all_command(mode:).map(&:foobara_manifest_reference).sort
|
23
18
|
|
@@ -25,7 +20,7 @@ module Foobara
|
|
25
20
|
end
|
26
21
|
|
27
22
|
def foobara_organization
|
28
|
-
full_org_name =
|
23
|
+
full_org_name = unexposed_domain.foobara_organization.scoped_full_name
|
29
24
|
root_registry.foobara_lookup_organization(full_org_name)
|
30
25
|
end
|
31
26
|
|
@@ -36,7 +31,7 @@ module Foobara
|
|
36
31
|
end
|
37
32
|
|
38
33
|
def foobara_manifest_reference
|
39
|
-
|
34
|
+
unexposed_domain.foobara_manifest_reference
|
40
35
|
end
|
41
36
|
end
|
42
37
|
end
|
@@ -1,21 +1,16 @@
|
|
1
1
|
module Foobara
|
2
2
|
class CommandRegistry
|
3
|
-
|
4
|
-
|
3
|
+
module ExposedOrganization
|
4
|
+
attr_reader :unexposed_organization
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
attr_accessor :organization_module
|
10
|
-
|
11
|
-
def initialize(organization_module)
|
12
|
-
self.organization_module = organization_module
|
13
|
-
self.scoped_path = organization_module.scoped_path
|
6
|
+
def unexposed_organization=(unexposed_organization)
|
7
|
+
@unexposed_organization = unexposed_organization
|
8
|
+
self.scoped_path = unexposed_organization.scoped_path
|
14
9
|
end
|
15
10
|
|
16
11
|
# TODO: unable to address types here so it is handled as a hack higher up...
|
17
12
|
def foobara_manifest(to_include: Set.new, remove_sensitive: true)
|
18
|
-
organization_manifest =
|
13
|
+
organization_manifest = unexposed_organization.foobara_manifest(to_include: Set.new, remove_sensitive:)
|
19
14
|
mode = Foobara::Namespace::LookupMode::DIRECT
|
20
15
|
domains = foobara_all_domain(mode:).map(&:foobara_manifest_reference).sort
|
21
16
|
|
@@ -23,7 +18,7 @@ module Foobara
|
|
23
18
|
end
|
24
19
|
|
25
20
|
def foobara_manifest_reference
|
26
|
-
|
21
|
+
unexposed_organization.foobara_manifest_reference
|
27
22
|
end
|
28
23
|
end
|
29
24
|
end
|
@@ -10,7 +10,7 @@ module Foobara
|
|
10
10
|
self.scoped_path = []
|
11
11
|
self.authenticator = authenticator
|
12
12
|
|
13
|
-
customized = %i[command
|
13
|
+
customized = %i[command]
|
14
14
|
|
15
15
|
Namespace.global.foobara_categories.keys.reverse.each do |symbol|
|
16
16
|
next if customized.include?(symbol)
|
@@ -21,8 +21,6 @@ module Foobara
|
|
21
21
|
end
|
22
22
|
|
23
23
|
foobara_add_category_for_instance_of(:command, ExposedCommand)
|
24
|
-
foobara_add_category_for_instance_of(:domain, ExposedDomain)
|
25
|
-
foobara_add_category_for_instance_of(:organization, ExposedOrganization)
|
26
24
|
end
|
27
25
|
|
28
26
|
def register(command_class, **)
|
@@ -67,7 +65,6 @@ module Foobara
|
|
67
65
|
end
|
68
66
|
|
69
67
|
def build_and_register_exposed_domain(domain_full_name)
|
70
|
-
# TODO: would be nice to not have to do this...
|
71
68
|
domain_module = if domain_full_name.to_s == ""
|
72
69
|
GlobalDomain
|
73
70
|
else
|
@@ -78,7 +75,13 @@ module Foobara
|
|
78
75
|
exposed_organization = foobara_lookup_organization(full_organization_name) ||
|
79
76
|
build_and_register_exposed_organization(full_organization_name)
|
80
77
|
|
81
|
-
exposed_domain =
|
78
|
+
exposed_domain = Module.new
|
79
|
+
exposed_domain.foobara_namespace!
|
80
|
+
exposed_domain.foobara_domain!
|
81
|
+
exposed_domain.extend(ExposedDomain)
|
82
|
+
exposed_domain.unexposed_domain = domain_module
|
83
|
+
|
84
|
+
exposed_domain.foobara_depends_on domain_module
|
82
85
|
|
83
86
|
exposed_organization.foobara_register(exposed_domain)
|
84
87
|
exposed_domain.foobara_parent_namespace = exposed_organization
|
@@ -86,6 +89,17 @@ module Foobara
|
|
86
89
|
exposed_domain
|
87
90
|
end
|
88
91
|
|
92
|
+
def global_domain
|
93
|
+
foobara_lookup_domain("") || build_and_register_exposed_domain("")
|
94
|
+
end
|
95
|
+
|
96
|
+
def global_organization
|
97
|
+
# TODO: test this
|
98
|
+
# :nocov:
|
99
|
+
foobara_lookup_organization("") || build_and_register_exposed_organization("")
|
100
|
+
# :nocov:
|
101
|
+
end
|
102
|
+
|
89
103
|
def build_and_register_exposed_organization(full_organization_name)
|
90
104
|
org = if full_organization_name.to_s == ""
|
91
105
|
GlobalOrganization
|
@@ -93,7 +107,12 @@ module Foobara
|
|
93
107
|
Namespace.global.foobara_lookup_organization!(full_organization_name)
|
94
108
|
end
|
95
109
|
|
96
|
-
exposed_organization =
|
110
|
+
exposed_organization = Module.new
|
111
|
+
exposed_organization.foobara_namespace!
|
112
|
+
exposed_organization.foobara_organization!
|
113
|
+
exposed_organization.extend(ExposedOrganization)
|
114
|
+
exposed_organization.unexposed_organization = org
|
115
|
+
|
97
116
|
foobara_register(exposed_organization)
|
98
117
|
exposed_organization.foobara_parent_namespace = self
|
99
118
|
|
@@ -7,7 +7,7 @@ module Foobara
|
|
7
7
|
when Entity
|
8
8
|
# TODO: handle polymorphism? Would require iterating over the result type not the object!
|
9
9
|
# Is there maybe prior art for this in the associations stuff?
|
10
|
-
unless object.loaded?
|
10
|
+
unless object.loaded? || object.built?
|
11
11
|
object.class.load(object)
|
12
12
|
end
|
13
13
|
|
@@ -9,6 +9,7 @@ module Foobara
|
|
9
9
|
TypeDeclarations.register_type_declaration(handler)
|
10
10
|
|
11
11
|
TypeDeclarations.register_sensitive_type_remover(SensitiveTypeRemovers::DetachedEntity.new(handler))
|
12
|
+
TypeDeclarations.register_sensitive_value_remover(handler, SensitiveValueRemovers::DetachedEntity)
|
12
13
|
|
13
14
|
model = Namespace.global.foobara_lookup_type!(:model)
|
14
15
|
BuiltinTypes.build_and_register!(:detached_entity, model, nil)
|
@@ -11,6 +11,7 @@ module Foobara
|
|
11
11
|
TypeDeclarations.register_type_declaration(handler)
|
12
12
|
|
13
13
|
TypeDeclarations.register_sensitive_type_remover(SensitiveTypeRemovers::Entity.new(handler))
|
14
|
+
TypeDeclarations.register_sensitive_value_remover(handler, SensitiveValueRemovers::Entity)
|
14
15
|
|
15
16
|
detached_entity = Namespace.global.foobara_lookup_type!(:detached_entity)
|
16
17
|
BuiltinTypes.build_and_register!(:entity, detached_entity, nil)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Foobara
|
2
|
+
class Entity < DetachedEntity
|
3
|
+
module SensitiveValueRemovers
|
4
|
+
class Entity < DetachedEntity::SensitiveValueRemovers::DetachedEntity
|
5
|
+
def transform(record)
|
6
|
+
sanitized_record = super
|
7
|
+
|
8
|
+
sanitized_record.is_loaded = record.loaded?
|
9
|
+
sanitized_record.is_persisted = record.persisted?
|
10
|
+
|
11
|
+
sanitized_record
|
12
|
+
end
|
13
|
+
|
14
|
+
def build_method
|
15
|
+
:build
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -3,7 +3,7 @@ require_relative "base_manifest"
|
|
3
3
|
module Foobara
|
4
4
|
module Manifest
|
5
5
|
class TypeDeclaration < BaseManifest
|
6
|
-
optional_keys(:allow_nil, :one_of)
|
6
|
+
optional_keys(:allow_nil, :one_of, :sensitive, :sensitive_exposed)
|
7
7
|
|
8
8
|
class << self
|
9
9
|
def new(root_manifest, path)
|
@@ -24,6 +24,10 @@ module Foobara
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
def sensitive?
|
28
|
+
sensitive || sensitive_exposed
|
29
|
+
end
|
30
|
+
|
27
31
|
# rubocop:disable Naming/MemoizedInstanceVariableName
|
28
32
|
# TODO: create an Attribute class to encapsulate this situation
|
29
33
|
def attribute?
|
@@ -12,9 +12,14 @@ module Foobara
|
|
12
12
|
TypeDeclarations.register_type_declaration(extended_model_handler)
|
13
13
|
|
14
14
|
TypeDeclarations.register_sensitive_type_remover(SensitiveTypeRemovers::Model.new(model_handler))
|
15
|
+
TypeDeclarations.register_sensitive_value_remover(model_handler, SensitiveValueRemovers::Model)
|
15
16
|
TypeDeclarations.register_sensitive_type_remover(
|
16
17
|
SensitiveTypeRemovers::ExtendedModel.new(extended_model_handler)
|
17
18
|
)
|
19
|
+
# TypeDeclarations.register_sensitive_value_remover(
|
20
|
+
# extended_model_handler,
|
21
|
+
# SensitiveValueRemovers::ExtendedModel
|
22
|
+
# )
|
18
23
|
|
19
24
|
atomic_duck = Namespace.global.foobara_lookup_type!(:atomic_duck)
|
20
25
|
BuiltinTypes.build_and_register!(:model, atomic_duck, nil)
|
@@ -79,6 +79,10 @@ module Foobara
|
|
79
79
|
strictish_type_declaration[:name] = strictish_type_declaration[:name].to_s
|
80
80
|
end
|
81
81
|
|
82
|
+
if strictish_type_declaration[:model_module].nil?
|
83
|
+
strictish_type_declaration.delete(:model_module)
|
84
|
+
end
|
85
|
+
|
82
86
|
strictish_type_declaration[:model_class] ||= [
|
83
87
|
*strictish_type_declaration[:model_module],
|
84
88
|
strictish_type_declaration[:name]
|
@@ -3,23 +3,46 @@ module Foobara
|
|
3
3
|
module Handlers
|
4
4
|
class ExtendModelTypeDeclaration < ExtendRegisteredTypeDeclaration
|
5
5
|
class ToTypeTransformer < ExtendRegisteredTypeDeclaration::ToTypeTransformer
|
6
|
+
def existing_class_from_same_namespace_root(model_class_name)
|
7
|
+
if Object.const_defined?(model_class_name) && Object.const_get(model_class_name).is_a?(::Class)
|
8
|
+
existing_class = Object.const_get(model_class_name)
|
9
|
+
|
10
|
+
# If we are operating in some other namespace tree then we don't want to use the non-anonymous class
|
11
|
+
if Domain.current == GlobalDomain || Domain.current.foobara_root_namespace == Foobara::Namespace.global
|
12
|
+
return existing_class
|
13
|
+
end
|
14
|
+
|
15
|
+
model_type = existing_class.model_type
|
16
|
+
|
17
|
+
if model_type
|
18
|
+
if model_type.foobara_root_namespace == Foobara::Namespace.current.foobara_root_namespace
|
19
|
+
# TODO: test this code path
|
20
|
+
# :nocov:
|
21
|
+
existing_class
|
22
|
+
# :nocov:
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
6
28
|
# TODO: make declaration validator for model_class and model_base_class
|
7
29
|
def target_classes(strict_type_declaration)
|
8
30
|
model_class_name = strict_type_declaration[:model_class]
|
9
31
|
|
10
|
-
|
11
|
-
Object.const_get(model_class_name)
|
12
|
-
else
|
13
|
-
base_class_name = strict_type_declaration[:model_base_class]
|
32
|
+
existing_class = existing_class_from_same_namespace_root(model_class_name)
|
14
33
|
|
15
|
-
|
16
|
-
|
17
|
-
else
|
18
|
-
foobara_domain.foobara_lookup_type!(base_class_name).target_class
|
19
|
-
end
|
20
|
-
|
21
|
-
base_class.subclass(name: model_class_name)
|
34
|
+
if existing_class
|
35
|
+
return existing_class
|
22
36
|
end
|
37
|
+
|
38
|
+
base_class_name = strict_type_declaration[:model_base_class]
|
39
|
+
|
40
|
+
base_class = existing_class_from_same_namespace_root(base_class_name)
|
41
|
+
base_class ||= lookup_type(base_class_name)&.target_class
|
42
|
+
# If we make it here, it's a real base class like Foobara::Entity
|
43
|
+
base_class ||= Object.const_get(base_class_name)
|
44
|
+
|
45
|
+
base_class.subclass(name: model_class_name)
|
23
46
|
end
|
24
47
|
|
25
48
|
# TODO: must explode if name missing...
|
@@ -52,7 +75,15 @@ module Foobara
|
|
52
75
|
# :nocov:
|
53
76
|
else
|
54
77
|
model_class.model_type = type
|
78
|
+
|
79
|
+
# this is a fairly complex way of making sure that we are getting the domain from the
|
80
|
+
# current namespace tree which might not be the case if we're in a command connector
|
81
|
+
# namespace
|
55
82
|
domain = model_class.domain
|
83
|
+
domain_name = domain.scoped_full_name
|
84
|
+
root_namespace = Namespace.current.foobara_root_namespace
|
85
|
+
domain = root_namespace.foobara_lookup_domain(domain_name)
|
86
|
+
|
56
87
|
type.type_symbol = type.declaration_data[:name]
|
57
88
|
model_class.description type.declaration_data[:description]
|
58
89
|
domain.foobara_register_model(model_class)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Foobara
|
2
|
+
class Model
|
3
|
+
module SensitiveValueRemovers
|
4
|
+
class Model < TypeDeclarations::RemoveSensitiveValuesTransformer
|
5
|
+
def transform(record)
|
6
|
+
attributes_type = from_type.element_types
|
7
|
+
|
8
|
+
sanitized_attributes, changed = sanitize_value(attributes_type, record.attributes)
|
9
|
+
|
10
|
+
if changed
|
11
|
+
type.target_class.send(build_method, sanitized_attributes)
|
12
|
+
else
|
13
|
+
record
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def build_method
|
18
|
+
:new
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -214,14 +214,16 @@ module Foobara
|
|
214
214
|
|
215
215
|
return if mode == Namespace::LookupMode::DIRECT
|
216
216
|
|
217
|
-
if
|
217
|
+
if [Namespace::LookupMode::GENERAL, Namespace::LookupMode::ABSOLUTE].include?(mode)
|
218
218
|
foobara_children.each do |child|
|
219
219
|
child.foobara_each(filter:, mode:, &)
|
220
220
|
end
|
221
221
|
end
|
222
222
|
|
223
|
-
|
224
|
-
|
223
|
+
if mode == Namespace::LookupMode::GENERAL
|
224
|
+
foobara_depends_on_namespaces.each do |dependent|
|
225
|
+
dependent.foobara_each(filter:, mode:, &)
|
226
|
+
end
|
225
227
|
end
|
226
228
|
end
|
227
229
|
|
@@ -111,7 +111,7 @@ module Foobara
|
|
111
111
|
to_load = Set.new
|
112
112
|
|
113
113
|
to_load_records.group_by(&:class).each_pair do |entity_class, records|
|
114
|
-
unloaded = records.
|
114
|
+
unloaded = records.select { |record| record.persisted? && !record.loaded? }
|
115
115
|
entity_class.current_transaction_table.load_many(unloaded)
|
116
116
|
|
117
117
|
associations = entity_class.associations
|
@@ -70,7 +70,9 @@ module Foobara
|
|
70
70
|
@sensitive_type_removers = nil
|
71
71
|
|
72
72
|
register_sensitive_type_remover(SensitiveTypeRemovers::Attributes.new(attributes_handler))
|
73
|
+
register_sensitive_value_remover(attributes_handler, SensitiveValueRemovers::Attributes)
|
73
74
|
register_sensitive_type_remover(SensitiveTypeRemovers::Array.new(array_handler))
|
75
|
+
register_sensitive_value_remover(array_handler, SensitiveValueRemovers::Array)
|
74
76
|
end
|
75
77
|
|
76
78
|
def install!
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require_relative "typed_transformer"
|
2
|
+
|
3
|
+
module Foobara
|
4
|
+
module TypeDeclarations
|
5
|
+
class RemoveSensitiveValuesTransformer < TypedTransformer
|
6
|
+
class << self
|
7
|
+
def type_declaration(type_declaration)
|
8
|
+
if type_declaration.is_a?(Types::Type)
|
9
|
+
type_declaration = type_declaration.declaration_data
|
10
|
+
end
|
11
|
+
|
12
|
+
TypeDeclarations.remove_sensitive_types(type_declaration)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_accessor :namespace
|
17
|
+
|
18
|
+
def initialize(...)
|
19
|
+
super
|
20
|
+
|
21
|
+
self.namespace = Namespace.current
|
22
|
+
|
23
|
+
type
|
24
|
+
end
|
25
|
+
|
26
|
+
def transform(_value)
|
27
|
+
# :nocov:
|
28
|
+
raise "subclass responsibility"
|
29
|
+
# :nocov:
|
30
|
+
end
|
31
|
+
|
32
|
+
def sanitize_value(type, value)
|
33
|
+
if type.has_sensitive_types?
|
34
|
+
remover_class = TypeDeclarations.sensitive_value_remover_class_for_type(type)
|
35
|
+
remover = Namespace.use(namespace) { remover_class.new(type) }
|
36
|
+
sanitized_value = remover.process_value!(value)
|
37
|
+
|
38
|
+
[sanitized_value, sanitized_value != value]
|
39
|
+
else
|
40
|
+
[value, false]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Foobara
|
2
|
+
module TypeDeclarations
|
3
|
+
module SensitiveValueRemovers
|
4
|
+
class Array < RemoveSensitiveValuesTransformer
|
5
|
+
def transform(array)
|
6
|
+
element_type = from_type.element_type
|
7
|
+
|
8
|
+
changed = false
|
9
|
+
|
10
|
+
sanitized_array = array.map do |element|
|
11
|
+
sanitized_value, changed2 = sanitize_value(element_type, element)
|
12
|
+
|
13
|
+
if changed2
|
14
|
+
changed = true
|
15
|
+
sanitized_value
|
16
|
+
else
|
17
|
+
element
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
if changed
|
22
|
+
sanitized_array
|
23
|
+
else
|
24
|
+
array
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative "../remove_sensitive_values_transformer"
|
2
|
+
|
3
|
+
module Foobara
|
4
|
+
module TypeDeclarations
|
5
|
+
module SensitiveValueRemovers
|
6
|
+
class Attributes < RemoveSensitiveValuesTransformer
|
7
|
+
def transform(attributes)
|
8
|
+
element_types = from_type.element_types
|
9
|
+
|
10
|
+
sanitized_attributes = {}
|
11
|
+
changed = false
|
12
|
+
|
13
|
+
attributes.each_pair do |attribute_name, value|
|
14
|
+
element_type = element_types[attribute_name]
|
15
|
+
|
16
|
+
if element_type.sensitive?
|
17
|
+
changed = true
|
18
|
+
next
|
19
|
+
else
|
20
|
+
value, changed2 = sanitize_value(element_type, value)
|
21
|
+
changed ||= changed2
|
22
|
+
sanitized_attributes[attribute_name] = value
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
if changed
|
27
|
+
sanitized_attributes
|
28
|
+
else
|
29
|
+
attributes
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -38,6 +38,28 @@ module Foobara
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
# TODO: since these are dealing with values instead of declarations maybe this should live somewhere else?
|
42
|
+
def register_sensitive_value_remover(handler, sensitive_value_remover)
|
43
|
+
sensitive_value_removers[handler.class.name] = sensitive_value_remover
|
44
|
+
end
|
45
|
+
|
46
|
+
def sensitive_value_removers
|
47
|
+
@sensitive_value_removers ||= {}
|
48
|
+
end
|
49
|
+
|
50
|
+
def sensitive_value_remover_class_for_type(type)
|
51
|
+
handler = GlobalDomain.foobara_type_builder.type_declaration_handler_for(type.declaration_data)
|
52
|
+
remover_class = sensitive_value_removers[handler.class.name]
|
53
|
+
|
54
|
+
unless remover_class
|
55
|
+
# :nocov:
|
56
|
+
raise "No sensitive value remover found for #{type.declaration_data}"
|
57
|
+
# :nocov:
|
58
|
+
end
|
59
|
+
|
60
|
+
remover_class
|
61
|
+
end
|
62
|
+
|
41
63
|
def strict(&)
|
42
64
|
using_mode(Mode::STRICT, &)
|
43
65
|
end
|
@@ -20,6 +20,10 @@ module Foobara
|
|
20
20
|
Foobara::Namespace.current.foobara_lookup_type!(...)
|
21
21
|
end
|
22
22
|
|
23
|
+
def lookup_type(...)
|
24
|
+
Foobara::Namespace.current.foobara_lookup_type(...)
|
25
|
+
end
|
26
|
+
|
23
27
|
def type_registered?(...)
|
24
28
|
Foobara::Namespace.current.foobara_type_registered?(...)
|
25
29
|
end
|
@@ -31,6 +35,7 @@ module Foobara
|
|
31
35
|
|
32
36
|
foobara_delegate :type_for_declaration,
|
33
37
|
:type_declaration_handler_for,
|
38
|
+
:lookup_type,
|
34
39
|
:lookup_type!,
|
35
40
|
:lookup_absolute_type!,
|
36
41
|
:type_registered?,
|
data/projects/types/src/type.rb
CHANGED
@@ -83,6 +83,24 @@ module Foobara
|
|
83
83
|
sensitive_exposed
|
84
84
|
end
|
85
85
|
|
86
|
+
def has_sensitive_types?
|
87
|
+
return true if sensitive?
|
88
|
+
|
89
|
+
if element_type
|
90
|
+
return true if element_type.has_sensitive_types?
|
91
|
+
end
|
92
|
+
|
93
|
+
if element_types
|
94
|
+
types = if element_types.is_a?(::Hash)
|
95
|
+
element_types.values
|
96
|
+
else
|
97
|
+
[*element_types]
|
98
|
+
end
|
99
|
+
|
100
|
+
types.any?(&:has_sensitive_types?)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
86
104
|
def apply_all_processors_needing_type!
|
87
105
|
each_processor_class_requiring_type do |processor_class|
|
88
106
|
# TODO: is this a smell?
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foobara
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.85
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miles Georgi
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-03-
|
10
|
+
date: 2025-03-23 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: bigdecimal
|
@@ -226,6 +226,7 @@ files:
|
|
226
226
|
- projects/detached_entity/src/extensions/type_declarations/handlers/extend_detached_entity_type_declaration/validate_primary_key_present.rb
|
227
227
|
- projects/detached_entity/src/extensions/type_declarations/handlers/extend_detached_entity_type_declaration/validate_primary_key_references_attribute.rb
|
228
228
|
- projects/detached_entity/src/sensitive_type_removers/detached_entity.rb
|
229
|
+
- projects/detached_entity/src/sensitive_value_removers/detached_entity.rb
|
229
230
|
- projects/domain/lib/foobara/domain.rb
|
230
231
|
- projects/domain/src/domain.rb
|
231
232
|
- projects/domain/src/domain_module_extension.rb
|
@@ -266,6 +267,7 @@ files:
|
|
266
267
|
- projects/entity/src/new_prepend.rb
|
267
268
|
- projects/entity/src/not_found_error.rb
|
268
269
|
- projects/entity/src/sensitive_type_removers/entity.rb
|
270
|
+
- projects/entity/src/sensitive_value_removers/entity.rb
|
269
271
|
- projects/enumerated/lib/foobara/enumerated.rb
|
270
272
|
- projects/enumerated/src/accessors.rb
|
271
273
|
- projects/enumerated/src/enumerated.rb
|
@@ -316,6 +318,7 @@ files:
|
|
316
318
|
- projects/model/src/model.rb
|
317
319
|
- projects/model/src/sensitive_type_removers/extended_model.rb
|
318
320
|
- projects/model/src/sensitive_type_removers/model.rb
|
321
|
+
- projects/model/src/sensitive_value_removers/model.rb
|
319
322
|
- projects/model_attribute_helpers/lib/foobara/model_attribute_helpers.rb
|
320
323
|
- projects/model_attribute_helpers/src/attribute_helper_aliases.rb
|
321
324
|
- projects/model_attribute_helpers/src/attribute_helpers.rb
|
@@ -387,9 +390,12 @@ files:
|
|
387
390
|
- projects/type_declarations/src/handlers/registered_type_declaration/to_type_transformer.rb
|
388
391
|
- projects/type_declarations/src/handlers/registered_type_declaration/type_desugarizer.rb
|
389
392
|
- projects/type_declarations/src/processor.rb
|
393
|
+
- projects/type_declarations/src/remove_sensitive_values_transformer.rb
|
390
394
|
- projects/type_declarations/src/sensitive_type_remover.rb
|
391
395
|
- projects/type_declarations/src/sensitive_type_removers/array.rb
|
392
396
|
- projects/type_declarations/src/sensitive_type_removers/attributes.rb
|
397
|
+
- projects/type_declarations/src/sensitive_value_removers/array.rb
|
398
|
+
- projects/type_declarations/src/sensitive_value_removers/attributes.rb
|
393
399
|
- projects/type_declarations/src/to_type_transformer.rb
|
394
400
|
- projects/type_declarations/src/transformer.rb
|
395
401
|
- projects/type_declarations/src/type_builder.rb
|