def loggedIn:Boolean // this would determine whether the user is already logged in
def testLoginPage(r:Req):Boolean //this would check the credentials of the user
def applyStoredReq(storedReq:Req):Box[LiftResponse] = {
??? // this is the bit I'd like some assistance with. I'd like to know that any logic I have in sitemap, statelessdispatch and dispatch are all applied.
}
val LoginFormPageLocPrefix = "loginForm"
def LoginFormPageLoc(originalRequestId:String) = List(LoginFormPageLocPrefix,originalRequestId)
object reqStore extends SessionVar[Map[String,Req]](Map.empty[String,Req])
LiftRules.dispatch.prepend {
case req:Req if !loggedIn => () => {
val originalReqId = nextFuncName
reqStore(reqStore.is.updated(originalReqId,req))
Full(RedirectResponse(LoginFormPageLoc(originalReqId)))
}
case Req(List(LoginFormPageLoc,originalReqId),_,_) => () => {
// this would generate a NodeResponse containing an html form which redirects to /handleLoginForm?originalReqId={originalReqId}, into which the user would authenticate
}
case r@Req("handleLoginForm") => () => {
testLoginPage(r) match {
case true => {
for (
originalReqId <- r.param("originalReqId");
originalReq <- reqStore.is.get(originalReqId);
resp <- applyStoredReq(originalReq)
) yield resp
}
case _ => r.param("originalReqId").map(originalReqId => RedirectResponse(LoginFormPageLoc(originalReqId)))
}
}
}
package code.servlets import java.util.UUID import javax.servlet._ import javax.servlet.http.{HttpServletRequest, HttpServletResponse} import code.config.AppSettings import code.model.AcmApp import code.model.user.ExtSession._ import net.liftmodules.mongoauth.MongoAuth import net.liftweb.common.{Empty, Box, Full, Failure} import net.liftweb.util.Helpers._ class LoggedInFilter extends Filter { def doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain): Unit = { val httpReq = req.asInstanceOf[HttpServletRequest] val sessionId = httpReq.getSession.getId val extSess = for { cookies <- Box.legacyNullTest(httpReq.getCookies) cookie <- Box(cookies.find { c => c.getName == MongoAuth.extSessionCookieName.vend }) cookieValue = cookie.getValue uuid <- tryo(UUID.fromString(cookieValue)) ?~ "Invalid UUID" es <- find(uuid) ?~ "ExtSession not found: %s".format(uuid.toString) } yield { es } val resp = res.asInstanceOf[HttpServletResponse] extSess match { case Failure(msg, _, _) => deleteExtCookie() resp.sendRedirect(AppSettings.protocol + "://" + AcmApp.Dashboard.domain + "/login") case Full(es) if es.expires.isExpired => // if it's expired, delete it and the cookie deleteExtCookie() resp.sendRedirect(AppSettings.protocol + "://" + AcmApp.Dashboard.domain + "/login") case Empty => resp.sendRedirect(AppSettings.protocol + "://" + AcmApp.Dashboard.domain + "/login") case _ => chain.doFilter(req, res) } } def init(config: FilterConfig): Unit = {} def destroy(): Unit = {} }
=================
Thanks
--
--
Lift, the simply functional web framework: http://liftweb.net
Code: http://github.com/lift
Discussion: http://groups.google.com/group/liftweb
Stuck? Help us help you: https://www.assembla.com/wiki/show/liftweb/Posting_example_code
---
You received this message because you are subscribed to the Google Groups "Lift" group.
To unsubscribe from this group and stop receiving emails from it, send an email to liftweb+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
package code.servlets
import javax.servlet._
import javax.servlet.http.{HttpServletRequest, HttpServletResponse, HttpSession}
class LoggedInFilter extends Filter {
def duplicateAndFreezeRequest(req: HttpServletRequest):HttpServletRequest = ??? // because servlet request is a lightweight reference to the current request, it needs to have its values copied to an instance which isn't related to the container, but which still returns the container's req from { def getRequest }, so I used a Lift MockHttpServletRequest and populated it with values from the original request.
def storeRequest(session:HttpSession,req:HttpServletRequest):Unit = ??? // because there are so many asynchronous calls flying around from cometActors, it isn't necessarily true that the first request on a new session will be the one which represents the navigate call of the user's browser, so the datamodel can't be as simple as a one-to-one relationship between user sessions and stored requests. So, storing, clearing and retrieving all need to be able to use the current HttpServletRequest as a key to determine which stored request to resume.def clearRequest(session:HttpSession,req:HttpServletRequest):Unit = ???
def retrieveRequest(session:HttpSession,req:HttpServletRequest):Option[HttpServletRequest] = ???
def isAuthenticated(session:HttpSession,req:HttpServletRequest):Boolean = ??? // for the sake of this example, I'm simplifying all the question of how authentication occurs from the mechanism of storing and replaying the request(s)def doAuthentication(session:HttpSession,req:HttpServletRequest,resp:HttpServletResponse):Unit = ???
def doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain): Unit = {
val httpReq = req.asInstanceOf[HttpServletRequest]
val session = httpReq.getSession
val resp = res.asInstanceOf[HttpServletResponse]
isAuthenticated match {
case true => {
retrieveRequest(session,httpReq).map(originalRequest => {
clearRequest(session,httpReq)
chain.doFilter(originalRequest,resp)
}).getOrElse({
chain.doFilter(httpReq,resp)
})
}
case false => {
doAuthentication(session,httpReq,resp)
}
}
}
def init(config: FilterConfig): Unit = {}
def destroy(): Unit = {}
}
Thanks again to both of you.
Of course, it still interests me to know whether there's an entry point from within a LiftApp where I can process a Req against the entire Lift Engine, to return a LiftResponse, and know that behaviour in statelessDispatch, dispatch and snippets all had their normal opportunity to handle it. If you've any further thoughts about that entrypoint, I'd love to hear them.
-Dave