-------------------------------------------------------------------------------- module App where -------------------------------------------------------------------------------- import RIO hiding (Handler) import Servant import API import Data.String.Conversions (cs) import Control.Monad.IO.Class (liftIO) import Network.Wai.Middleware.Cors import GoogleSignIn (EncodedJWT(..), ValidationResult(..)) import Utils import qualified Network.Wai.Handler.Warp as Warp import qualified GoogleSignIn import qualified Stripe import qualified Types as T -------------------------------------------------------------------------------- server :: T.Context -> Server API server ctx@T.Context{..} = verifyGoogleSignIn :<|> createPaymentIntent where verifyGoogleSignIn :: T.VerifyGoogleSignInRequest -> Handler NoContent verifyGoogleSignIn T.VerifyGoogleSignInRequest{..} = do validationResult <- liftIO $ GoogleSignIn.validateJWT False (EncodedJWT idToken) case validationResult of Valid _ -> do -- If GoogleLinkedAccounts has email from JWT: -- create a new session for email -- Else: -- Redirect the SPA to the sign-up / payment page pure NoContent err -> do throwError err401 { errBody = err |> GoogleSignIn.explainResult |> cs } createPaymentIntent :: T.PaymentIntent -> Handler T.CreatePaymentIntentResponse createPaymentIntent pmt = do clientSecret <- liftIO $ Stripe.createPaymentIntent ctx pmt pure T.CreatePaymentIntentResponse{..} run :: T.App run = do ctx@T.Context{..} <- ask ctx |> server |> serve (Proxy @API) |> cors (const $ Just corsPolicy) |> Warp.run contextServerPort |> liftIO pure $ Right () where corsPolicy :: CorsResourcePolicy corsPolicy = simpleCorsResourcePolicy { corsOrigins = Just (["http://localhost:8000"], True) , corsMethods = simpleMethods ++ ["PUT", "PATCH", "DELETE", "OPTIONS"] , corsRequestHeaders = simpleHeaders ++ ["Content-Type", "Authorization"] }