Beispiel #1
0
 /**
  * Anonymize user account by updating username to a random string 
  * and setting other user object fields (besides id) to their default values.
  * User comments are preserved. Catalog accounts, due date reminders, 
  * saved searches and lists are deleted.
  * 
  * @return boolean True on success
  */
 public function anonymizeAccount()
 {
     $conn = $this->getDatabaseConnection();
     $res = $conn->query("START TRANSACTION");
     try {
         // Delete catalog accounts
         $account = new User_account();
         $account->user_id = $this->id;
         if ($account->find(false)) {
             while ($account->fetch()) {
                 $account->delete();
             }
         }
         // Delete due date reminders
         $reminder = new Due_date_reminder();
         $reminder->user_id = $this->id;
         if ($reminder->find(false)) {
             while ($reminder->fetch()) {
                 $reminder->delete();
             }
         }
         // Delete lists (linked user_resource objects cascade)
         $list = new User_list();
         $list->user_id = $this->id;
         if ($list->find(false)) {
             while ($list->fetch()) {
                 $list->delete();
             }
         }
         // Delete saved searches
         $search = new SearchEntry();
         $search->user_id = $this->id;
         if ($search->find(false)) {
             while ($search->fetch()) {
                 $search->delete();
             }
         }
         // Anonymize user object
         $this->username = '******' . uniqid();
         $this->password = '';
         $this->firstname = '';
         $this->lastname = '';
         $this->email = '';
         $this->cat_username = '******';
         $this->cat_password = '******';
         $this->college = '';
         $this->major = '';
         $this->home_library = '';
         $this->language = '';
         $this->due_date_notification = 0;
         $this->due_date_reminder = 0;
         $this->authMethod = 'null';
         $this->update();
     } catch (Exception $e) {
         $conn->query("ROLLBACK");
         throw $e;
         return false;
     }
     $conn->query("COMMIT");
     return true;
 }
