r1401: Added a password reset system that works very similarly to the user activation...
authorRobert Sesek <rsesek@bluestatic.org>
Tue, 13 Feb 2007 07:43:58 +0000 (07:43 +0000)
committerRobert Sesek <rsesek@bluestatic.org>
Tue, 13 Feb 2007 07:43:58 +0000 (07:43 +0000)
docs/changes.txt
docs/schema_changes.sql
login.php
templates/login.tpl
templates/lostpassword.tpl [new file with mode: 0644]
templates/passwordreset.tpl [new file with mode: 0644]

index 4af03b0e2810af38c09e5326e7466669c2c13602..6c872057b12ef76c51e855553c2f5c15bf64d9b9 100644 (file)
@@ -16,6 +16,7 @@
 - Setting system cleanup that improves speed by reducing queries and not using eval()
 - Can now mass update of bug fields from the search screen
 - Search system no longer stores the actual query of the search, but rather the paramters
+- Added a lost password reset system
 
 1.1.5
 ===============================
index fc8d0e094bb73d0933e15890cea45ffec72c3f19..61fa7aefdf81d6caf6ac71d207b1d0bc99c7e7a0 100644 (file)
@@ -13,3 +13,11 @@ ALTER TABLE search ADD searchid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
 ALTER TABLE search ADD name VARCHAR(250) NULL;
 
 ALTER TABLE version ADD obsolete BOOL NULL;
+
+CREATE TABLE passwordreset
+(
+       activatorid VARCHAR(250) NOT NULL, 
+       userid INT NOT NULL, 
+       dateline INT NOT NULL,
+       PRIMARY KEY (activatorid)
+);
\ No newline at end of file
index 583988fca3e99b479c4fff8f1931e145fecafdbf..6ffdc7f713bff05521bd8238af6846ffa27edec3 100755 (executable)
--- a/login.php
+++ b/login.php
@@ -20,7 +20,9 @@
 \*=====================================================================*/
 
 $fetchtemplates = array(
-       'login'
+       'login',
+       'lostpassword',
+       'passwordreset'
 );
 
 define('SVN', '$Id$');
@@ -28,6 +30,10 @@ define('SVN', '$Id$');
 $focus['user'] = 'focus';
 
 require_once('./global.php');
+require_once('./includes/api_user.php');
+require_once('./includes/class_api_error.php');
+
+APIError(array(new API_Error_Handler($message), 'user_cumulative'));
 
 // ###################################################################
 
@@ -109,6 +115,115 @@ if ($_REQUEST['do'] == 'logout')
 
 // ###################################################################
 
