diff --git a/ocean_provider/validation/algo.py b/ocean_provider/validation/algo.py index b3d870ad..5104a8f2 100644 --- a/ocean_provider/validation/algo.py +++ b/ocean_provider/validation/algo.py @@ -14,6 +14,8 @@ get_asset_from_metadatastore, ) from ocean_provider.utils.basics import get_metadata_url, get_provider_wallet, get_web3 +from ocean_provider.utils.consumable import ConsumableCodes +from ocean_provider.utils.credentials import AddressCredential from ocean_provider.utils.datatoken import ( record_consume_request, validate_order, @@ -414,6 +416,14 @@ def validate(self): self.message = message return False + manager = AddressCredential(self.asset) + code = manager.validate_access(self.asset.credentials) + + if code != ConsumableCodes.OK: + self.resource += ".credentials" + self.message = "restricted_access_for_algo" + return False + if self.service.type not in ["access", "compute"]: self.resource += ".serviceId" self.message = "service_not_access_compute" diff --git a/ocean_provider/validation/test/test_algo_validation.py b/ocean_provider/validation/test/test_algo_validation.py index e94f9555..b78a1ec1 100644 --- a/ocean_provider/validation/test/test_algo_validation.py +++ b/ocean_provider/validation/test/test_algo_validation.py @@ -1010,3 +1010,25 @@ def side_effect(*args, **kwargs): assert validator.validate() is False assert validator.resource == "algorithm" assert validator.message == "file_unavailable" + + +def test_algo_credentials(provider_address, consumer_address): + ddo = Asset(ddo_dict) + alg_ddo_dict["credentials"] = {"allow": [], "deny": [consumer_address]} + alg_ddo = Asset(alg_ddo_dict) + sa_compute = get_first_service_by_type(alg_ddo, ServiceType.ACCESS) + sa = get_first_service_by_type(ddo, ServiceType.COMPUTE) + + data = { + "dataset": {"documentId": ddo.did, "serviceId": sa.id, "transferTxId": "tx_id"}, + "algorithm": { + "documentId": alg_ddo.did, + "serviceId": sa_compute.id, + "transferTxId": "alg_tx_id", + }, + } + + validator = WorkflowValidator(consumer_address, data) + assert validator.validate() is False + # assert validator.resource == "credentials" + # assert validator.message == "restricted_access_for_algo" diff --git a/tests/helpers/compute_helpers.py b/tests/helpers/compute_helpers.py index 119a8cab..19342433 100644 --- a/tests/helpers/compute_helpers.py +++ b/tests/helpers/compute_helpers.py @@ -25,6 +25,8 @@ def build_and_send_ddo_with_compute_service( publisher_wallet, consumer_wallet, alg_diff=False, + custom_dataset_credentials=None, + custom_algo_credentials=None, asset_type=None, c2d_address=None, do_send=True, @@ -39,11 +41,11 @@ def build_and_send_ddo_with_compute_service( algo_metadata = build_metadata_dict_type_algorithm() if c2d_address is None: c2d_address = consumer_wallet.address - if alg_diff: + if custom_algo_credentials: alg_ddo = get_registered_asset( publisher_wallet, custom_metadata=algo_metadata, - custom_service_endpoint="http://172.15.0.7:8030", + custom_credentials=custom_algo_credentials, timeout=timeout, unencrypted_files_list=[ {"url": this_is_a_gist, "type": "url", "method": "GET"} @@ -58,7 +60,6 @@ def build_and_send_ddo_with_compute_service( {"url": this_is_a_gist, "type": "url", "method": "GET"} ], ) - # publish an algorithm asset (asset with metadata of type `algorithm`) service = get_first_service_by_type(alg_ddo, ServiceType.ACCESS) mint_100_datatokens( diff --git a/tests/test_compute.py b/tests/test_compute.py index bc44d3af..1163830e 100644 --- a/tests/test_compute.py +++ b/tests/test_compute.py @@ -649,3 +649,53 @@ def test_compute_auth_token(client, publisher_wallet, consumer_wallet, free_c2d_ token = create_token(client, consumer_wallet) response = post_to_compute(client, payload, headers={"AuthToken": token}) assert response.status_code == 200, f"{response.data}" + + +@pytest.mark.integration +def test_algo_credentials( + client, publisher_wallet, consumer_wallet, free_c2d_env, web3 +): + valid_until = get_future_valid_until() + deployer_wallet = Account.from_key(os.getenv("FACTORY_DEPLOYER_PRIVATE_KEY")) + fee_token = get_datatoken_contract(web3, get_ocean_token_address(web3)) + fee_token.functions.mint(consumer_wallet.address, to_wei(80)).transact( + {"from": deployer_wallet.address} + ) + + algo_credentials = {"allow": [], "deny": [consumer_wallet.address]} + + ddo, tx_id, alg_ddo, alg_tx_id = build_and_send_ddo_with_compute_service( + client, + publisher_wallet, + consumer_wallet, + False, + custom_algo_credentials=algo_credentials, + c2d_address=free_c2d_env["consumerAddress"], + valid_until=valid_until, + c2d_environment=free_c2d_env["id"], + fee_token_args=(fee_token, to_wei(80)), + ) + sa_compute = get_first_service_by_type(alg_ddo, ServiceType.ACCESS) + sa = get_first_service_by_type(ddo, ServiceType.COMPUTE) + nonce, signature = get_compute_signature(client, consumer_wallet, ddo.did) + + # Start the compute job + payload = { + "dataset": {"documentId": ddo.did, "serviceId": sa.id, "transferTxId": tx_id}, + "algorithm": { + "serviceId": sa_compute.id, + "documentId": alg_ddo.did, + "transferTxId": alg_tx_id, + }, + "signature": signature, + "nonce": nonce, + "consumerAddress": consumer_wallet.address, + "environment": free_c2d_env["id"], + } + + # Start compute with valid signature + response = post_to_compute(client, payload) + assert ( + response.status == "400 BAD REQUEST" + ), f"start compute job failed: {response.data}" + print(f"resp: {response.content}")