2021-09-24 01:56:37 +03:00
|
|
|
-- |
|
|
|
|
-- Description: Create/delete SQL functions to/from Hasura metadata.
|
2023-04-03 13:18:54 +03:00
|
|
|
module Hasura.Function.API
|
2021-11-04 19:08:33 +03:00
|
|
|
( FunctionPermissionArgument (..),
|
|
|
|
SetFunctionCustomization (..),
|
|
|
|
TrackFunction (..),
|
|
|
|
TrackFunctionV2 (..),
|
|
|
|
UnTrackFunction (..),
|
|
|
|
doesFunctionPermissionExist,
|
|
|
|
dropFunctionInMetadata,
|
|
|
|
dropFunctionPermissionInMetadata,
|
2022-12-05 13:20:47 +03:00
|
|
|
getSingleUniqueFunctionOverload,
|
2021-11-04 19:08:33 +03:00
|
|
|
runCreateFunctionPermission,
|
|
|
|
runDropFunctionPermission,
|
|
|
|
runSetFunctionCustomization,
|
|
|
|
runTrackFunc,
|
|
|
|
runTrackFunctionV2,
|
|
|
|
runUntrackFunc,
|
|
|
|
trackFunctionP1,
|
|
|
|
trackFunctionP2,
|
|
|
|
)
|
|
|
|
where
|
2019-01-25 06:31:54 +03:00
|
|
|
|
2021-10-07 16:02:19 +03:00
|
|
|
import Control.Lens ((.~), (^.))
|
2021-09-24 01:56:37 +03:00
|
|
|
import Data.Aeson
|
2023-04-26 18:42:13 +03:00
|
|
|
import Data.HashMap.Strict qualified as HashMap
|
2023-04-27 10:41:55 +03:00
|
|
|
import Data.HashMap.Strict.InsOrd qualified as InsOrdHashMap
|
2021-09-24 01:56:37 +03:00
|
|
|
import Data.Text.Extended
|
|
|
|
import Hasura.Base.Error
|
|
|
|
import Hasura.EncJSON
|
2023-04-03 13:18:54 +03:00
|
|
|
import Hasura.Function.Cache
|
|
|
|
import Hasura.Function.Metadata (FunctionMetadata (..), fmConfiguration, fmPermissions)
|
2021-09-24 01:56:37 +03:00
|
|
|
import Hasura.Prelude
|
2022-04-27 16:57:28 +03:00
|
|
|
import Hasura.RQL.Types.Backend
|
2023-04-24 15:25:53 +03:00
|
|
|
import Hasura.RQL.Types.BackendTag
|
2023-04-24 21:35:48 +03:00
|
|
|
import Hasura.RQL.Types.BackendType
|
2022-04-27 16:57:28 +03:00
|
|
|
import Hasura.RQL.Types.Common
|
|
|
|
import Hasura.RQL.Types.Metadata
|
|
|
|
import Hasura.RQL.Types.Metadata.Backend
|
|
|
|
import Hasura.RQL.Types.Metadata.Instances ()
|
|
|
|
import Hasura.RQL.Types.Metadata.Object
|
2023-04-24 11:50:29 +03:00
|
|
|
import Hasura.RQL.Types.Roles (RoleName)
|
2022-04-27 16:57:28 +03:00
|
|
|
import Hasura.RQL.Types.SchemaCache
|
|
|
|
import Hasura.RQL.Types.SchemaCache.Build
|
2021-09-24 01:56:37 +03:00
|
|
|
import Hasura.SQL.AnyBackend qualified as AB
|
2019-01-25 06:31:54 +03:00
|
|
|
|
2021-09-24 01:56:37 +03:00
|
|
|
newtype TrackFunction b = TrackFunction {tfName :: FunctionName b}
|
2021-03-15 16:02:58 +03:00
|
|
|
|
2021-02-14 09:07:52 +03:00
|
|
|
deriving instance (Backend b) => FromJSON (TrackFunction b)
|
2021-09-24 01:56:37 +03:00
|
|
|
|
2021-02-14 09:07:52 +03:00
|
|
|
deriving instance (Backend b) => ToJSON (TrackFunction b)
|
2019-01-25 06:31:54 +03:00
|
|
|
|
2019-07-11 10:41:20 +03:00
|
|
|
-- | Track function, Phase 1:
|
|
|
|
-- Validate function tracking operation. Fails if function is already being
|
|
|
|
-- tracked, or if a table with the same name is being tracked.
|
2021-09-24 01:56:37 +03:00
|
|
|
trackFunctionP1 ::
|
|
|
|
forall b m.
|
|
|
|
(CacheRM m, QErrM m, Backend b) =>
|
|
|
|
SourceName ->
|
|
|
|
FunctionName b ->
|
|
|
|
m ()
|
2020-12-28 15:56:00 +03:00
|
|
|
trackFunctionP1 sourceName qf = do
|
2019-01-25 06:31:54 +03:00
|
|
|
rawSchemaCache <- askSchemaCache
|
2023-05-24 16:51:56 +03:00
|
|
|
unless (isJust $ AB.unpackAnyBackend @b =<< HashMap.lookup sourceName (scSources rawSchemaCache))
|
|
|
|
$ throw400 NotExists
|
|
|
|
$ sourceName
|
|
|
|
<<> " is not a known "
|
|
|
|
<> reify (backendTag @b)
|
|
|
|
<<> " source"
|
|
|
|
when (isJust $ unsafeFunctionInfo @b sourceName qf $ scSources rawSchemaCache)
|
|
|
|
$ throw400 AlreadyTracked
|
|
|
|
$ "function already tracked: "
|
|
|
|
<>> qf
|
2021-04-22 00:44:37 +03:00
|
|
|
let qt = functionToTable @b qf
|
2023-05-24 16:51:56 +03:00
|
|
|
when (isJust $ unsafeTableInfo @b sourceName qt $ scSources rawSchemaCache)
|
|
|
|
$ throw400 NotSupported
|
|
|
|
$ "table with name "
|
|
|
|
<> qf
|
|
|
|
<<> " already exists"
|
2019-01-25 06:31:54 +03:00
|
|
|
|
2021-09-24 01:56:37 +03:00
|
|
|
trackFunctionP2 ::
|
|
|
|
forall b m.
|
|
|
|
(MonadError QErr m, CacheRWM m, MetadataM m, BackendMetadata b) =>
|
|
|
|
SourceName ->
|
|
|
|
FunctionName b ->
|
2023-05-19 07:47:12 +03:00
|
|
|
FunctionConfig b ->
|
2021-09-24 12:18:40 +03:00
|
|
|
Maybe Text ->
|
2021-09-24 01:56:37 +03:00
|
|
|
m EncJSON
|
2021-09-24 12:18:40 +03:00
|
|
|
trackFunctionP2 sourceName qf config comment = do
|
2021-03-15 16:02:58 +03:00
|
|
|
buildSchemaCacheFor
|
2021-04-22 00:44:37 +03:00
|
|
|
(MOSourceObjId sourceName $ AB.mkAnyBackend $ SMOFunction @b qf)
|
2022-11-02 23:53:23 +03:00
|
|
|
$ MetadataModifier
|
2023-05-24 16:51:56 +03:00
|
|
|
$ metaSources
|
|
|
|
. ix sourceName
|
|
|
|
. toSourceMetadata
|
|
|
|
. (smFunctions @b)
|
|
|
|
%~ InsOrdHashMap.insert qf (FunctionMetadata qf config mempty comment)
|
2020-12-08 17:22:31 +03:00
|
|
|
pure successMsg
|
2019-10-18 11:29:47 +03:00
|
|
|
|
2022-12-05 13:20:47 +03:00
|
|
|
getSingleUniqueFunctionOverload ::
|
|
|
|
forall b m.
|
2021-09-24 01:56:37 +03:00
|
|
|
(QErrM m, Backend b) =>
|
|
|
|
FunctionName b ->
|
2022-12-05 13:20:47 +03:00
|
|
|
FunctionOverloads b ->
|
|
|
|
m (RawFunctionInfo b)
|
|
|
|
getSingleUniqueFunctionOverload qf = \case
|
|
|
|
FunctionOverloads (fi :| []) -> return fi
|
2021-09-24 01:56:37 +03:00
|
|
|
_ -> throw400 NotSupported $ "function " <> qf <<> " is overloaded. Overloaded functions are not supported"
|
2019-10-18 11:29:47 +03:00
|
|
|
|
2021-09-24 01:56:37 +03:00
|
|
|
runTrackFunc ::
|
|
|
|
forall b m.
|
|
|
|
(MonadError QErr m, CacheRWM m, MetadataM m, BackendMetadata b) =>
|
|
|
|
TrackFunction b ->
|
|
|
|
m EncJSON
|
2021-04-22 00:44:37 +03:00
|
|
|
runTrackFunc (TrackFunction qf) = do
|
2020-12-28 15:56:00 +03:00
|
|
|
-- v1 track_function lacks a means to take extra arguments
|
2021-04-22 00:44:37 +03:00
|
|
|
trackFunctionP1 @b defaultSource qf
|
2021-09-24 12:18:40 +03:00
|
|
|
trackFunctionP2 @b defaultSource qf emptyFunctionConfig Nothing
|
2019-11-20 09:47:06 +03:00
|
|
|
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
-- | JSON API payload for v2 of 'track_function':
|
|
|
|
--
|
|
|
|
-- https://hasura.io/docs/latest/graphql/core/api-reference/schema-metadata-api/custom-functions.html#track-function-v2
|
|
|
|
data TrackFunctionV2 (b :: BackendType) = TrackFunctionV2
|
2022-08-01 12:32:04 +03:00
|
|
|
{ _tfv2Source :: SourceName,
|
|
|
|
_tfv2Function :: FunctionName b,
|
2023-05-19 07:47:12 +03:00
|
|
|
_tfv2Configuration :: FunctionConfig b,
|
2022-08-01 12:32:04 +03:00
|
|
|
_tfv2Comment :: Maybe Text
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
}
|
|
|
|
|
2023-05-24 16:51:56 +03:00
|
|
|
instance (Backend b) => FromJSON (TrackFunctionV2 b) where
|
2021-09-20 22:49:33 +03:00
|
|
|
parseJSON = withObject "TrackFunctionV2" $ \o ->
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
TrackFunctionV2
|
2023-05-24 16:51:56 +03:00
|
|
|
<$> o
|
|
|
|
.:? "source"
|
|
|
|
.!= defaultSource
|
|
|
|
<*> o
|
|
|
|
.: "function"
|
|
|
|
<*> o
|
|
|
|
.:? "configuration"
|
|
|
|
.!= emptyFunctionConfig
|
|
|
|
<*> o
|
|
|
|
.:? "comment"
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
|
2021-09-24 01:56:37 +03:00
|
|
|
runTrackFunctionV2 ::
|
|
|
|
forall b m.
|
|
|
|
(BackendMetadata b, QErrM m, CacheRWM m, MetadataM m) =>
|
|
|
|
TrackFunctionV2 b ->
|
|
|
|
m EncJSON
|
2021-09-24 12:18:40 +03:00
|
|
|
runTrackFunctionV2 (TrackFunctionV2 source qf config comment) = do
|
2021-04-22 00:44:37 +03:00
|
|
|
trackFunctionP1 @b source qf
|
2021-09-24 12:18:40 +03:00
|
|
|
trackFunctionP2 @b source qf config comment
|
2019-01-25 06:31:54 +03:00
|
|
|
|
2020-11-18 21:04:57 +03:00
|
|
|
-- | JSON API payload for 'untrack_function':
|
|
|
|
--
|
2021-03-01 21:50:24 +03:00
|
|
|
-- https://hasura.io/docs/latest/graphql/core/api-reference/schema-metadata-api/custom-functions.html#untrack-function
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
data UnTrackFunction b = UnTrackFunction
|
2022-08-01 12:32:04 +03:00
|
|
|
{ _utfFunction :: FunctionName b,
|
|
|
|
_utfSource :: SourceName
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
}
|
2020-12-28 15:56:00 +03:00
|
|
|
|
2021-02-14 09:07:52 +03:00
|
|
|
instance (Backend b) => FromJSON (UnTrackFunction b) where
|
2021-05-24 18:56:32 +03:00
|
|
|
-- Following was the previous implementation, which while seems to be correct,
|
|
|
|
-- has an unexpected behaviour. In the case when @source@ key is present but
|
|
|
|
-- @function@ key is absent, it would silently coerce it into a @default@
|
|
|
|
-- source. The culprint being the _alternative_ operator, which silently fails
|
|
|
|
-- the first parse. This note exists so that we don't try to simplify using
|
|
|
|
-- the _alternative_ pattern here.
|
|
|
|
-- Previous implementation :-
|
|
|
|
-- Consider the following JSON -
|
|
|
|
-- {
|
|
|
|
-- "source": "custom_source",
|
|
|
|
-- "schema": "public",
|
|
|
|
-- "name": "my_function"
|
|
|
|
-- }
|
|
|
|
-- it silently fails parsing the source here because @function@ key is not
|
|
|
|
-- present, and proceeds to parse using @withoutSource@ as default source. Now
|
|
|
|
-- this is surprising for the user, because they mention @source@ key
|
|
|
|
-- explicitly. A better behaviour is to explicitly look for @function@ key if
|
|
|
|
-- a @source@ key is present.
|
|
|
|
-- >>
|
|
|
|
-- parseJSON v = withSource <|> withoutSource
|
|
|
|
-- where
|
|
|
|
-- withoutSource = UnTrackFunction <$> parseJSON v <*> pure defaultSource
|
|
|
|
-- withSource = flip (withObject "UnTrackFunction") v \o -> do
|
|
|
|
-- UnTrackFunction <$> o .: "function"
|
|
|
|
-- <*> o .:? "source" .!= defaultSource
|
|
|
|
parseJSON v = flip (withObject "UnTrackFunction") v $ \o -> do
|
|
|
|
source <- o .:? "source"
|
|
|
|
case source of
|
|
|
|
Just src -> flip UnTrackFunction src <$> o .: "function"
|
2021-09-24 01:56:37 +03:00
|
|
|
Nothing -> UnTrackFunction <$> parseJSON v <*> pure defaultSource
|
2019-01-25 06:31:54 +03:00
|
|
|
|
2021-09-24 01:56:37 +03:00
|
|
|
runUntrackFunc ::
|
|
|
|
forall b m.
|
|
|
|
(CacheRWM m, MonadError QErr m, MetadataM m, BackendMetadata b) =>
|
|
|
|
UnTrackFunction b ->
|
|
|
|
m EncJSON
|
2021-01-20 03:31:53 +03:00
|
|
|
runUntrackFunc (UnTrackFunction functionName sourceName) = do
|
2021-04-22 00:44:37 +03:00
|
|
|
void $ askFunctionInfo @b sourceName functionName
|
2023-05-24 16:51:56 +03:00
|
|
|
withNewInconsistentObjsCheck
|
|
|
|
$ buildSchemaCache
|
|
|
|
$ dropFunctionInMetadata @b sourceName functionName
|
2020-12-08 17:22:31 +03:00
|
|
|
pure successMsg
|
|
|
|
|
2021-01-29 08:48:17 +03:00
|
|
|
{- Note [Function Permissions]
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Before we started supporting tracking volatile functions, permissions
|
|
|
|
for a function was inferred from the target table of the function.
|
|
|
|
The rationale behind this is that a stable/immutable function does not
|
|
|
|
modify the database and the data returned by the function is filtered using
|
|
|
|
the permissions that are specified precisely for that data.
|
|
|
|
Now consider mutable/volatile functions, we can't automatically infer whether or
|
|
|
|
not these functions should be exposed for the sole reason that they can modify
|
|
|
|
the database. This necessitates a permission system for functions.
|
|
|
|
So, we introduce a new API `pg_create_function_permission` which will
|
|
|
|
explicitly grant permission to a function to a role. For creating a
|
|
|
|
function permission, the role must have select permissions configured
|
|
|
|
for the target table.
|
|
|
|
Since, this is a breaking change, we enable it only when the graphql-engine
|
|
|
|
is started with
|
|
|
|
`--infer-function-permissions`/HASURA_GRAPHQL_INFER_FUNCTION_PERMISSIONS set
|
|
|
|
to false (by default, it's set to true).
|
|
|
|
-}
|
|
|
|
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
data FunctionPermissionArgument b = FunctionPermissionArgument
|
2022-08-01 12:32:04 +03:00
|
|
|
{ _afpFunction :: FunctionName b,
|
|
|
|
_afpSource :: SourceName,
|
|
|
|
_afpRole :: RoleName
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
}
|
2021-01-29 08:48:17 +03:00
|
|
|
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
instance (Backend b) => FromJSON (FunctionPermissionArgument b) where
|
2021-01-29 08:48:17 +03:00
|
|
|
parseJSON v =
|
2021-09-20 22:49:33 +03:00
|
|
|
flip (withObject "FunctionPermissionArgument") v $ \o ->
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
FunctionPermissionArgument
|
2023-05-24 16:51:56 +03:00
|
|
|
<$> o
|
|
|
|
.: "function"
|
|
|
|
<*> o
|
|
|
|
.:? "source"
|
|
|
|
.!= defaultSource
|
|
|
|
<*> o
|
|
|
|
.: "role"
|
2021-01-29 08:48:17 +03:00
|
|
|
|
2021-09-24 01:56:37 +03:00
|
|
|
runCreateFunctionPermission ::
|
|
|
|
forall b m.
|
|
|
|
( CacheRWM m,
|
|
|
|
MonadError QErr m,
|
|
|
|
MetadataM m,
|
|
|
|
BackendMetadata b
|
|
|
|
) =>
|
|
|
|
FunctionPermissionArgument b ->
|
|
|
|
m EncJSON
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
runCreateFunctionPermission (FunctionPermissionArgument functionName source role) = do
|
2021-08-09 13:20:04 +03:00
|
|
|
metadata <- getMetadata
|
2021-02-23 20:37:27 +03:00
|
|
|
sourceCache <- scSources <$> askSchemaCache
|
2021-04-22 00:44:37 +03:00
|
|
|
functionInfo <- askFunctionInfo @b source functionName
|
2023-05-24 16:51:56 +03:00
|
|
|
when (doesFunctionPermissionExist @b metadata source functionName role)
|
|
|
|
$ throw400 AlreadyExists
|
|
|
|
$ "permission of role "
|
|
|
|
<> role
|
|
|
|
<<> " already exists for function "
|
|
|
|
<> functionName
|
|
|
|
<<> " in source: "
|
|
|
|
<>> source
|
2023-05-19 07:47:12 +03:00
|
|
|
(functionTableName, functionTableInfo) <- do
|
|
|
|
let tn = _fiReturnType functionInfo
|
|
|
|
case unsafeTableInfo @b source tn sourceCache of
|
|
|
|
Nothing -> throw400 NotExists ("function's return table " <> tn <<> " not found in the cache")
|
|
|
|
Just info -> pure (tn, info)
|
2023-05-24 16:51:56 +03:00
|
|
|
unless (role `HashMap.member` _tiRolePermInfoMap functionTableInfo)
|
|
|
|
$ throw400 NotSupported
|
|
|
|
$ "function permission can only be added when the function's return table "
|
|
|
|
<> functionTableName
|
|
|
|
<<> " has select permission configured for role: "
|
|
|
|
<>> role
|
2021-03-15 16:02:58 +03:00
|
|
|
buildSchemaCacheFor
|
2023-05-24 16:51:56 +03:00
|
|
|
( MOSourceObjId source
|
|
|
|
$ AB.mkAnyBackend (SMOFunctionPermission @b functionName role)
|
2021-09-24 01:56:37 +03:00
|
|
|
)
|
2022-11-02 23:53:23 +03:00
|
|
|
$ MetadataModifier
|
|
|
|
$ metaSources
|
2023-05-24 16:51:56 +03:00
|
|
|
. ix
|
|
|
|
source
|
|
|
|
. toSourceMetadata
|
|
|
|
. (smFunctions @b)
|
|
|
|
. ix functionName
|
|
|
|
. fmPermissions
|
|
|
|
%~ (:) (FunctionPermissionInfo role)
|
2021-01-29 08:48:17 +03:00
|
|
|
pure successMsg
|
|
|
|
|
2021-09-24 01:56:37 +03:00
|
|
|
dropFunctionPermissionInMetadata ::
|
|
|
|
forall b.
|
|
|
|
(BackendMetadata b) =>
|
|
|
|
SourceName ->
|
|
|
|
FunctionName b ->
|
|
|
|
RoleName ->
|
|
|
|
MetadataModifier
|
|
|
|
dropFunctionPermissionInMetadata source function role =
|
2023-05-24 16:51:56 +03:00
|
|
|
MetadataModifier
|
|
|
|
$ metaSources
|
|
|
|
. ix source
|
|
|
|
. toSourceMetadata
|
|
|
|
. (smFunctions @b)
|
|
|
|
. ix function
|
|
|
|
. fmPermissions
|
|
|
|
%~ filter ((/=) role . _fpmRole)
|
2021-01-29 08:48:17 +03:00
|
|
|
|
2021-09-24 01:56:37 +03:00
|
|
|
doesFunctionPermissionExist :: forall b. (BackendMetadata b) => Metadata -> SourceName -> FunctionName b -> RoleName -> Bool
|
2021-08-09 13:20:04 +03:00
|
|
|
doesFunctionPermissionExist metadata sourceName functionName roleName =
|
2021-09-24 01:56:37 +03:00
|
|
|
any ((== roleName) . _fpmRole) $ metadata ^. (metaSources . ix sourceName . toSourceMetadata . (smFunctions @b) . ix functionName . fmPermissions)
|
2021-08-09 13:20:04 +03:00
|
|
|
|
2021-09-24 01:56:37 +03:00
|
|
|
runDropFunctionPermission ::
|
|
|
|
forall m b.
|
|
|
|
( CacheRWM m,
|
|
|
|
MonadError QErr m,
|
|
|
|
MetadataM m,
|
|
|
|
BackendMetadata b
|
|
|
|
) =>
|
|
|
|
FunctionPermissionArgument b ->
|
|
|
|
m EncJSON
|
Clean metadata arguments
## Description
Thanks to #1664, the Metadata API types no longer require a `ToJSON` instance. This PR follows up with a cleanup of the types of the arguments to the metadata API:
- whenever possible, it moves those argument types to where they're used (RQL.DDL.*)
- it removes all unrequired instances (mostly `ToJSON`)
This PR does not attempt to do it for _all_ such argument types. For some of the metadata operations, the type used to describe the argument to the API and used to represent the value in the metadata are one and the same (like for `CreateEndpoint`). Sometimes, the two types are intertwined in complex ways (`RemoteRelationship` and `RemoteRelationshipDef`). In the spirit of only doing uncontroversial cleaning work, this PR only moves types that are not used outside of RQL.DDL.
Furthermore, this is a small step towards separating the different types all jumbled together in RQL.Types.
## Notes
This PR also improves several `FromJSON` instances to make use of `withObject`, and to use a human readable string instead of a type name in error messages whenever possible. For instance:
- before: `expected Object for Object, but encountered X`
after: `expected Object for add computed field, but encountered X`
- before: `Expecting an object for update query`
after: `expected Object for update query, but encountered X`
This PR also renames `CreateFunctionPermission` to `FunctionPermissionArgument`, to remove the quite surprising `type DropFunctionPermission = CreateFunctionPermission`.
This PR also deletes some dead code, mostly in RQL.DML.
This PR also moves a PG-specific source resolving function from DDL.Schema.Source to the only place where it is used: App.hs.
https://github.com/hasura/graphql-engine-mono/pull/1844
GitOrigin-RevId: a594521194bb7fe6a111b02a9e099896f9fed59c
2021-07-27 13:41:42 +03:00
|
|
|
runDropFunctionPermission (FunctionPermissionArgument functionName source role) = do
|
2021-08-09 13:20:04 +03:00
|
|
|
metadata <- getMetadata
|
2023-05-24 16:51:56 +03:00
|
|
|
unless (doesFunctionPermissionExist @b metadata source functionName role)
|
|
|
|
$ throw400 NotExists
|
|
|
|
$ "permission of role "
|
|
|
|
<> role
|
|
|
|
<<> " does not exist for function "
|
|
|
|
<> functionName
|
|
|
|
<<> " in source: "
|
|
|
|
<>> source
|
2021-03-15 16:02:58 +03:00
|
|
|
buildSchemaCacheFor
|
2023-05-24 16:51:56 +03:00
|
|
|
( MOSourceObjId source
|
|
|
|
$ AB.mkAnyBackend
|
|
|
|
$ SMOFunctionPermission @b functionName role
|
2021-09-24 01:56:37 +03:00
|
|
|
)
|
2021-04-22 00:44:37 +03:00
|
|
|
$ dropFunctionPermissionInMetadata @b source functionName role
|
2021-01-29 08:48:17 +03:00
|
|
|
pure successMsg
|
2021-10-07 16:02:19 +03:00
|
|
|
|
|
|
|
-- | Represents the payload of the API command 'pg_set_function_customization'.
|
|
|
|
--
|
|
|
|
-- See the Hasura API reference for a detailed description.
|
|
|
|
data SetFunctionCustomization b = SetFunctionCustomization
|
|
|
|
{ _sfcSource :: SourceName,
|
|
|
|
_sfcFunction :: FunctionName b,
|
2023-05-19 07:47:12 +03:00
|
|
|
_sfcConfiguration :: FunctionConfig b
|
2021-10-07 16:02:19 +03:00
|
|
|
}
|
|
|
|
|
2023-05-24 16:51:56 +03:00
|
|
|
deriving instance (Backend b) => Show (SetFunctionCustomization b)
|
2021-10-07 16:02:19 +03:00
|
|
|
|
2023-05-24 16:51:56 +03:00
|
|
|
deriving instance (Backend b) => Eq (SetFunctionCustomization b)
|
2021-10-07 16:02:19 +03:00
|
|
|
|
|
|
|
instance (Backend b) => FromJSON (SetFunctionCustomization b) where
|
|
|
|
parseJSON = withObject "set function customization" $ \o ->
|
|
|
|
SetFunctionCustomization
|
2023-05-24 16:51:56 +03:00
|
|
|
<$> o
|
|
|
|
.:? "source"
|
|
|
|
.!= defaultSource
|
|
|
|
<*> o
|
|
|
|
.: "function"
|
|
|
|
<*> o
|
|
|
|
.: "configuration"
|
2021-10-07 16:02:19 +03:00
|
|
|
|
|
|
|
-- | Changes the custom names of a function. Used in the API command 'pg_set_function_customization'.
|
|
|
|
runSetFunctionCustomization ::
|
|
|
|
forall b m.
|
2022-10-06 12:07:14 +03:00
|
|
|
(QErrM m, CacheRWM m, MetadataM m, Backend b) =>
|
2021-10-07 16:02:19 +03:00
|
|
|
SetFunctionCustomization b ->
|
|
|
|
m EncJSON
|
|
|
|
runSetFunctionCustomization (SetFunctionCustomization source function config) = do
|
2022-04-26 18:12:47 +03:00
|
|
|
void $ askFunctionInfo @b source function
|
2021-10-07 16:02:19 +03:00
|
|
|
buildSchemaCacheFor
|
|
|
|
(MOSourceObjId source $ AB.mkAnyBackend $ SMOFunction @b function)
|
2022-11-02 23:53:23 +03:00
|
|
|
$ MetadataModifier
|
2023-05-24 16:51:56 +03:00
|
|
|
$ ((functionMetadataSetter @b source function) . fmConfiguration)
|
|
|
|
.~ config
|
2021-10-07 16:02:19 +03:00
|
|
|
return successMsg
|