[Grok-dev] how to determine who is logged in?

Brandon Craig Rhodes brandon at rhodesmill.org
Thu Oct 11 00:16:24 EDT 2007


My weeks of staring at Grok and Zope 3 are finally resulting in a
small web app, but I was stopped this afternoon by the question: how
should my controller layer determine who is performing each action?
My app is structured like this (following recommendations both in
Design Patterns and in the PvW book):

  Content layer: some simple content components.

  Behavior layer: Adapters that offer methods for performing
     business-level operations on the content objects ("add one of
     these", "give this to that person", "remove one of those"), which
     often involve operating on several pieces of Content at once in a
     way that keeps them consistent with each other.

  View layer: my grok.Views, whose contexts are typically from the
     "Content" layer, but which, when a user hits a buttons or submits
     a form, adapt their context using a "Behavior" adapter so that
     they can perform actions upon it.

And so I am finding that, in the middle of Behavior code, I need to do
things like:

    def increase_quota(account, amount):
        fs = account.filesystem
        account.add_quota(amount)
        History.add('Admin %s has increased the %s quota by %f MB' %
                    (?admin?, account.username, amount)

You can see my problem!  I am not sure what to put for "?admin?"; I
don't know how, inside of application code, I'm supposed to determine
who is performing an action so that it can be properly logged.

How it this normally done?  Should the Controller "know" that it's
part of a Zope app and ask for zope.security to provide the current
interaction?  Or should Controllers be dumb and just trust the View to
pass in the admin, since the View has access to the request object?

My first instinct was to have the Controller know that it was inside
of Zope, and have it call a function like:

    from zope.security.management import getInteraction

    def get_current_admin():
        interaction = getInteraction()
        ids = [ p.principal.id for p in interaction.participations ]
        ...

But here we run into a second problem: needing CAS authentication, but
not seeing a Zope 3 module that can do so, I created a simple adapter
of my own that provides IAuthentication() as a local utility inside of
my grok.Application.  I had hoped that the presence of this utility
would make users appear in the current interaction fetched with
getInteraction() but, alas, no such magic occurs.  Even if I've done a
CAS login so that a principal is now available by calling up the
IAuthentication local utility and handing it the current request, the
list of principals returned by "interaction.participations" still
includes only users picked up at the top level of the ZODB (thus, only
admin users), not the users I'm CAS authenticating inside of my
grok.Application.

Thanks for any help!  Once I figure out this (and also how to use
skins and make my site pretty), I'll be ready to claim to my superiors
that they should let me start writing all sorts of things using Grok
and that it vastly increases my productivity.  (Right now, it just
results in my reading *lots* of Zope code, and the PvW book, and then
still not managing to get things exactly right.) ;-)

-- 
Brandon Craig Rhodes   brandon at rhodesmill.org   http://rhodesmill.org/brandon


More information about the Grok-dev mailing list