familia 2.0.0.pre5 → 2.0.0.pre7
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/.github/workflows/claude-code-review.yml +57 -0
- data/.github/workflows/claude.yml +71 -0
- data/.gitignore +5 -1
- data/.rubocop.yml +3 -0
- data/CLAUDE.md +32 -10
- data/Gemfile +2 -2
- data/Gemfile.lock +4 -3
- data/docs/wiki/API-Reference.md +95 -18
- data/docs/wiki/Connection-Pooling-Guide.md +437 -0
- data/docs/wiki/Encrypted-Fields-Overview.md +40 -3
- data/docs/wiki/Expiration-Feature-Guide.md +596 -0
- data/docs/wiki/Feature-System-Guide.md +631 -0
- data/docs/wiki/Features-System-Developer-Guide.md +892 -0
- data/docs/wiki/Field-System-Guide.md +784 -0
- data/docs/wiki/Home.md +82 -15
- data/docs/wiki/Implementation-Guide.md +126 -33
- data/docs/wiki/Quantization-Feature-Guide.md +721 -0
- data/docs/wiki/Relationships-Guide.md +684 -0
- data/docs/wiki/Security-Model.md +65 -25
- data/docs/wiki/Transient-Fields-Guide.md +280 -0
- data/examples/bit_encoding_integration.rb +237 -0
- data/examples/redis_command_validation_example.rb +231 -0
- data/examples/relationships_basic.rb +273 -0
- data/lib/familia/base.rb +1 -1
- data/lib/familia/connection.rb +3 -3
- data/lib/familia/data_type/types/counter.rb +38 -0
- data/lib/familia/data_type/types/hashkey.rb +18 -0
- data/lib/familia/data_type/types/lock.rb +43 -0
- data/lib/familia/data_type/types/string.rb +9 -2
- data/lib/familia/data_type.rb +9 -6
- data/lib/familia/encryption/encrypted_data.rb +137 -0
- data/lib/familia/encryption/manager.rb +21 -4
- data/lib/familia/encryption/providers/aes_gcm_provider.rb +20 -0
- data/lib/familia/encryption/providers/xchacha20_poly1305_provider.rb +20 -0
- data/lib/familia/encryption.rb +1 -1
- data/lib/familia/errors.rb +17 -3
- data/lib/familia/features/encrypted_fields/concealed_string.rb +293 -0
- data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +94 -26
- data/lib/familia/features/encrypted_fields.rb +413 -4
- data/lib/familia/features/expiration.rb +319 -33
- data/lib/familia/features/quantization.rb +385 -44
- data/lib/familia/features/relationships/cascading.rb +438 -0
- data/lib/familia/features/relationships/indexing.rb +370 -0
- data/lib/familia/features/relationships/membership.rb +503 -0
- data/lib/familia/features/relationships/permission_management.rb +264 -0
- data/lib/familia/features/relationships/querying.rb +620 -0
- data/lib/familia/features/relationships/redis_operations.rb +274 -0
- data/lib/familia/features/relationships/score_encoding.rb +442 -0
- data/lib/familia/features/relationships/tracking.rb +379 -0
- data/lib/familia/features/relationships.rb +466 -0
- data/lib/familia/features/safe_dump.rb +1 -1
- data/lib/familia/features/transient_fields/redacted_string.rb +1 -1
- data/lib/familia/features/transient_fields.rb +192 -10
- data/lib/familia/features.rb +2 -1
- data/lib/familia/field_type.rb +5 -2
- data/lib/familia/horreum/{connection.rb → core/connection.rb} +2 -8
- data/lib/familia/horreum/{database_commands.rb → core/database_commands.rb} +14 -3
- data/lib/familia/horreum/core/serialization.rb +535 -0
- data/lib/familia/horreum/{utils.rb → core/utils.rb} +0 -2
- data/lib/familia/horreum/core.rb +21 -0
- data/lib/familia/horreum/{settings.rb → shared/settings.rb} +0 -2
- data/lib/familia/horreum/{definition_methods.rb → subclass/definition.rb} +45 -29
- data/lib/familia/horreum/{management_methods.rb → subclass/management.rb} +9 -8
- data/lib/familia/horreum/{related_fields_management.rb → subclass/related_fields_management.rb} +15 -10
- data/lib/familia/horreum.rb +17 -17
- data/lib/familia/validation/command_recorder.rb +336 -0
- data/lib/familia/validation/expectations.rb +519 -0
- data/lib/familia/validation/test_helpers.rb +443 -0
- data/lib/familia/validation/validator.rb +412 -0
- data/lib/familia/validation.rb +140 -0
- data/lib/familia/version.rb +1 -1
- data/lib/familia.rb +1 -1
- data/try/core/create_method_try.rb +240 -0
- data/try/core/database_consistency_try.rb +299 -0
- data/try/core/errors_try.rb +25 -4
- data/try/core/familia_try.rb +1 -1
- data/try/core/persistence_operations_try.rb +297 -0
- data/try/data_types/counter_try.rb +93 -0
- data/try/data_types/lock_try.rb +133 -0
- data/try/debugging/debug_aad_process.rb +82 -0
- data/try/debugging/debug_concealed_internal.rb +59 -0
- data/try/debugging/debug_concealed_reveal.rb +61 -0
- data/try/debugging/debug_context_aad.rb +68 -0
- data/try/debugging/debug_context_simple.rb +80 -0
- data/try/debugging/debug_cross_context.rb +62 -0
- data/try/debugging/debug_database_load.rb +64 -0
- data/try/debugging/debug_encrypted_json_check.rb +53 -0
- data/try/debugging/debug_encrypted_json_step_by_step.rb +62 -0
- data/try/debugging/debug_exists_lifecycle.rb +54 -0
- data/try/debugging/debug_field_decrypt.rb +74 -0
- data/try/debugging/debug_fresh_cross_context.rb +73 -0
- data/try/debugging/debug_load_path.rb +66 -0
- data/try/debugging/debug_method_definition.rb +46 -0
- data/try/debugging/debug_method_resolution.rb +41 -0
- data/try/debugging/debug_minimal.rb +24 -0
- data/try/debugging/debug_provider.rb +68 -0
- data/try/debugging/debug_secure_behavior.rb +73 -0
- data/try/debugging/debug_string_class.rb +46 -0
- data/try/debugging/debug_test.rb +46 -0
- data/try/debugging/debug_test_design.rb +80 -0
- data/try/edge_cases/hash_symbolization_try.rb +1 -0
- data/try/edge_cases/reserved_keywords_try.rb +1 -0
- data/try/edge_cases/string_coercion_try.rb +2 -0
- data/try/encryption/encryption_core_try.rb +6 -4
- data/try/features/categorical_permissions_try.rb +515 -0
- data/try/features/encrypted_fields_core_try.rb +19 -11
- data/try/features/encrypted_fields_integration_try.rb +66 -70
- data/try/features/encrypted_fields_no_cache_security_try.rb +22 -8
- data/try/features/encrypted_fields_security_try.rb +151 -144
- data/try/features/encryption_fields/aad_protection_try.rb +108 -23
- data/try/features/encryption_fields/concealed_string_core_try.rb +253 -0
- data/try/features/encryption_fields/context_isolation_try.rb +30 -8
- data/try/features/encryption_fields/error_conditions_try.rb +6 -6
- data/try/features/encryption_fields/fresh_key_derivation_try.rb +20 -14
- data/try/features/encryption_fields/fresh_key_try.rb +27 -22
- data/try/features/encryption_fields/key_rotation_try.rb +16 -10
- data/try/features/encryption_fields/nonce_uniqueness_try.rb +15 -13
- data/try/features/encryption_fields/secure_by_default_behavior_try.rb +310 -0
- data/try/features/encryption_fields/thread_safety_try.rb +6 -6
- data/try/features/encryption_fields/universal_serialization_safety_try.rb +174 -0
- data/try/features/feature_dependencies_try.rb +3 -3
- data/try/features/relationships_edge_cases_try.rb +145 -0
- data/try/features/relationships_performance_minimal_try.rb +132 -0
- data/try/features/relationships_performance_simple_try.rb +155 -0
- data/try/features/relationships_performance_try.rb +420 -0
- data/try/features/relationships_performance_working_try.rb +144 -0
- data/try/features/relationships_try.rb +237 -0
- data/try/features/safe_dump_try.rb +3 -0
- data/try/features/transient_fields/redacted_string_try.rb +2 -0
- data/try/features/transient_fields/single_use_redacted_string_try.rb +2 -0
- data/try/features/transient_fields_core_try.rb +1 -1
- data/try/features/transient_fields_integration_try.rb +1 -1
- data/try/helpers/test_helpers.rb +26 -1
- data/try/horreum/base_try.rb +14 -8
- data/try/horreum/enhanced_conflict_handling_try.rb +3 -1
- data/try/horreum/initialization_try.rb +1 -1
- data/try/horreum/relations_try.rb +2 -2
- data/try/horreum/serialization_persistent_fields_try.rb +8 -8
- data/try/horreum/serialization_try.rb +39 -4
- data/try/models/customer_safe_dump_try.rb +1 -1
- data/try/models/customer_try.rb +1 -1
- data/try/validation/atomic_operations_try.rb.disabled +320 -0
- data/try/validation/command_validation_try.rb.disabled +207 -0
- data/try/validation/performance_validation_try.rb.disabled +324 -0
- data/try/validation/real_world_scenarios_try.rb.disabled +390 -0
- metadata +81 -12
- data/TEST_COVERAGE.md +0 -40
- data/lib/familia/features/relatable_objects.rb +0 -125
- data/lib/familia/horreum/serialization.rb +0 -473
- data/try/features/relatable_objects_try.rb +0 -220
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: familia
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.
|
4
|
+
version: 2.0.0.pre7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Delano Mandelbaum
|
@@ -121,6 +121,8 @@ extensions: []
|
|
121
121
|
extra_rdoc_files: []
|
122
122
|
files:
|
123
123
|
- ".github/workflows/ci.yml"
|
124
|
+
- ".github/workflows/claude-code-review.yml"
|
125
|
+
- ".github/workflows/claude.yml"
|
124
126
|
- ".github/workflows/docs.yml"
|
125
127
|
- ".gitignore"
|
126
128
|
- ".pre-commit-config.yaml"
|
@@ -132,15 +134,25 @@ files:
|
|
132
134
|
- Gemfile.lock
|
133
135
|
- LICENSE.txt
|
134
136
|
- README.md
|
135
|
-
- TEST_COVERAGE.md
|
136
137
|
- bin/irb
|
137
138
|
- docs/connection_pooling.md
|
138
139
|
- docs/overview.md
|
139
140
|
- docs/wiki/API-Reference.md
|
141
|
+
- docs/wiki/Connection-Pooling-Guide.md
|
140
142
|
- docs/wiki/Encrypted-Fields-Overview.md
|
143
|
+
- docs/wiki/Expiration-Feature-Guide.md
|
144
|
+
- docs/wiki/Feature-System-Guide.md
|
145
|
+
- docs/wiki/Features-System-Developer-Guide.md
|
146
|
+
- docs/wiki/Field-System-Guide.md
|
141
147
|
- docs/wiki/Home.md
|
142
148
|
- docs/wiki/Implementation-Guide.md
|
149
|
+
- docs/wiki/Quantization-Feature-Guide.md
|
150
|
+
- docs/wiki/Relationships-Guide.md
|
143
151
|
- docs/wiki/Security-Model.md
|
152
|
+
- docs/wiki/Transient-Fields-Guide.md
|
153
|
+
- examples/bit_encoding_integration.rb
|
154
|
+
- examples/redis_command_validation_example.rb
|
155
|
+
- examples/relationships_basic.rb
|
144
156
|
- familia.gemspec
|
145
157
|
- lib/familia.rb
|
146
158
|
- lib/familia/base.rb
|
@@ -149,12 +161,15 @@ files:
|
|
149
161
|
- lib/familia/data_type.rb
|
150
162
|
- lib/familia/data_type/commands.rb
|
151
163
|
- lib/familia/data_type/serialization.rb
|
164
|
+
- lib/familia/data_type/types/counter.rb
|
152
165
|
- lib/familia/data_type/types/hashkey.rb
|
153
166
|
- lib/familia/data_type/types/list.rb
|
167
|
+
- lib/familia/data_type/types/lock.rb
|
154
168
|
- lib/familia/data_type/types/sorted_set.rb
|
155
169
|
- lib/familia/data_type/types/string.rb
|
156
170
|
- lib/familia/data_type/types/unsorted_set.rb
|
157
171
|
- lib/familia/encryption.rb
|
172
|
+
- lib/familia/encryption/encrypted_data.rb
|
158
173
|
- lib/familia/encryption/manager.rb
|
159
174
|
- lib/familia/encryption/provider.rb
|
160
175
|
- lib/familia/encryption/providers/aes_gcm_provider.rb
|
@@ -165,10 +180,19 @@ files:
|
|
165
180
|
- lib/familia/errors.rb
|
166
181
|
- lib/familia/features.rb
|
167
182
|
- lib/familia/features/encrypted_fields.rb
|
183
|
+
- lib/familia/features/encrypted_fields/concealed_string.rb
|
168
184
|
- lib/familia/features/encrypted_fields/encrypted_field_type.rb
|
169
185
|
- lib/familia/features/expiration.rb
|
170
186
|
- lib/familia/features/quantization.rb
|
171
|
-
- lib/familia/features/
|
187
|
+
- lib/familia/features/relationships.rb
|
188
|
+
- lib/familia/features/relationships/cascading.rb
|
189
|
+
- lib/familia/features/relationships/indexing.rb
|
190
|
+
- lib/familia/features/relationships/membership.rb
|
191
|
+
- lib/familia/features/relationships/permission_management.rb
|
192
|
+
- lib/familia/features/relationships/querying.rb
|
193
|
+
- lib/familia/features/relationships/redis_operations.rb
|
194
|
+
- lib/familia/features/relationships/score_encoding.rb
|
195
|
+
- lib/familia/features/relationships/tracking.rb
|
172
196
|
- lib/familia/features/safe_dump.rb
|
173
197
|
- lib/familia/features/transient_fields.rb
|
174
198
|
- lib/familia/features/transient_fields/redacted_string.rb
|
@@ -176,44 +200,76 @@ files:
|
|
176
200
|
- lib/familia/features/transient_fields/transient_field_type.rb
|
177
201
|
- lib/familia/field_type.rb
|
178
202
|
- lib/familia/horreum.rb
|
179
|
-
- lib/familia/horreum/
|
180
|
-
- lib/familia/horreum/
|
181
|
-
- lib/familia/horreum/
|
182
|
-
- lib/familia/horreum/
|
183
|
-
- lib/familia/horreum/
|
184
|
-
- lib/familia/horreum/
|
185
|
-
- lib/familia/horreum/
|
186
|
-
- lib/familia/horreum/
|
203
|
+
- lib/familia/horreum/core.rb
|
204
|
+
- lib/familia/horreum/core/connection.rb
|
205
|
+
- lib/familia/horreum/core/database_commands.rb
|
206
|
+
- lib/familia/horreum/core/serialization.rb
|
207
|
+
- lib/familia/horreum/core/utils.rb
|
208
|
+
- lib/familia/horreum/shared/settings.rb
|
209
|
+
- lib/familia/horreum/subclass/definition.rb
|
210
|
+
- lib/familia/horreum/subclass/management.rb
|
211
|
+
- lib/familia/horreum/subclass/related_fields_management.rb
|
187
212
|
- lib/familia/logging.rb
|
188
213
|
- lib/familia/multi_result.rb
|
189
214
|
- lib/familia/refinements.rb
|
190
215
|
- lib/familia/secure_identifier.rb
|
191
216
|
- lib/familia/settings.rb
|
192
217
|
- lib/familia/utils.rb
|
218
|
+
- lib/familia/validation.rb
|
219
|
+
- lib/familia/validation/command_recorder.rb
|
220
|
+
- lib/familia/validation/expectations.rb
|
221
|
+
- lib/familia/validation/test_helpers.rb
|
222
|
+
- lib/familia/validation/validator.rb
|
193
223
|
- lib/familia/version.rb
|
194
224
|
- lib/middleware/database_middleware.rb
|
195
225
|
- try/configuration/scenarios_try.rb
|
196
226
|
- try/core/base_enhancements_try.rb
|
197
227
|
- try/core/connection_try.rb
|
228
|
+
- try/core/create_method_try.rb
|
229
|
+
- try/core/database_consistency_try.rb
|
198
230
|
- try/core/errors_try.rb
|
199
231
|
- try/core/extensions_try.rb
|
200
232
|
- try/core/familia_extended_try.rb
|
201
233
|
- try/core/familia_try.rb
|
202
234
|
- try/core/middleware_try.rb
|
235
|
+
- try/core/persistence_operations_try.rb
|
203
236
|
- try/core/pools_try.rb
|
204
237
|
- try/core/secure_identifier_try.rb
|
205
238
|
- try/core/settings_try.rb
|
206
239
|
- try/core/tools_try.rb
|
207
240
|
- try/core/utils_try.rb
|
208
241
|
- try/data_types/boolean_try.rb
|
242
|
+
- try/data_types/counter_try.rb
|
209
243
|
- try/data_types/datatype_base_try.rb
|
210
244
|
- try/data_types/hash_try.rb
|
211
245
|
- try/data_types/list_try.rb
|
246
|
+
- try/data_types/lock_try.rb
|
212
247
|
- try/data_types/set_try.rb
|
213
248
|
- try/data_types/sorted_set_try.rb
|
214
249
|
- try/data_types/string_try.rb
|
215
250
|
- try/debugging/README.md
|
216
251
|
- try/debugging/cache_behavior_tracer.rb
|
252
|
+
- try/debugging/debug_aad_process.rb
|
253
|
+
- try/debugging/debug_concealed_internal.rb
|
254
|
+
- try/debugging/debug_concealed_reveal.rb
|
255
|
+
- try/debugging/debug_context_aad.rb
|
256
|
+
- try/debugging/debug_context_simple.rb
|
257
|
+
- try/debugging/debug_cross_context.rb
|
258
|
+
- try/debugging/debug_database_load.rb
|
259
|
+
- try/debugging/debug_encrypted_json_check.rb
|
260
|
+
- try/debugging/debug_encrypted_json_step_by_step.rb
|
261
|
+
- try/debugging/debug_exists_lifecycle.rb
|
262
|
+
- try/debugging/debug_field_decrypt.rb
|
263
|
+
- try/debugging/debug_fresh_cross_context.rb
|
264
|
+
- try/debugging/debug_load_path.rb
|
265
|
+
- try/debugging/debug_method_definition.rb
|
266
|
+
- try/debugging/debug_method_resolution.rb
|
267
|
+
- try/debugging/debug_minimal.rb
|
268
|
+
- try/debugging/debug_provider.rb
|
269
|
+
- try/debugging/debug_secure_behavior.rb
|
270
|
+
- try/debugging/debug_string_class.rb
|
271
|
+
- try/debugging/debug_test.rb
|
272
|
+
- try/debugging/debug_test_design.rb
|
217
273
|
- try/debugging/encryption_method_tracer.rb
|
218
274
|
- try/debugging/provider_diagnostics.rb
|
219
275
|
- try/edge_cases/empty_identifiers_try.rb
|
@@ -231,11 +287,13 @@ files:
|
|
231
287
|
- try/encryption/providers/xchacha20_poly1305_provider_try.rb
|
232
288
|
- try/encryption/roundtrip_validation_try.rb
|
233
289
|
- try/encryption/secure_memory_handling_try.rb
|
290
|
+
- try/features/categorical_permissions_try.rb
|
234
291
|
- try/features/encrypted_fields_core_try.rb
|
235
292
|
- try/features/encrypted_fields_integration_try.rb
|
236
293
|
- try/features/encrypted_fields_no_cache_security_try.rb
|
237
294
|
- try/features/encrypted_fields_security_try.rb
|
238
295
|
- try/features/encryption_fields/aad_protection_try.rb
|
296
|
+
- try/features/encryption_fields/concealed_string_core_try.rb
|
239
297
|
- try/features/encryption_fields/context_isolation_try.rb
|
240
298
|
- try/features/encryption_fields/error_conditions_try.rb
|
241
299
|
- try/features/encryption_fields/fresh_key_derivation_try.rb
|
@@ -244,12 +302,19 @@ files:
|
|
244
302
|
- try/features/encryption_fields/memory_security_try.rb
|
245
303
|
- try/features/encryption_fields/missing_current_key_version_try.rb
|
246
304
|
- try/features/encryption_fields/nonce_uniqueness_try.rb
|
305
|
+
- try/features/encryption_fields/secure_by_default_behavior_try.rb
|
247
306
|
- try/features/encryption_fields/thread_safety_try.rb
|
307
|
+
- try/features/encryption_fields/universal_serialization_safety_try.rb
|
248
308
|
- try/features/expiration_try.rb
|
249
309
|
- try/features/feature_dependencies_try.rb
|
250
310
|
- try/features/quantization_try.rb
|
251
311
|
- try/features/real_feature_integration_try.rb
|
252
|
-
- try/features/
|
312
|
+
- try/features/relationships_edge_cases_try.rb
|
313
|
+
- try/features/relationships_performance_minimal_try.rb
|
314
|
+
- try/features/relationships_performance_simple_try.rb
|
315
|
+
- try/features/relationships_performance_try.rb
|
316
|
+
- try/features/relationships_performance_working_try.rb
|
317
|
+
- try/features/relationships_try.rb
|
253
318
|
- try/features/safe_dump_advanced_try.rb
|
254
319
|
- try/features/safe_dump_try.rb
|
255
320
|
- try/features/transient_fields/redacted_string_try.rb
|
@@ -296,6 +361,10 @@ files:
|
|
296
361
|
- try/prototypes/pooling/lib/visualize_stress_results.rb
|
297
362
|
- try/prototypes/pooling/pool_siege.rb
|
298
363
|
- try/prototypes/pooling/run_stress_tests.rb
|
364
|
+
- try/validation/atomic_operations_try.rb.disabled
|
365
|
+
- try/validation/command_validation_try.rb.disabled
|
366
|
+
- try/validation/performance_validation_try.rb.disabled
|
367
|
+
- try/validation/real_world_scenarios_try.rb.disabled
|
299
368
|
homepage: https://github.com/delano/familia
|
300
369
|
licenses:
|
301
370
|
- MIT
|
data/TEST_COVERAGE.md
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
# Encryption Test Coverage
|
2
|
-
|
3
|
-
## Summary
|
4
|
-
- **149/150 tests passing** (99.3%)
|
5
|
-
- **12 test files**, 281ms execution
|
6
|
-
- **1 failing test** in integration suite
|
7
|
-
|
8
|
-
## Test Distribution
|
9
|
-
|
10
|
-
| Category | Files | Tests | Status |
|
11
|
-
|----------|-------|-------|---------|
|
12
|
-
| Core Encryption | 6 | 77 | ✅ All Pass |
|
13
|
-
| Providers | 2 | 39 | ✅ All Pass |
|
14
|
-
| Encrypted Fields | 4 | 53 | ⚠️ 1 Failure |
|
15
|
-
|
16
|
-
## Key Test Areas
|
17
|
-
|
18
|
-
### Security Testing (59 tests)
|
19
|
-
- No key caching (22 tests)
|
20
|
-
- AAD tampering detection (15 tests)
|
21
|
-
- Memory wiping verification (11 tests)
|
22
|
-
- Context isolation (11 tests)
|
23
|
-
|
24
|
-
### Provider Testing (39 tests)
|
25
|
-
- XChaCha20-Poly1305: 19 tests
|
26
|
-
- AES-GCM: 20 tests
|
27
|
-
- Round-trip encryption/decryption
|
28
|
-
- Nonce uniqueness and tampering detection
|
29
|
-
|
30
|
-
### Integration Testing (53 tests)
|
31
|
-
- Mixed field types with encryption
|
32
|
-
- Provider selection and algorithm handling
|
33
|
-
- Full model initialization workflows
|
34
|
-
|
35
|
-
## Action Items
|
36
|
-
- [ ] Fix failing integration test in `encrypted_fields_integration_try.rb:186`
|
37
|
-
- [x] All security properties validated
|
38
|
-
- [x] Both encryption providers fully tested
|
39
|
-
|
40
|
-
## Coverage Assessment: **Production Ready**
|
@@ -1,125 +0,0 @@
|
|
1
|
-
# apps/api/v2/models/features/relatable_object.rb
|
2
|
-
|
3
|
-
module V2
|
4
|
-
module Features
|
5
|
-
class RelatableObjectError < Familia::Problem; end
|
6
|
-
|
7
|
-
# RelatableObject
|
8
|
-
#
|
9
|
-
# Provides the standard core object fields and methods.
|
10
|
-
#
|
11
|
-
module RelatableObject
|
12
|
-
def self.included(base)
|
13
|
-
base.class_sorted_set :relatable_objids
|
14
|
-
base.class_hashkey :owners
|
15
|
-
|
16
|
-
# NOTE: we do not automatically assign the objid field as the
|
17
|
-
# main identifier field. That's up to the implementing class.
|
18
|
-
base.field :objid
|
19
|
-
base.field :extid
|
20
|
-
base.field :api_version
|
21
|
-
|
22
|
-
base.extend(ClassMethods)
|
23
|
-
|
24
|
-
# prepend ensures our methods execute BEFORE field-generated accessors
|
25
|
-
# include would place them AFTER, but they'd never execute because
|
26
|
-
# attr_reader doesn't call super - it just returns the instance variable
|
27
|
-
#
|
28
|
-
# Method lookup chain:
|
29
|
-
# prepend: [InstanceMethods] → [Field Methods] → [Parent]
|
30
|
-
# include: [Field Methods] → [InstanceMethods] → [Parent]
|
31
|
-
# (stops here, no super) (never reached)
|
32
|
-
#
|
33
|
-
base.prepend(InstanceMethods)
|
34
|
-
end
|
35
|
-
|
36
|
-
module InstanceMethods
|
37
|
-
# We lazily generate the object ID and external ID when they are first
|
38
|
-
# accessed so that we can instantiate and load existing objects, without
|
39
|
-
# eagerly generating them, only to be overridden by the storage layer.
|
40
|
-
#
|
41
|
-
def init
|
42
|
-
super if defined?(super) # Only call if parent has init
|
43
|
-
|
44
|
-
@api_version ||= 'v2'
|
45
|
-
end
|
46
|
-
|
47
|
-
def objid
|
48
|
-
@objid ||= begin # lazy loader
|
49
|
-
generated_id = self.class.generate_objid
|
50
|
-
# Using the attr_writer method ensures any future Familia
|
51
|
-
# enhancements to the setter are properly invoked (as opposed
|
52
|
-
# to directly assigning @objid).
|
53
|
-
self.objid = generated_id
|
54
|
-
end
|
55
|
-
end
|
56
|
-
alias relatable_objid objid
|
57
|
-
|
58
|
-
def extid
|
59
|
-
@extid ||= begin # lazy loader
|
60
|
-
generated_id = self.class.generate_extid
|
61
|
-
self.extid = generated_id
|
62
|
-
end
|
63
|
-
end
|
64
|
-
alias external_identifier extid
|
65
|
-
|
66
|
-
# Check if the given customer is the owner of this domain
|
67
|
-
#
|
68
|
-
# @param cust [V2::Customer, String] The customer object or customer ID to check
|
69
|
-
# @return [Boolean] true if the customer is the owner, false otherwise
|
70
|
-
def owner?(related_object)
|
71
|
-
self.class.relatable?(related_object) do
|
72
|
-
# Check the hash (our objid => related_object's objid)
|
73
|
-
owner_objid = self.class.owners.get(objid).to_s
|
74
|
-
return false if owner_objid.empty?
|
75
|
-
|
76
|
-
owner_objid.eql?(related_object.objid)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def owned?
|
81
|
-
# We can only have an owner if we are relatable ourselves.
|
82
|
-
return false unless is_a?(RelatableObject)
|
83
|
-
|
84
|
-
# If our object identifier is present, we have an owner
|
85
|
-
self.class.owners.key?(objid)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
module ClassMethods
|
90
|
-
def relatable?(obj, &)
|
91
|
-
is_relatable = obj.is_a?(RelatableObject)
|
92
|
-
err_klass = V2::Features::RelatableObjectError
|
93
|
-
raise err_klass, 'Not relatable object' unless is_relatable
|
94
|
-
raise err_klass, 'No self-ownership' if obj.class == self
|
95
|
-
|
96
|
-
block_given? ? yield : is_relatable
|
97
|
-
end
|
98
|
-
|
99
|
-
def find_by_objid(objid)
|
100
|
-
return nil if objid.to_s.empty?
|
101
|
-
|
102
|
-
if Familia.debug?
|
103
|
-
reference = caller(1..1).first
|
104
|
-
Familia.trace :FIND_BY_OBJID, Familia.dbclient(uri), objkey, reference
|
105
|
-
end
|
106
|
-
|
107
|
-
find_by_key objkey
|
108
|
-
end
|
109
|
-
|
110
|
-
def generate_objid
|
111
|
-
SecureRandom.uuid_v7
|
112
|
-
end
|
113
|
-
|
114
|
-
# Guaranteed length of 54
|
115
|
-
def generate_extid
|
116
|
-
format('ext_%s', Familia.generate_id)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
extend ClassMethods
|
120
|
-
|
121
|
-
# Self-register the kids for martial arts classes
|
122
|
-
Familia::Base.add_feature self, :relatable_object
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|