module Hasura.Session
  ( RoleName,
    mkRoleName,
    mkRoleNameSafe,
    adminRoleName,
    roleNameToTxt,
    SessionVariable,
    mkSessionVariable,
    SessionVariables,
    filterSessionVariables,
    SessionVariableValue,
    sessionVariableToText,
    sessionVariableToGraphQLName,
    mkSessionVariablesText,
    mkSessionVariablesHeaders,
    sessionVariablesToHeaders,
    getSessionVariableValue,
    getSessionVariablesSet,
    getSessionVariables,
    UserAdminSecret (..),
    UserRoleBuild (..),
    UserInfo (..),
    UserInfoM (..),
    askCurRole,
    mkUserInfo,
    adminUserInfo,
    BackendOnlyFieldAccess (..),
  )
where

import Data.Aeson
import Data.Aeson.Types (Parser, toJSONKeyText)
import Data.CaseInsensitive qualified as CI
import Data.HashMap.Strict qualified as Map
import Data.HashSet qualified as Set
import Data.Text qualified as T
import Data.Text.Extended
import Data.Text.NonEmpty
import Database.PG.Query qualified as Q
import Hasura.Base.Error
import Hasura.Incremental (Cacheable)
import Hasura.Prelude
import Hasura.Server.Utils
import Hasura.Tracing (TraceT)
import Language.GraphQL.Draft.Syntax qualified as G
import Network.HTTP.Types qualified as HTTP

newtype RoleName = RoleName {RoleName -> NonEmptyText
getRoleTxt :: NonEmptyText}
  deriving
    ( Int -> RoleName -> ShowS
[RoleName] -> ShowS
RoleName -> String
(Int -> RoleName -> ShowS)
-> (RoleName -> String) -> ([RoleName] -> ShowS) -> Show RoleName
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [RoleName] -> ShowS
$cshowList :: [RoleName] -> ShowS
show :: RoleName -> String
$cshow :: RoleName -> String
showsPrec :: Int -> RoleName -> ShowS
$cshowsPrec :: Int -> RoleName -> ShowS
Show,
      RoleName -> RoleName -> Bool
(RoleName -> RoleName -> Bool)
-> (RoleName -> RoleName -> Bool) -> Eq RoleName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RoleName -> RoleName -> Bool
$c/= :: RoleName -> RoleName -> Bool
== :: RoleName -> RoleName -> Bool
$c== :: RoleName -> RoleName -> Bool
Eq,
      Eq RoleName
Eq RoleName
-> (RoleName -> RoleName -> Ordering)
-> (RoleName -> RoleName -> Bool)
-> (RoleName -> RoleName -> Bool)
-> (RoleName -> RoleName -> Bool)
-> (RoleName -> RoleName -> Bool)
-> (RoleName -> RoleName -> RoleName)
-> (RoleName -> RoleName -> RoleName)
-> Ord RoleName
RoleName -> RoleName -> Bool
RoleName -> RoleName -> Ordering
RoleName -> RoleName -> RoleName
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: RoleName -> RoleName -> RoleName
$cmin :: RoleName -> RoleName -> RoleName
max :: RoleName -> RoleName -> RoleName
$cmax :: RoleName -> RoleName -> RoleName
>= :: RoleName -> RoleName -> Bool
$c>= :: RoleName -> RoleName -> Bool
> :: RoleName -> RoleName -> Bool
$c> :: RoleName -> RoleName -> Bool
<= :: RoleName -> RoleName -> Bool
$c<= :: RoleName -> RoleName -> Bool
< :: RoleName -> RoleName -> Bool
$c< :: RoleName -> RoleName -> Bool
compare :: RoleName -> RoleName -> Ordering
$ccompare :: RoleName -> RoleName -> Ordering
$cp1Ord :: Eq RoleName
Ord,
      Int -> RoleName -> Int
RoleName -> Int
(Int -> RoleName -> Int) -> (RoleName -> Int) -> Hashable RoleName
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: RoleName -> Int
$chash :: RoleName -> Int
hashWithSalt :: Int -> RoleName -> Int
$chashWithSalt :: Int -> RoleName -> Int
Hashable,
      FromJSONKeyFunction [RoleName]
FromJSONKeyFunction RoleName
FromJSONKeyFunction RoleName
-> FromJSONKeyFunction [RoleName] -> FromJSONKey RoleName
forall a.
FromJSONKeyFunction a -> FromJSONKeyFunction [a] -> FromJSONKey a
fromJSONKeyList :: FromJSONKeyFunction [RoleName]
$cfromJSONKeyList :: FromJSONKeyFunction [RoleName]
fromJSONKey :: FromJSONKeyFunction RoleName
$cfromJSONKey :: FromJSONKeyFunction RoleName
FromJSONKey,
      ToJSONKeyFunction [RoleName]
ToJSONKeyFunction RoleName
ToJSONKeyFunction RoleName
-> ToJSONKeyFunction [RoleName] -> ToJSONKey RoleName
forall a.
ToJSONKeyFunction a -> ToJSONKeyFunction [a] -> ToJSONKey a
toJSONKeyList :: ToJSONKeyFunction [RoleName]
$ctoJSONKeyList :: ToJSONKeyFunction [RoleName]
toJSONKey :: ToJSONKeyFunction RoleName
$ctoJSONKey :: ToJSONKeyFunction RoleName
ToJSONKey,
      Value -> Parser [RoleName]
Value -> Parser RoleName
(Value -> Parser RoleName)
-> (Value -> Parser [RoleName]) -> FromJSON RoleName
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [RoleName]
$cparseJSONList :: Value -> Parser [RoleName]
parseJSON :: Value -> Parser RoleName
$cparseJSON :: Value -> Parser RoleName
FromJSON,
      [RoleName] -> Value
[RoleName] -> Encoding
RoleName -> Value
RoleName -> Encoding
(RoleName -> Value)
-> (RoleName -> Encoding)
-> ([RoleName] -> Value)
-> ([RoleName] -> Encoding)
-> ToJSON RoleName
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [RoleName] -> Encoding
$ctoEncodingList :: [RoleName] -> Encoding
toJSONList :: [RoleName] -> Value
$ctoJSONList :: [RoleName] -> Value
toEncoding :: RoleName -> Encoding
$ctoEncoding :: RoleName -> Encoding
toJSON :: RoleName -> Value
$ctoJSON :: RoleName -> Value
ToJSON,
      Maybe ByteString -> Either Text RoleName
(Maybe ByteString -> Either Text RoleName) -> FromCol RoleName
forall a. (Maybe ByteString -> Either Text a) -> FromCol a
fromCol :: Maybe ByteString -> Either Text RoleName
$cfromCol :: Maybe ByteString -> Either Text RoleName
Q.FromCol,
      RoleName -> PrepArg
(RoleName -> PrepArg) -> ToPrepArg RoleName
forall a. (a -> PrepArg) -> ToPrepArg a
toPrepVal :: RoleName -> PrepArg
$ctoPrepVal :: RoleName -> PrepArg
Q.ToPrepArg,
      (forall x. RoleName -> Rep RoleName x)
-> (forall x. Rep RoleName x -> RoleName) -> Generic RoleName
forall x. Rep RoleName x -> RoleName
forall x. RoleName -> Rep RoleName x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep RoleName x -> RoleName
$cfrom :: forall x. RoleName -> Rep RoleName x
Generic,
      RoleName -> ()
(RoleName -> ()) -> NFData RoleName
forall a. (a -> ()) -> NFData a
rnf :: RoleName -> ()
$crnf :: RoleName -> ()
NFData,
      Eq RoleName
Eq RoleName
-> (Accesses -> RoleName -> RoleName -> Bool) -> Cacheable RoleName
Accesses -> RoleName -> RoleName -> Bool
forall a. Eq a -> (Accesses -> a -> a -> Bool) -> Cacheable a
unchanged :: Accesses -> RoleName -> RoleName -> Bool
$cunchanged :: Accesses -> RoleName -> RoleName -> Bool
$cp1Cacheable :: Eq RoleName
Cacheable
    )

