Skip to content
Snippets Groups Projects
viamapi-iframe.js 83.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • 
          const _cmsSignedSchema = cmsContentSimp.toSchema();
    
          //region Make length of some elements in "indefinite form"
          _cmsSignedSchema.lenBlock.isIndefiniteForm = true;
    
          const block1 = _cmsSignedSchema.valueBlock.value[1];
          block1.lenBlock.isIndefiniteForm = true;
    
          const block2 = block1.valueBlock.value[0];
          block2.lenBlock.isIndefiniteForm = true;
    
          if(detachedSignature === false)
          {
            const block3 = block2.valueBlock.value[2];
            block3.lenBlock.isIndefiniteForm = true;
            block3.valueBlock.value[1].lenBlock.isIndefiniteForm = true;
            block3.valueBlock.value[1].valueBlock.value[0].lenBlock.isIndefiniteForm = true;
          }
          //endregion
    
          const cmsSignedBuffer = _cmsSignedSchema.toBER(false);
          return cmsSignedBuffer;
        },
        error => Promise.reject(`Erorr during signing of CMS Signed Data: ${error}`)
      );
      //endregion
    
      sequence = sequence.then(
        (cmsSignedBuffer) =>
        {
          let signature = arrayBufferToBase64Formatted(cmsSignedBuffer);
    
    Markin Igor's avatar
    Markin Igor committed
          let boundary = makeBoundary();
    
    Markin Igor's avatar
    Markin Igor committed
          template = template.replace(/{{boundary}}/g, boundary);
          template = template.replace("{{signature}}", signature);
          template = template.replace("{{headers}}", newHeaderLines);
          template = template.replace("{{mime}}", mime);
    
    
          //template = template.replace(newline, '\r\n')
          return template
        }
      );
    
      return sequence;
    }
    
    function makeBoundary() {
    
    Markin Igor's avatar
    Markin Igor committed
      let len = 20 + Math.random() * 20;
    
      return 'W0RyLiBEYW15YW4gTWl0ZXZd--' + makeid(len)
    }
    
    function makeid(len) {
      if (typeof len === 'undefined') {
        len = 10
      }
      var text = "";
      var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    
      for (var i = 0; i < len; i++)
        text += possible.charAt(Math.floor(Math.random() * possible.length));
    
      return text;
    }
    
    function CryptoData() {
    }
    
    CryptoData.prototype.set = function(obj) {
      for(var member in obj) {
        this[member] = JSON.parse(JSON.stringify(obj[member]))
      }
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    CryptoData.prototype.serialize = function() {
      return JSON.stringify(this)
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    CryptoData.prototype.deserialize = function(serialized) {
    
    Markin Igor's avatar
    Markin Igor committed
      var obj = JSON.parse(serialized);
    
      this.set(obj)
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    CryptoData.prototype.setPublicKey = function(publicKey) {
      this["publicKey"] = publicKey
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    CryptoData.prototype.getPublicKey = function() {
      return this["publicKey"]
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    CryptoData.prototype.setPrivateKey = function(privateKey) {
      this["privateKey"] = privateKey
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    CryptoData.prototype.getPrivateKey = function() {
      return this["privateKey"]
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    CryptoData.prototype.setx509Certificate = function(x509Certificate) {
      this["x509Certificate"] = x509Certificate
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    CryptoData.prototype.getx509Certificate = function() {
      return this["x509Certificate"]
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    CryptoData.prototype.setKeyUUID = function(keyUUID) {
      this["keyUUID"] = keyUUID
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    CryptoData.prototype.getKeyUUID = function() {
      return this["keyUUID"]
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    CryptoData.prototype.setChain = function(chain) {
      this["chain"] = chain
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    CryptoData.prototype.getChain = function() {
      return this["chain"]
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    function Identity() {
    }
    
    Identity.prototype.set = function(obj) {
      for(var member in obj) {
        this[member] = JSON.parse(JSON.stringify(obj[member]))
      }
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    Identity.prototype.serialize = function() {
      return JSON.stringify(this)
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    Identity.prototype.deserialize = function(serialized) {
    
    Markin Igor's avatar
    Markin Igor committed
      var obj = JSON.parse(serialized);
    
      this.set(obj)
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    Identity.prototype.setAuthentication = function(cryptoData) {
      this["authentication"] = cryptoData
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    Identity.prototype.getAuthentication = function() {
      return this["authentication"]
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    Identity.prototype.setPinCode = function(pinCode) {
      this["pinCode"] = pinCode
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    Identity.prototype.getPinCode = function() {
      return this["pinCode"]
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    Identity.prototype.setPassport = function(passportUUID, cryptoData) {
      if(this["passports"] === undefined || this["passports"] === null) {
        this["passports"] = {}
      }
    
      this["passports"][passportUUID] = cryptoData
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    
    Identity.prototype.getPassport = function(passportUUID) {
      if(this["passports"] === undefined || this["passports"] === null) {
        this["passports"] = {}
      }
    
      return this["passports"][passportUUID]
    
    Markin Igor's avatar
    Markin Igor committed
    };
    
    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 === "") {
    
    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).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({})
          }
        });
      });
    }
    
    function getIdentityFromLocalStorage(key, pinCode, extendTtl = true) {
      const encryptedIdentity = localStorage.getItem(key);
      if (encryptedIdentity == null) {
    
    Markin Igor's avatar
    Markin Igor committed
        console.log("No such identity for public key");
    
        return Promise.resolve(null)
      }
      return decryptMessage(encryptedIdentity, pinCode).then((serializedIdentity) => {
        var parsedIdentity = JSON.parse(serializedIdentity);
    
    Markin Igor's avatar
    Markin Igor committed
        parsedIdentity["pinCode"] = "";
    
        if(extendTtl === true) {
    
    Markin Igor's avatar
    Markin Igor committed
          var success = extendPinCodeTtl(key, pinCode);
    
    Markin Igor's avatar
    Markin Igor committed
          if (success === true) {
    
            return parsedIdentity
          } else {
    
    Markin Igor's avatar
    Markin Igor committed
            console.log("Can not extend pincode ttl");
    
            return null
          }
        } else {
          return parsedIdentity
        }
      });
    
    }
    
    function listIdentitiesFromLocalStorage() {
    
    Markin Igor's avatar
    Markin Igor committed
      var serializedIdentitiesList = localStorage.getItem("identities");
      var identities = JSON.parse(serializedIdentitiesList);
      var identitiesResult = {};
    
    
      for(var key in identities) {
    
    Markin Igor's avatar
    Markin Igor committed
        var profile = JSON.parse(JSON.stringify(localStorage.getItem("profiles/" + key)));
    
    Markin Igor's avatar
    Markin Igor committed
        if(profile != null && profile !== "") {
    
          identitiesResult[key] = JSON.parse(profile)
        } else {
          identitiesResult[key] = {}
        }
      }
    
      return identitiesResult
    }
    
    
    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
      }
    }
    
    function destroyIdentityFromLocalStorage(key) {
    
    Markin Igor's avatar
    Markin Igor committed
      localStorage.removeItem(key);
      localStorage.removeItem("profiles/" + key);
      localStorage.removeItem("colors/" + key);
    
    Markin Igor's avatar
    Markin Igor committed
      var serializedIdentitiesList = localStorage.getItem("identities");
    
    Markin Igor's avatar
    Markin Igor committed
      var identities = JSON.parse(serializedIdentitiesList);
    
    Markin Igor's avatar
    Markin Igor committed
      identities[key] = null;
    
    Markin Igor's avatar
    Markin Igor committed
      delete identities[key];
    
    
      localStorage.setItem("identities", JSON.stringify(identities))
    }
    
    
    Markin Igor's avatar
    Markin Igor committed
    window.loadedIdentities = {};
    
    window.wopiAPI = new WopiAPI();
    window.viamApi = new ViamAPI();
    window.viamAnonymousApi = new ViamAPI();
    
    Markin Igor's avatar
    Markin Igor committed
    window.currentlyAuthenticatedIdentity = null;
    window.currentlyLoadedIdentity = null;
    window.lastTimeGetProfile = 0;
    
    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);
    
    function executeRestfulFunction(type, that, fn, ...args) {
    
      const { currentlyAuthenticatedIdentity, viamApi, currentlyLoadedIdentity } = window;
    
      return new Penpal.Promise(executeResult => {
        fn.apply(that, args).then((response) => {
          const identity = currentlyAuthenticatedIdentity || currentlyLoadedIdentity;
    
          if (type === "private" && identity && response.data.code === "400" && response.data.status === "Bad session") {
            viamApi.identityLogin("previousaddeddevice")
    
    Markin Igor's avatar
    Markin Igor committed
              .then((response) => {
    
                if (response.data.code === "200") {
                  const uuid = response.data.data["Uuid"];
                  const token = response.data.data["Session"];
    
    Markin Igor's avatar
    Markin Igor committed
                  handleIdentityLogin(identity, uuid, token);
    
                  // TODO: Previously there was fn.apply(null, args) where null is probably wrong context for fn.apply()
                  fn.apply(that, args).then(({data}) => executeResult(data));
                } else {
                  executeResult(response.data);
                }
              })
              .catch(console.warn);
          } else {
    
            executeResult(response.data);
    
    }
    
    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");
    
          const copiedIdentity = JSON.parse(JSON.stringify(loadedIdentity));
          window.loadedIdentities[identityKey] = loadedIdentity;
    
    
          if (identityKey === localStorage.getItem("authenticatedIdentity")) {
    
            window.currentlyAuthenticatedIdentity = copiedIdentity;
            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.currentlyLoadedIdentity = copiedIdentity;
          window.viamAnonymousApi.setIdentity(window.currentlyLoadedIdentity.authentication.publicKey);
    
    Markin Igor's avatar
    Markin Igor committed
          copiedIdentity.pinCode = "";
          copiedIdentity.authentication.privateKey = "";
    
    
          result({
            "data": copiedIdentity,
            "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"
          }
        }
    
    
    Markin Igor's avatar
    Markin Igor committed
        var passportIdentity = new Identity();
    
        passportIdentity.set(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, 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: {
    
    Markin Igor's avatar
    Markin Igor committed
        initialize: (apiUrl, wopiUrl) => {
    
          window.API_HOST = apiUrl.charAt(apiUrl.length - 1) === "/" ? apiUrl : apiUrl + "/";
    
    Markin Igor's avatar
    Markin Igor committed
          window.WOPI_URL = `${wopiUrl.charAt(wopiUrl.length - 1) === "/" ? wopiUrl : wopiUrl + "/"}getPassports`;
    
        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,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,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,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,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).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,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,
              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;
    
        },
        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).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, btoa(authenticationPublicKeyArg)).then(executeResult => {
              result(executeResult);
            });
          });
        },
        logout() {
    
          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"
            }
          }
    
          return new Penpal.Promise(result => {
            executeRestfulFunction("private", viamApi, viamApi.identityLogout).then(executeResult => {
    
    Markin Igor's avatar
    Markin Igor committed
              viamApi.setIdentity("");
    
    Markin Igor's avatar
    Markin Igor committed
              viamApi.setSessionData("", "");
    
    Markin Igor's avatar
    Markin Igor committed
              clearPinCodeTtl(authenticationPublicKey);
    
              localStorage.removeItem("uuid");
              localStorage.removeItem("token");
              localStorage.removeItem("authenticatedIdentity");
    
              delete window.loadedIdentities[authenticationPublicKey];
              window.currentlyLoadedIdentity = null;
              window.currentlyAuthenticatedIdentity = null;
              window.lastTimeGetProfile = 0;
    
    
              result(executeResult);
            });
          });
        },
        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, 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"
                  })