async def fetchAvatar(self, ipfsop): avatarServiceId = self.ipid.didUrl(path='/avatar') service = await self.ipid.searchServiceById(avatarServiceId) if service: avatarPath = IPFSPath(service.endpoint) if not avatarPath.valid: log.debug(f'Invalid avatar for peer {self.peerId}') self._avatarPath = avatarPath statInfo = StatInfo( await ipfsop.objStat(str(avatarPath), timeout=15) ) if not statInfo.valid or statInfo.dataLargerThan( kilobytes(768)): log.debug(f'Invalid avatar for peer {self.peerId}') return await ipfsop.ctx.pin(str(avatarPath), qname='ipid-avatar') log.debug( f'Getting avatar for peer {self.peerId} from {avatarPath}') image = await getImageFromIpfs(str(avatarPath)) if image and not image.isNull(): self._avatarImage = image else: log.debug(f'Could not fetch avatar for peer {self.peerId}')
async def findIcon(self, ipfsop, ipfsPath, rscStat, mimeType, maxIconSize=kilobytes(512)): icon = None statInfo = StatInfo(rscStat) if statInfo.valid and mimeType.isImage: if statInfo.dataSmallerThan(maxIconSize): await ipfsop.sleep() data = await ipfsop.catObject(str(ipfsPath), timeout=5) if data: icon = getIconFromImageData(data) else: icon = getMimeIcon('image/x-generic') elif mimeType.isDir: favIcon = await getFavIconFromDir(ipfsop, ipfsPath) if favIcon: icon = favIcon else: icon = getMimeIcon('inode/directory') else: await ipfsop.sleep() icon = getIconFromMimeType(mimeType) if icon is None: icon = getIcon('unknown-file.png') return icon
async def getIconFromIpfs(ipfsop, ipfsPath, scaleWidth=None, sizeMax=kilobytes(256), timeout=10): """ We cache the icons that we got out of the IPFS repo by their path Max icons cached is set by 'ipfsIconsCacheMax' in the app object """ app = QApplication.instance() iconsCache = app.ipfsIconsCache if ipfsPath in iconsCache: # Already cached return iconsCache[ipfsPath] if len(iconsCache) >= app.ipfsIconsCacheMax: # FIFO 1/8 for icount in range(0, int(app.ipfsIconsCacheMax / 8)): out = list(iconsCache.keys())[0] del iconsCache[out] try: mimeType, stat = await app.rscAnalyzer(ipfsPath) if not mimeType or not stat: return None statInfo = StatInfo(stat) if not statInfo.valid or statInfo.dataLargerThan(sizeMax): return None elif not mimeType.isImage: return None imgData = await ipfsop.waitFor(ipfsop.client.cat(ipfsPath), timeout) if not imgData: return None icon = getIconFromImageData(imgData, scaleWidth=scaleWidth) if icon: iconsCache[ipfsPath] = icon return icon except BaseException: return None
async def registerFromIdent(self, ipfsop, sender, iMsg): profile = ipfsop.ctx.currentProfile log.debug(f'registerFromIdent ({iMsg.peer}): ' f'DID: {iMsg.personDid}, handle: {iMsg.iphandle}') try: inGraph = await profile.dagNetwork.byDid(iMsg.personDid) except Exception: # network dag not ready .. log.debug(f'registerFromIdent {iMsg.personDid}: ' 'network DAG not loaded yet ?') return if not inGraph: if isinstance(iMsg, PeerIdentMessageV4) and \ sender != ipfsop.ctx.node.id: pubKeyPem = await ipfsop.rsaPubKeyCheckImport( iMsg.defaultRsaPubKeyCid) if not pubKeyPem: log.debug( f'Invalid RSA pub key .. {iMsg.defaultRsaPubKeyCid}') return sigBlob = await ipfsop.catObject(iMsg.pssSigCurDid) if sigBlob is None: log.debug( f'Cannot get pss SIG {iMsg.pssSigCurDid}') return if not await ipfsop.ctx.rsaExec.pssVerif( iMsg.personDid.encode(), sigBlob, pubKeyPem ): log.debug(f'Invalid PSS sig for peer {sender}') return else: log.debug(f'Valid PSS sig for {sender} !') peerValidated = False personDid = iMsg.personDid if not ipidFormatValid(personDid): log.debug('Invalid DID: {}'.format(personDid)) return inProgress = self._didAuthInp.get(personDid, False) if inProgress is True: log.debug(f'registerFromIdent {iMsg.personDid}: ' f'authentication in progress') return self._didAuthInp[personDid] = True try: mType, stat = await self.app.rscAnalyzer(iMsg.iphandleqrpngcid) except Exception: log.debug('Cannot stat QR: {}'.format(iMsg.iphandleqrpngcid)) self._didAuthInp[personDid] = False return else: statInfo = StatInfo(stat) if not statInfo.valid or statInfo.dataLargerThan( kilobytes(512)) or not mType or not mType.isImage: log.debug('Invalid stat for QR: {}'.format( iMsg.iphandleqrpngcid)) self._didAuthInp[personDid] = False return if not await self.validateQr( iMsg.iphandleqrpngcid, iMsg) is True: log.debug('Invalid QR: {}'.format(iMsg.iphandleqrpngcid)) peerValidated = False self._didAuthInp[personDid] = False return else: log.debug('Ident QR {qr} for {peer} seems valid'.format( qr=iMsg.iphandleqrpngcid, peer=iMsg.peer)) peerValidated = True await ipfsop.ctx.pin(iMsg.iphandleqrpngcid) # Load the IPID loadAttempts = cGet('peers.didLoadAttempts') for attempt in range(0, loadAttempts): ipid = await self.app.ipidManager.load( personDid, localIdentifier=(iMsg.peer == ipfsop.ctx.node.id) ) if ipid: break if not ipid: log.debug(f'Cannot load DID: {personDid}') self._didAuthInp[personDid] = False return async with self.lock.writer_lock: piCtx = self.getByHandle(iMsg.iphandle) if not piCtx: log.debug(f'Creating new PeerIdentityCtx for ' f'{iMsg.iphandle} ({personDid})') piCtx = PeerIdentityCtx( self.ctx, iMsg.peer, iMsg.iphandle, ipid, validated=peerValidated ) ipid.sChanged.connectTo(partialEnsure( self.onPeerDidModified, piCtx)) piCtx.sStatusChanged.connectTo(partialEnsure( self.peerModified.emit, piCtx)) piCtx.ident = iMsg if not piCtx.authFailedRecently: ensure(self.didPerformAuth(piCtx, iMsg)) self._byHandle[iMsg.iphandle] = piCtx else: # This peer is already registered in the network graph # What we ought to do here is just to refresh the DID document async with self.lock.writer_lock: piCtx = self.getByHandle(iMsg.iphandle) if piCtx: self._byPeerId[piCtx.peerId] = piCtx piCtx.ident = iMsg await piCtx.ipid.refresh() await self.peerModified.emit(piCtx) await self.changed.emit()
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 registerFromIdent(self, op, iMsg): # iMsg is a PeerIdentMessage if iMsg.peer not in self.byPeerId: peerValidated = False now = int(time.time()) avgPing = await op.waitFor(op.pingAvg(iMsg.peer, count=2), 5) personDid = iMsg.personDid if not ipidFormatValid(personDid): log.debug('Invalid DID: {}'.format(personDid)) return try: mType, stat = await self.app.rscAnalyzer(iMsg.iphandleqrpngcid) except Exception: log.debug('Invalid QR: {}'.format(iMsg.iphandleqrpngcid)) else: statInfo = StatInfo(stat) if not statInfo.valid or statInfo.dataLargerThan( kilobytes(512)) or not mType or not mType.isImage: log.debug('Invalid stat for QR: {}'.format( iMsg.iphandleqrpngcid)) return if not await self.validateQr( iMsg.iphandleqrpngcid, iMsg) is True: log.debug('Invalid QR: {}'.format(iMsg.iphandleqrpngcid)) peerValidated = False else: log.debug('Ident QR {qr} for {peer} seems valid'.format( qr=iMsg.iphandleqrpngcid, peer=iMsg.peer)) peerValidated = True ensure(op.ctx.pin(iMsg.iphandleqrpngcid)) # Load the IPID ipid = await self.app.ipidManager.load( personDid, initialCid=iMsg.personDidCurCid, track=True ) if not ipid: log.debug('Cannot load DID: {}'.format(personDid)) return async with self.lock: pCtx = PeerCtx(self.ctx, iMsg.peer, iMsg, ipid, pingavg=avgPing if avgPing else 0, pinglast=now if avgPing else 0, validated=peerValidated ) ipid.sChanged.connectTo(partialEnsure( self.onPeerDidModified, pCtx)) pCtx.sInactive.connectTo(self.onUnresponsivePeer) ensure(self.didPerformAuth(pCtx)) self._byPeerId[iMsg.peer] = pCtx ensureLater(60, pCtx.watch) await self.peerAdded.emit(iMsg.peer) else: # This peer is already registered # What we ought to do here is just to refresh the DID document async with self.lock: pCtx = self.getByPeerId(iMsg.peer) if pCtx: log.debug('Updating ident for peer {}'.format(iMsg.peer)) pCtx.ident = iMsg log.debug('Refreshing DID: {}'.format(pCtx.ipid)) await pCtx.ipid.refresh() await self.peerModified.emit(iMsg.peer) await self.changed.emit()