{-# LANGUAGE CPP #-}
module Tonatona.Google
( run
, Dsl
, DslBackend
, Config
, ClientError
, JWT
, JWT.Scope(..)
) where
import Tonalude
import qualified Google.Client as Client
import Google.JWT (JWT)
import qualified Google.JWT as JWT
#if MIN_VERSION_servant_client(0, 16, 0)
import Servant.Client (ClientError)
#else
import Servant.Client (ServantError)
#endif
import Tonatona (HasConfig(..), HasParser(..))
import TonaParser (Parser, (.||), argLong, envVar, requiredVal)
import Tonatona.Google.Internal
#if !MIN_VERSION_servant_client(0, 16, 0)
type ClientError = ServantError
#endif
run ::
(HasConfig env Config)
=> (ClientError -> RIO env a)
-> [JWT.Scope]
-> Dsl env a
-> RIO env a
run errorHandler scopes query = do
Config {..} <- asks config
eToken <- liftIO $ Client.getToken (Just delegationEmail) jwt scopes
case eToken of
Left err -> errorHandler err
Right token ->
runReaderT query (DslBackend token) `catch` errorHandler
data Config = Config
{ serviceKeyFile :: ServiceKeyFile
, jwt :: JWT
, delegationEmail :: JWT.Email
}
newtype ServiceKeyFile = ServiceKeyFile { unServiceKeyFile :: FilePath }
deriving (Eq, Read, Show)
instance HasParser ServiceKeyFile where
parser = ServiceKeyFile <$>
requiredVal
"File path to service key file (Example: \"gmail-3abc452de.json\")"
( argLong "service-key-file" .|| envVar "SERVICE_KEY_FILE")
parseJwt :: ServiceKeyFile -> Parser JWT
parseJwt (ServiceKeyFile fp) = do
mjwt <- liftIO $ JWT.readServiceKeyFile fp
case mjwt of
Nothing ->
error $ "Failed to parse service key file: " <> fp
Just jwt ->
pure jwt
parseEmail :: Parser JWT.Email
parseEmail = JWT.Email <$>
requiredVal
"Email account to use for delegation."
( argLong "delegation-email" .|| envVar "DELEGATION_EMAIL")
instance HasParser Config where
parser = do
keyFile <- parser
Config
<$> pure keyFile
<*> parseJwt keyFile
<*> parseEmail