Skip to content
Snippets Groups Projects
viamapi-iframe.js 70.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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
        },
    
        signDocumentJava: async (
          passportUUID,
          documentUUID,
          documentContentType
        ) => {
    
          const authenticationPublicKey = localStorage.getItem(
            "authenticatedIdentity"
          );
    
          if (
            !authenticationPublicKey ||
            !window.loadedIdentities[authenticationPublicKey] ||
            !extendPinCodeTtl(authenticationPublicKey)
          ) {
            return encodeResponse("400", "", "Identity not authenticated");
          }
    
          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,
            pdfContentType
          );
          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;
    
    
          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;
          }
    
          let qrCodeImageData;
    
          let qrCodeCoordinates = { fromL: -1, fromR: -1, toL: -1, toR: -1 };
    
          if (
            vCardImageClaimValue &&
            "state" in vCardImageClaimValue &&
            vCardImageClaimValue.state === "disabled"
          ) {
    
            vCardImageData = new ImageData({
              contentType: "image/png",
    
              contentBase64:
                "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=" //1x1px transparent pixel
    
            });
          } else {
            const vCardImageResponse = await executeRestfulFunction(
              "private",
              window.viamApi,
              window.viamApi.passportGetVCardImage,
              null,
              passportUUID
            );
    
    Gospodin Bodurov's avatar
    Gospodin Bodurov committed
    
            console.log(vCardImageResponse);
    
    
            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'"
              );
    
            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();
    
    
          console.log(qrCodeImageData);
          console.log(qrCodeCoordinates);
    
    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");
        },
    
    Alexey Lunin's avatar
    Alexey Lunin committed
        documentPutDocument: async (
          passportUUID,
          resourceid,
          contentType,
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          file,
          upload
    
    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");
          }
    
    
          resourceid = encodeURI(resourceid);
          contentType = encodeURI(contentType);
    
    
    Alexey Lunin's avatar
    Alexey Lunin committed
              "Content-Type": "multipart/form-data",
    
              contentType,
              upload
    
    
          const response = await executeRestfulFunction(
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            "private",
            window.viamApi,
            window.viamApi.documentPutDocument,
            config,
            file
          );
    
          if (response.code !== "200") {
            return encodeResponse("400", "", response.status);
          }
    
    
          return encodeResponse("200", response.data, "Document stored");
        },
    
        hasSession() {
          return new Penpal.Promise(result => {
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            const authenticationPublicKey = localStorage.getItem(
              "authenticatedIdentity"
            );
    
            if (authenticationPublicKey === null) {
    
    Alexey Lunin's avatar
    Alexey Lunin committed
              result({
                data: "",
                code: "400",
                status: "Identity not authenticated"
    
            if (window.loadedIdentities[authenticationPublicKey] === null) {
    
    Alexey Lunin's avatar
    Alexey Lunin committed
              result({
                data: "",
                code: "400",
                status: "Identity not authenticated"
    
    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
            executeRestfulFunction(
              "private",
              viamApi,
              viamApi.identityHasSession,
              null
            ).then(executeResult => {
    
              result(executeResult);
            });
          });
        },
        marketingSignUpIdentificator(identificator, reference) {
          return new Penpal.Promise(result => {
    
    Markin Igor's avatar
    Markin Igor committed
            viamApi.setIdentity("marketingapppublickey");
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            executeRestfulFunction(
              "public",
              viamApi,
              viamApi.marketingSignUpIdentificator,
              null,
              identificator,
              reference
            ).then(executeResult => {
    
    Markin Igor's avatar
    Markin Igor committed
              viamApi.setIdentity("");
    
    Markin Igor's avatar
    Markin Igor committed
              viamApi.setSessionData("", "");
    
              result(executeResult);
            });
          });
        },
        marketingGetIdentificatorProfile(identificator, pincode) {
          return new Penpal.Promise(result => {
    
    Markin Igor's avatar
    Markin Igor committed
            viamApi.setIdentity("marketingapppublickey");
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            executeRestfulFunction(
              "public",
              viamApi,
              viamApi.marketingGetIdentificatorProfile,
              null,
              identificator,
              pincode
            ).then(executeResult => {
    
    Markin Igor's avatar
    Markin Igor committed
              viamApi.setIdentity("");
    
    Markin Igor's avatar
    Markin Igor committed
              viamApi.setSessionData("", "");
    
              result(executeResult);
            });
          });
        },
    
        marketingExecuteEventForIdentificator(identificator, pincode, event) {
    
          return new Penpal.Promise(result => {
    
    Markin Igor's avatar
    Markin Igor committed
            viamApi.setIdentity("marketingapppublickey");
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            executeRestfulFunction(
              "public",
              viamApi,
              viamApi.marketingExecuteEventForIdentificator,
              null,
              identificator,
              pincode,
              event
            ).then(executeResult => {
    
    Markin Igor's avatar
    Markin Igor committed
              viamApi.setIdentity("");
    
    Markin Igor's avatar
    Markin Igor committed
              viamApi.setSessionData("", "");
    
              result(executeResult);
            });
          });
        },
        getCurrentlyAuthenticatedIdentity() {
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          const {
            publicKey,
            x509Certificate
          } = window.currentlyAuthenticatedIdentity.authentication;
    
    
          return encodeResponse(
            "200",
            {
              authentication: {
                publicKey,
                x509Certificate
              }
            },
            "Currently authenticated identity"
          );
    
        extractMessageID(mime) {
          return new Penpal.Promise(result => {
            result(extractMessageID(mime));
          });
        },
    
        stringToUtf8ByteArray(str) {
          return new Penpal.Promise(result => {
    
            result(stringToUtf8ByteArray(str));
          });
    
        },
        utf8ByteArrayToString(ba) {
          return new Penpal.Promise(result => {
    
            result(utf8ByteArrayToString(ba));
          });
    
        },
        stringToUtf8Base64(str) {
          return new Penpal.Promise(result => {
    
            result(stringToUtf8Base64(str));
          });
    
        },
        utf8Base64ToString(strBase64) {
          return new Penpal.Promise(result => {
    
            result(utf8Base64ToString(strBase64));
          });
    
        },
        base64ToByteArray(strBase64) {
          return new Penpal.Promise(result => {
    
            result(base64ToByteArray(strBase64));
          });
    
        },
        byteArrayToBase64(ba) {
          return new Penpal.Promise(result => {
    
            result(byteArrayToBase64(ba));
          });
    
    Alexey Lunin's avatar
    Alexey Lunin committed
    
        // Collabora APIs
    
        collaboraDiscovery() {
    
          return collaboraApi.discovery().then(apps => apps);
    
    Alexey Lunin's avatar
    Alexey Lunin committed
        // WOPI
    
    Gospodin Bodurov's avatar
    Gospodin Bodurov committed
        getPassportsNewProtocol: async (resourceID, contentType) => {
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          const authenticationPublicKey = localStorage.getItem(
            "authenticatedIdentity"
          );
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          if (
            !authenticationPublicKey ||
            !window.loadedIdentities[authenticationPublicKey] ||
            !extendPinCodeTtl(authenticationPublicKey)
          ) {
            return encodeResponse("400", "", "Identity not authenticated");
          }
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          const response = await wopiAPI.getPassportsNewProtocol(
            resourceID,
            contentType
          );
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          return response.data;
    
    Alexey Lunin's avatar
    Alexey Lunin committed
        getPassports: async fileId => {
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          const authenticationPublicKey = localStorage.getItem(
            "authenticatedIdentity"
          );
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          if (
            !authenticationPublicKey ||
            !window.loadedIdentities[authenticationPublicKey] ||
            !extendPinCodeTtl(authenticationPublicKey)
          ) {
            return encodeResponse("400", "", "Identity not authenticated");
          }
    
          const response = await wopiAPI.getPassports(fileId);
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          return response.data;
    
        wopiCreateDocument: async (passportUUID, path, 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");
          }
    
          const config = {
            headers: {
              path,