Ejemplo n.º 1
0
    async def onPeerAuthenticated(self, ipfsop, piCtx: PeerIdentityCtx):
        """
        DID auth was successfull for a peer, store the handle
        and DID in the graph, and create the initial IPLD
        link for the DID document (diddoc)
        """

        profile = ipfsop.ctx.currentProfile
        did = piCtx.ipid.did
        handle = str(piCtx.spaceHandle)

        async with profile.dagNetwork as g:
            pData = g.root['peers'].setdefault(piCtx.peerId, {})

            if handle in pData:
                # This handle is already registered for this peer
                # This can happen if a peer created 2 IPIDs with
                # the same handle after losing the profile's data

                log.debug(f'{handle} already in the graph, overwriting')

            pData[handle] = {
                'did': did,
                'diddoc': {},
                'dateregistered': utcDatetimeIso(),
                'datedidauth': utcDatetimeIso(),
                'datelastseen': utcDatetimeIso(),
                'flags': 0
            }

            # Link the DID document in the graph
            if piCtx.ipid.docCid:
                pData[handle]['diddoc'] = g.ipld(piCtx.ipid.docCid)

            log.debug(f'Authenticated {handle} ({did}) in the peers graph')
Ejemplo n.º 2
0
    async def createIdentity(self,
                             ipfsop,
                             peered=False,
                             personDid=None,
                             setAsCurrent=True,
                             iphandle=None,
                             bio=None,
                             flags=None):
        # You never know ..

        uid = str(uuid.uuid4())
        while uid in self.root['identities'].keys():
            uid = str(uuid.uuid4())

        pFlags = flags if isinstance(flags, int) else 0

        qr = await self.encodeIpHandleQr(iphandle, personDid)

        bioEntry = await ipfsop.addString(bio if bio else '# Bio')

        identity = {
            'email':
            None,
            'flags':
            pFlags,
            'iphandle':
            iphandle,
            'iphandleqr': {
                'png': self.mkLink(qr)
            },
            'vplanet':
            'Earth',

            # DIDS
            'personDid':
            personDid,
            'following': {},
            'avatar':
            self.mkLink(
                await
                ipfsop.importQtResource('/share/icons/ipfs-cube-64.png')),
            'bio':
            self.mkLink(bioEntry),
            'crypto': {},
            'datecreated':
            utcDatetimeIso(),
            'datemodified':
            utcDatetimeIso()
        }

        async with self as dag:
            dag.root['identities'][uid] = identity

            if setAsCurrent:
                dag.root['currentIdentityUid'] = uid

        log.debug('Created identity', uid)
        return uid, dag.root['identities'][uid]
Ejemplo n.º 3
0
    async def a_iObjectCreate(self, app, loop, oid, obj):
        ipfsop = app.ipfsOperatorForLoop(loop)
        curProfile = ipfsop.ctx.currentProfile

        try:
            # Get the IPID and private key
            ipid = await curProfile.userInfo.ipIdentifier()
            assert ipid is not None

            passport = await ipid.searchServiceById(
                ipid.didUrl(path='/passport'))

            rsaAgent = await ipid.rsaAgentGet(ipfsop)
            privKey = await rsaAgent._privateKey()

            assert privKey is not None

            # Initial DAG structure
            dag = {"@context": {"@vocab": gLdBaseUri, "@base": gLdBaseUri}}

            dag.update(dict(obj))

            if passport:
                # Author
                dag['author'] = {
                    '@type': 'Person',
                    '@id': passport.endpoint['me'].get('@id')
                }

            # Dates
            if 'dateCreated' not in dag:
                dag['dateCreated'] = utcDatetimeIso()
            if 'dateModified' not in dag:
                dag['dateModified'] = utcDatetimeIso()

            # JSON-LD signature
            signed = jsonldsig.sign(dag, privKey.exportKey())

            # Store in IPFS
            cid = await ipfsop.dagPut(signed)

            # Notify the RDF service
            await runningApp().s.rdfStore(IPFSPath(cid))

            # Return the CID of the object
            return cid
        except Exception as err:
            log.debug(f'Error creating object: {err}')
            return ''
Ejemplo n.º 4
0
    async def writeStatus(self):
        client = self.daemonClient

        try:
            ident = await client.core.id()

            if self.process and ident:
                # Remember orjson.dumps returns bytes

                async with aiofiles.open(str(self.statusPath), 'w+b') as fd:
                    await fd.write(orjson.dumps({
                        'ident': ident,
                        'pid': self.process.pid,
                        'status': self.process.status(),
                        'date': utcDatetimeIso()
                    }))

                return True
            else:
                raise Exception(
                    "Could not get ident, what's going on ?")
        except aioipfs.APIError:
            return False
        except Exception as e:
            self.message(f'Status write error: {e}, postponing')
            return False
