UNPKG

@activeledger/activeprotocol

Version:

Underlying protocol which handles consensus and the smart contract virtual machine of Activeledger

236 lines 9.78 kB
import { ActiveDefinitions } from "@activeledger/activedefinitions"; export class PermissionsChecker { constructor(entry, db, checkRevs, securityCache, shared) { this.entry = entry; this.db = db; this.checkRevs = checkRevs; this.securityCache = securityCache; this.shared = shared; } async process(data, inputs = true) { this.inputs = inputs; this.data = data; try { const streams = await this.buildPromises(); return this.processStreams(streams); } catch (error) { return Promise.reject(error); } } async buildPromises() { const keys = []; let contractDataIncluded = false; for (let i = this.data.length; i--;) { const filteredPrefix = this.shared.filterPrefix(this.data[i], true); const suffix = this.data[i].split(":")[1]; contractDataIncluded = suffix === "data"; if (keys.indexOf(filteredPrefix) === -1) { keys.push(filteredPrefix + ":stream"); keys.push(filteredPrefix); } } try { const docs = await this.db.allDocs({ keys, include_docs: true, }); const reorder = {}; const results = []; for (let i = docs.rows.length; i--;) { const baseDoc = docs.rows[i].doc._id.replace(":stream", ""); let iMeta = null; let iState = null; if (baseDoc === docs.rows[i].doc._id) { iState = docs.rows[i].doc; } else { iMeta = docs.rows[i].doc; if (iMeta.contractlock && iMeta.contractlock.length && iMeta.contractlock.indexOf(this.entry.$tx.$contract) === -1) { throw { code: 1700, reason: "Stream contract locked", }; } if (iMeta.namespaceLock && iMeta.namespaceLock.length && iMeta.namespaceLock.indexOf(this.entry.$tx.$namespace) === -1) { throw { code: 1710, reason: "Stream namespace locked", }; } } if (!reorder[baseDoc]) { reorder[baseDoc] = results.push({ state: iState, meta: iMeta, }); } else { const result = results[reorder[baseDoc] - 1]; if (result.state) { if (iMeta) result.meta = iMeta; } else { if (iState) result.state = iState; } } } if (contractDataIncluded) { for (let i = results.length; i--;) { const sId = results[i].state._id; if (sId && sId.indexOf(":data")) { let cRes = results[i]; cRes.meta = { _id: `${cRes.state._id}:meta`, _rev: "0-context" }; results[i] = cRes; } } } if (results.length === (keys.length / 2)) { return results; } else { throw { code: 950, reason: "Stream(s) not found", }; } } catch (error) { error.code = 950; error.reason = "Stream(s) not found"; throw error; } } processStreams(stream) { return new Promise((resolve, reject) => { let i = stream.length; while (i--) { let streamId = stream[i].state._id; const revType = this.inputs ? this.entry.$revs.$i : this.entry.$revs.$o; const currentRevision = stream[i].meta._rev + ":" + stream[i].state._rev; if (revType && revType[streamId]) { if (revType[streamId] !== currentRevision) { return reject({ code: 1200, reason: (this.inputs ? "Input" : "Output") + " Stream Position Incorrect", }); } } else { revType[streamId] = currentRevision; } if (this.inputs || this.securityCache.signedOutputs) { let nhpkCheck = false; let nhpkCheckIO = this.inputs ? this.entry.$tx.$i : this.entry.$tx.$o; if (this.securityCache.hardenedKeys) { const nhpkDataCheck = nhpkCheckIO[this.shared.getLabelIOMap(this.inputs, streamId)] .$nhpk; if (!nhpkDataCheck) { return reject({ code: 1230, reason: (this.inputs ? "Inputs" : "Output") + " Security Hardened Key Transactions Only", }); } else { nhpkCheck = true; } } if (stream[i].meta.authorities) { this.signatureCheck(streamId, stream[i], nhpkCheck, nhpkCheckIO, reject); } else { const type = stream[i].meta.type ? stream[i].meta.type : "rsa"; const sigCheck = this.shared.signatureCheck(stream[i].meta.public, this.entry.$sigs[this.shared.filterPrefix(streamId)], type); if (!sigCheck) { return reject({ code: 1220, reason: (this.inputs ? "Input" : "Output") + " Signature Incorrect", }); } } } } resolve(stream); }); } signatureCheck(streamId, stream, nhpkCheck, nhpkCheckIO, reject) { const sigCheck = (authority) => this.shared.signatureCheck(authority.public, this.entry.$sigs[this.shared.filterPrefix(streamId)], authority.type); const isLedgerAuthSignatures = ActiveDefinitions.LedgerTypeChecks.isLedgerAuthSignatures(this.entry.$sigs[this.shared.filterPrefix(streamId)]); if (isLedgerAuthSignatures) { const sigStreamKeys = Object.keys(this.entry.$sigs[this.shared.filterPrefix(streamId)]); const authorities = stream.meta.authorities.length; if (sigStreamKeys.length > authorities) { return reject({ code: 1225, reason: (this.inputs ? "Input" : "Output") + " Incorrect Signature List Length", }); } const sigCheck = sigStreamKeys.every((sigStream) => { if (nhpkCheck) { const nhpk = false; if (!nhpk) { return reject({ code: 1230, reason: (this.inputs ? "Input" : "Output") + " Security Hardened Key Transactions Only", }); } } else { const signature = this.entry.$sigs[this.shared.filterPrefix(streamId)][sigStream]; const authCheck = stream.meta.authorities.some((authority) => { if (authority.hash === sigStream) { return this.shared.signatureCheck(authority.public, signature, authority.type); } else { return false; } }); return authCheck; } }); if (!sigCheck) { } } else { const authorityCheck = stream.meta.authorities.some((authority) => { const nhpk = nhpkCheckIO[this.shared.getLabelIOMap(this.inputs, streamId)].$nhpk; if (nhpkCheck && !nhpk) { return reject({ code: 1230, reason: (this.inputs ? "Input" : "Output") + " Security Hardened Key Transactions Only", }); } if (authority.hash && sigCheck(authority)) { this.entry.$sigs[this.shared.filterPrefix(streamId)] = { [authority.hash]: this.entry.$sigs[this.shared.filterPrefix(streamId)], }; return true; } else { return false; } }); if (!authorityCheck) { return reject({ code: 1220, reason: (this.inputs ? "Input" : "Output") + " Signature Incorrect", }); } } } } //# sourceMappingURL=permissionsChecker.js.map