-- |
-- Definitions for schema building configuration.
module Hasura.GraphQL.Schema.Options
  ( SchemaOptions (..),
    StringifyNumbers (..),
    DangerouslyCollapseBooleans (..),
    InferFunctionPermissions (..),
    RemoteSchemaPermissions (..),
    OptimizePermissionFilters (..),
  )
where

import Data.Aeson (FromJSON (..), ToJSON (..), Value (..), withBool)
import Hasura.Prelude

-- | The record of options required to build the schema. This includes options
-- that can be enabled with 'Hasura.Server.Types.ExperimentalFeature' flags.
data SchemaOptions = SchemaOptions
  { SchemaOptions -> StringifyNumbers
soStringifyNumbers :: StringifyNumbers,
    SchemaOptions -> DangerouslyCollapseBooleans
soDangerousBooleanCollapse :: DangerouslyCollapseBooleans,
    SchemaOptions -> InferFunctionPermissions
soInferFunctionPermissions :: InferFunctionPermissions,
    SchemaOptions -> OptimizePermissionFilters
soOptimizePermissionFilters :: OptimizePermissionFilters
  }

-- | Should we represent numbers in our responses as numbers, or strings?
-- Some backends can return numbers that exceed the bounds of JSON's own
-- number type. In these cases, we can use stringified versions of these
-- numbers to avoid this problem.
data StringifyNumbers
  = StringifyNumbers
  | Don'tStringifyNumbers
  deriving (StringifyNumbers -> StringifyNumbers -> Bool
(StringifyNumbers -> StringifyNumbers -> Bool)
-> (StringifyNumbers -> StringifyNumbers -> Bool)
-> Eq StringifyNumbers
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: StringifyNumbers -> StringifyNumbers -> Bool
$c/= :: StringifyNumbers -> StringifyNumbers -> Bool
== :: StringifyNumbers -> StringifyNumbers -> Bool
$c== :: StringifyNumbers -> StringifyNumbers -> Bool
Eq, Int -> StringifyNumbers -> ShowS
[StringifyNumbers] -> ShowS
StringifyNumbers -> String
(Int -> StringifyNumbers -> ShowS)
-> (StringifyNumbers -> String)
-> ([StringifyNumbers] -> ShowS)
-> Show StringifyNumbers
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [StringifyNumbers] -> ShowS
$cshowList :: [StringifyNumbers] -> ShowS
show :: StringifyNumbers -> String
$cshow :: StringifyNumbers -> String
showsPrec :: Int -> StringifyNumbers -> ShowS
$cshowsPrec :: Int -> StringifyNumbers -> ShowS
Show)

-- | Should Boolean fields be collapsed to 'True' when a null value is
-- given? This was the behaviour of Hasura V1, and is now discouraged.
data DangerouslyCollapseBooleans
  = DangerouslyCollapseBooleans
  | Don'tDangerouslyCollapseBooleans
  deriving (DangerouslyCollapseBooleans -> DangerouslyCollapseBooleans -> Bool
(DangerouslyCollapseBooleans
 -> DangerouslyCollapseBooleans -> Bool)
-> (DangerouslyCollapseBooleans
    -> DangerouslyCollapseBooleans -> Bool)
-> Eq DangerouslyCollapseBooleans
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DangerouslyCollapseBooleans -> DangerouslyCollapseBooleans -> Bool
$c/= :: DangerouslyCollapseBooleans -> DangerouslyCollapseBooleans -> Bool
== :: DangerouslyCollapseBooleans -> DangerouslyCollapseBooleans -> Bool
$c== :: DangerouslyCollapseBooleans -> DangerouslyCollapseBooleans -> Bool
Eq, Int -> DangerouslyCollapseBooleans -> ShowS
[DangerouslyCollapseBooleans] -> ShowS
DangerouslyCollapseBooleans -> String
(Int -> DangerouslyCollapseBooleans -> ShowS)
-> (DangerouslyCollapseBooleans -> String)
-> ([DangerouslyCollapseBooleans] -> ShowS)
-> Show DangerouslyCollapseBooleans
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DangerouslyCollapseBooleans] -> ShowS
$cshowList :: [DangerouslyCollapseBooleans] -> ShowS
show :: DangerouslyCollapseBooleans -> String
$cshow :: DangerouslyCollapseBooleans -> String
showsPrec :: Int -> DangerouslyCollapseBooleans -> ShowS
$cshowsPrec :: Int -> DangerouslyCollapseBooleans -> ShowS
Show)

instance FromJSON DangerouslyCollapseBooleans where
  parseJSON :: Value -> Parser DangerouslyCollapseBooleans
parseJSON =
    String