roleNameToTxt :: RoleName -> Text
roleNameToTxt :: RoleName -> Text
roleNameToTxt = NonEmptyText -> Text
unNonEmptyText (NonEmptyText -> Text)
-> (RoleName -> NonEmptyText) -> RoleName -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RoleName -> NonEmptyText
getRoleTxt

instance ToTxt RoleName where
  toTxt :: RoleName -> Text
toTxt = RoleName -> Text
roleNameToTxt

mkRoleName :: Text -> Maybe RoleName
mkRoleName :: Text -> Maybe RoleName
mkRoleName = (NonEmptyText -> RoleName) -> Maybe NonEmptyText -> Maybe RoleName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap NonEmptyText -> RoleName
RoleName (Maybe NonEmptyText -> Maybe RoleName)
-> (Text -> Maybe NonEmptyText) -> Text -> Maybe RoleName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Maybe NonEmptyText
mkNonEmptyText

mkRoleNameSafe :: NonEmptyText -> RoleName
mkRoleNameSafe :: NonEmptyText -> RoleName
mkRoleNameSafe = NonEmptyText -> RoleName
RoleName

adminRoleName :: RoleName
adminRoleName :: RoleName
adminRoleName = NonEmptyText -> RoleName
RoleName (NonEmptyText -> RoleName) -> NonEmptyText -> RoleName
forall a b. (a -> b) -> a -> b
$ Text -> NonEmptyText
mkNonEmptyTextUnsafe Text
"admin"

newtype SessionVariable = SessionVariable {SessionVariable -> CI Text
unSessionVariable :: CI.CI Text}
  deriving (Int -> SessionVariable -> ShowS
[SessionVariable] -> ShowS
SessionVariable -> String
(Int -> SessionVariable -> ShowS)
-> (SessionVariable -> String)
-> ([SessionVariable] -> ShowS)
-> Show SessionVariable
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SessionVariable] -> ShowS
$cshowList :: [SessionVariable] -> ShowS
show :: SessionVariable -> String
$cshow :: SessionVariable -> String
showsPrec :: Int -> SessionVariable -> ShowS
$cshowsPrec :: Int -> SessionVariable -> ShowS
Show, SessionVariable -> SessionVariable -> Bool
(SessionVariable -> SessionVariable -> Bool)
-> (SessionVariable -> SessionVariable -> Bool)
-> Eq SessionVariable
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SessionVariable -> SessionVariable -> Bool
$c/= :: SessionVariable -> SessionVariable -> Bool
== :: SessionVariable -> SessionVariable -> Bool
$c== :: SessionVariable -> SessionVariable -> Bool
Eq, Int -> SessionVariable -> Int
SessionVariable -> Int
(Int -> SessionVariable -> Int)
-> (SessionVariable -> Int) -> Hashable SessionVariable
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: SessionVariable -> Int
$chash :: SessionVariable -> Int
hashWithSalt :: Int -> SessionVariable -> Int
$chashWithSalt :: Int -> SessionVariable -> Int
Hashable, String -> SessionVariable
(String -> SessionVariable) -> IsString SessionVariable
forall a. (String -> a) -> IsString a
fromString :: String -> SessionVariable
$cfromString :: String -> SessionVariable
IsString, Eq SessionVariable
Eq SessionVariable
-> (Accesses -> SessionVariable -> SessionVariable -> Bool)
-> Cacheable SessionVariable
Accesses -> SessionVariable -> SessionVariable -> Bool
forall a. Eq a -> (Accesses -> a -> a -> Bool) -> Cacheable a
unchanged :: Accesses -> SessionVariable -> SessionVariable -> Bool
$cunchanged :: Accesses -> SessionVariable -> SessionVariable -> Bool
$cp1Cacheable :: Eq SessionVariable
Cacheable, Typeable SessionVariable
DataType
Constr
Typeable SessionVariable
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> SessionVariable -> c SessionVariable)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c SessionVariable)
-> (SessionVariable -> Constr)
-> (SessionVariable -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c SessionVariable))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c SessionVariable))
-> ((forall b. Data b => b -> b)
    -> SessionVariable -> SessionVariable)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> SessionVariable -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> SessionVariable -> r)
