diff --git a/javascript/src/iframe/viamapi-iframe.js b/javascript/src/iframe/viamapi-iframe.js index 43bb11975575dcc19d459600ddabfb97fa763c46..56cf322e3b4ec42b598d268917e71a9ee069c047 100644 --- a/javascript/src/iframe/viamapi-iframe.js +++ b/javascript/src/iframe/viamapi-iframe.js @@ -269,7 +269,7 @@ async function executeRestfulFunction(type, that, fn, config, ...args) { const badSession = type === "private" && identity && code === "400" && status === "Bad session"; if (!badSession) return response.data; - const loginResponse = await viamApi.identityLogin("previousaddeddevice"); + const loginResponse = await viamApi.identityLogin(null, "previousaddeddevice"); if (loginResponse.data.code !== "200") return loginResponse.data; const uuid = loginResponse.data.data["Uuid"]; @@ -330,36 +330,6 @@ function loadIdentityInternal(identityKey, pinCode) { }); } -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 => { @@ -504,8 +474,34 @@ const connection = Penpal.connectToParent({ loadIdentity(identityKey, pinCode) { return loadIdentityInternal(identityKey, pinCode) }, - changeIdentityPinCode(key, oldPinCode, newPinCode) { - return changeIdentityPinCodeInternal(key, oldPinCode, newPinCode) + checkIdentityPinCode: async (key, pinCode) => { + try { + const identity = await getIdentityFromLocalStorage(key, pinCode, false); + + if (identity) { + return encodeResponse("200", null, "Pincode check successful"); + } else { + return encodeResponse("400", null, "Pincode check failed"); + } + } catch (e) { + return encodeResponse("400", e, "Pincode check error"); + } + }, + changeIdentityPinCode: async (key, oldPinCode, newPinCode) => { + try { + const identity = await getIdentityFromLocalStorage(key, oldPinCode, false); + + if (identity) { + identity.pinCode = newPinCode; + await setIdentityInLocalStorage(identity); + + return encodeResponse("200", null, "Successfully changed pincode"); + } else { + return encodeResponse("400", null, "Identity not found"); + } + } catch (e) { + return encodeResponse("400", e.message, "Change pincode error"); + } }, getIdentityProfile(identityKey) { return new Penpal.Promise(result => { @@ -523,18 +519,15 @@ const connection = Penpal.connectToParent({ } }); }, - clearIdentities() { - return new Penpal.Promise(result => { - var identitiesTemp = listIdentitiesFromLocalStorage(); + clearIdentities: async () => { + destroyAuthentication(); - for(var i in identitiesTemp) { - destroyIdentityFromLocalStorage(i) - } - result({"data" : "", - "code" : "200", - "status" : "Identities cleared" - }) - }); + const identitiesTemp = listIdentitiesFromLocalStorage(); + + for (const i in identitiesTemp) { + destroyIdentityFromLocalStorage(i); + } + return encodeResponse("200", "", "Identities cleared"); }, confirmIdentificator(identity, confirmationCodeArg) { return new Penpal.Promise(result => { @@ -615,6 +608,7 @@ const connection = Penpal.connectToParent({ } const deviceHash = await createDeviceHash(loginIdentity.authentication.publicKey); + window.viamApi.setSessionData("", ""); window.viamApi.setDeviceHash(deviceHash); window.viamApi.setIdentity(loginIdentity.authentication.publicKey); @@ -647,19 +641,6 @@ const connection = Penpal.connectToParent({ 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"); @@ -732,28 +713,41 @@ const connection = Penpal.connectToParent({ }); }, logout: async () => { - const authenticationPublicKey = localStorage.getItem("authenticatedIdentity"); - if (!authenticationPublicKey || !window.loadedIdentities[authenticationPublicKey]) { + try { + const authenticationPublicKey = localStorage.getItem("authenticatedIdentity"); + if (!authenticationPublicKey || !window.loadedIdentities[authenticationPublicKey]) { + return { + data: "", + code: "400", + status: "Identity not loaded" + }; + } + + // Clone headers to be able destroy authentication first. + // We need it because clients should be able reload page right after logout invocation and not wait until request completed + const headers = {...window.viamApi.getConfig().headers}; + + destroyAuthentication(); + + return executeRestfulFunction( + "private", + window.viamApi, + window.viamApi.identityLogout, + { + headers + } + ); + } catch (e) { return { data: "", code: "400", - status: "Identity not loaded" + status: e.message }; } - - const identityLogoutResponse = await executeRestfulFunction( - "private", - window.viamApi, - window.viamApi.identityLogout, - null - ); - - destroyAuthentication(); - - return identityLogoutResponse; }, identityRestoreAccess(restoreAccessIdentity, identificator) { return new Penpal.Promise(result => { + viamApi.setSessionData("", ""); viamApi.setIdentity(restoreAccessIdentity.authentication.publicKey); executeRestfulFunction("public", viamApi, viamApi.identityRestoreAccess, null, identificator).then(executeResult => { @@ -1073,6 +1067,64 @@ const connection = Penpal.connectToParent({ return encodeResponse("200", response.data, "PDF signed"); }, + signPdf: async (passportUUID, pdfRaw /*array buffer*/) => { + + //TODO api is not finished + + 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, null, passportPrivateKey, passportCertificate); + + const { privateKeyPEM: privateKeyOneTime, certificatePEM: certificateOneTime } = keys; + + passportChain.push(passportCertificate); + + const signedPdf = await signPdf(pdfRaw, certificateOneTime, passportChain, privateKeyOneTime); + + //for test + response.data.signedPdf = signedPdf; + //for test + + // 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, "PDF signed"); + }, documentCreateDocument: async (path, passportUUID, contenttype) => { const authenticationPublicKey = localStorage.getItem("authenticatedIdentity"); if ( @@ -1325,6 +1377,8 @@ connection.promise.then(parent => { localStorage.getItem("token") === null || localStorage.getItem("authenticatedIdentity") === null ) { + const event = createEvent("", "NotAuthenticated"); + parent.onEvent(event); localStorage.removeItem("uuid"); localStorage.removeItem("token"); localStorage.removeItem("authenticatedIdentity"); @@ -1426,86 +1480,23 @@ connection.promise.then(parent => { } }, 50); - setInterval(async () => { - if (window.currentlyLoadedIdentity && !anynomousDeviceKeyEventsProcessing && !window.currentlyAuthenticatedIdentity) { - anynomousDeviceKeyEventsProcessing = true; - try { - const executeResult = await executeRestfulFunction("public", viamAnonymousApi, viamAnonymousApi.eventGetNewEventsWithoutSession, null, "devicekey"); - if(executeResult.code === "200") { - const eventsLen = executeResult.data.length; - let changedMaxDeviceKeyAnonymousEventTime = false; - for (let i = 0; i < eventsLen; i++) { - const event = executeResult.data[i]; - switch (event.type) { - case "Authenticated" : { - const uuid = event.payloads[0]; - const token = event.payloads[1]; - handleIdentityLogin(window.currentlyLoadedIdentity, uuid, token); - const identityToStore = window.currentlyAuthenticatedIdentity; - event.payloads = [{fromQRCode: true}]; - await setIdentityInLocalStorage(identityToStore); - await getProfileData(identityToStore); - parent.onEvent(event); - break; - } - - case "QRCodeUpdated" : { - const actionID = event["actionID"]; - const QrCode = event["payloads"][1]; - - const eventCopy = JSON.parse(JSON.stringify(event)); - - QRCode.toDataURL(actionID + "," + QrCode, function (err, url) { - eventCopy["payloads"].push(url); - parent.onEvent(eventCopy); - }); - break; - } - - case "KeyDeleted" : { - const authenticationPublicKey = localStorage.getItem("authenticatedIdentity"); - clearPinCodeTtl(authenticationPublicKey); - localStorage.removeItem("uuid"); - localStorage.removeItem("token"); - localStorage.removeItem("authenticatedIdentity"); - delete window.loadedIdentities[authenticationPublicKey]; - window.currentlyLoadedIdentity = null; - window.currentlyAuthenticatedIdentity = null; - window.lastTimeGetProfile = 0; - - destroyIdentityFromLocalStorage(authenticationPublicKey); - break; - } - - default : { - parent.onEvent(event); - } + const getNewEventsWithoutSession = async () => { + anynomousDeviceKeyEventsProcessing = true; + try { + const executeResult = await executeRestfulFunction("public", viamAnonymousApi, viamAnonymousApi.eventGetNewEventsWithoutSession, null, "devicekey"); + if(executeResult.code === "200") { + const eventsLen = executeResult.data.length; + let changedMaxDeviceKeyAnonymousEventTime = false; + for (let i = 0; i < eventsLen; i++) { + const event = executeResult.data[i]; + switch (event.type) { + case "DeviceConfirmed" : { + await setIdentityInLocalStorage(window.currentlyLoadedIdentity); + parent.onEvent(event); + break; } - changedMaxDeviceKeyAnonymousEventTime = true; - maxDeviceKeyAnonymousEventTime = Math.max(maxDeviceKeyAnonymousEventTime, event.stamp); - } - - if(changedMaxDeviceKeyAnonymousEventTime) { - await executeRestfulFunction("public", viamAnonymousApi, viamAnonymousApi.eventUpdateLastViewedWithoutSession, - null, "devicekey", maxDeviceKeyAnonymousEventTime.toString()); - } - } - } catch (e) { - console.warn(e); - } - anynomousDeviceKeyEventsProcessing = false; - } - if (window.currentlyAuthenticatedIdentity != null && eventsDeviceEventsProcessing === false) { - eventsDeviceEventsProcessing = true; - try { - const executeResult = await executeRestfulFunction("private", viamApi, viamApi.eventGetNewEvents, null, "devicekey"); - if (executeResult.code === "200") { - const eventsLen = executeResult.data.length; - const changedMaxDeviceKeyEventTime = false; - for (let i = 0; i < eventsLen; i++) { - const event = executeResult.data[i]; - if (event.type === "QRCodeUpdated") { + case "QRCodeUpdated" : { const actionID = event["actionID"]; const QrCode = event["payloads"][1]; @@ -1515,59 +1506,126 @@ connection.promise.then(parent => { eventCopy["payloads"].push(url); parent.onEvent(eventCopy); }); - } else { + break; + } + + case "KeyDeleted" : { + const authenticationPublicKey = localStorage.getItem("authenticatedIdentity"); + clearPinCodeTtl(authenticationPublicKey); + localStorage.removeItem("uuid"); + localStorage.removeItem("token"); + localStorage.removeItem("authenticatedIdentity"); + delete window.loadedIdentities[authenticationPublicKey]; + window.currentlyLoadedIdentity = null; + window.currentlyAuthenticatedIdentity = null; + window.lastTimeGetProfile = 0; + + destroyIdentityFromLocalStorage(authenticationPublicKey); + break; + } + + default : { parent.onEvent(event); } - maxDeviceKeyEventTime = Math.max(maxDeviceKeyEventTime, event.stamp); } - if(changedMaxDeviceKeyEventTime) { - await executeRestfulFunction("private", viamApi, viamApi.eventUpdateLastViewed, null, "devicekey", - maxDeviceKeyEventTime.toString()); + changedMaxDeviceKeyAnonymousEventTime = true; + maxDeviceKeyAnonymousEventTime = Math.max(maxDeviceKeyAnonymousEventTime, event.stamp); + } + + if(changedMaxDeviceKeyAnonymousEventTime) { + await executeRestfulFunction("public", viamAnonymousApi, viamAnonymousApi.eventUpdateLastViewedWithoutSession, + null, "devicekey", maxDeviceKeyAnonymousEventTime.toString()); + } + } + } catch (e) { + console.warn(e); + } + anynomousDeviceKeyEventsProcessing = false; + }; + + const getNewDeviceEvents = async () => { + eventsDeviceEventsProcessing = true; + try { + const executeResult = await executeRestfulFunction("private", viamApi, viamApi.eventGetNewEvents, null, "devicekey"); + if (executeResult.code === "200") { + const eventsLen = executeResult.data.length; + const changedMaxDeviceKeyEventTime = false; + for (let i = 0; i < eventsLen; i++) { + const event = executeResult.data[i]; + if (event.type === "QRCodeUpdated") { + const actionID = event["actionID"]; + const QrCode = event["payloads"][1]; + + const eventCopy = JSON.parse(JSON.stringify(event)); + + QRCode.toDataURL(actionID + "," + QrCode, function (err, url) { + eventCopy["payloads"].push(url); + parent.onEvent(eventCopy); + }); + } else { + parent.onEvent(event); } + maxDeviceKeyEventTime = Math.max(maxDeviceKeyEventTime, event.stamp); + } + if(changedMaxDeviceKeyEventTime) { + await executeRestfulFunction("private", viamApi, viamApi.eventUpdateLastViewed, null, "devicekey", + maxDeviceKeyEventTime.toString()); } - } catch (e) { - console.warn(e); } - eventsDeviceEventsProcessing = false; + } catch (e) { + console.warn(e); } + eventsDeviceEventsProcessing = false; + }; - if (window.currentlyAuthenticatedIdentity != null && eventsEntityEventsProcessing === false) { - eventsEntityEventsProcessing = true; - try { - const executeResult = await executeRestfulFunction("private", viamApi, viamApi.eventGetNewEvents, null, "entity"); - - if (executeResult.code === "200") { - const eventsLen = executeResult.data.length; - let changedMaxEntityEventTime = false; - for (let i = 0; i < eventsLen; i++) { - const event = executeResult.data[i]; - if (event.type === "QRCodeUpdated") { - const actionID = event["actionID"]; - const QrCode = event["payloads"][1]; + const getNewEntityEvents = async () => { + eventsEntityEventsProcessing = true; + try { + const executeResult = await executeRestfulFunction("private", viamApi, viamApi.eventGetNewEvents, null, "entity"); - const eventCopy = JSON.parse(JSON.stringify(event)); + if (executeResult.code === "200") { + const eventsLen = executeResult.data.length; + let changedMaxEntityEventTime = false; + for (let i = 0; i < eventsLen; i++) { + const event = executeResult.data[i]; + if (event.type === "QRCodeUpdated") { + const actionID = event["actionID"]; + const QrCode = event["payloads"][1]; - QRCode.toDataURL(actionID + "," + QrCode, function (err, url) { - eventCopy["payloads"].push(url); - parent.onEvent(eventCopy); - }); + const eventCopy = JSON.parse(JSON.stringify(event)); - continue; - } + QRCode.toDataURL(actionID + "," + QrCode, function (err, url) { + eventCopy["payloads"].push(url); + parent.onEvent(eventCopy); + }); - parent.onEvent(event); - changedMaxEntityEventTime = true; - maxEntityEventTime = Math.max(maxEntityEventTime, event.stamp); - } - if(changedMaxEntityEventTime) { - await executeRestfulFunction("private", viamApi, viamApi.eventUpdateLastViewed, null, "entity", - maxEntityEventTime.toString()); + continue; } + + parent.onEvent(event); + changedMaxEntityEventTime = true; + maxEntityEventTime = Math.max(maxEntityEventTime, event.stamp); + } + if(changedMaxEntityEventTime) { + await executeRestfulFunction("private", viamApi, viamApi.eventUpdateLastViewed, null, "entity", + maxEntityEventTime.toString()); } - } catch (e) { - console.warn(e); } - eventsEntityEventsProcessing = false; + } catch (e) { + console.warn(e); + } + eventsEntityEventsProcessing = false; + } + + setInterval(() => { + if (window.currentlyLoadedIdentity && !anynomousDeviceKeyEventsProcessing && !window.currentlyAuthenticatedIdentity) { + getNewEventsWithoutSession(); + } + + if (window.currentlyAuthenticatedIdentity) { + // These functions has to be executed at the same time. + !eventsDeviceEventsProcessing && getNewDeviceEvents(); + !eventsEntityEventsProcessing && getNewEntityEvents(); } }, 1000); });