diff --git a/engines/dfc_provider/app/controllers/dfc_provider/events_controller.rb b/engines/dfc_provider/app/controllers/dfc_provider/events_controller.rb index c90b259672..80980450cc 100644 --- a/engines/dfc_provider/app/controllers/dfc_provider/events_controller.rb +++ b/engines/dfc_provider/app/controllers/dfc_provider/events_controller.rb @@ -33,6 +33,8 @@ module DfcProvider return end + DfcImporter.new.import_enterprise_profiles(current_user.id) + render json: { success: true } end diff --git a/engines/dfc_provider/app/services/dfc_importer.rb b/engines/dfc_provider/app/services/dfc_importer.rb new file mode 100644 index 0000000000..9e6e112ab3 --- /dev/null +++ b/engines/dfc_provider/app/services/dfc_importer.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +# Fetch data from another platform and store it locally. +class DfcImporter + def import_enterprise_profiles(platform) + raise "unsupported platform" if platform != "lf-dev" + + endpoint = "https://api.beta.litefarm.org/dfc/enterprises/" + api = DfcPlatformRequest.new(platform) + body = api.call(endpoint) + graph = DfcIo.import(body).to_a + farms = graph.select { |item| item.semanticType == "dfc-b:Enterprise" } + farms.each { |farm| import_profile(farm) } + end + + def import_profile(farm) + address = farm.localizations.first + state = Spree::State.find_by(name: address.region) || Spree::State.first + owner = find_or_import_user(farm) + owner.owned_enterprises.create!( + name: farm.name, + address: Spree::Address.new( + address1: address.street, + city: address.city, + zipcode: address.postalCode, + state: state, + country: state.country, + ), + ) + end + + def find_or_import_user(farm) + email = farm.mainContact.emails.first + user = Spree::User.find_by(email:) + + return user if user + + Spree::User.create!( + email:, + password: SecureRandom.base58(64), + ) + end +end diff --git a/engines/dfc_provider/spec/requests/events_spec.rb b/engines/dfc_provider/spec/requests/events_spec.rb index 9e3514d354..4d3e4ed408 100644 --- a/engines/dfc_provider/spec/requests/events_spec.rb +++ b/engines/dfc_provider/spec/requests/events_spec.rb @@ -74,6 +74,12 @@ RSpec.describe "Events", swagger_doc: "dfc.yaml" do example.metadata[:operation][:parameters].first[:schema][:example] end + before do + stub_request(:post, %r{openid-connect/token$}) + stub_request(:get, "https://api.beta.litefarm.org/dfc/enterprises/") + .to_return(body: "[]") + end + run_test! do expect(json_response["success"]).to eq true end diff --git a/engines/dfc_provider/spec/services/dfc_importer_spec.rb b/engines/dfc_provider/spec/services/dfc_importer_spec.rb new file mode 100644 index 0000000000..d545d66ce2 --- /dev/null +++ b/engines/dfc_provider/spec/services/dfc_importer_spec.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require_relative "../spec_helper" + +# These tests depend on valid OpenID Connect client credentials in your +# `.env.test.local` file. +# +# OPENID_APP_ID="..." +# OPENID_APP_SECRET="..." +RSpec.describe DfcImporter do + it "fetches a list of enterprises", :vcr do + expect { + subject.import_enterprise_profiles("lf-dev") + }.to have_enqueued_mail(Spree::UserMailer, :confirmation_instructions).twice + .and have_enqueued_mail(EnterpriseMailer, :welcome).twice + + # You can show the emails in your browser. + # Consider creating a test helper if you find this useful elsewhere. + # allow(ApplicationMailer).to receive(:delivery_method).and_return(:letter_opener) + # perform_enqueued_jobs(only: ActionMailer::MailDeliveryJob) + end +end diff --git a/spec/fixtures/vcr_cassettes/DfcImporter/fetches_a_list_of_enterprises.yml b/spec/fixtures/vcr_cassettes/DfcImporter/fetches_a_list_of_enterprises.yml new file mode 100644 index 0000000000..c8406aa066 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/DfcImporter/fetches_a_list_of_enterprises.yml @@ -0,0 +1,194 @@ +--- +http_interactions: +- request: + method: post + uri: https://login.fooddatacollaboration.org.uk/realms/dev/protocol/openid-connect/token + body: + encoding: UTF-8 + string: client_id=&client_secret=&grant_type=client_credentials&scope=ReadEnterprise + headers: + User-Agent: + - Faraday v2.9.0 + Content-Type: + - application/x-www-form-urlencoded + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - no-store + Content-Length: + - '1588' + Content-Type: + - application/json + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + Date: + - Mon, 01 Dec 2025 04:20:08 GMT + body: + encoding: UTF-8 + string: '{"access_token":"","expires_in":300,"refresh_expires_in":0,"token_type":"Bearer","not-before-policy":0,"scope":"ReadEnterprise + profile email"}' + recorded_at: Mon, 01 Dec 2025 04:20:08 GMT +- request: + method: get + uri: https://api.beta.litefarm.org/dfc/enterprises/ + body: + encoding: US-ASCII + string: '' + headers: + Authorization: + - "" + User-Agent: + - Faraday v2.9.0 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Mon, 01 Dec 2025 04:20:10 GMT + Content-Type: + - application/json; charset=utf-8 + Content-Length: + - '4547' + Connection: + - keep-alive + Access-Control-Allow-Origin: + - https://beta.litefarm.org + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization + Etag: + - W/"11c3-UUiD8CqcZCyYKDmozGTahVipqsk" + body: + encoding: UTF-8 + string: |- + [ + { + "@context": "https://www.datafoodconsortium.org", + "@graph": [ + { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/23bfd9b1-98b5-4b91-88e5-efa7cb36219d", + "@type": "dfc-b:Enterprise", + "dfc-b:email": "manager@testfarm.example.com", + "dfc-b:hasAddress": { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/23bfd9b1-98b5-4b91-88e5-efa7cb36219d#address" + }, + "dfc-b:hasDescription": "This is a fantastic farm.", + "dfc-b:hasMainContact": { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/23bfd9b1-98b5-4b91-88e5-efa7cb36219d#person-mainContact" + }, + "dfc-b:hasPhoneNumber": { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/23bfd9b1-98b5-4b91-88e5-efa7cb36219d#phoneNumber" + }, + "dfc-b:hasSocialMedia": [ + { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/23bfd9b1-98b5-4b91-88e5-efa7cb36219d#socialMedia-instagram" + }, + { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/23bfd9b1-98b5-4b91-88e5-efa7cb36219d#socialMedia-facebook" + }, + { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/23bfd9b1-98b5-4b91-88e5-efa7cb36219d#socialMedia-x" + } + ], + "dfc-b:logo": "https://litefarmbeta.nyc3.digitaloceanspaces.com/farm_logo/bc35fc0f-19bc-4892-b487-869294abf37b.webp", + "dfc-b:name": "DFC Test Farm Beta (All Supplied Fields)", + "dfc-b:websitePage": "www.testfarm.example.com" + }, + { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/23bfd9b1-98b5-4b91-88e5-efa7cb36219d#address", + "@type": "dfc-b:Address", + "dfc-b:hasCity": "Vancouver", + "dfc-b:hasCountry": "Canada", + "dfc-b:hasPostalCode": "V6T 1W5", + "dfc-b:hasStreet": "3461 Ross Drive", + "dfc-b:region": "British Columbia" + }, + { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/23bfd9b1-98b5-4b91-88e5-efa7cb36219d#person-mainContact", + "@type": "dfc-b:Person", + "dfc-b:email": "dfctestfarmowner@gmail.com", + "dfc-b:familyName": "Test", + "dfc-b:firstName": "DFC" + }, + { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/23bfd9b1-98b5-4b91-88e5-efa7cb36219d#phoneNumber", + "@type": "dfc-b:PhoneNumber", + "dfc-b:countryCode": "1", + "dfc-b:phoneNumber": "(604) 555-5555" + }, + { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/23bfd9b1-98b5-4b91-88e5-efa7cb36219d#socialMedia-facebook", + "@type": "dfc-b:SocialMedia", + "dfc-b:URL": "https://www.facebook.com/dfc_test_farm/", + "dfc-b:name": "Facebook" + }, + { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/23bfd9b1-98b5-4b91-88e5-efa7cb36219d#socialMedia-instagram", + "@type": "dfc-b:SocialMedia", + "dfc-b:URL": "https://www.instagram.com/dfctest/", + "dfc-b:name": "Instagram" + }, + { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/23bfd9b1-98b5-4b91-88e5-efa7cb36219d#socialMedia-x", + "@type": "dfc-b:SocialMedia", + "dfc-b:URL": "https://x.com/dfc_farm/", + "dfc-b:name": "X" + } + ] + }, + { + "@context": "https://www.datafoodconsortium.org", + "@graph": [ + { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/09788ba1-da02-4b7a-8496-8a2e95cf78cb", + "@type": "dfc-b:Enterprise", + "dfc-b:hasAddress": { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/09788ba1-da02-4b7a-8496-8a2e95cf78cb#address" + }, + "dfc-b:hasMainContact": { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/09788ba1-da02-4b7a-8496-8a2e95cf78cb#person-mainContact" + }, + "dfc-b:name": "Canadian Farm (Minimal fields)" + }, + { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/09788ba1-da02-4b7a-8496-8a2e95cf78cb#address", + "@type": "dfc-b:Address", + "dfc-b:hasCity": "Vancouver", + "dfc-b:hasCountry": "Canada", + "dfc-b:hasPostalCode": "V6A 3Z7", + "dfc-b:hasStreet": "1455 Quebec Street", + "dfc-b:region": "British Columbia" + }, + { + "@id": "https://api.beta.litefarm.org/dfc/enterprises/09788ba1-da02-4b7a-8496-8a2e95cf78cb#person-mainContact", + "@type": "dfc-b:Person", + "dfc-b:email": "owner@minimal.example.com", + "dfc-b:familyName": "Owner", + "dfc-b:firstName": "Minimal Farm" + } + ] + } + ] + recorded_at: Mon, 01 Dec 2025 04:20:10 GMT +recorded_with: VCR 6.2.0