-> (forall u.
    (forall d. Data d => d -> u) -> SessionVariable -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> SessionVariable -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d)
    -> SessionVariable -> m SessionVariable)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> SessionVariable -> m SessionVariable)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> SessionVariable -> m SessionVariable)
-> Data SessionVariable
SessionVariable -> DataType
SessionVariable -> Constr
(forall b. Data b => b -> b) -> SessionVariable -> SessionVariable
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SessionVariable -> c SessionVariable
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c SessionVariable
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u.
Int -> (forall d. Data d => d -> u) -> SessionVariable -> u
forall u. (forall d. Data d => d -> u) -> SessionVariable -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> SessionVariable -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> SessionVariable -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> SessionVariable -> m SessionVariable
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> SessionVariable -> m SessionVariable
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c SessionVariable
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SessionVariable -> c SessionVariable
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c SessionVariable)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c SessionVariable)
$cSessionVariable :: Constr
$tSessionVariable :: DataType
gmapMo :: (forall d. Data d => d -> m d)
-> SessionVariable -> m SessionVariable
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> SessionVariable -> m SessionVariable
gmapMp :: (forall d. Data d => d -> m d)
-> SessionVariable -> m SessionVariable
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> SessionVariable -> m SessionVariable
gmapM :: (forall d. Data d => d -> m d)
-> SessionVariable -> m SessionVariable
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> SessionVariable -> m SessionVariable
gmapQi :: Int -> (forall d. Data d => d -> u) -> SessionVariable -> u
$cgmapQi :: forall u.
Int -> (forall d. Data d => d -> u) -> SessionVariable -> u
gmapQ :: (forall d. Data d => d -> u) -> SessionVariable -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> SessionVariable -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> SessionVariable -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> SessionVariable -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> SessionVariable -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> SessionVariable -> r
gmapT :: (forall b. Data b => b -> b) -> SessionVariable -> SessionVariable
$cgmapT :: (forall b. Data b => b -> b) -> SessionVariable -> SessionVariable
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c SessionVariable)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c SessionVariable)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c SessionVariable)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c SessionVariable)
dataTypeOf :: SessionVariable -> DataType
$cdataTypeOf :: SessionVariable -> DataType
toConstr :: SessionVariable -> Constr
$ctoConstr :: SessionVariable -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c SessionVariable
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c SessionVariable
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SessionVariable -> c SessionVariable
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SessionVariable -> c SessionVariable
$cp1Data :: Typeable SessionVariable
Data, SessionVariable -> ()
(SessionVariable -> ()) -> NFData SessionVariable
forall a. (a -> ()) -> NFData a
rnf :: SessionVariable -> ()
$crnf :: SessionVariable -> ()
NFData, Eq SessionVariable
Eq SessionVariable
-> (SessionVariable -> SessionVariable -> Ordering)
-> (SessionVariable -> SessionVariable -> Bool)
-> (SessionVariable -> SessionVariable -> Bool)
-> (SessionVariable -> SessionVariable -> Bool)
-> (SessionVariable -> SessionVariable -> Bool)
-> (SessionVariable -> SessionVariable -> SessionVariable)
-> (SessionVariable -> SessionVariable -> SessionVariable)
-> Ord SessionVariable
SessionVariable -> SessionVariable -> Bool
SessionVariable -> SessionVariable -> Ordering
SessionVariable -> SessionVariable -> SessionVariable
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: SessionVariable -> SessionVariable -> SessionVariable
$cmin :: SessionVariable -> SessionVariable -> SessionVariable
max :: SessionVariable -> SessionVariable -> SessionVariable
$cmax :: SessionVariable -> SessionVariable -> SessionVariable
>= :: SessionVariable -> SessionVariable -> Bool
$c>= :: SessionVariable -> SessionVariable -> Bool
> :: SessionVariable -> SessionVariable -> Bool
$c> :: SessionVariable -> SessionVariable -> Bool
<= :: SessionVariable -> SessionVariable -> Bool
$c<= :: SessionVariable -> SessionVariable -> Bool
< :: SessionVariable -> SessionVariable -> Bool
$c< :: SessionVariable -> SessionVariable -> Bool
compare :: SessionVariable -> SessionVariable -> Ordering
$ccompare :: SessionVariable -> SessionVariable -> Ordering
$cp1Ord :: Eq SessionVariable
Ord)

instance ToJSON SessionVariable where
  toJSON :: SessionVariable -> Value
toJSON = Text -> Value
forall a. ToJSON a => a -> Value
toJSON (Text -> Value)
-> (SessionVariable -> Text) -> SessionVariable -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CI Text -> Text
forall s. CI s -> s
CI.original (CI Text -> Text)
-> (SessionVariable -> CI Text) -> SessionVariable -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SessionVariable -> CI Text
unSessionVariable

instance ToJSONKey SessionVariable where
  toJSONKey :: ToJSONKeyFunction SessionVariable
toJSONKey = (SessionVariable -> Text) -> ToJSONKeyFunction SessionVariable
forall a. (a -> Text) -> ToJSONKeyFunction a
toJSONKeyText SessionVariable -> Text
sessionVariableToText

instance ToTxt SessionVariable where
  toTxt :: SessionVariable -> Text
toTxt = SessionVariable -> Text
sessionVariableToText

-- | Converts a `SessionVariable` value to a GraphQL name.
-- This will fail if the session variable contains characters that are not valid
-- for a graphql names. It is the caller's responsibility to decide what to do
-- in such a case.
sessionVariableToGraphQLName :: SessionVariable -> Maybe G.Name
sessionVariableToGraphQLName :: SessionVariable -> Maybe Name
sessionVariableToGraphQLName = Text -> Maybe Name
G.mkName (Text -> Maybe Name)
-> (SessionVariable -> Text) -> SessionVariable -> Maybe Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> Text -> Text
T.replace Text
"-" Text
"_" (Text -> Text)
-> (SessionVariable -> Text) -> SessionVariable -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SessionVariable -> Text
sessionVariableToText

parseSessionVariable :: Text -> Parser SessionVariable
parseSessionVariable :: Text -> Parser SessionVariable
parseSessionVariable Text
t =
  if Text -> Bool
