Add service to access FDC API

The current implementation of the FDC is not adhering to the DFC
standard. The difference is added in this compatibility layer.

This should be temporary code. The FDC dev team should change their API
in their next development cycle.
This commit is contained in:
Maikel Linke
2024-05-23 17:02:49 +10:00
parent 635234a889
commit 1f00662709
4 changed files with 280 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
# frozen_string_literal: true
require "private_address_check"
require "private_address_check/tcpsocket_ext"
# Request a JSON document from the FDC API with authentication.
#
# Currently, the API doesn't quite comply with the DFC standard and we need
# to authenticate a little bit differently.
#
# And then we get slightly different data as well.
class FdcRequest < DfcRequest
# Override main method to POST authorization data.
def call(url, data = {})
response = request(url, auth_data.merge(data).to_json)
if response.status >= 400 && token_stale?
refresh_access_token!
response = request(url, auth_data.merge(data).to_json)
end
response.body
end
private
def auth_data
{
userId: @user.oidc_account.uid,
accessToken: @user.oidc_account.token,
}
end
end

View File

@@ -0,0 +1,36 @@
# frozen_string_literal: true
require_relative "../spec_helper"
RSpec.describe FdcRequest do
subject(:api) { FdcRequest.new(user) }
let(:user) { build(:oidc_user) }
let(:account) { user.oidc_account }
let(:url) {
"https://food-data-collaboration-produc-fe870152f634.herokuapp.com/fdc/products?shop=test-hodmedod.myshopify.com"
}
it "refreshes the access token and retrieves a catalog", vcr: true do
# A refresh is only attempted if the token is stale.
account.uid = "testdfc@protonmail.com"
account.refresh_token = ENV.fetch("OPENID_REFRESH_TOKEN")
account.updated_at = 1.day.ago
response = nil
expect {
response = api.call(url)
}.to change {
account.token
}.and change {
account.refresh_token
}
json = JSON.parse(response)
expect(json["message"]).to eq "Products retrieved successfully"
graph = DfcIo.import(json["products"])
products = graph.select { |s| s.semanticType == "dfc-b:SuppliedProduct" }
expect(products).to be_present
end
end

File diff suppressed because one or more lines are too long

View File

@@ -40,4 +40,9 @@ VCR.configure do |config|
config.filter_sensitive_data('<HIDDEN-OPENID-TOKEN>') { |interaction|
interaction.response.body.match(/"refresh_token":"([^"]+)"/)&.public_send(:[], 1)
}
# FDC specific parameter:
config.filter_sensitive_data('<HIDDEN-OPENID-TOKEN>') { |interaction|
interaction.request.body.match(/"accessToken":"([^"]+)"/)&.public_send(:[], 1)
}
end