def __build_permissions(self): granted = [] revoked = [] granted_field_lookup = {} pbdb = PermissionBatchDatabase(default_pb_db()) permissions = UnifPermissions(get_ipfs_client(), self.__my_uapp_sc, pbdb) permissions.load_consumer_perms(self.__requesting_app) permission_obj = permissions.get_all_perms() # schema_id = self.__my_db_schemas[0]['pkey'] # tmp - only 1 db schema for user, perms in permission_obj['permissions'].items(): log.debug(perms) schema_perms = perms['0'] # tmp - only 1 db schema if schema_perms['perms'] == '': revoked.append(eosio_account.string_to_name(user)) else: granted.append(eosio_account.string_to_name(user)) native_id = self.__my_lookup.get_native_user_id(user) granted_field_lookup[native_id] = schema_perms['perms'].split( ',') # required granted_field_lookup[native_id].append('account_name') return granted, revoked, granted_field_lookup
def get_proof(): conf = app.unification_config d = flask.request.get_json() user = d['user'] consumer = d['consumer'] ipfs_hash = d['ipfs_hash'] schema_id = d['schema_id'] provider_uapp = UnificationUapp(get_eos_rpc_client(), conf['uapp_contract']) permission_db = PermissionBatchDatabase(pb_default_db()) permissions = UnifPermissions(get_ipfs_client(), provider_uapp, permission_db) if ipfs_hash is not None: permissions.load_perms_from_ipfs(ipfs_hash) else: permissions.load_consumer_perms(consumer) proof = permissions.get_proof(user, schema_id=schema_id) # ToDo: send as JWT return_d = {'proof': proof} return flask.jsonify(return_d), 200
def systest_merkle_proof_permissions(): ipfs = get_ipfs_client() users, consumers, providers = compile_actors() for provider in providers: log.debug(f'run systest_merkle_proof_' f'permissions for Provider {provider}') provider_uapp = UnificationUapp(get_eos_rpc_client(), provider) permission_db = PermissionBatchDatabase(pb_default_db()) permissions = UnifPermissions(ipfs, provider_uapp, permission_db) for consumer in consumers: if consumer != provider: log.debug(f'Provider {provider}: load ' f'permissions for Consumer {consumer}') permissions.load_consumer_perms(consumer) permissions_obj = permissions.get_all_perms() tree = MerkleTree() for user, perm in permissions_obj['permissions'].items(): for schema_id, schema_perm in perm.items(): tree.add_leaf(json.dumps(schema_perm)) tree.grow_tree() log.debug(f"Generated merkle root: {tree.get_root_str()}") log.debug(f"Recorded merkle root: " f"{permissions_obj['merkle_root']}") for user, perm in permissions_obj['permissions'].items(): for schema_id, schema_perm in perm.items(): requested_leaf = json.dumps(schema_perm) proof_chain = tree.get_proof(requested_leaf, is_hashed=False) log.debug(f'Permission leaf for {user}:' f' {requested_leaf}') log.debug(f'Proof chain for {user} - ' f'Schema {schema_id} ' f'permission leaf: ' f'{json.dumps(proof_chain)}') # simulate only having access to leaf, # root and proof chain for leaf verify_tree = MerkleTree() is_good = verify_tree.verify_leaf( requested_leaf, permissions_obj['merkle_root'], proof_chain, is_hashed=False) log.debug(f'Leaf is valid: {is_good}') assert is_good
def get_proof_tx(): d = flask.request.get_json() user = d['user'] proc_id = d['proc_id'] permission_db = PermissionBatchDatabase(pb_default_db()) operation_data = permission_db.get_op_for_user(user, proc_id) return_data = {'processed': False, 'proof_tx': None, 'found': False} if operation_data: return_data['found'] = True if operation_data['proof_tx']: return_data['processed'] = True return_data['proof_tx'] = operation_data['proof_tx'] return flask.jsonify(return_data), 200
def systest_check_permission_requests(): ipfs = get_ipfs_client() users, consumers, providers = compile_actors() for provider in providers: log.debug(f'run systest_check_permission_requests' f' for Provider {provider}') provider_uapp = UnificationUapp(get_eos_rpc_client(), provider) permission_db = PermissionBatchDatabase(pb_default_db()) permissions = UnifPermissions(ipfs, provider_uapp, permission_db) for consumer in consumers: if consumer != provider: log.debug(f'Provider {provider}: load permissions ' f'for Consumer {consumer}') permissions.load_consumer_perms(consumer) for user in users: user_permissions = permissions.get_user_perms_for_all_schemas( user) for schema_id, user_perms in user_permissions.items(): log.debug(f'User {user}, ' f'Schema {schema_id}: {user_perms}') is_valid = permissions.verify_permission(user_perms) log.debug(f'Perm sig valid: {is_valid}') assert is_valid demo_conf_check = demo_config['demo_permissions'][ user][consumer][provider] demo_conf_fields = demo_conf_check['fields'] demo_conf_granted = demo_conf_check['granted'] demo_conf_schema_id = demo_conf_check['schema_id'] assert int(demo_conf_schema_id) == int(schema_id) if demo_conf_granted: log.debug("Permission granted") log.debug(f"Demo fields: {demo_conf_fields}, " f"recorded fields: " f"{user_perms['perms']}") assert demo_conf_fields == user_perms['perms'] else: log.debug("Permission not granted. Recorded " "perms should be empty") log.debug(f"Recorded fields: " f"{user_perms['perms']}") assert user_perms['perms'] == ''
def check_and_process_stashed(self, consumer_account): from haiku_node.permissions.perm_batch_db import ( PermissionBatchDatabase, default_db as pb_db) pb = PermissionBatchDatabase(pb_db()) latest_stash = pb.get_stash(consumer_account) if latest_stash is not None: tx_id = self.__uapp.update_userperms(consumer_account, latest_stash['ipfs_hash'], latest_stash['merkle_root']) pb.update_batch_stashes_with_tx(latest_stash['stash_id'], tx_id) pb.delete_stash(latest_stash['stash_id'])
def data_request(): try: d = flask.request.get_json() # Validate requesting app against smart contracts # config is this Haiku Node's config fle, containing its UApp # Smart Contract account/address and the EOS RPC server/port used for # communicating with the blockchain. conf = app.unification_config sender = d['eos_account_name'] recipient = conf['uapp_contract'] if sender == recipient: return error_request_self() bundle_d = unbundle(app.keystore, sender, d) eos_client = get_eos_rpc_client() # Init the validation class for THIS Haiku, and validate the # REQUESTING APP. v = UnificationAppScValidation(eos_client, d['eos_account_name']) # If the REQUESTING APP is valid according to MOTHER, then we can # generate the data. If not, return an invalid_app response if v.valid(): users = bundle_d.get('users') request_id = bundle_d.get('request_id') # before processing data, check for any stashed permissions ipfs = get_ipfs_client() provider_uapp = UnificationUapp(eos_client, conf['uapp_contract']) permission_db = PermissionBatchDatabase(pb_default_db()) permissions = UnifPermissions(ipfs, provider_uapp, permission_db) permissions.check_and_process_stashed(sender) return obtain_data(app.keystore, sender, eos_client, conf['uapp_contract'], users, request_id) else: return invalid_app() except InvalidSignature: return invalid_response() except Exception as e: logger.exception(e) return generic_error()
def __init__(self, permissions_db: Path): self.db = PermissionBatchDatabase(permissions_db) self.ipfs = get_ipfs_client()
class PermissionBatcher: def __init__(self, permissions_db: Path): self.db = PermissionBatchDatabase(permissions_db) self.ipfs = get_ipfs_client() def add_to_queue(self, *kwargs): return self.db.add(*kwargs) def process_batch_queue(self, num=10): provider_uapp = get_self_uapp() permissions = UnifPermissions(self.ipfs, provider_uapp, self.db) processed = [] for item in self.db.get_unprocessed(num): perm = { 'perms': item['perms'], 'p_nonce': item['p_nonce'], 'p_sig': item['p_sig'], 'pub_key': item['pub_key'], 'schema_id': item['schema_id'], 'consumer': item['consumer_account'], 'user': item['end_user_account'] } is_added = permissions.add_change_request(item['consumer_account'], item['end_user_account'], perm) b_proc = { 'op_id': item['op_id'], 'consumer': item['consumer_account'], 'is_added': is_added } processed.append(b_proc) ret_data = permissions.process_change_requests() for item in processed: if item['is_added']: ret_d = ret_data[item['consumer']] if ret_d['bc']: self.db.update_processed(item['op_id'], proof_tx=ret_d['proof_tx']) else: stash_id = self.db.stash_permission( ret_d['stash']['consumer'], ret_d['stash']['ipfs_hash'], ret_d['stash']['merkle_root']) self.db.update_processed(item['op_id'], stash_id=stash_id) else: # Currently fails if sig is invalid, so delete self.db.delete_op(item['op_id']) # cleanup stashes for c, ret_d in ret_data.items(): if ret_d['stash_id_committed'] is not None: self.db.update_batch_stashes_with_tx( ret_d['stash_id_committed'], ret_d['proof_tx']) self.db.delete_stash(ret_d['stash_id_committed']) log.debug(ret_data) return ret_data