isSessionVariable Text
t
    then SessionVariable -> Parser SessionVariable
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SessionVariable -> Parser SessionVariable)
-> SessionVariable -> Parser SessionVariable
forall a b. (a -> b) -> a -> b
$ Text -> SessionVariable
mkSessionVariable Text
t
    else String -> Parser SessionVariable
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser SessionVariable)
-> String -> Parser SessionVariable
forall a b. (a -> b) -> a -> b
$ Text -> String
forall a. Show a => a -> String
show Text
t String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" is not a Hasura session variable"

instance FromJSON SessionVariable where
  parseJSON :: Value -> Parser SessionVariable
parseJSON = String
-> (Text -> Parser SessionVariable)
-> Value
-> Parser SessionVariable
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"String" Text -> Parser SessionVariable
parseSessionVariable

instance FromJSONKey SessionVariable where
  fromJSONKey :: FromJSONKeyFunction SessionVariable
fromJSONKey = (Text -> Parser SessionVariable)
-> FromJSONKeyFunction SessionVariable
forall a. (Text -> Parser a) -> FromJSONKeyFunction a
FromJSONKeyTextParser Text -> Parser SessionVariable
parseSessionVariable

sessionVariableToText :: SessionVariable -> Text
sessionVariableToText :: SessionVariable -> Text
sessionVariableToText = Text -> Text
T.toLower (Text -> Text)
-> (SessionVariable -> Text) -> SessionVariable -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CI Text -> Text
forall s. CI s -> s
CI.original (CI Text -> Text)
-> (SessionVariable -> CI Text) -> SessionVariable -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SessionVariable -> CI Text
unSessionVariable

mkSessionVariable :: Text -> SessionVariable
mkSessionVariable :: Text -> SessionVariable
mkSessionVariable = CI Text -> SessionVariable
SessionVariable (CI Text -> SessionVariable)
-> (Text -> CI Text) -> Text -> SessionVariable
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> CI Text
forall s. FoldCase s => s -> CI s
CI.mk

type SessionVariableValue = Text

newtype SessionVariables = SessionVariables {SessionVariables -> HashMap SessionVariable Text
unSessionVariables :: Map.HashMap SessionVariable SessionVariableValue}
  deriving (Int -> SessionVariables -> ShowS
[SessionVariables] -> ShowS
SessionVariables -> String
(Int -> SessionVariables -> ShowS)
-> (SessionVariables -> String)
-> ([SessionVariables] -> ShowS)
-> Show SessionVariables
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SessionVariables] -> ShowS
$cshowList :: [SessionVariables] -> ShowS
show :: SessionVariables -> String
$cshow :: SessionVariables -> String
showsPrec :: Int -> SessionVariables -> ShowS
$cshowsPrec :: Int -> SessionVariables -> ShowS
Show, SessionVariables -> SessionVariables -> Bool
(SessionVariables -> SessionVariables -> Bool)
-> (SessionVariables -> SessionVariables -> Bool)
-> Eq SessionVariables
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SessionVariables -> SessionVariables -> Bool
$c/= :: SessionVariables -> SessionVariables -> Bool
== :: SessionVariables -> SessionVariables -> Bool
$c== :: SessionVariables -> SessionVariables -> Bool
Eq, Int -> SessionVariables -> Int
SessionVariables -> Int
(Int -> SessionVariables -> Int)
-> (SessionVariables -> Int) -> Hashable SessionVariables
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: SessionVariables -> Int
$chash :: SessionVariables -> Int
hashWithSalt :: Int -> SessionVariables -> Int
$chashWithSalt :: Int -> SessionVariables -> Int
Hashable, b -> SessionVariables -> SessionVariables
NonEmpty SessionVariables -> SessionVariables
SessionVariables -> SessionVariables -> SessionVariables
(SessionVariables -> SessionVariables -> SessionVariables)
-> (NonEmpty SessionVariables -> SessionVariables)
-> (forall b.
    Integral b =>
    b -> SessionVariables -> SessionVariables)
-> Semigroup SessionVariables
forall b. Integral b => b -> SessionVariables -> SessionVariables
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: b -> SessionVariables -> SessionVariables
$cstimes :: forall b. Integral b => b -> SessionVariables -> SessionVariables
sconcat :: NonEmpty SessionVariables -> SessionVariables
$csconcat :: NonEmpty SessionVariables -> SessionVariables
<> :: SessionVariables -> SessionVariables -> SessionVariables
$c<> :: SessionVariables -> SessionVariables -> SessionVariables
Semigroup, Semigroup SessionVariables
SessionVariables
Semigroup SessionVariables
-> SessionVariables
-> (SessionVariables -> SessionVariables -> SessionVariables)
-> ([SessionVariables] -> SessionVariables)
-> Monoid SessionVariables
[SessionVariables] -> SessionVariables
SessionVariables -> SessionVariables -> SessionVariables
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [SessionVariables] -> SessionVariables
$cmconcat :: [SessionVariables] -> SessionVariables
mappend :: SessionVariables -> SessionVariables -> SessionVariables
$cmappend :: SessionVariables -> SessionVariables -> SessionVariables
mempty :: SessionVariables
$cmempty :: SessionVariables
$cp1Monoid :: Semigroup SessionVariables
Monoid)

filterSessionVariables ::
  (SessionVariable -> SessionVariableValue -> Bool) ->
  SessionVariables ->
  SessionVariables
filterSessionVariables :: (SessionVariable -> Text -> Bool)
-> SessionVariables -> SessionVariables
filterSessionVariables SessionVariable -> Text -> Bool
f = HashMap SessionVariable Text -> SessionVariables
SessionVariables (HashMap SessionVariable Text -> SessionVariables)
-> (SessionVariables -> HashMap SessionVariable Text)
-> SessionVariables
-> SessionVariables
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SessionVariable -> Text -> Bool)
-> HashMap SessionVariable Text -> HashMap SessionVariable Text
forall k v. (k -> v -> Bool) -> HashMap k v -> HashMap k v
Map.filterWithKey SessionVariable -> Text -> Bool
f (HashMap SessionVariable Text -> HashMap SessionVariable Text)
-> (SessionVariables -> HashMap SessionVariable Text)
-> SessionVariables
-> HashMap SessionVariable Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SessionVariables -> HashMap SessionVariable Text
unSessionVariables

