forest_admin_agent 1.42.0 → 1.43.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2efec0ce2de78876bbab2962c838ee712dc576c6133e6b705f6f4c9d62ea998b
4
- data.tar.gz: 557af82363e33d90b02952742832f4cdd3e2283610a4850ce3252eef12f6f3ca
3
+ metadata.gz: 66f7512ff41d63e36a47f1b185aea527183400d42c75bed6d96d89174240c65f
4
+ data.tar.gz: bf0a4a245127713056932ec2b8df5e418dfd8bd4afe7a67fef29d092507b4747
5
5
  SHA512:
6
- metadata.gz: 0dcfa322e26c5fb8c0e65865abf8d5f5ab4cd9a7f3c5e5abe6d86c5b8ffc6149f16ea609417fb3c9ce421b46f81157cb408078e18aced4b6336cb474d0a70a05
7
- data.tar.gz: 350b111bf50db137f596d884d4fceab32fbab20ee9858846d0342b360b731d157a37a9ecd59878483672f9c1411a683302ccac3cf76428714786e2bede72b319
6
+ metadata.gz: a32d256300750da27e820335a8b1c9953d967edca5f5d88b946c5d89ff33a3fee793e63ad7d800560c6e422bb97e30a3c04df032c607fb64c81aaa0b2bf42715
7
+ data.tar.gz: b050f6daf82e9596b99fc8d235acc62b478f44e2f2d6463570ff68b3e19a5582f9b8021ddf2f7e16d0ef6906202b962c5f2fec5122f68e7638b7e982553ad568
@@ -27,6 +27,7 @@ module ForestAdminAgent
27
27
  build_container
28
28
  build_cache
29
29
  build_logger
30
+ warn_relation_read_permissions_skipped
30
31
  end
31
32
 
32
33
  def add_datasource(datasource, options = {})
@@ -341,6 +342,19 @@ module ForestAdminAgent
341
342
  Facades::Container.cache(:skip_schema_update) == true
342
343
  end
343
344
 
345
+ # An auditor reading the boot log should see the weakened posture without reading the config.
346
+ # Read from the options `setup` was handed: `Facades::Container` resolves against
347
+ # `AgentFactory.instance`, which a host subclassing this factory has not populated.
348
+ def warn_relation_read_permissions_skipped
349
+ return unless @options.to_h[:skip_relation_read_permissions] == true
350
+
351
+ @logger.log(
352
+ 'Warn',
353
+ '[ForestAdmin] skip_relation_read_permissions is true: columns of collections the caller ' \
354
+ 'has no read permission on are served when a relation path reaches them'
355
+ )
356
+ end
357
+
344
358
  def log_schema_skip
345
359
  @logger.log('Warn', '[ForestAdmin] Schema update skipped (skip_schema_update flag is true)')
346
360
  environment = Facades::Container.cache(:is_production) ? 'production' : 'development'
@@ -68,7 +68,8 @@ module ForestAdminAgent
68
68
  canUseProjectionViaHeader: true,
69
69
  canUseProjectionViaHeaderOnList: true,
70
70
  canUseMultipleFieldsProjectionOnRelation: true,
71
- canUseAuditTrail: audit_trail_enabled?
71
+ canUseAuditTrail: audit_trail_enabled?,
72
+ checksRelationReadPermissions: !skip_relation_read_permissions?
72
73
  }
73
74
  },
74
75
  status: 200
@@ -83,6 +84,10 @@ module ForestAdminAgent
83
84
  def audit_trail_enabled?
84
85
  !::ForestAdminAgent::AuditTrail.store.nil?
85
86
  end
87
+
88
+ def skip_relation_read_permissions?
89
+ ForestAdminAgent::Facades::Container.config_from_cache[:skip_relation_read_permissions] == true
90
+ end
86
91
  end
87
92
  end
88
93
  end
@@ -55,6 +55,10 @@ module ForestAdminAgent
55
55
  field.nil? || field.to_s.empty? ? nil : field
56
56
  end
57
57
 
58
+ def skip_relation_read_permissions?
59
+ ForestAdminAgent::Facades::Container.config_from_cache[:skip_relation_read_permissions] == true
60
+ end
61
+
58
62
  def validate_and_get_type(type)
59
63
  chart_types = %w[Value Objective Pie Line Leaderboard]
60
64
  unless chart_types.include?(type)
@@ -202,8 +206,9 @@ module ForestAdminAgent
202
206
  )
203
207
 
204
208
  # A count exposes the cardinality of the relation, which `/relationships/<name>/count`
205
- # puts behind `browse`. No path names it, so nothing above sees it.
206
- if aggregation.field.nil?
209
+ # puts behind `browse`. No path names it, so nothing above sees it. It arrived with the
210
+ # related-read checks, so it goes away with them.
211
+ if aggregation.field.nil? && !skip_relation_read_permissions?
207
212
  context.permissions.can?(:browse, context.datasource.get_collection(field.foreign_collection))
