Minor refactors:
- Renames s_assemble to s_brief - Link s_local to s_brief
This commit is contained in:
43
apps/cic-ussd/cic_ussd/metadata/__init__.py
Normal file
43
apps/cic-ussd/cic_ussd/metadata/__init__.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# standard imports
|
||||
|
||||
# third-party imports
|
||||
import requests
|
||||
from chainlib.eth.address import to_checksum
|
||||
from hexathon import add_0x
|
||||
|
||||
# local imports
|
||||
from cic_ussd.error import UnsupportedMethodError
|
||||
|
||||
|
||||
def make_request(method: str, url: str, data: any = None, headers: dict = None):
|
||||
"""
|
||||
:param method:
|
||||
:type method:
|
||||
:param url:
|
||||
:type url:
|
||||
:param data:
|
||||
:type data:
|
||||
:param headers:
|
||||
:type headers:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
if method == 'GET':
|
||||
result = requests.get(url=url)
|
||||
elif method == 'POST':
|
||||
result = requests.post(url=url, data=data, headers=headers)
|
||||
elif method == 'PUT':
|
||||
result = requests.put(url=url, data=data, headers=headers)
|
||||
else:
|
||||
raise UnsupportedMethodError(f'Unsupported method: {method}')
|
||||
return result
|
||||
|
||||
|
||||
def blockchain_address_to_metadata_pointer(blockchain_address: str):
|
||||
"""
|
||||
:param blockchain_address:
|
||||
:type blockchain_address:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
return bytes.fromhex(blockchain_address[2:])
|
||||
63
apps/cic-ussd/cic_ussd/metadata/signer.py
Normal file
63
apps/cic-ussd/cic_ussd/metadata/signer.py
Normal file
@@ -0,0 +1,63 @@
|
||||
# standard imports
|
||||
import json
|
||||
import logging
|
||||
from typing import Optional
|
||||
from urllib.request import Request, urlopen
|
||||
|
||||
# third-party imports
|
||||
import gnupg
|
||||
|
||||
# local imports
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
class Signer:
|
||||
"""
|
||||
:cvar gpg_path:
|
||||
:type gpg_path:
|
||||
:cvar gpg_passphrase:
|
||||
:type gpg_passphrase:
|
||||
:cvar key_file_path:
|
||||
:type key_file_path:
|
||||
|
||||
"""
|
||||
gpg_path: str = None
|
||||
gpg_passphrase: str = None
|
||||
key_file_path: str = None
|
||||
|
||||
def __init__(self):
|
||||
self.gpg = gnupg.GPG(gnupghome=self.gpg_path)
|
||||
|
||||
# parse key file data
|
||||
key_file = open(self.key_file_path, 'r')
|
||||
self.key_data = key_file.read()
|
||||
key_file.close()
|
||||
|
||||
def get_operational_key(self):
|
||||
"""
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
# import key data into keyring
|
||||
self.gpg.import_keys(key_data=self.key_data)
|
||||
gpg_keys = self.gpg.list_keys()
|
||||
key_algorithm = gpg_keys[0].get('algo')
|
||||
key_id = gpg_keys[0].get("keyid")
|
||||
logg.info(f'using signing key: {key_id}, algorithm: {key_algorithm}')
|
||||
return gpg_keys[0]
|
||||
|
||||
def sign_digest(self, data: bytes):
|
||||
"""
|
||||
:param data:
|
||||
:type data:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
data = json.loads(data)
|
||||
digest = data['digest']
|
||||
key_id = self.get_operational_key().get('keyid')
|
||||
signature = self.gpg.sign(digest, passphrase=self.gpg_passphrase, keyid=key_id)
|
||||
return str(signature)
|
||||
|
||||
|
||||
102
apps/cic-ussd/cic_ussd/metadata/user.py
Normal file
102
apps/cic-ussd/cic_ussd/metadata/user.py
Normal file
@@ -0,0 +1,102 @@
|
||||
# standard imports
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
# third-party imports
|
||||
import requests
|
||||
from cic_types.models.person import generate_metadata_pointer, Person
|
||||
|
||||
# local imports
|
||||
from cic_ussd.chain import Chain
|
||||
from cic_ussd.metadata import make_request
|
||||
from cic_ussd.metadata.signer import Signer
|
||||
from cic_ussd.redis import cache_data
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
class UserMetadata:
|
||||
"""
|
||||
:cvar base_url:
|
||||
:type base_url:
|
||||
"""
|
||||
base_url = None
|
||||
|
||||
def __init__(self, identifier: bytes):
|
||||
"""
|
||||
:param identifier:
|
||||
:type identifier:
|
||||
"""
|
||||
self. headers = {
|
||||
'X-CIC-AUTOMERGE': 'server',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
self.identifier = identifier
|
||||
self.metadata_pointer = generate_metadata_pointer(
|
||||
identifier=self.identifier,
|
||||
cic_type='cic.person'
|
||||
)
|
||||
if self.base_url:
|
||||
self.url = os.path.join(self.base_url, self.metadata_pointer)
|
||||
|
||||
def create(self, data: dict):
|
||||
try:
|
||||
data = json.dumps(data).encode('utf-8')
|
||||
result = make_request(method='POST', url=self.url, data=data, headers=self.headers)
|
||||
metadata = result.content
|
||||
self.edit(data=metadata, engine='pgp')
|
||||
logg.info(f'Get sign material response status: {result.status_code}')
|
||||
result.raise_for_status()
|
||||
except requests.exceptions.HTTPError as error:
|
||||
raise RuntimeError(error)
|
||||
|
||||
def edit(self, data: bytes, engine: str):
|
||||
"""
|
||||
:param data:
|
||||
:type data:
|
||||
:param engine:
|
||||
:type engine:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
cic_meta_signer = Signer()
|
||||
signature = cic_meta_signer.sign_digest(data=data)
|
||||
algorithm = cic_meta_signer.get_operational_key().get('algo')
|
||||
formatted_data = {
|
||||
'm': data.decode('utf-8'),
|
||||
's': {
|
||||
'engine': engine,
|
||||
'algo': algorithm,
|
||||
'data': signature,
|
||||
'digest': json.loads(data).get('digest'),
|
||||
}
|
||||
}
|
||||
formatted_data = json.dumps(formatted_data).encode('utf-8')
|
||||
|
||||
try:
|
||||
result = make_request(method='PUT', url=self.url, data=formatted_data, headers=self.headers)
|
||||
logg.info(f'Signed content submission status: {result.status_code}.')
|
||||
result.raise_for_status()
|
||||
except requests.exceptions.HTTPError as error:
|
||||
raise RuntimeError(error)
|
||||
|
||||
def query(self):
|
||||
result = make_request(method='GET', url=self.url)
|
||||
status = result.status_code
|
||||
logg.info(f'Get latest data status: {status}')
|
||||
try:
|
||||
if status == 200:
|
||||
response_data = result.content
|
||||
data = json.loads(response_data.decode())
|
||||
|
||||
# validate data
|
||||
person = Person()
|
||||
deserialized_person = person.deserialize(metadata=json.loads(data))
|
||||
|
||||
cache_data(key=self.metadata_pointer, data=json.dumps(deserialized_person.serialize()))
|
||||
elif status == 404:
|
||||
logg.info('The data is not available and might need to be added.')
|
||||
result.raise_for_status()
|
||||
except requests.exceptions.HTTPError as error:
|
||||
raise RuntimeError(error)
|
||||
Reference in New Issue
Block a user