Menu access control not working as expected

41 views
Skip to first unread message

glenn

unread,
May 12, 2009, 7:54:36 PM5/12/09
to Lift
I have a menu defined as follows:

def quoteMenu:List[Menu] = {
val groupquote = Menu(Loc("groupquote", List("quote", "group"),
"Group Quote",loggedIn, LocGroup("quote")))
....More menu items
}

and an If LocParam to check if the user is logged in:

val loggedIn = If(() => User.loggedIn_?,
() => RedirectResponse("/login"))

When the sitemap is displayed, the menu item is not visible if the
user isn't logged in. This is not the behavior
expected. The user should be able to click on the menu item and be
redirected to the login page.

Any ideas as to what's going on here. Am I even using the right
mechanism to control page access?

Glenn...

David Pollak

unread,
May 12, 2009, 8:02:40 PM5/12/09
to lif...@googlegroups.com
If a top-level menu item is not accessible, then none of its children are accessible.  SiteMap does not display any pages that are inaccessible.

In the example, you've got all the menus controlled by the "loggedIn" If() clause and that's blocking access to menu and thus the menu is not displayed.
--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp

glenn

unread,
May 12, 2009, 8:23:16 PM5/12/09
to Lift
Hmm,

Here's my complete menu list for this LocGroup:

def quoteMenu:List[Menu] = {
val groupquote = Menu(Loc("groupquote", List("quote", "group"),
"Group Quote", LocGroup("quote"), loggedIn ))
val businessquote = Menu(Loc("businessquote", List("quote",
"business"), "Commercial Quote", LocGroup("quote")))
val lifequote = Menu(Loc("lifequote", List("quote", "life"),
"Life Ins. Quote", LocGroup("quote")))
val autoquote = Menu(Loc("autoquote", List("quote", "auto"),
"Auto Quote", LocGroup("quote")))
val homequote = Menu(Loc("homequote", List("quote", "home"),
"Homeowners Quote", LocGroup("quote")))
val medicarequote = Menu(Loc("medicarequote", List("quote",
"medicare"), "Medicare Sup. Quote", LocGroup("quote")))
List
(groupquote,businessquote,lifequote,autoquote,homequote,medicarequote)
}

I want to control page access so that whenever the user clicks on one
of the above menu items and isn't logged they are redirected to the
login page. As I understand it, there are no submenus here, only
siblings. Where would I put the loggedIn function to make this work?

On May 12, 5:02 pm, David Pollak <feeder.of.the.be...@gmail.com>
wrote:
> Beginning Scalahttp://www.apress.com/book/view/1430219890

David Pollak

unread,
May 13, 2009, 9:58:13 AM5/13/09
to lif...@googlegroups.com
Glenn,

I've added another Loc param:


  /**
   * Allows extra access testing for a given menu location such that
   * you can build a menu that is displayed but redirects the user to a login
   * page if they are not logged in
   */
  case class TestAccess(func: () => Box[LiftResponse]) extends LocParam

This will let you write a function that tests access for the page and return a RedirectResponse if the user needs to log in.  It will not impact the display of the menu item.

Hope this helps.

Thanks,

David
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890

glenn

unread,
May 13, 2009, 5:19:42 PM5/13/09
to Lift
David,

Pardon my ignorance, but I see a Test case class in the Lift 1.0 api
for Loc, but not TestAccess, which seems similar.

Glenn...

On May 13, 6:58 am, David Pollak <feeder.of.the.be...@gmail.com>
wrote:

David Pollak

unread,
May 13, 2009, 5:58:06 PM5/13/09
to lif...@googlegroups.com
On Wed, May 13, 2009 at 2:19 PM, glenn <gl...@exmbly.com> wrote:

David,

Pardon my ignorance, but I see a Test case class in the Lift 1.0 api
for Loc, but not TestAccess, which seems similar.

I added TestAccess to 1.1-SNAPSHOT last night.

It's possible to write something in 1.0, but it's a lot harder... basically, you have to write a Snippet and do a custom LocParam.

Most of us are on 1.1-SNAPSHOT and the sites I deploy are on 1.1-SNAPSHOT and there hasn't been an instability due to working on trunk-head that I've seen.




--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890

glenn

unread,
May 13, 2009, 6:30:17 PM5/13/09
to Lift
Thanks for the heads-up on the 1.1-SNAPSHOT version, but now, when I
compile,
I get errors. I don't think this has anything to do with menu
redirection, but, I have
a Company class defined like so:

class Company extends LongKeyedMapper[Company] with Address[Company]
with IdPK with CRUDify[Long,Company] {
...

}

And, this is what my compiler output tells me:

illegal inheritance; self-type com.exmbly.scala.apbul.model.Company
does not conform to net.liftweb.mapper.CRUDify
[Long,com.exmbly.scala.apbul.model.Company]'s
selftype net.liftweb.mapper.CRUDify
[Long,com.exmbly.scala.apbul.model.Company] with
com.exmbly.scala.apbul.model.Company with
net.liftweb.mapper.KeyedMetaMapper
[Long,com.exmbly.scala.apbul.model.Company]

