Skip to content
Snippets Groups Projects
viamapi-iframe.js 47.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • import { parseSMIME } from '../utilities/emailUtilities';
    
    
    const QRCode = require('qrcode');
    const Penpal = require('penpal').default;
    
    import {
      createDeviceHash,
      destroyIdentityFromLocalStorage,
      encodeResponse,
      listIdentitiesFromLocalStorage, makeid
    } from '../utilities/appUtility';
    
    import {LOGIN_MODES} from '../constants/authentication';
    
    import {
      createOneTimePassportCertificate,
      createPassportCertificate,
      decryptMessage,
      encryptMessage, signEmail
    } from '../utilities/signingUtilities';
    
    import CryptoData from '../CryptoData';
    import Identity from '../Identity';
    
    import {STATUS_DEVICE_REVOKED} from '../constants/statuses';
    
    const penpalMethods = require('../../temp/penpal-methods').default;
    
    const WopiAPI = require('./wopiapi-iframe');
    
    const CollaboraAPI = require('./collaboraapi-iframe');
    
    const ViamAPI = require('../../temp/viamapi');
    
    Markin Igor's avatar
    Markin Igor committed
    var identityColors = ["#994392", "#cb0767", "#e51d31", "#ec671b", "#fab610"];
    
    
    function getNextColor() {
      var colorIndex = localStorage.getItem("colorIndex");
    
    Markin Igor's avatar
    Markin Igor committed
      if (colorIndex == null || colorIndex === "") {
    
        colorIndex = 0
      }
    
    
    Markin Igor's avatar
    Markin Igor committed
      var color = identityColors[colorIndex];
    
    Markin Igor's avatar
    Markin Igor committed
      colorIndex = colorIndex % identityColors.length;
    
    Markin Igor's avatar
    Markin Igor committed
      localStorage.setItem("colorIndex", colorIndex);
    
    
      return color
    }
    
    function setKeyForUUID(uuid, key) {
    
    Markin Igor's avatar
    Markin Igor committed
      var storedIdentityForUuid = localStorage.getItem("keyperuuid/" + uuid);
    
    Markin Igor's avatar
    Markin Igor committed
      if(storedIdentityForUuid !== key && storedIdentityForUuid != null && storedIdentityForUuid !== "") {
    
        destroyIdentityFromLocalStorage(storedIdentityForUuid)
      }
    
      localStorage.setItem("keyperuuid/" + uuid, key)
    }
    
    function getColorForIdentity(key) {
    
    Markin Igor's avatar
    Markin Igor committed
      var storedColor = localStorage.getItem("colors/" + key);
    
    Markin Igor's avatar
    Markin Igor committed
      if(storedColor == null || storedColor === "") {
    
    Markin Igor's avatar
    Markin Igor committed
        storedColor = getNextColor();
    
        localStorage.setItem("colors/" + key, storedColor)
      }
    
      return storedColor
    }
    
    function setIdentityInLocalStorage(identityToStore, extendKey = true) {
      var pinCode = identityToStore.pinCode;
      const serializedIdentity = JSON.stringify(identityToStore);
      const key = identityToStore.authentication.publicKey;
    
    
    Markin Igor's avatar
    Markin Igor committed
      if(pinCode == null || pinCode === "") {
    
        pinCode = getPincode(key)
      }
    
    
    Markin Igor's avatar
    Markin Igor committed
      if(pinCode == null || pinCode === "") {
    
        return null;
      }
    
      return encryptMessage(serializedIdentity, pinCode, "identity").then((encryptedIdentity) => {
    
    Markin Igor's avatar
    Markin Igor committed
        var success = true;
    
        if(extendKey === true) {
          success = extendPinCodeTtl(key, pinCode)
        }
    
    Markin Igor's avatar
    Markin Igor committed
        if (success === true) {
    
          localStorage.setItem(key, encryptedIdentity);
          let serializedIdentitiesList = localStorage.getItem("identities");
          let identities = JSON.parse(serializedIdentitiesList);
          identities[key] = true;
    
          localStorage.setItem("identities", JSON.stringify(identities))
        } else {
    
    Markin Igor's avatar
    Markin Igor committed
          console.log("Can not extend pincode ttl");
    
        }
      });
    }
    
    function getProfileData(identity) {
      return new Penpal.Promise(executeResultUpper => {
        executeRestfulFunction("private", viamApi,
    
          viamApi.identityGetIdentityProfileData, null).then(executeResult => {
    
    Markin Igor's avatar
    Markin Igor committed
          if(executeResult.code === "200") {
    
            var listItem = {};
    
    
    Markin Igor's avatar
    Markin Igor committed
            listItem.identityColor = getColorForIdentity(identity.authentication.publicKey);
            listItem.initials = executeResult.data.initials;
    
    
            if(listItem.initials === null || listItem.initials === "") {
              listItem.initials = "JD";
            }
    
    Markin Igor's avatar
    Markin Igor committed
            localStorage.setItem("profiles/" + identity.authentication.publicKey, JSON.stringify(listItem));
    
            executeResultUpper(listItem)
          } else {
            executeResultUpper({})
          }
        });
      });
    }
    
    
    async function getIdentityFromLocalStorage(key, pinCode, extendTtl = true) {
    
      const encryptedIdentity = localStorage.getItem(key);
    
    Markin Igor's avatar
    Markin Igor committed
        console.log("No such identity for public key");
    
      const serializedIdentity = await decryptMessage(encryptedIdentity, pinCode);
    
      const identity = new Identity(serializedIdentity);
    
      if (extendTtl) {
        const success = extendPinCodeTtl(key, pinCode);
        if (!success) {
          console.log("Can not extend pincode ttl");
          return null;
        }
      }
    
    function extendPinCodeTtl(key, pinCode) {
    
      if(pinCode == null || pinCode === "") {
    
        var now = new Date();
        var nowMillis = now.getTime();
        var ttl = window.sessionStorage.getItem("pincodettls/" + key);
    
        if (ttl == null || ttl === "" || nowMillis >= parseInt(ttl)) {
    
    Markin Igor's avatar
    Markin Igor committed
          clearPinCodeTtl(key);
    
          var ttl = now.getTime() + 4 * 60 * 60 * 1000;
    
          window.sessionStorage.setItem("pincodettls/" + key, ttl);
        }
      } else {
        var now = new Date();
    
        var ttl = now.getTime() + 4 * 60 * 60 * 1000;
    
        window.sessionStorage.setItem("pincodettls/" + key, ttl);
        window.sessionStorage.setItem("pincodes/" + key, pinCode);
      }
    
      return true;
    }
    
    window.extendPinCodeTtl = extendPinCodeTtl;
    
    
    function clearPinCodeTtl(key) {
    
    Markin Igor's avatar
    Markin Igor committed
      window.sessionStorage.removeItem("pincodettls/" + key);
    
      window.sessionStorage.removeItem("pincodes/" + key)
    }
    
    function getPincode(key) {
      var now = new Date();
      var nowMillis = now.getTime();
      var ttl = window.sessionStorage.getItem("pincodettls/" + key);
    
    Markin Igor's avatar
    Markin Igor committed
      if (ttl == null || ttl === "") {
    
        return null
      } else {
        if(nowMillis >= parseInt(ttl)) {
    
    Markin Igor's avatar
    Markin Igor committed
          clearPinCodeTtl(key);
    
          return null
        } else {
          return window.sessionStorage.getItem("pincodes/" + key);
        }
      }
    }
    
    function createEvent(actionId, type, payloads) {
      return {
        "actionID": actionId,
        "type": type,
        "stamp": new Date().getTime(),
        "payloads" : payloads
      }
    }
    
    
    const destroyAuthentication = () => {
      const authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
    
      window.viamApi.setIdentity("");
      window.viamApi.setSessionData("", "");
    
      clearPinCodeTtl(authenticationPublicKey);
    
      localStorage.removeItem("uuid");
      localStorage.removeItem("token");
      localStorage.removeItem("authenticatedIdentity");
    
      window.currentlyAuthenticatedIdentity = null;
      window.lastTimeGetProfile = 0;
    };
    
    const destroyIdentity = () => {
      destroyAuthentication();
    
      if (window.currentlyLoadedIdentity) {
        const { publicKey } = window.currentlyLoadedIdentity.authentication;
    
        delete window.loadedIdentities[publicKey];
        window.currentlyLoadedIdentity = null;
        destroyIdentityFromLocalStorage(publicKey);
      }
    };
    
    
    Markin Igor's avatar
    Markin Igor committed
    window.loadedIdentities = {};
    
    window.wopiAPI = new WopiAPI();
    
    window.collaboraApi = new CollaboraAPI();
    
    window.viamApi = new ViamAPI();
    window.viamAnonymousApi = new ViamAPI();
    
    Markin Igor's avatar
    Markin Igor committed
    window.currentlyAuthenticatedIdentity = null;
    window.currentlyLoadedIdentity = null;
    window.lastTimeGetProfile = 0;
    
    let iframeParent = null;
    
    
    Markin Igor's avatar
    Markin Igor committed
    const handleIdentityLogin = (identity, uuid, token) => {
      const { loadedIdentities, viamApi } = window;
      const { publicKey } = identity.authentication;
    
      viamApi.setSessionData(uuid, token);
      localStorage.setItem("uuid", uuid);
      localStorage.setItem("token", token);
      localStorage.setItem("authenticatedIdentity", publicKey);
      window.currentlyAuthenticatedIdentity = loadedIdentities[publicKey];
      window.lastTimeGetProfile = 0;
      setKeyForUUID(uuid, publicKey);
    
    async function executeRestfulFunction(type, that, fn, config, ...args) {
    
      const { currentlyAuthenticatedIdentity, viamApi, currentlyLoadedIdentity } = window;
    
      const response = await fn.apply(that, [config, ...args]);
    
      const identity = currentlyAuthenticatedIdentity || currentlyLoadedIdentity;
    
      const deviceRevoked = type === "private" && code === "401" && status === STATUS_DEVICE_REVOKED;
      if (deviceRevoked) {
        destroyIdentity();
    
        const event = createEvent("", "DeviceRevoked");
        iframeParent.onEvent(event);
    
      const badSession = type === "private" && identity && code === "400" && status === "Bad session";
    
      if (!badSession) return response.data;
    
      const loginResponse = await viamApi.identityLogin("previousaddeddevice");
      if (loginResponse.data.code !== "200") return loginResponse.data;
    
      const uuid = loginResponse.data.data["Uuid"];
      const token = loginResponse.data.data["Session"];
      handleIdentityLogin(identity, uuid, token);
    
      const { data } = await fn.apply(that, [config, ...args]);
    
    }
    
    window.executeRestfulFunction = executeRestfulFunction;
    
    
    function loadIdentityInternal(identityKey, pinCode) {
      return new Penpal.Promise(result => {
    
        getIdentityFromLocalStorage(identityKey, pinCode).then(async (loadedIdentity) => {
    
          if (loadedIdentity == null) {
            result({
              "data": "",
              "code": "400",
    
    Olgun Cengiz's avatar
    Olgun Cengiz committed
              "status": "Please restore or authorize your account via another device."
    
    Olgun Cengiz's avatar
    Olgun Cengiz committed
          localStorage.removeItem("attempt");
    
          window.loadedIdentities[identityKey] = loadedIdentity;
    
          window.currentlyLoadedIdentity = loadedIdentity;
    
    
          if (identityKey === localStorage.getItem("authenticatedIdentity")) {
    
            window.currentlyAuthenticatedIdentity = loadedIdentity;
    
            const uuid = localStorage.getItem("uuid");
            const token = localStorage.getItem("token");
    
            const deviceHash = await createDeviceHash(identityKey);
    
    Markin Igor's avatar
    Markin Igor committed
            window.viamApi.setIdentity(identityKey);
            window.viamApi.setDeviceHash(deviceHash);
            window.viamApi.setSessionData(uuid, token);
    
          window.viamAnonymousApi.setIdentity(window.currentlyLoadedIdentity.authentication.publicKey);
    
          const { publicKey, x509Certificate } = loadedIdentity.authentication;
    
            "data": {
              authentication: {
                publicKey,
                x509Certificate
              }
            },
    
            "code": "200",
            "status": "Identity loaded"
    
        }).catch((e) => {
          result({
            "data": "",
            "code": "400",
    
    Olgun Cengiz's avatar
    Olgun Cengiz committed
            "status": "" + e
    
      });
    }
    
    function changeIdentityPinCodeInternal(key, oldPinCode, newPinCode) {
    
      return new Penpal.Promise(result => {
        getIdentityFromLocalStorage(key, oldPinCode, false).then((identity) => {
    
          identity.pinCode = newPinCode;
    
          setIdentityInLocalStorage(identity).then(() => {
    
            result({
              "data": "",
              "code": "200",
              "status": "Successfully changed pincode"
            });
    
          }).catch((e) => {
            result({
              "data": "",
              "code": "400",
              "status": "Cannot store identity " + e
            });
          });
    
        }).catch((e) => {
          result({
            "data": "",
            "code": "400",
            "status": "Cannot get identity " + e
          });
    
        });
      });
    }
    
    function getCertificateForPassport(passportUUID, internal) {
    
      return new Penpal.Promise(certificateResult => {
    
        if (window.currentlyAuthenticatedIdentity === null) {
    
          return {"data" : "",
            "code" : "400",
            "status" : "Identity not authenticated"
          }
        }
    
    
        const passportIdentity = window.currentlyAuthenticatedIdentity;
    
    Markin Igor's avatar
    Markin Igor committed
        var passport = passportIdentity.getPassport(passportUUID);
    
        if(passport === undefined || passport === null) {
          createPassportCertificate(passportUUID).then(function(keys){
    
    Markin Igor's avatar
    Markin Igor committed
            var cryptoData = new CryptoData();
            cryptoData.setPublicKey(keys["publicKeyPEM"]);
            cryptoData.setPrivateKey(keys["privateKeyPEM"]);
            var certificate = keys["certificatePEM"];
    
            //download("passportCertificateBeforeSigning.crt", "text/plain", certificate)
            //cryptoData.setx509Certificate(keys["certificate"])
    
            executeRestfulFunction("private", viamApi, viamApi.signSignCertificate, null, btoa(certificate), passportUUID).then(executeResult => {
    
    Markin Igor's avatar
    Markin Igor committed
              if(executeResult.code === "200") {
    
    Markin Igor's avatar
    Markin Igor committed
                var signedCertificate = atob(executeResult.data["SignedCertificate"]);
    
                //download("passportCertificateAfterSigning.crt", "text/plain", signedCertificate)
    
    Markin Igor's avatar
    Markin Igor committed
                var keyUUID = executeResult.data["CertificateUUID"];
                var encodedChain = executeResult.data["Chain"];
    
                //download("rootCertificate.crt", "text/plain", atob(encodedChain[0]))
    
    
    Markin Igor's avatar
    Markin Igor committed
                var chain = [];
    
    
                for(var i = 0; i < encodedChain.length; i++) {
                  chain.push(atob(encodedChain[i]))
                }
    
    
    Markin Igor's avatar
    Markin Igor committed
                cryptoData.setx509Certificate(signedCertificate);
                cryptoData.setKeyUUID(keyUUID);
                cryptoData.setChain(chain);
    
    Markin Igor's avatar
    Markin Igor committed
                passportIdentity.setPassport(passportUUID, cryptoData);
    
    
                getProfileData(passportIdentity).then(executeResult1 => {
                  setIdentityInLocalStorage(passportIdentity).then(() => {
    
                    window.currentlyAuthenticatedIdentity = passportIdentity;
                    window.lastTimeGetProfile = 0;
                    window.currentlyLoadedIdentity = passportIdentity;
                    const copyOfCryptoData = JSON.parse(JSON.stringify(cryptoData));
    
    
                    if (internal === false) {
    
                      copyOfCryptoData["privateKey"] = "";
    
                    }
    
                    certificateResult({
                      "data": copyOfCryptoData,
                      "code": "200",
                      "status": "Certificate got"
                    });
                  }).catch((e) => {
                    certificateResult({
                      "data": "",
                      "code": "400",
                      "status": "Can not store certificate " + e
                    });
                  });
                });
              } else {
    
                certificateResult(executeResult);
    
    Markin Igor's avatar
    Markin Igor committed
          var copyOfCryptoData = JSON.parse(JSON.stringify(passport));
    
    
          if(internal === false) {
            copyOfCryptoData["privateKey"] = ""
          }
    
          certificateResult({"data" : copyOfCryptoData,
            "code" : "200",
            "status" : "Certificate got"
          });
        }
      });
    }
    
    const connection = Penpal.connectToParent({
      // Methods child is exposing to parent
      methods: {
    
        initialize: (apiUrl, wopiUrl, collaboraUrl) => {
    
          if (!apiUrl) {
            apiUrl = `${window.location.origin}/api/`;
            console.warn(`API host URL not specified. Fall back to ${apiUrl}`); // eslint-disable-line no-console
          }
    
          if (!wopiUrl) {
            wopiUrl = `${window.location.origin}/wopi/`;
            console.warn(`WOPI host URL not specified. Fall back to ${wopiUrl}`); // eslint-disable-line no-console
          }
    
          if (!collaboraUrl) {
            collaboraUrl = window.location.origin;
            console.warn(`Collabora host URL not specified. Fall back to ${collaboraUrl}`); // eslint-disable-line no-console
          }
    
    
          window.API_HOST = apiUrl.charAt(apiUrl.length - 1) === "/" ? apiUrl : apiUrl + "/";
    
          window.WOPI_URL = wopiUrl.charAt(wopiUrl.length - 1) === "/" ? wopiUrl : wopiUrl + "/";
          window.COLLABORA_URL = collaboraUrl.charAt(collaboraUrl.length - 1) === "/" ? collaboraUrl : collaboraUrl + "/";
    
        createIdentity(pinCode) {
          return new Penpal.Promise(result => {
            createPassportCertificate(makeid()).then(function(keys){
    
    Markin Igor's avatar
    Markin Igor committed
              var newIdentity = new Identity();
              var cryptoData = new CryptoData();
              cryptoData.setPublicKey(keys["publicKeyPEM"]);
              cryptoData.setPrivateKey(keys["privateKeyPEM"]);
              cryptoData.setx509Certificate(keys["certificatePEM"]);
              newIdentity.setAuthentication(cryptoData);
              newIdentity.setPinCode(pinCode);
    
              window.currentlyLoadedIdentity = newIdentity;
              window.loadedIdentities[newIdentity.authentication.publicKey] = newIdentity;
    
    Markin Igor's avatar
    Markin Igor committed
              extendPinCodeTtl(newIdentity.authentication.publicKey, pinCode);
    
              window.viamAnonymousApi.setIdentity(newIdentity.authentication.publicKey);
    
    
              result({"data" : newIdentity,
                "code" : "200",
                "status" : "Identity created"
              })
    
          })
        },
        listIdentities() {
          return new Penpal.Promise(result => {
    
    Markin Igor's avatar
    Markin Igor committed
            var identities = listIdentitiesFromLocalStorage();
    
            result({"data" : identities,
              "code" : "200",
              "status" : "Identities listed"
            })
          });
        },
        loadIdentity(identityKey, pinCode) {
          return loadIdentityInternal(identityKey, pinCode)
        },
        changeIdentityPinCode(key, oldPinCode, newPinCode) {
          return changeIdentityPinCodeInternal(key, oldPinCode, newPinCode)
        },
        getIdentityProfile(identityKey) {
          return new Penpal.Promise(result => {
    
            const serializedProfile = localStorage.getItem("profiles/" + identityKey);
            if (serializedProfile === null || serializedProfile === "") {
    
              result({"data" : "",
                "code" : "400",
                "status" : "Profile is empty"
              });
            } else {
              result({"data" : JSON.parse(serializedProfile),
                "code" : "200",
                "status" : "Identities cleared"
              })
            }
          });
        },
        clearIdentities() {
          return new Penpal.Promise(result => {
    
    Markin Igor's avatar
    Markin Igor committed
            var identitiesTemp = listIdentitiesFromLocalStorage();
    
            for(var i in identitiesTemp) {
              destroyIdentityFromLocalStorage(i)
            }
            result({"data" : "",
              "code" : "200",
              "status" : "Identities cleared"
            })
          });
        },
    
        confirmIdentificator(identity, confirmationCodeArg) {
          return new Penpal.Promise(result => {
    
    Markin Igor's avatar
    Markin Igor committed
            viamApi.setIdentity(identity.authentication.publicKey);
    
            executeRestfulFunction("public", viamApi, viamApi.identityConfirmIdentificator, null, confirmationCodeArg).then(executeResult => {
    
              result(executeResult);
            });
          });
        },
        identityGetIdentificatorByRegisterToken(identity, tokenArg) {
          return new Penpal.Promise(result => {
    
    Markin Igor's avatar
    Markin Igor committed
            viamApi.setIdentity(identity.authentication.publicKey);
    
            executeRestfulFunction("public", viamApi, viamApi.identityGetIdentificatorByRegisterToken, null, tokenArg).then(executeResult => {
    
              result(executeResult);
            });
          });
        },
        submitIdentificator(identity, identificatorArg, registerToken) {
          return new Penpal.Promise(result => {
    
    Markin Igor's avatar
    Markin Igor committed
            viamApi.setIdentity(identity.authentication.publicKey);
    
            executeRestfulFunction("public", viamApi, viamApi.identitySubmitIdentificator, null, identificatorArg, registerToken).then(executeResult => {
    
              result(executeResult);
            });
          });
        },
        submitRegisterClaims(identity, givennameArg,familynameArg,emailArg,phonenumberArg) {
          return new Penpal.Promise(result => {
    
    Markin Igor's avatar
    Markin Igor committed
            viamApi.setIdentity(identity.authentication.publicKey);
    
            executeRestfulFunction("public", viamApi, viamApi.identitySubmitRegisterClaims, null, givennameArg,familynameArg,emailArg,phonenumberArg).then(executeResult => {
    
              result(executeResult);
            });
          });
        },
        agreeOnRegistration(registerIdentity) {
    
          return new Penpal.Promise(result => {
    
    Markin Igor's avatar
    Markin Igor committed
            viamApi.setIdentity(registerIdentity.authentication.publicKey);
    
            executeRestfulFunction("public", viamApi, viamApi.identityAgreeOnRegistration, null).then(executeResult => {
    
    Markin Igor's avatar
    Markin Igor committed
              let sequence = Promise.resolve();
    
              if (executeResult.code === "200") {
                sequence = sequence.then(() => {
                    setIdentityInLocalStorage(registerIdentity)
                  }
                )
              }
              sequence.then(() => {
                result(executeResult);
              }).catch((e) => {
                result({
                  "data": "",
                  "code": "400",
                  "status": "Can not store identity: " + e
                })
              })
            });
          });
        },
        resendConfirmationCode(identity, identificatorArg) {
          return new Penpal.Promise(result => {
    
    Markin Igor's avatar
    Markin Igor committed
            viamApi.setIdentity(identity.authentication.publicKey);
    
            executeRestfulFunction("public", viamApi, viamApi.identityResendConfirmationCode, null, identificatorArg).then(executeResult => {
    
              result(executeResult);
            });
          });
        },
    
    Markin Igor's avatar
    Markin Igor committed
        login: async (loginIdentity, mode, requestCode, requestActionID) => {
          if (!window.loadedIdentities[loginIdentity.authentication.publicKey]) {
            return {
              data: "",
              code: "400",
              status: "Identity not loaded"
            };
          }
    
    Markin Igor's avatar
    Markin Igor committed
          const deviceHash = await createDeviceHash(loginIdentity.authentication.publicKey);
    
    Markin Igor's avatar
    Markin Igor committed
          window.viamApi.setDeviceHash(deviceHash);
    
    Markin Igor's avatar
    Markin Igor committed
          window.viamApi.setIdentity(loginIdentity.authentication.publicKey);
    
          const identityLoginResponse =
            await executeRestfulFunction(
              "public",
              window.viamApi,
              window.viamApi.identityLogin,
    
    Markin Igor's avatar
    Markin Igor committed
              mode, requestCode,
              requestActionID
            );
    
          const { code, data } = identityLoginResponse;
          const responseToClient = Object.assign({}, identityLoginResponse);
    
          if (code === "200") {
            if (mode === LOGIN_MODES.SMS || mode === LOGIN_MODES.PREVIOUSLY_ADDED_DEVICE) {
    
    Markin Igor's avatar
    Markin Igor committed
              handleIdentityLogin(loginIdentity, data.Uuid, data.Session);
    
    Markin Igor's avatar
    Markin Igor committed
              await getProfileData(loginIdentity);
    
    
              if (mode === LOGIN_MODES.SMS) {
    
    Markin Igor's avatar
    Markin Igor committed
                await setIdentityInLocalStorage(loginIdentity);
    
    Markin Igor's avatar
    Markin Igor committed
            } else if (mode === LOGIN_MODES.NEW_DEVICE) {
              const dataUrl = await QRCode.toDataURL(`${data.ActionID},${data.QrCode}`);
              Object.assign(responseToClient.data, { image: dataUrl });
            }
          }
    
          return responseToClient;
    
        identityPullAvatarFromGravatar: async () => {
          const authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
    
          if (
            !authenticationPublicKey ||
            !window.loadedIdentities[authenticationPublicKey] ||
            !extendPinCodeTtl(authenticationPublicKey)
          ) {
            return encodeResponse("400", "", "Identity not authenticated");
    
          return await executeRestfulFunction("private", viamApi, viamApi.identityPullAvatarFromGravatar);
    
        identityAddNewDevice() {
          return new Penpal.Promise(result => {
    
            const authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
    
            if (authenticationPublicKey === null) {
    
              result({"data" : "",
                "code" : "400",
                "status" : "Identity not authenticated"
              })
            }
    
    
            if (window.loadedIdentities[authenticationPublicKey] === null) {
    
              result({"data" : "",
                "code" : "400",
                "status" : "Identity not authenticated"
              })
            }
    
    
    Markin Igor's avatar
    Markin Igor committed
            var success = extendPinCodeTtl(authenticationPublicKey);
    
    Markin Igor's avatar
    Markin Igor committed
            if(success === false) {
    
              result({"data" : "",
                "code" : "400",
                "status" : "Identity not authenticated"
              })
            }
    
    
            executeRestfulFunction("private", viamApi, viamApi.identityAddNewDevice, null).then(executeResult => {
    
    Markin Igor's avatar
    Markin Igor committed
              if (executeResult.code === "200") {
    
    Markin Igor's avatar
    Markin Igor committed
                var actionID = executeResult.data["ActionID"];
                var QrCode = executeResult.data["QrCode"];
    
                QRCode.toDataURL(actionID + "," + QrCode, function (err, url) {
    
    Markin Igor's avatar
    Markin Igor committed
                  executeResult.data["image"] = url;
    
                  result(executeResult);
                })
              } else {
                result(executeResult);
              }
            });
          });
        },
        identityDestroyKeysForDevice(authenticationPublicKeyArg) {
          return new Penpal.Promise(result => {
    
            const authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
            if (authenticationPublicKey === null) {
    
              result({"data" : "",
                "code" : "400",
                "status" : "Identity not authenticated"
              })
            }
    
            if (window.loadedIdentities[authenticationPublicKey] === null) {
    
              result({"data" : "",
                "code" : "400",
                "status" : "Identity not authenticated"
              })
            }
    
    
    Markin Igor's avatar
    Markin Igor committed
            var success = extendPinCodeTtl(authenticationPublicKey);
    
    Markin Igor's avatar
    Markin Igor committed
            if(success === false) {
    
              result({"data" : "",
                "code" : "400",
                "status" : "Identity not authenticated"
              })
            }
    
    
            executeRestfulFunction("private", viamApi, viamApi.identityDestroyKeysForDevice, null, btoa(authenticationPublicKeyArg)).then(executeResult => {
    
              result(executeResult);
            });
          });
        },
    
    Markin Igor's avatar
    Markin Igor committed
        logout: async () => {
    
          const authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
    
    Markin Igor's avatar
    Markin Igor committed
          if (!authenticationPublicKey || !window.loadedIdentities[authenticationPublicKey]) {
            return {
              data: "",
              code: "400",
              status: "Identity not loaded"
            };
    
    Markin Igor's avatar
    Markin Igor committed
          const identityLogoutResponse = await executeRestfulFunction(
            "private",
            window.viamApi,
    
    Markin Igor's avatar
    Markin Igor committed
          );
    
    
          destroyAuthentication();
    
    Markin Igor's avatar
    Markin Igor committed
    
          return identityLogoutResponse;
    
        },
        identityRestoreAccess(restoreAccessIdentity, identificator) {
          return new Penpal.Promise(result => {
    
    Markin Igor's avatar
    Markin Igor committed
            viamApi.setIdentity(restoreAccessIdentity.authentication.publicKey);
    
            executeRestfulFunction("public", viamApi, viamApi.identityRestoreAccess, null, identificator).then(executeResult => {
    
                result(executeResult);
            });
          });
        },
    
        getCurrentlyLoggedInUUID() {
          return new Penpal.Promise(result => {
    
            const authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
            if (authenticationPublicKey === null) {
    
              return {"data" : "",
                "code" : "400",
                "status" : "Identity not loaded"
              }
            }
    
            if (window.loadedIdentities[authenticationPublicKey] === null) {
    
              return {"data" : "",
                "code" : "400",
                "status" : "Identity not loaded"
              }
            }
    
    
    Markin Igor's avatar
    Markin Igor committed
            var success = extendPinCodeTtl(authenticationPublicKey);
    
    Markin Igor's avatar
    Markin Igor committed
            if(success === false) {
    
              result({"data" : "",
                "code" : "400",
                "status" : "Identity not authenticated"
              })
            }
    
            if(localStorage.getItem("uuid") === null) {
              result({"data" : "",
                "code" : "400",
                "status" : "Not logged in UUID"
              })
            }
            result({"data" : localStorage.getItem("uuid"),
              "code" : "200",
              "status" : "UUID loaded"
            })
          });
        },
        getCertificateByPassport(passportUUID) {
          return new Penpal.Promise(result => {
    
            const authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
            if (authenticationPublicKey === null) {
    
              return {"data" : "",
                "code" : "400",
                "status" : "Identity not loaded"
              }
            }
    
            if (window.loadedIdentities[authenticationPublicKey] === null) {
    
              return {"data" : "",
                "code" : "400",
                "status" : "Identity not loaded"
              }
            }
    
    
    Markin Igor's avatar
    Markin Igor committed
            var success = extendPinCodeTtl(authenticationPublicKey);
    
    Markin Igor's avatar
    Markin Igor committed
            if(success === false) {
    
              result({"data" : "",
                "code" : "400",
                "status" : "Identity not authenticated"
              })
            }
    
            getCertificateForPassport(passportUUID, false).then(certificateResult => {
              result(certificateResult)
            })
          });
        },
        getOneTimeCertificateByPassport(passportUUID, emailArg) {
          return new Penpal.Promise(result => {
    
            const authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
            if (authenticationPublicKey === null) {
    
              return {"data" : "",
                "code" : "400",
                "status" : "Identity not loaded"
              }
            }
    
            if (window.loadedIdentities[authenticationPublicKey] === null) {
    
              return {"data" : "",
                "code" : "400",
                "status" : "Identity not loaded"
              }
            }
    
    
    Markin Igor's avatar
    Markin Igor committed
            var success = extendPinCodeTtl(authenticationPublicKey);
    
    Markin Igor's avatar
    Markin Igor committed
            if(success === false) {
    
              result({"data" : "",
                "code" : "400",
                "status" : "Identity not authenticated"
              })
            }
    
            getCertificateForPassport(passportUUID, true).then(certificateResult => {
    
    Markin Igor's avatar
    Markin Igor committed
              if(certificateResult.code === "200") {
    
    Markin Igor's avatar
    Markin Igor committed
                var passportCertificate = certificateResult.data["x509Certificate"];
                var passportPrivateKey = certificateResult.data["privateKey"];
                var passportChain = certificateResult.data["chain"];
    
    
                createOneTimePassportCertificate(makeid() + "-" + passportUUID, emailArg, passportPrivateKey, passportCertificate).then(function(keys){
    
    Markin Igor's avatar
    Markin Igor committed
                  var publicKeyOneTime = keys["publicKeyPEM"];
                  var privateKeyOneTime = keys["privateKeyPEM"];
                  var certificateOneTime = keys["certificatePEM"];
                  passportChain.push(passportCertificate);
    
    
                  var oneTimeCryptoData = new CryptoData();
    
    Markin Igor's avatar
    Markin Igor 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"
                })
              }
            })
          });
        },
    
        signEmail: async (passportUUID, emailArg, emailMessage) => {
          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;
    
          const keys =
            await createOneTimePassportCertificate(
              makeid() + "-" + passportUUID, emailArg, passportPrivateKey, passportCertificate);
    
          const { privateKeyPEM: privateKeyOneTime, certificatePEM: certificateOneTime } = keys;
    
          passportChain.push(passportCertificate);
    
          response = await executeRestfulFunction(
    
            "private", window.viamApi, window.viamApi.passportGetEmailWithHeaderByPassport, null, passportUUID, emailMessage);
    
    
          if (response.code !== "200") {
            return encodeResponse("400", "", response.status);
          }
    
          const signedEmail = await signEmail(response.data, certificateOneTime, passportChain, privateKeyOneTime);
    
          response = await executeRestfulFunction(
    
            "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");
    
        documentCreateDocument: async (path, passportUUID, contenttype) => {
    
          const authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
          if (
            !authenticationPublicKey ||
            !window.loadedIdentities[authenticationPublicKey] ||
            !extendPinCodeTtl(authenticationPublicKey)
          ) {
            return encodeResponse("400", "", "Identity not authenticated");
          }
    
    
          const config = {
            headers: {
              path,
              passportuuid: passportUUID,
              contenttype
            }
          };
          const response = await executeRestfulFunction("private", window.viamApi, window.viamApi.documentCreateDocument,
            config);
    
    
          return encodeResponse("200", response.data, "Document created");
        },
    
        documentPutDocument: async (passportUUID, resourceid, file) => {
    
          const authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
          if (
            !authenticationPublicKey ||
            !window.loadedIdentities[authenticationPublicKey] ||
            !extendPinCodeTtl(authenticationPublicKey)
          ) {
            return encodeResponse("400", "", "Identity not authenticated");
          }
    
    
          const config = {
            headers: {
              'Content-Type': 'multipart/form-data',
              passportuuid: passportUUID,
              resourceid
            }
          };
    
    
          const response = await executeRestfulFunction(
    
            "private", window.viamApi, window.viamApi.documentPutDocument, config, file);
    
    
          return encodeResponse("200", response.data, "Document created");
        },
    
        hasSession() {
          return new Penpal.Promise(result => {
    
            const authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
            if (authenticationPublicKey === null) {
    
              result({"data" : "",
                "code" : "400",
                "status" : "Identity not authenticated"
              });
            }
    
            if (window.loadedIdentities[authenticationPublicKey] === null) {
    
              result({"data" : "",
                "code" : "400",
                "status" : "Identity not authenticated"
              });
            }
    
    
    Markin Igor's avatar
    Markin Igor committed
            var success = extendPinCodeTtl(authenticationPublicKey);