def es_query_ddo(): """Get a list of DDOs that match with the executed query. --- tags: - ddo consumes: - application/json parameters: - in: body name: body required: true description: Asset metadata. schema: type: object properties: query: type: string description: Query to realize example: {"value":1} text: type: string or list of strings description: Fulltext query example: ["text to search"] sort: type: object description: Key or list of keys to sort the result example: {"value":1} offset: type: int description: Number of records per page example: 100 page: type: int description: Page showed example: 1 responses: 200: description: successful action example: {"query": {"query_string": {"query": "(covid) -isInPurgatory:true"}}, "offset":1, "page": 1} """ assert isinstance(request.json, dict), 'invalid payload format.' data = request.json query_result, search_model = process_es_query(data) for ddo in query_result[0]: sanitize_record(ddo) response = make_paginate_response(query_result, search_model) return Response(json.dumps(response, default=datetime_converter), 200, content_type='application/json')
def query_text(): """Get a list of DDOs that match with the given text. --- tags: - ddo parameters: - name: text in: query description: ID of the asset. required: true type: string - name: sort in: query type: object description: Key or list of keys to sort the result example: {"value":1} - name: offset in: query type: int description: Number of records per page example: 100 - name: page in: query type: int description: Page showed example: 1 responses: 200: description: successful action """ data = get_request_data(request) assert isinstance( data, dict), 'invalid `args` type, should already formatted into a dict.' sort = data.get('sort', None) if sort is not None and isinstance(sort, str): sort = json.loads(sort) search_model = FullTextModel(text=data.get('text', None), sort=sort, offset=int(data.get('offset', 100)), page=int(data.get('page', 1))) query_result = dao.query(search_model) for i in query_result[0]: sanitize_record(i) response = make_paginate_response(query_result, search_model) return Response(json.dumps(response, default=datetime_converter), 200, content_type='application/json')
def get_asset_ddos(): """Get DDO of all assets. --- tags: - ddo responses: 200: description: successful action """ _assets = dao.get_all_listed_assets() for _record in _assets: sanitize_record(_record) return Response(json.dumps(_assets, default=datetime_converter), 200, content_type='application/json')
def get_ddo(did): """Get DDO of a particular asset. --- tags: - ddo parameters: - name: did in: path description: DID of the asset. required: true type: string responses: 200: description: successful operation 404: description: This asset DID is not in OceanDB """ try: asset_record = dao.get(did) return Response(sanitize_record(asset_record), 200, content_type='application/json') except Exception as e: logger.error(f'get_ddo: {str(e)}') return f'{did} asset DID is not in OceanDB', 404
def get_metadata(did): """Get metadata of a particular asset --- tags: - metadata parameters: - name: did in: path description: DID of the asset. required: true type: string responses: 200: description: successful operation. 404: description: This asset DID is not in OceanDB. """ try: asset_record = dao.get(did) metadata = get_metadata_from_services(asset_record['service']) return Response(sanitize_record(metadata), 200, content_type='application/json') except Exception as e: logger.error(f'get_metadata: {str(e)}') return f'{did} asset DID is not in OceanDB', 404
def test_sanitize_record_through_rbac(monkeypatch): monkeypatch.setenv("RBAC_SERVER_URL", "test") with patch("requests.post") as mock: response = Mock(spec=Response) response.json.return_value = {"this_is": "SPARTAAA!"} response.status_code = 200 mock.return_value = response result = json.loads(sanitize_record({})) assert result["this_is"] == "SPARTAAA!" with patch("requests.post") as mock: response = Mock(spec=Response) response.status_code = 404 mock.return_value = response result = json.loads(sanitize_record({"this_is": "something else"})) assert result["this_is"] == "something else"
def get_metadata(did): """Get metadata of a particular asset --- tags: - metadata parameters: - name: did in: path description: DID of the asset. required: true type: string responses: 200: description: successful operation. example: application/json: { "main": { "type": "dataset", "name": "Nu nl", "dateCreated": "2021-04-02T17:59:32Z", "author": "ab", "license": "MIT", "files": [ { "index": 0, "contentType": "application/json" } ], "datePublished": "2021-04-20T22:56:01Z" }, "encryptedFiles": "0x047c992274f3fa2bf9c5cc57d0e0852f7b3ec22d7ab4e798e3e73e77e7f971ff04896129c9f58deac" } 404: description: This asset DID is not in ES. """ try: asset_record = es_instance.get(did) response = app.response_class( response=sanitize_record(asset_record["metadata"]), status=200, mimetype="application/json", ) return response except Exception as e: logger.error(f"get_metadata: {str(e)}") return ( jsonify( error=f"Error encountered while retrieving metadata: {str(e)}." ), 404, )
def query_ddo(): """Get a list of DDOs that match with the executed query. --- tags: - ddo consumes: - application/json parameters: - in: body name: body required: true description: Asset metadata. schema: type: object properties: query: type: string description: Query to realize example: {"value":1} sort: type: object description: Key or list of keys to sort the result example: {"value":1} offset: type: int description: Number of records per page example: 100 page: type: int description: Page showed example: 1 responses: 200: description: successful action """ assert isinstance(request.json, dict), 'invalid payload format.' data = request.json assert isinstance( data, dict), 'invalid `body` type, should be formatted as a dict.' native_query = None if 'nativeSearch' in data: native_query = data.pop('nativeSearch') query = data.get('query', {}) if not native_query and 'nativeSearch' in query: native_query = query.pop('nativeSearch') if native_query: query_result, search_model = process_es_query(data) else: search_model = QueryModel(query=query, sort=data.get('sort'), offset=data.get('offset', 100), page=data.get('page', 1)) query_result = dao.query(search_model) for ddo in query_result[0]: sanitize_record(ddo) response = make_paginate_response(query_result, search_model) return Response(json.dumps(response, default=datetime_converter), 200, content_type='application/json')
def trigger_caching(): """Triggers manual caching of a specific transaction (MetadataCreated or MetadataUpdated event) --- tags: - name consumes: - application/json parameters: - name: transactionId required: true description: transaction id containing MetadataCreated or MetadataUpdated event - name: logIndex required: false description: zero-based index in log if transaction contains more events responses: 200: description: successful operation. 400: description: bad request. Log index not found or event not found. 500: description: server error/exception """ try: data = request.args if request.args else request.json tx_id = data.get("transactionId") log_index = int(data.get("logIndex", 0)) config_file = app.config["AQUARIUS_CONFIG_FILE"] web3 = setup_web3(config_file) tx_receipt = web3.eth.wait_for_transaction_receipt(tx_id) if len(tx_receipt.logs) <= log_index or log_index < 0: return jsonify(error=f"Log index {log_index} not found"), 400 dt_address = tx_receipt.logs[log_index].address dt_contract = web3.eth.contract( abi=ERC721Template.abi, address=web3.toChecksumAddress(dt_address)) created_event = dt_contract.events.MetadataCreated().processReceipt( tx_receipt, errors=DISCARD) updated_event = dt_contract.events.MetadataUpdated().processReceipt( tx_receipt, errors=DISCARD) if not created_event and not updated_event: return jsonify( error="No metadata created/updated event found in tx."), 400 es_instance = ElasticsearchInstance(config_file) allowed_publishers = get_allowed_publishers() purgatory = (Purgatory(es_instance) if (os.getenv("ASSET_PURGATORY_URL") or os.getenv("ACCOUNT_PURGATORY_URL")) else None) chain_id = web3.eth.chain_id processor_args = [ es_instance, web3, allowed_publishers, purgatory, chain_id ] processor = (MetadataCreatedProcessor if created_event else MetadataUpdatedProcessor) event_to_process = created_event[ 0] if created_event else updated_event[0] event_processor = processor( *([event_to_process, dt_contract, tx_receipt["from"]] + processor_args)) event_processor.process() did = make_did(dt_address, chain_id) response = app.response_class( response=sanitize_record(es_instance.get(did)), status=200, mimetype="application/json", ) return response except Exception as e: logger.error(f"trigger_caching failed: {str(e)}.") return ( jsonify( error=f"Encountered error when triggering caching: {str(e)}."), 500, )
def get_ddo(did): """Get DDO of a particular asset. --- tags: - ddo parameters: - name: did in: path description: DID of the asset. required: true type: string responses: 200: description: On successful operation returns DDO information. example: application/json: { "@context": "https://w3id.org/did/v1", "id": "did:op:00018b5b84eA05930f9D0dB8FFbb3B93EF86983b", "publicKey": [ { "id": "did:op:00018b5b84eA05930f9D0dB8FFbb3B93EF86983b", "type": "EthereumECDSAKey", "owner": "0x8aa92201E19E4930d4D25c0f7a245c1dCdD5A242" } ], "authentication": [ { "type": "RsaSignatureAuthentication2018", "publicKey": "did:op:00018b5b84eA05930f9D0dB8FFbb3B93EF86983b" } ], "service": [ { "type": "metadata", "attributes": { "main": { "type": "dataset", "name": "Nu nl", "dateCreated": "2021-04-02T17:59:32Z", "author": "ab", "license": "MIT", "files": [ { "index": 0, "contentType": "application/json" } ], "datePublished": "2021-04-20T22:56:01Z" }, "encryptedFiles": "0x047c992274f3fa2bf9c5cc57d0e0852f7b3ec22d7ab4e798e3e73e77e7f97" }, "index": 0 }, { "type": "access", "index": 1, "serviceEndpoint": "https://provider.datatunnel.allianceblock.io", "attributes": { "main": { "creator": "0x8aa92201E19E4930d4D25c0f7a245c1dCdD5A242", "datePublished": "2021-04-02T17:57:57Z", "cost": "1", "timeout": 2592000000, "name": "dataAssetAccess" } } } ], "datatoken": "0x00018b5b84eA05930f9D0dB8FFbb3B93EF86983b", "created": "2021-04-02T18:00:01Z", "proof": { "created": "2021-04-02T17:59:33Z", "creator": "0x8aa92201E19E4930d4D25c0f7a245c1dCdD5A242", "type": "AddressHash", "signatureValue": "0xd23d2f28fcf152347e5b5f1064422ba0288dd608f0ea6cf433a3717fb735a92d" }, "datatokenInfo": { "address": "0x00018b5b84eA05930f9D0dB8FFbb3B93EF86983b", "name": "Parsimonious Plankton Token", "symbol": "PARPLA-59", "decimals": 18, "totalSupply": 100.0, "cap": 1000.0, "minter": "0x8aa92201E19E4930d4D25c0f7a245c1dCdD5A242", "minterBalance": 99.999 }, "updated": "2021-04-02T18:00:01Z", "price": { "datatoken": 0.0, "ocean": 0.0, "value": 0.0, "type": "", "exchange_id": "", "address": "", "pools": [], "isConsumable": "" }, "isInPurgatory": "false" } content: application/json: schema: type: object 404: description: This asset DID is not in ES. """ try: asset_record = es_instance.get(did) response = app.response_class( response=sanitize_record(asset_record), status=200, mimetype="application/json", ) return response except elasticsearch.exceptions.NotFoundError: return jsonify( error=f"Asset DID {did} not found in Elasticsearch."), 404 except Exception as e: return ( jsonify( error= f"Error encountered while searching the asset DID {did}: {str(e)}." ), 404, )
def test_sanitize_record(): record = {"_id": "something", "other_value": "something else"} result = json.loads(sanitize_record(record)) assert "_id" not in result assert result["other_value"] == "something else"