ribc/scripts/floDapps.min.js
2022-10-18 15:29:10 +05:30

1 line
13 KiB
JavaScript

(function(e){"use strict";function t(){return new Promise((e,a)=>{var r={lastTx:{},supernodes:{indexes:{uri:null,pubKey:null}}},o={credentials:{},subAdmins:{},settings:{},appObjects:{},generalData:{},lastVC:{}};t.appObs=t.appObs||{};for(let e in t.appObs)e in o||(o[e]=t.appObs[e]);Promise.all([compactIDB.initDB(c.application,o),compactIDB.initDB(c.root,r)]).then(t=>{compactIDB.setDefaultDB(c.application),e("IndexedDB App Storage Initated Successfully")}).catch(e=>a(e))})}function a(){return new Promise((e,t)=>{var a={contacts:{},pubKeys:{},messages:{}};compactIDB.initDB(m.db_name,a).then(t=>{e("UserDB Initated Successfully")}).catch(e=>t("Init userDB failed"))})}function r(){return new Promise((e,t)=>{for(var a=["contacts","pubKeys","messages"],r=[],o=0;o<a.length;o++)r[o]=compactIDB.readAllData(a[o],m.db_name);Promise.all(r).then(t=>{for(var r=0;r<a.length;r++)m[a[r]]=t[r];e("Loaded Data from userDB")}).catch(e=>t("Load userDB failed"))})}function o(){const e=e=>new Promise((t,a)=>{for(var r=[],o=0;o<e.length;o++)r.push(compactIDB.readData("credentials",e[o]));Promise.all(r).then(e=>{var r=floCrypto.retrieveShamirSecret(e);r?t(r):a("Shares are insufficient or incorrect")}).catch(e=>{A(),location.reload()})}),t=(e,a=0,r=[])=>new Promise(o=>{if(a>=e.length)return o(r);var n=floCrypto.randInt(0,1e5);compactIDB.addData("credentials",e[a],n).then(c=>{r.push(n),t(e,a+1,r).then(e=>o(e))}).catch(n=>{t(e,a,r).then(e=>o(e))})}),a=()=>new Promise((a,r)=>{var o,n=localStorage.getItem(`${c.application}#privKey`);n?e(JSON.parse(n)).then(e=>a(e)).catch(e=>r(e)):D("PRIVATE_KEY").then(e=>{if(!e)return r("Empty Private Key");var t=floCrypto.getFloID(e);if(!t||!floCrypto.validateFloID(t))return r("Invalid Private Key");o=e}).catch(e=>{console.log(e,"Generating Random Keys"),o=floCrypto.generateNewID().privKey}).finally(e=>{if(o){var r=floCrypto.randInt(10,20),n=floCrypto.createShamirsSecretShares(o,r,r);t(n).then(e=>{localStorage.setItem(`${c.application}#privKey`,JSON.stringify(e));var r=floCrypto.generateNewID().privKey,n=floCrypto.randInt(10,20),i=floCrypto.createShamirsSecretShares(r,n,n);t(i),a(o)})}})}),r=e=>new Promise((t,a)=>{52==e.length?t(e):D("PIN/Password").then(r=>{try{let o=Crypto.AES.decrypt(e,r);t(o)}catch(e){a("Access Denied: Incorrect PIN/Password")}}).catch(e=>a("Access Denied: PIN/Password required"))});return new Promise((e,t)=>{a().then(a=>{r(a).then(o=>{try{u=floCrypto.getPubKeyHex(o),d=floCrypto.getAddress(o),floCloudAPI.user(d,o),l=(()=>r(a));let n=floCrypto.randInt(12,20);s=floCrypto.randString(n),i=Crypto.AES.encrypt(o,s),f=l,e("Login Credentials loaded successful")}catch(e){console.log(e),t("Corrupted Private Key")}}).catch(e=>t(e))}).catch(e=>t(e))})}const n=e,c={root:"floDapps",application:floGlobals.application,adminID:floGlobals.adminID};var i,s,l;Object.defineProperties(n,{application:{get:()=>c.application},adminID:{get:()=>c.adminID},root:{get:()=>c.root}});const p={get private(){if(!i)throw"User not logged in";return Crypto.AES.decrypt(i,s)}};var d,u,f;const m=n.user={get id(){if(!d)throw"User not logged in";return d},get public(){if(!u)throw"User not logged in";return u},get private(){if(f)return f instanceof Function?f():Crypto.AES.decrypt(f,s);throw"User not logged in"},sign:e=>floCrypto.signData(e,p.private),decrypt:e=>floCrypto.decryptData(e,p.private),encipher:e=>Crypto.AES.encrypt(e,p.private),decipher:e=>Crypto.AES.decrypt(e,p.private),get db_name(){return"floDapps#"+floCrypto.toFloID(m.id)},lock(){f=l},async unlock(){await m.private===p.private&&(f=i)},get_contact(e){if(!m.contacts)throw"Contacts not available";if(m.contacts[e])return m.contacts[e];{let t=floCrypto.decodeAddr(e).hex;for(let e in m.contacts)if(floCrypto.decodeAddr(e).hex==t)return m.contacts[e]}},get_pubKey(e){if(!m.pubKeys)throw"Contacts not available";if(m.pubKeys[e])return m.pubKeys[e];{let t=floCrypto.decodeAddr(e).hex;for(let e in m.pubKeys)if(floCrypto.decodeAddr(e).hex==t)return m.pubKeys[e]}},clear(){d=u=f=void 0,i=s=void 0,delete m.contacts,delete m.pubKeys,delete m.messages}};var y,h;Object.defineProperties(window,{myFloID:{get:()=>{try{return m.id}catch{return}}},myUserID:{get:()=>{try{return m.id}catch{return}}},myPubKey:{get:()=>{try{return m.public}catch{return}}},myPrivKey:{get:()=>{try{return m.private}catch{return}}}}),Object.defineProperties(floGlobals,{subAdmins:{get:()=>y},settings:{get:()=>h},contacts:{get:()=>m.contacts},pubKeys:{get:()=>m.pubKeys},messages:{get:()=>m.messages}});const g=[];g.push(function(){return new Promise((e,t)=>{compactIDB.readData("lastTx",floCloudAPI.SNStorageID,c.root).then(a=>{floBlockchainAPI.readData(floCloudAPI.SNStorageID,{ignoreOld:a,sentOnly:!0,pattern:"SuperNodeStorage"}).then(a=>{for(var r=a.data.length-1;r>=0;r--){var o=JSON.parse(a.data[r]).SuperNodeStorage;for(let e in o.removeNodes)compactIDB.removeData("supernodes",e,c.root);for(let e in o.newNodes)compactIDB.writeData("supernodes",o.newNodes[e],e,c.root)}compactIDB.writeData("lastTx",a.totalTxs,floCloudAPI.SNStorageID,c.root),compactIDB.readAllData("supernodes",c.root).then(a=>{floCloudAPI.init(a).then(t=>e("Loaded Supernode list\n"+t)).catch(e=>t(e))})})}).catch(e=>t(e))})}),g.push(function(){return new Promise((e,t)=>{compactIDB.readData("lastTx",`${c.application}|${c.adminID}`,c.root).then(t=>{floBlockchainAPI.readData(c.adminID,{ignoreOld:t,sentOnly:!0,pattern:c.application}).then(t=>{for(var a=t.data.length-1;a>=0;a--){var r=JSON.parse(t.data[a])[c.application];if(r&&"object"==typeof r){if(Array.isArray(r.removeSubAdmin))for(var o=0;o<r.removeSubAdmin.length;o++)compactIDB.removeData("subAdmins",r.removeSubAdmin[o]);if(Array.isArray(r.addSubAdmin))for(var n=0;n<r.addSubAdmin.length;n++)compactIDB.writeData("subAdmins",!0,r.addSubAdmin[n]);if(r.settings)for(let e in r.settings)compactIDB.writeData("settings",r.settings[e],e)}}compactIDB.writeData("lastTx",t.totalTxs,`${c.application}|${c.adminID}`,c.root),compactIDB.readAllData("subAdmins").then(t=>{y=Object.keys(t),compactIDB.readAllData("settings").then(t=>{h=t,e("Read app configuration from blockchain")})})})}).catch(e=>t(e))})}),g.push(function(){return new Promise((e,t)=>{for(var a=["appObjects","generalData","lastVC"],r=[],o=0;o<a.length;o++)r[o]=compactIDB.readAllData(a[o]);Promise.all(r).then(t=>{for(var r=0;r<a.length;r++)floGlobals[a[r]]=t[r];e("Loaded Data from app IDB")}).catch(e=>t(e))})});var D=e=>new Promise((t,a)=>{let r=prompt(`Enter ${e}: `);null===r?a(null):t(r)}),v=(e,t)=>e?console.log(t):console.error(t);const I=e=>new Promise((t,a)=>{g[e]().then(e=>{I.completed+=1,v(!0,`${e}\nCompleted ${I.completed}/${I.total} Startup functions`),t(!0)}).catch(e=>{I.failed+=1,v(!1,`${e}\nFailed ${I.failed}/${I.total} Startup functions`),a(!1)})});var b;const P=()=>new Promise((e,t)=>{b instanceof Function?b().then(t=>e("Mid startup function completed")).catch(e=>t("Mid startup function failed")):e("No mid startup function")}),S=e=>new Promise((t,a)=>{e.then(e=>{v(!0,e),t(e)}).catch(e=>{v(!1,e),a(e)})});n.launchStartUp=function(){return new Promise((e,n)=>{t().then(t=>{console.log(t),I.total=g.length,I.completed=0,I.failed=0;let c=new Promise((e,t)=>{Promise.all(g.map((e,t)=>I(t))).then(a=>{S(P()).then(t=>e(!0)).catch(e=>t(!1))})}),i=new Promise((e,t)=>{S(o()).then(o=>{S(a()).then(a=>{S(r()).then(t=>e(!0)).catch(e=>t(!1))}).catch(e=>t(!1))}).catch(e=>t(!1))});Promise.all([c,i]).then(t=>e("App Startup finished successful")).catch(e=>n("App Startup failed"))}).catch(e=>{v(!1,e),n("App database initiation failed")})})},n.addStartUpFunction=(e=>e instanceof Function&&!g.includes(e)&&g.push(e)),n.setMidStartup=(e=>e instanceof Function&&(b=e)),n.setCustomStartupLogger=(e=>e instanceof Function&&(v=e)),n.setCustomPrivKeyInput=(e=>e instanceof Function&&(D=e)),n.setAppObjectStores=(e=>t.appObs=e),n.storeContact=function(e,t){return new Promise((a,r)=>{if(!floCrypto.validateAddr(e))return r("Invalid floID!");compactIDB.writeData("contacts",t,e,m.db_name).then(r=>{m.contacts[e]=t,a("Contact stored")}).catch(e=>r(e))})},n.storePubKey=function(e,t){return new Promise((a,r)=>e in m.pubKeys?a("pubKey already stored"):floCrypto.validateAddr(e)?floCrypto.verifyPubKey(t,e)?void compactIDB.writeData("pubKeys",t,e,m.db_name).then(r=>{m.pubKeys[e]=t,a("pubKey stored")}).catch(e=>r(e)):r("Incorrect pubKey"):r("Invalid floID!"))},n.sendMessage=function(e,t){return new Promise((a,r)=>{let o={receiverID:e,application:c.root,comment:c.application};e in m.pubKeys&&(t=floCrypto.encryptData(JSON.stringify(t),m.pubKeys[e])),floCloudAPI.sendApplicationData(t,"Message",o).then(e=>a(e)).catch(e=>r(e))})},n.requestInbox=function(e){return new Promise((t,a)=>{let r=Object.keys(m.messages).sort().pop(),o={receiverID:m.id,application:c.root,lowerVectorClock:r+1},n=p.private;o.callback=((t,a)=>{for(let e in t){try{t[e].message instanceof Object&&"secret"in t[e].message&&(t[e].message=floCrypto.decryptData(t[e].message,n))}catch(e){}compactIDB.writeData("messages",t[e],e,m.db_name),m.messages[e]=t[e]}e instanceof Function&&e(t,a)}),floCloudAPI.requestApplicationData("Message",o).then(e=>t(e)).catch(e=>a(e))})},n.manageAppConfig=function(e,t,a,r){return new Promise((o,n)=>{if(Array.isArray(t)&&t.length||(t=void 0),Array.isArray(a)&&a.length||(a=void 0),r&&"object"==typeof r&&Object.keys(r).length||(r=void 0),!t&&!a&&!r)return n("No configuration change");var i={[c.application]:{addSubAdmin:t,removeSubAdmin:a,settings:r}},s=floCrypto.getFloID(e);s!=c.adminID?n("Access Denied for Admin privilege"):floBlockchainAPI.writeData(s,JSON.stringify(i),e).then(e=>o(["Updated App Configuration",e])).catch(e=>n(e))})};const A=n.clearCredentials=function(){return new Promise((e,t)=>{compactIDB.clearData("credentials",c.application).then(t=>{localStorage.removeItem(`${c.application}#privKey`),m.clear(),e("privKey credentials deleted!")}).catch(e=>t(e))})};n.deleteUserData=function(e=!1){return new Promise((t,a)=>{let r=[];r.push(compactIDB.deleteDB(m.db_name)),e&&r.push(A()),Promise.all(r).then(e=>t("User database(local) deleted")).catch(e=>a(e))})},n.deleteAppData=function(){return new Promise((e,t)=>{compactIDB.deleteDB(c.application).then(a=>{localStorage.removeItem(`${c.application}#privKey`),m.clear(),compactIDB.removeData("lastTx",`${c.application}|${c.adminID}`,c.root).then(t=>e("App database(local) deleted")).catch(e=>t(e))}).catch(e=>t(e))})},n.securePrivKey=function(e){return new Promise(async(t,a)=>{let r=localStorage.getItem(`${c.application}#privKey`);if(!r)return a("PrivKey not found");r=JSON.parse(r);let o=Crypto.AES.encrypt(await m.private,e),n=r.length,i=floCrypto.createShamirsSecretShares(o,n,n),s=[],l=(e,t)=>compactIDB.writeData("credentials",e,t,c.application);for(var p=0;p<n;p++)s.push(l(i[p],r[p]));Promise.all(s).then(e=>t("Private Key Secured")).catch(e=>a(e))})},n.verifyPin=function(e=null){const t=function(e){return new Promise((t,a)=>{for(var r=[],o=0;o<e.length;o++)r.push(compactIDB.readData("credentials",e[o]));Promise.all(r).then(e=>{var r=floCrypto.retrieveShamirSecret(e);console.info(e,r),r?t(r):a("Shares are insufficient or incorrect")}).catch(e=>{A(),location.reload()})})};return new Promise((a,r)=>{var o=localStorage.getItem(`${c.application}#privKey`);console.info(o),o||r("No login credentials found"),t(JSON.parse(o)).then(t=>{if(52==t.length)null===e?a("Private key not secured"):r("Private key not secured");else{if(null===e)return r("PIN/Password required");try{Crypto.AES.decrypt(t,e);a("PIN/Password verified")}catch(e){r("Incorrect PIN/Password")}}}).catch(e=>r(e))})};const w=n.getNextGeneralData=function(e,t=null,a={}){var r=floCloudAPI.util.filterKey(e,a);t=t||w[r]||"0";var o={};if(floGlobals.generalData[r])for(let e in floGlobals.generalData[r])e>t&&(o[e]=JSON.parse(JSON.stringify(floGlobals.generalData[r][e])));else if(a.comment){let r=a.comment;delete a.comment;let n=floCloudAPI.util.filterKey(e,a);for(let e in floGlobals.generalData[n])e>t&&floGlobals.generalData[n][e].comment==r&&(o[e]=JSON.parse(JSON.stringify(floGlobals.generalData[n][e])))}if(a.decrypt){let e=!0===a.decrypt?p.private:a.decrypt;Array.isArray(e)||(e=[e]);for(let t in o){let a=o[t];try{if(a.message instanceof Object&&"secret"in a.message)for(let t of e)try{let e=floCrypto.decryptData(a.message,t);a.message=JSON.parse(e);break}catch(e){}}catch(e){}}}return w[r]=Object.keys(o).sort().pop(),o},C=n.syncData={};C.oldDevice=(()=>new Promise((e,t)=>{let a={contacts:m.contacts,pubKeys:m.pubKeys,messages:m.messages},r=Crypto.AES.encrypt(JSON.stringify(a),p.private),o={receiverID:m.id,application:c.root};floCloudAPI.sendApplicationData(r,"syncData",o).then(t=>e(t)).catch(e=>t(e))})),C.newDevice=(()=>new Promise((e,t)=>{var a={receiverID:m.id,senderID:m.id,application:c.root,mostRecent:!0};floCloudAPI.requestApplicationData("syncData",a).then(a=>{let r=Object.keys(a).sort().pop(),o=JSON.parse(Crypto.AES.decrypt(a[r].message,p.private)),n=[],c=(e,t,a)=>n.push(compactIDB.writeData(a,t,e,m.db_name));["contacts","pubKeys","messages"].forEach(e=>{for(let t in o[e])c(t,o[e][t],e),m[e][t]=o[e][t]}),Promise.all(n).then(t=>e("Sync data successful")).catch(e=>t(e))}).catch(e=>t(e))}))})("object"==typeof module?module.exports:window.floDapps={});