async def validateQr(self, ipfsop, qrCid, iMsg): validCodes = 0 try: codes = await self.app.rscAnalyzer.decodeQrCodes(qrCid) if not codes: # QR decoder not available, or invalid QR return False if len(codes) not in range(2, 4): return False for code in codes: if isinstance(code, IPFSPath): if code.isIpns and str(code) == joinIpns(iMsg.peer): validCodes += 1 if code.isIpfs: computed = await ipfsop.hashComputeString( iMsg.iphandle) if computed['Hash'] == stripIpfs(code.objPath): validCodes += 1 elif isinstance(code, str) and ipidFormatValid(code) and \ code == iMsg.personDid: validCodes += 1 except Exception as e: log.debug('QR decode error: {}'.format(str(e))) return False else: # Just use 3 min codes here when we want the DID to be required return validCodes >= 2 return False
async def rpsUnpin(self, ipfsop, service, ipfsPath: IPFSPath): resolved = await ipfsop.resolve(ipfsPath.objPath, recursive=True) if not resolved: return False cid = stripIpfs(resolved) return await ipfsop.pinRemoteRemove(service.serviceName, cid=[cid])
def path(self, rscPath): if isinstance(rscPath, str) and isIpfsPath(rscPath): path = stripIpfs(rscPath.rstrip('/')).replace('/', '_') comps = path.split('/') if len(comps) > 0: containerId = comps[0][0:8] containerPath = os.path.join(self.metaDbPath, containerId) metaPath = os.path.join(containerPath, path) return containerPath, metaPath, os.path.exists(metaPath) return None, None, False
async def onIpldExplore(self, *args): """ Open the IPLD explorer application for the current clipboard item """ if not self.item: return mark = await database.hashmarksByObjTagLatest('#dapp-ipldexplorer') if mark: link = os.path.join( mark.path, '#', 'explore', stripIpfs(self.item.path)) self.app.mainWindow.addBrowserTab().browseFsPath(link) else: messageBox('IPLD explorer hashmark not found')
async def load(self, ipfsop, pin=True, initialCid=None, resolveTimeout=30): if not initialCid: resolved = await self.resolve() if not resolved: self.message('Failed to resolve ?') return False dagCid = stripIpfs(resolved['Path']) else: self.message('Loading from initial CID: {}'.format(initialCid)) dagCid = initialCid self.message('DID resolves to {}'.format(dagCid)) if self.docCid == dagCid: # We already have this one self.message('DID document already at latest iteration') return False self._lastResolve = loopTime() if pin is True: await ipfsop.ctx.pin(dagCid, qname='ipid') self.message('Load: IPNS key resolved to {}'.format(dagCid)) doc = await ipfsop.dagGet(dagCid) if doc: self._document = doc self._latestModified = doc.get('modified') self.docCid = dagCid await self.sChanged.emit(dagCid) if self.local: # Local IPID: propagate did services async for service in self.discoverServices(): await self.sServiceAvailable.emit(self, service) # Graph it await self.rdfPush() return True return False
def hashmark(self, path): hashV = stripIpfs(path) hit = self.findByHash(hashV) title = hit.get('title', iUnknown()) if hit else hashV descr = hit.get('description', iUnknown()) if hit else '' type = hit.get('type') if hit else None pinSingle = (type == 'file') pinRecursive = (type == 'directory') ensure( addHashmarkAsync(path, title=title, description=descr, pin=pinSingle, pinRecursive=pinRecursive))
async def load(self, ipfsop, pin=True, initialCid=None, resolveTimeout=30): if not initialCid: resolved = await self.resolve(resolveTimeout=resolveTimeout) if not resolved: self.message('Failed to resolve ?') return False dagCid = stripIpfs(resolved['Path']) else: self.message('Loading from initial CID: {}'.format(initialCid)) dagCid = initialCid self.message('DID resolves to {}'.format(dagCid)) if self.docCid == dagCid: # We already have this one self.message('DID document already at latest iteration') return False self._lastResolve = time.time() if pin is True: await ipfsop.ctx.pin(dagCid, qname='ipid') self.message('Load: IPNS key resolved to {}'.format(dagCid)) doc = await ipfsop.dagGet(dagCid) if doc: self._document = doc self._latestModified = doc.get('modified') self.docCid = dagCid await self.sChanged.emit(dagCid) return True return False
def explore(self, path): hashV = stripIpfs(path) if hashV: self.app.mainWindow.explore(hashV)
async def link(self, ipfsop, peerId: str, dagUid: str, dagCid: str, signerPubKeyCid: str, local=False): self.debug(f'Branching for {peerId}') if not local: if not await ipfsop.pin(dagCid, recursive=False, timeout=120): self.debug(f'Branching for {peerId}: PIN {dagCid}: FAILED') return False else: self.debug(f'Branching for {peerId}: PIN {dagCid}: OK') pubKeyStatInfo = await ipfsop.objStatInfo(signerPubKeyCid) if not pubKeyStatInfo.valid or \ pubKeyStatInfo.dataLargerThan(kilobytes(32)): return False pubKeyPem = await ipfsop.catObject(signerPubKeyCid, timeout=10) if not pubKeyPem: raise Exception(f'Cannot fetch pubkey with CID: {signerPubKeyCid}') # Keep it await ipfsop.pin(signerPubKeyCid, recursive=False, timeout=5) valid = await ipfsop.waitFor(self.analyze(peerId, dagCid, pubKeyPem), 60) if not valid: self.debug(f'Invalid DAG: {dagCid}') return False else: self.debug(f'DAG is valid: {dagCid}') linkId = self.udbHash(peerId, dagUid) r = await self.resolve(f'nodes/{linkId}/link') self.debug(f'Branching for {peerId}: has {r}') if r and stripIpfs(r) == dagCid: self.debug(f'Branching for {peerId}: already at latest') return False # Link it async with self as dag: dag.root['nodes'][linkId] = { 'datebranched': utcDatetimeIso(), 'signerpubkey': self.ipld(signerPubKeyCid), 'link': self.ipld(dagCid) } dag.root['data']['aggiter_uid'] = str(uuid.uuid4()) sig = await ipfsop.ctx.rsaAgent.pssSign64( dag.root['data']['aggiter_uid'].encode()) if sig: dag.root['signatures']['aggiter'] = sig # Link OK return True
async def blogPost(self, ipfsop, title, msg, category=None, tags=None, author=None): async with self.edag: sHandle = self.profile.userInfo.spaceHandle username = sHandle.human uid = str(uuid.uuid4()) postName = titleToPostName(title.strip().lower()) exEntries = await self.blogEntries() if not postName or postName in exEntries: raise Exception('A blog post with this name already exists') now = datetime.now(timezone.utc) postObject = { 'blogpost': { 'authordid': self.profile.userInfo.personDid, 'body': msg, 'title': title, 'uuid': uid, 'postname': postName, # name of the post's DAG node 'tags': tags if tags else [], 'category': None, 'author': author if author else username, 'date_published': isoformat(now), 'date_modified': isoformat(now) } } # Create the DAG node for this post # Its view will be rendered later on self.dagBlog[postName] = {POST_NODEKEY: postObject} await ipfsop.sleep(2) await self.update() await ipfsop.sleep(1) result = await self.dagUser.resolve( posixIpfsPath.join(BLOG_NODEKEY, postName, 'view')) resolved = IPFSPath(result, autoCidConv=True) if isinstance(tags, list) and resolved.isIpfsRoot and resolved.valid: # Register the post by tag async with self.edag as dag: byTags = dag.root[BLOG_NODEKEY][TAGS_NODEKEY] for tag in tags: if tag is None: continue planet, ptag = tag.split('#') if not planet or not ptag: continue planet = planet.replace('@', '') byTags.setdefault(planet, {}) byTags[planet].setdefault(ptag, {'_posts': []}) byTags[planet][ptag]['_posts'].append({ 'name': postName, 'title': title, 'view': { '/': stripIpfs(str(resolved)) } }) byTags[planet][ptag]['index.html'] = await self.renderLink( 'usersite/bytag.html', contained=True, tag=tag, tagposts=byTags[planet][ptag]['_posts']) logUser.info('Your blog post is online') return True