Initial commit

This commit is contained in:
Senad Uka
2018-06-11 11:09:35 +02:00
commit ed7df7b11f
1954 changed files with 483354 additions and 0 deletions

View File

@@ -0,0 +1,197 @@
<?php
class Database {
private $mysqli;
function __construct($server, $user, $password, $name){
$this->openConnection($server, $user, $password, $name);
}
private function openConnection($server, $user, $password, $name){
$this->mysqli = new mysqli($server, $user, $password, $name);
if($this->mysqli->connect_error){
trigger_error('Database connection failed!', E_USER_ERROR);
}
if (!$this->mysqli->set_charset("utf8")) {
trigger_error('Error loading character set '.$mysqli->error, E_USER_ERROR);
}
}
public function closeConnection(){
if(isset($this->mysqli)){
$closeResult = $this->mysqli->close();
if($closeResult === false){
trigger_error('Cannot close MySQL connection!', E_USER_ERROR);
}
}
}
public function query($sql){
$result= $this->mysqli->query($sql) ;
if(!$result){
$err_mes = 'Database query failed on line '.__LINE__.' in file '.__FILE__.'!<br/>';
$err_mes .= 'SQL: <span class="notice"><pre>'.$sql.'</pre></span><br/>';
$err_mes .= 'Error: <span class="error">'.$this->mysqli->error.'</span>';
var_dump(debug_backtrace());
trigger_error($err_mes, E_USER_ERROR);
}
return $result;
}
public function escapeValue($value){
$value=$this->mysqli->real_escape_string($value);
return $value;
}
public function prepare($sql){
$query = $this->mysqli->prepare($sql);
if(!$query) {
$err_mes = 'Database query failed on line '.__LINE__.' in file '.__FILE__.'!<br/>';
$err_mes .= 'SQL: <span class="notice"><pre>'.$sql.'</pre></span><br/>';
$err_mes .= 'Error: <span class="error">'.$this->mysqli->error.'</span>';
var_dump(debug_backtrace());
trigger_error($err_mes, E_USER_ERROR);
}
return $query;
}
public function fetchArray($result_set){
return $result_set->fetch_array(MYSQLI_ASSOC);
}
public function fetchResultArray($sql){
$query = $this->query($sql);
$data = [];
while($row = $this->fetchArray($query)){
array_push($data, $row);
}
if($query){
$query->close();
}
return $data;
}
public function numRows($result_set){
return $result_set->num_rows;
}
public function affectedRows(){
return $this->mysqli->affected_rows;
}
public function getInsertId(){
return $this->mysqli->insert_id;
}
public function closeQuery($query){
if($query){
var_dump($query);
$query->close();
}
}
public function beginTransaction($mode = MYSQLI_TRANS_START_READ_WRITE){
return $this->mysqli->begin_transaction();
}
public function commit(){
return $this->mysqli->commit();
}
public function rollback(){
return $this->mysqli->rollback();
}
/**
* check if empty value
* @param String $key key for translation
* @param String| INT| FLOAT $value value to be checked
* @return array error message array or null if passed
*/
public function isEmpty($key, $value){
$err_mes = null;
if($value === '' || $value === null){
$err_mes = [
'code' => 'error',
'message' => 'EMPTY_VALUE',
'key' => $key
];
}
return $err_mes;
}
/**
* check lenght for value
* @param String $key key for translation
* @param String| INT| FLOAT $value value to be checked
* @param INT $maxChars maximum chatacters
* @return array error message array or null if passed
*/
public function invalidLength($key ,$value, $maxChars){
$err_mes = null;
if(strlen($value) > $maxChars){
$err_mes = [
'code' => 'error',
'message' => 'MAX_CHARACTERS',
'key' => $key
];
}
return $err_mes;
}
/**
* check if number is to big or to low
* @param String $key key for translation
* @param INT| FLOAT $value value to be checked
* @param INT $min minimum value to cehck
* @param INT $max maximum value to cehck
* @return array error message array or null if passed
*/
public function invalidNumber($key, $value, $min, $max){
$err_mes = null;
$value = filter_var($value, FILTER_VALIDATE_FLOAT);
if(($value < $min || $value > $max) || $value === false){
$err_mes = [
'code' => 'error',
'message' => 'INVALID_NUMBER',
'key' => $key
];
}
return $err_mes;
}
public function invalidDate($key, $value, $delimiter = '-'){
$err_mes = [
'code' => 'error',
'message' => 'INVALID_DATE',
'key' => $key
];
$dateValues = explode($delimiter, $value);
if(count($dateValues) !== 3){
return $err_mes;
}
if(!checkdate($dateValues[1], $dateValues[2], $dateValues[0])){
return $err_mes;
}
return null;
}
}

