Skip to content
Snippets Groups Projects
viamapi-iframe.js 77.5 KiB
Newer Older
  • Learn to ignore specific revisions
  • Alexey Lunin's avatar
    Alexey Lunin committed
            if (localStorage.getItem("uuid") === null) {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              result({ data: "", code: "400", status: "Not logged in UUID" });
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            result({
              data: localStorage.getItem("uuid"),
              code: "200",
              status: "UUID loaded"
            });
    
          });
        },
        getCertificateByPassport(passportUUID) {
          return new Penpal.Promise(result => {
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            const authenticationPublicKey = localStorage.getItem(
              "authenticatedIdentity"
            );
    
            if (authenticationPublicKey === null) {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              return { data: "", code: "400", status: "Identity not loaded" };
    
            if (window.loadedIdentities[authenticationPublicKey] === null) {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              return { data: "", code: "400", status: "Identity not loaded" };
    
    Zdravko Iliev's avatar
    Zdravko Iliev committed
            const success = extendPinCodeTtl(authenticationPublicKey);
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            if (success === false) {
              result({
                data: "",
                code: "400",
                status: "Identity not authenticated"
              });
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            getCertificateForPassport(passportUUID, false).then(
              certificateResult => {
                result(certificateResult);
              }
            );
    
          });
        },
        getOneTimeCertificateByPassport(passportUUID, emailArg) {
          return new Penpal.Promise(result => {
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            const authenticationPublicKey = localStorage.getItem(
              "authenticatedIdentity"
            );
    
            if (authenticationPublicKey === null) {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              return { data: "", code: "400", status: "Identity not loaded" };
    
            if (window.loadedIdentities[authenticationPublicKey] === null) {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              return { data: "", code: "400", status: "Identity not loaded" };
    
    Zdravko Iliev's avatar
    Zdravko Iliev committed
            const success = extendPinCodeTtl(authenticationPublicKey);
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            if (success === false) {
              result({
                data: "",
                code: "400",
                status: "Identity not authenticated"
              });
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            getCertificateForPassport(passportUUID, true).then(
              certificateResult => {
                if (certificateResult.code === "200") {
    
    Zdravko Iliev's avatar
    Zdravko Iliev committed
                  const passportCertificate =
    
    Alexey Lunin's avatar
    Alexey Lunin committed
                    certificateResult.data["x509Certificate"];
    
    Zdravko Iliev's avatar
    Zdravko Iliev committed
                  const passportPrivateKey = certificateResult.data["privateKey"];
                  const passportChain = certificateResult.data["chain"];
    
    Alexey Lunin's avatar
    Alexey Lunin committed
    
                  createOneTimePassportCertificate(
                    makeid() + "-" + passportUUID,
                    emailArg,
                    passportPrivateKey,
                    passportCertificate
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                  ).then(function(keys) {
    
    Zdravko Iliev's avatar
    Zdravko Iliev committed
                    const publicKeyOneTime = keys["publicKeyPEM"];
                    const privateKeyOneTime = keys["privateKeyPEM"];
                    const certificateOneTime = keys["certificatePEM"];
    
    Alexey Lunin's avatar
    Alexey Lunin committed
                    passportChain.push(passportCertificate);
    
    
    Zdravko Iliev's avatar
    Zdravko Iliev committed
                    const oneTimeCryptoData = new CryptoData();
    
    Alexey Lunin's avatar
    Alexey Lunin committed
                    oneTimeCryptoData.setx509Certificate(certificateOneTime);
                    oneTimeCryptoData.setPrivateKey(privateKeyOneTime);
                    oneTimeCryptoData.setPublicKey(publicKeyOneTime);
                    oneTimeCryptoData.setChain(passportChain);
    
                    result({
                      data: oneTimeCryptoData,
                      code: "200",
                      status: "One time certificate generated"
                    });
                    // Prints PEM formatted signed certificate
                    // -----BEGIN CERTIFICATE-----MIID....7Hyg==-----END CERTIFICATE-----
                  });
                } else {
                  result({
                    data: "",
                    code: "400",
                    status: "Can not generate one time certificate"
                  });
                }
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            );
    
        verifySMIME: async smimeString => {
    
          const authenticationPublicKey = localStorage.getItem(
            "authenticatedIdentity"
          );
    
          if (
            !authenticationPublicKey ||
            !window.loadedIdentities[authenticationPublicKey] ||
            !extendPinCodeTtl(authenticationPublicKey)
          ) {
            return encodeResponse("400", "", "Identity not authenticated");
          }
    
    
    Damyan Mitev's avatar
    Damyan Mitev committed
          //TODO cache (for some time) the root certificate
          // either as PEM or as certificate object (preferred)
    
          const rootCaResponse = await executeRestfulFunction(
            "private",
            window.viamApi,
            window.viamApi.signRetrieveRootCertificate,
            null
          );
    
          if (rootCaResponse.code !== "200") {
            return encodeResponse("400", "", rootCaResponse.status);
          }
    
          const rootCaPem = rootCaResponse.data;
    
    Damyan Mitev's avatar
    Damyan Mitev committed
          const verificationResult = await verifySMIME(smimeString, rootCaPem);
    
          return encodeResponse(
            "200",
            verificationResult.verified,
            verificationResult.message
          );
    
        validateDocument: async (documentUUID, contentType) => {
    
          const authenticationPublicKey = localStorage.getItem(
            "authenticatedIdentity"
          );
    
    
          if (
            !authenticationPublicKey ||
            !window.loadedIdentities[authenticationPublicKey] ||
            !extendPinCodeTtl(authenticationPublicKey)
          ) {
            return encodeResponse("400", "", "Identity not authenticated");
          }
    
          const validateDocumentResponse = await executeRestfulFunction(
            "private",
            window.viamApi,
            window.viamApi.documentValidateDocumentByUUID,
            null,
            documentUUID,
    
    
          if (validateDocumentResponse.code !== "200") {
            return encodeResponse("400", "", validateDocumentResponse.status);
          }
    
          const signatures = validateDocumentResponse.data;
    
          if (signatures) {
            for (const signature of signatures) {
    
              const certificateChain = signature.certificateChainPEM.map(
                certificatePEM => {
                  const certificate = parseCertificate(certificatePEM);
                  const certificateData = new CertificateData(certificate);
                  return certificateData;
                }
              );
    
              signature.certificateChain = certificateChain;
            }
    
        signEmail: async (passportUUID, emailArg, emailMessage) => {
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          const authenticationPublicKey = localStorage.getItem(
            "authenticatedIdentity"
          );
    
          if (
            !authenticationPublicKey ||
            !window.loadedIdentities[authenticationPublicKey] ||
            !extendPinCodeTtl(authenticationPublicKey)
          ) {
            return encodeResponse("400", "", "Identity not authenticated");
          }
    
          let response = await getCertificateForPassport(passportUUID, true);
    
          if (response.code !== "200") {
            return encodeResponse("400", "", response.status);
          }
    
          const {
            x509Certificate: passportCertificate,
            privateKey: passportPrivateKey,
            chain: passportChain
          } = response.data;
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          const keys = await createOneTimePassportCertificate(
            makeid() + "-" + passportUUID,
            emailArg,
            passportPrivateKey,
            passportCertificate
          );
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          const {
            privateKeyPEM: privateKeyOneTime,
            certificatePEM: certificateOneTime
          } = keys;
    
          passportChain.push(passportCertificate);
    
          response = await executeRestfulFunction(
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            "private",
            window.viamApi,
            window.viamApi.passportGetEmailWithHeaderByPassport,
            null,
            passportUUID,
            emailMessage
          );
    
    
          if (response.code !== "200") {
            return encodeResponse("400", "", response.status);
          }
    
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          const signedEmail = await signEmail(
            response.data,
            certificateOneTime,
            passportChain,
            privateKeyOneTime
          );
    
    
          response = await executeRestfulFunction(
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            "private",
            window.viamApi,
            window.viamApi.signResignEmail,
            null,
            passportUUID,
            signedEmail
          );
    
    
          if (response.code !== "200") {
            return encodeResponse("400", "", response.status);
          }
    
          return encodeResponse("200", response.data, "Email signed");
    
    Damyan Mitev's avatar
    Damyan Mitev committed
        signDocument: async (passportUUID, documentUUID, documentContentType) => {
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          const authenticationPublicKey = localStorage.getItem(
            "authenticatedIdentity"
          );
    
    Damyan Mitev's avatar
    Damyan Mitev committed
    
          if (
            !authenticationPublicKey ||
            !window.loadedIdentities[authenticationPublicKey] ||
            !extendPinCodeTtl(authenticationPublicKey)
          ) {
            return encodeResponse("400", "", "Identity not authenticated");
          }
    
    
          const certResponse = await getCertificateForPassport(passportUUID, true);
    
    Damyan Mitev's avatar
    Damyan Mitev committed
    
    
          if (certResponse.code !== "200") {
            return encodeResponse("400", "", certResponse.status);
    
    Damyan Mitev's avatar
    Damyan Mitev committed
          }
    
          const {
            x509Certificate: passportCertificate,
            privateKey: passportPrivateKey,
            chain: passportChain
    
          } = certResponse.data;
    
    Damyan Mitev's avatar
    Damyan Mitev committed
    
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          const keys = await createOneTimePassportCertificate(
            makeid() + "-" + passportUUID,
            null,
            passportPrivateKey,
            passportCertificate
          );
    
    Damyan Mitev's avatar
    Damyan Mitev committed
    
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          const {
            privateKeyPEM: privateKeyOneTime,
            certificatePEM: certificateOneTime
          } = keys;
    
    Damyan Mitev's avatar
    Damyan Mitev committed
    
    
    Gospodin Bodurov's avatar
    Gospodin Bodurov committed
          passportChain.reverse();
    
    
    Damyan Mitev's avatar
    Damyan Mitev committed
          passportChain.push(passportCertificate);
    
    
    Gospodin Bodurov's avatar
    Gospodin Bodurov committed
          passportChain.reverse();
    
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          const pdfContentType = "application/pdf";
    
    Damyan Mitev's avatar
    Damyan Mitev committed
    
          if (documentContentType !== pdfContentType) {
            const convResponse = await executeRestfulFunction(
    
    Alexey Lunin's avatar
    Alexey Lunin committed
              "private",
              window.viamApi,
              window.viamApi.documentConvertDocumentByUUID,
              null,
              documentUUID,
              documentContentType,
              pdfContentType
            );
    
    Damyan Mitev's avatar
    Damyan Mitev committed
            if (convResponse.code !== "200") {
              return encodeResponse("400", "", convResponse.status);
            }
          }
    
          const downloadResponse = await executeRestfulFunction(
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            "private",
            window.viamApi,
            window.viamApi.documentGetDocumentByUUID,
            null,
            documentUUID,
            pdfContentType
          );
    
    Damyan Mitev's avatar
    Damyan Mitev committed
    
          if (downloadResponse.code !== "200") {
            return encodeResponse("400", "", downloadResponse.status);
          }
    
    
          const pdfRaw = base64ToByteArray(downloadResponse.data);
    
    Damyan Mitev's avatar
    Damyan Mitev committed
    
    
          let signedPdf;
          try {
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            signedPdf = await signPdf(
              pdfRaw,
              certificateOneTime,
              passportChain,
              privateKeyOneTime
            );
    
          } catch (err) {
            console.error(err);
            return encodeResponse("500", "", err.message);
          }
    
    Damyan Mitev's avatar
    Damyan Mitev committed
    
    
          const signedPdfB64 = byteArrayToBase64(signedPdf);
    
    
          const uploadResponse = await executeRestfulFunction(
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            "private",
            window.viamApi,
            window.viamApi.documentPutDocumentByUUID,
            null,
            documentUUID,
            pdfContentType,
            signedPdfB64
          );
    
          if (uploadResponse.code !== "200") {
            return encodeResponse("400", "", uploadResponse.status);
          }
    
          const signResponse = await executeRestfulFunction(
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            "private",
            window.viamApi,
            window.viamApi.documentSignDocumentByUUID,
            null,
            passportUUID,
            documentUUID,
            pdfContentType
          );
    
          if (signResponse.code !== "200") {
            return encodeResponse("400", "", signResponse.status);
          }
    
          return encodeResponse("200", "", "Document signed");
    
    Damyan Mitev's avatar
    Damyan Mitev committed
        },
    
        /**
         * Checks the state of the vCard. Current states are "disabled" and "enabled".
         * @param passportUUID
         * @returns {Promise<{code: *, data: *, status: *}>}
         */
        async checkVCardState(passportUUID) {
          const authenticationPublicKey = localStorage.getItem(
            "authenticatedIdentity"
          );
    
          if (
            !authenticationPublicKey ||
            !window.loadedIdentities[authenticationPublicKey] ||
            !extendPinCodeTtl(authenticationPublicKey)
          ) {
            return encodeResponse("400", "", "Identity not authenticated");
          }
    
          let vCardImageClaimValue;
    
          const vCardImageClaimName = "vCardImage";
          const defaultTagName = "notag";
    
          const vCardClaimResponse = await executeRestfulFunction(
            "private",
            window.viamApi,
            window.viamApi.entityGetClaim,
            null,
            vCardImageClaimName,
            defaultTagName,
            passportUUID
          );
    
          // You may not have vCard image claim, but backend will still return blank image from passportGetVCardImage
    
          // if (vCardClaimResponse.code !== "200") {
          //   return encodeResponse("400", "", vCardClaimResponse.status);
          // }
    
          if (vCardClaimResponse.code === "200") {
            vCardImageClaimValue = vCardClaimResponse.data;
          }
    
          if (
            vCardImageClaimValue &&
            "state" in vCardImageClaimValue
          ) {
            return encodeResponse("200", vCardImageClaimValue.state, "OK");
          }
    
          return encodeResponse("200", "enabled", "OK");
        },
        /**
         * 
         * @param passportUUID
         * @param documentUUID
         * @param documentContentType
         * @param signatureData -
         * @returns {Promise<{code: *, data: *, status: *}>}
         *
    // Image position in pixels
    message Position {
      int32 left = 1; // x
      int32 top = 2; // y
    }
    
         // Image size in pixels
         message Size {
      uint32 width = 1;
      uint32 height = 2;
    }
    
         // Image size in pixels
         message Bounds {
      int32 left = 1; // x
      int32 top = 2; // y
      uint32 width = 3;
      uint32 height = 4;
    }
    message SignatureData {
      ImageData signatureImageData = 1;
      Bounds signatureBounds = 2;
      uint32 pageNumber = 3;
      Size pageSize = 4;
    }
         * 
         */
    
        signDocumentJava: async (
          passportUUID,
          documentUUID,
    
          documentContentType,
          signatureData = null,
          qrCodeUrl = null
    
          const authenticationPublicKey = localStorage.getItem(
            "authenticatedIdentity"
          );
    
          if (
            !authenticationPublicKey ||
            !window.loadedIdentities[authenticationPublicKey] ||
            !extendPinCodeTtl(authenticationPublicKey)
          ) {
            return encodeResponse("400", "", "Identity not authenticated");
          }
    
    
    
          // Get vCard and QR Code Coordinates
    
          let vCardImageData;
          let vCardImageClaimValue;
    
          let qrCodeImageData;
          let qrCodeCoordinates = {fromL: -1, fromR: -1, toL: -1, toR: -1};
    
          if (signatureData) {
            const vCardImageClaimName = "vCardImage";
            const defaultTagName = "notag";
    
            const vCardClaimResponse = await executeRestfulFunction(
              "private",
              window.viamApi,
              window.viamApi.entityGetClaim,
              null,
              vCardImageClaimName,
              defaultTagName,
              passportUUID
            );
            // if (vCardClaimResponse.code !== "200") {
            //   return encodeResponse("400", "", vCardClaimResponse.status);
            // }
    
            if (vCardClaimResponse.code === "200") {
              vCardImageClaimValue = vCardClaimResponse.data;
            }
    
            if (
              vCardImageClaimValue &&
              "state" in vCardImageClaimValue &&
              vCardImageClaimValue.state === "disabled"
            ) {
              vCardImageData = TRANSPARENT_PIXEL;
            } else {
              const vCardImageResponse = await executeRestfulFunction(
                "private",
                window.viamApi,
                window.viamApi.passportGetVCardImage,
                null,
                passportUUID
              );
    
              if (vCardImageResponse.code !== "200") {
                return encodeResponse("400", "", vCardImageResponse.status);
              }
              vCardImageData = new ImageData(vCardImageResponse.data.Image);
              if (vCardImageData.contentType !== "image/png") {
                return encodeResponse(
                  "400",
                  "",
                  "Content type of vCard must be 'image/png'"
                );
              }
    
              if (qrCodeUrl) {
                qrCodeCoordinates = vCardImageResponse.data.QRCodeCoordinates;
                const qrCodeBase64Content = await generateQrCode(qrCodeUrl);
                qrCodeImageData = new ImageData({
                  contentType: "image/png",
                  content: qrCodeBase64Content
                });
              }
            }
    
            // Fill signature data onject
    
            signatureData.signatureImageData = vCardImageData;
          }
    
          // Generate certificate chain
    
    
          const certResponse = await getCertificateForPassport(passportUUID, true);
    
          if (certResponse.code !== "200") {
            return encodeResponse("400", "", certResponse.status);
          }
    
          const {
            x509Certificate: passportCertificate,
            privateKey: passportPrivateKey,
            chain: passportChain
          } = certResponse.data;
    
          const keys = await createOneTimePassportCertificate(
            makeid() + "-" + passportUUID,
    
            passportPrivateKey,
            passportCertificate
          );
    
          const {
            privateKeyPEM: privateKeyOneTime,
            certificatePEM: certificateOneTime
          } = keys;
    
    
    Gospodin Bodurov's avatar
    Gospodin Bodurov committed
          passportChain.reverse();
    
    
          passportChain.push(passportCertificate);
          passportChain.push(certificateOneTime);
    
    
    Gospodin Bodurov's avatar
    Gospodin Bodurov committed
          passportChain.reverse();
    
    
          const pdfContentType = "application/pdf";
    
          if (documentContentType !== pdfContentType) {
            const convResponse = await executeRestfulFunction(
              "private",
              window.viamApi,
              window.viamApi.documentConvertDocumentByUUID,
              null,
              documentUUID,
              documentContentType,
              pdfContentType
            );
            if (convResponse.code !== "200") {
              return encodeResponse("400", "", convResponse.status);
            }
          }
    
    
          const signResponse = await executeRestfulFunction(
            "private",
            window.viamApi,
            window.viamApi.documentSignDocumentJavaService,
            null,
            privateKeyOneTime,
            passportChain,
            passportUUID,
            documentUUID,
    
            vCardImageData,
    
            qrCodeCoordinates,
            signatureData
    
          );
          if (signResponse.code !== "200") {
            return encodeResponse("400", "", signResponse.status);
          }
    
          return encodeResponse("200", "", "Document signed");
        },
    
        // passportUUID - String - passport to sign the vCard
    
        // senderEmail - the email address of the sender
        // attribs - additional attributes, to be added to the vCard. Recognized attribs are:
        //   - emailService: "GMail", "Outlook 365", ...
    
        // text, html - String - the text and html part of the email, both optional
        // parts - array of objects, representing the MIME structure in format:
    
    Damyan Mitev's avatar
    Damyan Mitev committed
        // {
        //   headers: {
    
        //     "Content-Type": "image/jpeg",
        //     "Content-Disposition": "inline" or "attachment" with additional attributes,
        //     ... //other headers from MIME
    
    Damyan Mitev's avatar
    Damyan Mitev committed
        //   },
    
        //   body: String if it is a text part (Content-Type = "text/...") or Uint8Array otherwise; filled for leaf MIME nodes
        //   parts: array of instances of the same object; filled for container MIME nodes (Content-Type = "multipart/...")
    
    Damyan Mitev's avatar
    Damyan Mitev committed
        // }
    
        signVCard: async (
          passportUUID,
          senderEmail,
          attribs,
          textBody,
          htmlBody,
          parts
        ) => {
    
    Damyan Mitev's avatar
    Damyan Mitev committed
          const authenticationPublicKey = localStorage.getItem(
            "authenticatedIdentity"
          );
    
          if (
            !authenticationPublicKey ||
            !window.loadedIdentities[authenticationPublicKey] ||
            !extendPinCodeTtl(authenticationPublicKey)
          ) {
            return encodeResponse("400", "", "Identity not authenticated");
          }
    
    
          const messageUUID = makeid();
    
          const vCardAttribs = {
    
            ...attribs,
            passportUUID,
            messageUUID
    
          let vCardImageData;
          let vCardImageClaimValue;
    
    
          let qrCodeImageData;
          let qrCodeCoordinates = {fromL: -1, fromR: -1, toL: -1, toR: -1};
    
    
          const vCardImageClaimName = "vCardImage";
          const defaultTagName = "notag";
    
          const vCardClaimResponse = await executeRestfulFunction(
    
    Damyan Mitev's avatar
    Damyan Mitev committed
            "private",
            window.viamApi,
    
            window.viamApi.entityGetClaim,
    
    Damyan Mitev's avatar
    Damyan Mitev committed
            null,
    
            vCardImageClaimName,
            defaultTagName,
    
    Damyan Mitev's avatar
    Damyan Mitev committed
            passportUUID
          );
    
          // if (vCardClaimResponse.code !== "200") {
          //   return encodeResponse("400", "", vCardClaimResponse.status);
          // }
    
          if (vCardClaimResponse.code === "200") {
            vCardImageClaimValue = vCardClaimResponse.data;
          }
    
          if (
            vCardImageClaimValue &&
            "state" in vCardImageClaimValue &&
            vCardImageClaimValue.state === "disabled"
          ) {
    
          } else {
            const vCardImageResponse = await executeRestfulFunction(
              "private",
              window.viamApi,
              window.viamApi.passportGetVCardImage,
              null,
              passportUUID
            );
    
    Gospodin Bodurov's avatar
    Gospodin Bodurov committed
    
    
            if (vCardImageResponse.code !== "200") {
              return encodeResponse("400", "", vCardImageResponse.status);
            }
    
            vCardImageData = new ImageData(vCardImageResponse.data.Image);
    
            if (vCardImageData.contentType !== "image/png") {
    
                "Content type of vCard must be 'image/png'"
    
            qrCodeCoordinates = vCardImageResponse.data.QRCodeCoordinates;
    
            const qrCodeBase64Content = await generateQrCode(
              "https://" + location.host + "/check/" + messageUUID
    
            qrCodeImageData = new ImageData({
              contentType: "image/png",
              content: qrCodeBase64Content
            });
    
    Damyan Mitev's avatar
    Damyan Mitev committed
          if (typeof parts === "undefined" || parts === null) {
    
    Damyan Mitev's avatar
    Damyan Mitev committed
            parts = [];
          }
    
    
          if (htmlBody) {
            if (typeof htmlBody !== "string") {
              throw new Error("htmlBody is not string"); // should not happen
            }
    
    Damyan Mitev's avatar
    Damyan Mitev committed
            const htmlPart = {
              headers: {
                "Content-Type": "text/html"
              },
    
              body: htmlBody
    
    Damyan Mitev's avatar
    Damyan Mitev committed
            };
            parts.unshift(htmlPart);
    
          } else {
    
            console.log("Html body is not passed to signVCard, its value is ", {
              html: htmlBody
            });
    
          if (textBody) {
            if (typeof textBody !== "string") {
              throw new Error("textBody is not string"); // should not happen
            }
    
    Damyan Mitev's avatar
    Damyan Mitev committed
            const textPart = {
              headers: {
                "Content-Type": "text/plain"
              },
    
              body: textBody
    
    Damyan Mitev's avatar
    Damyan Mitev committed
            };
            parts.unshift(textPart);
    
          } else {
    
            console.log("Text body is not passed to signVCard, its value is ", {
              text: textBody
            });
    
          const count = await prepareVCardParts(parts);
    
          if (count.textParts === 0) {
            return encodeResponse("400", "", "No text parts passed to signVCard");
          }
          if (count.htmlParts === 0) {
            return encodeResponse("400", "", "No html parts passed to signVCard");
          }
    
    Damyan Mitev's avatar
    Damyan Mitev committed
          const certResponse = await getCertificateForPassport(passportUUID, true);
    
          if (certResponse.code !== "200") {
            return encodeResponse("400", "", certResponse.status);
          }
    
          const {
            x509Certificate: passportCertificate,
            privateKey: passportPrivateKey,
            chain: passportChain
          } = certResponse.data;
    
          const keys = await createOneTimePassportCertificate(
            makeid() + "-" + passportUUID,
    
            senderEmail,
    
    Damyan Mitev's avatar
    Damyan Mitev committed
            passportPrivateKey,
            passportCertificate
          );
    
          const {
            privateKeyPEM: privateKeyOneTime,
            certificatePEM: certificateOneTime
          } = keys;
    
          passportChain.reverse();
    
          passportChain.push(passportCertificate);
          passportChain.push(certificateOneTime);
    
          passportChain.reverse();
    
    
    Gospodin Bodurov's avatar
    Gospodin Bodurov committed
    
    
    Damyan Mitev's avatar
    Damyan Mitev committed
          const signVCardResponse = await executeRestfulFunction(
            "private",
            window.viamApi,
            window.viamApi.signSignVCardForChain,
            null,
            vCardImageData,
            privateKeyOneTime,
            passportChain,
    
            vCardAttribs,
            qrCodeImageData,
    
    Damyan Mitev's avatar
    Damyan Mitev committed
          );
          if (signVCardResponse.code !== "200") {
            return encodeResponse("400", "", signVCardResponse.status);
          }
    
    
    Damyan Mitev's avatar
    Damyan Mitev committed
          const signedVCardImageData = new ImageData(signVCardResponse.data);
    
          return encodeResponse(
            "200",
            {
              image: signedVCardImageData,
              messageUUID: messageUUID
            },
            "vCard signed"
          );
    
    Damyan Mitev's avatar
    Damyan Mitev committed
        },
    
        // mime - String - the MIME of the email message
        // vCardAttribs - optional attributes for the verification procedure in format
    
    Damyan Mitev's avatar
    Damyan Mitev committed
        // {
    
        //   passportUUID: passportUUID,
        //   messageUUID: messageUUID
        // };
    
    Damyan Mitev's avatar
    Damyan Mitev committed
        validateVMime: async (vMime, vCardAttribs = null) => {
    
    Damyan Mitev's avatar
    Damyan Mitev committed
          const authenticationPublicKey = localStorage.getItem(
            "authenticatedIdentity"
          );
    
          if (
            !authenticationPublicKey ||
            !window.loadedIdentities[authenticationPublicKey] ||
            !extendPinCodeTtl(authenticationPublicKey)
          ) {
            return encodeResponse("400", "", "Identity not authenticated");
          }
    
    
          const validateVMimeResponse = await executeRestfulFunction(
    
    Damyan Mitev's avatar
    Damyan Mitev committed
            "private",
            window.viamApi,
    
            window.viamApi.signValidateVMime,
    
    Damyan Mitev's avatar
    Damyan Mitev committed
            null,
    
    Damyan Mitev's avatar
    Damyan Mitev committed
            vMime,
    
    Damyan Mitev's avatar
    Damyan Mitev committed
          );
    
          if (validateVMimeResponse.code !== "200") {
            return encodeResponse("400", "", validateVMimeResponse.status);
    
    Damyan Mitev's avatar
    Damyan Mitev committed
          const validationResult = validateVMimeResponse.data;
    
          const { signatures } = validationResult;
    
          if (signatures) {
            for (const signature of signatures) {
    
              const certificateChain = signature.certificateChainPEM.map(
                certificatePEM => {
                  const certificate = parseCertificate(certificatePEM);
                  const certificateData = new CertificateData(certificate);
                  return certificateData;
                }
              );
    
              signature.certificateChain = certificateChain;
    
          return encodeResponse(
            "200",
            validationResult,
            "Validation result retrieved"
          );
    
    Damyan Mitev's avatar
    Damyan Mitev committed
        },
    
        generateQrCode,
    
        documentCreateDocument: async (passportUUID, path, contentType, title) => {
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          const authenticationPublicKey = localStorage.getItem(
            "authenticatedIdentity"
          );
    
          if (
            !authenticationPublicKey ||
            !window.loadedIdentities[authenticationPublicKey] ||
            !extendPinCodeTtl(authenticationPublicKey)
          ) {
            return encodeResponse("400", "", "Identity not authenticated");
          }
    
    
          path = encodeURI(path);
          contentType = encodeURI(contentType);
          title = encodeURI(title);
    
    
          const config = {
            headers: {
              path,
              passportuuid: passportUUID,
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          const response = await executeRestfulFunction(
            "private",
            window.viamApi,
            window.viamApi.documentCreateDocument,
            config
          );
    
          if (response.code !== "200") {
            return encodeResponse("400", "", response.status);
          }
    
    
          return encodeResponse("200", response.data, "Document created");
        },
    
        getVcardWithQrCode: async (passportUUID, QRCodeContent = null) =>{
          //TODO: IMPLEMENT QR CODE backend method needed
          const authenticationPublicKey = localStorage.getItem(
            "authenticatedIdentity"
          );
    
          if (
            !authenticationPublicKey ||
            !window.loadedIdentities[authenticationPublicKey] ||
            !extendPinCodeTtl(authenticationPublicKey)
          ) {
            return encodeResponse("400", "", "Identity not authenticated");
          }
    
          let vCardImageData;
          let vCardImageClaimValue;
    
          const vCardImageClaimName = "vCardImage";
          const defaultTagName = "notag";
    
          const vCardClaimResponse = await executeRestfulFunction(
            "private",
            window.viamApi,
            window.viamApi.entityGetClaim,
            null,
            vCardImageClaimName,
            defaultTagName,
            passportUUID
          );
    
          if (vCardClaimResponse.code === "200") {
            vCardImageClaimValue = vCardClaimResponse.data;
          }
    
          if (
            vCardImageClaimValue &&
            "state" in vCardImageClaimValue &&
            vCardImageClaimValue.state === "disabled"
          ) {
            //No image data if the user have disabled vCard for this profile.
            vCardImageData = null;
    
            // vCardImageData = new ImageData({
            //   contentType: "image/png",
            //   contentBase64:
            //     "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=" //1x1px transparent pixel
            // });
          } else {
            const vCardImageResponse = await executeRestfulFunction(
              "private",
              window.viamApi,
              window.viamApi.passportGetVCardImage,
              null,
              passportUUID
            );
    
            if (vCardImageResponse.code !== "200") {
              return encodeResponse("400", "", vCardImageResponse.status);
            }
            vCardImageData = new ImageData(vCardImageResponse.data.Image);
            if (vCardImageData.contentType !== "image/png") {
              return encodeResponse(
                "400",
                "",
                "Content type of vCard mmust be 'image/png'"
              );
            }
          }
          return  encodeResponse("200",vCardImageData, 'vCard got');
        },
    
    Alexey Lunin's avatar
    Alexey Lunin committed
        documentPutDocument: async (