Beispiel #2
0
 /**
  * Verify that the current catalog account is in the account list
  *
  * @param object $user User
  *
  * @return void
  */
 protected static function verifyAccountInList($user)
 {
     if (!isset($user->cat_username) || !$user->cat_username) {
         return;
     }
     $account = new User_account();
     $account->user_id = $user->id;
     $account->cat_username = $user->cat_username;
     if (!$account->find(true)) {
         list($login_target, $cat_username) = explode('.', $account->cat_username, 2);
         if ($login_target && $cat_username) {
             $account->account_name = translate(array('text' => $login_target, 'prefix' => 'source_'));
         } else {
             $account->account_name = translate('Default');
         }
         $account->cat_password = $user->cat_password;
         $account->home_library = $user->home_library;
         $account->created = date('Y-m-d h:i:s');
         $account->insert();
     } else {
         if ($account->cat_password != $user->cat_password) {
             $account->cat_password = $user->cat_password;
             $account->update();
         }
     }
 }
 /**
  * Process transactions. Try to register unregistered transactions
  * and inform on expired transactions.
  *
  * @return void
  * @access public
  */
 public function process()
 {
     global $configArray;
     global $interface;
     ini_set('display_errors', true);
     $configArray = $mainConfig = readConfig();
     $datasourceConfig = getExtraConfigArray('datasources');
     // Set up time zone. N.B. Don't use msg() or other
     // functions requiring date before this.
     date_default_timezone_set($configArray['Site']['timezone']);
     $this->msg("OnlinePayment monitor started");
     // Setup Local Database Connection
     ConnectionManager::connectToDatabase();
     // Initialize Mailer
     $mailer = new VuFindMailer();
     $now = new DateTime();
     $expiredCnt = 0;
     $failedCnt = 0;
     $registeredCnt = 0;
     $remindCnt = 0;
     $user = false;
     $report = array();
     // Attempt to re-register paid transactions whose registration has failed.
     $tr = new Transaction();
     foreach ($tr->getFailedTransactions() as $t) {
         $this->msg("  Registering transaction id {$t->id} / {$t->transaction_id}");
         // check if the transaction has not been registered for too long
         $paid_time = new DateTime($t->paid);
         $diff = $now->diff($paid_time);
         $diffHours = $diff->days * 24 + $diff->h;
         if ($diffHours > $this->expireHours) {
             if (!isset($report[$t->driver])) {
                 $report[$t->driver] = 0;
             }
             $report[$t->driver]++;
             $expiredCnt++;
             if (!$t->setTransactionReported($t->transaction_id)) {
                 $this->err('    Failed to update transaction ' . $t->transaction_id . 'as reported');
             }
             $transaction = clone $t;
             $transaction->complete = Transaction::STATUS_REGISTRATION_EXPIRED;
             if ($transaction->update($t) === false) {
                 $this->err('    Failed to update transaction ' . $t->transaction_id . 'as expired.');
             } else {
                 $this->msg('    Transaction ' . $t->transaction_id . ' expired.');
             }
         } else {
             if ($user === false || $t->user_id != $user->id) {
                 $user = User::staticGet($t->user_id);
             }
             $catalog = ConnectionManager::connectToCatalog();
             if ($catalog && $catalog->status) {
                 $account = new User_account();
                 $account->user_id = $t->user_id;
                 $account->cat_username = $t->cat_username;
                 if ($account->find(true)) {
                     if (!($patron = $catalog->patronLogin($t->cat_username, $account->cat_password))) {
                         $this->err('    Could not perform patron login for transaction ' . $t->transaction_id);
                         $failedCnt++;
                         continue;
                     }
                 }
                 $res = $catalog->markFeesAsPaid($patron, $t->amount);
                 if ($res === true) {
                     if (!$t->setTransactionRegistered($t->transaction_id)) {
                         $this->err('    Failed to update transaction ' . $t->transaction_id . 'as registered');
                     }
                     $registeredCnt++;
                 } else {
                     $t->setTransactionRegistrationFailed($t->transaction_id, $res);
                     $failedCnt++;
                     $this->msg('    Registration of transaction ' . $t->transaction_id . ' failed');
                     $this->msg("      {$res}");
                 }
             } else {
                 $this->err("Failed to connect to catalog ({$patronId})");
                 continue;
             }
         }
     }
     // Report paid and unregistered transactions whose registration
     // can not be re-tried:
     $tr = new Transaction();
     foreach ($tr->getUnresolvedTransactions($this->reportIntervalHours) as $t) {
         $this->msg("  Transaction id {$t->transaction_id} still unresolved.");
         if (!$t->setTransactionReported($t->transaction_id)) {
             $this->err('    Failed to update transaction ' . $t->transaction_id . ' as reported');
         }
         if (!isset($report[$t->driver])) {
             $report[$t->driver] = 0;
         }
         $report[$t->driver]++;
         $remindCnt++;
     }
     if ($registeredCnt) {
         $this->msg("  Total registered: {$registeredCnt}");
     }
     if ($expiredCnt) {
         $this->msg("  Total expired: {$expiredCnt}");
     }
     if ($failedCnt) {
         $this->msg("  Total failed: {$failedCnt}");
     }
     if ($remindCnt) {
         $this->msg("  Total to be reminded: {$remindCnt}");
     }
     $configArray = readConfig();
     $siteLocal = $configArray['Site']['local'];
     $interface = new UInterface($siteLocal);
     // Send report of transactions that need to be resolved manually:
     foreach ($report as $driver => $cnt) {
         if ($cnt) {
             $settings = getExtraConfigArray("VoyagerRestful_{$driver}");
             if (!$settings || !isset($settings['OnlinePayment']['errorEmail'])) {
                 $this->err("  Error email for expired transactions not defined for driver {$driver} ({$cnt} expired transactions)");
                 continue;
             }
             $email = $settings['OnlinePayment']['errorEmail'];
             $this->msg("  [{$driver}] Inform {$cnt} expired transactions for driver {$driver} to {$email}");
             $mailer = new VuFindMailer();
             $subject = "Finna: ilmoitus tietokannan {$driver} epäonnistuneista verkkomaksuista";
             $interface->assign('driver', $driver);
             $interface->assign('cnt', $cnt);
             $msg = $interface->fetch('Emails/online-payment-error.tpl');
             if (!($result = $mailer->send($email, $this->fromEmail, $subject, $msg))) {
                 $this->err("    Failed to send error email to customer: {$email}");
             }
         }
     }
     $this->msg("OnlinePayment monitor completed");
     $this->reportErrors();
 }
 /**
  * Send due date reminders
  *
  * @return void
  */
 public function send()
 {
     global $configArray;
     global $interface;
     global $translator;
     $iso8601 = 'Y-m-d\\TH:i:s\\Z';
     ini_set('display_errors', true);
     $configArray = $mainConfig = readConfig();
     $datasourceConfig = getExtraConfigArray('datasources');
     $siteLocal = $configArray['Site']['local'];
     // Set up time zone. N.B. Don't use msg() or other functions requiring date before this.
     date_default_timezone_set($configArray['Site']['timezone']);
     $this->msg('Sending due date reminders');
     // Setup Local Database Connection
     ConnectionManager::connectToDatabase();
     // And index
     $db = ConnectionManager::connectToIndex();
     // Initialize Mailer
     $mailer = new VuFindMailer();
     // Find all scheduled alerts
     $sql = 'SELECT * FROM "user" WHERE "due_date_reminder" > 0 ORDER BY id';
     $user = new User();
     $user->query($sql);
     $this->msg('Processing ' . $user->N . ' users');
     $interface = false;
     $institution = false;
     $todayTime = new DateTime();
     $catalog = ConnectionManager::connectToCatalog();
     while ($user->fetch()) {
         if (!$user->email || trim($user->email) == '') {
             $this->msg('User ' . $user->username . ' does not have an email address, bypassing due date reminders');
             continue;
         }
         // Initialize settings and interface
         $userInstitution = reset(explode(':', $user->username, 2));
         if (!$institution || $institution != $userInstitution) {
             $institution = $userInstitution;
             if (!isset($datasourceConfig[$institution])) {
                 foreach ($datasourceConfig as $code => $values) {
                     if (isset($values['institution']) && strcasecmp($values['institution'], $institution) == 0) {
                         $institution = $code;
                         break;
                     }
                 }
             }
             if (!($configArray = $this->readInstitutionConfig($institution))) {
                 continue;
             }
             // Start Interface
             $interface = new UInterface($siteLocal);
             $validLanguages = array_keys($configArray['Languages']);
             $dateFormat = new VuFindDate();
         }
         $language = $user->language;
         if (!in_array($user->language, $validLanguages)) {
             $language = $configArray['Site']['language'];
         }
         $translator = new I18N_Translator(array($configArray['Site']['local'] . '/lang', $configArray['Site']['local'] . '/lang_local'), $language, $configArray['System']['debug']);
         $interface->setLanguage($language);
         // Go through accounts and check loans
         $account = new User_account();
         $account->user_id = $user->id;
         if (!$account->find(false)) {
             continue;
         }
         $remindLoans = array();
         while ($account->fetch()) {
             $patron = $catalog->patronLogin($account->cat_username, $account->cat_password);
             if ($patron === null || PEAR::isError($patron)) {
                 $this->msg('Catalog login failed for user ' . $user->id . ', account ' . $account->id . ' (' . $account->cat_username . '): ' . ($patron ? $patron->getMessage() : 'patron not found'));
                 continue;
             }
             $loans = $catalog->getMyTransactions($patron);
             if (PEAR::isError($loans)) {
                 $this->msg('Could not fetch loans for user ' . $user->id . ', account ' . $account->id . ' (' . $account->cat_username . ')');
                 continue;
             }
             foreach ($loans as $loan) {
                 $dueDate = new DateTime($loan['duedate']);
                 if ($todayTime >= $dueDate || $dueDate->diff($todayTime)->days <= $user->due_date_reminder) {
                     // Check that a reminder hasn't been sent already
                     $reminder = new Due_date_reminder();
                     $reminder->user_id = $user->id;
                     $reminder->loan_id = $loan['item_id'];
                     $reminder->due_date = $dueDate->format($iso8601);
                     if ($reminder->find(false)) {
                         // Reminder already sent
                         continue;
                     }
                     // Store also title for display in email
                     $title = isset($loan['title']) ? $loan['title'] : translate('Title not available');
                     if (isset($loan['id'])) {
                         $record = $db->getRecord($loan['id']);
                         if ($record && isset($record['title'])) {
                             $title = $record['title'];
                         }
                     }
                     $remindLoans[] = array('loanId' => $loan['item_id'], 'dueDate' => $loan['duedate'], 'dueDateFormatted' => $dueDate->format(isset($configArray['Site']['displayDateFormat']) ? $configArray['Site']['displayDateFormat'] : "m-d-Y"), 'title' => $title);
                 }
             }
         }
         if ($remindLoans) {
             $this->msg(count($remindLoans) . ' new loans to remind for user ' . $user->id);
             $interface->assign('date', $dateFormat->convertToDisplayDate("U", floor(time())));
             $interface->assign('loans', $remindLoans);
             $key = $this->getSecret($user, $user->id);
             $params = array('id' => $user->id, 'type' => 'reminder', 'key' => $key);
             $unsubscribeUrl = $configArray['Site']['url'] . '/MyResearch/Unsubscribe?' . http_build_query($params);
             $interface->assign(compact('unsubscribeUrl'));
             // Load template
             $message = $interface->fetch('MyResearch/due-date-email.tpl');
             if (strstr($message, 'Warning: Smarty error:')) {
                 $this->msg("Message template processing failed: {$message}");
                 continue;
             }
             $result = $mailer->send($user->email, $configArray['Site']['email'], translate('due_date_email_subject'), $message);
             if (PEAR::isError($result)) {
                 $this->msg("Failed to send message to {$user->email}: " . $result->getMessage());
                 continue;
             }
             // Mark reminders sent
             foreach ($remindLoans as $loan) {
                 $reminder = new Due_date_reminder();
                 $reminder->user_id = $user->id;
                 $reminder->loan_id = $loan['loanId'];
                 $reminder->delete();
                 $dueDate = new DateTime($loan['dueDate']);
                 $reminder->due_date = $dueDate->format($iso8601);
                 $reminder->notification_date = gmdate($iso8601, time());
                 $reminder->insert();
             }
         } else {
             $this->msg('No loans to remind for user ' . $user->id);
         }
     }
     $this->reportErrors();
     $this->msg('Due date reminders execution completed');
 }
