durusmail: quixote-users: Re: Using _q_access? Any place for a _q_traverse?
Using _q_access? Any place for a _q_traverse?
2003-08-22
Re: Using _q_access? Any place for a _q_traverse?
2003-08-22
2003-08-22
Re: Using _q_access? Any place for a _q_traverse?
2003-08-22
2003-08-22
2003-08-23
2003-08-24
2003-08-24
2003-08-24
2003-08-24
2003-08-25
Re: Using _q_access? Any place for a _q_traverse?
Jason Sibre
2003-08-24
> Thank you for posting the code.  However, I note that you use the header
> to force the browser to pop up the username and password dialog.
> However, what I am trying to do is a little different -- I want an
> unauthorized user to always go to a web page with the login form.  That
> is what I am having trouble doing.  Do you know how to do that?
>
> Thanks,
>
> VanL

I'm not sure I completely followed your question in this chain, but what I
learned about this type of thing in quixote is that you can't issue
redirects during the traversal process.  Compared to some of the languages
I've worked with before that seemed odd, because it means that the code
that's checking for the error condition (be it a logged in user, a valid
report ID, etc) *isn't* the code that can produce the message, redirect, or
whatever.  Instead, you raise an exception which must be a subclass of the
PublishError or one of it's decendents, in this case, probably AccessError.
When the exception is raised, it busts processing out of the traversal
stage.  If the exception is an instance of PublishError (or it's children),
Quixote gives your application a chance to handle the exception, if it's
not, (for example a KeyError, or some other normal Python exception) Quixote
takes over, and handles the exception itself with a fairly generic
traceback, and then aborts processing of that request.  I guess the logic
there is that you (the developer) didn't anticipate that error, so you
probably don't have anything in place to correctly handle it.  So, after
raising the AccessError (or whatever) you then handle it in the appropriate
_q_exception_handler (i.e., issue the redirect).

/philosophy
This may seem kinda like a wasted step (you have to have a minimum of two
blocks of code to handle someone not logged in, for example), but it works
out well in the end.  You only have to raise the exception if you find a
condition that's not right, and know that another part will deal with that
exception.  In Quixote, it may help to think that exceptions aren't always
"exceptions," sometimes they're events, and those events can cause the
underlying quixote machinery to switch gears.
/philosophy end

Here's an example from one of my apps that uses a log in screen:
Hope this helps some,

Jason Sibre


#
# module to be protected has this function
#

def _q_access(request):
    requireLoggedIn(request)
    if not request.session.user.has_permission("play"):
        raise AccessError("You don't have access to these pages")


#
# in another module that provides utility functions you'll find
# these definitions
#

class NotLoggedInError (AccessError):
    pass

def requireLoggedIn(request):
    if request.session.user == None:
        raise NotLoggedInError, "You must be logged in"




#
# my app's root namespace (app/web/__init__.py) contains this:
#

def _q_exception_handler (request, exc):
    print "exception handler called: %s" % exc

    if isinstance(exc, NotLoggedInError):
        print "NotLoggedInError: %s" % request.get_path()
        #This make_goto function looks at the current URL, and
        #preservesthe user's attempted destination so they can
        #go there immediately after logging in.
        goto = make_goto(None, 1)
        return request.redirect(getRootedURL("login?" + goto))
    else:
        print "Unknown Error: %s" % request.get_path()
        res = htmltext("""
            
                
                    My Unhandled Exception Handler
                
                
                    

%s

%s

%s

%s """) % (exc.title, exc.description, exc.format(request), htmltext(request.dump_html())) print time.time(),res return res
reply