/**
 * Defines services and register them to the Service Container.
 */ import * as dotenv from "dotenv" ; import { parseJSON , right , toError } from "fp-ts/lib/Either" ; import { fromNullable , isSome } from "fp-ts/lib/Option" ; import * as t from "io-ts" ; import { record } from "fp-ts" ; import { agent } from "italia-ts-commons" ; import { getNodeEnvironmentFromProcessEnv , NodeEnvironmentEnum } from "italia-ts-commons/lib/environment" ; import { errorsToReadableMessages , readableReport } from "italia-ts-commons/lib/reporters" ; import { UrlFromString } from "italia-ts-commons/lib/url" ; import { IApplicationConfig , IServiceProviderConfig , SamlConfig } from "@pagopa/io-spid-commons" ; import { rights } from "fp-ts/lib/Array" ; import { AbortableFetch , setFetchTimeout , toFetch } from "italia-ts-commons/lib/fetch" ; import { IntegerFromString } from "italia-ts-commons/lib/numbers" ; import { NonEmptyString } from "italia-ts-commons/lib/strings" ; import { FiscalCode } from "italia-ts-commons/lib/strings" ; import { Millisecond , Second } from "italia-ts-commons/lib/units" ; import { CgnAPIClient } from "./clients/cgn" ; import { log } from "./utils/logger" ; import urlTokenStrategy from "./strategies/urlTokenStrategy" ; import { getRequiredENVVar , readFile } from "./utils/container" ; import PagoPAClientFactory from "./services/pagoPAClientFactory" ; import ApiClientFactory from "./services/apiClientFactory" ; import { BonusAPIClient } from "./clients/bonus" ; import { CommaSeparatedListOf , STRINGS_RECORD } from "./types/commons" ; import { SpidLevelArray } from "./types/spidLevel" ; import { decodeCIDRs } from "./utils/cidrs" ; import { CgnOperatorSearchAPIClient } from "./clients/cgn-operator-search" ; import { EUCovidCertAPIClient } from "./clients/eucovidcert.client" ; import * as pecClient from "./clients/pecserver" ; dotenv . config ( ) ; log . info ( `App service assigned port ${ process . env . PORT }` ) ; const DEFAULT_SERVER_PORT = "80" ; export const SERVER_PORT = process . env . PORT || DEFAULT_SERVER_PORT ; export const ENV = getNodeEnvironmentFromProcessEnv ( process . env ) ; const DEFAULT_CACHE_MAX_AGE_SECONDS = "300" ; export const CACHE_MAX_AGE_SECONDS = parseInt ( process . env . CACHE_MAX_AGE_SECONDS || DEFAULT_CACHE_MAX_AGE_SECONDS , 10 ) ; const DEFAULT_CGN_OPERATOR_SEARCH_CACHE_MAX_AGE_SECONDS = "3600" ; export const CGN_OPERATOR_SEARCH_CACHE_MAX_AGE_SECONDS = parseInt ( process . env . CGN_OPERATOR_SEARCH_CACHE_MAX_AGE_SECONDS || DEFAULT_CGN_OPERATOR_SEARCH_CACHE_MAX_AGE_SECONDS , 10 ) ; export const ENABLE_NOTICE_EMAIL_CACHE = fromNullable ( process . env . ENABLE_NOTICE_EMAIL_CACHE ) . map ( _ => _ . toLowerCase ( ) === "true" ) . getOrElse ( false ) ; const samlKey = ( ) => fromNullable ( process . env . SAML_KEY ) . getOrElseL ( ( ) => readFile ( process . env . SAML_KEY_PATH || "./certs/key.pem" , "SAML private key" ) ) ; export const SAML_KEY = samlKey ( ) ; const samlCert = ( ) => fromNullable ( process . env . SAML_CERT ) . getOrElseL ( ( ) => readFile ( process . env . SAML_CERT_PATH || "./certs/cert.pem" , "SAML certificate" ) ) ; export const SAML_CERT = samlCert ( ) ; const SAML_CALLBACK_URL = process . env . SAML_CALLBACK_URL || "http://italia-backend/assertionConsumerService" ; const SAML_LOGOUT_CALLBACK_URL = process . env . SAML_LOGOUT_CALLBACK_URL || "http://italia-backend/slo" ; const SAML_ISSUER = process . env . SAML_ISSUER || "https://spid.agid.gov.it/cd" ; const DEFAULT_SAML_ATTRIBUTE_CONSUMING_SERVICE_INDEX = "1" ; const SAML_ATTRIBUTE_CONSUMING_SERVICE_INDEX = process . env . SAML_ATTRIBUTE_CONSUMING_SERVICE_INDEX || DEFAULT_SAML_ATTRIBUTE_CONSUMING_SERVICE_INDEX ; const DEFAULT_SAML_ACCEPTED_CLOCK_SKEW_MS = "-1" ; const SAML_ACCEPTED_CLOCK_SKEW_MS = parseInt ( process . env . SAML_ACCEPTED_CLOCK_SKEW_MS || DEFAULT_SAML_ACCEPTED_CLOCK_SKEW_MS , 10 ) ; const SPID_TESTENV_URL = process . env . SPID_TESTENV_URL ; export const IDP_METADATA_URL = getRequiredENVVar ( "IDP_METADATA_URL" ) ; const CIE_METADATA_URL = getRequiredENVVar ( "CIE_METADATA_URL" ) ; export const STARTUP_IDPS_METADATA = fromNullable ( process . env . STARTUP_IDPS_METADATA ) . map ( _ => parseJSON ( _ , toError ) . chain < Record < string , string > | undefined > ( _1 => STRINGS_RECORD . decode ( _1 ) . mapLeft ( err => new Error ( errorsToReadableMessages ( err ) . join ( " / " ) ) ) ) . getOrElse ( undefined ) ) . getOrElse ( undefined ) ; export const CLIENT_ERROR_REDIRECTION_URL = process . env . CLIENT_ERROR_REDIRECTION_URL || "/error.html" ; export const CLIENT_REDIRECTION_URL = process . env . CLIENT_REDIRECTION_URL || "/login" ; const SPID_LEVEL_WHITELIST = fromNullable ( process . env . SPID_LEVEL_WHITELIST ) . map ( _ => _ . split ( "," ) ) . foldL ( ( ) => { if ( ENV === NodeEnvironmentEnum . DEVELOPMENT ) { return right < t . Errors , SpidLevelArray > ( [ "SpidL1" , "SpidL2" , "SpidL3" ] ) ; } return right < t . Errors , SpidLevelArray > ( [ "SpidL2" , "SpidL3" ] ) ; } , _ => SpidLevelArray . decode ( _ ) ) . getOrElseL ( err => { log . error ( "Invalid value for SPID_LEVEL_WHITELIST env [%s]" , readableReport ( err ) ) ; return process . exit ( 1 ) ; } ) ; export const appConfig = { assertionConsumerServicePath : "/assertionConsumerService" , clientErrorRedirectionUrl : CLIENT_ERROR_REDIRECTION_URL , clientLoginRedirectionUrl : CLIENT_REDIRECTION_URL , loginPath : "/login" , metadataPath : "/metadata" , sloPath : "/slo" , spidLevelsWhitelist : SPID_LEVEL_WHITELIST , startupIdpsMetadata : STARTUP_IDPS_METADATA } ; const maybeSpidValidatorUrlOption = fromNullable ( process . env . SPID_VALIDATOR_URL ) . map ( _ => ( { [ _ ] : true } ) ) ; const maybeSpidTestenvOption = fromNullable ( SPID_TESTENV_URL ) . map ( _ => ( { [ _ ] : true } ) ) ; export const DEFAULT_IDP_METADATA_REFRESH_INTERVAL_SECONDS = 3600 * 24 * 7 ; export const IDP_METADATA_REFRESH_INTERVAL_SECONDS = process . env . IDP_METADATA_REFRESH_INTERVAL_SECONDS ? parseInt ( process . env . IDP_METADATA_REFRESH_INTERVAL_SECONDS , 10 ) : DEFAULT_IDP_METADATA_REFRESH_INTERVAL_SECONDS ; log . info ( "IDP metadata refresh interval set to %s seconds" , IDP_METADATA_REFRESH_INTERVAL_SECONDS ) ; export const serviceProviderConfig = { IDPMetadataUrl : IDP_METADATA_URL , organization : { URL : "https://io.italia.it" , displayName : "IO - l'app dei servizi pubblici BETA" , name : "PagoPA S.p.A." } , publicCert : samlCert ( ) , requiredAttributes : { attributes : [ "email" , "name" , "familyName" , "fiscalNumber" , "dateOfBirth" ] , name : "IO - l'app dei servizi pubblici BETA" } , spidCieUrl : CIE_METADATA_URL , spidTestEnvUrl : SPID_TESTENV_URL , spidValidatorUrl : process . env . SPID_VALIDATOR_URL , strictResponseValidation : { ... ( isSome ( maybeSpidTestenvOption ) ? maybeSpidTestenvOption . value : { } ) , ... ( isSome ( maybeSpidValidatorUrlOption ) ? maybeSpidValidatorUrlOption . value : { } ) } } ; export const samlConfig = { RACComparison : "minimum" , acceptedClockSkewMs : SAML_ACCEPTED_CLOCK_SKEW_MS , attributeConsumingServiceIndex : SAML_ATTRIBUTE_CONSUMING_SERVICE_INDEX , authnContext : "https://www.spid.gov.it/SpidL1" , callbackUrl : SAML_CALLBACK_URL , identifierFormat : "urn:oasis:names:tc:SAML:2.0:nameid-format:transient" , issuer : SAML_ISSUER , logoutCallbackUrl : SAML_LOGOUT_CALLBACK_URL , privateCert : samlKey ( ) } ; export const clientProfileRedirectionUrl = process . env . CLIENT_REDIRECTION_URL || "/profile.html?token={token}" ; if ( ! clientProfileRedirectionUrl . includes ( "{token}" ) ) { log . error ( "CLIENT_REDIRECTION_URL must contains a {token} placeholder" ) ; } export const ALLOW_NOTIFY_IP_SOURCE_RANGE = decodeCIDRs ( process . env . ALLOW_NOTIFY_IP_SOURCE_RANGE ) . getOrElseL ( errs => { log . error ( `Missing or invalid ALLOW_NOTIFY_IP_SOURCE_RANGE environment variable: ${ readableReport ( errs ) }` ) ; return process . exit ( 1 ) ; } ) ; export const ALLOW_PAGOPA_IP_SOURCE_RANGE = decodeCIDRs ( process . env . ALLOW_PAGOPA_IP_SOURCE_RANGE ) . getOrElseL ( errs => { log . error ( `Missing or invalid ALLOW_PAGOPA_IP_SOURCE_RANGE environment variable: ${ readableReport ( errs ) }` ) ; return process . exit ( 1 ) ; } ) ; export const ALLOW_MYPORTAL_IP_SOURCE_RANGE = decodeCIDRs ( process . env . ALLOW_MYPORTAL_IP_SOURCE_RANGE ) . getOrElseL ( errs => { log . error ( `Missing or invalid ALLOW_MYPORTAL_IP_SOURCE_RANGE environment variable: ${ readableReport ( errs ) }` ) ; return process . exit ( 1 ) ; } ) ; export const ALLOW_BPD_IP_SOURCE_RANGE = decodeCIDRs ( process . env . ALLOW_BPD_IP_SOURCE_RANGE ) . getOrElseL ( errs => { log . error ( `Missing or invalid ALLOW_BPD_IP_SOURCE_RANGE environment variable: ${ readableReport ( errs ) }` ) ; return process . exit ( 1 ) ; } ) ; export const ALLOW_ZENDESK_IP_SOURCE_RANGE = decodeCIDRs ( process . env . ALLOW_ZENDESK_IP_SOURCE_RANGE ) . getOrElseL ( errs => { log . error ( `Missing or invalid ALLOW_ZENDESK_IP_SOURCE_RANGE environment variable: ${ readableReport ( errs ) }` ) ; return process . exit ( 1 ) ; } ) ; export const ALLOW_SESSION_HANDLER_IP_SOURCE_RANGE = decodeCIDRs ( process . env . ALLOW_SESSION_HANDLER_IP_SOURCE_RANGE ) . getOrElseL ( errs => { log . error ( `Missing or invalid ALLOW_SESSION_HANDLER_IP_SOURCE_RANGE environment variable: ${ readableReport ( errs ) }` ) ; return process . exit ( 1 ) ; } ) ; const DEFAULT_REQUEST_TIMEOUT_MS = 10000 as Millisecond ; const abortableFetch = AbortableFetch ( agent . getHttpFetch ( process . env ) ) ; const fetchWithTimeout = setFetchTimeout ( DEFAULT_REQUEST_TIMEOUT_MS , abortableFetch ) ; const httpApiFetch = toFetch ( fetchWithTimeout ) ; const httpsApiFetch = agent . getHttpsFetch ( process . env ) ; const bearerAuthFetch = ( origFetch = fetch , bearerToken ) : typeof fetch => ( input , init ) => origFetch ( input , { ... init , headers : { Authorization : `Bearer ${ bearerToken }` } } ) ; export const getHttpApiFetchWithBearer = ( bearer ) => toFetch ( setFetchTimeout ( DEFAULT_REQUEST_TIMEOUT_MS , AbortableFetch ( bearerAuthFetch ( agent . getHttpsFetch ( process . env ) , bearer ) ) ) ) ; export const PECSERVER_URL = getRequiredENVVar ( "PECSERVER_URL" ) ; export const PECSERVER_BASE_PATH = getRequiredENVVar ( "PECSERVER_BASE_PATH" ) ; export const PECSERVER_CLIENT = { getClient : ( bearer ) => pecClient . pecServerClient ( PECSERVER_URL , getHttpApiFetchWithBearer ( bearer ) ) } ; export const API_KEY = getRequiredENVVar ( "API_KEY" ) ; export const API_URL = getRequiredENVVar ( "API_URL" ) ; export const API_BASE_PATH = getRequiredENVVar ( "API_BASE_PATH" ) ; export const API_CLIENT = new ApiClientFactory ( API_KEY , API_URL , httpApiFetch ) ; export const BONUS_API_KEY = getRequiredENVVar ( "BONUS_API_KEY" ) ; export const BONUS_API_URL = getRequiredENVVar ( "BONUS_API_URL" ) ; export const BONUS_API_BASE_PATH = getRequiredENVVar ( "BONUS_API_BASE_PATH" ) ; export const BONUS_API_CLIENT = BonusAPIClient ( BONUS_API_KEY , BONUS_API_URL , httpApiFetch ) ; export const CGN_API_KEY = getRequiredENVVar ( "CGN_API_KEY" ) ; export const CGN_API_URL = getRequiredENVVar ( "CGN_API_URL" ) ; export const CGN_API_BASE_PATH = getRequiredENVVar ( "CGN_API_BASE_PATH" ) ; export const CGN_API_CLIENT = CgnAPIClient ( CGN_API_KEY , CGN_API_URL , CGN_API_BASE_PATH , httpApiFetch ) ; export const CGN_OPERATOR_SEARCH_API_KEY = getRequiredENVVar ( "CGN_OPERATOR_SEARCH_API_KEY" ) ; export const CGN_OPERATOR_SEARCH_API_URL = getRequiredENVVar ( "CGN_OPERATOR_SEARCH_API_URL" ) ; export const CGN_OPERATOR_SEARCH_API_BASE_PATH = getRequiredENVVar ( "CGN_OPERATOR_SEARCH_API_BASE_PATH" ) ; export const CGN_OPERATOR_SEARCH_API_CLIENT = CgnOperatorSearchAPIClient ( CGN_OPERATOR_SEARCH_API_KEY , CGN_OPERATOR_SEARCH_API_URL , CGN_OPERATOR_SEARCH_API_BASE_PATH , httpsApiFetch ) ; export const EUCOVIDCERT_API_KEY = getRequiredENVVar ( "EUCOVIDCERT_API_KEY" ) ; export const EUCOVIDCERT_API_URL = getRequiredENVVar ( "EUCOVIDCERT_API_URL" ) ; export const EUCOVIDCERT_API_BASE_PATH = getRequiredENVVar ( "EUCOVIDCERT_API_BASE_PATH" ) ; export const EUCOVIDCERT_API_CLIENT = EUCovidCertAPIClient ( EUCOVIDCERT_API_KEY , EUCOVIDCERT_API_URL , httpApiFetch ) ; export const MIT_VOUCHER_API_BASE_PATH = getRequiredENVVar ( "MIT_VOUCHER_API_BASE_PATH" ) ; const DEFAULT_TOKEN_DURATION_IN_SECONDS = 3600 * 24 * 30 ; export const tokenDurationSecs = process . env . TOKEN_DURATION_IN_SECONDS ? parseInt ( process . env . TOKEN_DURATION_IN_SECONDS , 10 ) : DEFAULT_TOKEN_DURATION_IN_SECONDS ; log . info ( "Session token duration set to %s seconds" , tokenDurationSecs ) ; const pagoPAApiUrlProd = getRequiredENVVar ( "PAGOPA_API_URL_PROD" ) ; const pagoPAApiUrlTest = getRequiredENVVar ( "PAGOPA_API_URL_TEST" ) ; export const PAGOPA_CLIENT = new PagoPAClientFactory ( pagoPAApiUrlProd , pagoPAApiUrlTest , httpsApiFetch ) ; export const AUTHENTICATION_BASE_PATH = getRequiredENVVar ( "AUTHENTICATION_BASE_PATH" ) ; export const PAGOPA_BASE_PATH = getRequiredENVVar ( "PAGOPA_BASE_PATH" ) ; export const MYPORTAL_BASE_PATH = getRequiredENVVar ( "MYPORTAL_BASE_PATH" ) ; export const BPD_BASE_PATH = getRequiredENVVar ( "BPD_BASE_PATH" ) ; export const ZENDESK_BASE_PATH = getRequiredENVVar ( "ZENDESK_BASE_PATH" ) ; export const PRE_SHARED_KEY = getRequiredENVVar ( "PRE_SHARED_KEY" ) ; export const URL_TOKEN_STRATEGY = urlTokenStrategy ( PRE_SHARED_KEY ) ; export const getClientProfileRedirectionUrl = ( token ) : UrlFromString => { const url = clientProfileRedirectionUrl . replace ( "{token}" , token ) ; return { href : url } ; } ; export const ClientErrorRedirectionUrlParams = t . union ( [ t . intersection ( [ t . interface ( { errorMessage : NonEmptyString } ) , t . partial ( { errorCode : t . number } ) ] ) , t . intersection ( [ t . partial ( { errorMessage : NonEmptyString } ) , t . interface ( { errorCode : t . number } ) ] ) , t . interface ( { errorCode : t . number , errorMessage : NonEmptyString } ) ] ) ; export type ClientErrorRedirectionUrlParams = t . TypeOf < typeof ClientErrorRedirectionUrlParams > ; export const getClientErrorRedirectionUrl = ( params ) : UrlFromString => { const errorParams = record . collect ( params , ( key , value ) => `${ key }=${ value }` ) . join ( "&" ) ; const url = CLIENT_ERROR_REDIRECTION_URL . concat ( `?${ errorParams }` ) ; return { href : url } ; } ; export const SPID_LOG_STORAGE_CONNECTION_STRING = getRequiredENVVar ( "SPID_LOG_STORAGE_CONNECTION_STRING" ) ; export const SPID_LOG_QUEUE_NAME = getRequiredENVVar ( "SPID_LOG_QUEUE_NAME" ) ; export const USERS_LOGIN_STORAGE_CONNECTION_STRING = getRequiredENVVar ( "USERS_LOGIN_STORAGE_CONNECTION_STRING" ) ; export const USERS_LOGIN_QUEUE_NAME = getRequiredENVVar ( "USERS_LOGIN_QUEUE_NAME" ) ; export const NOTIFICATIONS_STORAGE_CONNECTION_STRING = getRequiredENVVar ( "NOTIFICATIONS_STORAGE_CONNECTION_STRING" ) ; export const NOTIFICATIONS_QUEUE_NAME = getRequiredENVVar ( "NOTIFICATIONS_QUEUE_NAME" ) ; export const NOTIFICATION_DEFAULT_SUBJECT = "Entra nell'app per leggere il contenuto" ; export const NOTIFICATION_DEFAULT_TITLE = "Hai un nuovo messaggio su IO" ; export const BARCODE_ALGORITHM = NonEmptyString . decode ( process . env . BARCODE_ALGORITHM ) . getOrElse ( "code128" as NonEmptyString ) ; export const DEFAULT_APPINSIGHTS_SAMPLING_PERCENTAGE = 5 ; export const TEST_LOGIN_FISCAL_CODES = NonEmptyString . decode ( process . env . TEST_LOGIN_FISCAL_CODES ) . map ( _ => _ . split ( "," ) ) . map ( _ => rights ( _ . map ( FiscalCode . decode ) ) ) . getOrElse ( [ ] ) ; export const TEST_LOGIN_PASSWORD = NonEmptyString . decode ( process . env . TEST_LOGIN_PASSWORD ) ; export const FF_BONUS_ENABLED = process . env . FF_BONUS_ENABLED === "1" ; export const FF_CGN_ENABLED = process . env . FF_CGN_ENABLED === "1" ; export const FF_EUCOVIDCERT_ENABLED = process . env . FF_EUCOVIDCERT_ENABLED === "1" ; export const FF_MIT_VOUCHER_ENABLED = process . env . FF_MIT_VOUCHER_ENABLED === "1" ; export const FF_USER_AGE_LIMIT_ENABLED = process . env . FF_USER_AGE_LIMIT_ENABLED === "1" ; export const JWT_SUPPORT_TOKEN_PRIVATE_RSA_KEY = NonEmptyString . decode ( process . env . JWT_SUPPORT_TOKEN_PRIVATE_RSA_KEY ) . getOrElseL ( errs => { log . error ( `Missing or invalid JWT_SUPPORT_TOKEN_PRIVATE_RSA_KEY environment variable: ${ readableReport ( errs ) }` ) ; return process . exit ( 1 ) ; } ) ; export const JWT_SUPPORT_TOKEN_ISSUER = NonEmptyString . decode ( process . env . JWT_SUPPORT_TOKEN_ISSUER ) . getOrElseL ( errs => { log . error ( `Missing or invalid JWT_SUPPORT_TOKEN_ISSUER environment variable: ${ readableReport ( errs ) }` ) ; return process . exit ( 1 ) ; } ) ; const DEFAULT_JWT_SUPPORT_TOKEN_EXPIRATION = 604800 as Second ; export const JWT_SUPPORT_TOKEN_EXPIRATION = IntegerFromString . decode ( process . env . JWT_SUPPORT_TOKEN_EXPIRATION ) . getOrElse ( DEFAULT_JWT_SUPPORT_TOKEN_EXPIRATION ) as Second ; log . info ( "JWT support token expiration set to %s seconds" , JWT_SUPPORT_TOKEN_EXPIRATION ) ; export const JWT_ZENDESK_SUPPORT_TOKEN_SECRET = NonEmptyString . decode ( process . env . JWT_ZENDESK_SUPPORT_TOKEN_SECRET ) . getOrElseL ( errs => { log . error ( `Missing or invalid JWT_ZENDESK_SUPPORT_TOKEN_SECRET environment variable: ${ readableReport ( errs ) }` ) ; return process . exit ( 1 ) ; } ) ; export const JWT_ZENDESK_SUPPORT_TOKEN_ISSUER = NonEmptyString . decode ( process . env . JWT_ZENDESK_SUPPORT_TOKEN_ISSUER ) . getOrElseL ( errs => { log . error ( `Missing or invalid JWT_ZENDESK_SUPPORT_TOKEN_ISSUER environment variable: ${ readableReport ( errs ) }` ) ; return process . exit ( 1 ) ; } ) ; const DEFAULT_JWT_ZENDESK_SUPPORT_TOKEN_EXPIRATION = 604800 as Second ; export const JWT_ZENDESK_SUPPORT_TOKEN_EXPIRATION = IntegerFromString . decode ( process . env . JWT_ZENDESK_SUPPORT_TOKEN_EXPIRATION ) . getOrElse ( DEFAULT_JWT_ZENDESK_SUPPORT_TOKEN_EXPIRATION ) as Second ; log . info ( "JWT Zendesk support token expiration set to %s seconds" , JWT_ZENDESK_SUPPORT_TOKEN_EXPIRATION ) ; export const JWT_MIT_VOUCHER_TOKEN_PRIVATE_ES_KEY = NonEmptyString . decode ( process . env . JWT_MIT_VOUCHER_TOKEN_PRIVATE_ES_KEY ) . getOrElseL ( errs => { log . error ( `Missing or invalid JWT_MIT_VOUCHER_TOKEN_PRIVATE_ES_KEY environment variable: ${ readableReport ( errs ) }` ) ; return process . exit ( 1 ) ; } ) ; export const JWT_MIT_VOUCHER_TOKEN_ISSUER = NonEmptyString . decode ( process . env . JWT_MIT_VOUCHER_TOKEN_ISSUER ) . getOrElseL ( errs => { log . error ( `Missing or invalid JWT_MIT_VOUCHER_TOKEN_ISSUER environment variable: ${ readableReport ( errs ) }` ) ; return process . exit ( 1 ) ; } ) ; const DEFAULT_JWT_MIT_VOUCHER_TOKEN_EXPIRATION = 600 as Second ; export const JWT_MIT_VOUCHER_TOKEN_EXPIRATION = IntegerFromString . decode ( process . env . JWT_MIT_VOUCHER_TOKEN_EXPIRATION ) . getOrElse ( DEFAULT_JWT_MIT_VOUCHER_TOKEN_EXPIRATION ) as Second ; log . info ( "JWT Mit Voucher expiration set to %s seconds" , JWT_MIT_VOUCHER_TOKEN_EXPIRATION ) ; export const JWT_MIT_VOUCHER_TOKEN_AUDIENCE = NonEmptyString . decode ( process . env . JWT_MIT_VOUCHER_TOKEN_AUDIENCE ) . getOrElseL ( errs => { log . error ( `Missing or invalid JWT_MIT_VOUCHER_TOKEN_AUDIENCE environment variable: ${ readableReport ( errs ) }` ) ; return process . exit ( 1 ) ; } ) ; export const PECSERVER_TOKEN_SECRET = NonEmptyString . decode ( process . env . PECSERVER_TOKEN_SECRET ) . getOrElseL ( errs => { log . error ( `Missing or invalid PECSERVER_TOKEN_SECRET environment variable: ${ readableReport ( errs ) }` ) ; return process . exit ( 1 ) ; } ) ; export const PECSERVER_TOKEN_ISSUER = NonEmptyString . decode ( process . env . PECSERVER_TOKEN_ISSUER ) . getOrElseL ( errs => { log . error ( `Missing or invalid PECSERVER_TOKEN_ISSUER environment variable: ${ readableReport ( errs ) }` ) ; return process . exit ( 1 ) ; } ) ; const DEFAULT_PECSERVER_TOKEN_EXPIRATION = 600 as Second ; export const PECSERVER_TOKEN_EXPIRATION = IntegerFromString . decode ( process . env . PECSERVER_TOKEN_EXPIRATION ) . getOrElse ( DEFAULT_PECSERVER_TOKEN_EXPIRATION ) as Second ; log . info ( "PEC Server expiration set to %s seconds" , PECSERVER_TOKEN_EXPIRATION ) ; export const TEST_CGN_FISCAL_CODES = CommaSeparatedListOf ( FiscalCode ) . decode ( process . env . TEST_CGN_FISCAL_CODES || "" ) . getOrElseL ( err => { throw new Error ( `Invalid TEST_CGN_FISCAL_CODES value: ${ readableReport ( err ) }` ) ; } ) ;