Ejemplo n.º 5
0
 async def make(self,
                ipfsop,
                message='',
                links=[],
                attachments=[],
                date=None,
                type=CHATMSG_TYPE_MESSAGE,
                level=0):
     msgDate = date if date else utcDatetimeIso()
     msg = ChatRoomMessage({
         '@context':
         await ipfsop.ldContextJson('messages/ChatRoomMessage'),
         'msgtype':
         ChatRoomMessage.TYPE,
         'version':
         1,
         'ChatRoomMessage': {
             'chatmsgtype': type,
             'date': msgDate,
             'message': message,
             'links': links,
             'attachments': attachments,
             'level': level
         }
     })
     return msg
Ejemplo n.º 6
0
 async def make(self,
                ipfsop,
                jwsCid,
                links=[],
                attachments=[],
                date=None,
                type=CHATMSG_TYPE_MESSAGE,
                command='MSG',
                params=[],
                level=0):
     msgDate = date if date else utcDatetimeIso()
     msg = ChatRoomMessage({
         'msgtype': ChatRoomMessage.TYPE,
         'version': 1,
         'ChatRoomMessage': {
             'uid': uid4(),
             'jwsTokenCid': jwsCid,
             'chatmsgtype': type,
             'date': msgDate,
             'command': command,
             'params': params,
             'links': links,
             'attachments': attachments,
             'level': level
         }
     })
     return msg
Ejemplo n.º 7
0
    def make():
        msg = SparQLHeartbeatMessage({
            'msgtype': SparQLHeartbeatMessage.TYPE,
            'version': 1,
            'date': utcDatetimeIso(),
            'graphs': []
        })

        return msg
Ejemplo n.º 8
0
    def pyramidAdd(self, pyramidPath, path, unique=False, type='mark'):
        sec, category, name = self.pyramidAccess(pyramidPath)

        if not sec:
            return False

        if type == 'mark':
            key = pyramidsMarksKey
        elif type == 'inputmark':
            key = pyramidsInputMarksKey
        else:
            raise ValueError('Invalid mark type')

        if name in sec[pyramidsKey]:
            pyramid = sec[pyramidsKey][name]
            count = len(pyramid[key])

            if count >= pyramid.get('maxhashmarks', pyramidMaxHmarksDefault):
                pyramid[key].pop(0)

            # Don't register something that's already there
            if unique:
                for item in pyramid[key]:
                    _marksPaths = item.keys()
                    if path in _marksPaths:
                        log.debug(f'Hashmark {path} already in pyramid {name}')
                        return False

            exmark = self.find(path)

            if exmark:
                mark = copy.copy(exmark)
            else:
                datenowiso = utcDatetimeIso()
                mark = IPFSHashMark.make(
                    path,
                    title='{0}: #{1}'.format(name, count + 1),
                    description=pyramid['description'],
                    datecreated=datenowiso,
                    share=False,
                    pinSingle=True,
                    icon=pyramid['icon'],
                )
            pyramid[key].append(mark.data)
            pyramid['latest'] = path

            self.pyramidAddedMark.emit(pyramidPath, mark, type)
            self.pyramidChanged.emit(pyramidPath)

            if type == 'mark':
                self.pyramidCapstoned.emit(pyramidPath)

            self.changed.emit()

            return True

        return False
Ejemplo n.º 9
0
    async def initDag(self, ipfsop):
        now = utcDatetimeIso()

        return {
            'identities': {},
            'followingGlobal': {},
            'currentIdentityUid': None,
            'datecreated': now,
            'datemodified': now
        }
Ejemplo n.º 10
0
 def make(name, ipfsMPath, title=None, ipnsResolveFrequency=3600):
     datecreated = utcDatetimeIso()
     mapping = QuickAccessMapping({
         'name': name,
         'mappedto': str(ipfsMPath),
         'ipnsresolvefreq': ipnsResolveFrequency,
         'datecreated': datecreated,
         'hotkey': None,
         'title': title if title else name
     })
     return mapping
Ejemplo n.º 11
0
 async def addServiceCollection(self, ipfsop, name):
     return await self.addServiceContexted({
         'id': self.didUrl(
             path=posixpath.join('/collections', name)
         ),
         'type': IPService.SRV_TYPE_COLLECTION,
     }, context='ObjectsCollectionEndpoint',
         endpoint={
         'name': name,
         'created': utcDatetimeIso(),
         'objects': []
     }, publish=True)
