예제 #1
0
    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}')
예제 #2
0
    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
예제 #3
0
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
예제 #4
0
    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()
예제 #5
0
    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
예제 #6
0
    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()