Play framework. How to check if user is authenticated or not? - scala

I'm new to playframework and I'm using version 2.2.2.
I'm checking the zentask sample but could somebody tell me how to check in view if user is logged in or not?
In main.scala.html I've list of links.
<ul>
<li>New blogpost</li>
<li>Login</li>
<li>Logout</li>
</ul>
What I would like to have is that when user is logged in the logout link is shown.
My application.scala looks like this:
def index = Action {
Ok(views.html.index(BlogPost.all(), blogpostForm))
}
I can check that if user is allowed to access to create new blogpost:
def newBlogpost = IsAuthenticated { username => _ =>
User.findByUsername(username).map { user =>
Ok(views.html.blogpost.item(blogpostForm))
}.getOrElse(Forbidden)
}
So what would be the easiest way in main.scala.html to check if user is logged in or not and show correct link based on that?

You can pass session to you html template and check is defined user there or not:
#()(implicit session: Session)
<ul>
#session.get("user").map { user =>
<li>New blogpost</li>
<li>Logout</li>
}.getOrElse{
<li>Login</li>
}
</ul>
Note: you have to mark request in your action as implicit.

Related

Reactive Slick future response not rendered Play template

I am working on Slick 3 + Play Framework and Scala. I don't know why my Play template not rendering data I was getting from Slick DB call first time. When I was refreshing same page again it shows the data but unable to rendered 1st time.
Here is my code,
Slick DB call:
def findByAccessToken(Id: String): Future[Option[Organization]] =
db.run(orgs.filter(_.Id=== Id).result.headOption)
Controller Action Call:
def getOrgInfo = Action.async { request =>
val maybeOrg = for {
org <- orgDAO.findByAccessToken(request.session.get("oauthAccessToken").get)
} yield org
maybeOrg.map {
case org =>
org match {
case Some(c) => Ok(views.html.account(c))
case None => NotFound
}
}
And Final Play Template code:
#(Org: Organization)
#container("Org Info") {
<h1>Org Information</h1>
<ul>
<li>
User Id: #Org
</li>
</ul>
}
Looks like when 1st time my page loading at that time db call have not yet delivered result but because when I was refreshing it shows data.
How to handle this scenario and rendered data for first time as well ?
Thanks
Probably this doesn't have anything to do with the template. You could add some debug statements to verify that. Maybe the token does not exist at the moment the first request is fired?

Scala Play framework 2.2 - How to get information about a users loginstatus in template

I have the following use-case. I implemented a very simple authentication in my play app which adds a session cookie if a user logs in (See code below).
This code works fine so far. What I want to achieve now is to check in my main template if a user is logged in or not and display login/logout elements on the page according to the user status.
How can I achieve this in the most elegant way?
I have found sources where people access the session variables directly from the template with play <= 2.1. It seems like this method doesn't work for 2.2 anymore and is deprecated?
Do I have to pass a boolean value in every action to the template to define if a user is logged in??
Wrapper Action
case class Authenticated[A](action: Action[A]) extends Action[A] {
def apply(request: Request[A]): Future[SimpleResult] = {
if (request.session.get("user").getOrElse("").equals("user")) {
action(request)
} else {
Future.successful(Redirect("/login").withSession(("returnUrl", request.path)))
}
}
lazy val parser = action.parser
}
Submit Part of Login Controller
def submit = Action { implicit request =>
loginForm.bindFromRequest.fold(
errors => Ok(html.login.form(errors)),
requestUser => {
val user: String = Play.current.configuration.getString("fillable.user").getOrElse("")
val password: String = Play.current.configuration.getString("fillable.password").getOrElse("")
if (requestUser.name.equals(user) && requestUser.pw.equals(password))
Redirect(request.session.get("returnUrl").getOrElse("/")).withSession(session + ("user" -> requestUser.name) - "returnUrl")
else
Ok(html.login.form(loginForm, "error", Messages("error.wrongCredentials")))
})
}
Example Controller Action where Authentication is needed
def submit = Authenticated {
Action.async { implicit request =>
...
}
}
So what I found out now is that if the Controller Action uses an implicit request(like the one in my question above) I can use that request and therefore the session in my template if I add this to the head of the template:
(implicit request: Request[Any])
I am not sure if this is a good approach so I am happy if someone can approve it.