+if ($_POST['do'] == 'sendpw')
+{      
+       $user = new UserAPI($bugsys);
+       $user->set('email', $bugsys->in['email'], true, false); // don't verify so we don't get errors about existing emails
+       $user->set_condition(array('email'));
+       $user->fetch();
+       
+       if ($message->items)
+       {
+               $show['lostpwerror'] = true;
+               $_REQUEST['do'] = 'lostpw';
+       }
+       else
+       {
+               $activator = $funct->rand(25);
+               $db->query("INSERT INTO " . TABLE_PREFIX . "passwordreset (activatorid, dateline, userid) VALUES ('" . $activator . "', " . TIMENOW . ", " . $user->objdata['userid'] . ")");
+               
+               $mail->setSubject(sprintf(_('%1$s Password Reset'), $bugsys->options['trackertitle']));
+               $mail->setBodyText(sprintf(_('Hi %1$s,
+
+You requested this lost password email at the %2$s bug tracker. To reset your password, simply click the link below (or paste it into your browser window exactly) and enter a new password.
+
+%3$s/login.php?do=recoverpw&activator=%4$s
+
+If you did not request this, do not worry as this notice will expire in 24 hours.'),
+
+                                                               $user->objdata['displayname'],
+                                                               $bugsys->options['trackertitle'],
+                                                               $bugsys->options['trackerurl'],
+                                                               $activator
+               ));
+               
+               $mail->send($user->objdata['email'], $user->objdata['displayname']);
+               
+               $message->message(sprintf(_('An email has been dispatched to %1$s that contains instructions on how to reset your password.'), $user->objdata['email']));
+       }
+}
+
+// ###################################################################
+
+if ($_REQUEST['do'] == 'lostpw')
+{
+       eval('$template->flush("' . $template->fetch('lostpassword') . '");');
+}
+
+// ###################################################################
+
+if ($_POST['do'] == 'resetpw')
+{
+       // remove old activators
+       $db->query("DELETE FROM " . TABLE_PREFIX . "passwordreset WHERE dateline < " . (TIMENOW - 86400));
+       
+       // now look for ours
+       $activation = $db->query_first("SELECT * FROM " . TABLE_PREFIX . "passwordreset WHERE activatorid = '" . $bugsys->input_escape('activator') . "'");
+       if (!$activation)
+       {
+               $message->error(L_INVALID_ID);
+       }
+       
+       $user = new UserAPI($bugsys);
+       $user->set('userid', $activation['userid']);
+       $user->set_condition();
+       
+       if ($bugsys->in['fix_password'] != $bugsys->in['confirm_password'])
+       {
+               $message->add_error(_('The passwords you entered do not patch.'));
+       }
+       if (empty($bugsys->in['fix_password']))
+       {
+               $message->add_error(_('Your new password cannot be empty.'));
+       }
+       
+       $user->set('password', $bugsys->in['fix_password']);
+       
+       if (!$message->items)
+       {
+               // remove old other activators for this user
+               $db->query("DELETE FROM " . TABLE_PREFIX . "passwordreset WHERE userid = " . $activation['userid']);
+               
+               $user->update();
+               $message->redirect(_('Your password has been changed successfully. You will now be redirected to the login page.'), 'login.php');
+       }
+       else
+       {
+               $show['errors'] = true;
+               $_REQUEST['do'] = 'recoverpw';
+               $message->error_list_process();
+       }
+}
+
+// ###################################################################
+
+if ($_REQUEST['do'] == 'recoverpw')
+{
+       // remove old activators
+       $db->query("DELETE FROM " . TABLE_PREFIX . "passwordreset WHERE dateline < " . (TIMENOW - 86400));
+       
+       // now look for ours
+       $activation = $db->query_first("SELECT * FROM " . TABLE_PREFIX . "passwordreset WHERE activatorid = '" . $bugsys->input_escape('activator') . "'");
+       if (!$activation)
+       {
+               $message->error(_('Invalid activation reset key. Please make sure you copied the URL exactly as it appeared in the email.'));
+       }
+       
+       eval('$template->flush("' . $template->fetch('passwordreset') . '");');
+}
+
+// ###################################################################
+
 if ($_REQUEST['do'] == 'cplogout')
 {
        if ($_COOKIE[COOKIE_PREFIX . 'adminsession'])
index 776878861a0192841e724fdaea084aecf4cd89c7..cd2c2fb85c132d3c76c549092ec578c552d1d229 100644 (file)
@@ -23,7 +23,7 @@ $header
                        <div><strong>{@"Password"}:</strong> <input type="password" name="password" size="30" /></div>
                        <div><strong>{@"Remember Me"}:</strong> <input type="checkbox" name="rememberme" value="1" /> {@"Yes"}</div>
                        <br />
-                       <a href="register.php">{@"Click here if you do not have an account..."}</a>
+                       [<a href="register.php">{@"Register"}</a>] [<a href="login.php?do=lostpw">{@"Lost Password"}</a>]
                </div>
                
                <div class="box-foot box-center">
diff --git a/templates/lostpassword.tpl b/templates/lostpassword.tpl
new file mode 100644 (file)
index 0000000..4c5ed80
--- /dev/null
@@ -0,0 +1,35 @@
+$doctype
+<html lang="$stylevar[lang]" xml:lang="$stylevar[lang]" dir="$stylevar[lang_dir]">
+<head>
+$headinclude
+       <link rel="stylesheet" href="templates/box.css" media="screen" />
+       <title>{$bugsys->options['trackertitle']} - {@"Lost Password"}</title>
+</head>
+
+<body>
+
+$header
+
+<form action="login.php" name="lostpw" method="post">
+<input type="hidden" name="do" value="sendpw" />
+
+<div align="center" style="margin-top: 10px">
+       <div class="box" style="width: $stylevar[alternate_width]">
+               <div class="box-head">{@"Lost Password Recovery"}</div>
+               
+               <div class="box-mid">
+                       <if condition="$show['lostpwerror']"><div class="error">{@"The specified email could not be found or it is invalid."}</div></if>
+                       <div>{@"Enter your email in the box below and you will receive a message with instructions on how to set a new password."}</div>
+                       <div><strong>{@"Email"}:</strong> <input type="text" name="email" size="30" value="{$bugsys->in['email']}" /></div>
+               </div>
+               
+               <div class="box-foot box-center">
+                       <input type="submit" name="submit" value="  {@"Submit"}  " accesskey="s" />
+                       <input type="reset" name="reset" value="  {@"Reset"}  " accesskey="r" />
+               </div>
+       </div>
+</div>
+
+</form>
+
+$footer
\ No newline at end of file
diff --git a/templates/passwordreset.tpl b/templates/passwordreset.tpl
new file mode 100644 (file)
index 0000000..8e4845d
--- /dev/null
@@ -0,0 +1,43 @@
+$doctype
+<html lang="$stylevar[lang]" xml:lang="$stylevar[lang]" dir="$stylevar[lang_dir]">
+<head>
+$headinclude
+       <link rel="stylesheet" href="templates/box.css" media="screen" />
+       <title>{$bugsys->options['trackertitle']} - {@"Reset Password"}</title>
+</head>
+
+<body>
+
+$header
+
+<form action="login.php" name="resetpw" method="post">
+<input type="hidden" name="do" value="resetpw" />
+<input type="hidden" name="activator" value="$activation[activatorid]" />
+
+<if condition="$show['errors']">
+<div class="error" style="text-align: $stylevar[left]">
+       {@"The following errors occurred"}:
+       {$message->process}
+</div>
+</if>
+
+<div align="center" style="margin-top: 10px">
+       <div class="box" style="width: $stylevar[alternate_width]">
+               <div class="box-head">{@"Lost Password Recovery: Password Reset"}</div>
+               
+               <div class="box-mid">
+                       <div>{@"Enter a new password below and then confirm it."}</div>
+                       <div><strong>{@"New Password"}:</strong> <input type="password" name="fix_password" size="30" /></div>
+                       <div><strong>{@"Confirm Password"}:</strong> <input type="password" name="confirm_password" size="30" /></div>
+               </div>
+               
+               <div class="box-foot box-center">
+                       <input type="submit" name="submit" value="  {@"Submit"}  " accesskey="s" />
+                       <input type="reset" name="reset" value="  {@"Reset"}  " accesskey="r" />
+               </div>
+       </div>
+</div>
+
+</form>
+
+$footer
\ No newline at end of file