Files
old-wiaas-legacy/api-wiaas/server/core/User.php
2018-06-11 11:09:35 +02:00

427 lines
13 KiB
PHP

<?php
use \Firebase\JWT\JWT;
/**
* Class for identif
*/
class User{
private static $isLoggedIn;
private static $authToken;
private static $userInfo = [];
private static $userTypesTableKeys = [
'broker' => 'brokers',
'customer' => 'customers',
'commercial_lead' => 'commercial_leads',
'supplier' => 'suppliers'
];
private static $validationUsername = '';
function __construct($authToken = null){
if($authToken){
self::$authToken = str_replace('Bearer ', '', $authToken);
self::$isLoggedIn = self::validateAccessToken(self::$authToken);
}else{
self::$isLoggedIn = self::validateSession();
}
}
public function getTableByUser($userType){
return self::$userTypesTableKeys[$userType];
}
private static function validateSession(){
session_start();
if(isset($_SESSION['data'])){
self::$userInfo = $_SESSION['data'];
return true;
}
return false;
}
private static function validateAccessToken($authToken){
$secretKey = base64_decode(JWT_API_SECRET_KEY);
try {
$decodedJWT = JWT::decode($authToken, $secretKey, array(JWT_ALGORITHM));
self::$userInfo = (array) $decodedJWT->data;
return true;
} catch (Exception $e) {
self::$userInfo['errorMessage'] = $e->getMessage();
return false;
}
}
/**
* genereates a has for a password string. The value is 60 charactes MAX due to options
* @param String $password password to be hashed
* @return Sting 60 characters long hashed string
*/
public static function hashPassword($password){
$hashOptions = [
'cost' => 12
];
return password_hash($password, PASSWORD_BCRYPT, $hashOptions);
}
public static function generateApiToken($userInfo){
$tokenId = base64_encode(random_bytes(32));
$issuedAt = time();
$notBefore = $issuedAt;
$expire = $notBefore + JWT_MAX_LIFE; // 1 hour
$serverName = WIAAS_URL;
$data = [
'iat' => $issuedAt, // Issued at: time when the token was generated
'jti' => $tokenId, // Json Token Id: an unique identifier for the token
'iss' => $serverName, // Issuer
'nbf' => $notBefore, // Not before
'exp' => $expire, // Expire
'data' => $userInfo,
'type' => 'authorization_token' //Token type
];
$secretKey = base64_decode(JWT_API_SECRET_KEY);
$jwt = JWT::encode(
$data,
$secretKey,
JWT_ALGORITHM
);
return $jwt;
}
public function getRefreshToken() {
global $database;
$sql = "SELECT u.refresh_token
FROM ".TABLES['users']." u
WHERE id=".self::$userInfo['wiaas_id_user'];
$result = $database->fetchResultArray($sql);
return isset($result[0]) ? $result[0]['refresh_token'] : false;
}
private static function saveRefreshToken($userInfo, $refreshJwt){
global $database;
$sql = "UPDATE ".TABLES['users']."
SET refresh_token='$refreshJwt'
WHERE id=".$userInfo['wiaas_id_user'];
$query = $database->query($sql);
return $database->affectedRows() > 0;
}
private static function generateRefreshToken($userInfo){
global $user;
$tokenId = base64_encode(random_bytes(32));
$issuedAt = time();
$notBefore = $issuedAt;
$expire = $notBefore + (JWT_MAX_LIFE * 2); // 1 hour
$serverName = WIAAS_URL;
$data = [
'iat' => $issuedAt, // Issued at: time when the token was generated
'jti' => $tokenId, // Json Token Id: an unique identifier for the token
'iss' => $serverName, // Issuer
'nbf' => $notBefore, // Not before
'exp' => $expire, // Expire
'type' => 'refresh_token', //Token type
'data' => $userInfo
];
$secretKey = base64_decode(JWT_API_SECRET_KEY);
$jwt = JWT::encode(
$data,
$secretKey,
JWT_ALGORITHM
);
self::saveRefreshToken($userInfo, $jwt);
return $jwt;
}
public function getUserInfo() {
return self::$userInfo;
}
/**
* reutnrs if user is logged in
* @return boolean returns if a user is logged in
*/
public static function isLoggedIn(){
return self::$isLoggedIn;
}
/**
* login processing
* @param String $username username
* @param String $password password
* @return boolean true if the user is logged in
*/
public static function login($username, $password, $withToken = false){
global $database;
$username = $database->escapeValue($username);
$password = $database->escapeValue($password);
if(empty($username) OR empty($password)){
return ['status' => 'fail', 'errorMessage' => 'INVALID_USERNAME_PASSWORD'];
}
$sql = "SELECT u.id, u.username, u.password, ut.type, ut.id as idUserType, isCompanyAdmin
FROM ".TABLES['users']." u
INNER JOIN ".TABLES['rel_user_type']." rel_ut
ON rel_ut.idUser=u.id
INNER JOIN ".TABLES['user_types']." ut
ON ut.id=rel_ut.idType
WHERE u.username='".$username."'
LIMIT 1";
$query = $database->query($sql);
if($database->numRows($query) !== 1){
self::$isLoggedIn = false;
return ['status' => 'fail', 'errorMessage' => 'INVALID_USERNAME_PASSWORD'];
}
$row = $database->fetchArray($query);
if(!password_verify($password, $row['password'])){
return ['status' => 'fail', 'errorMessage' => 'INVALID_USERNAME_PASSWORD'];
}
$userTypeInfo = self::getUserTypeInfo($row['id'], $row['type']);
if(count($userTypeInfo) === 0){
return ['status' => 'fail', 'errorMessage' => 'invalid user type '.$row['type'].'. Add type in User class or add the user in the correct table!'];
}
self::$userInfo['wiaas_id_user'] = $row['id'];
self::$userInfo['wiaas_username'] = $row['username'];
self::$userInfo['wiaas_user_type'] = $row['type'];
self::$userInfo['wiaas_id_user_type'] = $row['idUserType'];
self::$userInfo['wiaas_user_full_name'] = $userTypeInfo['fullName'];
self::$userInfo['wiaas_is_company_admin'] = $row['isCompanyAdmin'] === '1' ? true : false;
self::$isLoggedIn = true;
if($withToken){
self::$authToken = self::generateApiToken(self::$userInfo);
$refreshToken = self::generateRefreshToken(self::$userInfo);
return ['status' => 'success', 'accessToken' => self::$authToken, 'refreshToken' => $refreshToken];
}else{
$_SESSION['data'] = self::$userInfo;
return ['status' => 'success'];
}
}
public function refreshToken($refreshToken, $lastActivity){
$inactivity = time() - (intval($lastActivity) / 1000);
$maxInactivity = 30 * 60; // 30 minutes
if($inactivity > $maxInactivity){//session expires if invactivity is more than 30 minutes
return ['status' => 'error', 'errorMessage' => 'EXPIRED_SESSION'];
}
if(self::validateAccessToken($refreshToken)){
self::$authToken = self::generateApiToken(self::$userInfo);
$refreshToken = self::generateRefreshToken(self::$userInfo);
return ['status' => 'success', 'accessToken' => self::$authToken, 'refreshToken' => $refreshToken];
}
return ['status' => 'error', 'errorMessage' => 'INVALID_REFRESH_TOKEN', 'extra' => $this->getErrorMessage()];
}
public static function setLastActivity(){
$_SESSION['LAST_ACTIVITY'] = time();
}
public static function getLastActivity(){
return $_SESSION['LAST_ACTIVITY'];
}
/**
* get extra info for connected user by user type
* @param Int $idUser id of the user
* @param string $userType the type of the user
* @return [Array] retruns an empty array if no info or an array with the info
*/
private static function getUserTypeInfo($idUser, $userType){
global $database;
if(!array_key_exists($userType, self::$userTypesTableKeys)){
return [];
}
$sql = "SELECT info.name AS fullName
FROM ".TABLES[self::$userTypesTableKeys[$userType]]." info
WHERE idUser=".$idUser."
LIMIT 1";
$query = $database->query($sql);
if($database->numRows($query) !== 1){
return [];
}
$row = $database->fetchArray($query);
return $row;
}
public function logout(){
session_unset();
session_destroy();
header("location:index.php");
}
/**
* get the logged username
* @return String Username
*/
public function getUser(){
return isset(self::$userInfo['wiaas_username']) ? self::$userInfo['wiaas_username'] : false;
}
/**
* get the logged id user
* @return String id suer
*/
public function getUserId(){
return isset(self::$userInfo['wiaas_id_user']) ? self::$userInfo['wiaas_id_user'] : 0;
}
/**
* get the logged user full name
* @return String full name
*/
public function getUserFullName(){
return isset(self::$userInfo['wiaas_user_full_name']) ? self::$userInfo['wiaas_user_full_name'] : false;
}
/**
* get the user type
* @return String returns the user type
*/
public function getUserType(){
return isset(self::$userInfo['wiaas_user_type']) ? self::$userInfo['wiaas_user_type'] : false;
}
/**
* get the user type id
* @return String returns the user type id
*/
public function getIdUserType(){
return isset(self::$userInfo['wiaas_id_user_type']) ? self::$userInfo['wiaas_id_user_type'] : 0;
}
public function getErrorMessage(){
return isset(self::$userInfo['errorMessage']) ? self::$userInfo['errorMessage'] : '';
}
/**
* checks whether the token from the url provided is valid or not
* @param String $token the token to check the url for
* @return String confirmation message
*/
public function checkPasswordToken($token) {
global $database;
$sql = "SELECT u.username
FROM ".TABLES['users']." u
WHERE u.token='".$database->escapeValue($token)."'
AND u.tokenTS <= DATE_ADD(u.tokenTS , INTERVAL 5 DAY)";
$result = $database->query($sql);
if($database->numRows($result) !== 1) {
return 'error';
}
self::$validationUsername = $database->fetchArray($result)['username'];
return 'success';
}
/**
* gets the username of the user that wants to reset the password
* @return String username
*/
public function getSetPasswordUsername() {
return self::$validationUsername;
}
/**
* Resets the password for the user with the right token number
* @param Array $passwords the new and confirmed passwords
* @return Array with confirmation message
*/
public function resetPassword($passwords) {
global $database;
$data = [];
if(self::$validationUsername) {
$data = UtilsModel::changePassword($passwords, self::$validationUsername);
$data['username'] = self::$validationUsername;
self::$validationUsername = '';
} else {
$data['messages'][] = [
'code' => 'error',
'message' => 'USER_NOT_SET'
];
}
return $data;
}
/**
* generatates a new password for the user given
* @param String $mail email of the user
* @return String confirtmation message
*/
public static function forgotPassword($mail) {
global $database;
$mail = $database->escapeValue($mail);
$now = new DateTime();
$now = $now->format('Y-m-d H:i:s');
$data = [];
$sql = "SELECT
u.username,
u.mail,
IF(
ADDTIME(u.tokenTS, '00:05') > '".$now."',
0,
1
) AS allowPasswordGeneration
FROM ".TABLES['users']." u
WHERE mail = '".$mail."'";
$userInfo = $database->fetchResultArray($sql);
if(count($userInfo) == 0) {
$data[] = 'NO_USER';
}
foreach ($userInfo as $info) {
if($info['allowPasswordGeneration'] == 1) {
$messageData = UtilsModel::generateTokenForUserPassword(json_encode($info));
$data[] = 'SIGN_IN';
} else {
$data[] = 'CHANGE_LATER';
}
}
return $data;
}
}