Was something changed in the definition of Crudify? What do I need to
change in my code? The error is a bit confusing.

Glenn...

On May 13, 2:58 pm, David Pollak <feeder.of.the.be...@gmail.com>

David Pollak

unread,
May 13, 2009, 7:03:07 PM5/13/09
to lif...@googlegroups.com
On Wed, May 13, 2009 at 3:30 PM, glenn <gl...@exmbly.com> wrote:

Thanks for the heads-up on the 1.1-SNAPSHOT version, but now, when I
compile,
I get errors. I don't think this has anything to do with menu
redirection, but, I have
a Company class defined like so:

CRUDify should be mixed into the Meta object not into th instance class.  In this case, move CRUDify to object Company.

This was the original intent with CRUDify, but I did not put the proper constraints on it in 1.0... I fixed that up in 1.1.
 



--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890

glenn

unread,
May 13, 2009, 11:51:47 PM5/13/09
to Lift
David,


Moving CRUDify to the object fixed the compiler error. However, back
on the original menu issue, using TestAccess, as you suggest, still
did not work as expected. The menu item doesn't display. Maybe I'm
missing something important. Sorry to be a bother, but hope you can
help.

Here's my menu code:

def logged:Box[LiftResponse] = if(User.loggedIn_?){
Full(RedirectResponse("/Login"))
}else{
Full(PlainTextResponse("No such location"))
}

val testLogin = TestAccess(() => logged)


override def deleteMenuLoc = Empty
override def createMenuLoc: Box[Menu] =
Full(Menu(Loc("Create "+Prefix, createPath, "Continue...",
locSnippets, LocGroup("company"), testLogin,
Loc.Template(createTemplate))))



On May 13, 4:03 pm, David Pollak <feeder.of.the.be...@gmail.com>

David Pollak

unread,
May 14, 2009, 12:27:34 AM5/14/09
to lif...@googlegroups.com
Glenn,

Sorry... there was a bug in the code.  I've fixed it.  It'll be available when this build finishes:

Please remember to do an mvn -U clean install

I'm enclosing the sample app that I used to test.  Please note that you should only return Full(LiftResponse) if you want to redirect... not if you want to stay on the page.

Thanks,

David
Lift, the simply functional web framework http://liftweb.net
menu.tgz

glenn

unread,
May 14, 2009, 10:31:30 AM5/14/09
to Lift
David,

Your sample app works. Mine doesn't. I even put your sample Menu item
in
my app, but in it's own LocGroup, and it does not work. It seems the
only
difference is that I'm separating my menus into groups. Could that be
the
culprit?

Glenn...

On May 13, 9:27 pm, David Pollak <feeder.of.the.be...@gmail.com>
>  menu.tgz
> 7KViewDownload

glenn

unread,
May 14, 2009, 7:22:22 PM5/14/09
to Lift
David,

I changed default html in your menu example a bit and the results were
similar to using LocGroup -
the menu item won't display.

here's the change:

<div class="column span-6 colborder sidebar">
<hr class="space" />
<!-- <lift:Menu.builder />-->
<lift:Menu.item name="Fake">
<li>Fake Out</li>
</lift:Menu.item>
<div>
<lift:snippet type="msgs"/>
<hr class="space" />
</div>
</div>

It seems this only works if you stick to outputting the full menu in
your templates with <lift:Menu.builder/>.
Anything else and it's broken.

Glenn...

David Pollak

unread,
May 15, 2009, 9:54:34 AM5/15/09
to lif...@googlegroups.com
Glenn,

My original design was a bad one... I was mixing access control and early responses... I've split the concept of access control (which stays the way it is) and sending an early response (rather than going through the whole rendering pipeline).

With the latest spin of Lift, try putting this in Boot:

 // Build SiteMap
    val entries = Menu(Loc("Home", List("index"), "Home")) ::
    Menu(Loc("Fake", List("fakeout"), "Fake Out", Loc.EarlyResponse(
          () => Full(RedirectResponse("/user_mgt/login")).
                     filter(ignore => !User.loggedIn_?)
        ))) ::
    User.sitemap

Note that TestAccess became EarlyResponse.

Access control works the way it used to, but you can set the redirect before any other rendering happens.

Please let me know if this works.

Thanks,

David
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890

glenn

unread,
May 15, 2009, 10:49:33 AM5/15/09
to Lift
David,

Yes, your EarlyAccess Loc did the trick. Thank you for all
your help.

Glenn...

On May 15, 6:54 am, David Pollak <feeder.of.the.be...@gmail.com>
> ...
>
> read more »

David Pollak

unread,
May 15, 2009, 12:06:51 PM5/15/09
to lif...@googlegroups.com
On Fri, May 15, 2009 at 7:49 AM, glenn <gl...@exmbly.com> wrote:

David,

Yes, your EarlyAccess Loc did the trick. Thank you for all
your help.

Thanks for the great suggestion.

Party on!
 
Reply all
Reply to author
Forward
0 new messages