Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
76.92% |
20 / 26 |
CRAP | |
84.91% |
90 / 106 |
User | |
0.00% |
0 / 1 |
|
76.92% |
20 / 26 |
66.78 | |
84.91% |
90 / 106 |
__construct(FAPI $storageAPI, \aae\app\Session $session = NULL, $options = NULL, \aae\app\Image $image = NULL) | |
100.00% |
1 / 1 |
5 | |
100.00% |
8 / 8 |
|||
toArray() | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 5 |
|||
getImage() | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 3 |
|||
createUser($userName, $password, $userEmail) | |
100.00% |
1 / 1 |
1 | |
100.00% |
4 / 4 |
|||
updateUser($userId, $userName, $password, $userEmail) | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
verify($email, $code) | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
login($email, $password, $LoginType = 1) | |
100.00% |
1 / 1 |
2 | |
100.00% |
8 / 8 |
|||
cookieLogin() | |
100.00% |
1 / 1 |
7 | |
100.00% |
16 / 16 |
|||
setLoginCookie($deviceName) | |
100.00% |
1 / 1 |
3 | |
100.00% |
6 / 6 |
|||
unsetLoginCookie($deviceName) | |
100.00% |
1 / 1 |
2 | |
100.00% |
2 / 2 |
|||
getAllPersistentLogins() | |
100.00% |
1 / 1 |
2 | |
100.00% |
5 / 5 |
|||
logout() | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 5 |
|||
updateUserDetails($firstName, $lastName, $phoneNbr, $address, $city, $zip, $state, $country) | |
100.00% |
1 / 1 |
2 | |
100.00% |
2 / 2 |
|||
getUserDetails() | |
100.00% |
1 / 1 |
2 | |
100.00% |
5 / 5 |
|||
isLoggedIn() | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
getEmail() | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
getId() | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
requestPasswordResetCode($email) | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
resetPassword($email, $newPassword, $resetCode) | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
_loginSessionManagement($email, $userId) | |
100.00% |
1 / 1 |
1 | |
100.00% |
4 / 4 |
|||
_validCookie($cookie) | |
100.00% |
1 / 1 |
10 | |
100.00% |
11 / 11 |
|||
_validateCookie($cookie) | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
_restoreFromSession() | |
100.00% |
1 / 1 |
1 | |
100.00% |
3 / 3 |
|||
getCode($length) | |
100.00% |
1 / 1 |
1 | |
100.00% |
4 / 4 |
|||
createPWHash($password) | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
verifyPWHash($password, $hash) | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
<?php | |
/** | |
* | |
*/ | |
namespace aae\app { | |
use \aae\db\FunctionAPI as FAPI; | |
/** | |
* @author Axel Ancona Esselmann | |
* @package aae\app | |
*/ | |
class User extends \aae\db\Persistable implements UserInterface { | |
private $_cost, $_storageAPI, $_remoteAddr; | |
protected $image, $userName, $userId = 0, $email; | |
const COOKIE_LOGIN = 2; | |
/** | |
* @param \aae\db\StorageAPI $storageAPI An API that maps application function calls to storage function calls | |
* @param \aae\app\Session $session [description] | |
* @param array An associative array with options. | |
* cost: determines computational effort for password hashes. | |
*/ | |
public function __construct(FAPI $storageAPI, \aae\app\Session $session = NULL, $options = NULL, \aae\app\Image $image = NULL) { | |
parent::__construct($storageAPI); | |
$this->_cost = (is_array($options) && array_key_exists("cost", $options) && is_int($options["cost"])) ? $options["cost"] : 10; | |
$this->_storageAPI = $storageAPI; | |
$this->_remoteAddr = (array_key_exists('REMOTE_ADDR', $_SERVER)) ? $_SERVER['REMOTE_ADDR'] : 0; | |
$this->_session = $session; | |
$this->_restoreFromSession(); | |
$this->image = $image; | |
} | |
public function toArray() { | |
return [ | |
"userId" => $this->userId, | |
"email" => $this->getEmail(), | |
"userName" => $this->userName, | |
"image" => $this->getImage(), | |
"promotional" => true | |
]; | |
} | |
public function getImage() { | |
if (!is_null($this->image)) { | |
return $this->image->getUrl($this->userId); | |
} | |
return NULL; | |
} | |
/** | |
* creates a new user and returns the verification code | |
* @param string $userName | |
* @param string $password The plaint-ext password | |
* @param string $userEmail | |
* @return string The verification code required by verify() | |
*/ | |
public function createUser($userName, $password, $userEmail) { | |
$hash = $this->createPWHash($password); | |
$code = $this->getCode(252); // change this once I fix the DB | |
$this->_storageAPI->createUser($userName, $hash, $userEmail, $code, $this->_remoteAddr); | |
return $code; | |
} | |
public function updateUser($userId, $userName, $password, $userEmail) { | |
throw new \Exception("Not implemented", 1); | |
} | |
/** | |
* Verify the email address the user provided during registration | |
* | |
* @param string $email User's email given during registration | |
* @param string $code Code given to user during registration | |
* @return bool | |
*/ | |
public function verify($email, $code) { | |
return (bool)$this->_storageAPI->verifyEmail($email, $code); | |
} | |
/** | |
* Login works for accounts with a verified email address | |
* @param string $email Verified email | |
* @param string $password Plain-text password | |
* @param int $LoginType Integer value signifying browser or application logins | |
* @return boolean True when login was successful | |
*/ | |
public function login($email, $password, $LoginType = 1) { | |
// $passwordHash = $this->createPWHash($password); | |
$hash = $this->_storageAPI->getPasswordHash($email); | |
$success = $this->verifyPWHash($password, $hash); | |
$userId = (int)$this->_storageAPI->logLogin($email, $success, $LoginType, $this->_remoteAddr); | |
if ($success) { | |
$this->_loginSessionManagement($email, $userId); | |
$this->userName = $this->_storageAPI->getUserName($userId); | |
} | |
return $userId; | |
} | |
/** | |
* If A cookie with valid persistent login credentials exists, log log in with the credentials | |
* @return bool True if login was successful, otherwise return false. | |
*/ | |
public function cookieLogin() { | |
$cookie = $this->_session->getLoginCookie(); | |
$noErrors = $this->_validateCookie($cookie); | |
if ($noErrors) { | |
$this->email = $cookie["email"]; | |
$hashedNewCookieCode = $this->setLoginCookie($cookie["deviceName"]); | |
if (!($hashedNewCookieCode !== false)) throw new \Exception("An error occurred when setting a new login cookie, after a valid login cookie was presented.", 1030140012); | |
$userId = $this->_storageAPI->logLogin($cookie["email"], true, self::COOKIE_LOGIN, $this->_remoteAddr); | |
$this->_loginSessionManagement($cookie["email"], $userId); | |
$this->userName = $this->_storageAPI->getUserName($userId); | |
return true; | |
} else if (is_array($cookie) && array_key_exists("email", $cookie) && !is_null($cookie["email"]) && $cookie["email"] != '') { | |
# Previously used login cookie presented. Possible attempt at stealing login credentials! | |
$this->_storageAPI->logLogin($cookie["email"], 0, self::COOKIE_LOGIN, $this->_remoteAddr); | |
$this->_storageAPI->remove_all_persistent_logins($cookie["email"]); | |
# TODO: Catch all tampering exceptions and for this one warn the user that something foul might be going on. | |
$this->_session->unsetLoggedIn(); | |
throw new LoginException("Invalid login cookie presented. Possible attempt at stealing persistent login credentials.", 1030141258); | |
} | |
return false; | |
} | |
/** | |
* Create a persistent credential login cookie. | |
* User has to be logged in. | |
* @param string $cookieUserEmail Users email | |
* @param string $deviceName A user defined name to identify the device with the credentials. | |
*/ | |
public function setLoginCookie($deviceName) { | |
if (is_null($this->getEmail())) throw new \Exception("Trying to create login cookie without being logged in.", 1029141812); | |
$plainNewCokieCode = $this->getCode(128); | |
$this->_session->setLoginCookie($this->getEmail(), $deviceName, $plainNewCokieCode); | |
$hashedNewCookieCode = $this->createPWHash($plainNewCokieCode); | |
#var_dump($this->getEmail()); | |
$noErrors = (bool)$this->_storageAPI->set_persistent_login($hashedNewCookieCode, $this->getEmail(), $deviceName, $this->_session->getUserAgent()); | |
return ($noErrors) ? $hashedNewCookieCode : false; | |
} | |
public function unsetLoginCookie($deviceName) { | |
if (!$this->_session->isLoggedIn()) throw new \Exception("Trying to unset a login cookie without being logged in.", 1030141121); | |
return (int)$this->_storageAPI->unset_persistent_login($this->getEmail(), $deviceName); | |
} | |
/** | |
* When logged in returns all active persistent logins | |
* @return array array of device names and browser info | |
*/ | |
public function getAllPersistentLogins() { | |
if (!$this->_session->isLoggedIn()) throw new \Exception("Trying to access persistent logins without being logged in.", 1030141030); | |
$this->_storageAPI->setFetchMode(FAPI::FETCH_NUM_ARRAY); | |
$result = $this->_storageAPI->get_all_persistent_logins($this->getEmail()); | |
$this->_storageAPI->setFetchMode(FAPI::RESET); | |
return $result; | |
} | |
/** | |
* Destroys the session and removes the device as a persistent login | |
*/ | |
public function logout() { | |
$cookie = $this->_session->getLoginCookie(); | |
if (array_key_exists("deviceName", $cookie)) { | |
$this->unsetLoginCookie($cookie["deviceName"]); | |
} | |
return $this->_session->unsetLoggedIn(); | |
} | |
public function updateUserDetails($firstName, $lastName, $phoneNbr, $address, $city, $zip, $state, $country) { | |
if (!$this->_session->isLoggedIn()) throw new \Exception("Has to be logged in to update.", 1207141819); | |
return (bool)$this->_storageAPI->updateUserDetails($this->userId, $firstName, $lastName, $phoneNbr, $address, $city, $zip, $state, $country); | |
} | |
public function getUserDetails() { | |
if (!$this->_session->isLoggedIn()) throw new \Exception("Has to be logged in to retrieve user details.", 1208141305); | |
$this->_storageAPI->setFetchMode(FAPI::FETCH_ASS_ARRAY | FAPI::FETCH_ONE_ROW); | |
$result = $this->_storageAPI->getUserDetails($this->userId); | |
$this->_storageAPI->setFetchMode(FAPI::RESET); | |
return $result; | |
} | |
public function isLoggedIn() { | |
return $this->_session->isLoggedIn(); | |
} | |
public function getEmail() { | |
return $this->email; | |
} | |
public function getId() { | |
return $this->userId; | |
} | |
/** | |
* Generates code required by resetPassword() | |
* @param string $email A registered email | |
* @return string/false A code accepted by resetPassword() or false | |
*/ | |
public function requestPasswordResetCode($email) { | |
$resetCode = $this->getCode(252); // change this once I fix the DB | |
$success = (bool)$this->_storageAPI->requestPasswordReset($email, $resetCode, $this->_remoteAddr); | |
return ($success) ? $resetCode : false; | |
} | |
/** | |
* Reset a password with a reset code generated by requestPasswordResetCode() | |
* @param string $email A registered email | |
* @param string $newPassword The new password in plain-text | |
* @param string $resetCode Code generated with requestPasswordResetCode | |
* @return boolean True if reset was successful | |
*/ | |
public function resetPassword($email, $newPassword, $resetCode) { | |
$passwordHash = $this->createPWHash($newPassword); | |
return (bool)$this->_storageAPI->resetPassword($email, $passwordHash, $resetCode); | |
} | |
private function _loginSessionManagement($email, $userId) { | |
$this->_session["aae_app_User"] = ["email" => $email, "userId" => $userId]; | |
$this->_restoreFromSession(); | |
$this->_session->setLoggedIn($email); | |
} | |
protected function _validCookie($cookie) { | |
return ( | |
is_array($cookie) && | |
array_key_exists("email", $cookie) && | |
array_key_exists("code", $cookie) && | |
array_key_exists("deviceName", $cookie) && | |
!is_null($cookie["email"]) && | |
!is_null($cookie["code"]) && | |
!is_null($cookie["deviceName"]) && | |
$cookie["email"] != '' && | |
$cookie["code"] != '' && | |
$cookie["deviceName"] != '' | |
); | |
} | |
private function _validateCookie($cookie) { | |
if (!$this->_validCookie($cookie)) return false; | |
$hashedFromDb = $this->_storageAPI->get_persistent_login($cookie["deviceName"], $cookie["email"]); | |
return $valid = (bool)$this->verifyPWHash($cookie["code"], $hashedFromDb); | |
} | |
private function _restoreFromSession() { | |
$this->email = $this->_session["aae_app_User"]["email"]; | |
$this->userId = $this->_session["aae_app_User"]["userId"]; | |
} | |
public function getCode($length) { | |
$code = base64_encode(openssl_random_pseudo_bytes(3 * ($length >> 2))); | |
$code = str_replace("+", "-", $code); | |
$code = str_replace("/", "_", $code); | |
return $code; | |
} | |
public function createPWHash($password) { | |
return password_hash($password, PASSWORD_BCRYPT, ['cost' => $this->_cost]); | |
} | |
public function verifyPWHash($password, $hash) { | |
return password_verify($password, $hash); | |
} | |
} | |
} |