Newer
Older
import { parseSMIME } from '../utilities/emailUtilities';
const QRCode = require('qrcode');
const Penpal = require('penpal').default;
Markin Igor
committed
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 {
signPdf
} from '../utilities/pdfUtilities';
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');
var identityColors = ["#994392", "#cb0767", "#e51d31", "#ec671b", "#fab610"];
function getNextColor() {
var colorIndex = localStorage.getItem("colorIndex");
return color
}
function setKeyForUUID(uuid, key) {
var storedIdentityForUuid = localStorage.getItem("keyperuuid/" + uuid);
if(storedIdentityForUuid !== key && storedIdentityForUuid != null && storedIdentityForUuid !== "") {
destroyIdentityFromLocalStorage(storedIdentityForUuid)
}
localStorage.setItem("keyperuuid/" + uuid, key)
}
function getColorForIdentity(key) {
var storedColor = localStorage.getItem("colors/" + key);
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;
return null;
}
return encryptMessage(serializedIdentity, pinCode, "identity").then((encryptedIdentity) => {
if(extendKey === true) {
success = extendPinCodeTtl(key, pinCode)
}
localStorage.setItem(key, encryptedIdentity);
let serializedIdentitiesList = localStorage.getItem("identities");
let identities = JSON.parse(serializedIdentitiesList);
identities[key] = true;
localStorage.setItem("identities", JSON.stringify(identities))
} else {
}
});
}
function getProfileData(identity) {
return new Penpal.Promise(executeResultUpper => {
executeRestfulFunction("private", viamApi,
viamApi.identityGetIdentityProfileData, null).then(executeResult => {
listItem.identityColor = getColorForIdentity(identity.authentication.publicKey);
listItem.initials = executeResult.data.initials;
if(listItem.initials === null || listItem.initials === "") {
listItem.initials = "JD";
}
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);
if (!encryptedIdentity) {
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;
}
}
return identity;
}
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)) {
return false
} else {
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;
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);
return null
} else {
if(nowMillis >= parseInt(ttl)) {
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 = () => {
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
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);
}
};
window.wopiAPI = new WopiAPI();
window.collaboraApi = new CollaboraAPI();
window.viamApi = new ViamAPI();
window.viamAnonymousApi = new ViamAPI();
window.currentlyAuthenticatedIdentity = null;
window.currentlyLoadedIdentity = null;
window.lastTimeGetProfile = 0;
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);

