move required stdop files to docs/scripts/
This commit is contained in:
parent
85de9d4b96
commit
fd6e09b157
21
LICENCE
21
LICENCE
@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2023 Sai Raj
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
257
compactIDB.js
257
compactIDB.js
@ -1,257 +0,0 @@
|
|||||||
(function (EXPORTS) { //compactIDB v2.1.2
|
|
||||||
/* Compact IndexedDB operations */
|
|
||||||
'use strict';
|
|
||||||
const compactIDB = EXPORTS;
|
|
||||||
|
|
||||||
var defaultDB;
|
|
||||||
|
|
||||||
const indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
|
|
||||||
const IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
|
|
||||||
const IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
|
|
||||||
|
|
||||||
if (!indexedDB) {
|
|
||||||
console.error("Your browser doesn't support a stable version of IndexedDB.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
compactIDB.setDefaultDB = dbName => defaultDB = dbName;
|
|
||||||
|
|
||||||
Object.defineProperty(compactIDB, 'default', {
|
|
||||||
get: () => defaultDB,
|
|
||||||
set: dbName => defaultDB = dbName
|
|
||||||
});
|
|
||||||
|
|
||||||
function getDBversion(dbName = defaultDB) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
openDB(dbName).then(db => {
|
|
||||||
resolve(db.version)
|
|
||||||
db.close()
|
|
||||||
}).catch(error => reject(error))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function upgradeDB(dbName, createList = null, deleteList = null) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
getDBversion(dbName).then(version => {
|
|
||||||
var idb = indexedDB.open(dbName, version + 1);
|
|
||||||
idb.onerror = (event) => reject("Error in opening IndexedDB");
|
|
||||||
idb.onupgradeneeded = (event) => {
|
|
||||||
let db = event.target.result;
|
|
||||||
if (createList instanceof Object) {
|
|
||||||
if (Array.isArray(createList)) {
|
|
||||||
let tmp = {}
|
|
||||||
createList.forEach(o => tmp[o] = {})
|
|
||||||
createList = tmp
|
|
||||||
}
|
|
||||||
for (let o in createList) {
|
|
||||||
let obs = db.createObjectStore(o, createList[o].options || {});
|
|
||||||
if (createList[o].indexes instanceof Object)
|
|
||||||
for (let i in createList[o].indexes)
|
|
||||||
obs.createIndex(i, i, createList[o].indexes || {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Array.isArray(deleteList))
|
|
||||||
deleteList.forEach(o => db.deleteObjectStore(o));
|
|
||||||
resolve('Database upgraded')
|
|
||||||
}
|
|
||||||
idb.onsuccess = (event) => event.target.result.close();
|
|
||||||
}).catch(error => reject(error))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
compactIDB.initDB = function (dbName, objectStores = {}) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
if (!(objectStores instanceof Object))
|
|
||||||
return reject('ObjectStores must be an object or array')
|
|
||||||
defaultDB = defaultDB || dbName;
|
|
||||||
var idb = indexedDB.open(dbName);
|
|
||||||
idb.onerror = (event) => reject("Error in opening IndexedDB");
|
|
||||||
idb.onsuccess = (event) => {
|
|
||||||
var db = event.target.result;
|
|
||||||
let cList = Object.values(db.objectStoreNames);
|
|
||||||
var obs = {},
|
|
||||||
a_obs = {},
|
|
||||||
d_obs = [];
|
|
||||||
if (!Array.isArray(objectStores))
|
|
||||||
var obs = objectStores
|
|
||||||
else
|
|
||||||
objectStores.forEach(o => obs[o] = {})
|
|
||||||
let nList = Object.keys(obs)
|
|
||||||
for (let o of nList)
|
|
||||||
if (!cList.includes(o))
|
|
||||||
a_obs[o] = obs[o]
|
|
||||||
for (let o of cList)
|
|
||||||
if (!nList.includes(o))
|
|
||||||
d_obs.push(o)
|
|
||||||
if (!Object.keys(a_obs).length && !d_obs.length)
|
|
||||||
resolve("Initiated IndexedDB");
|
|
||||||
else
|
|
||||||
upgradeDB(dbName, a_obs, d_obs)
|
|
||||||
.then(result => resolve(result))
|
|
||||||
.catch(error => reject(error))
|
|
||||||
db.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const openDB = compactIDB.openDB = function (dbName = defaultDB) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
var idb = indexedDB.open(dbName);
|
|
||||||
idb.onerror = (event) => reject("Error in opening IndexedDB");
|
|
||||||
idb.onupgradeneeded = (event) => {
|
|
||||||
event.target.result.close();
|
|
||||||
deleteDB(dbName).then(_ => null).catch(_ => null).finally(_ => reject("Datebase not found"))
|
|
||||||
}
|
|
||||||
idb.onsuccess = (event) => resolve(event.target.result);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const deleteDB = compactIDB.deleteDB = function (dbName = defaultDB) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
var deleteReq = indexedDB.deleteDatabase(dbName);;
|
|
||||||
deleteReq.onerror = (event) => reject("Error deleting database!");
|
|
||||||
deleteReq.onsuccess = (event) => resolve("Database deleted successfully");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
compactIDB.writeData = function (obsName, data, key = false, dbName = defaultDB) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
openDB(dbName).then(db => {
|
|
||||||
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
|
|
||||||
let writeReq = (key ? obs.put(data, key) : obs.put(data));
|
|
||||||
writeReq.onsuccess = (evt) => resolve(`Write data Successful`);
|
|
||||||
writeReq.onerror = (evt) => reject(
|
|
||||||
`Write data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
|
|
||||||
);
|
|
||||||
db.close();
|
|
||||||
}).catch(error => reject(error));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
compactIDB.addData = function (obsName, data, key = false, dbName = defaultDB) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
openDB(dbName).then(db => {
|
|
||||||
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
|
|
||||||
let addReq = (key ? obs.add(data, key) : obs.add(data));
|
|
||||||
addReq.onsuccess = (evt) => resolve(`Add data successful`);
|
|
||||||
addReq.onerror = (evt) => reject(
|
|
||||||
`Add data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
|
|
||||||
);
|
|
||||||
db.close();
|
|
||||||
}).catch(error => reject(error));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
compactIDB.removeData = function (obsName, key, dbName = defaultDB) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
openDB(dbName).then(db => {
|
|
||||||
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
|
|
||||||
let delReq = obs.delete(key);
|
|
||||||
delReq.onsuccess = (evt) => resolve(`Removed Data ${key}`);
|
|
||||||
delReq.onerror = (evt) => reject(
|
|
||||||
`Remove data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
|
|
||||||
);
|
|
||||||
db.close();
|
|
||||||
}).catch(error => reject(error));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
compactIDB.clearData = function (obsName, dbName = defaultDB) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
openDB(dbName).then(db => {
|
|
||||||
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
|
|
||||||
let clearReq = obs.clear();
|
|
||||||
clearReq.onsuccess = (evt) => resolve(`Clear data Successful`);
|
|
||||||
clearReq.onerror = (evt) => reject(`Clear data Unsuccessful`);
|
|
||||||
db.close();
|
|
||||||
}).catch(error => reject(error));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
compactIDB.readData = function (obsName, key, dbName = defaultDB) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
openDB(dbName).then(db => {
|
|
||||||
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
|
|
||||||
let getReq = obs.get(key);
|
|
||||||
getReq.onsuccess = (evt) => resolve(evt.target.result);
|
|
||||||
getReq.onerror = (evt) => reject(
|
|
||||||
`Read data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
|
|
||||||
);
|
|
||||||
db.close();
|
|
||||||
}).catch(error => reject(error));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
compactIDB.readAllData = function (obsName, dbName = defaultDB) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
openDB(dbName).then(db => {
|
|
||||||
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
|
|
||||||
var tmpResult = {}
|
|
||||||
let curReq = obs.openCursor();
|
|
||||||
curReq.onsuccess = (evt) => {
|
|
||||||
var cursor = evt.target.result;
|
|
||||||
if (cursor) {
|
|
||||||
tmpResult[cursor.primaryKey] = cursor.value;
|
|
||||||
cursor.continue();
|
|
||||||
} else
|
|
||||||
resolve(tmpResult);
|
|
||||||
}
|
|
||||||
curReq.onerror = (evt) => reject(
|
|
||||||
`Read-All data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
|
|
||||||
);
|
|
||||||
db.close();
|
|
||||||
}).catch(error => reject(error));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* compactIDB.searchData = function (obsName, options = {}, dbName = defaultDB) {
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
openDB(dbName).then(db => {
|
|
||||||
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
|
|
||||||
var filteredResult = {}
|
|
||||||
let keyRange;
|
|
||||||
if(options.lowerKey!==null && options.upperKey!==null)
|
|
||||||
keyRange = IDBKeyRange.bound(options.lowerKey, options.upperKey);
|
|
||||||
else if(options.lowerKey!==null)
|
|
||||||
keyRange = IDBKeyRange.lowerBound(options.lowerKey);
|
|
||||||
else if (options.upperKey!==null)
|
|
||||||
keyRange = IDBKeyRange.upperBound(options.upperBound);
|
|
||||||
else if (options.atKey)
|
|
||||||
let curReq = obs.openCursor(keyRange, )
|
|
||||||
}).catch(error => reject(error))
|
|
||||||
})
|
|
||||||
}*/
|
|
||||||
|
|
||||||
compactIDB.searchData = function (obsName, options = {}, dbName = defaultDB) {
|
|
||||||
options.lowerKey = options.atKey || options.lowerKey || 0
|
|
||||||
options.upperKey = options.atKey || options.upperKey || false
|
|
||||||
options.patternEval = options.patternEval || ((k, v) => true);
|
|
||||||
options.limit = options.limit || false;
|
|
||||||
options.reverse = options.reverse || false;
|
|
||||||
options.lastOnly = options.lastOnly || false
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
openDB(dbName).then(db => {
|
|
||||||
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
|
|
||||||
var filteredResult = {}
|
|
||||||
let curReq = obs.openCursor(
|
|
||||||
options.upperKey ? IDBKeyRange.bound(options.lowerKey, options.upperKey) : IDBKeyRange.lowerBound(options.lowerKey),
|
|
||||||
options.lastOnly || options.reverse ? "prev" : "next");
|
|
||||||
curReq.onsuccess = (evt) => {
|
|
||||||
var cursor = evt.target.result;
|
|
||||||
if (!cursor || (options.limit && options.limit <= Object.keys(filteredResult).length))
|
|
||||||
return resolve(filteredResult); //reached end of key list or limit reached
|
|
||||||
else if (options.patternEval(cursor.primaryKey, cursor.value)) {
|
|
||||||
filteredResult[cursor.primaryKey] = cursor.value;
|
|
||||||
options.lastOnly ? resolve(filteredResult) : cursor.continue();
|
|
||||||
} else
|
|
||||||
cursor.continue();
|
|
||||||
}
|
|
||||||
curReq.onerror = (evt) => reject(`Search unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`);
|
|
||||||
db.close();
|
|
||||||
}).catch(error => reject(error));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
})(window.compactIDB = {});
|
|
||||||
1055
floCloudAPI.js
1055
floCloudAPI.js
File diff suppressed because it is too large
Load Diff
845
floDapps.js
845
floDapps.js
@ -1,845 +0,0 @@
|
|||||||
(function (EXPORTS) { //floDapps v2.4.0
|
|
||||||
/* General functions for FLO Dapps*/
|
|
||||||
'use strict';
|
|
||||||
const floDapps = EXPORTS;
|
|
||||||
|
|
||||||
const DEFAULT = {
|
|
||||||
root: "floDapps",
|
|
||||||
application: floGlobals.application,
|
|
||||||
adminID: floGlobals.adminID
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.defineProperties(floDapps, {
|
|
||||||
application: {
|
|
||||||
get: () => DEFAULT.application
|
|
||||||
},
|
|
||||||
adminID: {
|
|
||||||
get: () => DEFAULT.adminID
|
|
||||||
},
|
|
||||||
root: {
|
|
||||||
get: () => DEFAULT.root
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var user_priv_raw, aes_key, user_priv_wrap; //private variable inside capsule
|
|
||||||
const raw_user = {
|
|
||||||
get private() {
|
|
||||||
if (!user_priv_raw)
|
|
||||||
throw "User not logged in";
|
|
||||||
return Crypto.AES.decrypt(user_priv_raw, aes_key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var user_id, user_public, user_private;
|
|
||||||
const user = floDapps.user = {
|
|
||||||
get id() {
|
|
||||||
if (!user_id)
|
|
||||||
throw "User not logged in";
|
|
||||||
return user_id;
|
|
||||||
},
|
|
||||||
get public() {
|
|
||||||
if (!user_public)
|
|
||||||
throw "User not logged in";
|
|
||||||
return user_public;
|
|
||||||
},
|
|
||||||
get private() {
|
|
||||||
if (!user_private)
|
|
||||||
throw "User not logged in";
|
|
||||||
else if (user_private instanceof Function)
|
|
||||||
return user_private();
|
|
||||||
else
|
|
||||||
return Crypto.AES.decrypt(user_private, aes_key);
|
|
||||||
},
|
|
||||||
sign(message) {
|
|
||||||
return floCrypto.signData(message, raw_user.private);
|
|
||||||
},
|
|
||||||
decrypt(data) {
|
|
||||||
return floCrypto.decryptData(data, raw_user.private);
|
|
||||||
},
|
|
||||||
encipher(message) {
|
|
||||||
return Crypto.AES.encrypt(message, raw_user.private);
|
|
||||||
},
|
|
||||||
decipher(data) {
|
|
||||||
return Crypto.AES.decrypt(data, raw_user.private);
|
|
||||||
},
|
|
||||||
get db_name() {
|
|
||||||
return "floDapps#" + floCrypto.toFloID(user.id);
|
|
||||||
},
|
|
||||||
lock() {
|
|
||||||
user_private = user_priv_wrap;
|
|
||||||
},
|
|
||||||
async unlock() {
|
|
||||||
if (await user.private === raw_user.private)
|
|
||||||
user_private = user_priv_raw;
|
|
||||||
},
|
|
||||||
get_contact(id) {
|
|
||||||
if (!user.contacts)
|
|
||||||
throw "Contacts not available";
|
|
||||||
else if (user.contacts[id])
|
|
||||||
return user.contacts[id];
|
|
||||||
else {
|
|
||||||
let id_raw = floCrypto.decodeAddr(id).hex;
|
|
||||||
for (let i in user.contacts)
|
|
||||||
if (floCrypto.decodeAddr(i).hex == id_raw)
|
|
||||||
return user.contacts[i];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
get_pubKey(id) {
|
|
||||||
if (!user.pubKeys)
|
|
||||||
throw "Contacts not available";
|
|
||||||
else if (user.pubKeys[id])
|
|
||||||
return user.pubKeys[id];
|
|
||||||
else {
|
|
||||||
let id_raw = floCrypto.decodeAddr(id).hex;
|
|
||||||
for (let i in user.pubKeys)
|
|
||||||
if (floCrypto.decodeAddr(i).hex == id_raw)
|
|
||||||
return user.pubKeys[i];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
clear() {
|
|
||||||
user_id = user_public = user_private = undefined;
|
|
||||||
user_priv_raw = aes_key = undefined;
|
|
||||||
delete user.contacts;
|
|
||||||
delete user.pubKeys;
|
|
||||||
delete user.messages;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.defineProperties(window, {
|
|
||||||
myFloID: {
|
|
||||||
get: () => {
|
|
||||||
try {
|
|
||||||
return user.id;
|
|
||||||
} catch {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
myUserID: {
|
|
||||||
get: () => {
|
|
||||||
try {
|
|
||||||
return user.id;
|
|
||||||
} catch {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
myPubKey: {
|
|
||||||
get: () => {
|
|
||||||
try {
|
|
||||||
return user.public;
|
|
||||||
} catch {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
myPrivKey: {
|
|
||||||
get: () => {
|
|
||||||
try {
|
|
||||||
return user.private;
|
|
||||||
} catch {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var subAdmins, trustedIDs, settings;
|
|
||||||
Object.defineProperties(floGlobals, {
|
|
||||||
subAdmins: {
|
|
||||||
get: () => subAdmins
|
|
||||||
},
|
|
||||||
trustedIDs: {
|
|
||||||
get: () => trustedIDs
|
|
||||||
},
|
|
||||||
settings: {
|
|
||||||
get: () => settings
|
|
||||||
},
|
|
||||||
contacts: {
|
|
||||||
get: () => user.contacts
|
|
||||||
},
|
|
||||||
pubKeys: {
|
|
||||||
get: () => user.pubKeys
|
|
||||||
},
|
|
||||||
messages: {
|
|
||||||
get: () => user.messages
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
function initIndexedDB() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
var obs_g = {
|
|
||||||
//general
|
|
||||||
lastTx: {},
|
|
||||||
//supernode (cloud list)
|
|
||||||
supernodes: {
|
|
||||||
indexes: {
|
|
||||||
uri: null,
|
|
||||||
pubKey: null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var obs_a = {
|
|
||||||
//login credentials
|
|
||||||
credentials: {},
|
|
||||||
//for Dapps
|
|
||||||
subAdmins: {},
|
|
||||||
trustedIDs: {},
|
|
||||||
settings: {},
|
|
||||||
appObjects: {},
|
|
||||||
generalData: {},
|
|
||||||
lastVC: {}
|
|
||||||
}
|
|
||||||
//add other given objectStores
|
|
||||||
initIndexedDB.appObs = initIndexedDB.appObs || {}
|
|
||||||
for (let o in initIndexedDB.appObs)
|
|
||||||
if (!(o in obs_a))
|
|
||||||
obs_a[o] = initIndexedDB.appObs[o]
|
|
||||||
Promise.all([
|
|
||||||
compactIDB.initDB(DEFAULT.application, obs_a),
|
|
||||||
compactIDB.initDB(DEFAULT.root, obs_g)
|
|
||||||
]).then(result => {
|
|
||||||
compactIDB.setDefaultDB(DEFAULT.application)
|
|
||||||
resolve("IndexedDB App Storage Initated Successfully")
|
|
||||||
}).catch(error => reject(error));
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function initUserDB() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
var obs = {
|
|
||||||
contacts: {},
|
|
||||||
pubKeys: {},
|
|
||||||
messages: {}
|
|
||||||
}
|
|
||||||
compactIDB.initDB(user.db_name, obs).then(result => {
|
|
||||||
resolve("UserDB Initated Successfully")
|
|
||||||
}).catch(error => reject('Init userDB failed'));
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadUserDB() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
var loadData = ["contacts", "pubKeys", "messages"]
|
|
||||||
var promises = []
|
|
||||||
for (var i = 0; i < loadData.length; i++)
|
|
||||||
promises[i] = compactIDB.readAllData(loadData[i], user.db_name)
|
|
||||||
Promise.all(promises).then(results => {
|
|
||||||
for (var i = 0; i < loadData.length; i++)
|
|
||||||
user[loadData[i]] = results[i]
|
|
||||||
resolve("Loaded Data from userDB")
|
|
||||||
}).catch(error => reject('Load userDB failed'))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const startUpOptions = {
|
|
||||||
cloud: true,
|
|
||||||
app_config: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
floDapps.startUpOptions = {
|
|
||||||
set app_config(val) {
|
|
||||||
if (val === true || val === false)
|
|
||||||
startUpOptions.app_config = val;
|
|
||||||
},
|
|
||||||
get app_config() { return startUpOptions.app_config },
|
|
||||||
|
|
||||||
set cloud(val) {
|
|
||||||
if (val === true || val === false)
|
|
||||||
startUpOptions.cloud = val;
|
|
||||||
},
|
|
||||||
get cloud() { return startUpOptions.cloud },
|
|
||||||
}
|
|
||||||
|
|
||||||
const startUpFunctions = [];
|
|
||||||
|
|
||||||
startUpFunctions.push(function readSupernodeListFromAPI() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
if (!startUpOptions.cloud)
|
|
||||||
return resolve("No cloud for this app");
|
|
||||||
compactIDB.readData("lastTx", floCloudAPI.SNStorageID, DEFAULT.root).then(lastTx => {
|
|
||||||
var query_options = { sentOnly: true, pattern: floCloudAPI.SNStorageName };
|
|
||||||
if (typeof lastTx == 'number') //lastTx is tx count (*backward support)
|
|
||||||
query_options.ignoreOld = lastTx;
|
|
||||||
else if (typeof lastTx == 'string') //lastTx is txid of last tx
|
|
||||||
query_options.after = lastTx;
|
|
||||||
//fetch data from flosight
|
|
||||||
floBlockchainAPI.readData(floCloudAPI.SNStorageID, query_options).then(result => {
|
|
||||||
for (var i = result.data.length - 1; i >= 0; i--) {
|
|
||||||
var content = JSON.parse(result.data[i])[floCloudAPI.SNStorageName];
|
|
||||||
for (let sn in content.removeNodes)
|
|
||||||
compactIDB.removeData("supernodes", sn, DEFAULT.root);
|
|
||||||
for (let sn in content.newNodes)
|
|
||||||
compactIDB.writeData("supernodes", content.newNodes[sn], sn, DEFAULT.root);
|
|
||||||
for (let sn in content.updateNodes)
|
|
||||||
compactIDB.readData("supernodes", sn, DEFAULT.root).then(r => {
|
|
||||||
r = r || {}
|
|
||||||
r.uri = content.updateNodes[sn];
|
|
||||||
compactIDB.writeData("supernodes", r, sn, DEFAULT.root);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
compactIDB.writeData("lastTx", result.lastItem, floCloudAPI.SNStorageID, DEFAULT.root);
|
|
||||||
compactIDB.readAllData("supernodes", DEFAULT.root).then(nodes => {
|
|
||||||
floCloudAPI.init(nodes)
|
|
||||||
.then(result => resolve("Loaded Supernode list\n" + result))
|
|
||||||
.catch(error => reject(error))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}).catch(error => reject(error))
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
startUpFunctions.push(function readAppConfigFromAPI() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
if (!startUpOptions.app_config)
|
|
||||||
return resolve("No configs for this app");
|
|
||||||
compactIDB.readData("lastTx", `${DEFAULT.application}|${DEFAULT.adminID}`, DEFAULT.root).then(lastTx => {
|
|
||||||
var query_options = { sentOnly: true, pattern: DEFAULT.application };
|
|
||||||
if (typeof lastTx == 'number') //lastTx is tx count (*backward support)
|
|
||||||
query_options.ignoreOld = lastTx;
|
|
||||||
else if (typeof lastTx == 'string') //lastTx is txid of last tx
|
|
||||||
query_options.after = lastTx;
|
|
||||||
//fetch data from flosight
|
|
||||||
floBlockchainAPI.readData(DEFAULT.adminID, query_options).then(result => {
|
|
||||||
for (var i = result.data.length - 1; i >= 0; i--) {
|
|
||||||
var content = JSON.parse(result.data[i])[DEFAULT.application];
|
|
||||||
if (!content || typeof content !== "object")
|
|
||||||
continue;
|
|
||||||
if (Array.isArray(content.removeSubAdmin))
|
|
||||||
for (var j = 0; j < content.removeSubAdmin.length; j++)
|
|
||||||
compactIDB.removeData("subAdmins", content.removeSubAdmin[j]);
|
|
||||||
if (Array.isArray(content.addSubAdmin))
|
|
||||||
for (var k = 0; k < content.addSubAdmin.length; k++)
|
|
||||||
compactIDB.writeData("subAdmins", true, content.addSubAdmin[k]);
|
|
||||||
if (Array.isArray(content.removeTrustedID))
|
|
||||||
for (var j = 0; j < content.removeTrustedID.length; j++)
|
|
||||||
compactIDB.removeData("trustedIDs", content.removeTrustedID[j]);
|
|
||||||
if (Array.isArray(content.addTrustedID))
|
|
||||||
for (var k = 0; k < content.addTrustedID.length; k++)
|
|
||||||
compactIDB.writeData("trustedIDs", true, content.addTrustedID[k]);
|
|
||||||
if (content.settings)
|
|
||||||
for (let l in content.settings)
|
|
||||||
compactIDB.writeData("settings", content.settings[l], l)
|
|
||||||
}
|
|
||||||
compactIDB.writeData("lastTx", result.lastItem, `${DEFAULT.application}|${DEFAULT.adminID}`, DEFAULT.root);
|
|
||||||
compactIDB.readAllData("subAdmins").then(result => {
|
|
||||||
subAdmins = Object.keys(result);
|
|
||||||
compactIDB.readAllData("trustedIDs").then(result => {
|
|
||||||
trustedIDs = Object.keys(result);
|
|
||||||
compactIDB.readAllData("settings").then(result => {
|
|
||||||
settings = result;
|
|
||||||
resolve("Read app configuration from blockchain");
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}).catch(error => reject(error))
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
startUpFunctions.push(function loadDataFromAppIDB() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
if (!startUpOptions.cloud)
|
|
||||||
return resolve("No cloud for this app");
|
|
||||||
var loadData = ["appObjects", "generalData", "lastVC"]
|
|
||||||
var promises = []
|
|
||||||
for (var i = 0; i < loadData.length; i++)
|
|
||||||
promises[i] = compactIDB.readAllData(loadData[i])
|
|
||||||
Promise.all(promises).then(results => {
|
|
||||||
for (var i = 0; i < loadData.length; i++)
|
|
||||||
floGlobals[loadData[i]] = results[i]
|
|
||||||
resolve("Loaded Data from app IDB")
|
|
||||||
}).catch(error => reject(error))
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
var keyInput = type => new Promise((resolve, reject) => {
|
|
||||||
let inputVal = prompt(`Enter ${type}: `)
|
|
||||||
if (inputVal === null)
|
|
||||||
reject(null)
|
|
||||||
else
|
|
||||||
resolve(inputVal)
|
|
||||||
});
|
|
||||||
|
|
||||||
function getCredentials() {
|
|
||||||
|
|
||||||
const readSharesFromIDB = indexArr => new Promise((resolve, reject) => {
|
|
||||||
var promises = []
|
|
||||||
for (var i = 0; i < indexArr.length; i++)
|
|
||||||
promises.push(compactIDB.readData('credentials', indexArr[i]))
|
|
||||||
Promise.all(promises).then(shares => {
|
|
||||||
var secret = floCrypto.retrieveShamirSecret(shares)
|
|
||||||
if (secret)
|
|
||||||
resolve(secret)
|
|
||||||
else
|
|
||||||
reject("Shares are insufficient or incorrect")
|
|
||||||
}).catch(error => {
|
|
||||||
clearCredentials();
|
|
||||||
location.reload();
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
const writeSharesToIDB = (shares, i = 0, resultIndexes = []) => new Promise(resolve => {
|
|
||||||
if (i >= shares.length)
|
|
||||||
return resolve(resultIndexes)
|
|
||||||
var n = floCrypto.randInt(0, 100000)
|
|
||||||
compactIDB.addData("credentials", shares[i], n).then(res => {
|
|
||||||
resultIndexes.push(n)
|
|
||||||
writeSharesToIDB(shares, i + 1, resultIndexes)
|
|
||||||
.then(result => resolve(result))
|
|
||||||
}).catch(error => {
|
|
||||||
writeSharesToIDB(shares, i, resultIndexes)
|
|
||||||
.then(result => resolve(result))
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
const getPrivateKeyCredentials = () => new Promise((resolve, reject) => {
|
|
||||||
var indexArr = localStorage.getItem(`${DEFAULT.application}#privKey`)
|
|
||||||
if (indexArr) {
|
|
||||||
readSharesFromIDB(JSON.parse(indexArr))
|
|
||||||
.then(result => resolve(result))
|
|
||||||
.catch(error => reject(error))
|
|
||||||
} else {
|
|
||||||
var privKey;
|
|
||||||
keyInput("PRIVATE_KEY").then(result => {
|
|
||||||
if (!result)
|
|
||||||
return reject("Empty Private Key")
|
|
||||||
var floID = floCrypto.getFloID(result)
|
|
||||||
if (!floID || !floCrypto.validateFloID(floID))
|
|
||||||
return reject("Invalid Private Key")
|
|
||||||
privKey = result;
|
|
||||||
}).catch(error => {
|
|
||||||
console.log(error, "Generating Random Keys")
|
|
||||||
privKey = floCrypto.generateNewID().privKey
|
|
||||||
}).finally(_ => {
|
|
||||||
if (!privKey)
|
|
||||||
return;
|
|
||||||
var threshold = floCrypto.randInt(10, 20)
|
|
||||||
var shares = floCrypto.createShamirsSecretShares(privKey, threshold, threshold)
|
|
||||||
writeSharesToIDB(shares).then(resultIndexes => {
|
|
||||||
//store index keys in localStorage
|
|
||||||
localStorage.setItem(`${DEFAULT.application}#privKey`, JSON.stringify(resultIndexes))
|
|
||||||
//also add a dummy privatekey to the IDB
|
|
||||||
var randomPrivKey = floCrypto.generateNewID().privKey
|
|
||||||
var randomThreshold = floCrypto.randInt(10, 20)
|
|
||||||
var randomShares = floCrypto.createShamirsSecretShares(randomPrivKey, randomThreshold, randomThreshold)
|
|
||||||
writeSharesToIDB(randomShares)
|
|
||||||
//resolve private Key
|
|
||||||
resolve(privKey)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const checkIfPinRequired = key => new Promise((resolve, reject) => {
|
|
||||||
if (key.length == 52)
|
|
||||||
resolve(key)
|
|
||||||
else {
|
|
||||||
keyInput("PIN/Password").then(pwd => {
|
|
||||||
try {
|
|
||||||
let privKey = Crypto.AES.decrypt(key, pwd);
|
|
||||||
resolve(privKey)
|
|
||||||
} catch (error) {
|
|
||||||
reject("Access Denied: Incorrect PIN/Password")
|
|
||||||
}
|
|
||||||
}).catch(error => reject("Access Denied: PIN/Password required"))
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
getPrivateKeyCredentials().then(key => {
|
|
||||||
checkIfPinRequired(key).then(privKey => {
|
|
||||||
try {
|
|
||||||
user_public = floCrypto.getPubKeyHex(privKey);
|
|
||||||
user_id = floCrypto.getAddress(privKey);
|
|
||||||
if (startUpOptions.cloud)
|
|
||||||
floCloudAPI.user(user_id, privKey); //Set user for floCloudAPI
|
|
||||||
user_priv_wrap = () => checkIfPinRequired(key);
|
|
||||||
let n = floCrypto.randInt(12, 20);
|
|
||||||
aes_key = floCrypto.randString(n);
|
|
||||||
user_priv_raw = Crypto.AES.encrypt(privKey, aes_key);
|
|
||||||
user_private = user_priv_wrap;
|
|
||||||
resolve('Login Credentials loaded successful')
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error)
|
|
||||||
reject("Corrupted Private Key")
|
|
||||||
}
|
|
||||||
}).catch(error => reject(error))
|
|
||||||
}).catch(error => reject(error))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var startUpLog = (status, log) => status ? console.log(log) : console.error(log);
|
|
||||||
|
|
||||||
const callStartUpFunction = i => new Promise((resolve, reject) => {
|
|
||||||
startUpFunctions[i]().then(result => {
|
|
||||||
callStartUpFunction.completed += 1;
|
|
||||||
startUpLog(true, `${result}\nCompleted ${callStartUpFunction.completed}/${callStartUpFunction.total} Startup functions`)
|
|
||||||
resolve(true)
|
|
||||||
}).catch(error => {
|
|
||||||
callStartUpFunction.failed += 1;
|
|
||||||
startUpLog(false, `${error}\nFailed ${callStartUpFunction.failed}/${callStartUpFunction.total} Startup functions`)
|
|
||||||
reject(false)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
var _midFunction;
|
|
||||||
const midStartUp = () => new Promise((res, rej) => {
|
|
||||||
if (_midFunction instanceof Function) {
|
|
||||||
_midFunction()
|
|
||||||
.then(r => res("Mid startup function completed"))
|
|
||||||
.catch(e => rej("Mid startup function failed"))
|
|
||||||
} else
|
|
||||||
res("No mid startup function")
|
|
||||||
});
|
|
||||||
|
|
||||||
const callAndLog = p => new Promise((res, rej) => {
|
|
||||||
p.then(r => {
|
|
||||||
startUpLog(true, r)
|
|
||||||
res(r)
|
|
||||||
}).catch(e => {
|
|
||||||
startUpLog(false, e)
|
|
||||||
rej(e)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
floDapps.launchStartUp = function () {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
initIndexedDB().then(log => {
|
|
||||||
console.log(log)
|
|
||||||
callStartUpFunction.total = startUpFunctions.length;
|
|
||||||
callStartUpFunction.completed = 0;
|
|
||||||
callStartUpFunction.failed = 0;
|
|
||||||
let p1 = new Promise((res, rej) => {
|
|
||||||
Promise.all(startUpFunctions.map((f, i) => callStartUpFunction(i))).then(r => {
|
|
||||||
callAndLog(midStartUp())
|
|
||||||
.then(r => res(true))
|
|
||||||
.catch(e => rej(false))
|
|
||||||
})
|
|
||||||
});
|
|
||||||
let p2 = new Promise((res, rej) => {
|
|
||||||
callAndLog(getCredentials()).then(r => {
|
|
||||||
callAndLog(initUserDB()).then(r => {
|
|
||||||
callAndLog(loadUserDB())
|
|
||||||
.then(r => res(true))
|
|
||||||
.catch(e => rej(false))
|
|
||||||
}).catch(e => rej(false))
|
|
||||||
}).catch(e => rej(false))
|
|
||||||
})
|
|
||||||
Promise.all([p1, p2])
|
|
||||||
.then(r => resolve('App Startup finished successful'))
|
|
||||||
.catch(e => reject('App Startup failed'))
|
|
||||||
}).catch(error => {
|
|
||||||
startUpLog(false, error);
|
|
||||||
reject("App database initiation failed")
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
floDapps.addStartUpFunction = fn => fn instanceof Function && !startUpFunctions.includes(fn) ? startUpFunctions.push(fn) : false;
|
|
||||||
|
|
||||||
floDapps.setMidStartup = fn => fn instanceof Function ? _midFunction = fn : false;
|
|
||||||
|
|
||||||
floDapps.setCustomStartupLogger = fn => fn instanceof Function ? startUpLog = fn : false;
|
|
||||||
|
|
||||||
floDapps.setCustomPrivKeyInput = fn => fn instanceof Function ? keyInput = fn : false;
|
|
||||||
|
|
||||||
floDapps.setAppObjectStores = appObs => initIndexedDB.appObs = appObs;
|
|
||||||
|
|
||||||
floDapps.storeContact = function (floID, name) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
if (!floCrypto.validateAddr(floID))
|
|
||||||
return reject("Invalid floID!")
|
|
||||||
compactIDB.writeData("contacts", name, floID, user.db_name).then(result => {
|
|
||||||
user.contacts[floID] = name;
|
|
||||||
resolve("Contact stored")
|
|
||||||
}).catch(error => reject(error))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
floDapps.storePubKey = function (floID, pubKey) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
if (floID in user.pubKeys)
|
|
||||||
return resolve("pubKey already stored")
|
|
||||||
if (!floCrypto.validateAddr(floID))
|
|
||||||
return reject("Invalid floID!")
|
|
||||||
if (!floCrypto.verifyPubKey(pubKey, floID))
|
|
||||||
return reject("Incorrect pubKey")
|
|
||||||
compactIDB.writeData("pubKeys", pubKey, floID, user.db_name).then(result => {
|
|
||||||
user.pubKeys[floID] = pubKey;
|
|
||||||
resolve("pubKey stored")
|
|
||||||
}).catch(error => reject(error))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
floDapps.sendMessage = function (floID, message) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let options = {
|
|
||||||
receiverID: floID,
|
|
||||||
application: DEFAULT.root,
|
|
||||||
comment: DEFAULT.application
|
|
||||||
}
|
|
||||||
if (floID in user.pubKeys)
|
|
||||||
message = floCrypto.encryptData(JSON.stringify(message), user.pubKeys[floID])
|
|
||||||
floCloudAPI.sendApplicationData(message, "Message", options)
|
|
||||||
.then(result => resolve(result))
|
|
||||||
.catch(error => reject(error))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
floDapps.requestInbox = function (callback) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let lastVC = Object.keys(user.messages).sort().pop()
|
|
||||||
let options = {
|
|
||||||
receiverID: user.id,
|
|
||||||
application: DEFAULT.root,
|
|
||||||
lowerVectorClock: lastVC + 1
|
|
||||||
}
|
|
||||||
let privKey = raw_user.private;
|
|
||||||
options.callback = (d, e) => {
|
|
||||||
for (let v in d) {
|
|
||||||
try {
|
|
||||||
if (d[v].message instanceof Object && "secret" in d[v].message)
|
|
||||||
d[v].message = floCrypto.decryptData(d[v].message, privKey)
|
|
||||||
} catch (error) { }
|
|
||||||
compactIDB.writeData("messages", d[v], v, user.db_name)
|
|
||||||
user.messages[v] = d[v]
|
|
||||||
}
|
|
||||||
if (callback instanceof Function)
|
|
||||||
callback(d, e)
|
|
||||||
}
|
|
||||||
floCloudAPI.requestApplicationData("Message", options)
|
|
||||||
.then(result => resolve(result))
|
|
||||||
.catch(error => reject(error))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
floDapps.manageAppConfig = function (adminPrivKey, addList, rmList, settings) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
if (!startUpOptions.app_config)
|
|
||||||
return reject("No configs for this app");
|
|
||||||
if (!Array.isArray(addList) || !addList.length) addList = undefined;
|
|
||||||
if (!Array.isArray(rmList) || !rmList.length) rmList = undefined;
|
|
||||||
if (!settings || typeof settings !== "object" || !Object.keys(settings).length) settings = undefined;
|
|
||||||
if (!addList && !rmList && !settings)
|
|
||||||
return reject("No configuration change")
|
|
||||||
var floData = {
|
|
||||||
[DEFAULT.application]: {
|
|
||||||
addSubAdmin: addList,
|
|
||||||
removeSubAdmin: rmList,
|
|
||||||
settings: settings
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var floID = floCrypto.getFloID(adminPrivKey)
|
|
||||||
if (floID != DEFAULT.adminID)
|
|
||||||
reject('Access Denied for Admin privilege')
|
|
||||||
else
|
|
||||||
floBlockchainAPI.writeData(floID, JSON.stringify(floData), adminPrivKey)
|
|
||||||
.then(result => resolve(['Updated App Configuration', result]))
|
|
||||||
.catch(error => reject(error))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
floDapps.manageAppTrustedIDs = function (adminPrivKey, addList, rmList) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
if (!startUpOptions.app_config)
|
|
||||||
return reject("No configs for this app");
|
|
||||||
if (!Array.isArray(addList) || !addList.length) addList = undefined;
|
|
||||||
if (!Array.isArray(rmList) || !rmList.length) rmList = undefined;
|
|
||||||
if (!addList && !rmList)
|
|
||||||
return reject("No change in list")
|
|
||||||
var floData = {
|
|
||||||
[DEFAULT.application]: {
|
|
||||||
addTrustedID: addList,
|
|
||||||
removeTrustedID: rmList
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var floID = floCrypto.getFloID(adminPrivKey)
|
|
||||||
if (floID != DEFAULT.adminID)
|
|
||||||
reject('Access Denied for Admin privilege')
|
|
||||||
else
|
|
||||||
floBlockchainAPI.writeData(floID, JSON.stringify(floData), adminPrivKey)
|
|
||||||
.then(result => resolve(['Updated App Configuration', result]))
|
|
||||||
.catch(error => reject(error))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const clearCredentials = floDapps.clearCredentials = function () {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
compactIDB.clearData('credentials', DEFAULT.application).then(result => {
|
|
||||||
localStorage.removeItem(`${DEFAULT.application}#privKey`);
|
|
||||||
user.clear();
|
|
||||||
resolve("privKey credentials deleted!")
|
|
||||||
}).catch(error => reject(error))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
floDapps.deleteUserData = function (credentials = false) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let p = []
|
|
||||||
p.push(compactIDB.deleteDB(user.db_name))
|
|
||||||
if (credentials)
|
|
||||||
p.push(clearCredentials())
|
|
||||||
Promise.all(p)
|
|
||||||
.then(result => resolve('User database(local) deleted'))
|
|
||||||
.catch(error => reject(error))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
floDapps.deleteAppData = function () {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
compactIDB.deleteDB(DEFAULT.application).then(result => {
|
|
||||||
localStorage.removeItem(`${DEFAULT.application}#privKey`)
|
|
||||||
user.clear();
|
|
||||||
compactIDB.removeData('lastTx', `${DEFAULT.application}|${DEFAULT.adminID}`, DEFAULT.root)
|
|
||||||
.then(result => resolve("App database(local) deleted"))
|
|
||||||
.catch(error => reject(error))
|
|
||||||
}).catch(error => reject(error))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
floDapps.securePrivKey = function (pwd) {
|
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
let indexArr = localStorage.getItem(`${DEFAULT.application}#privKey`)
|
|
||||||
if (!indexArr)
|
|
||||||
return reject("PrivKey not found");
|
|
||||||
indexArr = JSON.parse(indexArr)
|
|
||||||
let encryptedKey = Crypto.AES.encrypt(await user.private, pwd);
|
|
||||||
let threshold = indexArr.length;
|
|
||||||
let shares = floCrypto.createShamirsSecretShares(encryptedKey, threshold, threshold)
|
|
||||||
let promises = [];
|
|
||||||
let overwriteFn = (share, index) =>
|
|
||||||
compactIDB.writeData("credentials", share, index, DEFAULT.application);
|
|
||||||
for (var i = 0; i < threshold; i++)
|
|
||||||
promises.push(overwriteFn(shares[i], indexArr[i]));
|
|
||||||
Promise.all(promises)
|
|
||||||
.then(results => resolve("Private Key Secured"))
|
|
||||||
.catch(error => reject(error))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
floDapps.verifyPin = function (pin = null) {
|
|
||||||
const readSharesFromIDB = function (indexArr) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
var promises = []
|
|
||||||
for (var i = 0; i < indexArr.length; i++)
|
|
||||||
promises.push(compactIDB.readData('credentials', indexArr[i]))
|
|
||||||
Promise.all(promises).then(shares => {
|
|
||||||
var secret = floCrypto.retrieveShamirSecret(shares)
|
|
||||||
console.info(shares, secret)
|
|
||||||
if (secret)
|
|
||||||
resolve(secret)
|
|
||||||
else
|
|
||||||
reject("Shares are insufficient or incorrect")
|
|
||||||
}).catch(error => {
|
|
||||||
clearCredentials();
|
|
||||||
location.reload();
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
var indexArr = localStorage.getItem(`${DEFAULT.application}#privKey`)
|
|
||||||
console.info(indexArr)
|
|
||||||
if (!indexArr)
|
|
||||||
reject('No login credentials found')
|
|
||||||
readSharesFromIDB(JSON.parse(indexArr)).then(key => {
|
|
||||||
if (key.length == 52) {
|
|
||||||
if (pin === null)
|
|
||||||
resolve("Private key not secured")
|
|
||||||
else
|
|
||||||
reject("Private key not secured")
|
|
||||||
} else {
|
|
||||||
if (pin === null)
|
|
||||||
return reject("PIN/Password required")
|
|
||||||
try {
|
|
||||||
let privKey = Crypto.AES.decrypt(key, pin);
|
|
||||||
resolve("PIN/Password verified")
|
|
||||||
} catch (error) {
|
|
||||||
reject("Incorrect PIN/Password")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).catch(error => reject(error))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const getNextGeneralData = floDapps.getNextGeneralData = function (type, vectorClock = null, options = {}) {
|
|
||||||
var fk = floCloudAPI.util.filterKey(type, options)
|
|
||||||
vectorClock = vectorClock || getNextGeneralData[fk] || '0';
|
|
||||||
var filteredResult = {}
|
|
||||||
if (floGlobals.generalData[fk]) {
|
|
||||||
for (let d in floGlobals.generalData[fk])
|
|
||||||
if (d > vectorClock)
|
|
||||||
filteredResult[d] = JSON.parse(JSON.stringify(floGlobals.generalData[fk][d]))
|
|
||||||
} else if (options.comment) {
|
|
||||||
let comment = options.comment;
|
|
||||||
delete options.comment;
|
|
||||||
let fk = floCloudAPI.util.filterKey(type, options);
|
|
||||||
for (let d in floGlobals.generalData[fk])
|
|
||||||
if (d > vectorClock && floGlobals.generalData[fk][d].comment == comment)
|
|
||||||
filteredResult[d] = JSON.parse(JSON.stringify(floGlobals.generalData[fk][d]))
|
|
||||||
}
|
|
||||||
if (options.decrypt) {
|
|
||||||
let decryptionKey = (options.decrypt === true) ? raw_user.private : options.decrypt;
|
|
||||||
if (!Array.isArray(decryptionKey))
|
|
||||||
decryptionKey = [decryptionKey];
|
|
||||||
for (let f in filteredResult) {
|
|
||||||
let data = filteredResult[f]
|
|
||||||
try {
|
|
||||||
if (data.message instanceof Object && "secret" in data.message) {
|
|
||||||
for (let key of decryptionKey) {
|
|
||||||
try {
|
|
||||||
let tmp = floCrypto.decryptData(data.message, key)
|
|
||||||
data.message = JSON.parse(tmp)
|
|
||||||
break;
|
|
||||||
} catch (error) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getNextGeneralData[fk] = Object.keys(filteredResult).sort().pop();
|
|
||||||
return filteredResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
const syncData = floDapps.syncData = {};
|
|
||||||
|
|
||||||
syncData.oldDevice = () => new Promise((resolve, reject) => {
|
|
||||||
let sync = {
|
|
||||||
contacts: user.contacts,
|
|
||||||
pubKeys: user.pubKeys,
|
|
||||||
messages: user.messages
|
|
||||||
}
|
|
||||||
let message = Crypto.AES.encrypt(JSON.stringify(sync), raw_user.private)
|
|
||||||
let options = {
|
|
||||||
receiverID: user.id,
|
|
||||||
application: DEFAULT.root
|
|
||||||
}
|
|
||||||
floCloudAPI.sendApplicationData(message, "syncData", options)
|
|
||||||
.then(result => resolve(result))
|
|
||||||
.catch(error => reject(error))
|
|
||||||
});
|
|
||||||
|
|
||||||
syncData.newDevice = () => new Promise((resolve, reject) => {
|
|
||||||
var options = {
|
|
||||||
receiverID: user.id,
|
|
||||||
senderID: user.id,
|
|
||||||
application: DEFAULT.root,
|
|
||||||
mostRecent: true,
|
|
||||||
}
|
|
||||||
floCloudAPI.requestApplicationData("syncData", options).then(response => {
|
|
||||||
let vc = Object.keys(response).sort().pop()
|
|
||||||
let sync = JSON.parse(Crypto.AES.decrypt(response[vc].message, raw_user.private))
|
|
||||||
let promises = []
|
|
||||||
let store = (key, val, obs) => promises.push(compactIDB.writeData(obs, val, key, user.db_name));
|
|
||||||
["contacts", "pubKeys", "messages"].forEach(c => {
|
|
||||||
for (let i in sync[c]) {
|
|
||||||
store(i, sync[c][i], c)
|
|
||||||
user[c][i] = sync[c][i]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
Promise.all(promises)
|
|
||||||
.then(results => resolve("Sync data successful"))
|
|
||||||
.catch(error => reject(error))
|
|
||||||
}).catch(error => reject(error))
|
|
||||||
});
|
|
||||||
})('object' === typeof module ? module.exports : window.floDapps = {});
|
|
||||||
57
index.html
57
index.html
@ -1,57 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title>FLO Standard Operators</title>
|
|
||||||
<script id="floGlobals">
|
|
||||||
/* Constants for FLO blockchain operations !!Make sure to add this at beginning!! */
|
|
||||||
const floGlobals = {
|
|
||||||
blockchain: "FLO",
|
|
||||||
adminID: "FKAEdnPfjXLHSYwrXQu377ugN4tXU7VGdf",
|
|
||||||
application: "TEST_MODE",
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
(function () {
|
|
||||||
const urlSearchParams = new URLSearchParams(window.location.search);
|
|
||||||
const params = Object.fromEntries(urlSearchParams.entries());
|
|
||||||
if ('testnet' in params) {
|
|
||||||
floGlobals.blockchain = "FLO_TEST";
|
|
||||||
floGlobals.adminID = "oKKHdK5uYAJ52U91sYsWhnEaEAAhZP779B";
|
|
||||||
floGlobals.application = "TEST_MODE_testnet";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('quick' in params)
|
|
||||||
window.quick = true;
|
|
||||||
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
<script src="lib.js"></script>
|
|
||||||
<script src="floCrypto.js"></script>
|
|
||||||
<script src="btcOperator.js"></script>
|
|
||||||
<script src="floBlockchainAPI.js"></script>
|
|
||||||
<script src="floTokenAPI.js"></script>
|
|
||||||
<script src="compactIDB.js"></script>
|
|
||||||
<script src="floCloudAPI.js"></script>
|
|
||||||
<script src="floDapps.js"></script>
|
|
||||||
<script id="onLoadStartUp">
|
|
||||||
function onLoadStartUp() {
|
|
||||||
if (window.quick) return;
|
|
||||||
//floDapps.addStartUpFunction('Sample', Promised Function)
|
|
||||||
//floDapps.setAppObjectStores({sampleObs1:{}, sampleObs2:{options{autoIncrement:true, keyPath:'SampleKey'}, Indexes:{sampleIndex:{}}}})
|
|
||||||
//floDapps.setCustomPrivKeyInput( () => { FUNCTION BODY *must resolve private key* } )
|
|
||||||
floDapps.launchStartUp().then(result => {
|
|
||||||
console.log(result)
|
|
||||||
alert(`Welcome FLO_ID: ${myFloID}`)
|
|
||||||
//App functions....
|
|
||||||
}).catch(error => console.error(error))
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body onload="onLoadStartUp()">
|
|
||||||
TEST_MODE
|
|
||||||
(use console)
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
Loading…
Reference in New Issue
Block a user