Skip to content

Commit ac9bb28

Browse files
author
Richard Jones
committed
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
1 parent a4dc891 commit ac9bb28

File tree

4 files changed

+89
-6
lines changed

4 files changed

+89
-6
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ are given with the most recent entry first.
4646
- fixed the mailgw so that anonymous users may still access it
4747
- add hook to allow external password verification, overridable in the
4848
tracker interfaces module
49+
- fixed login attempt by user that doesn't exist
4950

5051
2002-09-13 0.5.0 beta2
5152
- all backends now have a .close() method, and it's used everywhere

doc/customizing.txt

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Customising Roundup
33
===================
44

5-
:Version: $Revision: 1.49 $
5+
:Version: $Revision: 1.50 $
66

77
.. This document borrows from the ZopeBook section on ZPT. The original is at:
88
http://www.zope.org/Documentation/Books/ZopeBook/current/ZPT.stx
@@ -2118,6 +2118,45 @@ Setting up a "wizard" (or "druid") for controlled adding of issues
21182118
4. Use the usual "new" action as the :action on the final page, and you're
21192119
done (the standard context/submit method can do this for you).
21202120

2121+
2122+
Using an external password validation source
2123+
--------------------------------------------
2124+
2125+
We have a centrally-managed password changing system for our users. This
2126+
results in a UN*X passwd-style file that we use for verification of users.
2127+
Entries in the file consist of ``name:password`` where the password is
2128+
encrypted using the standard UN*X ``crypt()`` function (see the ``crypt``
2129+
module in your Python distribution). An example entry would be::
2130+
2131+
admin:aamrgyQfDFSHw
2132+
2133+
Each user of Roundup must still have their information stored in the Roundup
2134+
database - we just use the passwd file to check their password. To do this, we
2135+
add the following code to our ``Client`` class in the tracker home
2136+
``interfaces.py`` module::
2137+
2138+
def verifyPassword(self, userid, password):
2139+
# get the user's username
2140+
username = self.db.user.get(userid, 'username')
2141+
2142+
# the passwords are stored in the "passwd.txt" file in the tracker
2143+
# home
2144+
file = os.path.join(self.db.config.TRACKER_HOME, 'passwd.txt')
2145+
2146+
# see if we can find a match
2147+
for ent in [line.strip().split(':') for line in open(file).readlines()]:
2148+
if ent[0] == username:
2149+
return crypt.crypt(password, ent[1][:2]) == ent[1]
2150+
2151+
# user doesn't exist in the file
2152+
return 0
2153+
2154+
What this does is look through the file, line by line, looking for a name that
2155+
matches.
2156+
2157+
We also remove the redundant password fields from the ``user.item`` template.
2158+
2159+
21212160
-------------------
21222161

21232162
Back to `Table of Contents`_

roundup/backends/back_sqlite.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $Id: back_sqlite.py,v 1.5 2002-09-24 01:59:28 richard Exp $
1+
# $Id: back_sqlite.py,v 1.6 2002-09-27 01:04:38 richard Exp $
22
__doc__ = '''
33
See https://pysqlite.sourceforge.net/ for pysqlite info
44
'''
@@ -25,6 +25,45 @@ def open_connection(self):
2525
self.cursor.execute('create table schema (schema varchar)')
2626
self.cursor.execute('create table ids (name varchar, num integer)')
2727

28+
def close(self):
29+
''' Close off the connection.
30+
31+
Squash any error caused by us already having closed the
32+
connection.
33+
'''
34+
try:
35+
self.conn.close()
36+
except sqlite.ProgrammingError, value:
37+
if str(value) != 'close failed - Connection is closed.':
38+
raise
39+
40+
41+
def rollback(self):
42+
''' Reverse all actions from the current transaction.
43+
44+
Undo all the changes made since the database was opened or the
45+
last commit() or rollback() was performed.
46+
47+
Squash any error caused by us having closed the connection (and
48+
therefore not having anything to roll back)
49+
'''
50+
if __debug__:
51+
print >>hyperdb.DEBUG, 'rollback', (self,)
52+
53+
# roll back
54+
try:
55+
self.conn.rollback()
56+
except sqlite.ProgrammingError, value:
57+
if str(value) != 'rollback failed - Connection is closed.':
58+
raise
59+
60+
# roll back "other" transaction stuff
61+
for method, args in self.transactions:
62+
# delete temporary files
63+
if method == self.doStoreFile:
64+
self.rollbackStoreFile(*args)
65+
self.transactions = []
66+
2867
def __repr__(self):
2968
return '<roundlite 0x%x>'%id(self)
3069

roundup/cgi/client.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $Id: client.py,v 1.47 2002-09-26 23:59:08 richard Exp $
1+
# $Id: client.py,v 1.48 2002-09-27 01:04:38 richard Exp $
22

33
__doc__ = """
44
WWW request handler (also used in the stand-alone server).
@@ -485,22 +485,23 @@ def loginAction(self):
485485
self.error_message.append(_('Username required'))
486486
return
487487

488+
# get the login info
488489
self.user = self.form['__login_name'].value
489-
# re-open the database for real, using the user
490-
self.opendb(self.user)
491490
if self.form.has_key('__login_password'):
492491
password = self.form['__login_password'].value
493492
else:
494493
password = ''
494+
495495
# make sure the user exists
496496
try:
497497
self.userid = self.db.user.lookup(self.user)
498498
except KeyError:
499499
name = self.user
500-
self.make_user_anonymous()
501500
self.error_message.append(_('No such user "%(name)s"')%locals())
501+
self.make_user_anonymous()
502502
return
503503

504+
# verify the password
504505
if not self.verifyPassword(self.userid, password):
505506
self.make_user_anonymous()
506507
self.error_message.append(_('Incorrect password'))
@@ -511,6 +512,9 @@ def loginAction(self):
511512
self.make_user_anonymous()
512513
raise Unauthorised, _("You do not have permission to login")
513514

515+
# now we're OK, re-open the database for real, using the user
516+
self.opendb(self.user)
517+
514518
# set the session cookie
515519
self.set_cookie(self.user)
516520

0 commit comments

Comments
 (0)