async def resolve(self, ipfsop, resolveTimeout=None): resolveTimeout = resolveTimeout if resolveTimeout else \ cGet('resolve.timeout') if self.local: hours = cGet('resolve.cacheLifetime.local.hours') else: hours = cGet('resolve.cacheLifetime.default.hours') maxLifetime = hours * 3600 useCache = 'always' cache = 'always' self.message('DID resolve: {did} (using cache: {usecache})'.format( did=self.ipnsKey, usecache=useCache)) return await ipfsop.nameResolveStreamFirst( joinIpns(self.ipnsKey), count=1, timeout=resolveTimeout, useCache=useCache, cache=cache, cacheOrigin='ipidmanager', maxCacheLifetime=maxLifetime )
def wpRegisterFromConfig(app): """ Initialize all the configured web profiles """ cfgWpList = cGet('webProfiles') defaults = cfgWpList.get('defaultProfile') for wpName, config in cfgWpList.items(): if wpName == 'defaultProfile': continue otr = cGet(f'webProfiles.{wpName}.settings.offTheRecord') sName = cGet(f'webProfiles.{wpName}.storageName') wp = BaseProfile(defaults, otr=True if otr else False, storageName=sName, name=wpName, parent=app) wp.configure() app.webProfiles[wpName] = wp cSet(f'webProfiles.{wpName}', wp.config, merge=True, noCallbacks=True) configModRegCallback(onProfilesChanged)
async def loadDidFromGraph(self, ipfsop, peerId: str, did: str, sHandle: str): loadTimeout = cGet('peers.didLoadTimeout') loadAttempts = cGet('peers.didLoadAttempts') peersService = ipfsop.ctx.pubsub.byTopic(TOPIC_PEERS) for attempt in range(0, max(2, loadAttempts)): ipid = await self.app.ipidManager.load( did, track=True, timeout=loadTimeout, localIdentifier=(peerId == ipfsop.ctx.node.id) ) if not ipid: log.debug(f'Cannot load IPID: {did}, attempt {attempt}') await ipfsop.sleep(cGet('peers.didFail.sleepInterval')) continue else: break if not ipid: log.debug(f'Cannot load IPID: {did}, bailing out') self._didGraphLStatus.remove(did) return False piCtx = PeerIdentityCtx( self.ctx, sHandle.peer, str(sHandle), ipid, validated=True, authenticated=True ) ipid.sChanged.connectTo(partialEnsure( self.onPeerDidModified, piCtx)) piCtx.sStatusChanged.connectTo(partialEnsure( self.peerModified.emit, piCtx)) async with self.lock.writer_lock: self._byHandle[str(sHandle)] = piCtx if piCtx.peerId not in self._byPeerId: self._byPeerId[piCtx.peerId] = piCtx log.debug(f'Loaded IPID from graph: {did}') await self.peerAdded.emit(piCtx) await ipfsop.sleep(1) await peersService.sendIdentReq(piCtx.peerId) self._didGraphLStatus.remove(did) return True
async def publish(self, ipfsop, timeout=None): """ Publish the DID document to the IPNS key We always cache the record so that your DID is always resolvable whatever the connection state. :rtype: bool """ # Get config settings timeout = timeout if timeout else cGet('publish.ipns.timeout') autoRepublish = cGet('publish.autoRepublish') republishDelay = cGet('publish.autoRepublishDelay') ipnsLifetime = cGet('publish.ipns.lifetime') ipnsTtl = cGet('publish.ipns.ttl') if not self.docCid: return False if autoRepublish is True: # Auto republish for local IPIDs ensureLater( republishDelay, self.publish ) try: if await ipfsop.publish(self.docCid, key=self.ipnsKey, lifetime=ipnsLifetime, ttl=ipnsTtl, cache='always', cacheOrigin='ipidmanager', timeout=timeout): self.message('Published !') self.message( 'Published IPID {did} with docCid: {docCid}'.format( did=self.did, docCid=self.docCid)) return True else: self.message('Error publishing IPID with DID: {did}'.format( did=self.did)) return False except Exception as e: self.message(str(e)) return False
async def onDoubleClick(self, modItem, col, *args): if not isinstance(modItem, ConfigModuleItem): return mod = modItem.text(0) if modItem.childCount() == 0: self.setEnabled(False) for attr in configModLeafAttributes(mod): value = cGet(attr, mod=mod) if isinstance(value, int) or isinstance(value, float): item = QTreeWidgetItem(modItem) item.setText(0, attr) item.setText(1, str(value)) item.setData(1, ModRole, mod) item.setData(1, AttrRole, attr) item.setData(1, AttrTypeRole, type(value)) self.tree.openPersistentEditor(item, 1) modItem.setExpanded(True) self.setEnabled(True)
async def createMailBox(self, label='default', select=False, default=False, iconCid=None): defaultIconCid = cGet('bmAccount.defaultIconCid') key, mailDir = await self.app.s.bmService.mailer.createMailBox() log.debug(f'Create BM: {key}, {mailDir}') if not key: return None, None, None await mailDir.storeWelcome() if select: await self.selectMailBox(key) bmMailBox = await bmMailBoxRegister( key, label, key, default=default, iconCid=iconCid if iconCid else defaultIconCid) if bmMailBox: return key, bmMailBox, mailDir
def cfgWatch(self, widget, cAttr, cMod): def valueChanged(value, attr, mod): cSet(attr, value, mod=mod) val = cGet(cAttr, mod=cMod) if isinstance(widget, QComboBox): widget.currentTextChanged.connect( lambda text: valueChanged(text, cAttr, cMod) ) widget.setCurrentText(val) elif isinstance(widget, QSpinBox): widget.valueChanged.connect( lambda value: valueChanged(value, cAttr, cMod) ) widget.setValue(val) elif isinstance(widget, QCheckBox): widget.stateChanged.connect( lambda state: valueChanged( state == Qt.Checked, cAttr, cMod) ) widget.setChecked(val) elif isinstance(widget, QLineEdit): widget.textChanged.connect( lambda text: valueChanged(text, cAttr, cMod) ) widget.setText(val)
async def peersWatcherTask(self): interval = cGet('peers.watcherTask.sleepInterval') while not self.should_stop: await asyncio.sleep(interval) await self.peersWatcherRun()
async def refresh(self): staleValue = cGet('resolve.staleAfterDelay') last = self._lastResolve if self.local or not last or (loopTime() - last) > staleValue: self.message('Reloading') return await self.load()
def __init__(self): self._managedIdentifiers = {} self._lock = asyncio.Lock() self._resolveTimeout = cGet('resolve.timeout') self._rsaExec = RSAExecutor() # JSON-LD cache self._ldCache = LRUCache(256)
def __init__(self, app, parent=None, validCidQSize=32, noMutexes=True): super(NativeIPFSSchemeHandler, self).__init__(parent=parent, noMutexes=noMutexes) self.app = app self.validCids = collections.deque([], validCidQSize) self.requestTimeout = cGet('schemes.ipfsNative.reqTimeout')
def setEditorData(self, editor, index): mod, attr, atype = self._tr(index) value = cGet(attr, mod=mod) if isinstance(editor, QSpinBox) or isinstance(editor, QDoubleSpinBox): editor.setValue(value) if isinstance(editor, QComboBox): editor.setCurrentText(str(value))
async def settingsInit(self): langCodeCurrent = cGet('language', mod='galacteek.application') langsAvailable = cGet('languagesAvailable', mod='galacteek.application') for langEntry in langsAvailable: langCode = langEntry.get('code') langDisplayName = langEntry.get('displayName') self.ui.language.addItem(langDisplayName, langCode) for idx in range(self.ui.language.count()): code = self.ui.language.itemData(idx) if code == langCodeCurrent: self.ui.language.setCurrentIndex(idx) # Theme self.ui.themeCombo.clear() for themeName, tPath in themesList(): self.ui.themeCombo.addItem(themeName) pNameList = self.app.availableWebProfilesNames() for pName in pNameList: self.ui.comboDefaultWebProfile.insertItem( self.ui.comboDefaultWebProfile.count(), pName) self.cfgWatch(self.ui.language, 'language', 'galacteek.application') self.cfgWatch(self.ui.comboDefaultWebProfile, 'defaultWebProfile', 'galacteek.browser.webprofiles') self.cfgWatch(self.ui.webEngineDefaultZoom, 'zoom.default', 'galacteek.ui.browser') self.cfgWatch(self.ui.themeCombo, 'theme', 'galacteek.ui') self.cfgWatch(self.ui.urlHistoryEnable, 'enabled', 'galacteek.ui.history') self.cfgWatch( self.ui.toolbarsIconSize, 'styles.galacteek.desktopGeneric.metrics.toolBarIconSize', 'galacteek.ui') self.ui.themeCombo.currentTextChanged.connect(self.applyTheme)
def baseDownloadDir(self): dlPath = Path( cGet('locations.downloadsPath', 'galacteek.application') ) seedsDir = dlPath.joinpath('seeds') baseDir = seedsDir.joinpath(self.seed.name) baseDir.mkdir(parents=True, exist_ok=True) return baseDir
def rpsConfigRegister(rService: dict, peerId: str): """ Register a remote pinning service in the config rService is an entry in the 'RemoteServices' list returned by IPFS peerID is the peer ID of the node that has this service """ from galacteek.config import merge name = rService['Service'] services = remoteServices() if rpsExists(rService, services=services): return False default = cGet(defCfgKey, mod=cmod) # Append cfg = { 'displayName': name, 'serviceName': name, 'endpoint': rService['ApiEndpoint'], 'peerId': peerId, 'priority': 0, 'pinQueueName': name, 'default': False, 'enabled': True, 'iconCid': None } merged = merge(default, cfg) services.append(merged) # Patch cSet(rSrvsKey, services, mod=cmod) # Profit return True
async def sendChannelsStatus(self): msgConfig = cGet('services.chat.messages.UserChannelsListMessage', mod='galacteek.ipfs.pubsub.srvs') delay = msgConfig.publishTimer pubChannels = {} pubChannels = [] for chan, _w in self.channelWidgets.items(): pubChannels.append({ 'tokenSigMethod': 'rsa', 'sessionJwsCid': _w.psService.jwsTokenCid }) userChannelsMsg = UserChannelsListMessage.make(self.userListRev, pubChannels) # Publish on the keyChatChanList PS key, the PS service catches it # and sends the message gHub.publish(keyChatChanList, userChannelsMsg) ensureLater(delay, self.sendChannelsStatus)
def accept(self): section = CFG_SECTION_IPFSD if self.ui.groupBoxDaemon.isChecked(): self.sManager.setTrue(section, CFG_KEY_ENABLED) else: self.sManager.setFalse(section, CFG_KEY_ENABLED) self.setS(section, CFG_KEY_SWARMPORT, self.ui.ipfsdSwarmPort.text()) self.setS(section, CFG_KEY_SWARMPORT_QUIC, self.ui.ipfsdSwarmPortQuic.text()) self.sManager.setBoolFrom(section, CFG_KEY_SWARM_QUIC, self.isChecked(self.ui.checkBoxQuic)) self.setS(section, CFG_KEY_APIPORT, self.ui.ipfsdApiPort.text()) self.setS(section, CFG_KEY_HTTPGWPORT, self.ui.ipfsdGwPort.text()) self.setS(section, CFG_KEY_SWARMLOWWATER, self.ui.swarmMinConns.text()) self.setS( section, CFG_KEY_SWARMHIGHWATER, self.ui.swarmMaxConns.text()) self.setS(section, CFG_KEY_STORAGEMAX, self.ui.storageMax.text()) self.setS(section, CFG_KEY_ROUTINGMODE, self.ui.routingMode.currentText()) self.setS(section, CFG_KEY_PUBSUB_ROUTER, self.ui.pubsubRoutingMode.currentText()) self.sManager.setBoolFrom(section, CFG_KEY_HTTPGWWRITABLE, self.isChecked(self.ui.writableHttpGw)) self.sManager.setBoolFrom(section, CFG_KEY_NAMESYS_PUBSUB, self.isChecked(self.ui.namesysPubsub)) self.sManager.setBoolFrom(section, CFG_KEY_FILESTORE, self.isChecked(self.ui.fileStore)) self.sManager.setBoolFrom(section, CFG_KEY_IPFSD_DETACHED, self.isChecked(self.ui.keepDaemonRunning)) section = CFG_SECTION_IPFSCONN1 self.setS(section, CFG_KEY_HOST, self.ui.customIpfsHost.text()) self.setS(section, CFG_KEY_APIPORT, self.ui.customIpfsApiPort.text()) self.setS(section, CFG_KEY_HTTPGWPORT, self.ui.customIpfsGwPort.text()) section = CFG_SECTION_BROWSER self.setS(section, CFG_KEY_HOMEURL, self.ui.home.text()) cSet('defaultWebProfile', self.ui.comboDefaultWebProfile.currentText(), mod='galacteek.browser.webprofiles') section = CFG_SECTION_HISTORY cSet('enabled', self.isChecked(self.ui.urlHistoryEnable), mod='galacteek.ui.history') cSet('zoom.default', self.ui.webEngineDefaultZoom.value(), mod='galacteek.ui.browser') idx = self.ui.language.currentIndex() langCode = self.ui.language.itemData(idx) curLang = cGet('language', mod='galacteek.application') if langCode != curLang: cSet('language', langCode, mod='galacteek.application') self.app.setupTranslator() section = CFG_SECTION_ETHEREUM if self.ui.groupBoxEth.isChecked(): self.sManager.setTrue(section, CFG_KEY_ENABLED) else: self.sManager.setFalse(section, CFG_KEY_ENABLED) rpcUrl = QUrl(self.ui.ethRpcUrl.text()) if not rpcUrl.isValid() or not rpcUrl.scheme() in [ 'http', 'https', 'wss'] or not rpcUrl.host(): return messageBox( 'Invalid Ethereum RPC URL (scheme should be http or wss)' ) self.setS(section, CFG_KEY_PROVIDERTYPE, self.ui.ethProvType.currentText()) self.setS(section, CFG_KEY_RPCURL, rpcUrl.toString()) self.app.urlHistory.historyConfigChanged.emit( self.sManager.urlHistoryEnabled) self.sManager.sync() self.sManager.changed = True self.done(1)
async def loadContracts(self): config = cGet('contracts.deployed', 'galacteek.ipdapps.{self.name}') await self.loadContractsFromConfig(config)
def cObjectOpener(self): return cGet('objectOpener', mod='galacteek.ui')
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()
def config(self): return merge(self.defaults, cGet(f'webProfiles.{self.profileName}'))
def cfgPeers(self): return cGet('peers')
def remoteServices(): return cGet(rSrvsKey, mod=cmod)
def rpsConfigGetByServiceName(serviceName: str): default = cGet(defCfgKey, mod=cmod) for srv in remoteServices(): if srv.serviceName == serviceName: return merge(default, srv)
def enabled(self): return cGet('enabled')
def cStyle(self): sType = cGet('styles.galacteek.styleType', mod='galacteek.ui') if not sType: sType = 'desktopGeneric' return cGet(f'styles.galacteek.{sType}', mod='galacteek.ui')
def loadSettings(self): # lang langCodeCurrent = cGet( 'language', mod='galacteek.application' ) langsAvailable = cGet( 'languagesAvailable', mod='galacteek.application' ) for langEntry in langsAvailable: langCode = langEntry.get('code') langDisplayName = langEntry.get('displayName') self.ui.language.addItem( langDisplayName, langCode ) for idx in range(self.ui.language.count()): code = self.ui.language.itemData(idx) if code == langCodeCurrent: self.ui.language.setCurrentIndex(idx) # Theme self.ui.themeCombo.clear() for themeName, tPath in themesList(): self.ui.themeCombo.addItem(themeName) curTheme = cGet('theme', mod='galacteek.ui') if curTheme: self.ui.themeCombo.setCurrentText(curTheme) # IPFSD section = CFG_SECTION_IPFSD ipfsdEnabled = self.sManager.isTrue(section, CFG_KEY_ENABLED) if ipfsdEnabled: self.enableGroupDaemon() else: self.enableGroupCustom() self.ui.ipfsdSwarmPort.setValue( self.getS(section, CFG_KEY_SWARMPORT, int)) self.ui.ipfsdSwarmPortQuic.setValue( self.getS(section, CFG_KEY_SWARMPORT_QUIC, int)) self.setChecked(self.ui.checkBoxQuic, self.sManager.isTrue(section, CFG_KEY_SWARM_QUIC)) self.setChecked(self.ui.keepDaemonRunning, self.sManager.isTrue(section, CFG_KEY_IPFSD_DETACHED)) self.ui.ipfsdApiPort.setValue( self.getS(section, CFG_KEY_APIPORT, int)) self.ui.ipfsdGwPort.setValue( self.getS(section, CFG_KEY_HTTPGWPORT, int)) self.ui.swarmMinConns.setValue( self.getS(section, CFG_KEY_SWARMLOWWATER, int)) self.ui.swarmMaxConns.setValue( self.getS(section, CFG_KEY_SWARMHIGHWATER, int)) self.ui.storageMax.setValue( self.getS(section, CFG_KEY_STORAGEMAX, int)) self.ui.routingMode.setCurrentText( self.getS(section, CFG_KEY_ROUTINGMODE, str)) self.ui.pubsubRoutingMode.setCurrentText( self.getS(section, CFG_KEY_PUBSUB_ROUTER, str)) self.setChecked(self.ui.writableHttpGw, self.sManager.isTrue(section, CFG_KEY_HTTPGWWRITABLE)) self.setChecked(self.ui.namesysPubsub, self.sManager.isTrue(section, CFG_KEY_NAMESYS_PUBSUB)) self.setChecked(self.ui.fileStore, self.sManager.isTrue(section, CFG_KEY_FILESTORE)) # IPFS connection section = CFG_SECTION_IPFSCONN1 self.ui.customIpfsHost.setText( self.getS(section, CFG_KEY_HOST, str)) self.ui.customIpfsApiPort.setValue( self.getS(section, CFG_KEY_APIPORT, int)) self.ui.customIpfsGwPort.setValue( self.getS(section, CFG_KEY_HTTPGWPORT, int)) # Browser section = CFG_SECTION_BROWSER self.ui.home.setText( self.getS(section, CFG_KEY_HOMEURL, str)) self.ui.downloadsLocation.setText( self.getS(section, CFG_KEY_DLPATH, str)) # Default web profile combo box currentDefault = cGet('defaultWebProfile', mod='galacteek.browser.webprofiles') pNameList = self.app.availableWebProfilesNames() for pName in pNameList: self.ui.comboDefaultWebProfile.insertItem( self.ui.comboDefaultWebProfile.count(), pName ) if currentDefault and currentDefault in pNameList: self.ui.comboDefaultWebProfile.setCurrentText(currentDefault) # History self.setChecked(self.ui.urlHistoryEnable, self.sManager.isTrue(CFG_SECTION_HISTORY, CFG_KEY_HISTORYENABLED)) # UI self.ui.webEngineDefaultZoom.setValue( cGet('zoom.default', mod='galacteek.ui.browser')) # Eth section = CFG_SECTION_ETHEREUM ethEnabled = self.sManager.isTrue(section, CFG_KEY_ENABLED) if ethEnabled: self.ui.groupBoxEth.setEnabled(True) self.ui.groupBoxEth.setChecked(True) self.ui.ethProvType.setCurrentText( self.sManager.getSetting(section, CFG_KEY_PROVIDERTYPE)) self.ui.ethRpcUrl.setText( self.sManager.getSetting(section, CFG_KEY_RPCURL))