I am writing a UserSource that gets it's information from an SQL database, here it is: ''' CCUserSource, a LoginManager user source for the ##### project. ''' from sha import sha from Products.LoginManager.UserSources import BasicUserSource class CCUserSource(BasicUserSource): """ CCUserSource is a ZPatterns plug-in intended to be used as a user source in LoginManager. It queries a database adapter to acquire authentication information on a user, and sets a user's role based on the user's age. A database connection with an id of cc_user_database must be visible. """ # string displayed in "Add Product" drop-down box. meta_type = "##### User Source" # public functions def retrieveItem(self, name): ''' Return a user object if user exists in database, otherwise return None ''' # call database adapter, if we can't connect return None try: result = self.__query( "select username from users where username='%s'" % name) except: return None # return a user object if user exists in database if result: return self._RawItem(name) else: return None def rolesForUser(self, user): ''' Calculate role from age ''' return ['Manager'] def domainsForUser(self, user): ''' Allow users from all domains ''' return [] def authenticateUser(self, user, password, request): """ Verify user's password, return true if correct, 0 if incorrect """ # get SHA encoded password and salt from the database passw = self.__query( "select password from users where username = '%s'" % user.getUserName()) (salt, passw) = (passw[:2], passw[2:]) # apply salt to user-supplied password and generate hash hash = sha(salt + password).hexdigest() # return result of match return hash == passw # private functions def __query(self, query): ''' Perform a query on cc_user_database, return the results of the query, return None on no result ''' # find database connection, let caller catch exceptions dbc = getattr(self, 'cc_user_database') db = dbc() # return results of database query # query returns result in form # ([field_data], [(row1), ...]) # all of our queries have max 1 result and only 1 column, so process # accordingly try: result = db.query(query)[1][0][0] except: result = None return result It is working, but I have some questions: 1. Am I doing anything wrong that will bite me later, especially I have not implemented all of the cache* methods called in GenericUserFolder because I don't understand what these do or what they are for. Are these important for my product? 2. I would like my client to be able to specify an alternate database connection id if he does not want to use the default connection id of cc_user_database. If he goes to his CCUserSource's "properties" tab and adds a property of use_database_id with the connection id he wants to use, how do I access it (this is my first Zope product, so I am learning the internals as I go along). Can I use self.use_database_id or do I have to use getattr(self, 'use_database_id') or do I have to use a completely different method to access properties. PS: I know I am giving everybody that passes authentication the manager role, I did this for testing purposes and haven't changed it yet because I have not been given me a list of the roles they want to use. -- Harry Henry Gebel, ICQ# 76308382 West Dover Hundred, Delaware