Поскольку все больше и больше людей интересуются Scala (как и я), а не вопросом, я хотел бы обсудить одну реализацию фрагмента кода входа / выхода для веб-приложения на основе на Lift .
Я только начал изучать Scala и Lift, так что, вероятно, не лучший способ реализовать такую функцию, но я хотел бы поделиться им с другими новичками и обсудить с более опытные разработчики. Please note that I'm also not an expert in web development. Any help for improvements would be greatly appreciated (especially performance and security related ones) ;-)
1) First of all, the snippet needs to be easily plugable, like with 1 line of code in your default template. I've done it using the embedded Lift feature (notice the underscore so it can't be rendered as a page itself but only invoked from a rendered page, in short, some kind of "private" snippet):
<lift:embed what="_logInForm" />
2) Then, in _logInForm.html, I use the below markup and a conditional display to handle everything:
<div>
<!-- User is not logged in, show a form to log in using the method loggedOut -->
<lift:LogInForm.loggedOut>
<form class="lift:LogInForm.logIn?form=post">
<label for="textName">Username: </label><input type="text" id="textName" name="name" /> <span class="lift:Msg?id=name;errorClass=error"/><br/>
<label for="textPassword">Password: </label><input type="password" id="textPassword" name="password" /> <span class="lift:Msg?id=password;errorClass=error"/><br/>
<input type="submit" value="Log in" />
</form>
</lift:LogInForm.loggedOut>
<!-- User is logged in, show who she is and a way to log out using the method loggedIn -->
<lift:LogInForm.loggedIn>
<form class="lift:LogInForm.logOut?form=post">
Connected as <span class="lift:LogInForm.getName" />.<br />
<input type="submit" id="btnLogOut" value="Log out" />
</form>
</lift:LogInForm.loggedIn>
</div>
3) ... and now the Scala/Lift logic behind this markup:
object LogInForm {
private object name extends SessionVar("")
private object password extends RequestVar("")
private object referer extends RequestVar(S.referer openOr "/")
var isLoggedIn = false
def loggedIn(html: NodeSeq) =
if (isLoggedIn) html else NodeSeq.Empty
def loggedOut(html: NodeSeq) =
if (!isLoggedIn) html else NodeSeq.Empty
def logIn = {
def processLogIn() {
Validator.isValidName(name) match {
case true => {
Validator.isValidLogin(name, password) match {
case true => { isLoggedIn = true } // Success: logged in
case _ => S.error("password", "Invalid username/password!")
}
}
case _ => S.error("name", "Invalid username format!")
}
}
val r = referer.is
"name=name" #> SHtml.textElem(name) &
"name=password" #> (
SHtml.textElem(password) ++
SHtml.hidden(() => referer.set(r))) &
"type=submit" #> SHtml.onSubmitUnit(processLogIn)
}
def logOut = {
def processLogOut() { isLoggedIn = false }
val r = referer.is
"type=submit" #> SHtml.onSubmitUnit(processLogOut)
}
def getName = "*" #> name.is
}
Comments:
4) You can control access to other pages doing the following in Boot.scala:
def sitemap() = SiteMap(
Menu("Home") / "index",
Menu("Protected page") / "protectedPageName" >> If(() => LogInForm.isLoggedIn, ""),
// etc.
Questions:
Cheers,
Marc.