instance ToJSON SessionVariables where
  toJSON :: SessionVariables -> Value
toJSON (SessionVariables HashMap SessionVariable Text
varMap) =
    HashMap Text Text -> Value
forall a. ToJSON a => a -> Value
toJSON (HashMap Text Text -> Value) -> HashMap Text Text -> Value
forall a b. (a -> b) -> a -> b
$ (SessionVariable -> Text)
-> HashMap SessionVariable Text -> HashMap Text Text
forall k2 k1 v.
(Eq k2, Hashable k2) =>
(k1 -> k2) -> HashMap k1 v -> HashMap k2 v
mapKeys SessionVariable -> Text
sessionVariableToText HashMap SessionVariable Text
varMap

instance FromJSON SessionVariables where
  parseJSON :: Value -> Parser SessionVariables
parseJSON Value
v = HashMap Text Text -> SessionVariables
mkSessionVariablesText (HashMap Text Text -> SessionVariables)
-> Parser (HashMap Text Text) -> Parser SessionVariables
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser (HashMap Text Text)
forall a. FromJSON a => Value -> Parser a
parseJSON Value
v

mkSessionVariablesText :: Map.HashMap Text Text -> SessionVariables
mkSessionVariablesText :: HashMap Text Text -> SessionVariables
mkSessionVariablesText = HashMap SessionVariable Text -> SessionVariables
SessionVariables (HashMap SessionVariable Text -> SessionVariables)
-> (HashMap Text Text -> HashMap SessionVariable Text)
-> HashMap Text Text
-> SessionVariables
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> SessionVariable)
-> HashMap Text Text -> HashMap SessionVariable Text
forall k2 k1 v.
(Eq k2, Hashable k2) =>
(k1 -> k2) -> HashMap k1 v -> HashMap k2 v
mapKeys Text -> SessionVariable
mkSessionVariable

mkSessionVariablesHeaders :: [HTTP.Header] -> SessionVariables
mkSessionVariablesHeaders :: [Header] -> SessionVariables
mkSessionVariablesHeaders =
  HashMap SessionVariable Text -> SessionVariables
SessionVariables
    (HashMap SessionVariable Text -> SessionVariables)
-> ([Header] -> HashMap SessionVariable Text)
-> [Header]
-> SessionVariables
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(SessionVariable, Text)] -> HashMap SessionVariable Text
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
Map.fromList
    ([(SessionVariable, Text)] -> HashMap SessionVariable Text)
-> ([Header] -> [(SessionVariable, Text)])
-> [Header]
-> HashMap SessionVariable Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((CI Text, Text) -> (SessionVariable, Text))
-> [(CI Text, Text)] -> [(SessionVariable, Text)]
forall a b. (a -> b) -> [a] -> [b]
map ((CI Text -> SessionVariable)
-> (CI Text, Text) -> (SessionVariable, Text)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first CI Text -> SessionVariable
SessionVariable)
    ([(CI Text, Text)] -> [(SessionVariable, Text)])
-> ([Header] -> [(CI Text, Text)])
-> [Header]
-> [(SessionVariable, Text)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((CI Text, Text) -> Bool) -> [(CI Text, Text)] -> [(CI Text, Text)]
forall a. (a -> Bool) -> [a] -> [a]
filter (Text -> Bool
isSessionVariable (Text -> Bool)
-> ((CI Text, Text) -> Text) -> (CI Text, Text) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CI Text -> Text
forall s. CI s -> s
CI.original (CI Text -> Text)
-> ((CI Text, Text) -> CI Text) -> (CI Text, Text) -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CI Text, Text) -> CI Text
forall a b. (a, b) -> a
fst) -- Only x-hasura-* headers
    ([(CI Text, Text)] -> [(CI Text, Text)])
-> ([Header] -> [(CI Text, Text)]) -> [Header] -> [(CI Text, Text)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Header -> (CI Text, Text)) -> [Header] -> [(CI Text, Text)]
forall a b. (a -> b) -> [a] -> [b]
map ((ByteString -> Text) -> CI ByteString -> CI Text
forall s2 s1. FoldCase s2 => (s1 -> s2) -> CI s1 -> CI s2
CI.map ByteString -> Text
bsToTxt (CI ByteString -> CI Text)
-> (ByteString -> Text) -> Header -> (CI Text, Text)
forall (a :: * -> * -> *) b c b' c'.
Arrow a =>
a b c -> a b' c' -> a (b, b') (c, c')
*** ByteString -> Text
bsToTxt)

sessionVariablesToHeaders :: SessionVariables -> [HTTP.Header]
sessionVariablesToHeaders :: SessionVariables -> [Header]
sessionVariablesToHeaders =
  ((SessionVariable, Text) -> Header)
-> [(SessionVariable, Text)] -> [Header]
forall a b. (a -> b) -> [a] -> [b]
map (((Text -> ByteString) -> CI Text -> CI ByteString
forall s2 s1. FoldCase s2 => (s1 -> s2) -> CI s1 -> CI s2
CI.map Text -> ByteString
txtToBs (CI Text -> CI ByteString)
-> (SessionVariable -> CI Text) -> SessionVariable -> CI ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SessionVariable -> CI Text
unSessionVariable) (SessionVariable -> CI ByteString)
-> (Text -> ByteString) -> (SessionVariable, Text) -> Header
forall (a :: * -> * -> *) b c b' c'.
Arrow a =>
a b c -> a b' c' -> a (b, b') (c, c')
*** Text -> ByteString
txtToBs)
    ([(SessionVariable, Text)] -> [Header])
-> (SessionVariables -> [(SessionVariable, Text)])
-> SessionVariables
-> [Header]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HashMap SessionVariable Text -> [(SessionVariable, Text)]
forall k v. HashMap k v -> [(k, v)]
Map.toList
    (HashMap SessionVariable Text -> [(SessionVariable, Text)])
