[Zope-dev] SQL user source, how is this?

Harry Henry Gebel hgebel@inet.net
Mon, 16 Oct 2000 13:28:36 -0400


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