Skip to content
This repository has been archived by the owner on Oct 31, 2021. It is now read-only.

Firebase Functions

Jenda Kolena edited this page May 5, 2021 · 51 revisions

Custom Endpoints

All endpoints have JSON API.
As is requested/done implicitly by the Firebase SDK, body of the request is expected to be wrapped in data field, e.g. {"data": { "ehrid": "..."}}. There exists a way how to send unwrapped request (mainly for testing purposes): just add X-Erouska-Wrapped: false header to the request.

All functions (except registerEhrid) are authenticated using ID token - see docs for where to get it. The custom token is returned in the response of registerEhrid. The ID token has to be included in all functions called by the client as idToken parameter (in the request JSON) even if not specified explicitly below. The eHRID is encoded in the ID token and there's no need to provide it again explicitly.

RegisterEhrid

Creates a new registration, saved to registrations collection.

Input:

  • platform (string; android/ ios)
  • platformVersion (string; system version, e.g. 10.0.4)
  • manufacturer (string; phone manufacturer, e.g. Samsung)
  • model (string; phone model, e.g. Galaxy S7)
  • locale (string; phone language, e.g. cs_CZ)
  • pushRegistrationToken (string; push token from Firebase Cloud Messaging)

Output:

  • customToken (string; created custom token to be exchanged for ID token on client)

RegisterNotification

In the registrations collection, changes the value of lastNotificationStatus attribute to sent and the value of lastNotificationUpdatedAt attribute to CURRENT_TIMESTAMP for a given eHRID.

Input:

  • idToken (string; ID token of the client)

ChangePushToken

Changes push token for eHRID.

Input

  • idToken (string; ID token of the client)
  • pushRegistrationToken (string)

GetCovidData

Returns data from collections covidDataTotal and vaccinations for the given input date (if date is missing, TODAY is used)

Input:

  • idToken (string; ID token of the client)
  • date (DATE, optional)

Output: from collection covidDataTotal:

  • date (DATE)
  • activeCasesTotal* (Int)
  • curedTotal* (Int)
  • deceasedTotal* (Int)
  • currentlyHospitalizedTotal* (Int)
  • testsTotal* (Int)
  • testsIncrease* (Int)
  • testsIncreaseDate* (DATE)
  • confirmedCasesTotal* (Int)
  • confirmedCasesIncrease* (Int)
  • confirmedCasesIncreaseDate* (DATE)
  • antigenTestsTotal* (Int)
  • antigenTestsIncrease* (Int)
  • antigenTestsIncreaseDate* (DATE)
  • pcrTestsTotal* (Int)
  • pcrTestsIncrease* (Int)
  • pcrTestsIncreaseDate* (DATE)

from collection vaccinations:

  • vaccinationsTotal* (Int)
  • vaccinationsIncrease* (Int)
  • vaccinationsIncreaseDate* (DATE)
  • vaccinationsDailyDosesDate* (DATE)
  • vaccinationsDailyFirstDose* (Int)
  • vaccinationsDailySecondDose* (Int)
  • vaccinationsTotalFirstDose* (Int)
  • vaccinationsTotalSecondDose* (Int)

DownloadMetrics

This function is NOT authenticated.
It serves metrics JSON for yesterday's data generated by metricsapi.PrepareNewVersion.

No input.

Output:
JSON with the data.

Server Functions

Note: these functions are not subject to authentication using ID token.

RegisterEhridAftermath

Following each registerEhrid, increases counters of activations in Realtime DB, path userCounters:

  1. Value for today, key format YYYYMMDD by 1
  2. Total value, key total by 1

Is triggered by PubSub event, published by registerEhrid.

Input:

  • ehrid (string; eHRID)

RegisterNotificationAftermath

Following each registerNotification:

  1. Increases by 1 the attemptCount attribute in the dailyNotificationAttemptsEhrid collection for date = TODAY and eHRID = eHRID which requested the registerNotification function. If no entry where eHRID = ehrid and date = TODAY exists, creates one.
  2. Checks whether attempts count = 1
  3. Checks result of previous step - if true,

Is triggered by PubSub event, published by registerNotification.

Input:

  • ehrid (string; eHRID)

DownloadCovidDataTotal

Every 5 minutes, downloads the covid data file. Checks, whether an entry exists in the collection covidDataTotal where date = value of datum in the covid data file.

If not, creates the following entries:

in the collection covidDataTotal where:

  • value of testsTotal in the collection covidDataTotal = value of provedene_testy_celkem in the covid data file
  • testsIncrease = value of provedene_testy_vcerejsi_den
  • pcrTestsTotal = value of provedene_testy_celkem
  • pcrTestsIncrease = value of provedene_testy_vcerejsi_den
  • antigenTestsTotal = provedene_antigenni_testy_celkem
  • antigenTestsIncrease = provedene_antigenni_testy_vcerejsi_den
  • confirmedCasesTotal = value of potvrzene_pripady_celkem
  • confirmedCasesIncrease = value of potvrzene_pripady_vcerejsi_den
  • vaccinationsTotal = value of vykazana_ockovani_celkem
  • vaccinationsIncrease = value of vykazana_ockovani_vcerejsi_den
  • activeCasesTotal = value of aktivni_pripady
  • curedTotal = value of vyleceni
  • deceasedTotal = value of umrti
  • currentlyHospitalizedTotal = value of aktualne_hospitalizovani
  • testsIncreaseDate = value of provedene_testy_vcerejsi_den_datum
  • pcrTestsIncreaseDate = value of provedene_testy_vcerejsi_den_datum
  • antigenTestsIncreaseDate = value of provedene_antigenni_testy_vcerejsi_den_datum
  • confirmedCasesIncreaseDate = value of potvrzene_pripady_vcerejsi_den_datum
  • vaccinationsIncreaseDate = value of vykazana_ockovani_vcerejsi_den_datum
  • date = value of datum

If yes, overwrites the existing entries for date = value of datum in the covidDataTotal collection with the downloaded entries.

Input:

  • testsTotal (Int)
  • testsIncrease (Int)
  • pcrTestsTotal (Int)
  • pcrTestsIncrease (Int)
  • antigenTestsTotal (Int)
  • antigenTestsIncrease (Int)
  • confirmedCasesTotal (Int)
  • confirmedCasesIncrease (Int)
  • vaccinationsTotal (Int)
  • vaccinationsIncrease (Int)
  • activeCasesTotal (Int)
  • curedTotal (Int)
  • deceasedTotal (Int)
  • currentlyHospitalizedTotal (Int)
  • testsIncreaseDate(DATE)
  • pcrTestsIncreaseDate (DATE)
  • antigenTestsIncreaseDate (DATE)
  • confirmedCasesIncreaseDate (DATE)
  • vaccinationsIncreaseDate (DATE)
  • date (DATE)

downloadAndCountVaccinations

Every 5 minutes,

  1. downloads the vaccinations file.
  2. sums up all the values of "prvnich_davek" in the vaccinations file and saves the resulting sum as TotalFirstDose (int) in the collection vaccinations.
  3. sums up all the values of "druhych_davek" in the vaccinations file and saves the resulting sum as TotalSecondDose (int) in the collection vaccinations.
  4. sums up all the values of "prvnich_davek" of the highest value of "datum" in the vaccinations file and saves the resulting sum as DailyFirstDose (int) in the collection vaccinations.
  5. sums up all the values of "druhych_davek" of the highest value of "datum" in the vaccinations file and saves the resulting sum as DailyFirstDose (int) in the collection vaccinations.
  6. saves the highest value of "datum" in the vaccinations file as Date (string, YYYYMMDD DATE) in the collection vaccinations.

Input:

  • TotalFirstDose (Int)
  • TotalSecondDose (Int)
  • DailyFirstDose (Int)
  • DailySecondDose (Int)
  • Date (string, YYYYMMDD DATE)

PrepareNewVersion

This function generates a record to metrics collection. The data are always generated for yesterday, yet saved with today's date.

Reads the following data:

  1. yesterday's and the total number of app activation
  2. yesterday's and the total number of exposure notifications
  3. yesterday's and the total number of key publishers (== people sharing their keys)

No input nor output.

EFGS integration

A set of cryptographic certs must be provided to the EFGS in advance and saved (together with related private keys) in the Google Secrets Manager to be able to handle the cryptographic magic.

PublishKeys

This function is a proxy for the Publish endpoint of the Key server. It understands a few additional EFGS-related fields in the request. It's transparent from device PoV, however, in reality, it:

  1. Forwards the request to the Key server and its response back to the calling device
  2. Saves uploaded keys (in case of the successful response of the Key server) into own DB
  3. Updates stats counters

Keys saved by this function are later collected and uploaded to EFGS by efgs.UploadBatch (see below). Per official doc, keys saved by this function have the visitedCountries field filled based on the traveler value (i.e. full-country list for traveler = true and empty country list for traveler = false).

This function:

  • doesn't need access to certificates
  • does need access to DB for saving the keys

Input:

  • fields that are normally contained in the publish request, specified by official docs
  • visitedCountries (string[])
  • reportType (enum, one of Unknown, ConfirmedTest, ConfirmedClinicalDiagnosis, SelfReport, Recursive,Revoked)
  • consentToFederation (bool)
  • traveler (bool)

