tags:

views:

315

answers:

1

Hi all-

I feel like I'm monopolizing the stack for Scala/Lift, so I apologize, but the questions keep coming. Here's the latest.

I'm trying to restrict access to anything in the /login/* to those users who have not yet logged in.

Here is how I'm trying to do it:

val entries = Menu(Loc("Home", List("index"), "Home")) ::  //login stuff
    Menu(Loc("loginBase", ("login"::""::Nil)->true, "Login Base", Hidden, anyLoggedIn))::...

Thats the entry in SiteMap. Then I define anyLoggedIn in Boot.scala like so:

val anyLoggedIn  = If(() => !(Student.loggedIn_? || Provider.loggedIn_?), 
         if (sessionLoginType.is map {_ == StudentLogin} openOr false)
         {
          println("student")
          RedirectResponse("studentHome")

         }
         else 
         {
          println("provider")
          RedirectResponse("providerHome")
         }

I want to send providers and students to their "homes" respectively, when they try to access any login page when they are already logged in. For some reason, (maybe its my boolean logic), it never works, and I never make it to the redirects.

Any Ideas?

Thanks

+2  A: 

Common mistake with val is to define a variable after the use:

scala> object test {  
     | val f = x      
     | val x = 1      
     | }
defined module test

scala> println(test.f)
0

Which is pretty often mistake when working with Lift's SiteMap conditions (I personally tend to define them in the bottom). To overcome this, define your val as lazy:

scala> object test {  
     | val f = x      
     | lazy val x = 1 
     | }
defined module test

scala> println(test.f)
1

Side note

Your second test in If does not look too Scalaish, it's a mix of functional and procedural styles. There are options on how to write it, please see just one possible variant:

sessionLoginType.is match {
  case Full(StudentLogin) => 
    println("student")
    RedirectResponse("studentHome")
  case Full(ProviderLogin) =>
    println("provider")
    RedirectResponse("providerHome")
}

Another option

You can define a static map from login type to uri, e.g.

val redirectMap = Map(StudentLogin -> "studentHome", ProviderLogin -> "providerHome")

Then you can use it in your If like

sessionLoginType.is.flatMap{ redirectMap.get }.map{ RedirectResponse _ }.open_!

the same can be rewritten using for-comprehensions:

(for {val loginType <- sessionLoginType.is
      val uri <- redirectMap.get(loginType) }
      yield RedirectResponse(uri)
).open_!

But beware, if redirectMap does not contain a key or your sessionLoginType is empty, you are in trouble -- open_! will fail, as it should not be applied to empty boxes. If you know a reasonable default value, better use .openOr defaultRedirect

Alexander Azarov
Alexander -Thanks once again. I tried using both lazy and normal evaluations but thought the If()'s were executed each time upon access. Thanks for the heads up on that. Also the later stuff was mostly for debugging, but also thanks for the example of the static map, have never tried it, but looks good.
Also as an aside, when doing the case matching in lift using a box, you need to use Full (type) instead of Some () because it gets confused about the box v. option stuff
Oops.. sorry for the confusion. Some(x) is an Option[T], while Full(x) is Box[T] -- I'll correct the answer.
Alexander Azarov