-> (SessionVariables -> HashMap SessionVariable Text)
-> SessionVariables
-> [(SessionVariable, Text)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SessionVariables -> HashMap SessionVariable Text
unSessionVariables

getSessionVariables :: SessionVariables -> [Text]
getSessionVariables :: SessionVariables -> [Text]
getSessionVariables = (SessionVariable -> Text) -> [SessionVariable] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map SessionVariable -> Text
sessionVariableToText ([SessionVariable] -> [Text])
-> (SessionVariables -> [SessionVariable])
-> SessionVariables
-> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HashMap SessionVariable Text -> [SessionVariable]
forall k v. HashMap k v -> [k]
Map.keys (HashMap SessionVariable Text -> [SessionVariable])
-> (SessionVariables -> HashMap SessionVariable Text)
-> SessionVariables
-> [SessionVariable]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SessionVariables -> HashMap SessionVariable Text
unSessionVariables

getSessionVariablesSet :: SessionVariables -> Set.HashSet SessionVariable
getSessionVariablesSet :: SessionVariables -> HashSet SessionVariable
getSessionVariablesSet = HashMap SessionVariable Text -> HashSet SessionVariable
forall k a. HashMap k a -> HashSet k
Map.keysSet (HashMap SessionVariable Text -> HashSet SessionVariable)
-> (SessionVariables -> HashMap SessionVariable Text)
-> SessionVariables
-> HashSet SessionVariable
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SessionVariables -> HashMap SessionVariable Text
unSessionVariables

getSessionVariableValue :: SessionVariable -> SessionVariables -> Maybe SessionVariableValue
getSessionVariableValue :: SessionVariable -> SessionVariables -> Maybe Text
getSessionVariableValue SessionVariable
k = SessionVariable -> HashMap SessionVariable Text -> Maybe Text
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
Map.lookup SessionVariable
k (HashMap SessionVariable Text -> Maybe Text)
-> (SessionVariables -> HashMap SessionVariable Text)
-> SessionVariables
-> Maybe Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SessionVariables -> HashMap SessionVariable Text
unSessionVariables

-- | Represent the admin secret state; whether the secret is sent
-- in the request or if actually authorization is not configured.
data UserAdminSecret
  = UAdminSecretSent
  | UAdminSecretNotSent
  | UAuthNotSet
  deriving (Int -> UserAdminSecret -> ShowS
[UserAdminSecret] -> ShowS
UserAdminSecret -> String
(Int -> UserAdminSecret -> ShowS)
-> (UserAdminSecret -> String)
-> ([UserAdminSecret] -> ShowS)
-> Show UserAdminSecret
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [UserAdminSecret] -> ShowS
$cshowList :: [UserAdminSecret] -> ShowS
show :: UserAdminSecret -> String
$cshow :: UserAdminSecret -> String
showsPrec :: Int -> UserAdminSecret -> ShowS
$cshowsPrec :: Int -> UserAdminSecret -> ShowS
Show, UserAdminSecret -> UserAdminSecret -> Bool
(UserAdminSecret -> UserAdminSecret -> Bool)
-> (UserAdminSecret -> UserAdminSecret -> Bool)
-> Eq UserAdminSecret
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: UserAdminSecret -> UserAdminSecret -> Bool
$c/= :: UserAdminSecret -> UserAdminSecret -> Bool
== :: UserAdminSecret -> UserAdminSecret -> Bool
$c== :: UserAdminSecret -> UserAdminSecret -> Bool
Eq)

-- | Represents the 'X-Hasura-Use-Backend-Only-Permissions' session variable
-- and request made with 'X-Hasura-Admin-Secret' if any auth configured.
-- For more details see Note [Backend only permissions]
data BackendOnlyFieldAccess
  = BOFAAllowed
  | BOFADisallowed
  deriving (Int -> BackendOnlyFieldAccess -> ShowS
[BackendOnlyFieldAccess] -> ShowS
BackendOnlyFieldAccess -> String
(Int -> BackendOnlyFieldAccess -> ShowS)
-> (BackendOnlyFieldAccess -> String)
-> ([BackendOnlyFieldAccess] -> ShowS)
-> Show BackendOnlyFieldAccess
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BackendOnlyFieldAccess] -> ShowS
$cshowList :: [BackendOnlyFieldAccess] -> ShowS
show :: BackendOnlyFieldAccess -> String
$cshow :: BackendOnlyFieldAccess -> String
showsPrec :: Int -> BackendOnlyFieldAccess -> ShowS
$cshowsPrec :: Int -> BackendOnlyFieldAccess -> ShowS
Show, BackendOnlyFieldAccess -> BackendOnlyFieldAccess -> Bool
(BackendOnlyFieldAccess -> BackendOnlyFieldAccess -> Bool)
-> (BackendOnlyFieldAccess -> BackendOnlyFieldAccess -> Bool)
-> Eq BackendOnlyFieldAccess
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BackendOnlyFieldAccess -> BackendOnlyFieldAccess -> Bool
$c/= :: BackendOnlyFieldAccess -> BackendOnlyFieldAccess -> Bool
== :: BackendOnlyFieldAccess -> BackendOnlyFieldAccess -> Bool
$c== :: BackendOnlyFieldAccess -> BackendOnlyFieldAccess -> Bool
Eq, (forall x. BackendOnlyFieldAccess -> Rep BackendOnlyFieldAccess x)
-> (forall x.
    Rep BackendOnlyFieldAccess x -> BackendOnlyFieldAccess)
-> Generic BackendOnlyFieldAccess
forall x. Rep BackendOnlyFieldAccess x -> BackendOnlyFieldAccess
forall x. BackendOnlyFieldAccess -> Rep BackendOnlyFieldAccess x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep BackendOnlyFieldAccess x -> BackendOnlyFieldAccess
$cfrom :: forall x. BackendOnlyFieldAccess -> Rep BackendOnlyFieldAccess x
Generic)

instance Hashable BackendOnlyFieldAccess

