{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}

{- |
Module          : Network.UnityM.Servant
Description     : The Unity Monad implementation for Servant
Copyright       : (c) Brian Hurt, 2017
License         : BSD3
Maintainer      : bhurt42@gmail.com
Stability       : experimental
Portability     : Haskell

This is the implementation of the Unity monad for Servant.  I assume that
the code is using enter to add a ReaderT or StateT on top of the Handler
monad.

Note that if we try to supply a implementation of UnityM for MTL's Reader
type class, this conflicts with the Trans implementation of UnityM in the
main library.  This whole implementation is tap dancing on the edge of
needing OverlappingInstances, which is bad. For more complex instances,
hand rolled implementations of UnityM may be required.

-}
module Network.UnityM.Servant where

    import Control.Monad.Except
    import Network.UnityM
    import qualified Control.Monad.Trans.Reader as TransR
    import qualified Control.Monad.Trans.State as TransS
    import qualified Data.Text as Text
    import Servant

    instance {-# OVERLAPPING #-}
        UnityM c (TransR.ReaderT c Handler) where
            getContext = TransR.ask
            permissionDenied msg = lift $ throwError (err403
                                                    { errReasonPhrase =
                                                        Text.unpack msg })
    instance {-# OVERLAPPING #-}
        UnityM c (TransS.StateT c Handler) where
            getContext = TransS.get
            permissionDenied msg = lift $ throwError (err403
                                                    { errReasonPhrase =
                                                        Text.unpack msg })