-> (Bool -> Parser DangerouslyCollapseBooleans)
-> Value
-> Parser DangerouslyCollapseBooleans
forall a. String -> (Bool -> Parser a) -> Value -> Parser a
withBool String
"DangerouslyCollapseBooleans" ((Bool -> Parser DangerouslyCollapseBooleans)
 -> Value -> Parser DangerouslyCollapseBooleans)
-> (Bool -> Parser DangerouslyCollapseBooleans)
-> Value
-> Parser DangerouslyCollapseBooleans
forall a b. (a -> b) -> a -> b
$
      DangerouslyCollapseBooleans -> Parser DangerouslyCollapseBooleans
forall (f :: * -> *) a. Applicative f => a -> f a
pure (DangerouslyCollapseBooleans -> Parser DangerouslyCollapseBooleans)
-> (Bool -> DangerouslyCollapseBooleans)
-> Bool
-> Parser DangerouslyCollapseBooleans
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \case
        Bool
True -> DangerouslyCollapseBooleans
DangerouslyCollapseBooleans
        Bool
False -> DangerouslyCollapseBooleans
Don'tDangerouslyCollapseBooleans

instance ToJSON DangerouslyCollapseBooleans where
  toJSON :: DangerouslyCollapseBooleans -> Value
toJSON = \case
    DangerouslyCollapseBooleans
DangerouslyCollapseBooleans -> Bool -> Value
Bool Bool
True
    DangerouslyCollapseBooleans
Don'tDangerouslyCollapseBooleans -> Bool -> Value
Bool Bool
False

-- | Should we infer function permissions? If this flag is set to
-- 'InferFunctionPermissions', we may fail to build expression parsers
-- in 'buildQueryAndSubscriptionFields' for users with unrecognised roles.
data InferFunctionPermissions
  = InferFunctionPermissions
  | Don'tInferFunctionPermissions
  deriving (InferFunctionPermissions -> InferFunctionPermissions -> Bool
(InferFunctionPermissions -> InferFunctionPermissions -> Bool)
-> (InferFunctionPermissions -> InferFunctionPermissions -> Bool)
-> Eq InferFunctionPermissions
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: InferFunctionPermissions -> InferFunctionPermissions -> Bool
$c/= :: InferFunctionPermissions -> InferFunctionPermissions -> Bool
== :: InferFunctionPermissions -> InferFunctionPermissions -> Bool
$c== :: InferFunctionPermissions -> InferFunctionPermissions -> Bool
Eq, Int -> InferFunctionPermissions -> ShowS
[InferFunctionPermissions] -> ShowS
InferFunctionPermissions -> String
(Int -> InferFunctionPermissions -> ShowS)
-> (InferFunctionPermissions -> String)
-> ([InferFunctionPermissions] -> ShowS)
-> Show InferFunctionPermissions
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [InferFunctionPermissions] -> ShowS
$cshowList :: [InferFunctionPermissions] -> ShowS
show :: InferFunctionPermissions -> String
$cshow :: InferFunctionPermissions -> String
showsPrec :: Int -> InferFunctionPermissions -> ShowS
$cshowsPrec :: Int -> InferFunctionPermissions -> ShowS
Show)

instance FromJSON InferFunctionPermissions where
  parseJSON :: Value -> Parser InferFunctionPermissions
parseJSON =
    String
-> (Bool -> Parser InferFunctionPermissions)
-> Value
-> Parser InferFunctionPermissions
forall a. String -> (Bool -> Parser a) -> Value -> Parser a
withBool String
"InferFunctionPermissions" ((Bool -> Parser InferFunctionPermissions)
 -> Value -> Parser InferFunctionPermissions)
-> (Bool -> Parser InferFunctionPermissions)
-> Value
-> Parser InferFunctionPermissions
forall a b. (a -> b) -> a -> b
$
      InferFunctionPermissions -> Parser InferFunctionPermissions
forall (f :: * -> *) a. Applicative f => a -> f a
pure (InferFunctionPermissions -> Parser InferFunctionPermissions)
-> (Bool -> InferFunctionPermissions)
-> Bool
-> Parser InferFunctionPermissions
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \case
        Bool
True -> InferFunctionPermissions
InferFunctionPermissions
        Bool
False -> InferFunctionPermissions
Don'tInferFunctionPermissions

instance ToJSON InferFunctionPermissions where
  toJSON :: InferFunctionPermissions -> Value
toJSON = \case
    InferFunctionPermissions
InferFunctionPermissions -> Bool -> Value
Bool Bool
True
    InferFunctionPermissions
Don'tInferFunctionPermissions -> Bool -> Value
Bool Bool
False

