244 lines
7.7 KiB
Python
244 lines
7.7 KiB
Python
#
|
|
# Extensible User Folder
|
|
#
|
|
# (C) Copyright 2000,2001 The Internet (Aust) Pty Ltd
|
|
# ACN: 082 081 472 ABN: 83 082 081 472
|
|
# All Rights Reserved
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
# SUCH DAMAGE.
|
|
#
|
|
# Author: Andrew Milton <akm@theinternet.com.au>
|
|
# $Id: User.py,v 1.10 2004/12/14 05:30:29 akm Exp $
|
|
|
|
##############################################################################
|
|
#
|
|
# Zope Public License (ZPL) Version 0.9.4
|
|
# ---------------------------------------
|
|
#
|
|
# Copyright (c) Digital Creations. All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or
|
|
# without modification, are permitted provided that the following
|
|
# conditions are met:
|
|
#
|
|
# 1. Redistributions in source code must retain the above
|
|
# copyright notice, this list of conditions, and the following
|
|
# disclaimer.
|
|
#
|
|
# 6. Redistributions of any form whatsoever must retain the
|
|
# following acknowledgment:
|
|
#
|
|
# "This product includes software developed by Digital
|
|
# Creations for use in the Z Object Publishing Environment
|
|
# (http://www.zope.org/)."
|
|
#
|
|
# Disclaimer
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND
|
|
# ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
# SHALL DIGITAL CREATIONS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
|
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
# THE POSSIBILITY OF SUCH DAMAGE.
|
|
#
|
|
##############################################################################
|
|
from AccessControl.User import BasicUser
|
|
from string import join,strip,split,lower,upper,find
|
|
|
|
class XUFUser(BasicUser):
|
|
|
|
icon='misc_/exUserFolder/exUser.gif'
|
|
|
|
# cacheable is a dict that must contain at least name, password,
|
|
# roles, and domains -- unless you're working with your own User class,
|
|
# in which case you need to override __init__ and define it yourself.
|
|
def __init__(self, cacheable, propSource, cryptPassword, authSource,
|
|
groupSource=None):
|
|
self.name =cacheable['name']
|
|
self.__ =cacheable['password']
|
|
if cacheable['roles']:
|
|
self.roles = filter(None, cacheable['roles'])
|
|
else:
|
|
self.roles = []
|
|
# domains may be passed as a string or a list
|
|
if type(cacheable['domains']) == type(''):
|
|
self.domains=filter(None, map(strip,
|
|
split(cacheable['domains'], ',')))
|
|
else:
|
|
self.domains=cacheable['domains']
|
|
self._authSource=authSource
|
|
self._propSource=propSource
|
|
self._groupSource=groupSource
|
|
self.cryptPassword=cryptPassword
|
|
|
|
def getUserName(self):
|
|
return self.name
|
|
|
|
def _getPassword(self):
|
|
return self.__
|
|
|
|
def getRoles(self):
|
|
return tuple(self.roles) + ('Authenticated',)
|
|
|
|
def getDomains(self):
|
|
return self.domains
|
|
|
|
# Ultra generic way of getting, checking and setting properties
|
|
def getProperty(self, property, default=None):
|
|
if self._propSource:
|
|
return self._propSource.getUserProperty(property, self.name, default)
|
|
|
|
def hasProperty(self, property):
|
|
if self._propSource:
|
|
return self._propSource.hasProperty(property)
|
|
|
|
def setProperty(self, property, value):
|
|
if property[0]=='_':
|
|
return
|
|
if self._propSource:
|
|
return self._propSource.setUserProperty(property, self.name, value)
|
|
|
|
def setTempProperty(self, property, value):
|
|
if property[0]=='_':
|
|
return
|
|
if self._propSource:
|
|
return self._propSource.setTempProperty(property, value)
|
|
|
|
def flushTempProperties(self):
|
|
if self._propSource:
|
|
return self._propSource.flushTempProperties()
|
|
|
|
def delProperty(self, property):
|
|
if property[0]=='_':
|
|
return
|
|
if self._propSource:
|
|
return self._propSource.delUserProperty(property, self.name)
|
|
|
|
def listProperties(self):
|
|
if self._propSource:
|
|
return self._propSource.listUserProperties(self.name)
|
|
|
|
# Try to allow User['property'] -- won't work for password d;)
|
|
def __getitem__(self, key):
|
|
# Don't return 'private' keys
|
|
if key[0] != '_':
|
|
if hasattr(self, key):
|
|
return getattr(self, key)
|
|
if self._propSource and self._propSource.hasProperty(key):
|
|
|
|
return self._propSource.getUserProperty(key, self.name)
|
|
raise KeyError, key
|
|
|
|
def __setitem__(self, key, value):
|
|
if key[0]=='_':
|
|
return
|
|
if self._propSource:
|
|
self._propSource.setUserProperty(key, self.name, value)
|
|
|
|
# List one user is supplied by the Auth Source...
|
|
|
|
def authenticate(self, listOneUser, password, request, remoteAuth=None):
|
|
result=listOneUser(username=self.name)
|
|
for people in result:
|
|
if remoteAuth:
|
|
return remoteAuth(self.name, password)
|
|
else:
|
|
secret=self.cryptPassword(self.name, password)
|
|
return secret==people['password']
|
|
return None
|
|
|
|
# You can set logout times or whatever here if you want to, the
|
|
# property source is still active.
|
|
def notifyCacheRemoval(self):
|
|
if self._propSource:
|
|
self._propSource.flushTempProperties()
|
|
|
|
# You must override this and __init__ if you are subclassing
|
|
# the user object, or your user object may not be reconstructed
|
|
# properly! All values in this dict must be non-Persistent objects
|
|
# or types, and may not hold any references to Persistent objects,
|
|
# or the cache will break.
|
|
def _getCacheableDict(self):
|
|
return {'name': self.name,
|
|
'password': self.__,
|
|
'roles': self.roles,
|
|
'domains': self.domains}
|
|
|
|
def getGroups(self):
|
|
if self._groupSource:
|
|
return self._groupSource.getGroupsOfUser(self.name)
|
|
else:
|
|
return ()
|
|
|
|
|
|
def _setGroups(self, groupnames):
|
|
if self._groupSource:
|
|
return self._groupSource.setGroupsOfUser(groupnames, self.name)
|
|
|
|
|
|
def _addGroups(self, groupnames):
|
|
if self._groupSource:
|
|
return self._groupSource.addGroupsToUser(groupnames, self.name)
|
|
|
|
def _delGroups(self, groupnames):
|
|
if self._groupSource:
|
|
return self._groupSource.delGroupsFromUser(groupnames, self.name)
|
|
|
|
def getId(self):
|
|
if self._propSource and self._propSource.getUserProperty('userid', self.name):
|
|
return self._propSource.getUserProperty('userid', self.name)
|
|
return self.name
|
|
|
|
|
|
#
|
|
# An Anonymous User for session tracking...
|
|
# Can set and get properties just like a normal user.
|
|
#
|
|
# These objects live in the cache, so, we have a __del__ method to
|
|
# clean ourselves up.
|
|
#
|
|
|
|
class XUFAnonUser(XUFUser):
|
|
def __init__(self, name, roles, propSource):
|
|
self.name =name
|
|
self.__ =''
|
|
self.roles =filter(None, roles)
|
|
self._propSource=propSource
|
|
|
|
def getRoles(self):
|
|
return tuple(self.roles) + ('Anonymous',)
|
|
|
|
def authenticate(self, listOneUser, password, request, remoteAuth=None):
|
|
return 1
|
|
|
|
def notifyCacheRemoval(self):
|
|
if self._propSource:
|
|
self._propSource.deleteUsers([self.name,])
|
|
|
|
# We now set up a dummy classes so that people can extend the User objects
|
|
# or override stuff with much less pain --akm
|
|
|
|
class User(XUFUser):
|
|
pass
|
|
|
|
class AnonUser(XUFAnonUser):
|
|
pass
|
|
|