How to runDB in AuthPlugin?

Skip to first unread message

Nov 28, 2021, 6:23:21 PM11/28/21
to Yesod Web Framework
Hi all,

I'm having trouble and no idea how to use persistent (with runDB?) in my custom AuthPlugin.

Here is a sample code which fails with a compile error:

authEmailLink :: YesodAuth m => AuthPlugin m
authEmailLink =
  AuthPlugin "email-link" dispatch login
    dispatch :: Text -> [Text] -> AuthHandler m TypedContent
    dispatch "GET" [loginToken] = do
      muser <- liftHandler . runDB $ selectFirst [UserLoginToken ==. Just loginToken] []


    • Could not deduce: BaseBackend (YesodPersistBackend m1)
                        ~ Database.Persist.SqlBackend.Internal.SqlBackend
        arising from a use of ‘selectFirst’
      from the context: MonadAuthHandler m1 m2
        bound by the type signature for:
                   dispatch :: Text -> [Text] -> AuthHandler m1 TypedContent

I guess I have to fix the class type header, maybe something with YesodPersist or YesodAuthPersist or YesodPersistBackend but I don't get it.

I'd be grateful for any help!


Michael Snoyman

Nov 29, 2021, 3:14:33 AM11/29/21
There are two different things I can see here that may be helpful:

1. You're using a type variable `m` in both the top level signature for `authEmailLink` and `dispatch`. _However_, because of how scoping rules work, they are _different_ type variables for the compiler. That's why you get the message containing `m1` instead of `m1`. I'd fix that by turning on the `ScopedTypeVariables` language pragma and putting a `forall m.` before the `YesodAuth` constraint.
2. You then likely need to further constrain that `m` to indicate that the `m` provides the ability to make SQL requests. Hopefully the error messages will be clearer though after you implement (1).
You received this message because you are subscribed to the Google Groups "Yesod Web Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to

Nov 29, 2021, 5:34:46 AM11/29/21
to Yesod Web Framework
Thanks Michael. I enabled ScopedTypeVariables in that module (Yesod.Auth.Dummy and Yesod.Auth.Email have this as well). And I changed the first line to:

authEmailLink :: forall m. YesodAuth m => AuthPlugin m

However, the error message is the same except that now `m1` has changed to `m`.

I've looked at the source of Yesod.Auth.HashDB. They define the type constraints using a "type" (using GHC extension ConstraintKinds) with a lot of constraints:

type HashDBPersist master user =
    ( YesodAuthPersist master
    , PersistUnique (YesodPersistBackend master)
    , AuthEntity master ~ user
#if MIN_VERSION_persistent(2,5,0)
    , PersistEntityBackend user ~ BaseBackend (YesodPersistBackend master)
    , PersistEntityBackend user ~ YesodPersistBackend master
    , HashDBUser user
    , PersistEntity user

I don't think that I need most of these. But even if I use all except `HashDBUser`, I still get the same error message :-/

Michael Snoyman

Nov 30, 2021, 2:29:41 AM11/30/21
I'm not sure what would lead to that behavior, sorry.

Nov 30, 2021, 3:54:32 AM11/30/21
to Yesod Web Framework
Thank you anyway! It will probably take me a few more hours trial and error but it must be possible... Yesod.Auth.HashDB did it. I'll post the solution when I find it.
Reply all
Reply to author
0 new messages