Skip to content
Snippets Groups Projects
viamapi-iframe.js 73.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • Sasha Ilieva's avatar
    Sasha Ilieva committed
              recoveryKey,
              sharesNumber
            );
            const sanityCheckResponse = checkRecoveryKeyCombine(
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              recoveryKeyShares
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            if (sanityCheckResponse.code !== "200") {
              return sanityCheckResponse;
    
            // Encrypt each share with every publicKey of each contact device
            const shamirPartsList = await Promise.all(
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              trusteesToDevices.map(async ([contactUuid, device], index) => {
    
                const deviceIdsToPublicKeys = Object.entries(device);
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                // Encrypt secret shares in parallel
                const deviceIdsToEncryptedPartsList = await Promise.all(
                  deviceIdsToPublicKeys.map(async ([deviceId, { publicKey }]) => {
    
                    const encryptedShare = await encryptShare(
                      recoveryKeyShares[index],
                      publicKey
                    );
    
                    return [deviceId, encryptedShare];
                  })
                );
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                // Turn deviceIdsToEncryptedPartsList array to object
                const deviceIdsToEncryptedParts = Object.fromEntries(
                  deviceIdsToEncryptedPartsList
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                return [contactUuid, deviceIdsToEncryptedParts];
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            // Turn shamirPartsList array to object
    
            const shamirParts = Object.fromEntries(shamirPartsList);
    
            // Save Shamir parts to database
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            await executeRestfulFunction(
    
              "private",
              window.viamApi,
              window.viamApi.contactsSaveShamirParts,
              null,
              shamirParts
            );
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            return response;
    
          } catch (error) {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            return encodeResponse("400", "", error.message);
    
        getCurrentlyLoggedInUUID() {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
          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",
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                status: "Identity not authenticated",
    
    Alexey Lunin's avatar
    Alexey Lunin committed
              });
    
    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",
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              status: "UUID loaded",
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            });
    
          });
        },
        getCertificateByPassport(passportUUID) {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
          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",
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                status: "Identity not authenticated",
    
    Alexey Lunin's avatar
    Alexey Lunin committed
              });
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            getCertificateForPassport(passportUUID, false).then(
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              (certificateResult) => {
    
    Alexey Lunin's avatar
    Alexey Lunin committed
                result(certificateResult);
              }
            );
    
          });
        },
        getOneTimeCertificateByPassport(passportUUID, emailArg) {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
          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",
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                status: "Identity not authenticated",
    
    Alexey Lunin's avatar
    Alexey Lunin committed
              });
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            getCertificateForPassport(passportUUID, true).then(
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              (certificateResult) => {
    
    Alexey Lunin's avatar
    Alexey Lunin committed
                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",
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                      status: "One time certificate generated",
    
    Alexey Lunin's avatar
    Alexey Lunin committed
                    });
                    // Prints PEM formatted signed certificate
                    // -----BEGIN CERTIFICATE-----MIID....7Hyg==-----END CERTIFICATE-----
                  });
                } else {
                  result({
                    data: "",
                    code: "400",
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                    status: "Can not generate one time certificate",
    
    Alexey Lunin's avatar
    Alexey Lunin committed
                  });
                }
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            );
    
    Sasha Ilieva's avatar
    Sasha Ilieva 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(
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                (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,
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            chain: passportChain,
    
    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,
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            certificatePEM: certificateOneTime,
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          } = 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,
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            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,
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            certificatePEM: certificateOneTime,
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          } = 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,
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            chain: passportChain,
    
          } = certResponse.data;
    
          const keys = await createOneTimePassportCertificate(
            makeid() + "-" + passportUUID,
    
            passportPrivateKey,
            passportCertificate
          );
    
          const {
            privateKeyPEM: privateKeyOneTime,
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            certificatePEM: certificateOneTime,
    
    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,
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            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",
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                "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",
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              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: {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                "Content-Type": "text/html",
    
    Damyan Mitev's avatar
    Damyan Mitev committed
              },
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              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 ", {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              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: {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                "Content-Type": "text/plain",
    
    Damyan Mitev's avatar
    Damyan Mitev committed
              },
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              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 ", {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              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,
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            chain: passportChain,
    
    Damyan Mitev's avatar
    Damyan Mitev committed
          } = certResponse.data;
    
          const keys = await createOneTimePassportCertificate(
            makeid() + "-" + passportUUID,
    
            senderEmail,
    
    Damyan Mitev's avatar
    Damyan Mitev committed
            passportPrivateKey,
            passportCertificate
          );
    
          const {
            privateKeyPEM: privateKeyOneTime,
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            certificatePEM: certificateOneTime,
    
    Damyan Mitev's avatar
    Damyan Mitev committed
          } = 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,
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              messageUUID: messageUUID,
    
    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(
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                (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,
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              title,
            },
    
    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,
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
              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() {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
          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",
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                status: "Identity not authenticated",
    
            if (window.loadedIdentities[authenticationPublicKey] === null) {
    
    Alexey Lunin's avatar
    Alexey Lunin committed
              result({
                data: "",
                code: "400",
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                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",
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                status: "Identity not authenticated",
    
    Alexey Lunin's avatar
    Alexey Lunin committed
              });
    
    Alexey Lunin's avatar
    Alexey Lunin committed
            executeRestfulFunction(
              "private",
              viamApi,
              viamApi.identityHasSession,
              null
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            ).then((executeResult) => {
    
              result(executeResult);
            });
          });
        },
        marketingSignUpIdentificator(identificator, reference) {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
          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
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            ).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) {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
          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
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            ).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) {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
          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
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            ).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,
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
            x509Certificate,
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          } = window.currentlyAuthenticatedIdentity.authentication;
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
                x509Certificate,
              },
    
        extractMessageID(mime) {
    
    Sasha Ilieva's avatar
    Sasha Ilieva committed
          return new Penpal.Promise((result) => {
    
            result(extractMessageID(mime));