#!/usr/bin/env python3 import pytest from conftest import extract_server_address_from from context import PytestConf from remote_server import NodeGraphQL from validate import check_query_f pytestmark = [ pytest.mark.admin_secret, pytest.mark.hge_env('HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS', 'true'), ] @pytest.fixture(scope='class') @pytest.mark.early def graphql_service_1(worker_id: str, hge_fixture_env: dict[str, str]): (_, port) = extract_server_address_from('GRAPHQL_SERVICE_1') server = NodeGraphQL(worker_id, 'remote_schemas/nodejs/remote_schema_perms.js', port=port) server.start() print(f'{graphql_service_1.__name__} server started on {server.url}') hge_fixture_env['GRAPHQL_SERVICE_1'] = server.url yield server server.stop() @pytest.fixture(scope='class') @pytest.mark.early def graphql_service_2(worker_id: str, hge_fixture_env: dict[str, str]): (_, port) = extract_server_address_from('GRAPHQL_SERVICE_2') server = NodeGraphQL(worker_id, 'remote_schemas/nodejs/secondary_remote_schema_perms.js', port=port) server.start() print(f'{graphql_service_2.__name__} server started on {server.url}') hge_fixture_env['GRAPHQL_SERVICE_2'] = server.url yield server server.stop() @pytest.fixture(scope='class') @pytest.mark.early def graphql_service_3(worker_id: str, hge_fixture_env: dict[str, str]): (_, port) = extract_server_address_from('GRAPHQL_SERVICE_3') server = NodeGraphQL(worker_id, 'remote_schemas/nodejs/secondary_remote_schema_perms_error.js', port=port) server.start() print(f'{graphql_service_3.__name__} server started on {server.url}') hge_fixture_env['GRAPHQL_SERVICE_3'] = server.url yield server server.stop() use_test_fixtures = pytest.mark.usefixtures( 'graphql_service_1', 'graphql_service_2', 'graphql_service_3', 'per_method_tests_db_state', ) @use_test_fixtures class TestAddRemoteSchemaPermissions: @classmethod def dir(cls): return "queries/remote_schemas/permissions/" def test_add_permission_with_valid_subset_of_fields(self, hge_ctx): hge_ctx.v1metadataq_f(self.dir() + 'add_permission_with_valid_subset_of_fields.yaml') """ Here the schemas are compatible """ def test_update_remote_schema_details_with_permissions_set(self, hge_ctx): """ Permissions check """ hge_ctx.v1metadataq_f(self.dir() + 'add_permission_with_valid_subset_of_fields.yaml') hge_ctx.v1metadataq_f(self.dir() + 'update_remote_schema/update_schema.yaml') """ check the details of remote schema in metadata """ resp = hge_ctx.v1metadataq({"type": "export_metadata", "args": {}}) assert resp['remote_schemas'][0]['definition']['url'] == "{{GRAPHQL_SERVICE_2}}" assert resp['remote_schemas'][0]['comment'] == 'this is from update query', resp assert resp['remote_schemas'][0]['definition']['timeout_seconds'] == 120, resp """ reset the changes to the original config """ hge_ctx.v1metadataq_f(self.dir() + 'update_remote_schema/revert_to_original_config.yaml') def test_update_remote_schema_details_with_permissions_set_with_error(self, hge_ctx): hge_ctx.v1metadataq_f(self.dir() + 'add_permission_with_valid_subset_of_fields.yaml') hge_ctx.v1metadataq_f(self.dir() + 'update_remote_schema/update_schema_error.yaml', expected_status_code = 400) def test_add_permission_with_valid_subset_of_arguments(self, hge_ctx): hge_ctx.v1metadataq_f(self.dir() + 'add_permission_with_valid_subset_of_arguments.yaml') def test_role_based_schema_enums_validation(self, hge_ctx): check_query_f(hge_ctx, self.dir() + 'role_based_schema_enum_validations.yaml') def test_role_based_schema_scalars_validation(self, hge_ctx): check_query_f(hge_ctx, self.dir() + 'role_based_schema_scalar_validation.yaml') def test_role_based_schema_interface_validation(self, hge_ctx): check_query_f(hge_ctx, self.dir() + 'role_based_schema_interface_validation.yaml') def test_role_based_schema_union_validation(self, hge_ctx): check_query_f(hge_ctx, self.dir() + 'role_based_schema_union_validation.yaml') def test_role_based_schema_input_object_validation(self, hge_ctx): check_query_f(hge_ctx, self.dir() + 'role_based_schema_input_object_validation.yaml') def test_role_based_schema_object_validation(self, hge_ctx): check_query_f(hge_ctx, self.dir() + 'role_based_schema_object_validation.yaml') def test_preset_directive_validation(self, hge_ctx): check_query_f(hge_ctx, self.dir() + 'argument_preset_validation.yaml') @use_test_fixtures class TestRemoteSchemaPermissionsExecution: @classmethod def dir(cls): return "queries/remote_schemas/permissions/" def test_execution_with_subset_of_fields_exposed_to_role(self, hge_ctx): hge_ctx.v1metadataq_f(self.dir() + 'add_permission_with_valid_subset_of_fields.yaml') check_query_f(hge_ctx, self.dir() + 'execution_with_partial_fields_exposed_to_role.yaml') @pytest.mark.skipif(not PytestConf.config.getoption('--redis-url'), reason="Must enable redis") def test_execution_with_subset_of_fields_exposed_to_role_with_caching(self, hge_ctx): hge_ctx.v1metadataq_f(self.dir() + 'add_permission_with_valid_subset_of_fields.yaml') check_query_f(hge_ctx, self.dir() + 'execution_with_partial_fields_exposed_to_role_cached.yaml') def test_execution_with_subset_of_arguments_exposed_to_role(self, hge_ctx): hge_ctx.v1metadataq_f(self.dir() + 'add_permission_with_valid_subset_of_arguments.yaml') check_query_f(hge_ctx, self.dir() + 'execution_with_partial_args_exposed_to_role.yaml') def test_execution_with_unknown_role(self, hge_ctx): check_query_f(hge_ctx, self.dir() + 'unknown_role_execution.yaml') @use_test_fixtures class TestCustomizedRemoteSchemaPermissionsExecution: @classmethod def dir(cls): return "queries/remote_schemas/permissions/schema_customization/" def test_execution_with_subset_of_fields_exposed_to_role(self, hge_ctx): hge_ctx.v1metadataq_f(self.dir() + 'add_permission_with_valid_subset_of_fields.yaml') check_query_f(hge_ctx, self.dir() + 'execution_with_partial_fields_exposed_to_role.yaml') def test_execution_with_subset_of_arguments_exposed_to_role(self, hge_ctx): hge_ctx.v1metadataq_f(self.dir() + 'add_permission_with_valid_subset_of_arguments.yaml') check_query_f(hge_ctx, self.dir() + 'execution_with_partial_args_exposed_to_role.yaml') @use_test_fixtures class TestRemoteSchemaPermissionsArgumentPresets: @classmethod def dir(cls): return "queries/remote_schemas/permissions/argument_presets/" def test_execution_with_static_argument_preset(self, hge_ctx): hge_ctx.v1metadataq_f(self.dir() + 'add_permission_with_static_preset_argument.yaml') check_query_f(hge_ctx, self.dir() + 'execution_with_static_preset_args.yaml') def test_execution_with_session_argument_preset(self, hge_ctx): hge_ctx.v1metadataq_f(self.dir() + 'add_permission_with_session_preset_argument.yaml') check_query_f(hge_ctx, self.dir() + 'execution_with_session_preset_args.yaml') @pytest.mark.usefixtures( 'graphql_service_1', 'graphql_service_2', 'graphql_service_3', ) class TestRemoteRelationshipPermissions: @classmethod def dir(cls): return "queries/remote_schemas/permissions/remote_relationships/" @pytest.fixture(autouse=True) def transact(self, hge_ctx): hge_ctx.v1q_f(self.dir() + 'setup_with_permissions.yaml') yield hge_ctx.v1q_f(self.dir() + 'teardown.yaml') def test_basic_relationship(self, hge_ctx): hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic.yaml') hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic_user.yaml') check_query_f(hge_ctx, self.dir() + 'basic_remote_relationship_without_remote_schema_permissions_configured.yaml') check_query_f(hge_ctx, self.dir() + 'basic_remote_relationship_with_remote_schema_permissions_configured.yaml') # Test queries that combine several remote relationships, nested in # different ways, variously filtering different bits using permissions. def test_complex_multiple_joins(self, hge_ctx): hge_ctx.v1q_f(self.dir() + 'setup_multiple_remote_rel.yaml') check_query_f(hge_ctx, self.dir() + 'complex_multiple_joins.yaml') def test_remote_relationship_with_field_containing_preset_argument(self, hge_ctx): hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic.yaml') check_query_f(hge_ctx, self.dir() + 'derive_remote_relationship_with_joining_field_containing_preset.yaml') def test_partial_arguments_of_remote_relationship_from_preset(self, hge_ctx): hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_messages_single_field.yaml') check_query_f(hge_ctx, self.dir() + 'partial_arguments_from_preset.yaml')