Scala-Lift redirect user after login

I want to redirect to a certain page after a user logs in to my Scala Lift web application. I found this answer which doesn't seem to work:
In my User object (which is a MetaMegaProtoUser) I override the following method like so:
object User extends User with MetaMegaProtoUser[User] {
override def loginFirst = If(
loggedIn_? _,
() => {
import net.liftweb.http.{RedirectWithState, RedirectState}
val uri = Full("/myPicks")
println("login sucessful .. redirecting!..")
RedirectWithState(
loginPageURL,
RedirectState( ()=>{loginRedirect.set(uri)})
)
}
)
}
This doesn’t work. Any ideas?
loginFirst defines a LocParam which can be used for specifying where to send the user if they are not logged in. It is used in conjunction with SiteMap.
For the page you want to protect, you can modify that entry like:
Menu("Protected Page") / "protected" >> User.loginFirst
That should test whether the user is logged in when you access /protected and, if they are not, set the loginRedirect SessionVar and display the login form. On a successful login, you should be redirected to the page specified in loginRedirect.
I believe you can also just use: override def homePage = "/myPicks" if you want to set a default page to redirect to.

How to update securesocial username after user is created

I'm trying to write an editUser page with the Secure Social plugin implemented in a Play Framework app. I'm having trouble staying logged in after the username is changed. The issue occurs when I press submit for the editUser form after changing the username. It goes to the login page and says "You need to log in to access that page." The desired behavior is to redirect to editUser page without needing to relogin. In the database everything is successfully updated. So that works, it just is no longer is logged in.
Below is my controller method for my "User" controller for the POST of the user update.
If anyone could help me out with this it would be greatly appreciated. Thanks.
// The form uses the following case class
case class AccountInfo(userName: String, firstName: String, lastName: String, email: Option[String])
def update(username: String) = SecuredAction { implicit request =>
this.editAccountForm.bindFromRequest.fold (
hasErrors = { info =>
Redirect(routes.Users.edit()).flashing(Flash(editAccountForm.data) +
("error" -> Messages("validation.errors")))
},
success = { info =>
DB.withSession { implicit s: Session =>
val uid = User.currentUser(request.user.id.id,providerId).get.uid
User.update(uid, info, providerId)
}
val message = Messages("user.update.success")
Redirect(routes.Users.edit()).flashing("success" -> message)
.withCookies(request.cookies.get("id").get)
}
)
}
By changing the username you are changing the values used to identify the user (username + provider id). What is happening is that on the next request SecureSocial is looking for the old username and since it can't find it in the database it just kicks you out.
What you should do besides updating the database is update the Authenticator stored for your current session. Something like:
SecureSocial.authenticatorFromRequest(request).map { authenticator =>
val newId = request.user.id.copy( id = userName )
Authenticator.save(authenticator.copy( userId = newId))
}
That should make it work. Also, you don't need to add the id cookie to your Redirect. SecureSocial does that for you.

Play Framework 2 (Scala) templates: see if user is logged in

Moin,
I wrote an app with help of play framework. Now I have a main template which should be used for every request. In this template I have links routing to login form and logout method. Of course only users that are logged out should see the login form and so on. Does anybody know how to implement that without writing every action two times?
Thanks from northern Germany!
I put a gist up on securing actions, which could be of use to you.
Controllers extending the SecureableController trait have:
implicit def user(implicit request : RequestHeader) : Option[User] = {
// substitute in your own user lookup mechanism here
session.get("email").flatMap(User.findOne(_))
}
which allows you to get the user via implicit parameters in views you route to from that controller by specifying:
# ... other parameters ... (implicit user: Option[User] = None)
on each of your views. (Haven't got a way around that particular boilerplate yet.)
I then have something like this in my menu:
#user match {
case Some(u) => {
#defining(u.givenName + " " + u.familyName) { profileName =>
<li class="dropdown">#profileName<b class="caret"></b>
}
<ul class="dropdown-menu">
#defining("/profile/"+u.email) { profileUrl =>
<li>Profile</li>
<li>Logout</li>
}
</ul>
</li>
}
case None => {
<li>
Login
</li>
}
}
It gives a bootstrap dropdown linking to the Profile page and Logout for a logged in user, and a Login link in place if there is no logged in user.