-- | Should we enable remote schema permissions? If so, these permissions will
-- influence 'Hasura.GraphQL.Schema.buildGQLContext'.
data RemoteSchemaPermissions
  = EnableRemoteSchemaPermissions
  | DisableRemoteSchemaPermissions
  deriving (RemoteSchemaPermissions -> RemoteSchemaPermissions -> Bool
(RemoteSchemaPermissions -> RemoteSchemaPermissions -> Bool)
-> (RemoteSchemaPermissions -> RemoteSchemaPermissions -> Bool)
-> Eq RemoteSchemaPermissions
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RemoteSchemaPermissions -> RemoteSchemaPermissions -> Bool
$c/= :: RemoteSchemaPermissions -> RemoteSchemaPermissions -> Bool
== :: RemoteSchemaPermissions -> RemoteSchemaPermissions -> Bool
$c== :: RemoteSchemaPermissions -> RemoteSchemaPermissions -> Bool
Eq, Int -> RemoteSchemaPermissions -> ShowS
[RemoteSchemaPermissions] -> ShowS
RemoteSchemaPermissions -> String
(Int -> RemoteSchemaPermissions -> ShowS)
-> (RemoteSchemaPermissions -> String)
-> ([RemoteSchemaPermissions] -> ShowS)
-> Show RemoteSchemaPermissions
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [RemoteSchemaPermissions] -> ShowS
$cshowList :: [RemoteSchemaPermissions] -> ShowS
show :: RemoteSchemaPermissions -> String
$cshow :: RemoteSchemaPermissions -> String
showsPrec :: Int -> RemoteSchemaPermissions -> ShowS
$cshowsPrec :: Int -> RemoteSchemaPermissions -> ShowS
Show)

instance FromJSON RemoteSchemaPermissions where
  parseJSON :: Value -> Parser RemoteSchemaPermissions
parseJSON =
    String
-> (Bool -> Parser RemoteSchemaPermissions)
-> Value
-> Parser RemoteSchemaPermissions
forall a. String -> (Bool -> Parser a) -> Value -> Parser a
withBool String
"RemoteSchemaPermissions" ((Bool -> Parser RemoteSchemaPermissions)
 -> Value -> Parser RemoteSchemaPermissions)
-> (Bool -> Parser RemoteSchemaPermissions)
-> Value
-> Parser RemoteSchemaPermissions
forall a b. (a -> b) -> a -> b
$
      RemoteSchemaPermissions -> Parser RemoteSchemaPermissions
forall (f :: * -> *) a. Applicative f => a -> f a
pure (RemoteSchemaPermissions -> Parser RemoteSchemaPermissions)
-> (Bool -> RemoteSchemaPermissions)
-> Bool
-> Parser RemoteSchemaPermissions
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \case
        Bool
True -> RemoteSchemaPermissions
EnableRemoteSchemaPermissions
        Bool
False -> RemoteSchemaPermissions
DisableRemoteSchemaPermissions

instance ToJSON RemoteSchemaPermissions where
  toJSON :: RemoteSchemaPermissions -> Value
toJSON = \case
    RemoteSchemaPermissions
EnableRemoteSchemaPermissions -> Bool -> Value
Bool Bool
True
    RemoteSchemaPermissions
DisableRemoteSchemaPermissions -> Bool -> Value
Bool Bool
False

-- | Should we attempt to deduplicate permission filters? This flag is used in
-- 'Hasura.GraphQL.Schema.Select.relationshipField' to determine whether
-- certain row-level permission filters can be dropped in certain cases.
data OptimizePermissionFilters
  = OptimizePermissionFilters
  | Don'tOptimizePermissionFilters
  deriving (OptimizePermissionFilters -> OptimizePermissionFilters -> Bool
(OptimizePermissionFilters -> OptimizePermissionFilters -> Bool)
-> (OptimizePermissionFilters -> OptimizePermissionFilters -> Bool)
-> Eq OptimizePermissionFilters
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: OptimizePermissionFilters -> OptimizePermissionFilters -> Bool
$c/= :: OptimizePermissionFilters -> OptimizePermissionFilters -> Bool
== :: OptimizePermissionFilters -> OptimizePermissionFilters -> Bool
$c== :: OptimizePermissionFilters -> OptimizePermissionFilters -> Bool
Eq, Int -> OptimizePermissionFilters -> ShowS
[OptimizePermissionFilters] -> ShowS
OptimizePermissionFilters -> String
(Int -> OptimizePermissionFilters -> ShowS)
-> (OptimizePermissionFilters -> String)
-> ([OptimizePermissionFilters] -> ShowS)
-> Show OptimizePermissionFilters
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [OptimizePermissionFilters] -> ShowS
$cshowList :: [OptimizePermissionFilters] -> ShowS
show :: OptimizePermissionFilters -> String
$cshow :: OptimizePermissionFilters -> String
showsPrec :: Int -> OptimizePermissionFilters -> ShowS
$cshowsPrec :: Int -> OptimizePermissionFilters -> ShowS
Show)