Class: ForestAdminAgent::Routes::AbstractAuthenticatedRoute

Inherits:
AbstractRoute
  • Object
show all
Defined in:
lib/forest_admin_agent/routes/abstract_authenticated_route.rb

Instance Method Summary collapse

Methods inherited from AbstractRoute

#add_route, #initialize, #routes, #setup_routes

Constructor Details

This class inherits a constructor from ForestAdminAgent::Routes::AbstractRoute

Instance Method Details

#build(args = {}) ⇒ Object



4
5
6
7
8
9
10
11
12
13
# File 'lib/forest_admin_agent/routes/abstract_authenticated_route.rb', line 4

def build(args = {})
  if args.dig(:headers, 'action_dispatch.remote_ip')
    Facades::Whitelist.check_ip(args[:headers]['action_dispatch.remote_ip'].to_s)
  end

  context = super
  context.caller = Utils::QueryStringParser.parse_caller(args)
  context.permissions = ForestAdminAgent::Services::Permissions.new(context.caller)
  context
end

#format_attributes(args, collection) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/forest_admin_agent/routes/abstract_authenticated_route.rb', line 35

def format_attributes(args, collection)
  record = args[:params][:data][:attributes] || {}

  args[:params][:data][:relationships]&.map do |field, value|
    schema = collection.schema[:fields][field]

    if schema.type == 'ManyToOne'
      record[schema.foreign_key] = value.dig('data', 'id')
    elsif schema.type == 'PolymorphicManyToOne'
      record[schema.foreign_key] = value.dig('data', 'id')
      json_api_type = value.dig('data', 'type')
      # Find matching collection from foreign_collections (handles both singular and plural forms)
      collection_name = schema.foreign_collections.find do |coll_name|
        coll = collection.datasource.get_collection(coll_name)
        coll.name == json_api_type || coll.name.pluralize == json_api_type
      rescue ForestAdminDatasourceToolkit::Exceptions::ForestException
        false
      end || json_api_type
      record[schema.foreign_key_type_field] = collection_name&.gsub('__', '::')
    end
  end

  record || {}
end

#redacted_full_projection(context) ⇒ Object

Never refused: a write must not 403 because the row it just wrote carries a relation the caller cannot read.



17
18
19
20
21
# File 'lib/forest_admin_agent/routes/abstract_authenticated_route.rb', line 17

def redacted_full_projection(context)
  all = ForestAdminDatasourceToolkit::Components::Query::ProjectionFactory.all(context.collection)

  context.permissions.redact_projection(context.collection, all, named_by_caller: false)
end

#redacted_projection_with_pks(context, collection, args) ⇒ Object

with_pks runs after the redaction on purpose. It only re-adds keys for relations the redaction kept a path through, and the serializer needs those keys to emit the readable column behind them — dropping them would take the permitted path down with them. A relation the redaction emptied contributes no path, so nothing is re-added for it.



27
28
29
30
31
32
33
# File 'lib/forest_admin_agent/routes/abstract_authenticated_route.rb', line 27

def redacted_projection_with_pks(context, collection, args)
  requested = Utils::QueryStringParser.parse_requested_projection(collection, args)

  context.permissions.redact_projection(
    collection, requested[:projection], named_by_caller: requested[:named_by_caller]
  ).with_pks(collection)
end