2021-09-24 01:56:37 +03:00
|
|
|
-- | BackendAPI
|
|
|
|
--
|
|
|
|
-- This module defines the 'BackendAPI' class, alongside a few helpers. Its goal is to delegate to
|
|
|
|
-- backends the responsibility of creating the parsers for the metadata API. Each backend is expected
|
|
|
|
-- to provide a list of 'CommandParser', which in turn is a simple function from command name and
|
|
|
|
-- command arguments to a corresponding parser. Command parsers can easily be created using the
|
|
|
|
-- 'commandParser' function.
|
|
|
|
--
|
|
|
|
-- Furthermore, for each set of related features, such as table tracking commands, or permission
|
|
|
|
-- commands, a helper function is provided, that allows a backend to write its instance by simply
|
|
|
|
-- listing the set of features it supports.
|
2021-11-04 19:08:33 +03:00
|
|
|
module Hasura.Server.API.Backend
|
|
|
|
( BackendAPI (..),
|
|
|
|
commandParser,
|
|
|
|
eventTriggerCommands,
|
|
|
|
functionCommands,
|
|
|
|
functionPermissionsCommands,
|
|
|
|
relationshipCommands,
|
|
|
|
remoteRelationshipCommands,
|
|
|
|
sourceCommands,
|
|
|
|
tableCommands,
|
|
|
|
tablePermissionsCommands,
|
2022-05-04 17:52:29 +03:00
|
|
|
computedFieldCommands,
|
2021-11-04 19:08:33 +03:00
|
|
|
)
|
|
|
|
where
|
2021-07-07 04:43:42 +03:00
|
|
|
|
2021-09-24 01:56:37 +03:00
|
|
|
import Data.Aeson ((<?>))
|
2022-04-29 05:13:13 +03:00
|
|
|
import Data.Aeson.Extended (FromJSONWithContext (..))
|
2021-09-24 01:56:37 +03:00
|
|
|
import Data.Aeson.Types (modifyFailure)
|
|
|
|
import Data.Aeson.Types qualified as J
|
|
|
|
import Data.Text qualified as T
|
|
|
|
import Hasura.Prelude
|
|
|
|
import Hasura.RQL.Types.Backend
|
|
|
|
import Hasura.SQL.AnyBackend
|
|
|
|
import Hasura.SQL.Backend
|
|
|
|
import {-# SOURCE #-} Hasura.Server.API.Metadata
|
2021-07-07 04:43:42 +03:00
|
|
|
|
|
|
|
-- API class
|
|
|
|
|
2022-04-29 05:13:13 +03:00
|
|
|
type CommandParser b = BackendSourceKind b -> Text -> J.Value -> J.Parser (Maybe RQLMetadataV1)
|
2021-07-07 04:43:42 +03:00
|
|
|
|
|
|
|
class BackendAPI (b :: BackendType) where
|
2022-04-29 05:13:13 +03:00
|
|
|
metadataV1CommandParsers :: [CommandParser b]
|
2021-07-07 04:43:42 +03:00
|
|
|
|
|
|
|
-- helpers
|
|
|
|
|
2022-04-29 05:13:13 +03:00
|
|
|
commandParserWithExplicitParser ::
|
|
|
|
-- | Explicit parsing function that also takes a BackendKind
|
|
|
|
(BackendSourceKind b -> J.Value -> J.Parser a) ->
|
2021-09-24 01:56:37 +03:00
|
|
|
-- | expected command name
|
|
|
|
Text ->
|
|
|
|
-- | corresponding parser
|
|
|
|
(a -> RQLMetadataV1) ->
|
2022-04-29 05:13:13 +03:00
|
|
|
CommandParser b
|
|
|
|
commandParserWithExplicitParser parseJSONWithBackendKind expected constructor backendKind provided arguments =
|
2021-07-07 04:43:42 +03:00
|
|
|
-- We return a Maybe parser here if the command name doesn't match, as Aeson's alternative
|
|
|
|
-- instance backtracks: if we used 'fail', we would not be able to distinguish between "this is
|
|
|
|
-- the correct branch, the name matches, but the argument fails to parse, we must fail" and "this
|
|
|
|
-- is not the command we were expecting here, it is fine to continue with another".
|
2021-09-20 22:49:33 +03:00
|
|
|
whenMaybe (expected == provided) $
|
2022-04-29 05:13:13 +03:00
|
|
|
modifyFailure withDetails $ constructor <$> (parseJSONWithBackendKind backendKind arguments <?> J.Key "args")
|
2021-09-20 22:49:33 +03:00
|
|
|
where
|
2021-09-24 01:56:37 +03:00
|
|
|
withDetails internalErrorMessage =
|
|
|
|
intercalate
|
|
|
|
"\n"
|
|
|
|
[ "Error when parsing command " <> T.unpack expected <> ".",
|
|
|
|
"See our documentation at https://hasura.io/docs/latest/graphql/core/api-reference/metadata-api/index.html#metadata-apis.",
|
|
|
|
"Internal error message: " <> internalErrorMessage
|
|
|
|
]
|
2021-07-07 04:43:42 +03:00
|
|
|
|
2022-04-29 05:13:13 +03:00
|
|
|
commandParser ::
|
|
|
|
J.FromJSON a =>
|
|
|
|
-- | expected command name
|
|
|
|
Text ->
|
|
|
|
-- | corresponding parser
|
|
|
|
(a -> RQLMetadataV1) ->
|
|
|
|
CommandParser b
|
|
|
|
commandParser =
|
|
|
|
commandParserWithExplicitParser (const J.parseJSON) -- Ignore the backend source kind and just parse using the FromJSON instance
|
|
|
|
|
|
|
|
commandParserWithBackendKind ::
|
|
|
|
FromJSONWithContext (BackendSourceKind b) a =>
|
|
|
|
-- | expected command name
|
|
|
|
Text ->
|
|
|
|
-- | corresponding parser
|
|
|
|
(a -> RQLMetadataV1) ->
|
|
|
|
CommandParser b
|
|
|
|
commandParserWithBackendKind =
|
|
|
|
commandParserWithExplicitParser parseJSONWithContext
|
|
|
|
|
2021-09-24 01:56:37 +03:00
|
|
|
sourceCommands,
|
|
|
|
tableCommands,
|
|
|
|
tablePermissionsCommands,
|
|
|
|
functionCommands,
|
|
|
|
functionPermissionsCommands,
|
|
|
|
relationshipCommands,
|
|
|
|
remoteRelationshipCommands,
|
2022-05-04 17:52:29 +03:00
|
|
|
eventTriggerCommands,
|
|
|
|
computedFieldCommands ::
|
2021-09-24 01:56:37 +03:00
|
|
|
forall (b :: BackendType).
|
|
|
|
Backend b =>
|
2022-04-29 05:13:13 +03:00
|
|
|
[CommandParser b]
|
2021-07-07 04:43:42 +03:00
|
|
|
sourceCommands =
|
2022-04-29 05:13:13 +03:00
|
|
|
[ commandParserWithBackendKind "add_source" $ RMAddSource . mkAnyBackend @b,
|
2021-09-24 01:56:37 +03:00
|
|
|
commandParser "drop_source" $ RMDropSource,
|
2022-06-22 10:06:19 +03:00
|
|
|
commandParser "set_table_customization" $ RMSetTableCustomization . mkAnyBackend @b,
|
|
|
|
commandParserWithBackendKind "update_source" $ RMUpdateSource . mkAnyBackend @b
|
2021-07-07 04:43:42 +03:00
|
|
|
]
|
|
|
|
tableCommands =
|
2021-09-24 01:56:37 +03:00
|
|
|
[ commandParser "track_table" $ RMTrackTable . mkAnyBackend @b,
|
|
|
|
commandParser "untrack_table" $ RMUntrackTable . mkAnyBackend @b
|
2021-07-07 04:43:42 +03:00
|
|
|
]
|
|
|
|
tablePermissionsCommands =
|
2021-09-24 01:56:37 +03:00
|
|
|
[ commandParser "create_insert_permission" $ RMCreateInsertPermission . mkAnyBackend @b,
|
|
|
|
commandParser "create_select_permission" $ RMCreateSelectPermission . mkAnyBackend @b,
|
|
|
|
commandParser "create_update_permission" $ RMCreateUpdatePermission . mkAnyBackend @b,
|
|
|
|
commandParser "create_delete_permission" $ RMCreateDeletePermission . mkAnyBackend @b,
|
|
|
|
commandParser "drop_insert_permission" $ RMDropInsertPermission . mkAnyBackend @b,
|
|
|
|
commandParser "drop_select_permission" $ RMDropSelectPermission . mkAnyBackend @b,
|
|
|
|
commandParser "drop_update_permission" $ RMDropUpdatePermission . mkAnyBackend @b,
|
|
|
|
commandParser "drop_delete_permission" $ RMDropDeletePermission . mkAnyBackend @b,
|
|
|
|
commandParser "set_permission_comment" $ RMSetPermissionComment . mkAnyBackend @b
|
2021-07-07 04:43:42 +03:00
|
|
|
]
|
|
|
|
functionCommands =
|
2021-09-24 01:56:37 +03:00
|
|
|
[ commandParser "track_function" $ RMTrackFunction . mkAnyBackend @b,
|
2021-10-07 16:02:19 +03:00
|
|
|
commandParser "untrack_function" $ RMUntrackFunction . mkAnyBackend @b,
|
|
|
|
commandParser "set_function_customization" $ RMSetFunctionCustomization . mkAnyBackend @b
|
2021-07-07 04:43:42 +03:00
|
|
|
]
|
|
|
|
functionPermissionsCommands =
|
2021-09-24 01:56:37 +03:00
|
|
|
[ commandParser "create_function_permission" $ RMCreateFunctionPermission . mkAnyBackend @b,
|
|
|
|
commandParser "drop_function_permission" $ RMDropFunctionPermission . mkAnyBackend @b
|
2021-07-07 04:43:42 +03:00
|
|
|
]
|
|
|
|
relationshipCommands =
|
2021-09-24 01:56:37 +03:00
|
|
|
[ commandParser "create_object_relationship" $ RMCreateObjectRelationship . mkAnyBackend @b,
|
|
|
|
commandParser "create_array_relationship" $ RMCreateArrayRelationship . mkAnyBackend @b,
|
|
|
|
commandParser "set_relationship_comment" $ RMSetRelationshipComment . mkAnyBackend @b,
|
|
|
|
commandParser "rename_relationship" $ RMRenameRelationship . mkAnyBackend @b,
|
|
|
|
commandParser "drop_relationship" $ RMDropRelationship . mkAnyBackend @b
|
2021-07-07 04:43:42 +03:00
|
|
|
]
|
|
|
|
remoteRelationshipCommands =
|
2021-09-24 01:56:37 +03:00
|
|
|
[ commandParser "create_remote_relationship" $ RMCreateRemoteRelationship . mkAnyBackend @b,
|
|
|
|
commandParser "update_remote_relationship" $ RMUpdateRemoteRelationship . mkAnyBackend @b,
|
Fix several issues with remote relationships.
## Remaining Work
- [x] changelog entry
- [x] more tests: `<backend>_delete_remote_relationship` is definitely untested
- [x] negative tests: we probably want to assert that there are some APIs we DON'T support
- [x] update the console to use the new API, if necessary
- [x] ~~adding the corresponding documentation for the API for other backends (only `pg_` was added here)~~
- deferred to https://github.com/hasura/graphql-engine-mono/issues/3170
- [x] ~~deciding which backends should support this API~~
- deferred to https://github.com/hasura/graphql-engine-mono/issues/3170
- [x] ~~deciding what to do about potentially overlapping schematic representations~~
- ~~cf. https://github.com/hasura/graphql-engine-mono/pull/3157#issuecomment-995307624~~
- deferred to https://github.com/hasura/graphql-engine-mono/issues/3171
- [x] ~~add more descriptive versioning information to some of the types that are changing in this PR~~
- cf. https://github.com/hasura/graphql-engine-mono/pull/3157#discussion_r769830920
- deferred to https://github.com/hasura/graphql-engine-mono/issues/3172
## Description
This PR fixes several important issues wrt. the remote relationship API.
- it fixes a regression introduced by [#3124](https://github.com/hasura/graphql-engine-mono/pull/3124), which prevented `<backend>_create_remote_relationship` from accepting the old argument format (break of backwards compatibility, broke the console)
- it removes the command `create_remote_relationship` added to the v1/metadata API as a work-around as part of [#3124](https://github.com/hasura/graphql-engine-mono/pull/3124)
- it reverts the subsequent fix in the console: [#3149](https://github.com/hasura/graphql-engine-mono/pull/3149)
Furthermore, this PR also addresses two other issues:
- THE DOCUMENTATION OF THE METADATA API WAS WRONG, and documented `create_remote_relationship` instead of `<backend>_create_remote_relationship`: this PR fixes this by adding `pg_` everywhere, but does not attempt to add the corresponding documentation for other backends, partly because:
- `<backend>_delete_remote_relationship` WAS BROKEN ON NON-POSTGRES BACKENDS; it always expected an argument parameterized by Postgres.
As of main, the `<backend>_(create|update|delete)_remote_relationship` commands are supported on Postgres, Citus, BigQuery, but **NOT MSSQL**. I do not know if this is intentional or not, if it even should be publicized or not, and as a result this PR doesn't change this.
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/3157
Co-authored-by: jkachmar <8461423+jkachmar@users.noreply.github.com>
GitOrigin-RevId: 37e2f41522a9229a11c595574c3f4984317d652a
2021-12-16 23:28:08 +03:00
|
|
|
commandParser "delete_remote_relationship" $ RMDeleteRemoteRelationship . mkAnyBackend @b
|
2021-07-07 04:43:42 +03:00
|
|
|
]
|
2021-09-06 14:15:36 +03:00
|
|
|
eventTriggerCommands =
|
2021-09-24 01:56:37 +03:00
|
|
|
[ commandParser "invoke_event_trigger" $ RMInvokeEventTrigger . mkAnyBackend @b,
|
|
|
|
commandParser "create_event_trigger" $ RMCreateEventTrigger . mkAnyBackend @b,
|
|
|
|
commandParser "delete_event_trigger" $ RMDeleteEventTrigger . mkAnyBackend @b,
|
|
|
|
commandParser "redeliver_event" $ RMRedeliverEvent . mkAnyBackend @b
|
2021-09-06 14:15:36 +03:00
|
|
|
]
|
2022-05-04 17:52:29 +03:00
|
|
|
computedFieldCommands =
|
|
|
|
[ commandParser "add_computed_field" $ RMAddComputedField . mkAnyBackend @b,
|
|
|
|
commandParser "drop_computed_field" $ RMDropComputedField . mkAnyBackend @b
|
|
|
|
]
|