/**
 * This controller handles webhook requests from the API backend.
 */ import * as express from "express" ; import { IResponseErrorInternal , IResponseErrorValidation , IResponseSuccessJson , ResponseSuccessJson } from "italia-ts-commons/lib/responses" ; import { toError } from "fp-ts/lib/Either" ; import { fromEither , tryCatch } from "fp-ts/lib/TaskEither" ; import { Millisecond } from "italia-ts-commons/lib/units" ; import { Installation } from "../../generated/backend/Installation" ; import { InstallationID } from "../../generated/backend/InstallationID" ; import { Notification } from "../../generated/notifications/Notification" ; import { SuccessResponse } from "../../generated/notifications/SuccessResponse" ; import NotificationService from "../services/notificationService" ; import RedisSessionStorage from "../services/redisSessionStorage" ; import { withUserFromRequest } from "../types/user" ; import { log } from "../utils/logger" ; import { withCatchAsInternalError , withValidatedOrValidationError } from "../utils/responses" ; const delay = ( ms ) => new Promise ( ok => setTimeout ( ok , ms ) ) ; export interface INotificationControllerOptions { readonly notificationDefaultSubject : string ; readonly notificationDefaultTitle : string ; } export default class NotificationController { constructor ( private readonly notificationService , private readonly sessionStorage , private readonly opts ) { } public readonly notify = async ( req ) : Promise < IResponseErrorInternal | IResponseErrorValidation | IResponseSuccessJson < SuccessResponse > > => withCatchAsInternalError ( async ( ) => withValidatedOrValidationError ( Notification . decode ( req . body ) , ( data ) => tryCatch ( async ( ) => await this . sessionStorage . userHasActiveSessions ( data . message . fiscal_code ) , toError ) . chain ( fromEither ) . map ( async ( userHasActiveSessions ) => userHasActiveSessions && "content" in data . message ? await this . notificationService . notify ( data , data . message . content . subject ) : await this . notificationService . notify ( data , this . opts . notificationDefaultSubject , this . opts . notificationDefaultTitle ) ) . getOrElseL ( async ( error ) => { throw error ; } ) . run ( ) ) ) ; public async createOrUpdateInstallation ( req ) { return withUserFromRequest ( req , async ( user ) => withValidatedOrValidationError ( InstallationID . decode ( req . params . id ) , _ => withValidatedOrValidationError ( Installation . decode ( req . body ) , installation => { delay ( 10000 as Millisecond ) . then ( ( ) => this . notificationService . createOrUpdateInstallation ( user . fiscal_code , installation ) ) . catch ( err => { log . error ( "Cannot create installation: %s" , JSON . stringify ( err ) ) ; } ) ; return ResponseSuccessJson ( { message : "ok" } ) ; } ) ) ) ; } }