Xataface 2.0
Xataface Application Framework
actions/forgot_password.php
Go to the documentation of this file.
00001 <?php
00002 class dataface_actions_forgot_password {
00003         public static $TABLE_RESET_PASSWORD = 'dataface__reset_password';
00004         public static $EX_MULTIPLE_USERS_WITH_SAME_EMAIL = 500;
00005         public static $EX_NO_USERS_WITH_EMAIL = 501;
00006         public static $EX_NO_EMAIL_COLUMN_FOUND = 502;
00007         public static $EX_NO_USERNAME_COLUMN_FOUND = 504;
00008         public static $EX_NO_USERNAME_FOR_USER = 503;
00009         public static $EX_NO_SUCH_UUID = 505;
00010         public static $EX_USER_NOT_FOUND = 506;
00011         public static $EX_NO_EMAIL_FOR_USER = 507;
00012         public static $EX_NO_USERS_FOUND_WITH_USERNAME = 508;
00013         public static $EX_MULTIPLE_USERS_WITH_SAME_USERNAME = 509;
00014         
00015         function handle($params){
00016                 
00017                 
00018                 $app = Dataface_Application::getInstance();
00019                 $query =& $app->getQuery();
00020                 $jt = Dataface_JavascriptTool::getInstance();
00021                 $jt->import('forgot_password.js');
00022                                 
00023                 try {
00024                         if ( isset($query['--uuid']) ){
00025                                 // A uuid was supplied, 
00026                                 $res = $this->reset_password_with_uuid($query['--uuid']);
00027                                 if ( $res ){
00028                                         df_display(array(), 'xataface/forgot_password/password_has_been_reset.html');
00029                                         exit;
00030                                 } else {
00031                                         throw new Exception("Failed to reset password for uuid ".$query['--uuid']);
00032                                 }
00033                                 
00034                         }  else if ( isset($query['--email']) ){
00035                                 
00036                                 $this->send_reset_email_for_email($query['--email']);
00037                                 if ( @$query['--format'] == 'json' ){
00038                                         $this->response(array(
00039                                                 'code'=>200,
00040                                                 'message'=>'An email has been sent to the provided email address with instructions for resetting your password.'
00041                                         ));
00042                                         exit;
00043                                 } else {
00044                                         df_display(array(), 'xataface/forgot_password/sent_email.html');
00045                                         exit;
00046                                 }
00047                                 
00048                         
00049                         } else if ( isset($query['--username']) ){
00050                                 
00051                                 $this->send_reset_email_for_username($query['--username']);
00052                                 if ( @$query['--format'] == 'json' ){
00053                                         $this->response(array(  
00054                                         'code'=>200,
00055                                         'message'=> 'An email has been sent to the email on file for this user account with instructions for resetting the password.'
00056                                         ));
00057                                         exit;
00058                                 } else {
00059                                         df_display(array(), 'xataface/forgot_password/sent_email.html');
00060                                         exit;
00061                                 }
00062                                 
00063                                 
00064                         } else {
00065                         
00066                                 
00067                                 df_display(array(), 'xataface/forgot_password/form.html');
00068                                 exit;
00069                         }
00070                 } catch ( Exception $ex ){
00071                 
00072                         if ( @$query['--format'] == 'json' ){
00073                                 $this->response(array(
00074                                         'code'=>$ex->getCode(),
00075                                         'message'=>$ex->getMessage()
00076                                 ));
00077                                 exit;
00078                         } else {
00079                                 df_display(array('error'=>$ex->getMessage()), 'xataface/forgot_password/form.html');
00080                         }
00081                 
00082                 }
00083                 
00084                 
00085                 
00086         }
00087         
00088         
00089         function response($p){
00090                 header('Content-type: text/json; charset="'.Dataface_Application::getInstance()->_conf['oe'].'"');
00091                 echo json_encode($p);
00092                 
00093         }
00094         
00098         function create_reset_password_table(){
00099                 $table = self::$TABLE_RESET_PASSWORD;
00100                 $res = mysql_query("create table if not exists `{$table}` (
00101                         request_id int(11) auto_increment primary key,
00102                         request_uuid binary(32),
00103                         username varchar(255),
00104                         request_ip int(11),
00105                         date_created datetime,
00106                         expires int(11),
00107                         key (request_uuid) )", df_db());
00108                 if ( !$res ) throw new Exception(mysql_error(df_db()));
00109                 
00110         }
00111         
00112         
00116         function clear_expired(){
00117                 $table = self::$TABLE_RESET_PASSWORD;
00118                 $res = mysql_query("delete from `{$table}` where expires < ".time(), df_db());
00119                 if ( !$res ) throw new Exception(mysql_error(df_db()));
00120                 
00121                 
00122         
00123         }
00124         
00125         
00126         function send_reset_email_for_username($username){
00127                 $auth = Dataface_AuthenticationTool::getInstance();
00128                 $usernameCol = $auth->usernameColumn;
00129                 if ( !$usernameCol ) throw new Exception("No username Column found in the users table.  Please specify one using the username_column directive in the [_auth] section of the conf.ini file.", self::$EX_NO_EMAIL_COLUMN_FOUND);
00130                 
00131                 $people = df_get_records_array($auth->usersTable, array($usernameCol => '='.$username));
00132                 if ( !$people ) throw new Exception("No account found with that username", self::$EX_NO_USERS_FOUND_WITH_USERNAME);
00133                 if ( count($people) > 1 ){
00134                         throw new Exception("Multiple users found with same username", self::$EX_MULTIPLE_USERS_WITH_SAME_USERNAME);
00135                         
00136                 } else {
00137                 
00138                         $this->send_reset_email_for_user($people[0]);
00139                         
00140                 }
00141         
00142         }
00143         
00144         
00145         
00146         
00158         function send_reset_email_for_email($email){
00159                 $auth = Dataface_AuthenticationTool::getInstance();
00160                 $emailCol = $auth->getEmailColumn();
00161                 if ( !$emailCol ) throw new Exception("No Email Column found in the users table.  Please specify one using the email_column directive in the [_auth] section of the conf.ini file.", self::$EX_NO_EMAIL_COLUMN_FOUND);
00162                 
00163                 $people = df_get_records_array($auth->usersTable, array($emailCol => '='.$email));
00164                 if ( !$people ) throw new Exception("No account found with that email address", self::$EX_NO_USERS_WITH_EMAIL);
00165                 if ( count($people) > 1 ){
00166                         throw new Exception("Multiple users found with same email address", self::$EX_MULTIPLE_USERS_WITH_SAME_EMAIL);
00167                         
00168                 } else {
00169                         $this->send_reset_email_for_user($people[0]);
00170                         
00171                 }
00172                 
00173                 
00174         }
00175         
00186         public function send_reset_email_for_user(Dataface_Record $user){
00187                 $app = Dataface_Application::getInstance();
00188                 $auth = Dataface_AuthenticationTool::getInstance();
00189                 $emailCol = $auth->getEmailColumn();
00190                 $usernameCol = $auth->usernameColumn;
00191                 
00192                 if ( !$emailCol ) throw new Exception("No Email Column found in the users table.  Please specify one using the email_column directive in the [_auth] section of the conf.ini file.", self::$EX_NO_EMAIL_COLUMN_FOUND);
00193                 if ( !$usernameCol ) throw new Exception("No username column found in the users table. Please specify one using the username_column directive in the [_auth] section of the conf.ini file.", self::$EX_NO_USERNAME_COLUMN_FOUND);
00194                 if ( !$user ) throw new Exception("Cannot send email for null user", self::$EX_NO_USERS_FOUND_WITH_EMAIL);
00195                 
00196                 
00197                 $username = $user->val($usernameCol);
00198                 if ( !$username ){
00199                         throw new Exception("Cannot reset password for user without a username", self::$EX_NO_USERNAME_FOR_USER);       
00200                 }
00201                 
00202                 $email = $user->val($emailCol);
00203                 if ( !$email ) throw new Exception("User has not email address on file", $EX_NO_EMAIL_FOR_USER);
00204                 
00205                 
00206                 $ip = null;
00207                 $val = ip2long($_SERVER['REMOTE_ADDR']);
00208                 if ( $val !== false ){
00209                         $ip = sprintf('%u', $val );
00210                 }
00211                 
00212                 // Insert the entry
00213                 $this->create_reset_password_table();
00214                 $table = self::$TABLE_RESET_PASSWORD;
00215                 $sql = "insert into `{$table}`
00216                         (`request_uuid`, `username`, `request_ip`, `date_created`, `expires`)
00217                         values
00218                         (UUID(),'".addslashes($username)."','".addslashes($ip)."', NOW(), ".(time()+600).")";
00219                 $res = mysql_query($sql, df_db());
00220                 if ( !$res ) throw new Exception(mysql_error(df_db()));
00221                 $id = mysql_insert_id(df_db());
00222                 
00223                 $res = mysql_query("select * from `{$table}` where request_id='".addslashes($id)."'", df_db());
00224                 if ( !$res ) throw new Exception(mysql_error(df_db()));
00225                 
00226                 $row = mysql_fetch_assoc($res);
00227                 if ( !$row ) throw new Exception("Failed to fetch reset password request row from database after it has been inserted.  This should never happen ... must be a bug");
00228                 
00229                 $uuid = $row['request_uuid'];
00230                 if ( !$uuid ) throw new Exception("Blank uuid for the reset request.  This should never happen.  Must be a bug.");
00231                 
00232                 $url = df_absolute_url(DATAFACE_SITE_HREF.'?-action=forgot_password&--uuid='.$uuid);
00233                 $site_url = df_absolute_url(DATAFACE_SITE_URL);
00234                 
00235                 $msg = <<<END
00236 You have requested to reset the password for the user '$username'.
00237 Please go to the URL below in order to proceed with resetting your password:
00238 <$url>
00239 
00240 If you did not make this request, please disregard this email.
00241 END;
00242 
00243                 $subject = 'Password Reset';
00244                 
00245                 
00246                 $del = $app->getDelegate();
00247                 $info = array();
00248                 if ( isset($del) and method_exists($del, 'getResetPasswordEmailInfo') ){
00249                         $info = $del->getResetPasswordEmailInfo($user, $url);
00250                 }
00251                 
00252                 if ( isset($info['subject']) ) $subject = $info['subject'];
00253                 if ( isset($info['message']) ) $msg = $info['message'];
00254                 $parameters = null;
00255                 if ( isset($info['parameters']) ) $parameters = $info['parameters'];
00256                 
00257                 
00258                 
00259                 $site_title = $app->getSiteTitle();
00260                 $support_email = $_SERVER['SERVER_ADMIN'];
00261                 if ( isset($app->_conf['admin_email']) ) $support_email = $app->_conf['admin_email'];
00262                 if ( isset($app->_conf['support_email']) ) $support_email = $app->_conf['support_email'];
00263                 
00264                 
00265                 $headers = 'From: '.$site_title.' <'.$support_email.'>'."\r\nReply-to: ".$site_title." <".$support_email.">";
00266                 if ( isset($info['headers']) ) $headers = $info['headers'];
00267                 //echo "Subject: $subject \nEmail: $email \n$msg \nHeaders: $headers";exit;
00268                 if ( @$app->_conf['_mail']['func'] ) $func = $app->_conf['_mail']['func'];
00269                 else $func = 'mail';
00270                 $res = $func($email,
00271                                         $subject,
00272                                         $msg,
00273                                         $headers,
00274                                         $parameters);
00275                 if ( !$res ){
00276                         throw new Exception('Failed to send activation email.  Please try again later.', DATAFACE_E_ERROR);
00277                 } else {
00278                         //echo "Successfully sent mail to $email";exit;
00279                         return true;
00280                 }
00281                 
00282                 
00283                 
00284         }
00285         
00286         
00287         
00288         public function reset_password_with_uuid($uuid){
00289                 $auth = Dataface_AuthenticationTool::getInstance();
00290                 $app = Dataface_Application::getInstance();
00291         
00292                 $this->create_reset_password_table();
00293                 $this->clear_expired();
00294                 $table = self::$TABLE_RESET_PASSWORD;
00295                 $res = mysql_query("select * from `{$table}` where request_uuid='".addslashes($uuid)."' limit 1", df_db());
00296                 if ( !$res ) throw new Exception(mysql_error(df_db()));
00297                 $row = mysql_fetch_assoc($res);
00298                 if ( !$row ) throw new Exception("No such reset request could be found", self::$EX_NO_SUCH_UUID);
00299                 
00300                 if ( !$row['username'] ){
00301                         throw new Exception("Attempt to reset password for user with null username", self::$EX_NO_USERNAME_FOR_USER);
00302                         
00303                 }
00304                 $username = $row['username'];
00305                 
00306                 
00307                 
00308                 
00309                 @mysql_free_result($res);
00310                 
00311                 
00312                 
00313                 // now that we have the username, let's reset the password.
00314                 //$rand = strval(rand())."".$uuid;
00315                 $rand = md5($uuid);
00316                 error_log("Rand is ".$rand);
00317                 $pw = '';
00318                 for ( $i=0; $i<=16; $i+=2 ){
00319                         $pw .= $rand{$i};
00320                 }
00321                 $password = $pw;
00322                 //error_log("Password is $password");
00323                 $user = df_get_record($auth->usersTable, array($auth->usernameColumn => '='.$username));
00324                 if ( !$user ){
00325                         throw new Exception("No user account found with that username", self::$EX_USER_NOT_FOUND);
00326                         
00327                 }
00328                 $emailColumn = $auth->getEmailColumn();
00329                 if ( !$emailColumn ) throw new Exception("No email column found in the users table", self::$EX_NO_EMAIL_COLUMN_FOUND);
00330                 $email = $user->val($emailColumn);
00331                 
00332                 if ( !$email ){
00333                         throw new Exception("User has account has no email address on record.  Please contact support to reset the password", self::$EX_NO_EMAIL_FOR_USER);
00334                         
00335                 }
00336                 
00337                 
00338                 $user->setValue($auth->passwordColumn, $password);
00339                 $res = $user->save();
00340                 if ( PEAR::isError($res) ){
00341                         throw new Exception($res->getMessage());
00342                 }
00343                 
00344                 
00345                 // Let's delete this request from the password reset requests.
00346                 $this->delete_request_with_uuid($uuid);
00347                 
00348                 // Now let's send the email.
00349                 $del = $app->getDelegate();
00350                 $info = array();
00351                 if ( isset($del) and method_exists($del, 'getPasswordChangedEmailInfo') ){
00352                         $info = $del->getPasswordChangedEmailInfo($user, $password);
00353                 }
00354                 
00355                 $subject = 'Password Changed';
00356                 if ( isset($info['subject']) ) $subject = $info['subject'];
00357                 
00358                 
00359                 $site_url = df_absolute_url(DATAFACE_SITE_HREF);
00360                 
00361                 $msg = <<<END
00362 Your new temporary password is
00363 $password
00364 
00365 You can change your password as follows:
00366 
00367 1. Log in with your temporary password at <$site_url?-action=login>
00368 2. Click on the "My Profile" link in the upper right of the page
00369 3. Click on the "Edit" tab.
00370 4. Change your password in the edit form and click "Save" when done.
00371 END;
00372 
00373                 if ( isset($info['message']) ) $msg = $info['message'];
00374                 
00375                 $parameters = null;
00376                 if ( isset($info['parameters']) ) $parameters = $info['parameters'];
00377                 
00378                 
00379                 
00380                 $site_title = $app->getSiteTitle();
00381                 $support_email = $_SERVER['SERVER_ADMIN'];
00382                 if ( isset($app->_conf['admin_email']) ) $support_email = $app->_conf['admin_email'];
00383                 if ( isset($app->_conf['support_email']) ) $support_email = $app->_conf['support_email'];
00384                 
00385                 $headers = 'From: '.$site_title.' <'.$support_email.'>'."\r\nReply-to: ".$site_title." <".$support_email.">";
00386                 if ( isset($info['headers']) ) $headers = $info['headers'];
00387                 
00388                 
00389                 if ( @$app->_conf['_mail']['func'] ) $func = $app->_conf['_mail']['func'];
00390                 else $func = 'mail';
00391                 $res = $func($email,
00392                                         $subject,
00393                                         $msg,
00394                                         $headers,
00395                                         $parameters);
00396                 if ( !$res ){
00397                         return PEAR::raiseError('Failed to send activation email.  Please try again later.', DATAFACE_E_ERROR);
00398                 } else {
00399                         return true;
00400                 }
00401                 
00402                 
00403                 
00404                 
00405         }
00406         
00407         function delete_request_with_uuid($uuid){
00408                 $table = self::$TABLE_RESET_PASSWORD;
00409                 $res = mysql_query("delete from `{$table}` where request_uuid='".addslashes($uuid)."' limit 1", df_db());
00410                 if ( !$res ) throw new Exception(mysql_error(df_db()));
00411                 
00412         }
00413 }
 All Data Structures Namespaces Files Functions Variables Enumerations