View File

@@ -0,0 +1,118 @@
<?php
/**
* ErrorHandler is tracking and login erros
*/
class ErrorHandler{
private $handler;
function __construct(){
register_shutdown_function(function(){
self::check_for_fatal();
});
$this->handler = set_error_handler(function($errno, $errstr, $errfile, $errline){
self::myHandler($errno, $errstr, $errfile, $errline);
});
error_reporting( E_ALL );
ini_set('display_errors', 1);
}
/**
* Custom error handler
* @param INT $errno error code
* @param String $errstr the error message
* @param String $errfile the file that triggered the error
* @param INT $errline line of code where error was triggered
* @return Boolean
*/
private static function myHandler($errno, $errstr, $errfile, $errline){
if (!(error_reporting() & $errno)) {
return;
}
header('Status: 500 Internal Server Error');
header('HTTP/1.0 500 Internal Server Error');
switch ($errno) {
case E_USER_ERROR:
$err_mes = '<div class="alert alert-danger col-md-12">';
$err_mes .= '<span class="glyphicon glyphicon-exclamation-sign"></span>';
$err_mes .= "<b>My ERROR</b> [$errno] $errstr<br />". PHP_EOL;
$err_mes .= " Fatal error on line $errline in file $errfile";
$err_mes .= ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />". PHP_EOL;
$err_mes .= "Aborting...<br />" . PHP_EOL;
$err_mes .= '</div>';
self::addLog($err_mes);
exit(1);
break;
case E_USER_WARNING:
$err_mes = '<div class="alert alert-warning col-md-12">';
$err_mes = "<b>My WARNING</b> [$errno] $errstr<br />". PHP_EOL;
$err_mes .= '</div>';
self::addLog($err_mes);
break;
case E_USER_NOTICE:
$err_mes = '<div class="alert alert-info col-md-12">';
$err_mes = "<b>My NOTICE</b> [$errno] $errstr<br />". PHP_EOL;
$err_mes .= '</div>';
self::addLog($err_mes);
break;
default:
$err_mes = '<div class="alert alert-danger col-md-12">';
$err_mes .= '<span class="glyphicon glyphicon-exclamation-sign"></span>';
$err_mes .= "<b>My ERROR</b> [$errno] $errstr<br />". PHP_EOL;
$err_mes .= " Fatal error on line $errline in file $errfile";
$err_mes .= ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />". PHP_EOL;
$err_mes .= "Aborting...<br />" . PHP_EOL;
$err_mes .= '</div>';
self::addLog($err_mes);
exit(1);
break;
}
return true;
}
/**
* Subscribe fatal php errors
*/
private static function check_for_fatal(){
$error = error_get_last();
if ( $error["type"] == E_ERROR )
self::myHandler( $error["type"], $error["message"], $error["file"], $error["line"] );
}
/**
* Adds the error message to a log file using the date of trigger
* @param String $err_mes the errror message to be added to the log
*/
public static function addLog($err_mes){
if(APPLICATION_MODE !== 'PROD'){
header('Content-Type: text/html; charset=utf-8');
echo $err_mes;
}else{
$errorDate = date('Y/m/d H:i:s');
$today = getdate();
$logDir = PATH_LOGS.$today['year'].'/'.$today['month'].'/'.$today['mday'].'/';
if (!file_exists($logDir)) {
mkdir($logDir, 0777, true);
}
$logFile = $logDir.$today['hours'].'_'.$today['minutes'].'.log';
$fileHandler = fopen($logFile, "a");
fwrite($fileHandler, $errorDate . PHP_EOL);
fwrite($fileHandler, $err_mes . PHP_EOL . PHP_EOL);
fclose($fileHandler);
$friendlyErrorMessage = '<div class="alert alert-danger">';
$friendlyErrorMessage .= '<span class="glyphicon glyphicon-exclamation-sign"></span>';
$friendlyErrorMessage .= ' There seems to be a problem with the page.';
$friendlyErrorMessage .= ' An error message has been sent to the support team.';
$friendlyErrorMessage .= ' In case the error persists please contact the support!';
$friendlyErrorMessage .= '</div>';
echo $friendlyErrorMessage;
}
}
}