Ejemplo n.º 12
0
 async def make(self, ipfsop, status):
     msg = ChatStatusMessage({
         '@context':
         await ipfsop.ldContextJson('messages/ChatStatusMessage'),
         'msgtype':
         ChatStatusMessage.TYPE,
         'ChatStatusMessage': {
             'status': status,
             'date': utcDatetimeIso()
         }
     })
     return msg
Ejemplo n.º 13
0
    async def addServiceVideoCall(self, ipfsop, roomName):
        servicePath = posixpath.join('videocall', roomName)

        return await self.addServiceContexted({
            'id': self.didUrl(
                path=servicePath
            ),
            'type': IPService.SRV_TYPE_VIDEOCALL,
        }, context='DwebVideoCallServiceEndpoint',
            endpoint={
            'roomName': roomName,
            'created': utcDatetimeIso(),
            'p2pEndpoint': ipfsop.p2pEndpoint(servicePath)
        }, publish=True)
Ejemplo n.º 14
0
    async def ipfsSave(self, op):
        self.debug('Saving (acquiring lock)')

        async with self.wLock:
            prevCid = self.dagCid
            history = self.dagMeta.setdefault('history', [])
            maxItems = self.dagMetaMaxHistoryItems

            if prevCid and self._autoPrevious:
                # Create a 'previous' IPLD link
                self.dagRoot['previous'] = self.mkLink(prevCid)

            if isinstance(self.dagRoot, dict) and self._autoUpdateDates:
                # Update 'datemodified' if enabled
                if 'datemodified' in self.dagRoot:
                    self.dagRoot['datemodified'] = utcDatetimeIso()

            # We always PIN the latest DAG and do a pin update using the
            # previous item in the history

            cid = await op.dagPut(self.dagRoot, pin=True,
                                  offline=self._offline)
            if cid is not None:
                if prevCid is not None and prevCid not in history:
                    if len(history) > maxItems:
                        # Purge old items
                        [history.pop() for idx in range(
                            0, len(history) - maxItems)]

                    history.insert(0, prevCid)

                    if 0:
                        # pinUpdate randomly blocks so
                        # disable it for now
                        await op.pinUpdate(
                            prevCid, cid, unpin=self._unpinOnUpdate)

                # Save the new CID and update the metadata
                await self.saveNewCid(cid)
            else:
                # Bummer
                self.debug('DAG could not be built')
                return False

        self.debug('Saved (wlock released)')
        return True
Ejemplo n.º 15
0
    def make(iGraphList):
        msg = RDFGraphsExchangeMessage({
            'msgtype': RDFGraphsExchangeMessage.TYPE,
            'version': 1,
            'date': utcDatetimeIso(),
            'graphs': []
        })
        for name, graph in iGraphList.items():
            if not graph.cid:
                continue

            msg.data['graphs'].append({
                'graphExportCid': graph.cid,
                'graphUri': str(graph.identifier),
                'format': 'ttl'
            })

        return msg
Ejemplo n.º 16
0
async def importHashmark(mark, source):
    url = mark.get('url')
    datecreated = mark.get('datecreated', utcDatetimeIso())

    log.debug('Importing {u} ({date})'.format(u=url, date=datecreated))

    return await database.hashmarkAdd(
        url,
        title=mark.get('title'),
        description=mark.get('description'),
        comment=mark.get('comment'),
        category=mark.get('category'),
        icon=mark.get('icon'),
        datecreated=datecreated,
        tags=mark.get('tags', []),
        objtags=mark.get('objtags', []),
        source=source,
        schemepreferred=mark.get('schemepreferred'))
Ejemplo n.º 17
0
    def make(path,
             title=None,
             datecreated=None,
             share=False,
             description='',
             comment='',
             datasize=None,
             cumulativesize=None,
             srcplanet='Earth',
             tags=None,
             numlinks=None,
             icon=None,
             pinSingle=False,
             pinRecursive=False):
        if datecreated is None:
            datecreated = utcDatetimeIso()

        mData = IPFSHashMark({
            path: {
                'metadata': {
                    'title': title,
                    'description': description,
                    'comment': comment,
                    'srcplanet': srcplanet,
                    'datasize': datasize,
                    'cumulativesize': cumulativesize,
                    'numlinks': numlinks,
                },
                'pin': {
                    'single': pinSingle,
                    'recursive': pinRecursive,
                    'filters': []
                },
                'datecreated': datecreated,
                'tscreated': int(time.time()),
                'icon': icon,
                'share': share,
                'tags': tags if tags else [],
            }
        })

        mData.path = path
        return mData
