Haskell 如何向一组处理程序提供从servant中的Db获取的值?

Haskell 如何向一组处理程序提供从servant中的Db获取的值?,haskell,servant,Haskell,Servant,我正在使用servant和JWT身份验证。我试图获取经过身份验证的用户并将其传递给处理程序,而不必在每个处理程序中重复相同的逻辑 通过一个单参数函数,它就像一个符咒: listMeters :: Entity User -> Handler [Meter] protected :: Servant.Auth.Server.AuthResult Token -> Server Protected protected (Servant.Auth.Server.Authenticated

我正在使用servant和JWT身份验证。我试图获取经过身份验证的用户并将其传递给处理程序,而不必在每个处理程序中重复相同的逻辑

通过一个单参数函数,它就像一个符咒:

listMeters :: Entity User -> Handler [Meter]
protected :: Servant.Auth.Server.AuthResult Token -> Server Protected
protected (Servant.Auth.Server.Authenticated email) = do
  user <- getUser email
  listMeters user
listMeters::实体用户->处理程序[Meter]
受保护::Servant.Auth.Server.AuthResult令牌->服务器受保护
受保护(Servant.Auth.Server.Authenticated email)=do
用户仪表->处理器仪表
受保护::Servant.Auth.Server.AuthResult令牌->服务器受保护
受保护(Servant.Auth.Server.Authenticated email)=do
用户处理器仪表'
•可能原因:“addMeter”应用于的参数太少
在“do”块的stmt中:addMeter user
在表达式中:
用户是否返回用户

为什么第一个示例有效,而另一个不有效?如何妥善解决此类案件

在这个特殊问题中,创建IsAuth的自定义实例似乎是最好的解决方案。不过,似乎没有官方/惯用的方式

我通过以下操作解决了问题:

data UserCookie

extractUser userId = (maybe mzero (return . Entity userId)) =<< fetch
  where
    fetch = liftIO $ runSql $ get userId

instance IsAuth UserCookie (Entity User) where
  type AuthArgs UserCookie = '[CookieSettings, JWTSettings]
  runAuth _ _ = \c jwt -> extractUser =<< cookieAuthCheck c jwt
数据用户cookie

extractUser userId=(可能是mzero(return.Entity userId))=您好!你退房了吗?如果您使用servant的机制来指定身份验证方案,servant将实际为您提取并传递
实体用户
值,如示例所示。如果还不够清楚,请告诉我。嗨@AlpMestanogullari,谢谢您的回复。我想通用身份验证是一种可行的方法。事实上,我曾尝试使用常规jwt,并附加了一个从db获取用户的步骤,所以我想知道是否有更简单的方法来实现这一点。此外,我可以想象这样一种为一组处理程序执行特定代码的方式在其他情况下也会有所帮助,因此我想知道在servantNote中是否可能存在这样一种情况,即还有一个包提供了现成的JWT,但是仍然使用相同的原则,声明身份验证保护,并将一些用户数据提供给所有受身份验证保护的处理程序。明确地说:身份验证本身是有效的。我只是想将实体用户传递给处理程序,而不是令牌,但我不知道如何实现这一点(对于这样一个简单的修改来说,通用身份验证似乎有点太多),因为它需要在特定的monad中运行以访问数据库并抛出异常(如getUser函数所示)。这就是为什么我概括了我的问题,因为它与身份验证并没有严格的关系,而是将db对象传递给更高级别的处理程序。另外请注意,我知道有一些解决方法可以解决这个问题。我只是出于好奇问,是否可以在servant中定义处理程序组的常见行为。或者,我想如果我可以使用FromJWT从数据库中获取用户,但不幸的是,它的文档不足,我没有找到任何这样的例子
/usr/src/app/src/Handlers.hs:57:3: error:
    • Couldn't match type ‘Handler b0’ with ‘Meter -> Handler Meter’
      Expected type: Server Protected
        Actual type: Handler b0
    • In a stmt of a 'do' block: user <- getUser email
      In the expression:
        do user <- getUser email
           addMeter user
      In an equation for ‘protected’:
          protected (Authenticated email)
            = do user <- getUser email
                 addMeter user
   |
57 |   user <- getUser email
   |   ^^^^^^^^^^^^^^^^^^^^^

/usr/src/app/src/Handlers.hs:64:3: error:
    • Couldn't match expected type ‘Handler b0’
                  with actual type ‘Meter -> Handler Meter’
    • Probable cause: ‘addMeter’ is applied to too few arguments
      In a stmt of a 'do' block: addMeter user
      In the expression:
        do user <- getUser email
           addMeter user
      In an equation for ‘protected’:
          protected (Authenticated email)
            = do user <- getUser email
                 addMeter user
   |
64 |   addMeter user
   |   ^^^^^^^^^^^^^
getUser :: Token -> Handler (Entity User)
getUser email = do
  userEntity <- liftIO $ runSql $ getBy $ UniqueEmail email
  case userEntity of
        Nothing -> throwError err401
        Just user -> return user
data UserCookie

extractUser userId = (maybe mzero (return . Entity userId)) =<< fetch
  where
    fetch = liftIO $ runSql $ get userId

instance IsAuth UserCookie (Entity User) where
  type AuthArgs UserCookie = '[CookieSettings, JWTSettings]
  runAuth _ _ = \c jwt -> extractUser =<< cookieAuthCheck c jwt