mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-14 17:02:49 +03:00
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:
parent
71a00338ff
commit
9c99bcb6f8
@ -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
|
||||
|
@ -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
|
||||
|
@ -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: "*"
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
|
@ -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 ..]
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 =
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 ()
|
||||
|
@ -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)
|
||||
|
@ -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 ->
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
]
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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 ->
|
||||
|
@ -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'.
|
||||
|
@ -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) ->
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -81,7 +81,6 @@ spec = do
|
||||
_lmmCode = InterpolatedQuery mempty,
|
||||
_lmmReturns = CustomReturnTypeName (G.unsafeMkName "custom_return_type_name"),
|
||||
_lmmArguments = mempty,
|
||||
_lmmSelectPermissions = mempty,
|
||||
_lmmDescription = mempty
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user