witten
/
luminotes
Archived
1
0
Fork 0

Password reset now stores and uses a revision timestamp, which helps when testing for expiry.

This commit is contained in:
Dan Helfman 2007-10-11 20:18:20 +00:00
parent bbebad528e
commit 322134cba6
4 changed files with 24 additions and 9 deletions

View File

@ -487,7 +487,7 @@ class Users( object ):
# record the sending of this reset email # record the sending of this reset email
password_reset_id = self.__database.next_id( Password_reset, commit = False ) password_reset_id = self.__database.next_id( Password_reset, commit = False )
password_reset = Password_reset( password_reset_id, email_address ) password_reset = Password_reset.create( password_reset_id, email_address )
self.__database.save( password_reset ) self.__database.save( password_reset )
# create an email message with a unique link # create an email message with a unique link

View File

@ -5,12 +5,14 @@ class Password_reset( Persistent ):
""" """
A request for a password reset. A request for a password reset.
""" """
def __init__( self, object_id, email_address = None, redeemed = False ): def __init__( self, object_id, revision = None, email_address = None, redeemed = False ):
""" """
Create a password reset request with the given id. Create a password reset request with the given id.
@type object_id: unicode @type object_id: unicode
@param object_id: id of the password reset @param object_id: id of the password reset
@type revision: datetime or NoneType
@param revision: revision timestamp of the object (optional, defaults to now)
@type email_address: unicode @type email_address: unicode
@param email_address: where the reset confirmation was emailed @param email_address: where the reset confirmation was emailed
@type redeemed: bool or NoneType @type redeemed: bool or NoneType
@ -18,17 +20,29 @@ class Password_reset( Persistent ):
@rtype: Password_reset @rtype: Password_reset
@return: newly constructed password reset @return: newly constructed password reset
""" """
Persistent.__init__( self, object_id ) Persistent.__init__( self, object_id, revision )
self.__email_address = email_address self.__email_address = email_address
self.__redeemed = redeemed self.__redeemed = redeemed
@staticmethod
def create( object_id, email_address = None ):
"""
Convenience constructor for creating a new note.
@type email_address: unicode
@param email_address: where the reset confirmation was emailed
@rtype: Password_reset
@return: newly constructed password reset
"""
return Password_reset( object_id, email_address = email_address )
@staticmethod @staticmethod
def sql_load( object_id, revision = None ): def sql_load( object_id, revision = None ):
# password resets don't track revisions # password resets don't track revisions
if revision: if revision:
raise NotImplementedError() raise NotImplementedError()
return "select * from password_reset where id = %s;" % quote( object_id ) return "select id, revision, email_address, redeemed from password_reset where id = %s;" % quote( object_id )
@staticmethod @staticmethod
def sql_id_exists( object_id, revision = None ): def sql_id_exists( object_id, revision = None ):
@ -41,12 +55,12 @@ class Password_reset( Persistent ):
return Password_reset.sql_id_exists( self.object_id ) return Password_reset.sql_id_exists( self.object_id )
def sql_create( self ): def sql_create( self ):
return "insert into password_reset ( id, email_address, redeemed ) values ( %s, %s, %s );" % \ return "insert into password_reset ( id, revision, email_address, redeemed ) values ( %s, %s, %s, %s );" % \
( quote( self.object_id ), quote( self.__email_address ), quote( self.__redeemed and "t" or "f" ) ) ( quote( self.object_id ), quote( self.revision ), quote( self.__email_address ), quote( self.__redeemed and "t" or "f" ) )
def sql_update( self ): def sql_update( self ):
return "update password_reset set email_address = %s, redeemed = %s where id = %s;" % \ return "update password_reset set revision = %s, email_address = %s, redeemed = %s where id = %s;" % \
( quote( self.__email_address ), quote( self.__redeemed and "t" or "f" ), quote( self.object_id ) ) ( quote( self.revision ), quote( self.__email_address ), quote( self.__redeemed and "t" or "f" ), quote( self.object_id ) )
def __set_redeemed( self, redeemed ): def __set_redeemed( self, redeemed ):
if redeemed != self.__redeemed: if redeemed != self.__redeemed:

View File

@ -98,6 +98,7 @@ ALTER TABLE public.notebook_current OWNER TO luminotes;
CREATE TABLE password_reset ( CREATE TABLE password_reset (
id text NOT NULL, id text NOT NULL,
revision timestamp with time zone NOT NULL,
email_address text, email_address text,
redeemed boolean redeemed boolean
); );

View File

@ -7,7 +7,7 @@ class Test_password_reset( object ):
self.object_id = u"17" self.object_id = u"17"
self.email_address = u"bob@example.com" self.email_address = u"bob@example.com"
self.password_reset = Password_reset( self.object_id, self.email_address ) self.password_reset = Password_reset.create( self.object_id, self.email_address )
def test_create( self ): def test_create( self ):
assert self.password_reset.object_id == self.object_id assert self.password_reset.object_id == self.object_id