|
package fleetzone |
|
package http |
|
|
|
|
|
import net.liftweb.http._ |
|
import net.liftweb.http.provider._ |
|
import net.liftweb.sitemap._ |
|
import net.liftweb.common._ |
|
|
|
import net.liftweb.util._ |
|
import scala.xml._ |
|
|
|
/** |
|
* Class used for checking landing pages |
|
* |
|
* Verifies that cookies are enabled and redirects to error page if not. |
|
* |
|
* Example usage: |
|
* |
|
* val cookieVerifier = new CookieVerifier(cookies => RedirectResponse("/cookieerror.html", cookies:_*)) { |
|
* verify { |
|
* case Req(path, _, _) if pathIsPublic(path) => true |
|
* } |
|
* } |
|
*/ |
|
class CookieVerifier(errorHandler: (HTTPCookie*) => LiftResponse, cookieName: String = "verifier", verifyURI: List[String] = List("verifycookies")) extends Logger { |
|
private object cookiesEnabled extends SessionVar[Box[Boolean]](Empty) |
|
|
|
LiftRules.dispatch.append { |
|
case Req(path, _, _) if path == verifyURI => () => Full{ |
|
debug("Verify if cookie with name %s is present".format(cookieName)) |
|
trace("Received cookies: "+S.request.dmap("")(_.cookies.toString)) |
|
val receivedValue = S.cookieValue(cookieName) |
|
val expected = S.param("verify") |
|
val cookiesOk = receivedValue.isDefined && receivedValue == expected |
|
debug("Cookie found: %s, should match: %s. Result: %s".format(receivedValue, expected, cookiesOk)) |
|
|
|
cookiesEnabled(Full(cookiesOk)) |
|
S.deleteCookie(cookieName) |
|
trace("Deleted cookie, Response cookies: "+S.responseCookies) |
|
if (cookiesOk) { |
|
val returnTo = (S.param("returnTo").map(Helpers.urlDecode(_)) or S.referer).getOrElse("/") |
|
debug("Cookie present, redirect back to %s. referer=%s".format(returnTo, S.referer)) |
|
RedirectResponse(returnTo, S.responseCookies :_*) |
|
} else { |
|
debug("Cookie not present, calling error handler") |
|
errorHandler(S.responseCookies :_*) |
|
} |
|
} |
|
} |
|
|
|
protected def verify(handler: PartialFunction[Req, Boolean]): Unit = LiftRules.dispatch.append(new LiftRules.DispatchPF() { |
|
def isDefinedAt(in: Req) = { |
|
if (handler.isDefinedAt(in) && handler(in)) { |
|
val skipCheck = in.param("_nocheck").isDefined |
|
|
|
val enabled = cookiesEnabled.dmap(false)(enabled => enabled) |
|
trace("Cookies enabled (%s)=%s, skip=%s".format(in.uri, enabled, skipCheck)) |
|
!(enabled || skipCheck) |
|
} else |
|
false |
|
} |
|
|
|
def apply(in: Req): () => Box[LiftResponse] = { |
|
val value = StringHelpers.randomString(16) |
|
debug("Cookies not checked, redirecting to verify url, value=%s".format(value)) |
|
val cookie = HTTPCookie(cookieName, value).setMaxAge(-1).setPath("/") |
|
|
|
|
|
// Need to escape the incoming URL, as it may itself contain URL parameters |
|
val paramList = in.params.keys.flatMap(key => in.params(key).map(v => key -> v)).toList |
|
val paramString = Helpers.paramsToUrlParams(paramList) |
|
val returnUrl = in.uri + "?" + paramString |
|
val encoded = Helpers.urlEncode(returnUrl) |
|
|
|
val uri = "/%s?verify=%s&returnTo=%s".format(verifyURI.mkString("/"), value,encoded) |
|
trace("Redirecting to "+uri) |
|
() => Full(RedirectResponse(uri, cookie)) |
|
} |
|
}) |
|
} |