View File

@@ -0,0 +1,333 @@
<?php
/**
* File manager cals
*/
class FileManager{
/**
* upload new files
* @param file $file file to be uploaded
* @param String $documentType type of the document
* @param String $documentName name of the document
* @param INT $uploadedBy who uploaded the document, if not set the loged in user will be
* @param INT $owner document owner
* @return Array upload message
*/
public function uploadFile($file, $idDocumentType, $documentName, $uploadedBy = 0, $owner = 0, $visibleToCustomer = 1){
global $database, $user;
$data = [];
$documentName = $database->escapeValue($documentName);
$idDocumentType = $database->escapeValue($idDocumentType);
$visibleToCustomer = isset($visibleToCustomer) ? $database->escapeValue($visibleToCustomer) : 1;
if(empty($file)){
$data['messages'][] = [
'code' => 'error',
'message' => 'NO_FILE'
];
return $data;
}
$tmpName = $file['tmp_name'];
$ext = explode('.',$file['name']);
$ext = end($ext);
$errorCode = $file['error'];
if($errorCode !== 0){
$data['messages'][] = [
'code' => 'error',
'message' => 'UPLOAD_ERROR'
];
return $data;
}
if(!$uploadedBy){
$uploadedBy = $user->getUserId();
}
if(!$owner){
$owner = "null";
}
$sql = "SELECT dt.id AS idDocumentType, dt.folderName
FROM ".TABLES['document_types']." dt
WHERE id=$idDocumentType";
$query = $database->query($sql);
if($database->numRows($query) !== 1){
$data['messages'][] = [
'code' => 'error',
'message' => 'INVALID_DOCUMENT_TYPE'
];
return $data;
}
$documentType = $database->fetchArray($query);
$timestamp = time() . '_'. rand(1000,9999);
$documentPath = $documentType['folderName'].'/'.$timestamp. '.' .$ext;
$documentFullPath = PATH_UPLOAD.$documentPath;
$sql = "INSERT INTO ".TABLES['documents']."
(uploadedBy, idOwner, idDocumentType, documentName, documentPath, extension, visibleToCustomer)
VALUES($uploadedBy, $owner,'".$documentType['idDocumentType']."', '$documentName', '$documentPath', '$ext', $visibleToCustomer)";
$query = $database->query($sql);
$idDocument = $database->getInsertId();
$saveStatus = move_uploaded_file( $tmpName , $documentFullPath );
if(!$saveStatus || $database->affectedRows() === 0){
$data['messages'][] = [
'code' => 'error',
'message' => 'UPLOAD_ERROR'
];
return $data;
}
$data['idDocument'] = $idDocument;
return $data;
}
/**
* update an existing document
* @param INT $idDocument id of the document
* @param file $file file to be uploaded
* @return Array Array with document id in case of success or error messages
*/
public function updateDocument($idDocument, $file, $documentName = ''){
global $database, $user;
$data = [];
$idDocument = $database->escapeValue($idDocument);
$extraField = '';
if(empty($file)){
$data['messages'][] = [
'code' => 'error',
'message' => 'WRONG_FILE_TYPE'
];
return $data;
}
$sql = "SELECT d.documentPath
FROM ".TABLES['documents']." d
WHERE d.id=$idDocument
LIMIT 1";
$query = $database->query($sql);
if($database->numRows($query) !== 1){
$data['messages'][] = [
'code' => 'error',
'message' => 'FILE_NOT_EXISTS'
];
return $data;
}
$oldFile = $database->fetchArray($query);
$tmpName = $file['tmp_name'];
$ext = explode('.',$file['name']);
$ext = end($ext);
$errorCode = $file['error'];
if($errorCode !== 0){
$data['messages'][] = [
'code' => 'error',
'message' => 'UPLOAD_ERROR'
];
return $data;
}
$documentPath = $oldFile['documentPath'];
$documentFullPath = PATH_UPLOAD.$documentPath;
$del_status = unlink($documentFullPath);
$saveStatus = move_uploaded_file($tmpName, $documentFullPath);
if(!$saveStatus){
$data['messages'][] = [
'code' => 'error',
'message' => 'UPLOAD_ERROR'
];
return $data;
}
if($documentName) {
$extraField = ", documentName='".$documentName."'";
}
$sql = "
UPDATE ".TABLES['documents']."
SET extension='".$ext."'
$extraField
WHERE id=$idDocument";
$query = $database->query($sql);
$data['idDocument'] = $idDocument;
return $data;
}
/**
* download an existing file
* @param String $filePath path of the file
* @param String $fileName the name of the document after download
* @return octet-stream file to be downloaded
*/
public function downloadFile($idDocument, $fileName, $fileType=''){
global $database, $user;
$whereSql = "";
$userType = $user->getUserType();
if($userType !== USER_TYPES['BROKER'] && $fileType !== 'installationProtocol'){
if($userType === USER_TYPES['CUSTOMER']) {
$whereSql = "AND d.visibleToCustomer = 1";
} else {
$whereSql = "AND ( d.uploadedBy=".$user->getUserId()." OR d.uploadedBy IS NULL )";
}
}
$sql = "SELECT d.documentPath
FROM ".TABLES['documents']." d
WHERE d.id=$idDocument $whereSql";
$query = $database->query($sql);
if($database->numRows($query) !== 1){
trigger_error("Invalid document!", E_USER_ERROR);
}
$document = $database->fetchArray($query);
header('Content-Disposition: attachment;filename="'.$fileName.'"');
header('Content-Type: application/octet-stream');
ob_start();
require(PATH_UPLOAD . $document['documentPath']);
return ob_get_clean();
}
/**
* add a new type for a document
* @param String $documentNewType name for the new document type
*/
public function addNewDocumnetType($documentNewType){
global $database;
$documentNewType = $database->escapeValue($documentNewType);
if(!$documentNewType){
$data['messages'][] = [
'code' => 'error',
'message' => 'NO_TYPE_FOR_NEW'
];
return $data;
}
$folderName = '';
$folderNamePieces = explode(' ',$documentNewType);
foreach ($folderNamePieces as $key => $value) {
$folderName .= $key === 0 ? $value : ucfirst($value) ;
}
$folderFullName = PATH_UPLOAD.$folderName;
if (file_exists($folderFullName)){
$data['messages'][] = [
'code' => 'error',
'message' => 'TYPE_EXISTS'
];
return $data;
}
$createNewDir = mkdir($folderFullName, 0777);
if(!$createNewDir){
$data['messages'][] = [
'code' => 'error',
'message' => 'MKDIR_ERROR'
];
return $data;
}
$sql = "INSERT INTO ".TABLES['document_types']."
(type, folderName)
VALUES('$documentNewType', '$folderName')";
$query = $database->query($sql);
if($database->affectedRows() > 0){
$data['messages'][] = [
'code' => 'success',
'message' => 'NEW_TYPE_ADDED'
];
}else{
$data['messages'][] = [
'code' => 'error',
'message' => 'ERROR_NEW_TYPE'
];
}
return $data;
}
/**
* remove documents
* @param INT $idDocument id for the document
* @return Array delete message
*/
public function removeDocument($idDocument){
global $database;
if(!$idDocument){
$data['messages'][] = [
'code' => 'error',
'message' => 'NO_SELECTION_FOR_REMOVE'
];
}
$sql = "SELECT d.documentPath
FROM ".TABLES['documents']." d
WHERE d.id=$idDocument
LIMIT 1";
$query = $database->query($sql);
if($database->numRows($query) !== 1){
$data['messages'][] = [
'code' => 'error',
'message' => 'FILE_NOT_EXISTS'
];
return $data;
}
$documentPath = $database->fetchArray($query);
$documentFullPath = PATH_UPLOAD.$documentPath['documentPath'];
$del_status = unlink($documentFullPath);
if(!$del_status){
$data['messages'][] = [
'code' => 'error',
'message' => 'UNABLE_TO_DELETE'
];
return $data;
}
$sqlDelete = "DELETE FROM ".TABLES['documents']."
WHERE id=$idDocument";
$query = $database->query($sqlDelete);
$documentsDeleted = $database->affectedRows();
if($documentsDeleted > 0){
$data['messages'][] = [
'code' => 'success',
'message' => 'DOCUMENT_DELETED'
];
}else{
$data['messages'][] = [
'code' => 'error',
'message' => 'UNABLE_TO_DELETE'
];
}
return $data;
}
}

