I use the AuthProtect
combinator from servant: Servant.API.Experimental.Auth. There is not much code there, the instance HasServer (AuthProtect tag)
is in servant-server
and the insance HasClient (AuthProtect tag)
in whatever servant client you use.
I use servant-snap
instead of servant-server
and a custom HasClient
implementation for an obelisk
project, with a project structure that consists of three cabal packages:
I used to have a custom implementation of AuthProtect
along with the instances in the common
package. However, common
can neither depend on servant-snap
nor on snap-core
because of ghcjs.
Now I moved the HasServer
instance to the backend ... no problem, right? Wrong. Once the HasServer
instance is orphaned, ghc does not correctly resolve my api type anymore. It's just as if the orphaned instance were not there at all.
Why is that?
What is there, I can do?
Either of those solves my problem:
instance HasServer api context m => HasServer (AuthProtect "jwt" :> api) context m where
type ServerT (AuthProtect "jwt" :> api) context m =
String -> ServerT api context m
hoistServerWithContext _ pc nt s = hoistServerWithContext (Proxy :: Proxy api) pc nt . s
route (Proxy :: Proxy (AuthProtect "jwt" :> api)) context subserver =
route (Proxy :: Proxy api) context (subserver `addAuthCheck` withRequest authCheck)
where
authCheck :: Request -> DelayedM m String
authCheck =
liftIO . evalSnap (pure "account info")
(\x -> pure $! (x `seq` ()))
(\f -> let !_ = f 0 in pure ())
If I don't want specialize to AuthProtect "jwt"
for some reason, I have to provide the constraint KnownSymbol tag
.
instance (KnownSymbol tag, HasServer api context m) => HasServer (AuthProtect tag :> api) context m where
type ServerT (AuthProtect tag :> api) context m =
String -> ServerT api context m
hoistServerWithContext _ pc nt s = hoistServerWithContext (Proxy :: Proxy api) pc nt . s
route (Proxy :: Proxy (AuthProtect tag :> api)) context subserver =
route (Proxy :: Proxy api) context (subserver `addAuthCheck` withRequest authCheck)
where
authCheck :: Request -> DelayedM m String
authCheck =
liftIO . evalSnap (pure "account info")
(\x -> pure $! (x `seq` ()))
(\f -> let !_ = f 0 in pure ())