Beispiel #5
0
 /**
  * Register payment provided in the request.
  * This is called by JSON_Transaction.
  *
  * @param array   $params       Key-value list of request variables.
  * @param boolean $userLoggedIn Is user logged in at the time of method call.
  *
  * @return array array with keys
  *   - 'success' (boolean)
  *   - 'msg' (string) error message if payment could not be processed.
  * @access public
  */
 public function processPayment($params, $userLoggedIn = true)
 {
     global $interface;
     global $user;
     $error = false;
     $msg = null;
     $transactionId = $params['transaction'];
     $tr = new Transaction();
     if (!($t = $tr->getTransaction($transactionId))) {
         error_log("Error processing payment: transaction {$transactionId} not found");
         $error = true;
     }
     if (!$tr->isTransactionInProgress($transactionId)) {
         error_log("Error processing payment: transaction {$transactionId} already processed.");
         $error = true;
     }
     if (!$error) {
         $patron = null;
         $patronId = $t->cat_username;
         if (!$userLoggedIn) {
             // MultiBackend::getConfig expects global user object and user->cat_username to be defined.
             $user = new User();
             $user->cat_username = $patronId;
             $account = new User_account();
             $account->user_id = $t->user_id;
             $account->cat_username = $t->cat_username;
             if ($account->find(true)) {
                 $patron = $this->catalog->patronLogin($t->cat_username, $account->cat_password);
             }
             if (!$patron) {
                 error_log("Error processing payment: could not perform patron login (transaction {$transactionId})");
                 $error = true;
             }
         } else {
             $patron = UserAccount::catalogLogin();
         }
         $config = $this->catalog->getConfig('OnlinePayment');
         if ($config && $config['enabled']) {
             $paymentHandler = CatalogConnection::getOnlinePaymentHandler($patronId);
             $res = $paymentHandler->processResponse($params);
             if (is_array($res) && isset($res['markFeesAsPaid']) && $res['markFeesAsPaid']) {
                 $finesAmount = $this->catalog->getOnlinePayableAmount($patron);
                 // Check that payable sum has not been updated
                 if ($finesAmount == $res['amount']) {
                     $paidRes = $this->catalog->markFeesAsPaid($patron, $res['amount']);
                     if ($paidRes === true) {
                         $t = new Transaction();
                         if (!$t->setTransactionRegistered($res['transactionId'])) {
                             error_log("Error updating transaction {$transactionId} status: registered");
                         }
                         $_SESSION['payment_ok'] = true;
                     } else {
                         $t = new Transaction();
                         if (!$t->setTransactionRegistrationFailed($res['transactionId'], $paidRes)) {
                             error_log("Error updating transaction {$transactionId} status: registering failed");
                         }
                         $error = true;
                         $msg = translate($paidRes);
                     }
                 } else {
                     // Payable sum updated. Skip registration and inform user that payment processing has been delayed..
                     $t = new Transaction();
                     if (!$t->setTransactionFinesUpdated($res['transactionId'])) {
                         error_log("Error updating transaction {$transactionId} status: payable sum updated");
                     }
                     $error = true;
                     $msg = translate('online_payment_registration_failed');
                 }
             } else {
                 $error = true;
                 $msg = translate($res);
             }
         }
     }
     $res = array('success' => !$error);
     if ($msg) {
         $res['msg'] = $msg;
     }
     return $res;
 }
