完全重写以包含更好的理解
Yesod
类型类包含您可以调整的函数isAuthorized
,以便不同的用户组只能访问不同的路由。
脚手架网站显示了如何执行此操作的示例,包括使授权子网站可供所有人使用:
isAuthorized (AuthR _) _ = return Authorized
脚手架网站还有助于包含静态内容的子网站。但是:静态子网站不尊重您在isAuthorized
中所做的事情。您可以通过添加类似
isAuthorized (StaticR _) _ = error "this error is never reached"
您仍然可以访问所有静态内容(包括新创建的内容),您将永远不会遇到此模式匹配。
让每个人都能访问bootstrap或jquery等内容确实有点意义。尽管如此,可以通过尊重isAuthorized
并始终返回Authorized
来实现相同的结果,就像使用授权子网站或favicon处理程序一样。
我个人想进一步发送像
这样的发送isAuthorized (StaticR (StaticRoute ("public":_) _)) _ = pure Authorized
isAuthorized (StaticR (StaticRoute ("admin" :_) _)) _ = checkIsAdmin
isAuthorized (StaticR (StaticRoute ("cats" :_) _)) False = checkIsAllowedToViewCats
:
似乎唯一缺少的是让静态子网站接受检查或添加一个垫片。
可悲的是,子网站是一个庞大的复杂代码,其中包含模板haskell和很多魔术,可以执行复杂的操作,例如在可执行文件中嵌入文件。它包含在脚手架中的方式还有更多的魔力。我也只是学习子网站和我的培训,看到类型作为文档在类型系列或Q Def
等上下文中失败。由于这些原因,我无法弄清楚如何添加支票。任何指针都会受到赞赏。
答案 0 :(得分:1)
所以我发现了一个不完美的答案,这对我现在的目的来说已经足够了。
我无法弄清楚如何使静态网站的行为不同。它似乎以某种方式使用了wai服务器的底层功能,因此它甚至从未接触到它的Yesod部分。并且由于子网站似乎在核心系统之前进行调度,这是我可以改变某些东西的唯一地方。让核心系统排在最后的奇怪选择,但无论如何,这可能是有原因的。
然后,解决方案是复制静态子网站的功能。但请尽可能少地工作。所以这是你可以创建的最基本的处理程序:
getStaticCatContentHtmlR :: Text -> Handler Value
getStaticCatContentHtmlR path = do
let filePath = "static/cats/html" </> unpack path
sendFile "text/html" filePath
只需将您的静态子网站指向static/public
,为每个子网站为html,css和js创建三个新的子文件夹,添加三个具有适当权限的相应处理程序并完成它。路由系统确保用户无法请求/static/cats/html/../../../
等路径。
但是有几个缺点。
是否值得努力创建一个子网站来捆绑这三个处理程序?好吧,也许是作为训练练习......