changeset 1236:dd52bf10f934

Bug fixes. - fixed bug in login if the username wasn't known - handle close/rollback of already-closed sqlite database - added example for external passwd-style user password verification
author Richard Jones <richard@users.sourceforge.net>
date Fri, 27 Sep 2002 01:04:38 +0000
parents 7441653e5330
children 4a7caa50785b
files CHANGES.txt doc/customizing.txt roundup/backends/back_sqlite.py roundup/cgi/client.py
diffstat 4 files changed, 89 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES.txt	Thu Sep 26 23:59:08 2002 +0000
+++ b/CHANGES.txt	Fri Sep 27 01:04:38 2002 +0000
@@ -46,6 +46,7 @@
 - fixed the mailgw so that anonymous users may still access it
 - add hook to allow external password verification, overridable in the
   tracker interfaces module
+- fixed login attempt by user that doesn't exist
 
 2002-09-13 0.5.0 beta2
 -  all backends now have a .close() method, and it's used everywhere
--- a/doc/customizing.txt	Thu Sep 26 23:59:08 2002 +0000
+++ b/doc/customizing.txt	Fri Sep 27 01:04:38 2002 +0000
@@ -2,7 +2,7 @@
 Customising Roundup
 ===================
 
-:Version: $Revision: 1.49 $
+:Version: $Revision: 1.50 $
 
 .. This document borrows from the ZopeBook section on ZPT. The original is at:
    http://www.zope.org/Documentation/Books/ZopeBook/current/ZPT.stx
@@ -2118,6 +2118,45 @@
 4. Use the usual "new" action as the :action on the final page, and you're
    done (the standard context/submit method can do this for you).
 
+
+Using an external password validation source
+--------------------------------------------
+
+We have a centrally-managed password changing system for our users. This
+results in a UN*X passwd-style file that we use for verification of users.
+Entries in the file consist of ``name:password`` where the password is
+encrypted using the standard UN*X ``crypt()`` function (see the ``crypt``
+module in your Python distribution). An example entry would be::
+
+    admin:aamrgyQfDFSHw
+
+Each user of Roundup must still have their information stored in the Roundup
+database - we just use the passwd file to check their password. To do this, we
+add the following code to our ``Client`` class in the tracker home
+``interfaces.py`` module::
+
+    def verifyPassword(self, userid, password):
+        # get the user's username
+        username = self.db.user.get(userid, 'username')
+
+        # the passwords are stored in the "passwd.txt" file in the tracker
+        # home
+        file = os.path.join(self.db.config.TRACKER_HOME, 'passwd.txt')
+
+        # see if we can find a match
+        for ent in [line.strip().split(':') for line in open(file).readlines()]:
+            if ent[0] == username:
+                return crypt.crypt(password, ent[1][:2]) == ent[1]
+
+        # user doesn't exist in the file
+        return 0
+
+What this does is look through the file, line by line, looking for a name that
+matches.
+
+We also remove the redundant password fields from the ``user.item`` template.
+
+
 -------------------
 
 Back to `Table of Contents`_
--- a/roundup/backends/back_sqlite.py	Thu Sep 26 23:59:08 2002 +0000
+++ b/roundup/backends/back_sqlite.py	Fri Sep 27 01:04:38 2002 +0000
@@ -1,4 +1,4 @@
-# $Id: back_sqlite.py,v 1.5 2002-09-24 01:59:28 richard Exp $
+# $Id: back_sqlite.py,v 1.6 2002-09-27 01:04:38 richard Exp $
 __doc__ = '''
 See https://pysqlite.sourceforge.net/ for pysqlite info
 '''
@@ -25,6 +25,45 @@
             self.cursor.execute('create table schema (schema varchar)')
             self.cursor.execute('create table ids (name varchar, num integer)')
 
+    def close(self):
+        ''' Close off the connection.
+
+            Squash any error caused by us already having closed the
+            connection.
+        '''
+        try:
+            self.conn.close()
+        except sqlite.ProgrammingError, value:
+            if str(value) != 'close failed - Connection is closed.':
+                raise
+
+
+    def rollback(self):
+        ''' Reverse all actions from the current transaction.
+
+            Undo all the changes made since the database was opened or the
+            last commit() or rollback() was performed.
+
+            Squash any error caused by us having closed the connection (and
+            therefore not having anything to roll back)
+        '''
+        if __debug__:
+            print >>hyperdb.DEBUG, 'rollback', (self,)
+
+        # roll back
+        try:
+            self.conn.rollback()
+        except sqlite.ProgrammingError, value:
+            if str(value) != 'rollback failed - Connection is closed.':
+                raise
+
+        # roll back "other" transaction stuff
+        for method, args in self.transactions:
+            # delete temporary files
+            if method == self.doStoreFile:
+                self.rollbackStoreFile(*args)
+        self.transactions = []
+
     def __repr__(self):
         return '<roundlite 0x%x>'%id(self)
 
--- a/roundup/cgi/client.py	Thu Sep 26 23:59:08 2002 +0000
+++ b/roundup/cgi/client.py	Fri Sep 27 01:04:38 2002 +0000
@@ -1,4 +1,4 @@
-# $Id: client.py,v 1.47 2002-09-26 23:59:08 richard Exp $
+# $Id: client.py,v 1.48 2002-09-27 01:04:38 richard Exp $
 
 __doc__ = """
 WWW request handler (also used in the stand-alone server).
@@ -485,22 +485,23 @@
             self.error_message.append(_('Username required'))
             return
 
+        # get the login info
         self.user = self.form['__login_name'].value
-        # re-open the database for real, using the user
-        self.opendb(self.user)
         if self.form.has_key('__login_password'):
             password = self.form['__login_password'].value
         else:
             password = ''
+
         # make sure the user exists
         try:
             self.userid = self.db.user.lookup(self.user)
         except KeyError:
             name = self.user
+            self.error_message.append(_('No such user "%(name)s"')%locals())
             self.make_user_anonymous()
-            self.error_message.append(_('No such user "%(name)s"')%locals())
             return
 
+        # verify the password
         if not self.verifyPassword(self.userid, password):
             self.make_user_anonymous()
             self.error_message.append(_('Incorrect password'))
@@ -511,6 +512,9 @@
             self.make_user_anonymous()
             raise Unauthorised, _("You do not have permission to login")
 
+        # now we're OK, re-open the database for real, using the user
+        self.opendb(self.user)
+
         # set the session cookie
         self.set_cookie(self.user)
 

Roundup Issue Tracker: http://roundup-tracker.org/