All added fields are optional to provide backward compatibility. The server will use the following defaults:

  • visitedCountries = empty
  • reportType = ConfirmedTest
  • consentToFederation = false
  • traveler = false

See source code.

Output:

The standard response of the Key server Publish endpoint, specified by official docs. Failure of DB save (for the EFGS integration purpose) will not fail the whole request and the device will receive an unmodified response of the Key server in every case.

efgs.UploadBatch

This function is triggered by a scheduler. It collects uploaded keys, changes the value of each key's reportType parameter to confirmedTest, makes a batch from the keys, and sends the batch to the EFGS. Uploaded keys are deleted afterward.

This function:

  • does need access to certificates to be able to sign the batch and to be able to make a secure connection with the EFGS
  • does need access to DB for loading the keys
  • does not need access to PubSub
  • does not need access to Redis

This function has no input nor output.

efgs.DownloadAndSaveYesterdaysKeys

This function is triggered by a scheduler. It downloads data from EFGS with yesterday's date. The value of each downloaded key's reportType parameter is changed to confirmedTest. The downloaded keys are then sorted by their origin country and published to the Key server.
If there are too many of the keys (over configured threshold), a tag of the next batch is submitted into efgs-postponed-yesterdays-downloading PubSub topic which triggers DownloadAndSaveYesterdaysKeysPostponed function.
Downloaded keys are sorted and split into batches. To prevent timeout of the function, it doesn't do import to the Key server by itself but postpones this to the ImportKeysToKeyServer function instead.

This function:

  • does need access to certificates to be able to make a secure connection with the EFGS
  • does not need access to DB
  • does need access to country<->HAID mappings
  • does need access to PubSub (publish)
  • does not need access to Redis

No input or output.

efgs.DownloadAndSaveYesterdaysKeysPostponed

This function is triggered by the efgs-postponed-yesterdays-downloading PubSub topic. It downloads data from EFGS with yesterday's date, beginning with the tag present in input message. The value of each downloaded key's reportType parameter is changed to confirmedTest. The downloaded keys are then sorted by their origin country and published to the Key server.
If there are too many of the keys (over configured threshold), a tag of the next batch is submitted into efgs-postponed-yesterdays-downloading PubSub topic which triggers DownloadAndSaveYesterdaysKeysPostponed function.
Downloaded keys are sorted and split into batches. To prevent timeout of the function, it doesn't do import to the Key server by itself but postpones this to the ImportKeysToKeyServer function instead.

This function:

  • does need access to certificates to be able to make a secure connection with the EFGS
  • does not need access to DB
  • does need access to country<->HAID mappings
  • does need access to PubSub (publish)
  • does not need access to Redis

Input:

  • date (DATE)
  • batchTag (string)

These are params of the batch where the download should start (continue, in fact).

No output.

efgs.DownloadAndSaveKeys

This function is triggered by a scheduler. It downloads data from EFGS with today's date, loading the batch tag (which is about to be downloaded) from Redis (key nextDownloadBatch), and saving the tag of the next batch there again. The tag resets every day to the beginning of the particular day.
To prevent timeout of the function, it doesn't do import to the Key server by itself but postpones this to the ImportKeysToKeyServer function instead.

This function:

  • does need access to certificates to be able to make a secure connection with the EFGS
  • does not need access to DB
  • does need access to country<->HAID mappings
  • does need access to PubSub (publish)
  • does need access to Redis (state storage)

No input or output.

efgs.ImportKeysToKeyServer

This function is triggered by the efgs-import-keys PubSub topic. It takes provided keys and pushes them into the Key Server under provided HAID (doing the necessary job around - contacting Verification Server, keys signing etc.; the same as devices do).

This function:

  • does not need access to certificates to be able to make a secure connection with the EFGS
  • does not need access to DB
  • does need access to admin and device keys for Verification server
  • does not need access to PubSub
  • does not need access to Redis

Input:

  • haid (string)
  • keys ([]ExpKey)

No output.

efgs.CleanupDatabase

Triggered by a scheduler. Cleans EFGS DB from too old keys.

This function:

  • does not need access to certificates to be able to make a secure connection with the EFGS
  • does need access to DB
  • does not need access to admin and device keys for Verification server
  • does not need access to PubSub
  • does not need access to Redis

No input or output.

EFGS internal functions

Only a brief description of some helper functions used by EFGS functions listed above.

efgs.PublishKeysToKeyServer

Publishes key to the Key server under a given HAID.

efgs.utils.CalculateExposureKeysHMAC

Calculates HMAC of given keys as a part of signing procedure during publishing to the Key server.

Other Functions

isEhridActive

Checks if eHRID exists.

Input:

  • idToken (string; ID token of the client)

Output:

  • active (boolean)