forked from ScoDoc/DocScoDoc
1381 lines
44 KiB
Python
1381 lines
44 KiB
Python
# Zope User Folder for ScoDoc
|
|
# Adapte de l'Extensible User Folder
|
|
# simplifie pour les besoins de ScoDoc.
|
|
# Emmanuel Viennet 2013
|
|
|
|
#
|
|
# 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: exUserFolder.py,v 1.93 2004/11/10 14:15:33 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.
|
|
#
|
|
##############################################################################
|
|
|
|
# Portions Copyright (c) 2002 Nuxeo SARL <http://nuxeo.com>,
|
|
# Copyright (c) 2002 Florent Guillaume <mailto:fg@nuxeo.com>.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are
|
|
# met:
|
|
#
|
|
# 1. Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
#
|
|
# 2. Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in
|
|
# the documentation and/or other materials provided with the
|
|
# distribution.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
|
|
# OWNER 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.
|
|
|
|
import Globals, App.Undo, socket, os, string, sha, random, sys, zLOG
|
|
|
|
from Globals import DTMLFile, PersistentMapping
|
|
from string import join,strip,split,lower,upper,find
|
|
|
|
from OFS.Folder import Folder
|
|
from OFS.CopySupport import CopyContainer
|
|
|
|
from base64 import decodestring, encodestring
|
|
from urllib import quote, unquote
|
|
|
|
from Acquisition import aq_base
|
|
from AccessControl import ClassSecurityInfo
|
|
from AccessControl.Role import RoleManager
|
|
from AccessControl.User import BasicUser, BasicUserFolder, readUserAccessFile
|
|
from AccessControl.PermissionRole import PermissionRole
|
|
from AccessControl.ZopeSecurityPolicy import _noroles
|
|
from OFS.DTMLMethod import DTMLMethod
|
|
from time import time
|
|
from OFS.ObjectManager import REPLACEABLE
|
|
from Persistence import Persistent
|
|
|
|
from PropertyEditor import *
|
|
|
|
from User import User, AnonUser
|
|
from UserCache.UserCache import GlobalUserCache, GlobalNegativeUserCache, GlobalAdvancedCookieCache, SessionExpiredException
|
|
|
|
from LoginRequiredMessages import LoginRequiredMessages
|
|
|
|
from AccessControl import Unauthorized
|
|
|
|
class LoginRequired(Exception):
|
|
"""Login required"""
|
|
pass
|
|
|
|
|
|
# If there is no NUG Product just define a dummy class
|
|
try:
|
|
from Products.NuxUserGroups.UserFolderWithGroups import BasicGroupFolderMixin, _marker
|
|
except ImportError:
|
|
class BasicGroupFolderMixin:
|
|
pass
|
|
_marker = None
|
|
|
|
# Little function to create temp usernames
|
|
def createTempName():
|
|
t=time()
|
|
t1=time()
|
|
t2=time()
|
|
t3 = 0.0
|
|
t3 = (t + t1 + t2) / 3
|
|
un = "Anonymous %.0f"%(t3)
|
|
return(un)
|
|
|
|
|
|
manage_addexUserFolderForm=DTMLFile('dtml/manage_addexUserFolder', globals(), __name__='manage_addexUserFolderForm')
|
|
|
|
|
|
|
|
def manage_addexUserFolder(self, authId, propId, memberId,
|
|
cookie_mode=0, session_length=0,
|
|
not_session_length=0,
|
|
sessionTracking=None, idleTimeout=None,
|
|
REQUEST={}, groupId=None, cryptoId=None):
|
|
""" """
|
|
if hasattr(self.aq_base, 'acl_users'):
|
|
return Globals.MessageDialog(self,REQUEST,
|
|
title ='Item Exists',
|
|
message='This object already contains a User Folder',
|
|
action ='%s/manage_main' % REQUEST['URL1'])
|
|
ob=exUserFolder(authId, propId, memberId, groupId, cryptoId, cookie_mode,
|
|
session_length, sessionTracking, idleTimeout,
|
|
not_session_length)
|
|
|
|
self._setObject('acl_users', ob, None, None, 0)
|
|
self.__allow_groups__=self.acl_users
|
|
ob=getattr(self, 'acl_users')
|
|
ob.postInitialisation(REQUEST)
|
|
|
|
if REQUEST:
|
|
return self.manage_main(self, REQUEST)
|
|
return ''
|
|
|
|
#
|
|
# Module level caches
|
|
#
|
|
XUFUserCache=GlobalUserCache()
|
|
XUFNotUserCache=GlobalNegativeUserCache()
|
|
XUFCookieCache=GlobalAdvancedCookieCache()
|
|
|
|
class exUserFolder(Folder,BasicUserFolder,BasicGroupFolderMixin,
|
|
CopyContainer):
|
|
""" """
|
|
|
|
# HACK! We use this meta_type internally so we can be pasted into
|
|
# the root. We registered with 'exUserFolder' meta_type however, so
|
|
# our constructors work.
|
|
meta_type='User Folder'
|
|
id ='acl_users'
|
|
title ='Extensible User Folder'
|
|
icon ='misc_/exUserFolder/exUserFolder.gif'
|
|
|
|
isPrincipiaFolderish=1
|
|
isAUserFolder=1
|
|
__allow_access_to_unprotected_subobjects__=1
|
|
authSources={}
|
|
propSources={}
|
|
cryptoSources={}
|
|
membershipSources={}
|
|
groupSources={} # UNUSED by ScoDoc
|
|
|
|
manage_options=(
|
|
{'label':'Users', 'action':'manage_main'},
|
|
{'label':'Groups', 'action':'manage_userGroups'},
|
|
{'label':'Parameters', 'action':'manage_editexUserFolderForm'},
|
|
{'label':'Authentication Source','action':'manage_editAuthSourceForm'},
|
|
{'label':'Properties Source','action':'manage_editPropSourceForm'},
|
|
{'label':'Membership Source', 'action':'manage_editMembershipSourceForm'},
|
|
{'label':'Cache Data', 'action':'manage_showCacheData'},
|
|
{'label':'Security', 'action':'manage_access'},
|
|
{'label':'Contents', 'action':'manage_contents'},
|
|
{'label':'Ownership', 'action':'manage_owner'},
|
|
{'label':'Undo', 'action':'manage_UndoForm'},
|
|
)
|
|
|
|
__ac_permissions__=(
|
|
('View management screens', ('manage','manage_menu','manage_main',
|
|
'manage_copyright', 'manage_tabs',
|
|
'manage_properties', 'manage_UndoForm',
|
|
'manage_edit', 'manage_contents',
|
|
'manage_cutObjects','manage_copyObjects',
|
|
'manage_pasteObjects',
|
|
'manage_renameForm',
|
|
'manage_renameObject',
|
|
'manage_renameObjects', ),
|
|
('Manager',)),
|
|
|
|
('Undo changes', ('manage_undo_transactions',),
|
|
('Manager',)),
|
|
|
|
('Change permissions', ('manage_access',),
|
|
('Manager',)),
|
|
|
|
('Manage users', ('manage_users', 'manage_editUserForm',
|
|
'manage_editUser', 'manage_addUserForm',
|
|
'manage_addUser', 'manage_userActions',
|
|
'userFolderAddGroup',
|
|
'userFolderDelGroups',
|
|
'getGroupNames',
|
|
'getGroupById',
|
|
'manage_userGroups',
|
|
'manage_addGroup',
|
|
'manage_showGroup',),
|
|
('Manager',)),
|
|
|
|
('Change exUser Folders', ('manage_edit',),
|
|
('Manager',)),
|
|
|
|
('View', ('manage_changePassword',
|
|
'manage_forgotPassword','docLoginRedirect',
|
|
'logout', 'DialogHeader',
|
|
'DialogFooter', 'manage_signupUser',
|
|
'MessageDialog', 'redirectToLogin','manage_changeProps'),
|
|
('Anonymous', 'Authenticated', 'Manager')),
|
|
|
|
('Manage properties', ('manage_addProperty',
|
|
'manage_editProperties',
|
|
'manage_delProperties',
|
|
'manage_changeProperties',
|
|
'manage_propertiesForm',
|
|
'manage_propertyTypeForm',
|
|
'manage_changePropertyTypes',
|
|
),
|
|
('Manager',)),
|
|
('Access contents information', ('hasProperty', 'propertyIds',
|
|
'propertyValues','propertyItems',
|
|
'getProperty', 'getPropertyType',
|
|
'propertyMap', 'docLoginRedirect',
|
|
'DialogHeader', 'DialogFooter',
|
|
'MessageDialog', 'redirectToLogin',),
|
|
('Anonymous', 'Authenticated', 'Manager')),
|
|
)
|
|
manage_access=DTMLFile('dtml/access',globals())
|
|
manage_tabs=DTMLFile('common/manage_tabs',globals())
|
|
manage_properties=DTMLFile('dtml/properties', globals())
|
|
manage_main=DTMLFile('dtml/mainUser', globals())
|
|
manage_contents=Folder.manage_main
|
|
manage_showCacheData=DTMLFile('dtml/manage_showCacheData', globals())
|
|
|
|
# This is going away soon...
|
|
docLoginRedirect=DTMLFile('dtml/docLoginRedirect', globals())
|
|
|
|
# Stupid crap
|
|
try:
|
|
manage_contents._setName('manage_contents')
|
|
except AttributeError:
|
|
pass
|
|
|
|
|
|
MessageDialog=DTMLFile('common/MessageDialog', globals())
|
|
MessageDialog.__replaceable__ = REPLACEABLE
|
|
|
|
manage_addUserForm=DTMLFile('dtml/manage_addUserForm',globals())
|
|
manage_editUserForm=DTMLFile('dtml/manage_editUserForm',globals())
|
|
|
|
DialogHeader__roles__=()
|
|
DialogHeader=DTMLFile('common/DialogHeader',globals())
|
|
DialogFooter__roles__=()
|
|
DialogFooter=DTMLFile('common/DialogFooter',globals())
|
|
|
|
manage_editAuthSourceForm=DTMLFile('dtml/manage_editAuthSourceForm',globals())
|
|
manage_editPropSourceForm=DTMLFile('dtml/manage_editPropSourceForm',globals())
|
|
manage_editMembershipSourceForm=DTMLFile('dtml/manage_editMembershipSourceForm', globals())
|
|
|
|
manage_addPropertyForm=DTMLFile('dtml/manage_addPropertyForm', globals())
|
|
manage_createPropertyForm=DTMLFile('dtml/manage_createPropertyForm', globals())
|
|
manage_editUserPropertyForm=DTMLFile('dtml/manage_editUserPropertyForm', globals())
|
|
|
|
manage_editexUserFolderForm=DTMLFile('dtml/manage_editexUserFolderForm', globals())
|
|
|
|
manage_userGroups=DTMLFile('dtml/mainGroup',globals())
|
|
|
|
|
|
# Use pages from NUG if it's there, otherwise no group support
|
|
try:
|
|
manage_addGroup = BasicGroupFolderMixin.manage_addGroup
|
|
manage_showGroup = BasicGroupFolderMixin.manage_showGroup
|
|
except:
|
|
manage_addGroup = None
|
|
manage_showGroup = None
|
|
|
|
# No more class globals
|
|
|
|
# sessionLength=0 # Upgrading users should get no caching.
|
|
# notSessionLength=0 # bad cache limit
|
|
# cookie_mode=0
|
|
# sessionTracking=None # Or session tracking.
|
|
# idleTimeout=0
|
|
|
|
def __init__(self, authId, propId, memberId, groupId, cryptoId,
|
|
cookie_mode=0, session_length=0, sessionTracking=None,
|
|
idleTimeout=0, not_session_length=0):
|
|
self.cookie_mode=cookie_mode
|
|
self.sessionLength=session_length
|
|
self.notSessionLength=not_session_length
|
|
self.sessionTracking=sessionTracking
|
|
self.idleTimeout=idleTimeout
|
|
|
|
_docLogin=DTMLFile('dtml/docLogin',globals())
|
|
_docLogout=DTMLFile('dtml/docLogout',globals())
|
|
|
|
docLogin=DTMLMethod(__name__='docLogin')
|
|
docLogin.manage_edit(data=_docLogin, title='Login Page')
|
|
self._setObject('docLogin', docLogin, None, None, 0)
|
|
|
|
docLogout=DTMLMethod(__name__='docLogout')
|
|
docLogout.manage_edit(data=_docLogout, title='Logout Page')
|
|
self._setObject('docLogout', docLogout, None, None, 0)
|
|
|
|
postUserCreate=DTMLMethod(__name__='postUserCreate')
|
|
postUserCreate.manage_edit(data=_postUserCreate, title='Post User Creation methods')
|
|
self._setObject('postUserCreate', postUserCreate, None, None, 0)
|
|
|
|
self.manage_addAuthSource=self.authSources[authId].manage_addMethod
|
|
self.manage_addPropSource=self.propSources[propId].manage_addMethod
|
|
self.manage_addMembershipSource=self.membershipSources[memberId].manage_addMethod
|
|
|
|
self.manage_addGroupSource=None # UNUSED by ScoDoc
|
|
self.currentGroupsSource=None
|
|
|
|
if cryptoId:
|
|
self.cryptoId = cryptoId
|
|
else:
|
|
self.cryptoId = 'Crypt'
|
|
|
|
def __setstate__(self, state):
|
|
Persistent.__setstate__(self, state)
|
|
if not hasattr(self, 'currentGroupSource'):
|
|
self.currentGroupSource = None
|
|
if not hasattr(self, 'sessionLength'):
|
|
self.sessionLength = 0
|
|
if not hasattr(self, 'notSessionLength'):
|
|
self.notSessionLength = 0
|
|
if not hasattr(self, 'cookie_mode'):
|
|
self.cookie_mode = 0
|
|
if not hasattr(self, 'sessionTraining'):
|
|
self.sessionTracking = None
|
|
if not hasattr(self, 'idleTimeout'):
|
|
self.idleTimeout=0
|
|
|
|
def manage_beforeDelete(self, item, container):
|
|
zLOG.LOG("exUserFolder", zLOG.BLATHER, "Attempting to delete an exUserFolder instance")
|
|
if item is self:
|
|
try:
|
|
self.cache_deleteCache()
|
|
self.xcache_deleteCache()
|
|
zLOG.LOG("exUserFolder", zLOG.BLATHER, "-- Caches deleted")
|
|
except:
|
|
#pass
|
|
zLOG.LOG("exUserFolder", zLOG.BLATHER, "-- Cache deletion failed")
|
|
|
|
try:
|
|
del container.__allow_groups__
|
|
zLOG.LOG("exUserFolder", zLOG.BLATHER, "-- container.__allow_groups_ deleted")
|
|
except:
|
|
#pass
|
|
zLOG.LOG("exUserFolder", zLOG.BLATHER, "-- container.__allow_groups_ deletion failed")
|
|
|
|
|
|
def manage_afterAdd(self, item, container):
|
|
zLOG.LOG("exUserFolder", zLOG.BLATHER, "Adding an exUserFolder")
|
|
|
|
if item is self:
|
|
if hasattr(self, 'aq_base'): self=self.aq_base
|
|
container.__allow_groups__=self
|
|
|
|
def manage_editPropSource(self, REQUEST):
|
|
""" Edit Prop Source """
|
|
if self.currentPropSource:
|
|
self.currentPropSource.manage_editPropSource(REQUEST)
|
|
return self.manage_main(self, REQUEST)
|
|
|
|
def manage_editAuthSource(self, REQUEST):
|
|
""" Edit Auth Source """
|
|
self.currentAuthSource.manage_editAuthSource(REQUEST)
|
|
return self.manage_main(self, REQUEST)
|
|
|
|
def manage_editMembershipSource(self, REQUEST):
|
|
""" Edit Membership Source """
|
|
if self.currentMembershipSource:
|
|
return self.currentMembershipSource.manage_editMembershipSource(REQUEST)
|
|
|
|
def postInitialisation(self, REQUEST):
|
|
self.manage_addAuthSource(self=self,REQUEST=REQUEST)
|
|
self.manage_addPropSource(self=self,REQUEST=REQUEST)
|
|
self.manage_addMembershipSource(self=self,REQUEST=REQUEST)
|
|
self.currentGroupSource = None
|
|
|
|
def addAuthSource(self, REQUEST={}):
|
|
return self.manage_addAuthSourceForm(self, REQUEST)
|
|
|
|
def addPropSource(self, REQUEST={}):
|
|
return self.manage_addPropSourceForm(self, REQUEST)
|
|
|
|
def addMembershipSource(self, REQUEST={}):
|
|
return self.manage_editMembershipSourceForm(self, REQUEST)
|
|
|
|
def listUserProperties(self, username):
|
|
if self.currentPropSource:
|
|
return self.currentPropSource.listUserProperties(username=username)
|
|
|
|
def getUserProperty(self, username, key):
|
|
if self.currentPropSource:
|
|
return self.currentPropSource.getUserProperty(key=key, username=username)
|
|
|
|
def reqattr(self, request, attr, default=None):
|
|
try: return request[attr]
|
|
except: return default
|
|
|
|
def getAuthFailedMessage(self, code):
|
|
""" Return a code """
|
|
if LoginRequiredMessages.has_key(code):
|
|
return LoginRequiredMessages[code]
|
|
return 'Login Required'
|
|
|
|
# Called when we are deleted
|
|
def cache_deleteCache(self):
|
|
pp = string.join(self.getPhysicalPath(), '/')
|
|
XUFUserCache.deleteCache(pp)
|
|
|
|
def cache_addToCache(self, username, password, user):
|
|
if not self.sessionLength:
|
|
return
|
|
# fix by emmanuel
|
|
if username == self._emergency_user.getUserName():
|
|
return
|
|
# /fix
|
|
pp = string.join(self.getPhysicalPath(), '/')
|
|
x = XUFUserCache.getCache(pp)
|
|
if not x:
|
|
x = XUFUserCache.createCache(pp, self.sessionLength)
|
|
x.addToCache(username, password, user)
|
|
|
|
def cache_getUser(self, username, password, checkpassword=1):
|
|
if not self.sessionLength:
|
|
return None
|
|
pp = string.join(self.getPhysicalPath(), '/')
|
|
x = XUFUserCache.getCache(pp)
|
|
if not x:
|
|
return None
|
|
u = x.getUser(self, username, password, checkpassword)
|
|
if u is not None:
|
|
u = u.__of__(self)
|
|
return u
|
|
|
|
def cache_removeUser(self, username):
|
|
if not self.sessionLength:
|
|
return
|
|
pp = string.join(self.getPhysicalPath(), '/')
|
|
x = XUFUserCache.getCache(pp)
|
|
if x:
|
|
x.removeUser(username)
|
|
|
|
def cache_getCacheStats(self):
|
|
pp = string.join(self.getPhysicalPath(), '/')
|
|
x = XUFUserCache.getCache(pp)
|
|
if not x:
|
|
x = XUFUserCache.createCache(pp, self.sessionLength)
|
|
if x:
|
|
return x.getCacheStats()
|
|
|
|
def cache_getCurrentUsers(self):
|
|
pp = string.join(self.getPhysicalPath(), '/')
|
|
x = XUFUserCache.getCache(pp)
|
|
if x:
|
|
return x.getCurrentUsers(self)
|
|
|
|
# negative cache functions
|
|
def xcache_deleteCache(self):
|
|
pp = string.join(self.getPhysicalPath(), '/')
|
|
XUFNotUserCache.deleteCache(pp)
|
|
|
|
def xcache_addToCache(self, username):
|
|
if not self.notSessionLength:
|
|
return
|
|
pp = string.join(self.getPhysicalPath(), '/')
|
|
x = XUFNotUserCache.getCache(pp)
|
|
if not x:
|
|
x = XUFNotUserCache.createCache(pp, self.notSessionLength)
|
|
x.addToCache(username)
|
|
|
|
def xcache_getUser(self, username):
|
|
if not self.notSessionLength:
|
|
return None
|
|
pp = string.join(self.getPhysicalPath(), '/')
|
|
x = XUFNotUserCache.getCache(pp)
|
|
if not x:
|
|
return None
|
|
return x.getUser(username)
|
|
|
|
def xcache_removeUser(self, username):
|
|
#zLOG.LOG('exUserFolder', zLOG.PANIC, 'xcache_removeUser(%s)' % username)
|
|
if not self.notSessionLength:
|
|
return
|
|
pp = string.join(self.getPhysicalPath(), '/')
|
|
x = XUFNotUserCache.getCache(pp)
|
|
if x:
|
|
#zLOG.LOG('exUserFolder', zLOG.PANIC, 'xcache_removeUser removing')
|
|
x.removeUser(username)
|
|
|
|
# Cookie Cache Functions
|
|
def cache_deleteCookieCache(self):
|
|
pp = string.join(self.getPhysicalPath(), '/')
|
|
XUFCookieCache.deleteCache(pp)
|
|
|
|
def cache_addToCookieCache(self, username, password, key):
|
|
pp = string.join(self.getPhysicalPath(), '/')
|
|
c = XUFCookieCache.getCache(pp)
|
|
if not c:
|
|
c = XUFCookieCache.createCache(pp, 86400)
|
|
c.addToCache(username, password, key)
|
|
|
|
def cache_getCookieCacheUser(self, key):
|
|
pp = string.join(self.getPhysicalPath(), '/')
|
|
c = XUFCookieCache.getCache(pp)
|
|
if not c:
|
|
return None
|
|
return c.getUser(key)
|
|
|
|
def cache_removeCookieCacheUser(self, key):
|
|
pp = string.join(self.getPhysicalPath(), '/')
|
|
c = XUFCookieCache.getCache(pp)
|
|
if c:
|
|
c.removeUser(key)
|
|
|
|
def manage_editUser(self, username, REQUEST={}): # UNUSED by ScoDoc
|
|
""" Edit a User """
|
|
# username=self.reqattr(REQUEST,'username')
|
|
password=self.reqattr(REQUEST,'password')
|
|
password_confirm=self.reqattr(REQUEST,'password_confirm')
|
|
roles=self.reqattr(REQUEST,'roles', [])
|
|
groups=self.reqattr(REQUEST, 'groupnames', [])
|
|
|
|
if not username:
|
|
return self.MessageDialog(self,REQUEST=REQUEST,
|
|
title ='Illegal value',
|
|
message='A username must be specified',
|
|
action ='manage_main')
|
|
|
|
if (password or password_confirm) and (password != password_confirm):
|
|
return self.MessageDialog(self,REQUEST=REQUEST,
|
|
title ='Illegal value',
|
|
message='Password and confirmation do not match',
|
|
action ='manage_main')
|
|
|
|
self._doChangeUser(username, password, roles, domains='', groups=groups, REQUEST=REQUEST)
|
|
|
|
return self.MessageDialog(self,REQUEST=REQUEST,
|
|
title = 'User Updated',
|
|
message= 'User %s was updated.'%(username),
|
|
action = 'manage_main')
|
|
|
|
|
|
# Methode special pour ScoDoc: evite le code inutile dans notre contexte
|
|
# et accede a la BD via le curseur psycopg2 fourni
|
|
# (facilitera la separation de Zope)
|
|
def scodoc_editUser(self, cursor, username, password=None, roles=[]):
|
|
"""Edit a ScoDoc user"""
|
|
roles = list(roles)
|
|
rolestring= ','.join(roles)
|
|
# Don't change passwords if it's null
|
|
if password:
|
|
secret=self.cryptPassword(username, password)
|
|
# Update just the password:
|
|
# self.sqlUpdateUserPassword(username=username, password=secret)
|
|
cursor.execute("UPDATE sco_users SET passwd=%(secret)s WHERE user_name=%(username)s",
|
|
{ 'secret':secret, 'username': username } )
|
|
|
|
#self.sqlUpdateUser(username=username, roles=rolestring)
|
|
cursor.execute("UPDATE sco_users SET roles=%(rolestring)s WHERE user_name=%(username)s",
|
|
{ 'rolestring':rolestring, 'username': username } )
|
|
|
|
if hasattr(self.currentAuthSource, '_v_lastUser'):
|
|
# Specific for pgAuthSource:
|
|
self.currentAuthSource._v_lastUser={} # clear pg user cache
|
|
|
|
# We may have updated roles or passwords... flush the user...
|
|
self.cache_removeUser(username)
|
|
self.xcache_removeUser(username)
|
|
|
|
#
|
|
# Membership helper
|
|
#
|
|
def goHome(self, REQUEST, RESPONSE):
|
|
""" Go to home directory """
|
|
if self.currentMembershipSource:
|
|
self.currentMembershipSource.goHome(REQUEST, RESPONSE)
|
|
|
|
|
|
#
|
|
# Membership method of changing user properties
|
|
#
|
|
|
|
def manage_changeProps(self, REQUEST):
|
|
""" Change Properties """
|
|
if self.currentMembershipSource:
|
|
return self.currentMembershipSource.changeProperties(REQUEST)
|
|
else:
|
|
|
|
return self.MessageDialog(self,REQUEST,
|
|
title = 'This is a test',
|
|
message= 'This was a test',
|
|
action = '..')
|
|
|
|
|
|
#
|
|
# Membership method of adding a new user.
|
|
# If everything goes well the membership plugin calls manage_addUser()
|
|
#
|
|
|
|
def manage_signupUser(self, REQUEST):
|
|
""" Signup a new user """
|
|
""" This is seperate so you can add users using the normal """
|
|
""" interface w/o going through membership policy """
|
|
|
|
username=self.reqattr(REQUEST,'username')
|
|
roles=self.reqattr(REQUEST,'roles')
|
|
|
|
if not username:
|
|
return self.MessageDialog(self,REQUEST=REQUEST,
|
|
title ='Illegal value',
|
|
message='A username must be specified',
|
|
action ='manage_main')
|
|
|
|
if (self.getUser(username) or
|
|
(self._emergency_user and
|
|
username == self._emergency_user.getUserName())):
|
|
return self.MessageDialog(self,REQUEST=REQUEST,
|
|
title ='Illegal value',
|
|
message='A user with the specified name already exists',
|
|
action ='manage_main')
|
|
|
|
if self.currentMembershipSource:
|
|
return self.currentMembershipSource.createUser(REQUEST)
|
|
|
|
#
|
|
# Membership method of changing passwords
|
|
#
|
|
def manage_changePassword(self, REQUEST):
|
|
""" Change a password """
|
|
if self.currentMembershipSource:
|
|
return self.currentMembershipSource.changePassword(REQUEST)
|
|
|
|
#
|
|
# User says they can't remember their password
|
|
#
|
|
def manage_forgotPassword(self, REQUEST):
|
|
""" So something about forgetting your password """
|
|
if self.currentMembershipSource:
|
|
return self.currentMembershipSource.forgotPassword(REQUEST)
|
|
|
|
def __creatable_by_emergency_user__(self): return 1
|
|
|
|
def manage_addUser(self, REQUEST):
|
|
""" Add a New User """
|
|
username=self.reqattr(REQUEST,'username')
|
|
password=self.reqattr(REQUEST,'password')
|
|
password_confirm=self.reqattr(REQUEST,'password_confirm')
|
|
roles=self.reqattr(REQUEST,'roles')
|
|
groups=self.reqattr(REQUEST, 'groupnames', [])
|
|
|
|
if not username:
|
|
return self.MessageDialog(self,REQUEST=REQUEST,
|
|
title ='Illegal value',
|
|
message='A username must be specified',
|
|
action ='manage_main')
|
|
|
|
if not password or not password_confirm:
|
|
return self.MessageDialog(self,REQUEST=REQUEST,
|
|
title ='Illegal value',
|
|
message='Password and confirmation must be specified',
|
|
action ='manage_main')
|
|
|
|
if (self.getUser(username) or
|
|
(self._emergency_user and
|
|
username == self._emergency_user.getUserName())):
|
|
return self.MessageDialog(self,REQUEST=REQUEST,
|
|
title ='Illegal value',
|
|
message='A user with the specified name already exists',
|
|
action ='manage_main')
|
|
|
|
if (password or password_confirm) and (password != password_confirm):
|
|
return self.MessageDialog(self,REQUEST=REQUEST,
|
|
title ='Illegal value',
|
|
message='Password and confirmation do not match',
|
|
action ='manage_main')
|
|
|
|
self._doAddUser(username, password, roles, domains='', groups=groups, REQUEST=REQUEST)
|
|
#
|
|
# Explicitly check our contents, do not just acquire postUserCreate
|
|
#
|
|
if 'postUserCreate' in self.objectIds():
|
|
self.postUserCreate(self, REQUEST)
|
|
|
|
return self.MessageDialog(self,REQUEST=REQUEST,
|
|
title = 'User Created',
|
|
message= 'User %s was created.'%(username),
|
|
action = 'manage_main')
|
|
|
|
def _doAddUser(self, name, password, roles, domains='', groups=(), **kw):
|
|
""" For programatically adding simple users """
|
|
self.currentAuthSource.createUser(name, password, roles)
|
|
if self.currentPropSource:
|
|
# copy items not in kw from REQUEST
|
|
REQUEST = kw.get('REQUEST', self.REQUEST)
|
|
map(kw.setdefault, REQUEST.keys(), REQUEST.values())
|
|
self.currentPropSource.createUser(name, kw)
|
|
|
|
def _doChangeUser(self, name, password, roles, domains='', groups=(), **kw):
|
|
self.currentAuthSource.updateUser(name, password, roles)
|
|
if self.currentPropSource:
|
|
# copy items not in kw from REQUEST
|
|
REQUEST = kw.get('REQUEST', self.REQUEST)
|
|
map(kw.setdefault, REQUEST.keys(), REQUEST.values())
|
|
self.currentPropSource.updateUser(name, kw)
|
|
# We may have updated roles or passwords... flush the user...
|
|
self.cache_removeUser(name)
|
|
self.xcache_removeUser(name)
|
|
|
|
def _doDelUsers(self, names):
|
|
self.deleteUsers(names)
|
|
|
|
def _createInitialUser(self):
|
|
if len(self.getUserNames()) <= 1:
|
|
info = readUserAccessFile('inituser')
|
|
if info:
|
|
name, password, domains, remote_user_mode = info
|
|
self._doAddUser(name, password, ('Manager',), domains)
|
|
|
|
|
|
def getUsers(self):
|
|
"""Return a list of user objects or [] if no users exist"""
|
|
data=[]
|
|
try:
|
|
items=self.listUsers()
|
|
for people in items:
|
|
user=User({'name': people['username'],
|
|
'password': people['password'],
|
|
'roles': people['roles'],
|
|
'domains': ''},
|
|
self.currentPropSource,
|
|
self.cryptPassword,
|
|
self.currentAuthSource,
|
|
self.currentGroupSource)
|
|
data.append(user)
|
|
except:
|
|
import traceback
|
|
traceback.print_exc()
|
|
pass
|
|
|
|
return data
|
|
|
|
getUsers__roles__=('Anonymous','Authenticated')
|
|
|
|
def getUser(self, name):
|
|
"""Return the named user object or None if no such user exists"""
|
|
user = self.cache_getUser(name, '', 0)
|
|
#zLOG.LOG('exUserFolder.getUser', zLOG.PANIC, 'cache_getUser(%s)=%s' % (name,user))
|
|
if user:
|
|
return user
|
|
try:
|
|
items=self.listOneUser(name)
|
|
#zLOG.LOG('exUserFolder.getUser', zLOG.PANIC, 'listOneUser=%s' % items)
|
|
except:
|
|
zLOG.LOG("exUserFolder", zLOG.ERROR,
|
|
"error trying to list user %s" % name,
|
|
'',
|
|
sys.exc_info())
|
|
return None
|
|
|
|
if not items:
|
|
return None
|
|
|
|
for people in items:
|
|
user = User({'name': people['username'],
|
|
'password':people['password'],
|
|
'roles': people['roles'],
|
|
'domains': ''},
|
|
self.currentPropSource,
|
|
self.cryptPassword,
|
|
self.currentAuthSource,
|
|
self.currentGroupSource)
|
|
return user
|
|
return None
|
|
|
|
def manage_userActions(self, submit=None, userids=None, REQUEST={}):
|
|
""" Do things to users """
|
|
if submit==' Add ':
|
|
if hasattr(self.currentAuthSource,'manage_addUserForm'):
|
|
return self.currentAuthSource.manage_addUserForm(self, REQUEST)
|
|
else:
|
|
return self.manage_addUserForm(self, REQUEST)
|
|
if submit==' Delete ':
|
|
self.deleteUsers(userids)
|
|
return self.MessageDialog(self,REQUEST=REQUEST,
|
|
title ='Users Deleted',
|
|
message='Selected Users have been deleted',
|
|
action =REQUEST['URL1']+'/manage_main',
|
|
target ='manage_main')
|
|
|
|
if REQUEST:
|
|
return self.manage_main(self,REQUEST)
|
|
return ''
|
|
|
|
def identify(self, auth):
|
|
# Identify the username and password. This is where new modes should
|
|
# be called from, and if pluggable modes ever take shape, here ya go!
|
|
|
|
if self.cookie_mode and not auth:
|
|
# The identify signature does not include the request, sadly.
|
|
# I think that's dumb.
|
|
request = self.REQUEST
|
|
response = request.RESPONSE
|
|
|
|
if request.has_key('__ac_name') and request.has_key('__ac_password'):
|
|
return request['__ac_name'], request['__ac_password']
|
|
elif request.has_key('__ac') and self.cookie_mode == 1:
|
|
return self.decodeBasicCookie(request, response)
|
|
elif request.has_key('__aca') and self.cookie_mode == 2:
|
|
return self.decodeAdvancedCookie(request, response)
|
|
|
|
if auth and lower(auth[:6]) == 'basic ':
|
|
return tuple(split(decodestring(split(auth)[-1]), ':', 1))
|
|
|
|
return None, None
|
|
|
|
def decodeUserCookie(self, request, response):
|
|
return self.identify('')
|
|
|
|
def validate(self, request, auth='', roles=_noroles):
|
|
"""
|
|
Perform identification, authentication, and authorization.
|
|
"""
|
|
# Called at each web request
|
|
#zLOG.LOG('exUserFolder', zLOG.PANIC, 'validate')
|
|
v = request['PUBLISHED']
|
|
a, c, n, v = self._getobcontext(v, request)
|
|
|
|
name, password = self.identify(auth) # decode cookie, and raises LoginRequired if no ident info
|
|
# password is the cleartext passwd
|
|
# zLOG.LOG('exUserFolder', zLOG.DEBUG, 'identify returned %s, %s' % (name, password))
|
|
|
|
response = request.RESPONSE
|
|
if name is not None:
|
|
try:
|
|
xcached_user = self.xcache_getUser(name)
|
|
#zLOG.LOG('exUserFolder.validate', zLOG.PANIC, 'xcached_user=%s' % xcached_user)
|
|
if xcached_user:
|
|
#zLOG.LOG('exUserFolder.validate', zLOG.PANIC, 'returning None')
|
|
return None
|
|
except:
|
|
zLOG.LOG('exUserFolder', zLOG.ERROR,
|
|
"error while looking up '%s' on the xcache" % name,
|
|
'',
|
|
sys.exc_info())
|
|
|
|
user = self.authenticate(name, password, request)
|
|
#zLOG.LOG('exUserFolder.validate', zLOG.PANIC, 'user=%s' % user)
|
|
if user is None:
|
|
# If it's none, because there's no user by that name,
|
|
# don't raise a login, allow it to go higher...
|
|
# This kinda breaks for people putting in the wrong username
|
|
# when the Folder above uses a different auth method.
|
|
# But it doesn't lock Manager users out inside Zope.
|
|
# Perhaps this should be a tunable.
|
|
|
|
# modified by Emmanuel
|
|
try:
|
|
lou = self.listOneUser(name)
|
|
except:
|
|
lou = None
|
|
if lou:
|
|
self.challenge(request, response, 'login_failed', auth)
|
|
return None
|
|
self.remember(name, password, request)
|
|
self.cache_addToCache(name, password, user)
|
|
emergency = self._emergency_user
|
|
if emergency and user is emergency:
|
|
if self._isTop():
|
|
return emergency.__of__(self)
|
|
else:
|
|
return None
|
|
if self.authorize(user, a, c, n, v, roles):
|
|
return user.__of__(self)
|
|
if self._isTop() and self.authorize(self._nobody, a, c, n, v, roles):
|
|
return self._nobody.__of__(self)
|
|
self.challenge(request, response, 'unauthorized')
|
|
return None
|
|
else:
|
|
if self.sessionTracking and self.currentPropSource:
|
|
user = self.createAnonymousUser(request, response)
|
|
if self.authorize(user, a, c, n, v, roles):
|
|
return user.__of__(self)
|
|
if self.authorize(self._nobody, a, c, n, v, roles):
|
|
if self._isTop():
|
|
return self._nobody.__of__(self)
|
|
else:
|
|
return None
|
|
else:
|
|
self.challenge(request, response, None, auth)
|
|
return None
|
|
|
|
def authenticate(self, name, password, request):
|
|
#zLOG.LOG('exUserFolder.authenticate', zLOG.PANIC, '%s %s' % (name, password))
|
|
emergency = self._emergency_user
|
|
if emergency and name == emergency.getUserName():
|
|
return emergency
|
|
try:
|
|
user = self.cache_getUser(name, password)
|
|
#zLOG.LOG('exUserFolder.authenticate', zLOG.PANIC, 'cache_getUser=%s' % user)
|
|
if user:
|
|
return user
|
|
except SessionExpiredException:
|
|
if self.idleTimeout:
|
|
self.logout(request)
|
|
self.challenge(request, request.RESPONSE, 'session_expired')
|
|
return None
|
|
user = self.getUser(name)
|
|
#zLOG.LOG('exUserFolder.authenticate', zLOG.PANIC, 'getUser=%s' % user)
|
|
if user is not None:
|
|
if user.authenticate(self.currentAuthSource.listOneUser,
|
|
password,
|
|
request,
|
|
self.currentAuthSource.remoteAuthMethod):
|
|
return user
|
|
return None
|
|
|
|
def challenge(self, request, response, reason_code='unauthorized',
|
|
auth=''):
|
|
# Give whatever mode we're in a chance to challenge the validation
|
|
# failure. We do this to preserve LoginRequired behavior. The
|
|
# other thing we could do is let the None propagate on up and patch
|
|
# the request's unauthorized method to
|
|
|
|
if self.cookie_mode and not auth:
|
|
zLOG.LOG('exUserFolder', zLOG.DEBUG, 'raising LoginRequired for %s' % reason_code)
|
|
if reason_code == 'login_failed':
|
|
response.expireCookie('__ac', path='/')
|
|
response.expireCookie('__aca', path='/')
|
|
if reason_code:
|
|
request.set('authFailedCode', reason_code)
|
|
raise LoginRequired(self.docLogin(self, request))
|
|
else:
|
|
zLOG.LOG('exUserFolder', zLOG.DEBUG, 'not raising LoginRequired for %s' % reason_code)
|
|
|
|
def remember(self, name, password, request):
|
|
response = request.RESPONSE
|
|
if self.cookie_mode == 1:
|
|
self.setBasicCookie(name, password, request, response)
|
|
elif self.cookie_mode == 2:
|
|
self.setAdvancedCookie(name, password, request, response)
|
|
|
|
if self.cookie_mode:
|
|
try:
|
|
del request.form['__ac_name']
|
|
del request.form['__ac_password']
|
|
except KeyError:
|
|
pass
|
|
|
|
def makeRedirectPath(self):
|
|
REQUEST=self.REQUEST
|
|
if not REQUEST.has_key('destination'):
|
|
script=REQUEST['SCRIPT_NAME']
|
|
pathinfo=REQUEST['PATH_INFO']
|
|
redirectstring=script+pathinfo
|
|
if REQUEST.has_key('QUERY_STRING'):
|
|
querystring='?'+quote(REQUEST['QUERY_STRING'])
|
|
redirectstring=redirectstring+querystring
|
|
|
|
REQUEST['destination']=redirectstring
|
|
|
|
def redirectToLogin(self, REQUEST):
|
|
""" Allow methods to call from Web """
|
|
script=''
|
|
pathinfo=''
|
|
querystring=''
|
|
redirectstring=''
|
|
authFailedCode=''
|
|
|
|
if not REQUEST.has_key('destination'):
|
|
if self.currentMembershipSource:
|
|
redirectstring = self.currentMembershipSource.getLoginDestination(REQUEST)
|
|
else:
|
|
script=REQUEST['SCRIPT_NAME']
|
|
pathinfo=REQUEST['PATH_INFO']
|
|
redirectstring=script+pathinfo
|
|
if REQUEST.has_key('QUERY_STRING'):
|
|
querystring='?'+REQUEST['QUERY_STRING']
|
|
redirectstring=redirectstring+querystring
|
|
|
|
REQUEST['destination']=redirectstring
|
|
|
|
|
|
if REQUEST.has_key('authFailedCode'):
|
|
authFailedCode='&authFailedCode='+REQUEST['authFailedCode']
|
|
|
|
|
|
|
|
if self.currentMembershipSource and self.currentMembershipSource.loginPage:
|
|
try:
|
|
REQUEST.RESPONSE.redirect('%s/%s?destination=%s%s'%(self.currentMembershipSource.baseURL, self.currentMembershipSource.loginPage,REQUEST['destination'],authFailedCode))
|
|
return
|
|
except:
|
|
pass
|
|
return self.docLogin(self,REQUEST)
|
|
|
|
def decodeBasicCookie(self, request, response):
|
|
c=request['__ac']
|
|
c=unquote(c)
|
|
try:
|
|
c=decodestring(c)
|
|
except:
|
|
response.expireCookie('__ac', path='/')
|
|
raise LoginRequired(self.docLogin(self, request))
|
|
|
|
name,password=tuple(split(c, ':', 1))
|
|
return name, password
|
|
|
|
def decodeAdvancedCookie(self, request, response):
|
|
c = ''
|
|
try:
|
|
c = request['__aca']
|
|
c = unquote(c)
|
|
except:
|
|
response.expireCookie('__aca', path='/')
|
|
response.expireCookie('__ac', path='/') # Precaution
|
|
response.flush()
|
|
raise LoginRequired(self.docLogin(self, request))
|
|
|
|
u = self.cache_getCookieCacheUser(c)
|
|
if u:
|
|
return u
|
|
|
|
response.expireCookie('__aca', path='/')
|
|
response.expireCookie('__ac', path='/') # Precaution
|
|
response.flush()
|
|
raise LoginRequired(self.docLogin(self, request))
|
|
|
|
def setBasicCookie(self, name, password, request, response):
|
|
token='%s:%s' % (name, password)
|
|
token=encodestring(token)
|
|
token=quote(token)
|
|
response.setCookie('__ac', token, path='/')
|
|
request['__ac']=token
|
|
|
|
def setAdvancedCookie(self, name, password, request, response):
|
|
xufid = self._p_oid
|
|
hash = encodestring(sha.new('%s%s%f%f%s'%(
|
|
name, password, time(), random.random(), str(request))).digest())
|
|
token=quote(hash)
|
|
response.setCookie('__aca', token, path='/')
|
|
response.flush()
|
|
request['__aca']=token
|
|
self.cache_addToCookieCache(name, password, hash)
|
|
|
|
def setAnonCookie(self, name, request, resp):
|
|
token='%s:%s' % (name, '')
|
|
token=encodestring(token)
|
|
token=quote(token)
|
|
resp.setCookie('__ac', token, path='/')
|
|
request['__ac']=token
|
|
|
|
def createAnonymousUser(self, request, resp):
|
|
aName=createTempName()
|
|
bogusREQUEST={}
|
|
bogusREQUEST['user_realname']='Guest User'
|
|
self.currentPropSource.createUser(aName, bogusREQUEST)
|
|
ob = AnonUser(aName, [], self.currentPropSource)
|
|
ob = ob.__of__(self)
|
|
self.cache_addToCache(aName, '', ob)
|
|
self.setAnonCookie(aName, request, resp)
|
|
return ob
|
|
|
|
def manage_edit(self, cookie_mode, session_length, sessionTracking=None,
|
|
idleTimeout=0, not_session_length=0,
|
|
title=None,
|
|
REQUEST=None):
|
|
"""Change properties"""
|
|
|
|
self.cookie_mode=cookie_mode
|
|
self.sessionLength=session_length
|
|
self.notSessionLength=not_session_length
|
|
self.sessionTracking=sessionTracking
|
|
self.idleTimeout=idleTimeout
|
|
if title:
|
|
self.title = title
|
|
|
|
if REQUEST:
|
|
return self.MessageDialog(self,REQUEST=REQUEST,
|
|
title ='exUserFolder Changed',
|
|
message='exUserFolder properties have been updated',
|
|
action =REQUEST['URL1']+'/manage_main',
|
|
target ='manage_main')
|
|
|
|
def logout(self, REQUEST):
|
|
"""Logout"""
|
|
try:
|
|
self.cache_removeUser(REQUEST['AUTHENTICATED_USER'].getUserName())
|
|
except:
|
|
pass
|
|
|
|
REQUEST['RESPONSE'].expireCookie('__ac', path='/')
|
|
REQUEST.cookies['__ac']=''
|
|
try:
|
|
acc = REQUEST['__aca']
|
|
self.cache_removeCookieCacheUser(acc)
|
|
REQUEST.cookies['__aca']=''
|
|
except:
|
|
pass
|
|
REQUEST['RESPONSE'].expireCookie('__aca', path='/')
|
|
|
|
|
|
|
|
return self.docLogout(self, REQUEST)
|
|
|
|
#
|
|
# Methods to be supplied by Auth Source
|
|
#
|
|
def deleteUsers(self, userids):
|
|
self.currentAuthSource.deleteUsers(userids)
|
|
|
|
# Comment out to use Andreas' pgSchema
|
|
if self.currentPropSource:
|
|
self.currentPropSource.deleteUsers(userids)
|
|
|
|
if self.currentGroupSource:
|
|
self.currentGroupSource.deleteUsers(userids)
|
|
|
|
|
|
def listUsers(self):
|
|
return self.currentAuthSource.listUsers()
|
|
|
|
def user_names(self):
|
|
return self.currentAuthSource.listUserNames()
|
|
|
|
def getUserNames(self):
|
|
return self.currentAuthSource.listUserNames()
|
|
|
|
def listOneUser(self,username):
|
|
return self.currentAuthSource.listOneUser(username)
|
|
|
|
def cryptPassword(self, username, password):
|
|
if hasattr(aq_base(self.currentAuthSource), 'cryptPassword'):
|
|
return self.currentAuthSource.cryptPassword(username, password)
|
|
|
|
if hasattr(self, 'cryptoId'):
|
|
return self.cryptoSources[self.cryptoId].plugin(self, username, password)
|
|
return self.cryptoSources['Crypt'].plugin(self, username, password)
|
|
|
|
def PropertyEditor(self):
|
|
""" """
|
|
if self.REQUEST.has_key(self.REQUEST['propName']):
|
|
return PropertyEditor.EditMethods[self.REQUEST['propType']](self.REQUEST['propName'], self.REQUEST[self.REQUEST['propName']])
|
|
return PropertyEditor.EditMethods[self.REQUEST['propType']](self.REQUEST['propName'], None)
|
|
|
|
def PropertyView(self):
|
|
""" """
|
|
if self.REQUEST.has_key(self.REQUEST['propName']):
|
|
return PropertyEditor.ViewMethods[self.REQUEST['propType']](self.REQUEST['propName'], self.REQUEST[self.REQUEST['propName']])
|
|
return PropertyEditor.ViewMethods[self.REQUEST['propType']](self.REQUEST['propName'], None)
|
|
|
|
def manage_addUserProperty(self, username, propName, propValue, REQUEST):
|
|
""" add a new property """
|
|
self.currentPropSource.setUserProperty(propName, username, propValue)
|
|
if hasattr(self.currentAuthSource,'manage_editUserForm'):
|
|
return self.currentAuthSource.manage_editUserForm(self, REQUEST)
|
|
else:
|
|
return self.manage_editUserForm(self,REQUEST)
|
|
|
|
def getUserCacheStats(self):
|
|
""" Stats """
|
|
if self.sessionLength:
|
|
if self.cache_getCacheStats()['attempts']:
|
|
return self.cache_getCacheStats()
|
|
return None
|
|
|
|
def getUserCacheUsers(self):
|
|
""" Current Users """
|
|
if self.sessionLength:
|
|
return self.cache_getCurrentUsers()
|
|
return None
|
|
|
|
def userFolderAddGroup(self, groupname, title='', **kw):
|
|
"""Creates a group"""
|
|
if self.currentGroupSource:
|
|
apply(self.currentGroupSource.addGroup, (groupname, title), kw)
|
|
|
|
def userFolderDelGroups(self, groupnames):
|
|
"""Deletes groups"""
|
|
if self.currentGroupSource:
|
|
for groupname in groupnames:
|
|
self.currentGroupSource.delGroup(groupname)
|
|
|
|
def getGroupNames(self):
|
|
"""Returns a list of group names"""
|
|
if self.currentGroupSource:
|
|
return self.currentGroupSource.listGroups()
|
|
else:
|
|
return []
|
|
|
|
|
|
def getGroupById(self, groupname, default=_marker):
|
|
"""Returns the given group"""
|
|
if self.currentGroupSource:
|
|
group = self.currentGroupSource.getGroup(groupname, default)
|
|
if group:
|
|
return group.__of__(self)
|
|
else:
|
|
return None
|
|
|
|
def setUsersOfGroup(self, usernames, groupname):
|
|
"""Sets the users of the group"""
|
|
if self.currentGroupSource:
|
|
return self.currentGroupSource.setUsersOfGroup(usernames, groupname)
|
|
|
|
def addUsersToGroup(self, usernames, groupname):
|
|
"""Adds users to a group"""
|
|
if self.currentGroupSource:
|
|
return self.currentGroupSource.addUsersToGroup(usernames, groupname)
|
|
|
|
def delUsersFromGroup(self, usernames, groupname):
|
|
"""Deletes users from a group"""
|
|
if self.currentGroupSource:
|
|
return self.currentGroupSource.delUsersFromGroup(usernames, groupname)
|
|
|
|
def setGroupsOfUser(self, groupnames, username):
|
|
"""Sets the groups of a user"""
|
|
if self.currentGroupSource:
|
|
return self.currentGroupSource.setGroupsOfUser(groupnames, username)
|
|
|
|
def addGroupsOfUser(self, groupnames, username):
|
|
"""Add groups to a user"""
|
|
if self.currentGroupSource:
|
|
return self.currentGroupSource.addGroupsToUser(groupnames, username)
|
|
|
|
def delGroupsOfUser(self, groupnames, username):
|
|
"""Deletes groups from a user"""
|
|
if self.currentGroupSource:
|
|
return self.currentGroupSource.delGroupsFromUser(groupnames, username)
|
|
|
|
# We lie.
|
|
def hasUsers(self):
|
|
return 1
|
|
|
|
|
|
def doAuthSourceForm(self,authId):
|
|
""" la de da """
|
|
return exUserFolder.authSources[authId].manage_addForm
|
|
|
|
def doPropSourceForm(self,propId):
|
|
""" la de da """
|
|
return exUserFolder.propSources[propId].manage_addForm
|
|
|
|
def doMembershipSourceForm(self, memberId):
|
|
""" doot de doo """
|
|
return exUserFolder.membershipSources[memberId].manage_addForm
|
|
|
|
#def doGroupSourceForm(self,groupId):
|
|
# """ la de da """
|
|
# return exUserFolder.groupSources[groupId].manage_addForm
|
|
|
|
def getAuthSources(self):
|
|
""" Hrm I need a docstring """
|
|
l=[]
|
|
for o in exUserFolder.authSources.keys():
|
|
l.append(
|
|
exUserFolder.authSources[o]
|
|
)
|
|
return l
|
|
|
|
def getPropSources(self):
|
|
""" Hrm I need a docstring """
|
|
l=[]
|
|
for o in exUserFolder.propSources.keys():
|
|
l.append(
|
|
exUserFolder.propSources[o]
|
|
)
|
|
return l
|
|
|
|
def getMembershipSources(self):
|
|
""" Hrm I need a docstring """
|
|
l=[]
|
|
for o in exUserFolder.membershipSources.keys():
|
|
l.append(
|
|
exUserFolder.membershipSources[o]
|
|
)
|
|
return l
|
|
|
|
def getGroupSources(self):
|
|
""" Hrm I need a docstring """
|
|
return [] # UNUSED by ScoDoc: empty
|
|
|
|
def getCryptoSources(self):
|
|
""" Doc String """
|
|
l = []
|
|
for o in exUserFolder.cryptoSources.keys():
|
|
l.append(
|
|
exUserFolder.cryptoSources[o]
|
|
)
|
|
return l
|
|
|
|
def MailHostIDs(self):
|
|
"""Find SQL database connections in the current folder and above
|
|
|
|
This function return a list of ids.
|
|
"""
|
|
return [] # UNUSED BY SCODOC
|
|
|
|
from types import ListType, IntType, LongType, FloatType, NoneType, DictType, StringType
|
|
|
|
def getVariableType(self, o):
|
|
|
|
if type(o) == ListType:
|
|
return 'List'
|
|
if type(o) == IntType:
|
|
return 'Int'
|
|
if type(o) == LongType:
|
|
return 'Long'
|
|
if type(o) == FloatType:
|
|
return 'Float'
|
|
if type(o) == NoneType:
|
|
return 'None'
|
|
if type(o) == DictType:
|
|
return 'Dict'
|
|
if type(o) == StringType:
|
|
return 'String'
|
|
return 'Unknown or Restricted'
|
|
|
|
_postUserCreate='''
|
|
<dtml-comment>
|
|
Replace this method with whatever you want to do
|
|
when a user is created, you can use a Python Script,
|
|
or External Method, or keep it as a DTML Method if you
|
|
want to
|
|
</dtml-comment>
|
|
'''
|