Ejemplo n.º 18
0
    def make(name,
             description='Pyramid',
             icon=None,
             ipnskey=None,
             internal=False,
             publishdelay=0,
             comment=None,
             flags=0,
             allowoffline=False,
             lifetime='48h',
             maxhashmarks=pyramidMaxHmarksDefault,
             type=None,
             extra=None):

        extraOpts = extra if isinstance(extra, dict) else {}
        datecreated = utcDatetimeIso()
        pyramid = MultihashPyramid({
            name: {
                'ipns': {
                    'publishtokey': ipnskey,
                    'publishdelay': publishdelay,
                    'allowoffline': allowoffline,
                    'ttl': None,
                    'lifetime': lifetime
                },
                'uuid': str(uuid.uuid4()),
                'datecreated': datecreated,
                'icon': icon,
                'latest': None,
                'description': description,
                'comment': comment,
                'type': type if type else MultihashPyramid.TYPE_STANDARD,
                'internal': internal,
                'maxhashmarks': maxhashmarks,
                'flags': flags,
                'extra': extraOpts,
                pyramidsInputMarksKey: [],
                pyramidsMarksKey: []  # list of hashmarks in the pyramid
            }
        })

        pyramid.name = name
        return pyramid
Ejemplo n.º 19
0
    async def didPing(self, ipfsop, request):
        async with self.throttler:
            curProfile = ipfsop.ctx.currentProfile

            if not curProfile:
                return await self.msgError()

            try:
                js = await request.json()
                if not js or not isinstance(js, dict):
                    return await self.msgError()

                if not jsonSchemaValidate(js, pingReqSchema):
                    raise Exception('Invalid req schema')

                token = js.get('ident_token')
                if token != self.service._token:
                    self.message(f'didPing: Invalid token {token}')
                    raise Exception('Invalid token')
            except Exception:
                return await self.msgError()

            did = js.get('did')
            self.message('Received didPing request for DID: {}'.format(
                did))

            currentIpid = await curProfile.userInfo.ipIdentifier()

            if not currentIpid or did != currentIpid.did:
                return await self.msgError(error='Invalid DID')

            return web.json_response({
                'didpong': {
                    'version': 0,
                    did: {
                        'userstatus': curProfile.status,
                        'userstatusmessage': curProfile.statusMessage,
                        'date': utcDatetimeIso()
                    }
                }
            })
Ejemplo n.º 20
0
 def make(revision: str, dagClass: str, dagCid: str, dagNet: str,
          dagName: str, dagUid: str, signerPubKeyCid: str, mDagCid: str,
          serviceToken: str, snakeOil: str):
     return DAGExchangeMessage({
         'msgtype': DAGExchangeMessage.TYPE,
         'version': 2,
         'date': utcDatetimeIso(),
         'rev': revision,
         'exchange': {
             'dagCid': dagCid,
             'megaDagCid': mDagCid,
             'dagClass': dagClass,
             'dagNet': dagNet,
             'dagName': dagName,
             'dagUid': dagUid,
             'signerPubKeyCid': signerPubKeyCid,
             'session': {
                 'serviceToken': serviceToken,
                 'snakeOil': snakeOil
             }
         }
     })
Ejemplo n.º 21
0
    async def trace(self, iPath: IPFSPath, graphs: list):
        """
        Main history API (trace an object in the history graph)
        """
        h = hashlib.sha1()
        h.update(iPath.ipfsUrl.encode())
        nodeId = f'io:{h.hexdigest()}'

        doc = {
            '@context': {
                '@vocab': 'ips://galacteek.ld/'
            },
            '@type': 'GraphTrail',
            '@id': nodeId,
            'dateCreated': utcDatetimeIso(),
            'ipfsPath': str(iPath),
            'outputGraphs': graphs
        }

        result = list(self.hGraph.predicate_objects(nodeId))

        if result:
            return

        try:
            ex = await jsonld.expand(doc)

            graph = BaseGraph()

            graph.parse(data=orjson.dumps(ex).decode(), format='json-ld')

            # Could be optimized using another rdflib method
            self.hGraph.parse(await graph.ttlize())

            ttl = await self.hGraph.ttlize()
            print(ttl.decode())
        except Exception as err:
            log.debug(f'Error recording {iPath} in history: {err}')