Beispiel #6
0
 /**
  * Delete an account
  *
  * @param int $id Account ID
  *
  * @return boolean Whether the account was deleted
  */
 protected function deleteAccount($id)
 {
     global $user;
     $account = new User_account();
     $account->id = $id;
     $account->user_id = $user->id;
     if ($account->find(true)) {
         $account->delete();
         if ($user->cat_username == $account->cat_username) {
             // Active account deleted, select another or deactivate
             $account = new User_account();
             $account->user_id = $user->id;
             if ($account->find(true)) {
                 UserAccount::activateCatalogAccount($account->cat_username, $account->cat_password, $account->home_library);
             } else {
                 UserAccount::activateCatalogAccount('', '', '');
             }
         }
         return true;
     }
     return false;
 }
 /**
  * Check if library card is already connected to an existing User object.
  *
  * @param array $info User details returned by ILS driver.
  *
  * @return array User objects that have the given library card connected.
  * @access private
  */
 protected function checkIfLibraryCardIsConnectedToOtherUser($info)
 {
     global $configArray;
     include_once "services/MyResearch/lib/User.php";
     include_once "services/MyResearch/lib/User_account.php";
     $account = new User_account();
     $account->cat_username = $info['cat_username'];
     $users = array();
     if ($account->find(false)) {
         $fullUsername = (isset($configArray['Site']['institution']) ? $configArray['Site']['institution'] . ':' : '') . $account->cat_username;
         while ($account->fetch()) {
             $user = new User();
             $user->id = $account->user_id;
             if ($user->find(true)) {
                 if ($user->username !== $fullUsername) {
                     $users[] = $user;
                 }
             }
         }
     }
     return $users;
 }