View File

@@ -0,0 +1,41 @@
<?php
class HeadersHelper{
/**
* [getHeader description]
* @param array[] $headers headers array ex: [column_name => column_alias]
* @param string $type type of the return it can have values sql or array
* @return strin|array return sql header if type is sql and array of headers if type is array
*/
public function getHeader($headers = [], $type = 'array'){
$method = 'generate' . ucfirst($type) . 'Header';
return $this->{$method}($headers);
}
/**
* generates required header string for an sql (columns to be fetch from DB)
* @param array $headers headers array
* @return string sql columns string
*/
private function generateSqlHeader($headers){
$formattedHeader = '';
foreach ($headers as $key => $value) {
$formattedHeader .= $key . ' AS ' . $value . ',';
}
return rtrim($formattedHeader, ',');
}
/**
* generates an integer indexed array for the headers
* @param array $headers headers array
* @return array array of values for the header
*/
private function generateArrayHeader($headers){
$formattedHeader = [];
foreach ($headers as $value) {
array_push($formattedHeader, $value);
}
return $formattedHeader;
}
}

View File

@@ -0,0 +1,76 @@
<?php
/**
* class notifications
*/
class Mail{
private static function getTemplate($template){
ob_start();
global $apiVersion;
require(ROOT_DIR . PATH_COMPONENTS.$apiVersion.'/utils/mail_templates/'.$template);
return ob_get_clean();
}
private static function replaceTemplateParams($message, $tempalteParams){
$tempalteParams['APPLICATION_NAME'] = APPLICATION_NAME;
$replaceFrom = array_keys($tempalteParams);
foreach ($replaceFrom as &$value) {
$value = '{'.$value.'}';
}
$replaceWith = $tempalteParams;
$message = str_replace($replaceFrom, $replaceWith, $message);
return $message;
}
public static function sendMail($toList, $subject, $template, $tempalteParams = []){
$multipleTos = false;
if(is_array($toList)) {
$toList = array_unique($toList);
if(count($toList) === 1) {
$to = new SendGrid\Email(null, $toList[0]);
} else {
$personalization = new SendGrid\Personalization();
foreach($toList as $position => $toMail) {
if($position === 0) {
$to = new SendGrid\Email(null, $toMail);
$multipleTos = true;
} else {
$email = new SendGrid\Email(null, $toMail);
$personalization->addTo($email);
}
}
}
} else {
$to = new SendGrid\Email(null, $toList);
}
if(APPLICATION_MODE === 'PROD') {
$from = new SendGrid\Email(APPLICATION_NAME." Admin", ADMIN_MAIL);
$message = self::getTemplate($template);
$message = empty($tempalteParams) ? $message : self::replaceTemplateParams($message, $tempalteParams);
$content = new SendGrid\Content("text/html", $message);
$mail = new SendGrid\Mail($from, $subject, $to, $content);
if($multipleTos) {
$mail->addPersonalization($personalization);
}
$sg = new \SendGrid(SENDGRID_API_KEY);
$response = $sg->client->mail()->send()->post($mail);
$sendStatus = $response->statusCode() === 202;
if(!$sendStatus){
var_dump($response);
$err_mes = 'SendGrid failed to send the mail!';
trigger_error($err_mes, E_USER_ERROR);
}
return $sendStatus;
} else {
return true;
}
}
}