Alexey Lunin
committed
async function executeRestfulFunction(type, that, fn, config, ...args) {
const { currentlyAuthenticatedIdentity, viamApi, currentlyLoadedIdentity } = window;
let response;
try {
response = await fn.apply(that, [config, ...args]);
} catch (error) {
if (error.response) {
//Resposnse with status code != 2xx still has valid response
response = error.response;
} else {
//Connection error or similar
const data = {
"data": "",
"code": "999",
"status": error.message
};
return data;
}
}
const identity = currentlyAuthenticatedIdentity || currentlyLoadedIdentity;

Alexey Lunin
committed
const { code, status } = response.data;

Alexey Lunin
committed
const deviceRevoked = type === "private" && code === "401" && status === STATUS_DEVICE_REVOKED;
if (deviceRevoked) {
destroyIdentity();

Alexey Lunin
committed
const event = createEvent("", "DeviceRevoked");
iframeParent.onEvent(event);

Alexey Lunin
committed
return response.data;
}

Alexey Lunin
committed
const badSession = type === "private" && identity && code === "400" && status === "Bad session";
if (!badSession) return response.data;
const loginResponse = await viamApi.identityLogin(null, "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);
try {
response = await fn.apply(that, [config, ...args]);
} catch (error) {
response = error.response;
}
return 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",
"status": "Please restore or authorize your account via another device."
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);
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",
});
}
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;
var passport = passportIdentity.getPassport(passportUUID);
if(passport === undefined || passport === null) {
createPassportCertificate(passportUUID).then(function(keys){
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 => {
var signedCertificate = atob(executeResult.data["SignedCertificate"]);
//download("passportCertificateAfterSigning.crt", "text/plain", signedCertificate)
var keyUUID = executeResult.data["CertificateUUID"];
var encodedChain = executeResult.data["Chain"];
//download("rootCertificate.crt", "text/plain", atob(encodedChain[0]))
for(var i = 0; i < encodedChain.length; i++) {
chain.push(atob(encodedChain[i]))
}
cryptoData.setx509Certificate(signedCertificate);
cryptoData.setKeyUUID(keyUUID);
cryptoData.setChain(chain);
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));
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);
var copyOfCryptoData = JSON.parse(JSON.stringify(passport));
if(internal === false) {
copyOfCryptoData["privateKey"] = ""
}
certificateResult({"data" : copyOfCryptoData,
"code" : "200",
"status" : "Certificate got"
});
}
});
}
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
function stringToUtf8ByteArray(str) {
if (typeof str !== 'string') {
str = str.toString();
}
const res = Buffer.from(str, 'utf-8');
return res;
}
function utf8ByteArrayToString(ba) {
if (!Buffer.isBuffer(ba)) {
ba = Buffer.from(ba);
}
const res = ba.toString('utf-8');
return res;
}
function stringToUtf8Base64(str) {
if (!Buffer.isBuffer(str)) {
if (typeof str !== 'string') {
str = str.toString();
}
str = Buffer.from(str, 'utf-8');
}
const res = str.toString('base64');
return res;
}
function utf8Base64ToString(strBase64) {
if (!Buffer.isBuffer(strBase64)) {
if (typeof strBase64 !== 'string') {
strBase64 = strBase64.toString();
}
strBase64 = Buffer.from(strBase64, 'base64');
}
const res = strBase64.toString('utf-8');
return res;
}
function base64ToByteArray(strBase64) {
if (typeof strBase64 !== 'string') {
strBase64 = strBase64.toString();
}
const res = Buffer.from(strBase64, 'base64');
return res;
}
function byteArrayToBase64(ba) {
if (!Buffer.isBuffer(ba)) {
ba = Buffer.from(ba);
}
const res = ba.toString('base64');
return res;
}
const connection = Penpal.connectToParent({
// Methods child is exposing to parent
methods: {
initialize: (apiUrl, wopiUrl, collaboraUrl) => {
Alexey Lunin
committed
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 + "/";
...penpalMethods,
createIdentity(pinCode) {
return new Penpal.Promise(result => {
createPassportCertificate(makeid()).then(function(keys){
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;
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 => {
result({"data" : identities,
"code" : "200",
"status" : "Identities listed"
})
});
},
loadIdentity(identityKey, pinCode) {
return loadIdentityInternal(identityKey, pinCode)
},
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 => {
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: async () => {
destroyAuthentication();
const identitiesTemp = listIdentitiesFromLocalStorage();
for (const i in identitiesTemp) {
destroyIdentityFromLocalStorage(i);
}
return encodeResponse("200", "", "Identities cleared");
confirmIdentificator(identity, confirmationCodeArg) {
return new Penpal.Promise(result => {
viamApi.setIdentity(identity.authentication.publicKey);
executeRestfulFunction("public", viamApi, viamApi.identityConfirmIdentificator, null, confirmationCodeArg).then(executeResult => {
result(executeResult);
});
});
},
identityGetIdentificatorByRegisterToken(identity, tokenArg) {
return new Penpal.Promise(result => {
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 => {
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 => {
viamApi.setIdentity(identity.authentication.publicKey);
executeRestfulFunction("public", viamApi, viamApi.identitySubmitRegisterClaims, null, givennameArg,familynameArg,emailArg,phonenumberArg).then(executeResult => {
result(executeResult);
});
});
},
agreeOnRegistration(registerIdentity) {
viamApi.setIdentity(registerIdentity.authentication.publicKey);
executeRestfulFunction("public", viamApi, viamApi.identityAgreeOnRegistration, null).then(executeResult => {
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 => {
viamApi.setIdentity(identity.authentication.publicKey);
executeRestfulFunction("public", viamApi, viamApi.identityResendConfirmationCode, null, identificatorArg).then(executeResult => {
result(executeResult);
});
});
},
login: async (loginIdentity, mode, requestCode, requestActionID) => {
if (!window.loadedIdentities[loginIdentity.authentication.publicKey]) {
return {
data: "",
code: "400",
status: "Identity not loaded"
};
}
const deviceHash = await createDeviceHash(loginIdentity.authentication.publicKey);
window.viamApi.setSessionData("", "");
window.viamApi.setIdentity(loginIdentity.authentication.publicKey);
const identityLoginResponse =
await executeRestfulFunction(
"public",
window.viamApi,
window.viamApi.identityLogin,
null,
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) {
handleIdentityLogin(loginIdentity, data.Uuid, data.Session);
if (mode === LOGIN_MODES.SMS) {
} 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"
})
}
var success = extendPinCodeTtl(authenticationPublicKey);
result({"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
})
}
executeRestfulFunction("private", viamApi, viamApi.identityAddNewDevice, null).then(executeResult => {
var actionID = executeResult.data["ActionID"];
var QrCode = executeResult.data["QrCode"];
QRCode.toDataURL(actionID + "," + QrCode, function (err, 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"
})
}
var success = extendPinCodeTtl(authenticationPublicKey);
result({"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
})
}
executeRestfulFunction("private", viamApi, viamApi.identityDestroyKeysForDevice, null, btoa(authenticationPublicKeyArg)).then(executeResult => {
result(executeResult);
});
});
},
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();
"private",
window.viamApi,
window.viamApi.identityLogout,
}
},
identityRestoreAccess(restoreAccessIdentity, identificator) {
return new Penpal.Promise(result => {
viamApi.setSessionData("", "");
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"
}
}
var success = extendPinCodeTtl(authenticationPublicKey);
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"
}
}
var success = extendPinCodeTtl(authenticationPublicKey);
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"
}
}
var success = extendPinCodeTtl(authenticationPublicKey);
result({"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
})
}
getCertificateForPassport(passportUUID, true).then(certificateResult => {
var passportCertificate = certificateResult.data["x509Certificate"];
var passportPrivateKey = certificateResult.data["privateKey"];
var passportChain = certificateResult.data["chain"];
createOneTimePassportCertificate(makeid() + "-" + passportUUID, emailArg, passportPrivateKey, passportCertificate).then(function(keys){
var publicKeyOneTime = keys["publicKeyPEM"];
var privateKeyOneTime = keys["privateKeyPEM"];
var certificateOneTime = keys["certificatePEM"];
passportChain.push(passportCertificate);
var oneTimeCryptoData = new CryptoData();
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");
signDocument: async (passportUUID, documentUUID, documentContentType) => {
const authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
if (
!authenticationPublicKey ||
!window.loadedIdentities[authenticationPublicKey] ||
!extendPinCodeTtl(authenticationPublicKey)
) {
return encodeResponse("400", "", "Identity not authenticated");
}
const certResponse = await getCertificateForPassport(passportUUID, true);
if (certResponse.code !== "200") {
return encodeResponse("400", "", certResponse.status);
}
const {
x509Certificate: passportCertificate,
privateKey: passportPrivateKey,
chain: passportChain
const keys =
await createOneTimePassportCertificate(
makeid() + "-" + passportUUID, null, passportPrivateKey, passportCertificate);
const { privateKeyPEM: privateKeyOneTime, certificatePEM: certificateOneTime } = keys;
passportChain.push(passportCertificate);
const pdfContentType = 'application/pdf';
if (documentContentType !== pdfContentType) {
const convResponse = await executeRestfulFunction(
"private", window.viamApi, window.viamApi.documentConvertDocumentByUUID, null, documentUUID, documentContentType, pdfContentType);
if (convResponse.code !== "200") {
return encodeResponse("400", "", convResponse.status);
}
}
const downloadResponse = await executeRestfulFunction(
"private", window.viamApi, window.viamApi.documentGetDocumentByUUID, null, documentUUID, pdfContentType);
if (downloadResponse.code !== "200") {
return encodeResponse("400", "", downloadResponse.status);
}
const pdfRaw = base64ToByteArray(downloadResponse.data);
const signedPdf = await signPdf(pdfRaw, certificateOneTime, passportChain, privateKeyOneTime);
const signedPdfB64 = byteArrayToBase64(signedPdf);
const uploadResponse = await executeRestfulFunction(
"private", window.viamApi, window.viamApi.documentPutDocumentByUUID, null, documentUUID, pdfContentType, signedPdfB64);
if (uploadResponse.code !== "200") {
return encodeResponse("400", "", uploadResponse.status);
}
const signResponse = await executeRestfulFunction(
"private", window.viamApi, window.viamApi.documentSignDocumentByUUID, null, passportUUID, documentUUID, pdfContentType);
if (signResponse.code !== "200") {
return encodeResponse("400", "", signResponse.status);
}
return encodeResponse("200", "", "Document 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"
});
}
var success = extendPinCodeTtl(authenticationPublicKey);
result({"data" : "",
"code" : "400",
"status" : "Identity not authenticated"
})
}
executeRestfulFunction("private", viamApi, viamApi.identityHasSession, null).then(executeResult => {
result(executeResult);
});
});
},
marketingSignUpIdentificator(identificator, reference) {
return new Penpal.Promise(result => {
executeRestfulFunction("public", viamApi, viamApi.marketingSignUpIdentificator, null, identificator, reference).then(executeResult => {
result(executeResult);
});
});
},
marketingGetIdentificatorProfile(identificator, pincode) {
return new Penpal.Promise(result => {
executeRestfulFunction("public", viamApi, viamApi.marketingGetIdentificatorProfile, null, identificator, pincode).then(executeResult => {
result(executeResult);
});
});
},
marketingExecuteEventForIdentificator(identificator, pincode, event) {
executeRestfulFunction("public", viamApi, viamApi.marketingExecuteEventForIdentificator, null, identificator, pincode, event).then(executeResult => {
result(executeResult);
});
});
},
getCurrentlyAuthenticatedIdentity() {
const { publicKey, x509Certificate } = window.currentlyAuthenticatedIdentity.authentication;
return encodeResponse(
"200",
{
authentication: {
publicKey,
x509Certificate
}
},
"Currently authenticated identity"
);
stringToUtf8ByteArray(str) {
return new Penpal.Promise(result => {
result(stringToUtf8ByteArray(str));
});
},
utf8ByteArrayToString(ba) {
return new Penpal.Promise(result => {
result(utf8ByteArrayToString(ba));
});
},
stringToUtf8Base64(str) {
return new Penpal.Promise(result => {
result(stringToUtf8Base64(str));
});
},
utf8Base64ToString(strBase64) {
return new Penpal.Promise(result => {
result(utf8Base64ToString(strBase64));
});
},
base64ToByteArray(strBase64) {
return new Penpal.Promise(result => {
result(base64ToByteArray(strBase64));
});
},
byteArrayToBase64(ba) {
return new Penpal.Promise(result => {
result(byteArrayToBase64(ba));
});
return collaboraApi.discovery().then(apps => apps);
getPassports: async (resourceID, contentType) => {
const authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
if (
!authenticationPublicKey ||
!window.loadedIdentities[authenticationPublicKey] ||
!extendPinCodeTtl(authenticationPublicKey)
) {
return encodeResponse("400", "", "Identity not authenticated");
}
const response = await wopiAPI.getPassports(resourceID, contentType);
wopiPutFile: async (path, accessToken, file) => {
const authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
if (
!authenticationPublicKey ||
!window.loadedIdentities[authenticationPublicKey] ||
!extendPinCodeTtl(authenticationPublicKey)
) {
return encodeResponse("400", "", "Identity not authenticated");
}
const response = await wopiAPI.putDocument(path, accessToken, file);
connection.promise.then(parent => {
if (!navigator.cookieEnabled) {
console.warn("Cookie disabled. Can't start library.");
return;
}
window.addEventListener('storage', event => {
if (event.key === "authenticatedIdentity" && event.newValue === null) {
const publicKey = window.currentlyAuthenticatedIdentity.authentication.publicKey;
window.currentlyLoadedIdentity = null;
window.currentlyAuthenticatedIdentity = null;
const event = createEvent("LogoutFromAnotherTab", "Logout", [publicKey]);
parent.onEvent(event);
}
});
const identities = localStorage.getItem("identities");
console.log("Library loaded at: " + new Date().toISOString());
if (identities === "" || identities === null) {
localStorage.setItem("identities", JSON.stringify({}));
if (
localStorage.getItem("uuid") === null ||
localStorage.getItem("token") === null ||
localStorage.getItem("authenticatedIdentity") === null
) {
const event = createEvent("", "NotAuthenticated");
parent.onEvent(event);
localStorage.removeItem("uuid");
localStorage.removeItem("token");
const authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
const pinCode = getPincode(authenticationPublicKey);
loadIdentityInternal(authenticationPublicKey, "00000000").then(result => {
if (result.code !== "200") {
const event = createEvent(
"CanNotGetPincodeForAuthenticatedIdentity",
"IdentityNotLoaded",
loadIdentityInternal(authenticationPublicKey, pinCode).then(result => {
if (result.code !== "200") {
const event = createEvent(
"CanNotLoadIdentity",
"ErrorDuringLoadingIdentity",
let anynomousDeviceKeyEventsProcessing = false;
let maxDeviceKeyAnonymousEventTime = 0;
let eventsDeviceEventsProcessing = false;
let maxDeviceKeyEventTime = 0;
let eventsEntityEventsProcessing = false;
let maxEntityEventTime = 0;
let identityLoadedEvent = false;
let identityAuthenticatedEvent = false;
let previousLocalStorageUUID;
let previousLocalStorageToken;
let previousLocalStorageIdentity;
setInterval(async function () {
if (window.currentlyAuthenticatedIdentity) {
const { authentication } = window.currentlyAuthenticatedIdentity;
const pinCode = getPincode(authentication.publicKey);
if (pinCode) {
const identity = await getIdentityFromLocalStorage(authentication.publicKey, pinCode, false);
window.currentlyLoadedIdentity = identity;
if (!identityAuthenticatedEvent && identity) {
const event = createEvent("IdentityAuthenticated", "Authenticated", [identity.authentication.publicKey]);
parent.onEvent(event);
identityAuthenticatedEvent = true;
}
const authenticationPublicKey = localStorage.getItem("authenticatedIdentity");
if (authenticationPublicKey) {
const result = await loadIdentityInternal(authenticationPublicKey, "00000000");
if (result.code !== "200") {
const event = createEvent("CanNotGetPincodeForAuthenticatedIdentity", "IdentityNotLoaded", [authenticationPublicKey]);
parent.onEvent(event);
clearPinCodeTtl(authenticationPublicKey);
window.currentlyAuthenticatedIdentity = null;
}
if (window.currentlyLoadedIdentity) {
const pinCode = getPincode(window.currentlyLoadedIdentity.authentication.publicKey);
if (!pinCode) {
if (!identityLoadedEvent) {
const result = await loadIdentityInternal(window.currentlyLoadedIdentity.authentication.publicKey, "00000000");

Alexey Lunin
committed
if (window.currentlyLoadedIdentity && result.code !== "200") {
const event = createEvent("CanNotLoadPincodeForLoadedIdentity", "IdentityNotLoaded", [window.currentlyLoadedIdentity.authentication.publicKey]);
parent.onEvent(event);
identityLoadedEvent = true;
}
if (window.currentlyAuthenticatedIdentity) {
const now = new Date().getTime();
if (now - window.lastTimeGetProfile > 30000) {
getProfileData(window.currentlyAuthenticatedIdentity);
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
const currentLocalStorageUUID = localStorage.getItem("uuid");
const currentLocalStorageToken = localStorage.getItem("token");
const currentLocalStorageIdentity = localStorage.getItem("authenticatedIdentity");
if (
!currentLocalStorageUUID && previousLocalStorageUUID ||
!currentLocalStorageToken && previousLocalStorageToken ||
!currentLocalStorageIdentity && previousLocalStorageIdentity
) {
previousLocalStorageUUID = null;
previousLocalStorageToken = null;
previousLocalStorageIdentity = null;
destroyAuthentication();
const event = createEvent("", "LogoutExternal");
parent.onEvent(event);
} else {
previousLocalStorageUUID = currentLocalStorageUUID;
previousLocalStorageToken = currentLocalStorageToken;
previousLocalStorageIdentity = currentLocalStorageIdentity;
}
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;
const actionID = event["actionID"];
const QrCode = event["payloads"][1];
const eventCopy = JSON.parse(JSON.stringify(event));
QRCode.toDataURL(actionID + "," + QrCode, function (err, 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);
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
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;
};
const getNewEntityEvents = async () => {
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 eventCopy = JSON.parse(JSON.stringify(event));
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());
} 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();