Browse files

New Action Recorder module to check and limit customer password resets.

  • Loading branch information...
1 parent 3b544ed commit 22dc7e8c538b962367ee0c4e44ba001ca3216a02 @haraldpdl haraldpdl committed Jul 15, 2012
View
15 catalog/includes/languages/english/modules/action_recorder/ar_reset_password.php
@@ -0,0 +1,15 @@
+<?php
+/*
+ $Id$
+
+ osCommerce, Open Source E-Commerce Solutions
+ http://www.oscommerce.com
+
+ Copyright (c) 2012 osCommerce
+
+ Released under the GNU General Public License
+*/
+
+ define('MODULE_ACTION_RECORDER_RESET_PASSWORD_TITLE', 'Customer Password Reset');
+ define('MODULE_ACTION_RECORDER_RESET_PASSWORD_DESCRIPTION', 'Record usage of customer password resets.');
+?>
View
2 catalog/includes/languages/english/password_forgotten.php
@@ -23,4 +23,6 @@
define('EMAIL_PASSWORD_RESET_SUBJECT', STORE_NAME . ' - New Password');
define('EMAIL_PASSWORD_RESET_BODY', 'A new password has been requested for your account at ' . STORE_NAME . '.' . "\n\n" . 'Please follow this personal link to securely change your password:' . "\n\n" . '%s' . "\n\n" . 'This link will be automatically discarded after 24 hours or after your password has been changed.' . "\n\n" . 'For help with any of our online services, please email the store-owner: ' . STORE_OWNER_EMAIL_ADDRESS . '.' . "\n\n");
+
+define('ERROR_ACTION_RECORDER', 'Error: A password reset link has already been sent. Please try again in %s minutes.');
?>
View
70 catalog/includes/modules/action_recorder/ar_reset_password.php
@@ -0,0 +1,70 @@
+<?php
+/*
+ $Id$
+
+ osCommerce, Open Source E-Commerce Solutions
+ http://www.oscommerce.com
+
+ Copyright (c) 2012 osCommerce
+
+ Released under the GNU General Public License
+*/
+
+ class ar_reset_password {
+ var $code = 'ar_reset_password';
+ var $title;
+ var $description;
+ var $sort_order = 0;
+ var $minutes = 5;
+ var $attempts = 1;
+ var $identifier;
+
+ function ar_reset_password() {
+ $this->title = MODULE_ACTION_RECORDER_RESET_PASSWORD_TITLE;
+ $this->description = MODULE_ACTION_RECORDER_RESET_PASSWORD_DESCRIPTION;
+
+ if ($this->check()) {
+ $this->minutes = (int)MODULE_ACTION_RECORDER_RESET_PASSWORD_MINUTES;
+ $this->attempts = (int)MODULE_ACTION_RECORDER_RESET_PASSWORD_ATTEMPTS;
+ }
+ }
+
+ function setIdentifier() {
+ $this->identifier = tep_get_ip_address();
+ }
+
+ function canPerform($user_id, $user_name) {
+ $check_query = tep_db_query("select id from " . TABLE_ACTION_RECORDER . " where module = '" . tep_db_input($this->code) . "' and user_name = '" . tep_db_input($user_name) . "' and date_added >= date_sub(now(), interval " . (int)$this->minutes . " minute) and success = 1 order by date_added desc limit " . (int)$this->attempts);
+ if (tep_db_num_rows($check_query) == $this->attempts) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ function expireEntries() {
+ global $db_link;
+
+ tep_db_query("delete from " . TABLE_ACTION_RECORDER . " where module = '" . $this->code . "' and date_added < date_sub(now(), interval " . (int)$this->minutes . " minute)");
+
+ return mysql_affected_rows($db_link);
+ }
+
+ function check() {
+ return defined('MODULE_ACTION_RECORDER_RESET_PASSWORD_MINUTES');
+ }
+
+ function install() {
+ tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) VALUES ('Allowed Minutes', 'MODULE_ACTION_RECORDER_RESET_PASSWORD_MINUTES', '5', 'Number of minutes to allow password resets to occur.', '6', '0', now())");
+ tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) VALUES ('Allowed Attempts', 'MODULE_ACTION_RECORDER_RESET_PASSWORD_ATTEMPTS', '1', 'Number of password reset attempts to allow within the specified period.', '6', '0', now())");
+ }
+
+ function remove() {
+ tep_db_query("delete from " . TABLE_CONFIGURATION . " where configuration_key in ('" . implode("', '", $this->keys()) . "')");
+ }
+
+ function keys() {
+ return array('MODULE_ACTION_RECORDER_RESET_PASSWORD_MINUTES', 'MODULE_ACTION_RECORDER_RESET_PASSWORD_ATTEMPTS');
+ }
+ }
+?>
View
26 catalog/password_forgotten.php
@@ -23,19 +23,29 @@
if (tep_db_num_rows($check_customer_query)) {
$check_customer = tep_db_fetch_array($check_customer_query);
- $reset_key = tep_create_random_value(40);
+ $actionRecorder = new actionRecorder('ar_reset_password', $check_customer['customers_id'], $email_address);
- tep_db_query("update " . TABLE_CUSTOMERS_INFO . " set password_reset_key = '" . tep_db_input($reset_key) . "', password_reset_date = now() where customers_info_id = '" . (int)$check_customer['customers_id'] . "'");
+ if ($actionRecorder->canPerform()) {
+ $actionRecorder->record();
- $reset_key_url = tep_href_link(FILENAME_PASSWORD_RESET, 'account=' . urlencode($email_address) . '&key=' . $reset_key, 'SSL', false);
+ $reset_key = tep_create_random_value(40);
- if ( strpos($reset_key_url, '&amp;') !== false ) {
- $reset_key_url = str_replace('&amp;', '&', $reset_key_url);
- }
+ tep_db_query("update " . TABLE_CUSTOMERS_INFO . " set password_reset_key = '" . tep_db_input($reset_key) . "', password_reset_date = now() where customers_info_id = '" . (int)$check_customer['customers_id'] . "'");
+
+ $reset_key_url = tep_href_link(FILENAME_PASSWORD_RESET, 'account=' . urlencode($email_address) . '&key=' . $reset_key, 'SSL', false);
+
+ if ( strpos($reset_key_url, '&amp;') !== false ) {
+ $reset_key_url = str_replace('&amp;', '&', $reset_key_url);
+ }
- tep_mail($check_customer['customers_firstname'] . ' ' . $check_customer['customers_lastname'], $email_address, EMAIL_PASSWORD_RESET_SUBJECT, sprintf(EMAIL_PASSWORD_RESET_BODY, $reset_key_url), STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);
+ tep_mail($check_customer['customers_firstname'] . ' ' . $check_customer['customers_lastname'], $email_address, EMAIL_PASSWORD_RESET_SUBJECT, sprintf(EMAIL_PASSWORD_RESET_BODY, $reset_key_url), STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);
- $password_reset_initiated = true;
+ $password_reset_initiated = true;
+ } else {
+ $actionRecorder->record(false);
+
+ $messageStack->add('password_forgotten', sprintf(ERROR_ACTION_RECORDER, (defined('MODULE_ACTION_RECORDER_RESET_PASSWORD_MINUTES') ? (int)MODULE_ACTION_RECORDER_RESET_PASSWORD_MINUTES : 5)));
+ }
} else {
$messageStack->add('password_forgotten', TEXT_NO_EMAIL_ADDRESS_FOUND);
}

0 comments on commit 22dc7e8

Please sign in to comment.