View File

@@ -0,0 +1,185 @@
<?php
/**
* Route class is used to load dynamically the controlers from each module
*/
class Route
{ private static $user;
private static $apiVersion;
function __construct($user, $version){
spl_autoload_register(function ($className) {
self::autoloadClass($className);
});
self::$user = $user;
self::$apiVersion = $version;
}
/**
*@param String $module the name of the modules
*@param String $controller the name of the contorle can be api, page or nothing
*@param String $action the name of the method to be executed from module controller
*/
public static function call($module, $controller, $action, $apiScriptKey = ''){
if ($controller === 'page') {
$action = 'showPage';
}
$controllerClassName = $module.'Controller';
$controller = new $controllerClassName();
if ($module !== 'login' && $module !== 'translate' && $module !== 'terms' && !self::$user->isLoggedIn() && !self::isAPiKeyValid($apiScriptKey)){
$userInfo = self::$user->getUserInfo();
$message = isset($userInfo) && isset($userInfo['errorMessage']) ? $userInfo['errorMessage'] : '';
trigger_error("You need to login in order to access this module! $message", E_USER_ERROR);
}
if (!method_exists ($controller, $action)){
trigger_error("Module $action method not found for $controllerClassName!", E_USER_ERROR);
}
if(!self::hasRightsForModule($module) && !self::isAPiKeyValid($apiScriptKey) && $module !== 'terms'){
trigger_error("This module is not available!", E_USER_ERROR);
}
if($action !== 'checkActivityStatus'){
self::$user->setLastActivity();
}
$controller->{ $action }();
}
/**
* [loadClass description]
* @param String $fileName name of the full path to the file
* @return Boolean returns true if file is foound
*/
private static function loadClass($fileName){
if ( file_exists($fileName) ){
require_once($fileName);
return true;
} else {
return false;
}
}
/**
*@param $className String name of the class to be autoloaded
*/
private static function autoloadClass($className){
$isClassLoaded = false;
$apiPath = ROOT_DIR . PATH_COMPONENTS . self::$apiVersion .'/';
$classFolders = scandir($apiPath);
foreach ($classFolders as $folder) {
if (!in_array($folder, array(".",".."))){
$fileName = $apiPath . $folder . '/' . ucfirst($className) .'.php';
$isClassLoaded = self::loadClass($fileName);
if ($isClassLoaded){
break;
}
}
}
if(!$isClassLoaded){
$fileName = ROOT_DIR . PATH_CORE . ucfirst($className) .'.php';
if (!self::loadClass($fileName)){
trigger_error("Module $fileName not found!", E_USER_ERROR);
}
}
}
/**
* get all avaialable modules for user
* @return Array modules array
*/
public static function getModules(){
global $database;
$idUserType = self::$user->getIdUserType();
$whereSql = self::$apiVersion === 'v1' ? "AND m.isInMenu=1" : "AND m.idParent IS NULL";
$sql = "SELECT
m.id,
m.name,
m.menuName,
m.url,
m.isInMenu
FROM ".TABLES['modules']." m
INNER JOIN ".TABLES['rel_user_types_modules']." um
ON m.id=um.idModule
WHERE
um.idUserType=".$idUserType."
AND um.idVersion='".self::$apiVersion."'
$whereSql
ORDER BY m.menuPosition";
$data['modules'] = $database->fetchResultArray($sql);
$data['subModules'] = self::$apiVersion === 'v1' ? [] : self::getSubModules();
return $data ? $data : [];
}
/**
* get all avaialable subModules for selected module
* @return Array subModules array
*/
private static function getSubModules(){
global $database;
$idUserType = self::$user->getIdUserType();
$sql = "
SELECT
parent.url AS moduleUrl,
m.menuName,
m.name,
m.url
FROM
".TABLES['modules']." m
INNER JOIN
(SELECT
id,
url
FROM
".TABLES['modules']." pm
INNER JOIN ".TABLES['rel_user_types_modules']." um
ON pm.id = um.idModule
WHERE um.idUserType = $idUserType
AND um.idVersion = '".self::$apiVersion."') parent
ON parent.id = m.idParent
WHERE m.isInMenu = 1
ORDER BY m.menuPosition";
$query = $database->query($sql);
while($row = $database->fetchArray($query)) {
$data[$row['moduleUrl']][] = $row;
}
return $data ? $data : [];
}
public static function hasRightsForModule($module){
global $database;
if($module === 'login' || $module === 'translate' || $module === 'utils')
return true;
$idUserType = self::$user->getIdUserType();
$sql = "SELECT m.id
FROM ".TABLES['modules']." m
INNER JOIN ".TABLES['rel_user_types_modules']." um
ON m.id=um.idModule
WHERE um.idUserType=".$idUserType." AND m.name='$module'
LIMIT 1";
$query = $database->query($sql);
return $database->numRows($query) === 1;
}
public static function isAPiKeyValid($apiScriptKey){
if($apiScriptKey === DASH_KEY){
return true;
}
return false;
}
}

View File

@@ -0,0 +1,426 @@
<?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;
}
}