208
213
  end
209
214
 
@@ -66,7 +66,10 @@ module ForestAdminAgent
66
66
 
67
67
  # An absent permission system is not a denial: `can?` allows everything there, and answering
68
68
  # anything else would redact every relation on a deployment that granted nothing to check.
69
- return allowed.merge(to_check.to_h { |name| [name, true] }) unless permission_system?
69
+ # `skip_relation_read_permissions` is the operator asking for that same answer on purpose.
70
+ if skip_relation_read_permissions? || !permission_system?
71
+ return allowed.merge(to_check.to_h { |name| [name, true] })
72
+ end
70
73
 
71
74
  @read_permissions ||= {}
72
75
  missing = to_check - @read_permissions.keys
@@ -273,6 +276,10 @@ module ForestAdminAgent
273
276
  names.any? && names.all? { |name| allowed[name] }
274
277
  end
275
278
 
279
+ def skip_relation_read_permissions?
280
+ Facades::Container.config_from_cache[:skip_relation_read_permissions] == true
281
+ end
282
+
276
283
  def leaf_label(names)
277
284
  names.empty? ? 'an unresolved polymorphic relation' : "the '#{names.join("' or '")}' collection"
278
285
  end
@@ -356,6 +363,8 @@ module ForestAdminAgent
356
363
  return unless search_extended
357
364
  return unless describes_own_search?(collection)
358
365
  return unless permission_system?
366
+ # Refused ahead of `read_permissions`, so the skip has to be read here as well.
367
+ return if skip_relation_read_permissions?
359
368
 
360
369
  raise ForbiddenError,
361
370
  "You cannot run an extended search on the '#{collection.name}' collection: the fields " \
@@ -50,7 +50,7 @@ module ForestAdminAgent
50
50
  end
51
51
 
52
52
  def self.parse_projection_from_header(collection, args)
53
- header = args.dig(:headers, 'HTTP_FOREST_PROJECTION')&.to_s&.strip
53
+ header = decode_header_value(args.dig(:headers, 'HTTP_FOREST_PROJECTION'))&.strip
54
54
 
55
55
  return if header.nil? || header.empty?
56
56
 
@@ -83,6 +83,21 @@ module ForestAdminAgent
83
83
  }
84
84
  end
85
85
 
86
+ # Rack hands header values back as raw bytes. A column named after a workspace's own free
87
+ # text -- `Ce que j'ai vérifié` -- reaches us either as UTF-8 or, from a browser (which
88
+ # sends a header value as one byte per code unit), as Latin-1. Left tagged BINARY it
89
+ # matches no schema key, and interpolating it into the not-found message raises
90
+ # Encoding::CompatibilityError before that 400 is ever built. The fallback cannot raise
91
+ # in turn: ISO-8859-1 defines all 256 bytes, and each maps to a character UTF-8 can hold.
92
+ def self.decode_header_value(value)
93
+ return if value.nil?
94
+
95
+ utf8 = value.to_s.dup.force_encoding(Encoding::UTF_8)
96
+ return utf8 if utf8.valid_encoding?
97
+
98
+ utf8.force_encoding(Encoding::ISO_8859_1).encode(Encoding::UTF_8)
99
+ end
100
+
86
101
  def self.add_polymorphic_type_fields(collection, requested_field_names)
87
102
  polymorphic_relations = collection.schema[:fields].select { |_, field| field.type == 'PolymorphicManyToOne' }
88
103
 
@@ -197,7 +212,7 @@ module ForestAdminAgent
197
212
  "Available fields are: [#{available_fields}]. " \
198
213
  'Please check if the field name is correct.'
199
214
  end
200
- private_class_method :add_polymorphic_type_fields, :build_projection_fields,
215
+ private_class_method :decode_header_value, :add_polymorphic_type_fields, :build_projection_fields,
201
216
  :build_header_projection_fields, :get_field,
202
217
  :expand_polymorphic_leaf, :nested_polymorphic_linkage_fields,
203
218
  :polymorphic_linkage_columns, :each_field_along_path,
@@ -6,7 +6,7 @@ module ForestAdminAgent
6
6
  module Schema
7
7
  class SchemaEmitter
8
8
  LIANA_NAME = "agent-ruby"
9
- LIANA_VERSION = "1.42.0"
9
+ LIANA_VERSION = "1.43.1"
10
10
 
11
11
  def self.generate(datasource)
12
12
  datasource.collections
@@ -1,3 +1,3 @@
1
1
  module ForestAdminAgent
2
- VERSION = "1.42.0"
2
+ VERSION = "1.43.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forest_admin_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.42.0
4
+ version: 1.43.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthieu
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2026-09-02 00:00:00.000000000 Z
12
+ date: 2026-09-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport