chore(server): move perms to custom return types

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8604
GitOrigin-RevId: ff024429b3f06e4867334665f35d4bd404a85cba
This commit is contained in:
Daniel Harvey 2023-04-04 13:45:20 +01:00 committed by hasura-bot
parent 71a00338ff
commit 9c99bcb6f8
36 changed files with 407 additions and 695 deletions

View File

@ -5,7 +5,7 @@ GRAPHQL_ENGINE_PATH=$(shell cabal list-bin exe:graphql-engine)
# Traditional way
GHC_OPTIONS=-Wno-prepositive-qualified-module
GHCID_FLAGS = --builddir ./dist-newstyle/repl --repl-option -O0 --repl-option -fobject-code --ghc-options=$(GHC_OPTIONS)
GHCID_FLAGS = --builddir ./dist-newstyle/repl --repl-option -O0 --repl-option -frefinement-level-hole-fits=0 -fobject-code --ghc-options=$(GHC_OPTIONS)
GHCID_TESTS_FLAGS = --builddir ./dist-newstyle/repl-tests --repl-option -O0 --ghc-options=$(GHC_OPTIONS)
define run_ghcid_api_tests

View File

@ -70,9 +70,7 @@ spec = do
traverse_
(Fixture.runClean fixtures)
[ testAdminAccess,
testImplementation,
testPermissions,
testPermissionFailures
testImplementation
]
metadataHandlingWhenDisabledSpec
@ -394,264 +392,6 @@ testImplementation = do
)
[yaml| message: success |]
----------------------
-- Test permissions --
----------------------
testPermissions :: SpecWith TestEnvironment
testPermissions = do
let simpleQuery :: Text
simpleQuery = "SELECT thing / 2 AS divided FROM stuff"
describe "Permissions" do
let dividedStuffLogicalModel :: Schema.LogicalModel
dividedStuffLogicalModel =
(Schema.logicalModel "divided_stuff" simpleQuery "divided_stuff")
{ Schema.logicalModelArguments =
[ Schema.logicalModelColumn "unused" Schema.TInt
]
}
it "Adds a simple logical model function with no arguments a select permission and returns a 200" $ \testEnvironment -> do
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
sourceName = BackendType.backendSourceName backendTypeMetadata
backendType = BackendType.backendTypeString backendTypeMetadata
createPermRequestType = backendType <> "_create_logical_model_select_permission"
getRequestType = backendType <> "_get_logical_model"
Schema.trackCustomType sourceName dividedStuffReturnType testEnvironment
Schema.trackLogicalModel sourceName dividedStuffLogicalModel testEnvironment
shouldReturnYaml
testEnvironment
( GraphqlEngine.postMetadata
testEnvironment
[yaml|
type: bulk
args:
- type: *createPermRequestType
args:
source: *sourceName
root_field_name: divided_stuff
role: "test"
permission:
columns:
- divided
filter: {}
|]
)
[yaml|
- message: success
|]
shouldReturnYaml
testEnvironment
( GraphqlEngine.postMetadata
testEnvironment
[yaml|
type: *getRequestType
args:
source: *sourceName
|]
)
[interpolateYaml|
- root_field_name: divided_stuff
code: #{simpleQuery}
arguments:
unused:
type: #{scalarTypeToText testEnvironment Schema.TInt}
nullable: false
select_permissions:
- role: "test"
permission:
columns:
- divided
filter: {}
returns: "divided_stuff"
|]
it "Adds a logical model, removes it, and returns 200" $ \testEnvironment -> do
let rootfield :: Text
rootfield = Schema.logicalModelName dividedStuffLogicalModel
backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
sourceName = BackendType.backendSourceName backendTypeMetadata
backendType = BackendType.backendTypeString backendTypeMetadata
createPermRequestType = backendType <> "_create_logical_model_select_permission"
dropPermRequestType = backendType <> "_drop_logical_model_select_permission"
getRequestType = backendType <> "_get_logical_model"
Schema.trackCustomType sourceName dividedStuffReturnType testEnvironment
Schema.trackLogicalModel sourceName dividedStuffLogicalModel testEnvironment
shouldReturnYaml
testEnvironment
( GraphqlEngine.postMetadata
testEnvironment
[yaml|
type: bulk
args:
- type: *createPermRequestType
args:
source: *sourceName
root_field_name: *rootfield
role: "test"
permission:
columns:
- divided
filter: {}
- type: *dropPermRequestType
args:
source: *sourceName
root_field_name: *rootfield
role: "test"
|]
)
[yaml|
- message: success
- message: success
|]
shouldReturnYaml
testEnvironment
( GraphqlEngine.postMetadata
testEnvironment
[yaml|
type: *getRequestType
args:
source: *sourceName
|]
)
[interpolateYaml|
- root_field_name: #{rootfield}
code: #{simpleQuery}
arguments:
unused:
type: #{scalarTypeToText testEnvironment Schema.TInt}
nullable: false
returns: divided_stuff
|]
testPermissionFailures :: SpecWith TestEnvironment
testPermissionFailures = do
describe "Permission failures" do
it "Fails to adds a select permission to a nonexisting source" $ \testEnvironment -> do
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
backendType = BackendType.backendTypeString backendTypeMetadata
createPermRequestType = backendType <> "_create_logical_model_select_permission"
shouldReturnYaml
testEnvironment
( GraphqlEngine.postMetadataWithStatus
400
testEnvironment
[yaml|
type: bulk
args:
- type: *createPermRequestType
args:
source: made_up_source
root_field_name: made_up_logical_model
role: "test"
permission:
columns:
- divided
filter: {}
|]
)
[yaml|
code: not-found
error: "Source \"made_up_source\" not found."
path: "$.args[0].args"
|]
it "Fails to adds a select permission to a nonexisting logical model" $ \testEnvironment -> do
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
sourceName = BackendType.backendSourceName backendTypeMetadata
backendType = BackendType.backendTypeString backendTypeMetadata
createPermRequestType = backendType <> "_create_logical_model_select_permission"
expectedError = "Logical model \"made_up_logical_model\" not found in source \"" <> sourceName <> "\"."
shouldReturnYaml
testEnvironment
( GraphqlEngine.postMetadataWithStatus
400
testEnvironment
[yaml|
type: bulk
args:
- type: *createPermRequestType
args:
source: *sourceName
root_field_name: made_up_logical_model
role: "test"
permission:
columns:
- divided
filter: {}
|]
)
[yaml|
code: "not-found"
error: *expectedError
path: "$.args[0].args"
|]
it "Fails to drop a select permission on a nonexisting source" $ \testEnvironment -> do
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
backendType = BackendType.backendTypeString backendTypeMetadata
dropPermRequestType = backendType <> "_drop_logical_model_select_permission"
shouldReturnYaml
testEnvironment
( GraphqlEngine.postMetadataWithStatus
400
testEnvironment
[yaml|
type: *dropPermRequestType
args:
source: made_up_source
root_field_name: made_up_logical_model
role: "test"
permission:
columns:
- divided
filter: {}
|]
)
[yaml|
code: not-found
error: "Source \"made_up_source\" not found."
path: "$.args"
|]
it "Fails to drop a select permission from a nonexisting logical model" $ \testEnvironment -> do
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
sourceName = BackendType.backendSourceName backendTypeMetadata
backendType = BackendType.backendTypeString backendTypeMetadata
dropPermRequestType = backendType <> "_drop_logical_model_select_permission"
expectedError = "Logical model \"made_up_logical_model\" not found in source \"" <> sourceName <> "\"."
shouldReturnYaml
testEnvironment
( GraphqlEngine.postMetadataWithStatus
400
testEnvironment
[yaml|
type: *dropPermRequestType
args:
source: *sourceName
root_field_name: made_up_logical_model
role: "test"
|]
)
[yaml|
code: "not-found"
error: *expectedError
path: "$.args"
|]
metadataHandlingWhenDisabledSpec :: SpecWith GlobalTestEnvironment
metadataHandlingWhenDisabledSpec = do
describe "When logical models are enabled" do

View File

@ -409,7 +409,7 @@ tests = do
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
source = BackendType.backendSourceName backendTypeMetadata
backendType = BackendType.backendTypeString backendTypeMetadata
createPermRequestType = backendType <> "_create_logical_model_select_permission"
createPermRequestType = backendType <> "_create_custom_return_type_select_permission"
helloWorldPermLogicalModel :: Schema.LogicalModel
helloWorldPermLogicalModel =
@ -429,7 +429,7 @@ tests = do
- type: *createPermRequestType
args:
source: *source
root_field_name: hello_world_perms
name: hello_world_function
role: "test"
permission:
columns:
@ -468,7 +468,7 @@ tests = do
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
source = BackendType.backendSourceName backendTypeMetadata
backendType = BackendType.backendTypeString backendTypeMetadata
createPermRequestType = backendType <> "_create_logical_model_select_permission"
createPermRequestType = backendType <> "_create_custom_return_type_select_permission"
helloWorldPermLogicalModel :: Schema.LogicalModel
helloWorldPermLogicalModel =
@ -488,7 +488,7 @@ tests = do
- type: *createPermRequestType
args:
source: *source
root_field_name: hello_world_perms
name: hello_world_function
role: "test"
permission:
columns:
@ -506,7 +506,7 @@ tests = do
- extensions:
code: validation-failed
path: $.selectionSet.hello_world_perms.selectionSet.one
message: "field 'one' not found in type: 'hello_world_perms'"
message: "field 'one' not found in type: 'hello_world_function'"
|]
actual :: IO Value
@ -528,7 +528,7 @@ tests = do
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
source = BackendType.backendSourceName backendTypeMetadata
backendType = BackendType.backendTypeString backendTypeMetadata
createPermRequestType = backendType <> "_create_logical_model_select_permission"
createPermRequestType = backendType <> "_create_custom_return_type_select_permission"
helloWorldPermLogicalModel :: Schema.LogicalModel
helloWorldPermLogicalModel =
@ -548,7 +548,7 @@ tests = do
- type: *createPermRequestType
args:
source: *source
root_field_name: hello_world_perms
name: hello_world_function
role: "test"
permission:
columns: "*"

View File

@ -76,7 +76,7 @@ tests = do
helloWorldReturnType :: Schema.CustomType
helloWorldReturnType =
(Schema.customType "hello_world_function")
(Schema.customType "hello_world_return_type")
{ Schema.customTypeColumns =
[ Schema.logicalModelColumn "one" Schema.TStr,
Schema.logicalModelColumn "two" Schema.TStr
@ -85,7 +85,7 @@ tests = do
helloWorldLogicalModel :: Schema.LogicalModel
helloWorldLogicalModel =
(Schema.logicalModel "hello_world_function" query "hello_world_function")
(Schema.logicalModel "hello_world_function" query "hello_world_return_type")
describe "Testing Logical Models" $ do
it "Explain works" $ \testEnvironment -> do
@ -148,6 +148,7 @@ tests = do
}
Schema.trackCustomType sourceName descriptionsAndNullableReturnType testEnvironment
Schema.trackLogicalModel sourceName descriptionsAndNullableLogicalModel testEnvironment
let queryTypesIntrospection :: Value
@ -308,7 +309,7 @@ tests = do
helloWorldLogicalModelWithDummyArgument :: Schema.LogicalModel
helloWorldLogicalModelWithDummyArgument =
(Schema.logicalModel "hello_world_function_with_dummy" query "hello_world_function")
(Schema.logicalModel "hello_world_function_with_dummy" query "hello_world_return_type")
{ Schema.logicalModelArguments =
[ Schema.logicalModelColumn "dummy" Schema.TStr
]
@ -349,7 +350,7 @@ tests = do
helloCommentLogicalModel :: Schema.LogicalModel
helloCommentLogicalModel =
(Schema.logicalModel "hello_comment_function" spicyQuery "hello_world_function")
(Schema.logicalModel "hello_comment_function" spicyQuery "hello_world_return_type")
Schema.trackCustomType source helloWorldReturnType testEnvironment
@ -384,11 +385,11 @@ tests = do
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
source = BackendType.backendSourceName backendTypeMetadata
backendType = BackendType.backendTypeString backendTypeMetadata
createPermRequestType = backendType <> "_create_logical_model_select_permission"
createPermRequestType = backendType <> "_create_custom_return_type_select_permission"
helloWorldPermLogicalModel :: Schema.LogicalModel
helloWorldPermLogicalModel =
(Schema.logicalModel "hello_world_perms" query "hello_world_function")
(Schema.logicalModel "hello_world_with_permissions" query "hello_world_return_type")
Schema.trackCustomType source helloWorldReturnType testEnvironment
@ -404,7 +405,7 @@ tests = do
- type: *createPermRequestType
args:
source: *source
root_field_name: hello_world_perms
name: hello_world_return_type
role: "test"
permission:
columns:
@ -419,7 +420,7 @@ tests = do
let expected =
[yaml|
data:
hello_world_perms:
hello_world_with_permissions:
- one: "hello"
- one: "welcome"
|]
@ -431,7 +432,7 @@ tests = do
[("X-Hasura-Role", "test")]
[graphql|
query {
hello_world_perms {
hello_world_with_permissions {
one
}
}
@ -443,11 +444,11 @@ tests = do
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
source = BackendType.backendSourceName backendTypeMetadata
backendType = BackendType.backendTypeString backendTypeMetadata
createPermRequestType = backendType <> "_create_logical_model_select_permission"
createPermRequestType = backendType <> "_create_custom_return_type_select_permission"
helloWorldPermLogicalModel :: Schema.LogicalModel
helloWorldPermLogicalModel =
(Schema.logicalModel "hello_world_perms" query "hello_world_function")
(Schema.logicalModel "hello_world_with_permissions" query "hello_world_return_type")
Schema.trackCustomType source helloWorldReturnType testEnvironment
@ -463,7 +464,7 @@ tests = do
- type: *createPermRequestType
args:
source: *source
root_field_name: hello_world_perms
name: hello_world_return_type
role: "test"
permission:
columns:
@ -480,8 +481,8 @@ tests = do
errors:
- extensions:
code: validation-failed
path: $.selectionSet.hello_world_perms.selectionSet.one
message: "field 'one' not found in type: 'hello_world_perms'"
path: $.selectionSet.hello_world_with_permissions.selectionSet.one
message: "field 'one' not found in type: 'hello_world_return_type'"
|]
actual :: IO Value
@ -491,7 +492,7 @@ tests = do
[("X-Hasura-Role", "test")]
[graphql|
query {
hello_world_perms {
hello_world_with_permissions {
one
}
}
@ -503,11 +504,11 @@ tests = do
let backendTypeMetadata = fromMaybe (error "Unknown backend") $ getBackendTypeConfig testEnvironment
source = BackendType.backendSourceName backendTypeMetadata
backendType = BackendType.backendTypeString backendTypeMetadata
createPermRequestType = backendType <> "_create_logical_model_select_permission"
createPermRequestType = backendType <> "_create_custom_return_type_select_permission"
helloWorldPermLogicalModel :: Schema.LogicalModel
helloWorldPermLogicalModel =
(Schema.logicalModel "hello_world_perms" query "hello_world_function")
(Schema.logicalModel "hello_world_with_permissions" query "hello_world_return_type")
Schema.trackCustomType source helloWorldReturnType testEnvironment
@ -523,7 +524,7 @@ tests = do
- type: *createPermRequestType
args:
source: *source
root_field_name: hello_world_perms
name: hello_world_return_type
role: "test"
permission:
columns: "*"
@ -539,7 +540,7 @@ tests = do
let expected =
[yaml|
data:
hello_world_perms:
hello_world_with_permissions:
- one: "welcome"
two: "friend"
|]
@ -551,7 +552,7 @@ tests = do
[("X-Hasura-Role", "test")]
[graphql|
query {
hello_world_perms {
hello_world_with_permissions {
one
two
}

View File

@ -88,9 +88,9 @@ instance BackendTableSelectSchema 'BigQuery where
selectTableAggregate = defaultSelectTableAggregate
tableSelectionSet = defaultTableSelectionSet
instance BackendCustomTypeSelectSchema 'BigQuery where
logicalModelArguments = defaultLogicalModelArgs
logicalModelSelectionSet = defaultLogicalModelSelectionSet
instance BackendCustomReturnTypeSelectSchema 'BigQuery where
customReturnTypeArguments = defaultCustomReturnTypeArgs
customReturnTypeSelectionSet = defaultCustomReturnTypeSelectionSet
----------------------------------------------------------------
-- Individual components

View File

@ -100,9 +100,9 @@ instance BackendTableSelectSchema 'MSSQL where
selectTableAggregate = defaultSelectTableAggregate
tableSelectionSet = defaultTableSelectionSet
instance BackendCustomTypeSelectSchema 'MSSQL where
logicalModelArguments = defaultLogicalModelArgs
logicalModelSelectionSet = defaultLogicalModelSelectionSet
instance BackendCustomReturnTypeSelectSchema 'MSSQL where
customReturnTypeArguments = defaultCustomReturnTypeArgs
customReturnTypeSelectionSet = defaultCustomReturnTypeSelectionSet
instance BackendUpdateOperatorsSchema 'MSSQL where
type UpdateOperators 'MSSQL = UpdateOperator

View File

@ -286,10 +286,10 @@ instance
( PostgresSchema pgKind,
Backend ('Postgres pgKind)
) =>
BS.BackendCustomTypeSelectSchema ('Postgres pgKind)
BS.BackendCustomReturnTypeSelectSchema ('Postgres pgKind)
where
logicalModelArguments = defaultLogicalModelArgs
logicalModelSelectionSet = defaultLogicalModelSelectionSet
customReturnTypeArguments = defaultCustomReturnTypeArgs
customReturnTypeSelectionSet = defaultCustomReturnTypeSelectionSet
instance
( Backend ('Postgres pgKind),

View File

@ -1,11 +1,17 @@
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE UndecidableInstances #-}
module Hasura.CustomReturnType.Cache
( CustomReturnTypeInfo (..),
CustomReturnTypeCache,
crtiName,
crtiPermissions,
crtiDescription,
crtiFields,
)
where
import Control.Lens (makeLenses)
import Data.Aeson (ToJSON (..), genericToJSON)
import Data.HashMap.Strict.InsOrd qualified as InsOrd
import Hasura.CustomReturnType.Types (CustomReturnTypeName)
@ -19,13 +25,15 @@ type CustomReturnTypeCache b = HashMap CustomReturnTypeName (CustomReturnTypeInf
-- | Description of a custom return type for use in metadata (before schema cache)
data CustomReturnTypeInfo (b :: BackendType) = CustomReturnTypeInfo
{ _ctiName :: CustomReturnTypeName,
_ctiFields :: InsOrd.InsOrdHashMap (Column b) (NullableScalarType b),
_ctiDescription :: Maybe Text,
_ctiPermissions :: RolePermInfoMap b
{ _crtiName :: CustomReturnTypeName,
_crtiFields :: InsOrd.InsOrdHashMap (Column b) (NullableScalarType b),
_crtiDescription :: Maybe Text,
_crtiPermissions :: RolePermInfoMap b
}
deriving (Generic)
makeLenses ''CustomReturnTypeInfo
instance
(Backend b, ToJSON (RolePermInfoMap b)) =>
ToJSON (CustomReturnTypeInfo b)

View File

@ -5,7 +5,6 @@ where
import Data.HashMap.Strict.InsOrd qualified as InsOrd
import Data.Text.Extended (ToTxt (toTxt))
import Hasura.CustomReturnType.Cache (CustomReturnTypeInfo (..))
import Hasura.LogicalModel.Types (NullableScalarType (..))
import Hasura.Prelude
import Hasura.RQL.Types.Backend (Backend (..))
@ -13,11 +12,11 @@ import Hasura.RQL.Types.Column (ColumnInfo (..), ColumnMutability (..), ColumnTy
import Hasura.RQL.Types.Table (FieldInfo (..))
import Language.GraphQL.Draft.Syntax qualified as G
toFieldInfo :: forall b. (Backend b) => CustomReturnTypeInfo b -> Maybe [FieldInfo b]
toFieldInfo customReturnType =
toFieldInfo :: forall b. (Backend b) => InsOrd.InsOrdHashMap (Column b) (NullableScalarType b) -> Maybe [FieldInfo b]
toFieldInfo fields =
traverseWithIndex
(\i -> fmap FIColumn . customTypeToColumnInfo i)
(InsOrd.toList (_ctiFields customReturnType))
(InsOrd.toList fields)
where
traverseWithIndex :: (Applicative m) => (Int -> aa -> m bb) -> [aa] -> m [bb]
traverseWithIndex f = zipWithM f [0 ..]

View File

@ -4,6 +4,7 @@
module Hasura.CustomReturnType.Metadata
( CustomReturnTypeMetadata (..),
CustomReturnTypeName (..),
WithCustomReturnType (..),
crtmName,
crtmFields,
crtmDescription,
@ -14,7 +15,8 @@ where
import Autodocodec (Autodocodec (Autodocodec), HasCodec)
import Autodocodec qualified as AC
import Control.Lens (makeLenses)
import Data.Aeson (FromJSON, ToJSON)
import Data.Aeson (FromJSON (parseJSON), ToJSON, (.!=), (.:), (.:?))
import Data.Aeson qualified as Aeson
import Data.HashMap.Strict.InsOrd qualified as InsOrd
import Data.HashMap.Strict.InsOrd.Autodocodec (sortedElemsCodec)
import Hasura.CustomReturnType.Types
@ -22,6 +24,7 @@ import Hasura.LogicalModel.Types (NullableScalarType (..), nullableScalarTypeMap
import Hasura.Metadata.DTO.Utils (codecNamePrefix)
import Hasura.Prelude hiding (first)
import Hasura.RQL.Types.Backend (Backend (..))
import Hasura.RQL.Types.Common (SourceName, ToAesonPairs (toAesonPairs), defaultSource)
import Hasura.RQL.Types.Permission (SelPermDef, _pdRole)
import Hasura.SQL.Backend (BackendType)
import Hasura.Session (RoleName)
@ -72,3 +75,27 @@ deriving via
deriving stock instance (Backend b) => Eq (CustomReturnTypeMetadata b)
deriving stock instance (Backend b) => Show (CustomReturnTypeMetadata b)
-- | A wrapper to tie something to a particular logical model. Specifically, it
-- assumes the underlying '_wlmInfo' is represented as an object, and adds two
-- keys to that object: @source@ and @root_field_name@.
data WithCustomReturnType a = WithCustomReturnType
{ _wcrtSource :: SourceName,
_wcrtName :: CustomReturnTypeName,
_wcrtInfo :: a
}
deriving stock (Eq, Show)
-- | something to note here: if the `a` contains a `name` or `source` key then
-- this won't work anymore.
instance (FromJSON a) => FromJSON (WithCustomReturnType a) where
parseJSON = Aeson.withObject "CustomReturnType" \obj -> do
_wcrtSource <- obj .:? "source" .!= defaultSource
_wcrtName <- obj .: "name"
_wcrtInfo <- parseJSON (Aeson.Object obj)
pure WithCustomReturnType {..}
instance (ToAesonPairs a) => ToJSON (WithCustomReturnType a) where
toJSON (WithCustomReturnType source name info) =
Aeson.object $ ("source", Aeson.toJSON source) : ("name", Aeson.toJSON name) : toAesonPairs info

View File

@ -1,12 +1,101 @@
-- | Schema parsers for custom return types
module Hasura.CustomReturnType.Schema (buildCustomReturnType) where
module Hasura.CustomReturnType.Schema
( buildCustomReturnTypeIR,
buildCustomReturnTypePermissions,
buildCustomReturnTypeFields,
)
where
import Data.HashMap.Strict qualified as HM
import Hasura.CustomReturnType.Cache (CustomReturnTypeInfo (..))
import Hasura.CustomReturnType.IR (CustomReturnType (..))
import Hasura.CustomReturnType.Types (CustomReturnTypeName (..))
import Hasura.GraphQL.Schema.Backend
( BackendCustomReturnTypeSelectSchema (..),
MonadBuildSchema,
)
import Hasura.GraphQL.Schema.Common
( AnnotatedFields,
SchemaT,
partialSQLExpToUnpreparedValue,
retrieve,
scRole,
)
import Hasura.GraphQL.Schema.Parser qualified as P
import Hasura.GraphQL.Schema.Select
( customReturnTypeSelectionList,
)
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp (gBoolExpTrue)
import Hasura.RQL.IR.Select qualified as IR
import Hasura.RQL.IR.Value qualified as IR
import Hasura.RQL.Types.Backend (Backend)
import Hasura.RQL.Types.Table (SelPermInfo (..), _permSel)
import Hasura.Session (RoleName, adminRoleName)
buildCustomReturnType :: CustomReturnTypeInfo b -> CustomReturnType b
buildCustomReturnType (CustomReturnTypeInfo {_ctiName, _ctiFields}) =
-- | find list of columns we're allowed to access for this role
getSelPermInfoForCustomReturnType ::
RoleName ->
CustomReturnTypeInfo b ->
Maybe (SelPermInfo b)
getSelPermInfoForCustomReturnType role customReturnType =
HM.lookup role (_crtiPermissions customReturnType) >>= _permSel
-- | build select permissions for custom return type
-- `admin` can always select everything
customReturnTypePermissions ::
(Backend b) =>
CustomReturnTypeInfo b ->
RoleName ->
IR.TablePermG b (IR.UnpreparedValue b)
customReturnTypePermissions customReturnType roleName = do
if roleName == adminRoleName
then IR.TablePerm gBoolExpTrue Nothing
else case getSelPermInfoForCustomReturnType roleName customReturnType of
Just selectPermissions ->
IR.TablePerm
{ IR._tpFilter = fmap partialSQLExpToUnpreparedValue <$> spiFilter selectPermissions,
IR._tpLimit = spiLimit selectPermissions
}
Nothing -> IR.TablePerm gBoolExpTrue Nothing
-- | turn post-schema cache CustomReturnTypeInfo into IR
buildCustomReturnTypeIR :: CustomReturnTypeInfo b -> CustomReturnType b
buildCustomReturnTypeIR CustomReturnTypeInfo {..} =
CustomReturnType
{ crtName = _ctiName,
crtFields = _ctiFields
{ crtName = _crtiName,
crtFields = _crtiFields
}
-- | top-level select permissions for a custom return type
buildCustomReturnTypePermissions ::
forall b r m n.
( MonadBuildSchema b r m n
) =>
CustomReturnTypeInfo b ->
SchemaT r m (IR.TablePermG b (IR.UnpreparedValue b))
buildCustomReturnTypePermissions customReturnType = do
roleName <- retrieve scRole
pure $ customReturnTypePermissions customReturnType roleName
buildCustomReturnTypeFields ::
forall b r m n.
( MonadBuildSchema b r m n,
BackendCustomReturnTypeSelectSchema b
) =>
CustomReturnTypeInfo b ->
SchemaT
r
m
( Maybe
( P.Parser 'P.Output n (AnnotatedFields b),
P.InputFieldsParser n (IR.SelectArgsG b (IR.UnpreparedValue b))
)
)
buildCustomReturnTypeFields customReturnType = runMaybeT $ do
let fieldName = getCustomReturnTypeName (_crtiName customReturnType)
selectionSetParser <- MaybeT $ customReturnTypeSelectionList @b @r @m @n fieldName customReturnType
customTypesArgsParser <- lift $ customReturnTypeArguments @b @r @m @n fieldName customReturnType
pure (selectionSetParser, customTypesArgsParser)

View File

@ -20,6 +20,7 @@ import Data.Text.NonEmpty qualified as NT
import Hasura.Base.Error
import Hasura.Base.ErrorMessage
import Hasura.Base.ToErrorValue
import Hasura.CustomReturnType.Cache (_crtiPermissions)
import Hasura.Function.Cache
import Hasura.GraphQL.ApolloFederation
import Hasura.GraphQL.Context
@ -45,7 +46,7 @@ import Hasura.GraphQL.Schema.Remote (buildRemoteParser)
import Hasura.GraphQL.Schema.RemoteRelationship
import Hasura.GraphQL.Schema.Table
import Hasura.GraphQL.Schema.Typename (MkTypename (..))
import Hasura.LogicalModel.Cache (LogicalModelCache, _lmiPermissions)
import Hasura.LogicalModel.Cache (LogicalModelCache, _lmiReturns)
import Hasura.Name qualified as Name
import Hasura.Prelude
import Hasura.QueryTags.Types
@ -121,8 +122,8 @@ buildGQLContext ServerConfigCtx {..} sources allRemoteSchemas allActions customT
<> Set.fromList (bool mempty remoteSchemasRoles $ _sccRemoteSchemaPermsCtx == Options.EnableRemoteSchemaPermissions)
allActionInfos = Map.elems allActions
allTableRoles = Set.fromList $ getTableRoles =<< Map.elems sources
allLogicalModelRoles = Set.fromList $ getLogicalModelRoles =<< Map.elems sources
allRoles = actionRoles <> allTableRoles <> allLogicalModelRoles
allCustomReturnTypeRoles = Set.fromList $ getCustomReturnTypeRoles =<< Map.elems sources
allRoles = actionRoles <> allTableRoles <> allCustomReturnTypeRoles
contexts <-
-- Buld role contexts in parallel. We'd prefer deterministic parallelism
@ -707,7 +708,7 @@ buildLogicalModelFields sourceInfo logicalModels = runMaybeTmempty $ do
-- more granularly on columns and then rows)
guard $
roleName == adminRoleName
|| roleName `Map.member` _lmiPermissions logicalModel
|| roleName `Map.member` _crtiPermissions (_lmiReturns logicalModel)
lift (buildLogicalModelRootFields logicalModel)
where

View File

@ -26,7 +26,7 @@ module Hasura.GraphQL.Schema.Backend
( -- * Main Types
BackendSchema (..),
BackendTableSelectSchema (..),
BackendCustomTypeSelectSchema (..),
BackendCustomReturnTypeSelectSchema (..),
BackendUpdateOperatorsSchema (..),
MonadBuildSchema,
@ -302,17 +302,17 @@ class Backend b => BackendTableSelectSchema (b :: BackendType) where
type ComparisonExp b = OpExpG b (UnpreparedValue b)
class Backend b => BackendCustomTypeSelectSchema (b :: BackendType) where
logicalModelArguments ::
class Backend b => BackendCustomReturnTypeSelectSchema (b :: BackendType) where
customReturnTypeArguments ::
MonadBuildSourceSchema b r m n =>
G.Name ->
CustomReturnTypeInfo b ->
SchemaT r m (InputFieldsParser n (IR.SelectArgsG b (UnpreparedValue b)))
logicalModelSelectionSet ::
customReturnTypeSelectionSet ::
MonadBuildSourceSchema b r m n =>
G.Name ->
LogicalModelInfo b ->
CustomReturnTypeInfo b ->
SchemaT r m (Maybe (Parser 'Output n (AnnotatedFields b)))
class Backend b => BackendUpdateOperatorsSchema (b :: BackendType) where

View File

@ -4,7 +4,7 @@
module Hasura.GraphQL.Schema.BoolExp
( AggregationPredicatesSchema (..),
tableBoolExp,
customTypeBoolExp,
customReturnTypeBoolExp,
mkBoolOperator,
equalityOperators,
comparisonOperators,
@ -171,7 +171,7 @@ boolExpInternal gqlName fieldInfos description memoizeKey mkAggPredParser = do
-- > ...
-- > }
-- | Boolean expression for custom return types
customTypeBoolExp ::
customReturnTypeBoolExp ::
forall b r m n.
( MonadBuildSchema b r m n,
AggregationPredicatesSchema b
@ -179,9 +179,9 @@ customTypeBoolExp ::
G.Name ->
CustomReturnTypeInfo b ->
SchemaT r m (Parser 'Input n (AnnBoolExp b (UnpreparedValue b)))
customTypeBoolExp name customReturnType =
case toFieldInfo customReturnType of
Nothing -> throw500 $ "Error creating fields for custom type " <> tshow (_ctiName customReturnType)
customReturnTypeBoolExp name customReturnType =
case toFieldInfo (_crtiFields customReturnType) of
Nothing -> throw500 $ "Error creating fields for custom type " <> tshow (_crtiName customReturnType)
Just fieldInfo -> do
let gqlName = mkTableBoolExpTypeName (C.fromCustomName name)

View File

@ -31,7 +31,7 @@ module Hasura.GraphQL.Schema.Common
StreamSelectExp,
TablePerms,
getTableRoles,
getLogicalModelRoles,
getCustomReturnTypeRoles,
askTableInfo,
comparisonAggOperators,
mapField,
@ -65,6 +65,7 @@ import Data.Text.Casing qualified as C
import Data.Text.Extended
import Hasura.Backends.Postgres.SQL.Types qualified as Postgres
import Hasura.Base.Error
import Hasura.CustomReturnType.Cache (CustomReturnTypeInfo (_crtiPermissions))
import Hasura.Function.Cache
import Hasura.GraphQL.Namespace (NamespacedField)
import Hasura.GraphQL.Parser.Internal.TypeChecking qualified as P
@ -73,7 +74,7 @@ import Hasura.GraphQL.Schema.Options (SchemaOptions)
import Hasura.GraphQL.Schema.Options qualified as Options
import Hasura.GraphQL.Schema.Parser qualified as P
import Hasura.GraphQL.Schema.Typename
import Hasura.LogicalModel.Cache (LogicalModelCache, _lmiPermissions)
import Hasura.LogicalModel.Cache (LogicalModelCache)
import Hasura.Prelude
import Hasura.RQL.IR qualified as IR
import Hasura.RQL.IR.BoolExp
@ -323,10 +324,10 @@ getTableRoles bsi = AB.dispatchAnyBackend @Backend bsi go
where
go si = Map.keys . _tiRolePermInfoMap =<< Map.elems (_siTables si)
getLogicalModelRoles :: BackendSourceInfo -> [RoleName]
getLogicalModelRoles bsi = AB.dispatchAnyBackend @Backend bsi go
getCustomReturnTypeRoles :: BackendSourceInfo -> [RoleName]
getCustomReturnTypeRoles bsi = AB.dispatchAnyBackend @Backend bsi go
where
go si = Map.keys . _lmiPermissions =<< Map.elems (_siLogicalModels si)
go si = Map.keys . _crtiPermissions =<< Map.elems (_siCustomReturnTypes si)
-- | Looks up table information for the given table name. This function
-- should never fail, since the schema cache construction process is

View File

@ -12,7 +12,7 @@ import Data.HashMap.Strict.Extended qualified as HashMap
import Data.Text.Casing qualified as C
import Data.Text.Extended
import Hasura.Base.Error
import Hasura.CustomReturnType.Cache (CustomReturnTypeInfo)
import Hasura.CustomReturnType.Cache (CustomReturnTypeInfo (_crtiFields))
import Hasura.CustomReturnType.Common (toFieldInfo)
import Hasura.Function.Cache
import Hasura.GraphQL.Parser.Class
@ -73,7 +73,7 @@ customTypeOrderByExp ::
CustomReturnTypeInfo b ->
SchemaT r m (Parser 'Input n [IR.AnnotatedOrderByItemG b (IR.UnpreparedValue b)])
customTypeOrderByExp name customReturnType =
case toFieldInfo customReturnType of
case toFieldInfo (_crtiFields customReturnType) of
Nothing -> throw500 $ "Error creating fields for custom type " <> tshow name
Just tableFields -> do
let description =

View File

@ -13,8 +13,8 @@ module Hasura.GraphQL.Schema.Select
defaultSelectTableAggregate,
defaultTableArgs,
defaultTableSelectionSet,
defaultLogicalModelArgs,
defaultLogicalModelSelectionSet,
defaultCustomReturnTypeArgs,
defaultCustomReturnTypeSelectionSet,
tableAggregationFields,
tableConnectionArgs,
tableConnectionSelectionSet,
@ -25,7 +25,7 @@ module Hasura.GraphQL.Schema.Select
tableOffsetArg,
tablePermissionsInfo,
tableSelectionList,
logicalModelSelectionList,
customReturnTypeSelectionList,
)
where
@ -66,7 +66,6 @@ import Hasura.GraphQL.Schema.Parser
import Hasura.GraphQL.Schema.Parser qualified as P
import Hasura.GraphQL.Schema.Table
import Hasura.GraphQL.Schema.Typename
import Hasura.LogicalModel.Cache (LogicalModelInfo (..))
import Hasura.LogicalModel.Types (NullableScalarType (..))
import Hasura.Name qualified as Name
import Hasura.Prelude
@ -474,31 +473,31 @@ tableSelectionList ::
tableSelectionList tableInfo =
fmap nonNullableObjectList <$> tableSelectionSet tableInfo
logicalModelColumnsForRole ::
customReturnTypeColumnsForRole ::
RoleName ->
LogicalModelInfo b ->
CustomReturnTypeInfo b ->
Maybe (Permission.PermColSpec b)
logicalModelColumnsForRole role logicalModelInfo =
customReturnTypeColumnsForRole role customReturnType =
if role == adminRoleName
then -- if admin, assume all columns are OK
pure Permission.PCStar
else -- find list of columns we're allowed to access for this role
HM.lookup role (_lmiPermissions logicalModelInfo)
HM.lookup role (_crtiPermissions customReturnType)
>>= _permSel
<&> Permission.PCCols . HM.keys . spiCols
defaultLogicalModelSelectionSet ::
defaultCustomReturnTypeSelectionSet ::
forall b r m n.
( MonadBuildSchema b r m n
) =>
G.Name ->
LogicalModelInfo b ->
CustomReturnTypeInfo b ->
SchemaT r m (Maybe (Parser 'Output n (AnnotatedFields b)))
defaultLogicalModelSelectionSet name logicalModelInfo = runMaybeT $ do
defaultCustomReturnTypeSelectionSet name customReturnType = runMaybeT $ do
roleName <- retrieve scRole
selectableColumns <- hoistMaybe $ logicalModelColumnsForRole roleName logicalModelInfo
selectableColumns <- hoistMaybe $ customReturnTypeColumnsForRole roleName customReturnType
let isSelectable column =
case selectableColumns of
@ -506,10 +505,7 @@ defaultLogicalModelSelectionSet name logicalModelInfo = runMaybeT $ do
Permission.PCCols cols -> column `elem` cols
let parseField (column, NullableScalarType {..}) = do
let -- Currently, row-level permissions are unsupported for custom
-- return types. In fact, permissions are unsupported: the feature
-- is assumed to be admin-only. If you've been asked to implement
-- permissions, this is the place.
let -- We have not yet worked out what providing permissions here enables
caseBoolExpUnpreparedValue = Nothing
columnType = ColumnScalar nstType
@ -529,11 +525,11 @@ defaultLogicalModelSelectionSet name logicalModelInfo = runMaybeT $ do
let allowedColumns =
filter
(isSelectable . fst)
(InsOrd.toList (_ctiFields (_lmiReturns logicalModelInfo)))
(InsOrd.toList (_crtiFields customReturnType))
parsers <- traverse parseField allowedColumns
let description = G.Description <$> _ctiDescription (_lmiReturns logicalModelInfo)
let description = G.Description <$> _crtiDescription customReturnType
-- We entirely ignore Relay for now.
implementsInterfaces = mempty
@ -542,13 +538,13 @@ defaultLogicalModelSelectionSet name logicalModelInfo = runMaybeT $ do
P.selectionSetObject fieldName description parsers implementsInterfaces
<&> parsedSelectionsToFields IR.AFExpression
logicalModelSelectionList ::
(MonadBuildSchema b r m n, BackendCustomTypeSelectSchema b) =>
customReturnTypeSelectionList ::
(MonadBuildSchema b r m n, BackendCustomReturnTypeSelectSchema b) =>
G.Name ->
LogicalModelInfo b ->
CustomReturnTypeInfo b ->
SchemaT r m (Maybe (Parser 'Output n (AnnotatedFields b)))
logicalModelSelectionList name logicalModel =
fmap nonNullableObjectList <$> logicalModelSelectionSet name logicalModel
customReturnTypeSelectionList name customReturnType =
fmap nonNullableObjectList <$> customReturnTypeSelectionSet name customReturnType
-- | Converts an output type parser from object_type to [object_type!]!
nonNullableObjectList :: Parser 'Output m a -> Parser 'Output m a
@ -695,7 +691,7 @@ defaultTableArgs tableInfo = do
-- | Argument to filter rows returned from table selection
-- > where: table_bool_exp
logicalModelWhereArg ::
customReturnTypeWhereArg ::
forall b r m n.
( MonadBuildSchema b r m n,
AggregationPredicatesSchema b
@ -703,8 +699,8 @@ logicalModelWhereArg ::
G.Name ->
CustomReturnTypeInfo b ->
SchemaT r m (InputFieldsParser n (Maybe (IR.AnnBoolExp b (IR.UnpreparedValue b))))
logicalModelWhereArg name customReturnType = do
boolExpParser <- customTypeBoolExp name customReturnType
customReturnTypeWhereArg name customReturnType = do
boolExpParser <- customReturnTypeBoolExp name customReturnType
pure $
fmap join $
P.fieldOptional whereName whereDesc $
@ -715,14 +711,14 @@ logicalModelWhereArg name customReturnType = do
-- | Argument to sort rows returned from table selection
-- > order_by: [table_order_by!]
logicalModelOrderByArg ::
customReturnTypeOrderByArg ::
forall b r m n.
( MonadBuildSchema b r m n
) =>
G.Name ->
CustomReturnTypeInfo b ->
SchemaT r m (InputFieldsParser n (Maybe (NonEmpty (IR.AnnotatedOrderByItemG b (IR.UnpreparedValue b)))))
logicalModelOrderByArg name customReturnType = do
customReturnTypeOrderByArg name customReturnType = do
tCase <- retrieve $ _rscNamingConvention . _siCustomization @b
orderByParser <- customTypeOrderByExp name customReturnType
let orderByName = applyFieldNameCaseCust tCase Name._order_by
@ -737,22 +733,22 @@ logicalModelOrderByArg name customReturnType = do
-- | Argument to distinct select on columns returned from table selection
-- > distinct_on: [table_select_column!]
logicalModelDistinctArg ::
customReturnTypeDistinctArg ::
forall b r m n.
( MonadBuildSchema b r m n
) =>
G.Name ->
CustomReturnTypeInfo b ->
SchemaT r m (InputFieldsParser n (Maybe (NonEmpty (Column b))))
logicalModelDistinctArg name customReturnType = do
customReturnTypeDistinctArg name customReturnType = do
tCase <- retrieve $ _rscNamingConvention . _siCustomization @b
let maybeColumnDefinitions =
traverse definitionFromTypeRow (InsOrd.keys (_ctiFields customReturnType))
traverse definitionFromTypeRow (InsOrd.keys (_crtiFields customReturnType))
>>= NE.nonEmpty
case (,) <$> G.mkName "_enum_name" <*> maybeColumnDefinitions of
Nothing -> throw500 $ "Error creating an enum name for custom type " <> tshow (_ctiName customReturnType)
Nothing -> throw500 $ "Error creating an enum name for custom type " <> tshow (_crtiName customReturnType)
Just (enum', columnDefinitions) -> do
let enumName = name <> enum'
description = Nothing
@ -1210,7 +1206,7 @@ defaultArgsParser whereParser orderByParser distinctParser = do
parseError
"\"distinct_on\" columns must match initial \"order_by\" columns"
defaultLogicalModelArgs ::
defaultCustomReturnTypeArgs ::
forall b r m n.
( MonadBuildSchema b r m n,
AggregationPredicatesSchema b
@ -1218,10 +1214,10 @@ defaultLogicalModelArgs ::
G.Name ->
CustomReturnTypeInfo b ->
SchemaT r m (InputFieldsParser n (SelectArgs b))
defaultLogicalModelArgs name customReturnType = do
whereParser <- logicalModelWhereArg name customReturnType
orderByParser <- logicalModelOrderByArg name customReturnType
distinctParser <- logicalModelDistinctArg name customReturnType
defaultCustomReturnTypeArgs name customReturnType = do
whereParser <- customReturnTypeWhereArg name customReturnType
orderByParser <- customReturnTypeOrderByArg name customReturnType
distinctParser <- customReturnTypeDistinctArg name customReturnType
defaultArgsParser whereParser orderByParser distinctParser

View File

@ -5,13 +5,9 @@ module Hasura.LogicalModel.API
( GetLogicalModel (..),
TrackLogicalModel (..),
UntrackLogicalModel (..),
CreateLogicalModelPermission (..),
DropLogicalModelPermission (..),
runGetLogicalModel,
runTrackLogicalModel,
runUntrackLogicalModel,
runCreateSelectLogicalModelPermission,
runDropSelectLogicalModelPermission,
dropLogicalModelInMetadata,
module Hasura.LogicalModel.Types,
)
@ -28,22 +24,20 @@ import Hasura.Base.Error
import Hasura.CustomReturnType.API (getCustomTypes)
import Hasura.CustomReturnType.Metadata (CustomReturnTypeName)
import Hasura.EncJSON
import Hasura.LogicalModel.Metadata (LogicalModelArgumentName, LogicalModelMetadata (..), lmmSelectPermissions, parseInterpolatedQuery)
import Hasura.LogicalModel.Metadata (LogicalModelArgumentName, LogicalModelMetadata (..), parseInterpolatedQuery)
import Hasura.LogicalModel.Types (LogicalModelName, NullableScalarType)
import Hasura.Metadata.DTO.Utils (codecNamePrefix)
import Hasura.Prelude
import Hasura.RQL.Types.Backend (Backend, SourceConnConfiguration)
import Hasura.RQL.Types.Common (SourceName, defaultSource, sourceNameToText, successMsg)
import Hasura.RQL.Types.Common (SourceName, sourceNameToText, successMsg)
import Hasura.RQL.Types.Metadata
import Hasura.RQL.Types.Metadata.Backend
import Hasura.RQL.Types.Metadata.Object
import Hasura.RQL.Types.Permission (PermDef (_pdRole), SelPerm)
import Hasura.RQL.Types.SchemaCache.Build
import Hasura.SQL.AnyBackend qualified as AB
import Hasura.SQL.Backend
import Hasura.Server.Init.FeatureFlag as FF
import Hasura.Server.Types (HasServerConfigCtx (..), ServerConfigCtx (..))
import Hasura.Session (RoleName)
-- | Default implementation of the 'track_logical_model' request payload.
data TrackLogicalModel (b :: BackendType) = TrackLogicalModel
@ -112,7 +106,6 @@ logicalModelTrackToMetadata env sourceConnConfig TrackLogicalModel {..} = do
_lmmCode = code,
_lmmReturns = tlmReturns,
_lmmArguments = tlmArguments,
_lmmSelectPermissions = mempty,
_lmmDescription = tlmDescription
}
@ -280,88 +273,6 @@ throwIfFeatureDisabled = do
unless enableLogicalModels (throw500 "LogicalModels is disabled!")
-- | A permission for logical models is tied to a specific root field name and
-- source. This wrapper adds both of those things to the JSON object that
-- describes the permission.
data CreateLogicalModelPermission a (b :: BackendType) = CreateLogicalModelPermission
{ clmpSource :: SourceName,
clmpRootFieldName :: LogicalModelName,
clmpInfo :: PermDef b a
}
deriving stock (Generic)
instance
FromJSON (PermDef b a) =>
FromJSON (CreateLogicalModelPermission a b)
where
parseJSON = withObject "CreateLogicalModelPermission" \obj -> do
clmpSource <- obj .:? "source" .!= defaultSource
clmpRootFieldName <- obj .: "root_field_name"
clmpInfo <- parseJSON (Object obj)
pure CreateLogicalModelPermission {..}
runCreateSelectLogicalModelPermission ::
forall b m.
(Backend b, CacheRWM m, MetadataM m, MonadError QErr m, MonadIO m, HasServerConfigCtx m) =>
CreateLogicalModelPermission SelPerm b ->
m EncJSON
runCreateSelectLogicalModelPermission CreateLogicalModelPermission {..} = do
throwIfFeatureDisabled
assertLogicalModelExists @b clmpSource clmpRootFieldName
let metadataObj :: MetadataObjId
metadataObj =
MOSourceObjId clmpSource $
AB.mkAnyBackend $
SMOLogicalModel @b clmpRootFieldName
buildSchemaCacheFor metadataObj $
MetadataModifier $
logicalModelMetadataSetter @b clmpSource clmpRootFieldName . lmmSelectPermissions
%~ OMap.insert (_pdRole clmpInfo) clmpInfo
pure successMsg
-- | To drop a permission, we need to know the source and root field name of
-- the logical model, as well as the role whose permission we want to drop.
data DropLogicalModelPermission (b :: BackendType) = DropLogicalModelPermission
{ dlmpSource :: SourceName,
dlmpRootFieldName :: LogicalModelName,
dlmpRole :: RoleName
}
deriving stock (Generic)
instance FromJSON (DropLogicalModelPermission b) where
parseJSON = withObject "DropLogicalModelPermission" \obj -> do
dlmpSource <- obj .:? "source" .!= defaultSource
dlmpRootFieldName <- obj .: "root_field_name"
dlmpRole <- obj .: "role"
pure DropLogicalModelPermission {..}
runDropSelectLogicalModelPermission ::
forall b m.
(Backend b, CacheRWM m, MetadataM m, MonadError QErr m, MonadIO m, HasServerConfigCtx m) =>
DropLogicalModelPermission b ->
m EncJSON
runDropSelectLogicalModelPermission DropLogicalModelPermission {..} = do
throwIfFeatureDisabled
assertLogicalModelExists @b dlmpSource dlmpRootFieldName
let metadataObj :: MetadataObjId
metadataObj =
MOSourceObjId dlmpSource $
AB.mkAnyBackend $
SMOLogicalModel @b dlmpRootFieldName
buildSchemaCacheFor metadataObj $
MetadataModifier $
logicalModelMetadataSetter @b dlmpSource dlmpRootFieldName . lmmSelectPermissions
%~ OMap.delete dlmpRole
pure successMsg
-- | Check whether a logical model with the given root field name exists for
-- the given source.
assertLogicalModelExists :: forall b m. (Backend b, MetadataM m, MonadError QErr m) => SourceName -> LogicalModelName -> m ()

View File

@ -9,7 +9,6 @@ module Hasura.LogicalModel.Cache
lmiCode,
lmiReturns,
lmiArguments,
lmiPermissions,
lmiDescription,
)
where
@ -33,7 +32,6 @@ data LogicalModelInfo (b :: BackendType) = LogicalModelInfo
_lmiCode :: InterpolatedQuery LogicalModelArgumentName,
_lmiReturns :: CustomReturnTypeInfo b,
_lmiArguments :: HashMap LogicalModelArgumentName (NullableScalarType b),
_lmiPermissions :: RolePermInfoMap b,
_lmiDescription :: Maybe Text
}
deriving stock (Generic)

View File

@ -12,11 +12,9 @@ module Hasura.LogicalModel.Metadata
lmmDescription,
lmmReturns,
lmmRootFieldName,
lmmSelectPermissions,
LogicalModelArgumentName (..),
InterpolatedItem (..),
InterpolatedQuery (..),
WithLogicalModel (..),
parseInterpolatedQuery,
module Hasura.LogicalModel.Types,
)
@ -25,20 +23,15 @@ where
import Autodocodec
import Autodocodec qualified as AC
import Control.Lens (makeLenses)
import Data.Aeson (FromJSON (parseJSON), FromJSONKey, ToJSON, ToJSONKey, (.!=), (.:), (.:?))
import Data.Aeson qualified as Aeson
import Data.Aeson (FromJSON, FromJSONKey, ToJSON, ToJSONKey)
import Data.Bifunctor (first)
import Data.HashMap.Strict.InsOrd.Autodocodec (sortedElemsCodec)
import Data.Text qualified as T
import Hasura.CustomReturnType.Metadata (CustomReturnTypeName)
import Hasura.LogicalModel.Types (LogicalModelName (..), NullableScalarType)
import Hasura.Metadata.DTO.Utils (codecNamePrefix)
import Hasura.Prelude hiding (first)
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Common (SourceName, ToAesonPairs (toAesonPairs), defaultSource)
import Hasura.RQL.Types.Permission (SelPermDef, _pdRole)
import Hasura.SQL.Backend
import Hasura.Session (RoleName)
import Language.Haskell.TH.Syntax (Lift)
newtype RawQuery = RawQuery {getRawQuery :: Text}
@ -130,7 +123,6 @@ data LogicalModelMetadata (b :: BackendType) = LogicalModelMetadata
_lmmCode :: InterpolatedQuery LogicalModelArgumentName,
_lmmReturns :: CustomReturnTypeName,
_lmmArguments :: HashMap LogicalModelArgumentName (NullableScalarType b),
_lmmSelectPermissions :: InsOrdHashMap RoleName (SelPermDef b),
_lmmDescription :: Maybe Text
}
deriving (Generic)
@ -153,8 +145,6 @@ instance (Backend b) => HasCodec (LogicalModelMetadata b) where
AC..= _lmmReturns
<*> optionalFieldWithDefault "arguments" mempty argumentDoc
AC..= _lmmArguments
<*> optSortedList "select_permissions" _pdRole
AC..= _lmmSelectPermissions
<*> optionalField "description" descriptionDoc
AC..= _lmmDescription
where
@ -164,9 +154,6 @@ instance (Backend b) => HasCodec (LogicalModelMetadata b) where
returnsDoc = "Return type (table) of the expression"
descriptionDoc = "A description of the logical model which appears in the graphql schema"
optSortedList name keyForElem =
AC.optionalFieldWithOmittedDefaultWith' name (sortedElemsCodec keyForElem) mempty
deriving via
(Autodocodec (LogicalModelMetadata b))
instance
@ -177,28 +164,6 @@ deriving via
instance
(Backend b) => (ToJSON (LogicalModelMetadata b))
-- | A wrapper to tie something to a particular logical model. Specifically, it
-- assumes the underlying '_wlmInfo' is represented as an object, and adds two
-- keys to that object: @source@ and @root_field_name@.
data WithLogicalModel a = WithLogicalModel
{ _wlmSource :: SourceName,
_wlmName :: LogicalModelName,
_wlmInfo :: a
}
deriving stock (Eq, Show)
instance (FromJSON a) => FromJSON (WithLogicalModel a) where
parseJSON = Aeson.withObject "LogicalModel" \obj -> do
_wlmSource <- obj .:? "source" .!= defaultSource
_wlmName <- obj .: "root_field_name"
_wlmInfo <- parseJSON (Aeson.Object obj)
pure WithLogicalModel {..}
instance (ToAesonPairs a) => ToJSON (WithLogicalModel a) where
toJSON (WithLogicalModel source name info) =
Aeson.object $ ("source", Aeson.toJSON source) : ("root_field_name", Aeson.toJSON name) : toAesonPairs info
-- | extract all of the `{{ variable }}` inside our query string
parseInterpolatedQuery ::
Text ->

View File

@ -8,27 +8,21 @@ import Data.HashMap.Strict qualified as HM
import Data.Monoid (Ap (Ap, getAp))
import Hasura.CustomReturnType.Schema
import Hasura.GraphQL.Schema.Backend
( BackendCustomTypeSelectSchema (..),
( BackendCustomReturnTypeSelectSchema (..),
BackendSchema (columnParser),
MonadBuildSchema,
)
import Hasura.GraphQL.Schema.Common
( SchemaT,
partialSQLExpToUnpreparedValue,
retrieve,
scRole,
)
import Hasura.GraphQL.Schema.Options qualified as Options
import Hasura.GraphQL.Schema.Parser qualified as P
import Hasura.GraphQL.Schema.Select
( logicalModelSelectionList,
)
import Hasura.LogicalModel.Cache (LogicalModelInfo (..))
import Hasura.LogicalModel.IR (LogicalModel (..))
import Hasura.LogicalModel.Metadata (InterpolatedQuery (..), LogicalModelArgumentName (getLogicalModelArgumentName))
import Hasura.LogicalModel.Types (NullableScalarType (..), getLogicalModelName)
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp (gBoolExpTrue)
import Hasura.RQL.IR.Root (RemoteRelationshipField)
import Hasura.RQL.IR.Select (QueryDB (QDBMultipleRows))
import Hasura.RQL.IR.Select qualified as IR
@ -41,36 +35,27 @@ import Hasura.RQL.Types.Source
import Hasura.RQL.Types.SourceCustomization
( ResolvedSourceCustomization (_rscNamingConvention),
)
import Hasura.RQL.Types.Table (SelPermInfo (..), _permSel)
import Hasura.SQL.AnyBackend (mkAnyBackend)
import Hasura.Session (RoleName, adminRoleName)
import Language.GraphQL.Draft.Syntax qualified as G
import Language.GraphQL.Draft.Syntax.QQ qualified as G
-- | find list of columns we're allowed to access for this role
getSelPermInfoForLogicalModel ::
RoleName ->
LogicalModelInfo b ->
Maybe (SelPermInfo b)
getSelPermInfoForLogicalModel role logicalModel =
HM.lookup role (_lmiPermissions logicalModel) >>= _permSel
defaultBuildLogicalModelRootFields ::
forall b r m n.
( MonadBuildSchema b r m n,
BackendCustomTypeSelectSchema b
BackendCustomReturnTypeSelectSchema b
) =>
LogicalModelInfo b ->
SchemaT
r
m
(Maybe (P.FieldParser n (QueryDB b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))))
defaultBuildLogicalModelRootFields logicalModel@LogicalModelInfo {..} = runMaybeT $ do
defaultBuildLogicalModelRootFields LogicalModelInfo {..} = runMaybeT $ do
let fieldName = getLogicalModelName _lmiRootFieldName
logicalModelArgsParser <- logicalModelArgumentsSchema @b @r @m @n fieldName _lmiArguments
logicalModelArgsParser <-
logicalModelArgumentsSchema @b @r @m @n fieldName _lmiArguments
sourceInfo :: SourceInfo b <- asks getter
roleName <- retrieve scRole
let sourceName = _siName sourceInfo
tCase = _rscNamingConvention $ _siCustomization sourceInfo
@ -78,8 +63,12 @@ defaultBuildLogicalModelRootFields logicalModel@LogicalModelInfo {..} = runMaybe
stringifyNumbers <- retrieve Options.soStringifyNumbers
selectionSetParser <- MaybeT $ logicalModelSelectionList @b @r @m @n (getLogicalModelName _lmiRootFieldName) logicalModel
customTypesArgsParser <- lift $ logicalModelArguments @b @r @m @n (getLogicalModelName _lmiRootFieldName) _lmiReturns
customReturnTypePermissions <-
MaybeT . fmap Just $
buildCustomReturnTypePermissions @b @r @m @n _lmiReturns
(selectionSetParser, customTypesArgsParser) <-
MaybeT $ buildCustomReturnTypeFields _lmiReturns
let interpolatedQuery lmArgs =
InterpolatedQuery $
@ -94,18 +83,13 @@ defaultBuildLogicalModelRootFields logicalModel@LogicalModelInfo {..} = runMaybe
)
(getInterpolatedQuery _lmiCode)
let logicalModelPerm = case getSelPermInfoForLogicalModel roleName logicalModel of
Just selectPermissions ->
IR.TablePerm
{ IR._tpFilter = fmap partialSQLExpToUnpreparedValue <$> spiFilter selectPermissions,
IR._tpLimit = spiLimit selectPermissions
}
Nothing -> IR.TablePerm gBoolExpTrue Nothing
let customReturnTypeIR = buildCustomReturnType _lmiReturns
let sourceObj =
MO.MOSourceObjId
sourceName
(mkAnyBackend $ MO.SMOLogicalModel @b _lmiRootFieldName)
pure $
P.setFieldParserOrigin (MO.MOSourceObjId sourceName (mkAnyBackend $ MO.SMOLogicalModel @b _lmiRootFieldName)) $
P.setFieldParserOrigin sourceObj $
P.subselection
fieldName
description
@ -114,7 +98,7 @@ defaultBuildLogicalModelRootFields logicalModel@LogicalModelInfo {..} = runMaybe
<*> logicalModelArgsParser
)
selectionSetParser
<&> \((args, lmArgs), fields) ->
<&> \((crtArgs, lmArgs), fields) ->
QDBMultipleRows $
IR.AnnSelectG
{ IR._asnFields = fields,
@ -124,13 +108,10 @@ defaultBuildLogicalModelRootFields logicalModel@LogicalModelInfo {..} = runMaybe
{ lmRootFieldName = _lmiRootFieldName,
lmArgs,
lmInterpolatedQuery = interpolatedQuery lmArgs,
lmReturnType = customReturnTypeIR
lmReturnType = buildCustomReturnTypeIR _lmiReturns
},
IR._asnPerm =
if roleName == adminRoleName
then IR.TablePerm gBoolExpTrue Nothing
else logicalModelPerm,
IR._asnArgs = args,
IR._asnPerm = customReturnTypePermissions,
IR._asnArgs = crtArgs,
IR._asnStrfyNum = stringifyNumbers,
IR._asnNamingConvention = Just tCase
}

View File

@ -708,12 +708,12 @@ purgeMetadataObj = \case
SMOFunctionPermission qf rn -> dropFunctionPermissionInMetadata @b source qf rn
SMOCustomReturnType crt -> dropCustomReturnTypeInMetadata @b source crt
SMOLogicalModel lm -> dropLogicalModelInMetadata @b source lm
SMOLogicalModelObj logicalModelName logicalModelMetadataObjId ->
SMOCustomReturnTypeObj customReturnTypeName customReturnTypeMetadataObjId ->
MetadataModifier $
logicalModelMetadataSetter @b source logicalModelName
%~ case logicalModelMetadataObjId of
LMMOPerm roleName permType ->
dropLogicalModelPermissionInMetadata roleName permType
customReturnTypeMetadataSetter @b source customReturnTypeName
%~ case customReturnTypeMetadataObjId of
CRTMOPerm roleName permType ->
dropCustomReturnTypePermissionInMetadata roleName permType
SMOTableObj qt tableObj ->
MetadataModifier $
tableMetadataSetter @b source qt %~ case tableObj of

View File

@ -24,7 +24,7 @@ module Hasura.RQL.DDL.Permission
runSetPermComment,
PermInfo,
buildPermInfo,
buildLogicalModelPermInfo,
buildCustomReturnTypePermInfo,
addPermissionToMetadata,
annBoolExp,
)
@ -40,8 +40,8 @@ import Data.HashSet qualified as HS
import Data.Sequence qualified as Seq
import Data.Text.Extended
import Hasura.Base.Error
import Hasura.CustomReturnType.Types (CustomReturnTypeName)
import Hasura.EncJSON
import Hasura.LogicalModel.Types (LogicalModelName)
import Hasura.Prelude
import Hasura.RQL.DDL.Permission.Internal
import Hasura.RQL.IR.BoolExp
@ -236,19 +236,19 @@ buildPermInfo x1 x2 x3 roleName = \case
-- | Given the logical model's definition and the permissions as defined in the
-- logical model's metadata, try to construct the permission definition.
buildLogicalModelPermInfo ::
buildCustomReturnTypePermInfo ::
( BackendMetadata b,
QErrM m,
TableCoreInfoRM b m,
GetAggregationPredicatesDeps b
) =>
SourceName ->
LogicalModelName ->
CustomReturnTypeName ->
FieldInfoMap (FieldInfo b) ->
PermDefPermission b perm ->
m (WithDeps (PermInfo perm b))
buildLogicalModelPermInfo sourceName logicalModelName fieldInfoMap = \case
SelPerm' p -> buildLogicalModelSelPermInfo sourceName logicalModelName fieldInfoMap p
buildCustomReturnTypePermInfo sourceName customReturnTypeName fieldInfoMap = \case
SelPerm' p -> buildCustomReturnTypeSelPermInfo sourceName customReturnTypeName fieldInfoMap p
InsPerm' _ -> error "Not implemented yet"
UpdPerm' _ -> error "Not implemented yet"
DelPerm' _ -> error "Not implemented yet"
@ -421,7 +421,7 @@ validateAllowedRootFields sourceName tableName roleName SelPerm {..} = do
-- | Given the logical model's definition and the permissions as defined in the
-- logical model's metadata, try to construct the @SELECT@ permission
-- definition.
buildLogicalModelSelPermInfo ::
buildCustomReturnTypeSelPermInfo ::
forall b m.
( QErrM m,
TableCoreInfoRM b m,
@ -429,18 +429,18 @@ buildLogicalModelSelPermInfo ::
GetAggregationPredicatesDeps b
) =>
SourceName ->
LogicalModelName ->
CustomReturnTypeName ->
FieldInfoMap (FieldInfo b) ->
SelPerm b ->
m (WithDeps (SelPermInfo b))
buildLogicalModelSelPermInfo source logicalModelName fieldInfoMap sp = withPathK "permission" do
buildCustomReturnTypeSelPermInfo source customReturnTypeName fieldInfoMap sp = withPathK "permission" do
let columns :: [Column b]
columns = interpColSpec (ciColumn <$> getCols fieldInfoMap) (spColumns sp)
-- Interpret the row permissions in the 'SelPerm' definition.
(spiFilter, boolExpDeps) <-
withPathK "filter" $
procLogicalModelBoolExp source logicalModelName fieldInfoMap (spFilter sp)
procCustomReturnTypeBoolExp source customReturnTypeName fieldInfoMap (spFilter sp)
let -- What parts of the metadata are interesting when computing the
-- permissions? These dependencies bubble all the way up to
@ -449,9 +449,9 @@ buildLogicalModelSelPermInfo source logicalModelName fieldInfoMap sp = withPathK
deps :: Seq SchemaDependency
deps =
mconcat
[ Seq.singleton (mkLogicalModelParentDep @b source logicalModelName),
[ Seq.singleton (mkCustomReturnTypeParentDep @b source customReturnTypeName),
boolExpDeps,
fmap (mkLogicalModelColDep @b DRUntyped source logicalModelName) $
fmap (mkCustomReturnTypeColDep @b DRUntyped source customReturnTypeName) $
Seq.fromList columns
]

View File

@ -10,7 +10,7 @@ module Hasura.RQL.DDL.Permission.Internal
getDependentHeaders,
annBoolExp,
procBoolExp,
procLogicalModelBoolExp,
procCustomReturnTypeBoolExp,
)
where
@ -23,7 +23,7 @@ import Data.Sequence qualified as Seq
import Data.Text qualified as T
import Data.Text.Extended
import Hasura.Base.Error
import Hasura.LogicalModel.Types (LogicalModelName)
import Hasura.CustomReturnType.Types (CustomReturnTypeName)
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.Types.Backend
@ -110,8 +110,8 @@ procBoolExp source tn fieldInfoMap be = do
-- | Interpret a 'BoolExp' into an 'AnnBoolExp', collecting any dependencies as
-- we go. At the moment, the only dependencies we're likely to encounter are
-- independent dependencies on other tables. For example, "this user can only
-- select from this logical model if their ID is in the @allowed_users@ table".
procLogicalModelBoolExp ::
-- select from this custom return type if their ID is in the @allowed_users@ table".
procCustomReturnTypeBoolExp ::
forall b m.
( QErrM m,
TableCoreInfoRM b m,
@ -119,11 +119,11 @@ procLogicalModelBoolExp ::
GetAggregationPredicatesDeps b
) =>
SourceName ->
LogicalModelName ->
CustomReturnTypeName ->
FieldInfoMap (FieldInfo b) ->
BoolExp b ->
m (AnnBoolExpPartialSQL b, Seq SchemaDependency)
procLogicalModelBoolExp source lmn fieldInfoMap be = do
procCustomReturnTypeBoolExp source lmn fieldInfoMap be = do
let -- The parser for the "right hand side" of operations. We use @rhsParser@
-- as the name here for ease of grepping, though it's maybe a bit vague.
-- More specifically, if we think of an operation that combines a field
@ -140,9 +140,9 @@ procLogicalModelBoolExp source lmn fieldInfoMap be = do
let -- What dependencies do we have on the schema cache in order to process
-- this boolean expression? This dependency system is explained more
-- thoroughly in the 'buildLogicalModelSelPermInfo' inline comments.
-- thoroughly in the 'buildCustomReturnTypeSelPermInfo' inline comments.
deps :: [SchemaDependency]
deps = getLogicalModelBoolExpDeps source lmn abe
deps = getCustomReturnTypeBoolExpDeps source lmn abe
return (abe, Seq.fromList deps)

View File

@ -754,16 +754,23 @@ buildSchemaCacheRule logger env = proc (MetadataWithResourceVersion metadataNoDe
unless areLogicalModelsEnabled $
throw400 InvalidConfiguration "The Logical Models feature is disabled"
fieldInfoMap <- case toFieldInfo _crtmFields of
Nothing -> pure mempty
Just fields -> pure (mapFromL fieldInfoName fields)
customTypePermissions <-
buildCustomReturnTypePermissions sourceName tableCoreInfos _crtmName fieldInfoMap _crtmSelectPermissions orderedRoles
pure
CustomReturnTypeInfo
{ _ctiName = _crtmName,
_ctiFields = _crtmFields,
_ctiPermissions = mempty,
_ctiDescription = _crtmDescription
{ _crtiName = _crtmName,
_crtiFields = _crtmFields,
_crtiPermissions = customTypePermissions,
_crtiDescription = _crtmDescription
}
let customReturnTypesCache :: CustomReturnTypeCache b
customReturnTypesCache = mapFromL _ctiName (catMaybes customReturnTypeCacheMaybes)
customReturnTypesCache = mapFromL _crtiName (catMaybes customReturnTypeCacheMaybes)
let mkLogicalModelMetadataObject :: LogicalModelMetadata b -> MetadataObject
mkLogicalModelMetadataObject lmm =
@ -789,20 +796,12 @@ buildSchemaCacheRule logger env = proc (MetadataWithResourceVersion metadataNoDe
(M.lookup _lmmReturns customReturnTypesCache)
(throw400 InvalidConfiguration ("The custom return type " <> toTxt _lmmReturns <> " could not be found"))
fieldInfoMap <- case toFieldInfo customReturnType of
Nothing -> pure mempty
Just fields -> pure (mapFromL fieldInfoName fields)
logicalModelPermissions <-
buildLogicalModelPermissions sourceName tableCoreInfos _lmmRootFieldName fieldInfoMap _lmmSelectPermissions orderedRoles
pure
LogicalModelInfo
{ _lmiRootFieldName = _lmmRootFieldName,
_lmiCode = _lmmCode,
_lmiReturns = customReturnType,
_lmiArguments = _lmmArguments,
_lmiPermissions = logicalModelPermissions,
_lmiDescription = _lmmDescription
}

View File

@ -24,7 +24,7 @@ module Hasura.RQL.DDL.Schema.Cache.Common
TableBuildInput (TableBuildInput, _tbiName),
TablePermissionInputs (..),
addTableContext,
addLogicalModelContext,
addCustomReturnTypeContext,
bindErrorA,
boActions,
boCustomTypes,
@ -55,9 +55,9 @@ import Data.HashMap.Strict.InsOrd qualified as OMap
import Data.Sequence qualified as Seq
import Data.Text.Extended
import Hasura.Base.Error
import Hasura.CustomReturnType.Types (CustomReturnTypeName)
import Hasura.EncJSON
import Hasura.Incremental qualified as Inc
import Hasura.LogicalModel.Types (LogicalModelName)
import Hasura.Prelude
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Column
@ -428,5 +428,5 @@ buildInfoMapPreservingMetadataM extractKey mkMetadataObject buildInfo =
addTableContext :: (Backend b) => TableName b -> Text -> Text
addTableContext tableName e = "in table " <> tableName <<> ": " <> e
addLogicalModelContext :: LogicalModelName -> Text -> Text
addLogicalModelContext logicalModelName e = "in logical model " <> logicalModelName <<> ": " <> e
addCustomReturnTypeContext :: CustomReturnTypeName -> Text -> Text
addCustomReturnTypeContext logicalModelName e = "in custom return type " <> logicalModelName <<> ": " <> e

View File

@ -14,9 +14,8 @@ import Data.List (nub)
import Data.Monoid (First)
import Data.Text.Extended
import Hasura.Base.Error
import Hasura.CustomReturnType.Cache (_ctiFields)
import Hasura.CustomReturnType.Cache (crtiPermissions, _crtiFields)
import Hasura.Function.Cache
import Hasura.LogicalModel.Cache (lmiPermissions, _lmiReturns)
import Hasura.Prelude
import Hasura.RQL.DDL.Permission.Internal (permissionIsDefined)
import Hasura.RQL.DDL.Schema.Cache.Common
@ -163,24 +162,26 @@ pruneDanglingDependents cache =
void $
M.lookup functionName (_siFunctions sourceInfo)
`onNothing` Left ("function " <> functionName <<> " is not tracked")
SOILogicalModel logicalModelName -> do
void $ resolveLogicalModel sourceInfo logicalModelName
SOILogicalModelObj logicalModelName logicalModelObjectId -> do
logicalModel <- resolveLogicalModel sourceInfo logicalModelName
case logicalModelObjectId of
LMOPerm roleName permType -> do
SOICustomReturnType customReturnTypeName -> do
void $ resolveCustomReturnType sourceInfo customReturnTypeName
SOICustomReturnTypeObj customReturnTypeName customReturnTypeObjId -> do
customReturnType <- resolveCustomReturnType sourceInfo customReturnTypeName
case customReturnTypeObjId of
CRTOPerm roleName permType -> do
let rolePermissions :: Maybe (RolePermInfo b)
rolePermissions = logicalModel ^? lmiPermissions . ix roleName
rolePermissions = customReturnType ^? crtiPermissions . ix roleName
unless (any (permissionIsDefined permType) rolePermissions) $
Left $
"no "
<> permTypeToCode permType
<> " permission defined on logical model "
<> logicalModelName <<> " for role " <>> roleName
LMOCol column ->
unless (InsOrd.member column (_ctiFields (_lmiReturns logicalModel))) do
Left ("Could not find column " <> column <<> " in logical model " <>> logicalModelName)
<> " permission defined on custom return type "
<> customReturnTypeName <<> " for role " <>> roleName
CRTOCol column ->
unless (InsOrd.member column (_crtiFields customReturnType)) do
Left ("Could not find column " <> column <<> " in custom return type " <>> customReturnTypeName)
SOILogicalModel logicalModelName -> do
void $ resolveLogicalModel sourceInfo logicalModelName
SOITableObj tableName tableObjectId -> do
tableInfo <- resolveTable sourceInfo tableName
case tableObjectId of
@ -231,6 +232,10 @@ pruneDanglingDependents cache =
M.lookup logicalModelName (_siLogicalModels sourceInfo)
`onNothing` Left ("logical model " <> logicalModelName <<> " is not tracked")
resolveCustomReturnType sourceInfo customReturnTypeName =
M.lookup customReturnTypeName (_siCustomReturnTypes sourceInfo)
`onNothing` Left ("custom return type " <> customReturnTypeName <<> " is not tracked")
columnToFieldName :: forall b. (Backend b) => TableInfo b -> Column b -> FieldName
columnToFieldName _ = fromCol @b
@ -298,14 +303,14 @@ deleteMetadataObject = \case
SMOFunction name -> siFunctions %~ M.delete name
SMOFunctionPermission functionName role ->
siFunctions . ix functionName . fiPermissions %~ M.delete role
SMOCustomReturnType name -> siCustomReturnTypes %~ M.delete name
SMOLogicalModel name -> siLogicalModels %~ M.delete name
SMOLogicalModelObj logicalModelName logicalModelObjectId ->
siLogicalModels . ix logicalModelName %~ case logicalModelObjectId of
LMMOPerm roleName PTSelect -> lmiPermissions . ix roleName . permSel .~ Nothing
LMMOPerm roleName PTInsert -> lmiPermissions . ix roleName . permIns .~ Nothing
LMMOPerm roleName PTUpdate -> lmiPermissions . ix roleName . permUpd .~ Nothing
LMMOPerm roleName PTDelete -> lmiPermissions . ix roleName . permDel .~ Nothing
SMOCustomReturnType name -> siCustomReturnTypes %~ M.delete name
SMOCustomReturnTypeObj customReturnTypeName customReturnTypeObjectId ->
siCustomReturnTypes . ix customReturnTypeName %~ case customReturnTypeObjectId of
CRTMOPerm roleName PTSelect -> crtiPermissions . ix roleName . permSel .~ Nothing
CRTMOPerm roleName PTInsert -> crtiPermissions . ix roleName . permIns .~ Nothing
CRTMOPerm roleName PTUpdate -> crtiPermissions . ix roleName . permUpd .~ Nothing
CRTMOPerm roleName PTDelete -> crtiPermissions . ix roleName . permDel .~ Nothing
SMOTableObj tableName tableObjectId ->
siTables . ix tableName %~ case tableObjectId of
MTORel name _ -> tiCoreInfo . tciFieldInfoMap %~ M.delete (fromRel name)

View File

@ -5,7 +5,7 @@ module Hasura.RQL.DDL.Schema.Cache.Permission
_unOrderedRoles,
mkBooleanPermissionMap,
resolveCheckPermission,
buildLogicalModelPermissions,
buildCustomReturnTypePermissions,
)
where
@ -16,8 +16,8 @@ import Data.HashMap.Strict.InsOrd qualified as OMap
import Data.Sequence qualified as Seq
import Data.Text.Extended
import Hasura.Base.Error
import Hasura.LogicalModel.Metadata (WithLogicalModel (..))
import Hasura.LogicalModel.Types (LogicalModelName)
import Hasura.CustomReturnType.Metadata (WithCustomReturnType (..))
import Hasura.CustomReturnType.Types (CustomReturnTypeName)
import Hasura.Prelude
import Hasura.RQL.DDL.Permission
import Hasura.RQL.DDL.Schema.Cache.Common
@ -283,7 +283,7 @@ buildTablePermissions source tableCache tableFields tablePermissions orderedRole
-- | Create the permission map for a logical model based on the select
-- permissions given in metadata. Compare with 'buildTablePermissions'.
buildLogicalModelPermissions ::
buildCustomReturnTypePermissions ::
forall b m.
( MonadError QErr m,
MonadWriter (Seq (Either InconsistentMetadata MetadataDependency)) m,
@ -292,12 +292,12 @@ buildLogicalModelPermissions ::
) =>
SourceName ->
TableCoreCache b ->
LogicalModelName ->
CustomReturnTypeName ->
FieldInfoMap (FieldInfo b) ->
InsOrdHashMap RoleName (SelPermDef b) ->
OrderedRoles ->
m (RolePermInfoMap b)
buildLogicalModelPermissions sourceName tableCache logicalModelName logicalModelFields selectPermissions orderedRoles = do
buildCustomReturnTypePermissions sourceName tableCache customReturnTypeName customReturnTypeFields selectPermissions orderedRoles = do
let combineRolePermissions :: RolePermInfoMap b -> Role -> m (RolePermInfoMap b)
combineRolePermissions acc (Role roleName (ParentRoles parentRoles)) = do
-- This error will ideally never be thrown, but if it's thrown then
@ -335,7 +335,7 @@ buildLogicalModelPermissions sourceName tableCache logicalModelName logicalModel
pure (M.insert roleName rolePermInfo acc)
-- At the moment, we only support select permissions for logical models.
-- At the moment, we only support select permissions for custom return types
metadataRolePermissions <-
for (OMap.toHashMap selectPermissions) \selectPermission -> do
let role :: RoleName
@ -347,8 +347,8 @@ buildLogicalModelPermissions sourceName tableCache logicalModelName logicalModel
sourceObjId =
MOSourceObjId sourceName $
AB.mkAnyBackend $
SMOLogicalModelObj @b logicalModelName $
LMMOPerm role PTSelect
SMOCustomReturnTypeObj @b customReturnTypeName $
CRTMOPerm role PTSelect
-- The object we're going to use to track the dependency and any
-- potential cache inconsistencies.
@ -356,10 +356,10 @@ buildLogicalModelPermissions sourceName tableCache logicalModelName logicalModel
metadataObject =
MetadataObject sourceObjId $
toJSON
WithLogicalModel
{ _wlmSource = sourceName,
_wlmName = logicalModelName,
_wlmInfo = selectPermission
WithCustomReturnType
{ _wcrtSource = sourceName,
_wcrtName = customReturnTypeName,
_wcrtInfo = selectPermission
}
-- An identifier for this permission within the metadata structure.
@ -367,12 +367,12 @@ buildLogicalModelPermissions sourceName tableCache logicalModelName logicalModel
schemaObject =
SOSourceObj sourceName $
AB.mkAnyBackend $
SOILogicalModelObj @b logicalModelName $
LMOPerm role PTSelect
SOICustomReturnTypeObj @b customReturnTypeName $
CRTOPerm role PTSelect
modifyError :: ExceptT QErr m a -> ExceptT QErr m a
modifyError = modifyErr \err ->
addLogicalModelContext logicalModelName $
addCustomReturnTypeContext customReturnTypeName $
"in permission for role " <> role <<> ": " <> err
select <- withRecordInconsistencyM metadataObject $ modifyError do
@ -381,7 +381,7 @@ buildLogicalModelPermissions sourceName tableCache logicalModelName logicalModel
(permissionInformation, dependencies) <-
flip runTableCoreCacheRT tableCache $
buildLogicalModelPermInfo sourceName logicalModelName logicalModelFields $
buildCustomReturnTypePermInfo sourceName customReturnTypeName customReturnTypeFields $
_pdPermission selectPermission
recordDependenciesM metadataObject schemaObject dependencies

View File

@ -12,7 +12,7 @@ module Hasura.RQL.Types.Metadata
dropEventTriggerInMetadata,
dropFunctionInMetadata,
dropPermissionInMetadata,
dropLogicalModelPermissionInMetadata,
dropCustomReturnTypePermissionInMetadata,
dropRelationshipInMetadata,
dropRemoteRelationshipInMetadata,
dropTableInMetadata,
@ -55,11 +55,11 @@ import Data.Aeson.TH
import Data.Aeson.Types
import Data.HashMap.Strict.InsOrd.Extended qualified as OM
import Data.Monoid (Dual (..), Endo (..))
import Hasura.CustomReturnType.Metadata (CustomReturnTypeMetadata, CustomReturnTypeName)
import Hasura.CustomReturnType.Metadata (CustomReturnTypeMetadata, CustomReturnTypeName, crtmSelectPermissions)
import Hasura.Function.Cache
import Hasura.Function.Metadata (FunctionMetadata (..))
import Hasura.Incremental qualified as Inc
import Hasura.LogicalModel.Metadata (LogicalModelMetadata, LogicalModelName, lmmSelectPermissions)
import Hasura.LogicalModel.Metadata (LogicalModelMetadata, LogicalModelName)
import Hasura.Metadata.DTO.MetadataV3 (MetadataV3 (..))
import Hasura.Prelude
import Hasura.RQL.Types.Allowlist
@ -396,10 +396,10 @@ dropPermissionInMetadata rn = \case
PTDelete -> tmDeletePermissions %~ OM.delete rn
PTUpdate -> tmUpdatePermissions %~ OM.delete rn
dropLogicalModelPermissionInMetadata ::
RoleName -> PermType -> LogicalModelMetadata b -> LogicalModelMetadata b
dropLogicalModelPermissionInMetadata rn = \case
PTSelect -> lmmSelectPermissions %~ OM.delete rn
dropCustomReturnTypePermissionInMetadata ::
RoleName -> PermType -> CustomReturnTypeMetadata b -> CustomReturnTypeMetadata b
dropCustomReturnTypePermissionInMetadata rn = \case
PTSelect -> crtmSelectPermissions %~ OM.delete rn
PTInsert -> error "Not implemented yet"
PTDelete -> error "Not implemented yet"
PTUpdate -> error "Not implemented yet"

View File

@ -7,7 +7,7 @@ module Hasura.RQL.Types.Metadata.Object
MetadataObject (..),
SourceMetadataObjId (..),
TableMetadataObjId (..),
LogicalModelMetadataObjId (..),
CustomReturnTypeMetadataObjId (..),
droppableInconsistentMetadata,
getInconsistentRemoteSchemas,
groupInconsistentMetadataById,
@ -72,12 +72,12 @@ data TableMetadataObjId
instance Hashable TableMetadataObjId
-- | Identifiers for logical model elements within the metadata structure.
data LogicalModelMetadataObjId
= LMMOPerm RoleName PermType
-- | Identifiers for custom return type elements within the metadata structure.
data CustomReturnTypeMetadataObjId
= CRTMOPerm RoleName PermType
deriving (Show, Eq, Ord, Generic)
instance Hashable LogicalModelMetadataObjId
instance Hashable CustomReturnTypeMetadataObjId
data SourceMetadataObjId b
= SMOTable (TableName b)
@ -85,8 +85,8 @@ data SourceMetadataObjId b
| SMOFunctionPermission (FunctionName b) RoleName
| SMOTableObj (TableName b) TableMetadataObjId
| SMOLogicalModel LogicalModelName
| SMOLogicalModelObj LogicalModelName LogicalModelMetadataObjId
| SMOCustomReturnType CustomReturnTypeName
| SMOCustomReturnTypeObj CustomReturnTypeName CustomReturnTypeMetadataObjId
deriving (Generic)
deriving instance (Backend b) => Show (SourceMetadataObjId b)
@ -148,9 +148,9 @@ moiTypeName = \case
SMOTable _ -> "table"
SMOFunction _ -> "function"
SMOLogicalModel _ -> "logical_model"
SMOLogicalModelObj _ logicalModelObjectId -> case logicalModelObjectId of
LMMOPerm _ permType -> permTypeToCode permType <> "_permission"
SMOCustomReturnType _ -> "custom_type"
SMOCustomReturnTypeObj _ customReturnTypeObjectId -> case customReturnTypeObjectId of
CRTMOPerm _ permType -> permTypeToCode permType <> "_permission"
SMOFunctionPermission _ _ -> "function_permission"
SMOTableObj _ tableObjectId -> case tableObjectId of
MTORel _ relType -> relTypeToTxt relType <> "_relation"
@ -202,18 +202,18 @@ moiName objectId =
<> toTxt functionName
<> " in source "
<> toTxt source
SMOCustomReturnType name -> toTxt name <> " in source " <> toTxt source
SMOLogicalModel name -> toTxt name <> " in source " <> toTxt source
SMOLogicalModelObj logicalModelName logicalModelObjectId -> do
SMOCustomReturnType name -> toTxt name <> " in source " <> toTxt source
SMOCustomReturnTypeObj customReturnTypeName customReturnTypeObjectId -> do
let objectName :: Text
objectName = case logicalModelObjectId of
LMMOPerm name _ -> toTxt name
objectName = case customReturnTypeObjectId of
CRTMOPerm name _ -> toTxt name
sourceObjectId :: MetadataObjId
sourceObjectId =
MOSourceObjId source $
AB.mkAnyBackend $
SMOLogicalModel @b logicalModelName
SMOCustomReturnType @b customReturnTypeName
objectName <> " in " <> moiName sourceObjectId
SMOTableObj tableName tableObjectId ->

View File

@ -87,9 +87,9 @@ module Hasura.RQL.Types.SchemaCache
DependencyReason (..),
SchemaDependency (..),
mkParentDep,
mkLogicalModelParentDep,
mkCustomReturnTypeParentDep,
mkColDep,
mkLogicalModelColDep,
mkCustomReturnTypeColDep,
mkComputedFieldDep,
getDependentObjs,
getDependentObjsWith,
@ -103,7 +103,7 @@ module Hasura.RQL.Types.SchemaCache
showMetadataResourceVersion,
initialResourceVersion,
MetadataWithResourceVersion (..),
getLogicalModelBoolExpDeps,
getCustomReturnTypeBoolExpDeps,
getBoolExpDeps,
InlinedAllowlist,
BoolExpM (..),
@ -127,9 +127,9 @@ import Database.MSSQL.Transaction qualified as MSSQL
import Database.PG.Query qualified as PG
import Hasura.Backends.Postgres.Connection qualified as Postgres
import Hasura.Base.Error
import Hasura.CustomReturnType.Types (CustomReturnTypeName)
import Hasura.Function.Cache
import Hasura.GraphQL.Context (GQLContext, RoleContext)
import Hasura.LogicalModel.Types (LogicalModelName)
import Hasura.Prelude
import Hasura.RQL.DDL.Webhook.Transform
import Hasura.RQL.IR.BoolExp
@ -196,18 +196,18 @@ mkParentDep s tn =
-- | When we depend on anything to do with logical models, we also declare that
-- we depend on the logical model as a whole. This is the "parent" dependency
-- in the dependency tree for a given logical model.
mkLogicalModelParentDep ::
mkCustomReturnTypeParentDep ::
forall b.
Backend b =>
SourceName ->
LogicalModelName ->
CustomReturnTypeName ->
SchemaDependency
mkLogicalModelParentDep source logicalModelName = do
mkCustomReturnTypeParentDep source logicalModelName = do
let sourceObject :: SchemaObjId
sourceObject =
SOSourceObj source $
AB.mkAnyBackend @b $
SOILogicalModel logicalModelName
SOICustomReturnType logicalModelName
SchemaDependency sourceObject DRTable
@ -226,23 +226,22 @@ mkColDep reason source tn col =
. SOITableObj @b tn
$ TOCol @b col
-- | Declare a dependency on a particular column of a logical model's return
-- type.
mkLogicalModelColDep ::
-- | Declare a dependency on a particular column of a custom return type
mkCustomReturnTypeColDep ::
forall b.
(Backend b) =>
DependencyReason ->
SourceName ->
LogicalModelName ->
CustomReturnTypeName ->
Column b ->
SchemaDependency
mkLogicalModelColDep reason source logicalModelName column = do
mkCustomReturnTypeColDep reason source logicalModelName column = do
let sourceObject :: SchemaObjId
sourceObject =
SOSourceObj source $
AB.mkAnyBackend $
SOILogicalModelObj @b logicalModelName $
LMOCol @b column
SOICustomReturnTypeObj @b logicalModelName $
CRTOCol @b column
SchemaDependency sourceObject reason
@ -746,18 +745,18 @@ getRemoteDependencies schemaCache sourceName =
-- can't relate tables and logical models yet, we can still declare permissions
-- like, "you can only see this logical model if your user ID exists in this
-- table".
getLogicalModelBoolExpDeps ::
getCustomReturnTypeBoolExpDeps ::
forall b.
(GetAggregationPredicatesDeps b) =>
SourceName ->
LogicalModelName ->
CustomReturnTypeName ->
AnnBoolExpPartialSQL b ->
[SchemaDependency]
getLogicalModelBoolExpDeps source logicalModelName = \case
BoolAnd exps -> concatMap (getLogicalModelBoolExpDeps source logicalModelName) exps
BoolOr exps -> concatMap (getLogicalModelBoolExpDeps source logicalModelName) exps
BoolNot e -> getLogicalModelBoolExpDeps source logicalModelName e
BoolField fld -> getLogicalModelColExpDeps source logicalModelName fld
getCustomReturnTypeBoolExpDeps source logicalModelName = \case
BoolAnd exps -> concatMap (getCustomReturnTypeBoolExpDeps source logicalModelName) exps
BoolOr exps -> concatMap (getCustomReturnTypeBoolExpDeps source logicalModelName) exps
BoolNot e -> getCustomReturnTypeBoolExpDeps source logicalModelName e
BoolField fld -> getCustomReturnTypeColExpDeps source logicalModelName fld
BoolExists (GExists refqt whereExp) -> do
let table :: SchemaObjId
table = SOSourceObj source $ AB.mkAnyBackend $ SOITable @b refqt
@ -769,14 +768,14 @@ getLogicalModelBoolExpDeps source logicalModelName = \case
-- as there's only one type of column: columns! As a result, we have no
-- dependencies from relationships, computed fields, or aggregation predicates,
-- as none of these things are supported.
getLogicalModelColExpDeps ::
getCustomReturnTypeColExpDeps ::
forall b.
(GetAggregationPredicatesDeps b) =>
SourceName ->
LogicalModelName ->
CustomReturnTypeName ->
AnnBoolExpFld b (PartialSQLExp b) ->
[SchemaDependency]
getLogicalModelColExpDeps source logicalModelName = \case
getCustomReturnTypeColExpDeps source logicalModelName = \case
AVRelationship _ _ -> []
AVComputedField _ -> []
AVAggregationPredicates _ -> []
@ -790,9 +789,9 @@ getLogicalModelColExpDeps source logicalModelName = \case
colDepReason = bool DRSessionVariable DROnType (any hasStaticExp opExps)
colDep :: SchemaDependency
colDep = mkLogicalModelColDep @b colDepReason source logicalModelName columnName
colDep = mkCustomReturnTypeColDep @b colDepReason source logicalModelName columnName
colDep : getLogicalModelOpExpDeps source logicalModelName opExps
colDep : getCustomReturnTypeOpExpDeps source logicalModelName opExps
-- | Discover the schema dependencies of an @AnnBoolExpPartialSQL@.
getBoolExpDeps ::
@ -883,17 +882,17 @@ getOpExpDeps opExps = do
-- | What dependencies does this row permission for a logical model have? This
-- is really a utility function for the tree of dependency traversals under
-- 'getLogicalModelBoolExpDeps', specifically focusing on boolean operators.
getLogicalModelOpExpDeps ::
-- 'getCustomReturnTypeBoolExpDeps', specifically focusing on boolean operators.
getCustomReturnTypeOpExpDeps ::
forall b.
(Backend b) =>
SourceName ->
LogicalModelName ->
CustomReturnTypeName ->
[OpExpG b (PartialSQLExp b)] ->
[SchemaDependency]
getLogicalModelOpExpDeps source logicalModelName operatorExpressions = do
getCustomReturnTypeOpExpDeps source logicalModelName operatorExpressions = do
RootOrCurrentColumn _ column <- mapMaybe opExpDepCol operatorExpressions
pure (mkLogicalModelColDep @b DROnType source logicalModelName column)
pure (mkCustomReturnTypeColDep @b DROnType source logicalModelName column)
-- | Asking for a table's fields info without explicit @'SourceName' argument.
-- The source name is implicitly inferred from @'SourceM' via @'TableCoreInfoRM'.

View File

@ -10,7 +10,7 @@ module Hasura.RQL.Types.SchemaCacheTypes
SchemaObjId (..),
SourceObjId (..),
TableObjId (..),
LogicalModelObjId (..),
CustomReturnTypeObjId (..),
purgeDependentObject,
purgeSourceAndSchemaDependencies,
reasonToTxt,
@ -29,6 +29,7 @@ import Data.Text qualified as T
import Data.Text.Extended
import Data.Text.NonEmpty
import Hasura.Base.Error
import Hasura.CustomReturnType.Types (CustomReturnTypeName)
import Hasura.LogicalModel.Types (LogicalModelName)
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp (PartialSQLExp)
@ -59,24 +60,25 @@ deriving instance Backend b => Eq (TableObjId b)
instance (Backend b) => Hashable (TableObjId b)
-- | Identifiers for components of logical models within the metadata. These
-- | Identifiers for components of custom return types within the metadata. These
-- are used to track dependencies within the resolved schema (see
-- 'SourceInfo').
data LogicalModelObjId (b :: BackendType)
= LMOPerm RoleName PermType
| LMOCol (Column b)
data CustomReturnTypeObjId (b :: BackendType)
= CRTOPerm RoleName PermType
| CRTOCol (Column b)
deriving (Generic)
deriving stock instance (Backend b) => Eq (LogicalModelObjId b)
deriving stock instance (Backend b) => Eq (CustomReturnTypeObjId b)
instance (Backend b) => Hashable (LogicalModelObjId b)
instance (Backend b) => Hashable (CustomReturnTypeObjId b)
data SourceObjId (b :: BackendType)
= SOITable (TableName b)
| SOITableObj (TableName b) (TableObjId b)
| SOIFunction (FunctionName b)
| SOILogicalModel LogicalModelName
| SOILogicalModelObj LogicalModelName (LogicalModelObjId b)
| SOICustomReturnType CustomReturnTypeName
| SOICustomReturnTypeObj CustomReturnTypeName (CustomReturnTypeObjId b)
deriving (Eq, Generic)
instance (Backend b) => Hashable (SourceObjId b)
@ -106,10 +108,11 @@ reportSchemaObj = \case
SOITable tn -> "table " <> toTxt tn
SOIFunction fn -> "function " <> toTxt fn
SOILogicalModel lmn -> "logical model " <> toTxt lmn
SOILogicalModelObj lmn (LMOCol cn) ->
"logical model column " <> toTxt lmn <> "." <> toTxt cn
SOILogicalModelObj lmn (LMOPerm rn pt) ->
"permission " <> toTxt lmn <> "." <> roleNameToTxt rn <> "." <> permTypeToCode pt
SOICustomReturnType crt -> "custom return type " <> toTxt crt
SOICustomReturnTypeObj crt (CRTOCol cn) ->
"custom return type column " <> toTxt crt <> "." <> toTxt cn
SOICustomReturnTypeObj crt (CRTOPerm rn pt) ->
"permission " <> toTxt crt <> "." <> roleNameToTxt rn <> "." <> permTypeToCode pt
SOITableObj tn (TOCol cn) ->
"column " <> toTxt tn <> "." <> toTxt cn
SOITableObj tn (TORel cn) ->

View File

@ -172,9 +172,7 @@ logicalModelsCommands :: forall (b :: BackendType). Backend b => [CommandParser
logicalModelsCommands =
[ commandParser "get_logical_model" $ RMGetLogicalModel . mkAnyBackend @b,
commandParser "track_logical_model" $ RMTrackLogicalModel . mkAnyBackend @b,
commandParser "untrack_logical_model" $ RMUntrackLogicalModel . mkAnyBackend @b,
commandParser "create_logical_model_select_permission" $ RMCreateSelectLogicalModelPermission . mkAnyBackend @b,
commandParser "drop_logical_model_select_permission" $ RMDropSelectLogicalModelPermission . mkAnyBackend @b
commandParser "untrack_logical_model" $ RMUntrackLogicalModel . mkAnyBackend @b
]
customReturnTypesCommands :: forall (b :: BackendType). Backend b => [CommandParser b]

View File

@ -138,8 +138,6 @@ data RQLMetadataV1
RMGetLogicalModel !(AnyBackend LogicalModels.GetLogicalModel)
| RMTrackLogicalModel !(AnyBackend LogicalModels.TrackLogicalModel)
| RMUntrackLogicalModel !(AnyBackend LogicalModels.UntrackLogicalModel)
| RMCreateSelectLogicalModelPermission !(AnyBackend (LogicalModels.CreateLogicalModelPermission SelPerm))
| RMDropSelectLogicalModelPermission !(AnyBackend LogicalModels.DropLogicalModelPermission)
| -- Custom types
RMGetCustomReturnType !(AnyBackend CustomReturnType.GetCustomReturnType)
| RMTrackCustomReturnType !(AnyBackend CustomReturnType.TrackCustomReturnType)
@ -504,8 +502,6 @@ queryModifiesMetadata = \case
RMGetLogicalModel _ -> False
RMTrackLogicalModel _ -> True
RMUntrackLogicalModel _ -> True
RMCreateSelectLogicalModelPermission _ -> True
RMDropSelectLogicalModelPermission _ -> True
RMGetCustomReturnType _ -> False
RMTrackCustomReturnType _ -> True
RMUntrackCustomReturnType _ -> True
@ -698,8 +694,6 @@ runMetadataQueryV1M env currentResourceVersion = \case
RMGetLogicalModel q -> dispatchMetadata LogicalModels.runGetLogicalModel q
RMTrackLogicalModel q -> dispatchMetadata (LogicalModels.runTrackLogicalModel env) q
RMUntrackLogicalModel q -> dispatchMetadata LogicalModels.runUntrackLogicalModel q
RMCreateSelectLogicalModelPermission q -> dispatchMetadata LogicalModels.runCreateSelectLogicalModelPermission q
RMDropSelectLogicalModelPermission q -> dispatchMetadata LogicalModels.runDropSelectLogicalModelPermission q
RMGetCustomReturnType q -> dispatchMetadata CustomReturnType.runGetCustomReturnType q
RMTrackCustomReturnType q -> dispatchMetadata CustomReturnType.runTrackCustomReturnType q
RMUntrackCustomReturnType q -> dispatchMetadata CustomReturnType.runUntrackCustomReturnType q

View File

@ -93,8 +93,6 @@ data RQLMetadataV1
RMGetLogicalModel !(AnyBackend LogicalModels.GetLogicalModel)
| RMTrackLogicalModel !(AnyBackend LogicalModels.TrackLogicalModel)
| RMUntrackLogicalModel !(AnyBackend LogicalModels.UntrackLogicalModel)
| RMCreateSelectLogicalModelPermission !(AnyBackend (LogicalModels.CreateLogicalModelPermission SelPerm))
| RMDropSelectLogicalModelPermission !(AnyBackend LogicalModels.DropLogicalModelPermission)
| -- Custom types
RMGetCustomReturnType !(AnyBackend CustomReturnType.GetCustomReturnType)
| RMTrackCustomReturnType !(AnyBackend CustomReturnType.TrackCustomReturnType)

View File

@ -81,7 +81,6 @@ spec = do
_lmmCode = InterpolatedQuery mempty,
_lmmReturns = CustomReturnTypeName (G.unsafeMkName "custom_return_type_name"),
_lmmArguments = mempty,
_lmmSelectPermissions = mempty,
_lmmDescription = mempty
}