Ejemplo n.º 22
0
    async def make(ipfsop, channel, pubKeyCid, encType='rsa-aes256-cbc'):
        curProfile = ipfsop.ctx.currentProfile
        try:
            hasher = hashlib.sha3_384()
            hasher.update('{peer}_{uid}'.format(
                peer=ipfsop.ctx.node.id,
                uid=doubleUid4()).encode())
            topic = encChatChannelTopic(hasher.hexdigest())
        except Exception:
            return None

        if encType == 'rsa-aes256-cbc':
            enc = {
                'etype': encType,
                'pubKeyCid': await ipfsop.rsaAgent.pubKeyCid()
            }
        elif encType == 'curve25519':
            enc = {
                'etype': encType,
                'pubKeyCid': pubKeyCid
            }
        else:
            enc = {}

        return ChatToken({
            'version': 1,
            'type': 'pubchattoken',
            't': {
                'date': utcDatetimeIso(),
                'did': curProfile.userInfo.personDid,
                'channel': channel,
                'psTopic': topic,
                'pubKeyCid': await ipfsop.rsaAgent.pubKeyCid(),
                'cpass': secrets.token_hex(8),
                'enc': enc
            }
        })
Ejemplo n.º 23
0
 async def initDag(self, ipfsop):
     return {
         'peers': {},
         'datecreated': utcDatetimeIso(),
         'datemodified': utcDatetimeIso()
     }
Ejemplo n.º 24
0
    async def seed(self,
                   ipfsop,
                   name: str,
                   objectsInfo: list,
                   section='all',
                   description='',
                   comment='',
                   revision=0,
                   icon=None,
                   authorName=None,
                   authorEmail=None,
                   authorDid=None,
                   creatorDid=None,
                   creatorIpHandle=None,
                   licenseCid=None,
                   licenseName=None,
                   manifestCid=None,
                   cumulativeSize=0,
                   pinReqMin=10,
                   pinReqTarget=20,
                   tags=[],
                   keywords=[],
                   refid=None):

        profile = ipfsop.ctx.currentProfile

        ipid = await profile.userInfo.ipIdentifier()
        if not ipid:
            raise Exception('No IPID found')

        uid = doubleUid4()
        signedUid = await ipfsop.rsaAgent.pssSign64(uid.encode())

        preSeed = {
            'formatv': 0,
            'seed': {
                'name': name,
                'uid': uid,
                'revision': revision,
                'tags': tags,
                'dateCreated': utcDatetimeIso(),
                'dateModified': utcDatetimeIso(),
                'icon': self.ipld(icon) if icon else None,
                'license': {
                    'name': licenseName,
                    'link': self.ipld(licenseCid) if licenseCid else None
                },
                'author': {
                    'name': authorName,
                    'email': authorEmail,
                    'did': authorDid
                },
                'wallets': {},
                'creatorDid': creatorDid,
                'creatorIpHandle': creatorIpHandle,
                'description': description,
                'comment': comment,
                'manifests': [],
                'pinRequest': {
                    'minproviders': pinReqMin,
                    'targetproviders': pinReqTarget,
                    'p2pPinServiceUrl': None
                },
                'objects': objectsInfo,
                'cumulativeSize': cumulativeSize
            },
            'parent': None,
            'signatures': {
                'pss_uid': signedUid,
            }
        }

        if manifestCid:
            preSeed['seed']['manifests'].append(self.ipld(manifestCid))

        seedCid = await ipfsop.dagPut(preSeed, pin=True)

        if seedCid:
            try:
                cidSign = await ipfsop.rsaAgent.pssSign(seedCid.encode())
                if not cidSign:
                    raise Exception('Could not sign CID')

                cidSignEntry = await ipfsop.addBytes(cidSign)

                if not cidSignEntry:
                    raise Exception('Could not import CID signature')

                async with self as dagw:
                    s = dagw.root['c']['seeds'].setdefault(section, {})
                    cur = s.setdefault(name, [])

                    # We store some metadata to make it easier to search
                    # without loading the full seed DAG
                    cur.append({
                        '_metadata': {
                            'datecreated': utcDatetimeIso(),
                            'dateexpires': None,
                            'icon': self.ipld(icon) if icon else None,
                            'tags': tags,
                            'keywords': keywords,
                            'refid': refid,
                            'pss_cid_link': dagw.ipld(cidSignEntry)
                        },
                        'seedlink': dagw.ipld(seedCid)
                    })

                    # Regenerate an iteration UID
                    dagw.root['params']['revnum'] += 1
                    dagw.root['params']['seediteruid'] = doubleUid4()

                    # Sign the iteration

                    signedIter = await ipfsop.rsaAgent.pssSign64(
                        dagw.root['params']['seediteruid'].encode())

                    dagw.root['signatures']['iteration'] = signedIter

                await self.sSeedAdded.emit(seedCid)

                return seedCid
            except Exception as err:
                log.debug(f'Error creating seed: {err}')
                raise err
Ejemplo n.º 25
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