diff --git a/server/src-lib/Hasura/Server/API/Metadata.hs b/server/src-lib/Hasura/Server/API/Metadata.hs index be77778eb7f..8d1f7ee68ec 100644 --- a/server/src-lib/Hasura/Server/API/Metadata.hs +++ b/server/src-lib/Hasura/Server/API/Metadata.hs @@ -94,6 +94,10 @@ data RQLMetadata | RMReloadRemoteSchema !RemoteSchemaNameQuery | RMIntrospectRemoteSchema !RemoteSchemaNameQuery + -- remote-schema permissions + | RMAddRemoteSchemaPermissions !AddRemoteSchemaPermissions + | RMDropRemoteSchemaPermissions !DropRemoteSchemaPermissions + -- scheduled triggers | RMCreateCronTrigger !CreateCronTrigger | RMDeleteCronTrigger !ScheduledTriggerName @@ -185,11 +189,12 @@ runMetadataQueryM , HTTP.HasHttpManagerM m , MetadataM m , MonadMetadataStorageQueryAPI m + , HasRemoteSchemaPermsCtx m ) => Env.Environment -> RQLMetadata -> m EncJSON -runMetadataQueryM env = \case +runMetadataQueryM env = withPathK "args" . \case RMPgAddSource q -> runAddPgSource q RMPgDropSource q -> runDropPgSource q @@ -238,6 +243,9 @@ runMetadataQueryM env = \case RMReloadRemoteSchema q -> runReloadRemoteSchema q RMIntrospectRemoteSchema q -> runIntrospectRemoteSchema q + RMAddRemoteSchemaPermissions q -> runAddRemoteSchemaPermissions q + RMDropRemoteSchemaPermissions q -> runDropRemoteSchemaPermissions q + RMCreateCronTrigger q -> runCreateCronTrigger q RMDeleteCronTrigger q -> runDeleteCronTrigger q RMCreateScheduledEvent q -> runCreateScheduledEvent q diff --git a/server/src-lib/Hasura/Server/API/Query.hs b/server/src-lib/Hasura/Server/API/Query.hs index eac4b4de665..fba995eed12 100644 --- a/server/src-lib/Hasura/Server/API/Query.hs +++ b/server/src-lib/Hasura/Server/API/Query.hs @@ -98,10 +98,6 @@ data RQLQueryV1 | RQReloadRemoteSchema !RemoteSchemaNameQuery | RQIntrospectRemoteSchema !RemoteSchemaNameQuery - -- remote-schema permissions - | RQAddRemoteSchemaPermissions !AddRemoteSchemaPermissions - | RQDropRemoteSchemaPermissions !DropRemoteSchemaPermissions - | RQCreateEventTrigger !CreateEventTriggerQuery | RQDeleteEventTrigger !DeleteEventTriggerQuery | RQRedeliverEvent !RedeliverEventQuery @@ -268,9 +264,6 @@ queryModifiesSchemaCache (RQV1 qi) = case qi of RQReloadRemoteSchema _ -> True RQIntrospectRemoteSchema _ -> False - RQAddRemoteSchemaPermissions _ -> True - RQDropRemoteSchemaPermissions _ -> True - RQCreateEventTrigger _ -> True RQDeleteEventTrigger _ -> True RQRedeliverEvent _ -> False @@ -407,9 +400,6 @@ runQueryM env rq = withPathK "args" $ case rq of RQReloadRemoteSchema q -> runReloadRemoteSchema q RQIntrospectRemoteSchema q -> runIntrospectRemoteSchema q - RQAddRemoteSchemaPermissions q -> runAddRemoteSchemaPermissions q - RQDropRemoteSchemaPermissions q -> runDropRemoteSchemaPermissions q - RQCreateRemoteRelationship q -> runCreateRemoteRelationship q RQUpdateRemoteRelationship q -> runUpdateRemoteRelationship q RQDeleteRemoteRelationship q -> runDeleteRemoteRelationship q @@ -505,9 +495,6 @@ requiresAdmin = \case RQReloadRemoteSchema _ -> True RQIntrospectRemoteSchema _ -> True - RQAddRemoteSchemaPermissions _ -> True - RQDropRemoteSchemaPermissions _ -> True - RQCreateEventTrigger _ -> True RQDeleteEventTrigger _ -> True RQRedeliverEvent _ -> True diff --git a/server/tests-py/context.py b/server/tests-py/context.py index c7a3059dd57..df0bfc2c7f2 100644 --- a/server/tests-py/context.py +++ b/server/tests-py/context.py @@ -521,12 +521,12 @@ class HGECtx: conn.close() return res - def v1q(self, q, headers = {}): + def execute_query(self, q, url_path, headers = {}): h = headers.copy() if self.hge_key is not None: h['X-Hasura-Admin-Secret'] = self.hge_key resp = self.http.post( - self.hge_url + "/v1/query", + self.hge_url + url_path, json=q, headers=h ) @@ -534,12 +534,25 @@ class HGECtx: # properties in the graphql spec properly return resp.status_code, resp.json(object_pairs_hook=OrderedDict) + + def v1q(self, q, headers = {}): + return self.execute_query(q, "/v1/query", headers) + def v1q_f(self, fn): with open(fn) as f: # NOTE: preserve ordering with ruamel yml = yaml.YAML() return self.v1q(yml.load(f)) + def v1metadataq(self, q, headers = {}): + return self.execute_query(q, "/v1/metadata", headers) + + def v1metadataq_f(self, fn): + with open(fn) as f: + # NOTE: preserve ordering with ruamel + yml = yaml.YAML() + return self.v1metadataq(yml.load(f)) + def teardown(self): self.http.close() self.engine.dispose() diff --git a/server/tests-py/queries/remote_schemas/permissions/argument_preset_validation.yaml b/server/tests-py/queries/remote_schemas/permissions/argument_preset_validation.yaml index e53bcc8eed5..eb1c5065366 100644 --- a/server/tests-py/queries/remote_schemas/permissions/argument_preset_validation.yaml +++ b/server/tests-py/queries/remote_schemas/permissions/argument_preset_validation.yaml @@ -1,5 +1,5 @@ - description: adding preset directive at the wrong location - url: /v1/query + url: /v1/metadata status: 400 query: type: add_remote_schema_permissions @@ -21,7 +21,7 @@ code: validation-failed - description: adding an invalid directive preset value - url: /v1/query + url: /v1/metadata status: 400 query: type: add_remote_schema_permissions @@ -80,7 +80,7 @@ code: validation-failed - description: adding an invalid directive preset value - url: /v1/query + url: /v1/metadata status: 400 query: type: add_remote_schema_permissions diff --git a/server/tests-py/queries/remote_schemas/permissions/role_based_schema_enum_validations.yaml b/server/tests-py/queries/remote_schemas/permissions/role_based_schema_enum_validations.yaml index f9b98236622..9e9846fd182 100644 --- a/server/tests-py/queries/remote_schemas/permissions/role_based_schema_enum_validations.yaml +++ b/server/tests-py/queries/remote_schemas/permissions/role_based_schema_enum_validations.yaml @@ -1,5 +1,5 @@ - description: Include Enum Occupation which doesn't exist in the remote schema - url: /v1/query + url: /v1/metadata status: 400 response: path: $.args @@ -33,7 +33,7 @@ } - description: Include unknown enum value "IDLE" in the 'MessageStatus' Enum - url: /v1/query + url: /v1/metadata status: 400 response: path: $.args @@ -70,7 +70,7 @@ } - description: Add duplicate enum value in the `MessageStatus` Enum - url: /v1/query + url: /v1/metadata status: 400 response: path: $.args diff --git a/server/tests-py/queries/remote_schemas/permissions/role_based_schema_input_object_validation.yaml b/server/tests-py/queries/remote_schemas/permissions/role_based_schema_input_object_validation.yaml index e29bcb478fa..dfb072d4d97 100644 --- a/server/tests-py/queries/remote_schemas/permissions/role_based_schema_input_object_validation.yaml +++ b/server/tests-py/queries/remote_schemas/permissions/role_based_schema_input_object_validation.yaml @@ -2,7 +2,7 @@ description: The types of the fields of the input 'IntCompareObj' object in the upstream remote schema is 'Int', so a different type should throw an error -url: /v1/query +url: /v1/metadata status: 400 query: type: add_remote_schema_permissions diff --git a/server/tests-py/queries/remote_schemas/permissions/role_based_schema_interface_validation.yaml b/server/tests-py/queries/remote_schemas/permissions/role_based_schema_interface_validation.yaml index 258556a9825..8caaad04e8f 100644 --- a/server/tests-py/queries/remote_schemas/permissions/role_based_schema_interface_validation.yaml +++ b/server/tests-py/queries/remote_schemas/permissions/role_based_schema_interface_validation.yaml @@ -1,5 +1,5 @@ description: Include unknown field "timestamp" in the "Communication" interface -url: /v1/query +url: /v1/metadata status: 400 query: type: add_remote_schema_permissions diff --git a/server/tests-py/queries/remote_schemas/permissions/role_based_schema_object_validation.yaml b/server/tests-py/queries/remote_schemas/permissions/role_based_schema_object_validation.yaml index 04540a79c82..b2485eeddfb 100644 --- a/server/tests-py/queries/remote_schemas/permissions/role_based_schema_object_validation.yaml +++ b/server/tests-py/queries/remote_schemas/permissions/role_based_schema_object_validation.yaml @@ -1,7 +1,7 @@ - description: The types of the fields of the 'User' object have been changed, 'user_id' has the type 'Int' in the upstream remote schema and the field 'created_at' doesn't exist in the upstream remote schema. - url: /v1/query + url: /v1/metadata status: 400 query: type: add_remote_schema_permissions @@ -33,7 +33,7 @@ - description: The 'Person' object is implementing the interface 'FullName' which doesn't exist in the remote schema - url: /v1/query + url: /v1/metadata status: 400 query: type: add_remote_schema_permissions @@ -72,7 +72,7 @@ - description: The 'user' field in the 'Query' object doesn't have all the non-nullable arguments that the corresponding remote 'user' field implements. - url: /v1/query + url: /v1/metadata status: 400 query: type: add_remote_schema_permissions diff --git a/server/tests-py/queries/remote_schemas/permissions/role_based_schema_scalar_validation.yaml b/server/tests-py/queries/remote_schemas/permissions/role_based_schema_scalar_validation.yaml index 8a9af865b9a..d7301d539e7 100644 --- a/server/tests-py/queries/remote_schemas/permissions/role_based_schema_scalar_validation.yaml +++ b/server/tests-py/queries/remote_schemas/permissions/role_based_schema_scalar_validation.yaml @@ -1,5 +1,5 @@ description: Include Enum Occupation which doesn't exist in the remote schema -url: /v1/query +url: /v1/metadata status: 400 query: type: add_remote_schema_permissions diff --git a/server/tests-py/queries/remote_schemas/permissions/role_based_schema_union_validation.yaml b/server/tests-py/queries/remote_schemas/permissions/role_based_schema_union_validation.yaml index 9245793ef0b..19ceebc4dae 100644 --- a/server/tests-py/queries/remote_schemas/permissions/role_based_schema_union_validation.yaml +++ b/server/tests-py/queries/remote_schemas/permissions/role_based_schema_union_validation.yaml @@ -1,5 +1,5 @@ description: Provide a member type 'Message' in the 'SearchResult' which doesn't exist in the upstream remote -url: /v1/query +url: /v1/metadata status: 400 query: type: add_remote_schema_permissions diff --git a/server/tests-py/test_remote_schema_permissions.py b/server/tests-py/test_remote_schema_permissions.py index cb89d0cadcc..115f5eae366 100644 --- a/server/tests-py/test_remote_schema_permissions.py +++ b/server/tests-py/test_remote_schema_permissions.py @@ -31,11 +31,11 @@ class TestAddRemoteSchemaPermissions: return "queries/remote_schemas/permissions/" def test_add_permission_with_valid_subset_of_fields(self, hge_ctx): - st_code, resp = hge_ctx.v1q_f(self.dir() + 'add_permission_with_valid_subset_of_fields.yaml') + st_code, resp = hge_ctx.v1metadataq_f(self.dir() + 'add_permission_with_valid_subset_of_fields.yaml') assert st_code == 200, resp def test_add_permission_with_valid_subset_of_arguments(self, hge_ctx): - st_code, resp = hge_ctx.v1q_f(self.dir() + 'add_permission_with_valid_subset_of_arguments.yaml') + st_code, resp = hge_ctx.v1metadataq_f(self.dir() + 'add_permission_with_valid_subset_of_arguments.yaml') assert st_code == 200, resp def test_role_based_schema_enums_validation(self, hge_ctx): @@ -67,12 +67,12 @@ class TestRemoteSchemaPermissionsExecution: return "queries/remote_schemas/permissions/" def test_execution_with_subset_of_fields_exposed_to_role(self, hge_ctx): - st_code, resp = hge_ctx.v1q_f(self.dir() + 'add_permission_with_valid_subset_of_fields.yaml') + st_code, resp = hge_ctx.v1metadataq_f(self.dir() + 'add_permission_with_valid_subset_of_fields.yaml') assert st_code == 200, resp 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): - st_code, resp = hge_ctx.v1q_f(self.dir() + 'add_permission_with_valid_subset_of_arguments.yaml') + st_code, resp = hge_ctx.v1metadataq_f(self.dir() + 'add_permission_with_valid_subset_of_arguments.yaml') assert st_code == 200, resp check_query_f(hge_ctx, self.dir() + 'execution_with_partial_args_exposed_to_role.yaml') @@ -88,11 +88,11 @@ class TestRemoteSchemaPermissionsArgumentPresets: return "queries/remote_schemas/permissions/argument_presets/" def test_execution_with_static_argument_preset(self, hge_ctx): - st_code, resp = hge_ctx.v1q_f(self.dir() + 'add_permission_with_static_preset_argument.yaml') + st_code, resp = hge_ctx.v1metadataq_f(self.dir() + 'add_permission_with_static_preset_argument.yaml') assert st_code == 200, resp check_query_f(hge_ctx, self.dir() + 'execution_with_static_preset_args.yaml') def test_execution_with_session_argument_preset(self, hge_ctx): - st_code, resp = hge_ctx.v1q_f(self.dir() + 'add_permission_with_session_preset_argument.yaml') + st_code, resp = hge_ctx.v1metadataq_f(self.dir() + 'add_permission_with_session_preset_argument.yaml') assert st_code == 200, resp check_query_f(hge_ctx, self.dir() + 'execution_with_session_preset_args.yaml')