[Zope-PTK] Zope User Management API

Phillip J. Eby pje@telecommunity.com
Tue, 03 Oct 2000 09:45:58 -0500


At 01:48 PM 10/3/00 +0100, Chris Withers wrote:
>Bill Anderson wrote:
>> 
>> logout_User
>> Used to log the user out. Likely returns a redirect url.
>
>What about Basic Authentication?

FYI, LoginManager supports a logout protocol, although it doesn't currently
have a very useful implementation of logout for Basic Auth.  That's
overrideable, however.  Anyway, LoginManager keeps track of how a user is
logged in, and automatically calls back the same LoginMethod objects to log
them out.  The LoginUser class has a logout() method which activates this.
So AUTHENTICATED_USER.logout() will log out the current user, in an
implementation-independent way.


>> get_User
>> Used when you need the user object (useful or not?), and returns the
object itsself. (What about SQL-Authed Users?)
>
>SQL should return a wrapper object (ZPatterns DataSkin perhaps?)
>This probably will be useful, and it'd be great it this object could
>handle having data tacked onto it (like maybe propertysheets, etc)
>although this feels like a 'core Zope' thing, as I've already
>mentioned...

FWIW, LoginManager.getUser(name) does this, and LoginUsers are DataSkins.
So any data or behavior appropriate for the application can be "tacked on".

In general, however, I am suspicious of proposals to implement generic
collections of data as part of an object's interface.  This always sounds
to me like the kind of workaround that people do in languages like Java to
bypass strong typing, and it's thoroughly unnecessary in Python.

I made the big mistake a few years back of co-designing an SQL data model
that did objects in a generic way.  You could create arbitrary
associations, properties, hierarchies, inheritance...  you name it, this
data model does it.  I'm still supporting an application written with it.
It was great for quick prototyping and getting the app out the door.  But
it has sucked rocks in both performance *and* code clarity, compared to a
specifically designed data model for the application.  Worst, it has been
almost impossible to prevent implementation assumptions from creeping into
the application-level code.

It's also possible to see this kind of creep in the Zope core today,
through the use of generic data collections where methods or attributes
should have been used.  For example, "__ac_local_roles__" and the whole
local roles machinery as it exists today is purest
implementation-into-application creep.  Assumptions are made in various
parts of Zope that local roles are implemented using a dictionary which
contains all possible local roles for that object.  The "interface" that
was later created to replace direct access on __ac_local_roles__ was no
real help, because all it did was move the access into the object without
creating any actual abstraction.

I'd much prefer that no *new* creep of this kind occur, and IMHO one of the
best ways to stop it is to stamp out generic data collections tacked onto
objects for the benefit of other objects.  That is one reason why I've been
so active on the session tracking proposals - IMHO generic session objects
are evil, if they're the only kind you get to have.  I wanted to make sure
that session support got done in a way that allowed you to have
session-specific *objects*, rather than arbitrary bundles of data, which
might or might not be storable in the back-end you had in mind.  While
being able to put arbitrary data in a "session" object is convenient for a
quick-and-dirty hack, a robust application can and should create a class
for its specific kind of session-specific thing, with methods to do the
things that it does, and not pollute application code with managing the
session data.

In the same way, providing arbitrary properties on users as some kind of
interface to get and set them is a kludge, IMHO.  Zope already has a
perfectly good interface for property sheets and properties, let's just use
that.  It's even in the core already.  :)


>> get_UserPage
>> Used ot get the user's URL if any. In Community sites that implement a
Member Folder (such as PTKDemo), it would return
>> the URL to the User's Folder. In sites that don't it can return the URL
to their 'Profile Page' or whatever stands in
>> place (maybe a redirect or something). Returns a URL.
>
>Don't like this...

Me either.  This can be an app-specific method on the user object, OR, it
could be handled even more simply by using the user object's
absolute_url().  Thus, defining the index_html method on the user object
class can implement a redirect, profile page, or whatever.  Going to the
absolute_url plus /manage_workspace would pull up the user's management
tabs, per the Zope standard, and then you can have multiple views on the
user object.  This is the approach Ty and I currently take in our apps at
work.  They usually have an "Edit your profile" link that points to an
/acl_users/yourUserId/manage_edit method, while clicking on someone's name
displayed on a page just goes to /acl_users/theirUserId/ (index_html
implied), which in most of our apps is a redirect to our primary user
management application (which is in the same domain and shares the auth
cookie).

Of course, our "log out" links just go to a page in that application that
includes a call to AUTHENTICATED_USER.logout().


>> mail_UserPassword
>> Here is the tricky one, but only for what it returns. The UMP would do
the work, and should return a URL, or an actual
>> page fo rth euser to see.
>
>Don't like this...

Again, methinks this should be an app-specific method on the actual user
object, called by an application-level method at the "specialist" level.



The trickiest part of designing something like this is drawing the
distinction between what is part of the framework and what is just an
example implementation.  I think the "user's page" concept and "mail user
password" are both slightly over that line.  Many interesting (and
policy/context-dependent) implementations are possible, so whatever is done
as an example for them should be just that: an example.