Add usumbufu hoba capable opener object
This commit is contained in:
parent
e3c002082b
commit
8568e352be
@ -13,6 +13,7 @@ from chainlib.chain import ChainSpec
|
||||
import clicada.cli.user as cmd_user
|
||||
import clicada.cli.tag as cmd_tag
|
||||
from clicada.cli.auth import PGPAuthCrypt
|
||||
from clicada.cli.http import HTTPSession
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
data_dir = os.path.join(script_dir, '..', 'data')
|
||||
@ -68,9 +69,12 @@ class CmdCtrl:
|
||||
else:
|
||||
self.config = chainlib.eth.cli.Config.from_args(self.cmd_args, base_config_dir=base_config_dir, extra_args=extra_args)
|
||||
|
||||
self.__auth = self.auth(self.get('AUTH_TYPE'))
|
||||
self.auth(self.get('AUTH_TYPE'))
|
||||
|
||||
self.config.add(False, '_SEQ')
|
||||
|
||||
self.config.censor('AUTH_PASSPHRASE')
|
||||
|
||||
logger.debug('loaded config:\n{}'.format(self.config))
|
||||
|
||||
self.chain_spec = ChainSpec.from_chain_str(self.config.get('CHAIN_SPEC'))
|
||||
@ -78,6 +82,9 @@ class CmdCtrl:
|
||||
self.rpc = chainlib.eth.cli.Rpc()
|
||||
self.__conn = self.rpc.connect_by_config(self.config)
|
||||
|
||||
self.remote_openers = {
|
||||
'meta': HTTPSession(self.get('META_URL'), auth=self.__auth),
|
||||
}
|
||||
|
||||
|
||||
def auth(self, typ):
|
||||
@ -110,3 +117,7 @@ class CmdCtrl:
|
||||
|
||||
def execute(self):
|
||||
self.cmd_mod.execute(self)
|
||||
|
||||
|
||||
def opener(self, k):
|
||||
return self.remote_openers[k]
|
||||
|
@ -5,6 +5,7 @@ import logging
|
||||
|
||||
# external imports
|
||||
import gnupg
|
||||
from usumbufu.client.hoba import HobaClientSession
|
||||
|
||||
# local imports
|
||||
from clicada.error import AuthError
|
||||
@ -12,7 +13,10 @@ from clicada.error import AuthError
|
||||
logg = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PGPAuthCrypt:
|
||||
class PGPAuthCrypt(HobaClientSession):
|
||||
|
||||
typ = 'gnupg'
|
||||
alg = '969'
|
||||
|
||||
def __init__(self, db_dir, auth_key, pgp_dir=None):
|
||||
self.db_dir = db_dir
|
||||
@ -51,3 +55,21 @@ class PGPAuthCrypt:
|
||||
if not self.secret.ok:
|
||||
raise AuthError('could not decrypt encryption secret. wrong password?')
|
||||
f.close()
|
||||
|
||||
|
||||
def sign_auth_challenge(self, plaintext, hoba, encoding):
|
||||
r = self.gpg.sign(plaintext, passphrase=self.passphrase, detach=True)
|
||||
|
||||
if encoding == 'base64':
|
||||
r = r.data
|
||||
|
||||
hoba.signature = r
|
||||
return str(hoba)
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return 'clicada hoba/pgp auth'
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return 'clicada hoba/pgp auth'
|
||||
|
52
clicada/cli/http.py
Normal file
52
clicada/cli/http.py
Normal file
@ -0,0 +1,52 @@
|
||||
# standard imports
|
||||
import hashlib
|
||||
import urllib.parse
|
||||
import os
|
||||
import logging
|
||||
|
||||
# external imports
|
||||
from usumbufu.client.base import (
|
||||
ClientSession,
|
||||
BaseTokenStore,
|
||||
)
|
||||
from usumbufu.client.bearer import BearerClientSession
|
||||
|
||||
logg = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HTTPSession:
|
||||
|
||||
token_dir = '/run/user/{}/clicada/usumbufu/.token'.format(os.getuid())
|
||||
|
||||
def __init__(self, url, auth=None):
|
||||
logg.debug('auth auth {}'.format(auth))
|
||||
self.base_url = url
|
||||
url_parts = urllib.parse.urlparse(self.base_url)
|
||||
self.origin = urllib.parse.urljoin(url_parts[0], url_parts[1])
|
||||
|
||||
h = hashlib.sha256()
|
||||
h.update(self.base_url.encode('utf-8'))
|
||||
z = h.digest()
|
||||
|
||||
token_store_dir = os.path.join(self.token_dir, z.hex())
|
||||
self.token_store = BaseTokenStore(path=token_store_dir)
|
||||
|
||||
self.session = ClientSession(self.origin, token_store=self.token_store)
|
||||
bearer_handler = BearerClientSession(self.origin, token_store=self.token_store)
|
||||
self.session.add_subhandler(bearer_handler)
|
||||
|
||||
if auth != None:
|
||||
self.session.add_subhandler(auth)
|
||||
|
||||
self.opener = urllib.request.build_opener(self.session)
|
||||
|
||||
|
||||
def open(self, endpoint):
|
||||
url = urllib.parse.urljoin(self.base_url, endpoint)
|
||||
logg.debug('open {} with opener {}'.format(url, self))
|
||||
r = self.opener.open(url)
|
||||
return r.read().decode('utf-8')
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return str(self.session)
|
@ -26,7 +26,7 @@ logg = logging.getLogger(__name__)
|
||||
def process_args(argparser):
|
||||
argparser.add_argument('-m', '--method', type=str, help='lookup method')
|
||||
argparser.add_argument('--meta-url', dest='meta_url', type=str, help='Url to retrieve metadata from')
|
||||
argparser.add_argument('-f', '--force-update', dest='force_update', type=str, help='Update records of mutable entries')
|
||||
argparser.add_argument('-f', '--force-update', dest='force_update', action='store_true', help='Update records of mutable entries')
|
||||
argparser.add_argument('identifier', type=str, help='user identifier')
|
||||
|
||||
|
||||
@ -55,7 +55,7 @@ def execute(ctrl):
|
||||
|
||||
store_path = '.clicada'
|
||||
user_phone_file_label = 'phone'
|
||||
user_phone_store = FileUserStore(ctrl.chain(), user_phone_file_label, store_path, int(ctrl.get('FILESTORE_TTL')))
|
||||
user_phone_store = FileUserStore(ctrl.opener('meta'), ctrl.chain(), user_phone_file_label, store_path, int(ctrl.get('FILESTORE_TTL')))
|
||||
|
||||
user_address = user_phone_store.by_phone(ctrl.get('_IDENTIFIER'), update=ctrl.get('_FORCE'))
|
||||
if user_address == None:
|
||||
@ -74,9 +74,9 @@ def execute(ctrl):
|
||||
token_store = FileTokenStore(ctrl.chain(), ctrl.conn(), 'token', store_path)
|
||||
|
||||
user_address_file_label = 'address'
|
||||
user_address_store = FileUserStore(ctrl.chain(), user_address_file_label, store_path, int(ctrl.get('FILESTORE_TTL')))
|
||||
user_address_store = FileUserStore(ctrl.opener('meta'), ctrl.chain(), user_address_file_label, store_path, int(ctrl.get('FILESTORE_TTL')))
|
||||
|
||||
r = user_address_store.by_address(user_address)
|
||||
r = user_address_store.by_address(user_address, update=ctrl.get('_FORCE'))
|
||||
|
||||
print("""Phone: {}
|
||||
Network address: {}
|
||||
|
@ -33,12 +33,13 @@ class Account(Person):
|
||||
|
||||
def apply_custom(self, custom_data):
|
||||
self.tags = custom_data['tags']
|
||||
logg.debug('tags are now {}'.format(self.tags))
|
||||
|
||||
|
||||
|
||||
class FileUserStore:
|
||||
|
||||
def __init__(self, chain_spec, label, store_base_path, ttl):
|
||||
def __init__(self, metadata_opener, chain_spec, label, store_base_path, ttl):
|
||||
invalidate_before = datetime.datetime.now() - datetime.timedelta(seconds=ttl)
|
||||
self.invalidate_before = int(invalidate_before.timestamp())
|
||||
self.have_xattr = False
|
||||
@ -53,6 +54,7 @@ class FileUserStore:
|
||||
self.memstore_entity = MemDictStore()
|
||||
os.makedirs(self.store_path, exist_ok=True)
|
||||
self.__validate_dir()
|
||||
self.metadata_opener = metadata_opener
|
||||
|
||||
|
||||
def __validate_dir(self):
|
||||
@ -177,7 +179,7 @@ class FileUserStore:
|
||||
logg.debug('no address found for phone {}: {}'.format(phone, e))
|
||||
return None
|
||||
|
||||
self.put(phone_file, user_address)
|
||||
self.put(phone_file, user_address, force=update)
|
||||
return user_address
|
||||
|
||||
|
||||
@ -189,12 +191,12 @@ class FileUserStore:
|
||||
try:
|
||||
v = self.get(address, ignore_expired=ignore_expired)
|
||||
v = json.loads(v)
|
||||
person = Person()
|
||||
person = Account()
|
||||
try:
|
||||
person_data = person.deserialize(person_data=v)
|
||||
except Exception as e:
|
||||
person_data = v
|
||||
return str(person_data)
|
||||
return person_data
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
except ExpiredRecordError as e:
|
||||
@ -202,25 +204,28 @@ class FileUserStore:
|
||||
pass
|
||||
|
||||
address = strip_0x(address)
|
||||
getter = MetadataRequestsHandler(MetadataPointer.PERSON, bytes.fromhex(address))
|
||||
getter = self.metadata_opener
|
||||
|
||||
ptr = generate_metadata_pointer(bytes.fromhex(address), MetadataPointer.PERSON)
|
||||
r = None
|
||||
try:
|
||||
r = getter.query()
|
||||
except requests.exceptions.HTTPError as e:
|
||||
r = getter.open(ptr)
|
||||
except Exception as e:
|
||||
logg.debug('no metadata found for {}: {}'.format(address, e))
|
||||
return address
|
||||
|
||||
data = r.json()
|
||||
data = json.loads(r)
|
||||
person = Account()
|
||||
person_data = person.deserialize(person_data=data)
|
||||
self.put(address, json.dumps(person_data.serialize()))
|
||||
self.put(address, json.dumps(person_data.serialize()), force=update)
|
||||
|
||||
getter = MetadataRequestsHandler(MetadataPointer.CUSTOM, bytes.fromhex(address))
|
||||
ptr = generate_metadata_pointer(bytes.fromhex(address), MetadataPointer.CUSTOM)
|
||||
r = None
|
||||
try:
|
||||
r = getter.query()
|
||||
person_data.apply_custom(r.json())
|
||||
except requests.exceptions.HTTPError as e:
|
||||
r = getter.open(ptr)
|
||||
o = json.loads(r)
|
||||
person_data.apply_custom(o)
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
return person_data
|
||||
|
Loading…
Reference in New Issue
Block a user