data UserInfo = UserInfo
  { UserInfo -> RoleName
_uiRole :: !RoleName,
    UserInfo -> SessionVariables
_uiSession :: !SessionVariables,
    UserInfo -> BackendOnlyFieldAccess
_uiBackendOnlyFieldAccess :: !BackendOnlyFieldAccess
  }
  deriving (Int -> UserInfo -> ShowS
[UserInfo] -> ShowS
UserInfo -> String
(Int -> UserInfo -> ShowS)
-> (UserInfo -> String) -> ([UserInfo] -> ShowS) -> Show UserInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [UserInfo] -> ShowS
$cshowList :: [UserInfo] -> ShowS
show :: UserInfo -> String
$cshow :: UserInfo -> String
showsPrec :: Int -> UserInfo -> ShowS
$cshowsPrec :: Int -> UserInfo -> ShowS
Show, UserInfo -> UserInfo -> Bool
(UserInfo -> UserInfo -> Bool)
-> (UserInfo -> UserInfo -> Bool) -> Eq UserInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: UserInfo -> UserInfo -> Bool
$c/= :: UserInfo -> UserInfo -> Bool
== :: UserInfo -> UserInfo -> Bool
$c== :: UserInfo -> UserInfo -> Bool
Eq, (forall x. UserInfo -> Rep UserInfo x)
-> (forall x. Rep UserInfo x -> UserInfo) -> Generic UserInfo
forall x. Rep UserInfo x -> UserInfo
forall x. UserInfo -> Rep UserInfo x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep UserInfo x -> UserInfo
$cfrom :: forall x. UserInfo -> Rep UserInfo x
Generic)

instance Hashable UserInfo

class (Monad m) => UserInfoM m where
  askUserInfo :: m UserInfo

instance (UserInfoM m) => UserInfoM (ReaderT r m) where
  askUserInfo :: ReaderT r m UserInfo
askUserInfo = m UserInfo -> ReaderT r m UserInfo
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m UserInfo
forall (m :: * -> *). UserInfoM m => m UserInfo
askUserInfo

instance (UserInfoM m) => UserInfoM (ExceptT r m) where
  askUserInfo :: ExceptT r m UserInfo
askUserInfo = m UserInfo -> ExceptT r m UserInfo
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m UserInfo
forall (m :: * -> *). UserInfoM m => m UserInfo
askUserInfo

instance (UserInfoM m) => UserInfoM (StateT s m) where
  askUserInfo :: StateT s m UserInfo
askUserInfo = m UserInfo -> StateT s m UserInfo
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m UserInfo
forall (m :: * -> *). UserInfoM m => m UserInfo
askUserInfo

instance (UserInfoM m) => UserInfoM (TraceT m) where
  askUserInfo :: TraceT m UserInfo
askUserInfo = m UserInfo -> TraceT m UserInfo
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m UserInfo
forall (m :: * -> *). UserInfoM m => m UserInfo
askUserInfo

askCurRole :: (UserInfoM m) => m RoleName
askCurRole :: m RoleName
askCurRole = UserInfo -> RoleName
_uiRole (UserInfo -> RoleName) -> m UserInfo -> m RoleName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m UserInfo
forall (m :: * -> *). UserInfoM m => m UserInfo
askUserInfo

-- | Represents how to build a role from the session variables
data UserRoleBuild
  = -- | Look for `x-hasura-role` session variable value and absence will raise an exception
    URBFromSessionVariables
  | -- | Look for `x-hasura-role` session variable value, if absent fall back to given role
    URBFromSessionVariablesFallback !RoleName
  | -- | Use only the pre-determined role
    URBPreDetermined !RoleName
  deriving (Int -> UserRoleBuild -> ShowS
[UserRoleBuild] -> ShowS
UserRoleBuild -> String
(Int -> UserRoleBuild -> ShowS)
-> (UserRoleBuild -> String)
-> ([UserRoleBuild] -> ShowS)
-> Show UserRoleBuild
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [UserRoleBuild] -> ShowS
$cshowList :: [UserRoleBuild] -> ShowS
show :: UserRoleBuild -> String
$cshow :: UserRoleBuild -> String
showsPrec :: Int -> UserRoleBuild -> ShowS
$cshowsPrec :: Int -> UserRoleBuild -> ShowS
Show, UserRoleBuild -> UserRoleBuild -> Bool
(UserRoleBuild -> UserRoleBuild -> Bool)
-> (UserRoleBuild -> UserRoleBuild -> Bool) -> Eq UserRoleBuild
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: UserRoleBuild -> UserRoleBuild -> Bool
$c/= :: UserRoleBuild -> UserRoleBuild -> Bool
== :: UserRoleBuild -> UserRoleBuild -> Bool
$c== :: UserRoleBuild -> UserRoleBuild -> Bool
Eq)

-- | Build @'UserInfo' from @'SessionVariables'
mkUserInfo ::
  forall m.
  (MonadError QErr m) =>
  UserRoleBuild ->
  UserAdminSecret ->
  SessionVariables ->
  m UserInfo
mkUserInfo :: UserRoleBuild -> UserAdminSecret -> SessionVariables -> m UserInfo
mkUserInfo UserRoleBuild
roleBuild UserAdminSecret
userAdminSecret SessionVariables
sessionVariables = do
  RoleName
roleName <- case UserRoleBuild
roleBuild of
    UserRoleBuild
URBFromSessionVariables ->
      Maybe RoleName -> m RoleName -> m RoleName
forall (m :: * -> *) a. Applicative m => Maybe a -> m a -> m a
onNothing Maybe RoleName
maybeSessionRole (m RoleName -> m RoleName) -> m RoleName -> m RoleName
forall a b. (a -> b) -> a -> b
$
        Code -> Text -> m RoleName
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
InvalidParams (Text -> m RoleName) -> Text -> m RoleName
forall a b. (a -> b) -> a -> b
$ Text
forall a. IsString a => a
userRoleHeader Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" not found in session variables"
    URBFromSessionVariablesFallback RoleName
roleName' -> RoleName -> m RoleName
forall (f :: * -> *) a. Applicative f => a -> f a
pure (RoleName -> m RoleName) -> RoleName -> m RoleName
forall a b. (a -> b) -> a -> b
$ RoleName -> Maybe RoleName -> RoleName
forall a. a -> Maybe a -> a
fromMaybe RoleName
roleName' Maybe RoleName
maybeSessionRole
    URBPreDetermined RoleName
roleName' -> RoleName -> m RoleName
forall (f :: * -> *) a. Applicative f => a -> f a
pure RoleName
roleName'
  BackendOnlyFieldAccess
backendOnlyFieldAccess <- m BackendOnlyFieldAccess
getBackendOnlyFieldAccess
  let modifiedSession :: SessionVariables
modifiedSession = RoleName -> SessionVariables -> SessionVariables
modifySessionVariables RoleName
roleName SessionVariables
sessionVariables
  UserInfo -> m UserInfo
forall (f :: * -> *) a. Applicative f => a -> f a
pure (UserInfo -> m UserInfo) -> UserInfo -> m UserInfo
forall a b. (a -> b) -> a -> b
$ RoleName -> SessionVariables -> BackendOnlyFieldAccess -> UserInfo
UserInfo RoleName
roleName SessionVariables
modifiedSession BackendOnlyFieldAccess
backendOnlyFieldAccess
  where
    maybeSessionRole :: Maybe RoleName
maybeSessionRole = SessionVariables -> Maybe RoleName
maybeRoleFromSessionVariables SessionVariables
sessionVariables

    modifySessionVariables :: RoleName -> SessionVariables -> SessionVariables
    modifySessionVariables :: RoleName -> SessionVariables -> SessionVariables
modifySessionVariables RoleName
roleName =
      HashMap SessionVariable Text -> SessionVariables
SessionVariables
        (HashMap SessionVariable Text -> SessionVariables)
-> (SessionVariables -> HashMap SessionVariable Text)
-> SessionVariables
-> SessionVariables
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SessionVariable
-> Text
-> HashMap SessionVariable Text
-> HashMap SessionVariable Text
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
Map.insert SessionVariable
forall a. IsString a => a
userRoleHeader (RoleName -> Text
roleNameToTxt RoleName
roleName)
        (HashMap SessionVariable Text -> HashMap SessionVariable Text)
-> (SessionVariables -> HashMap SessionVariable Text)
-> SessionVariables
-> HashMap SessionVariable Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SessionVariable
-> HashMap SessionVariable Text -> HashMap SessionVariable Text
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> HashMap k v
Map.delete SessionVariable
forall a. IsString a => a
adminSecretHeader
        (HashMap SessionVariable Text -> HashMap SessionVariable Text)
-> (SessionVariables -> HashMap SessionVariable Text)
-> SessionVariables
-> HashMap SessionVariable Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SessionVariable
-> HashMap SessionVariable Text -> HashMap SessionVariable Text
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> HashMap k v
Map.delete SessionVariable
forall a. IsString a => a
deprecatedAccessKeyHeader
        (HashMap SessionVariable Text -> HashMap SessionVariable Text)
-> (SessionVariables -> HashMap SessionVariable Text)
-> SessionVariables
-> HashMap SessionVariable Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SessionVariables -> HashMap SessionVariable Text
unSessionVariables

    getBackendOnlyFieldAccess :: m BackendOnlyFieldAccess
    getBackendOnlyFieldAccess :: m BackendOnlyFieldAccess
getBackendOnlyFieldAccess = case UserAdminSecret
userAdminSecret of
      UserAdminSecret
UAdminSecretNotSent -> BackendOnlyFieldAccess -> m BackendOnlyFieldAccess
forall (f :: * -> *) a. Applicative f => a -> f a
pure BackendOnlyFieldAccess
BOFADisallowed
      UserAdminSecret
UAdminSecretSent -> m BackendOnlyFieldAccess
lookForBackendOnlyPermissionsConfig
      UserAdminSecret
UAuthNotSet -> m BackendOnlyFieldAccess
lookForBackendOnlyPermissionsConfig
      where
        lookForBackendOnlyPermissionsConfig :: m BackendOnlyFieldAccess
lookForBackendOnlyPermissionsConfig =
          case SessionVariable -> SessionVariables -> Maybe Text
getSessionVariableValue SessionVariable
forall a. IsString a => a
useBackendOnlyPermissionsHeader SessionVariables
sessionVariables of
            Maybe Text
Nothing -> BackendOnlyFieldAccess -> m BackendOnlyFieldAccess
forall (f :: * -> *) a. Applicative f => a -> f a
pure BackendOnlyFieldAccess
BOFADisallowed
            Just Text
varVal ->
              case String -> Either String Bool
parseStringAsBool (Text -> String
T.unpack Text
varVal) of
                Left String
err ->
                  Code -> Text -> m BackendOnlyFieldAccess
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
BadRequest (Text -> m BackendOnlyFieldAccess)
-> Text -> m BackendOnlyFieldAccess
forall a b. (a -> b) -> a -> b
$
                    Text
forall a. IsString a => a
useBackendOnlyPermissionsHeader Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
": " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack String
err
                Right Bool
privilege -> BackendOnlyFieldAccess -> m BackendOnlyFieldAccess
forall (f :: * -> *) a. Applicative f => a -> f a
pure (BackendOnlyFieldAccess -> m BackendOnlyFieldAccess)
-> BackendOnlyFieldAccess -> m BackendOnlyFieldAccess
forall a b. (a -> b) -> a -> b
$ if Bool
privilege then BackendOnlyFieldAccess
BOFAAllowed else BackendOnlyFieldAccess
BOFADisallowed

maybeRoleFromSessionVariables :: SessionVariables -> Maybe RoleName
maybeRoleFromSessionVariables :: SessionVariables -> Maybe RoleName
maybeRoleFromSessionVariables SessionVariables
sessionVariables =
  -- returns Nothing if x-hasura-role is an empty string
  SessionVariable -> SessionVariables -> Maybe Text
getSessionVariableValue SessionVariable
forall a. IsString a => a
userRoleHeader SessionVariables
sessionVariables Maybe Text -> (Text -> Maybe RoleName) -> Maybe RoleName
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Text -> Maybe RoleName
mkRoleName

adminUserInfo :: UserInfo
adminUserInfo :: UserInfo
adminUserInfo = RoleName -> SessionVariables -> BackendOnlyFieldAccess -> UserInfo
UserInfo RoleName
adminRoleName SessionVariables
forall a. Monoid a => a
mempty BackendOnlyFieldAccess
BOFADisallowed