HEX
Server: Apache
System: Linux v38079.2is.nl 3.10.0-1160.119.1.el7.x86_64 #1 SMP Tue Jun 4 14:43:51 UTC 2024 x86_64
User: democfellows (10015)
PHP: 8.1.34
Disabled: opcache_get_status
Upload Files
File: /var/www/vhosts/creativefellows.nl/jhtaxatie.creativefellows.nl/classes/LoginController.php
<?php
	
	class LoginController {
		
		private $password_hash;
		
		var $passwordFields 		= array(
			array("userid",		"userid",				"hidden",	"userid"),
			array("redirect",	"redirect",				"hidden",	"redirect"),
			array("current",	"Huidig wachtwoord",	"password",	"Huidig wachtwoord",null,null,null,true,null),
			array("hash",		"Nieuw wachtwoord",		"password",	"Voer wachtwoord in",null,null,null,true,null,array("not_equal_to","current")),
			array("hash_repeat","Herhaal wachtwoord",	"password",	"Herhaal wachtwoord",null,null,null,true,"hash")
		);
		
		
	    public function __construct($settings,$db,$router,$view,$logger)
		{
			
			$this->settings = $settings;
			$this->db 		= $db;
			$this->router	= $router;	
			$this->view 	= $view;
			$this->logger	= $logger;
	    }
		
		protected function getRouter()
		{
			return $this->router;
		}
							
	    public function showLogin($request,$response)
		{
			
			$data = array(
				'router' => $this->getRouter(),
			    'loginError' => $request->getAttribute('loginError'),
				'loginAttemps' => $request->getAttribute('loginAttemps')	
			);
			return $this->view->render($response, 'login.php',$data);
			
	    }
		
		public function showReset($request,$response)
		{
			$data = array(
				'router' => $this->getRouter(),
			    'loginError' => $request->getAttribute('loginError'),
				'loginAttemps' => $request->getAttribute('loginAttemps')	
			);
			return $this->view->render($response, 'reset.php',$data);
			
		}
		
		public function resetPassword($request,$response)
		{	
			
			// get form data
		 	$post = $request->getParsedBody();
			
			$email = $post["email"];		
		
			$sth = $this->db->prepare("SELECT * FROM users WHERE email=:email AND status = 1");
			$sth->execute(array(
			    "email" => $email
			));

			// query results
			$user_data				= $sth->fetch();
			
			if($user_data){
				
				/*
				 * Set user 
				 */
				$user = new JhUser( $user_data );
				
				
				/*
				 * new email
				 */
	  			$email = new TaxationEmail();
				
				
				/*
				 * get reset key
				 */
				$resetKey = $this->addLoginKey( $user->getUserId() );
				
				
				/*
				 *  reset url
				 */
				$reset_url = $this->getSiteUrl() . $this->router->pathFor('password.new',['key'=> $resetKey]); 

				
				/*
				 * set email template
				 */
	  			$email->setTemplate("resetpassword",["/{advisor}/" => $user->getFullName(), "/{route}/" => $reset_url]); 
				$email->setSubject("Wachtwoord herstellen");
	  			$email->setReceiver( $user->getEmailAddress() );
				
	  			$email->setFromAddress( $this->getDefaultToEmail() );
				$email->sendEmail(); 
				
				//echo $email->getBody();
								
				$request = $request->withAttribute('loginError','E-mail verstuurd');
			    return $this->showLogin($request,$response);
				
			}
			
			$attempts 	= $request->getAttribute('loginAttemps');
					
			// Set error to response
			$request 	= $request->withAttribute('loginError','Wachtwoord reset mislukt');
			$request 	= $request->withAttribute('loginAttemps',$attempts);
						
			return $this->showReset($request,$response);
	
			
		}
		
		public function viewResetForm($request,$response,$args)
		{
			
			// validate key
			$key_is_valid = $this->validateKey($args["key"]);
			
			// key not valid
			if($key_is_valid === false)
			{
				$request 	= $request->withAttribute('loginError','Url niet geldig');
				return $this->showReset($request,$response);
			}
			else{
				
				$request = $request->withAttribute('userid',$this->user_id);
				$request = $request->withAttribute('key',$args["key"]);
				
				return $this->newPassword($request,$response,$args);
				
			}
			
	    }
		
		
		public function newPassword($request,$response,$args)
		{
		
			$password_fields = $this->getPasswordFields();
			unset($password_fields[1]);
			unset($password_fields[2]);

			$data = array(
				'router' 	=> $this->getRouter(),
			    'userid'	=> $request->getAttribute('userid'),
				'fields' 	=> $password_fields,
				'key'		=> $args["key"]
			);	
			return $this->view->render($response, 'new-password.php',$data);
			
		}
		
		public function updatePassword($request,$response,$args)
		{
		 	$post 	= $request->getParsedBody();

			$request = $request->withAttribute('loginError',$post['message']);
			//$request = $request->withAttribute('redirect',$post['redirect']);
			
			$this->patchKeyStatus($post['key'],0);
			
			$this->patchPassword($request,$response,$args);
			
		}	
		
		private function patchKeyStatus($key,$status)
		{
			
			$query	= "UPDATE password_reset SET status = :status WHERE code = :key"; 
			$sth 	= $this->db->prepare($query);
			$sth->execute(array(
				"status" 	=> $status,
				"key"		=> $key
			));				
	
		}
		
		
		private function validateKey($key)
		{
			$sth 	= $this->db->prepare("SELECT * FROM password_reset WHERE code = :code AND valid_until > :currenttime AND status = 1");
			$sth->execute(array(
				"code" => $key,
				"currenttime" => date('Y-m-d h:m:s')
			));		
			$data = $sth->fetch();	
			
			$this->user_id = $data["user_id"];
			
			return $sth->rowCount() == 1 ? true : false;
			
		}
		
		
		private function addLoginKey($user_id)
		{
			$resetKey = $this->randomString();
			
			$sth 	= $this->db->prepare("INSERT INTO password_reset (user_id,code,valid_until) values (:user_id,:code,:valid_until)");
			$sth->execute(array(
				"user_id" 		=> $user_id,
				"code" 			=> $resetKey,
				"valid_until" 	=> date('Y-m-d h:m:s', strtotime('+1 day'))	
			));	 
			
			return $resetKey;
		}
		
		
		private function randomString()
		{
		    $alphabet 	= 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
		    $pass 		= array(); //remember to declare $pass as an array
		    $alphaLength = strlen($alphabet) - 1; //put the length -1 in cache
		    for ($i = 0; $i < 50; $i++) {
		        $n = rand(0, $alphaLength);
		        $pass[] = $alphabet[$n];
		    }
		    return implode($pass);
		}
			
			
		public function getDefaultToEmail()
		{
			return $this->settings['default_to_email'];
		}
		
		
		public function getSiteUrl()
		{
			return $this->settings['siteUrl'];
		}
		
		public function setAdminLogin($request,$response,$args)
		{
			$user_id 	= $args["id"];
			$post_hash 	= $args["hash"];
			
			// check referere
			$this->validReferer($request,$response,$args);
						
			
			$sth = $this->db->prepare("SELECT * FROM users WHERE user_id=:id AND status = 1 AND password_valid_until > NOW()");
			$sth->execute(array(
			    "id" => $user_id
			));

			// query results
			$user_data	= $sth->fetch();
			$hash_check = hash("sha256",$user_data["hash"]);
			
		
			// login is ok
			if($sth->rowCount() == 1 && $hash_check == $post_hash)
			{	
								
				$user_permissions			= $this->getPermission($user_data["role"]);
				
				$_SESSION['user_id'] 		= $user_data["user_id"];
				$_SESSION['role'] 			= $user_data["role"];		
				$_SESSION['full_name'] 		= $user_data["full_name"];
				$_SESSION['reset_password'] = $user_data["password_valid_until"] < date("Y-m-d") ? true : false;
				$_SESSION['user_access']	= $user_permissions;
				$_SESSION['home_page']		= "/".$user_permissions[0]["route"];
				$user_browser 				= $_SERVER['HTTP_USER_AGENT'];
				$login_str					= hash('sha512',$password . $user_browser);
				
				$this->user_id				= $user_data["user_id"];
				
				/*
				 * Login succesfull
				 */
				$this->logger->addInfo("Admin Login ok", array('username' => $user_data['username'], "IP" => $_SERVER["REMOTE_ADDR"]));


				/*
				 * Login hash
				 */
				$_SESSION['session_id'] = $login_str;
				
				//return $response->withHeader('Location',"/");		
				/*
				 * Redirect to homepage
				 */
				return $response->withHeader('Location',$_SESSION['home_page']);								
				
			}
			else{
				
			 	return $response->withHeader('Location',$this->router->pathFor("admin.viewuser",["id" => $user_id,"msg"=>"Inloggen+mislukt"]));		
				
			}
		
		}
		private function validReferer($request,$response,$args){
			
			//echo $_SERVER['HTTP_REFERER'];
			//echo '<br />' . $this->settings["siteUrl"] ;
			if( strpos($_SERVER['HTTP_REFERER'], $this->settings["siteUrl"]) === false) die("bad request");
			
		}
			
			
		
	    public function setLogin($request,$response)
		{
			
			/*
			 * Get post data
			 */
			$postData 	= $request->getParsedBody();
			//die("do captcha");	
			
			/*
			 * Csrf protection
			 */
			if(isset($postData["csrf"]) && $postData["csrf"] != $_SESSION["csrf_token"])
			{
				return $this->failedLogin($request,$response);
			}
				
				
			/*
			 * Check if user is blocked
			 */
			$is_blocked	= $this->confirmIPAddress($_SERVER["REMOTE_ADDR"]);
			
					
			/*
			 * Post has a google Captcha
			
			if($this->loginAttempt() > 0)
			{	
				
			
				
				$recaptcha 	= new \ReCaptcha\ReCaptcha($this->settings['captcha_secret']);
				$resp 		= $recaptcha->verify($postData["g-recaptcha-response"], $_SERVER['REMOTE_ADDR']);
				
				//print_r($resp);
				/*
				 * Captcha not verfied
				
				
				if (!$resp->isSuccess())
				{
					// Update login attempts on IP
					$attempts =	$this->addLoginAttempt($_SERVER["REMOTE_ADDR"]);
					
					// Set attempts to request
					$request = $request->withAttribute('loginAttemps',$attempts);
				
					// Log failed login
					$this->logger->addInfo("Login failed (captcha)", array('username' => $postData['username'], "IP" => $_SERVER["REMOTE_ADDR"]));
					
					// Return to login page
					return $this->failedLogin($request,$response);
				
				}
				
			} */
			
			
			/*
			 * User is blocked on IP address
			 */
			if($is_blocked == 1)
			{	
				$request = $request->withAttribute('loginError','Geen toegang voor 10 minuten');
				$request = $request->withAttribute('loginAttemps',0);
			    return $this->showLogin($request,$response);
			}
			
			
			/*
			 * Verify post login data
			 */
			$user 		= $this->getLogin($postData['username'],$postData['password']);
			
			
			/*
			 * Check if there is a redirect in the post
			 */
			$redirect	= $postData['redirect'] != null ? $postData['redirect'] : "/".$_SESSION['home_page'];
			
			
			/*
			 * Login failed
			 */
			if (empty($user)) {
			    
				// Update login attempts on IP
				$attempts =	$this->addLoginAttempt($_SERVER["REMOTE_ADDR"]);
				
				// Set attempts to request
				$request = $request->withAttribute('loginAttemps',$attempts);
				
				// Log failed login
				$this->logger->addInfo("Login failed", array('username' => $postData['username'],"IP" => $_SERVER["REMOTE_ADDR"]));
				
				// Return to login page
				return $this->failedLogin($request,$response);
			}
			
			
			/*
			 * Login succesfull
			 */
			$this->logger->addInfo("Login ok", array('username' => $postData['username'], "IP" => $_SERVER["REMOTE_ADDR"]));


			/*
			 * Login hash
			 */
			$_SESSION['session_id'] = $user;
			
			
			/*
			 * Prompt reset password
			 */
			if($_SESSION['reset_password'] === true)
			{	
				
				$request = $request->withAttribute('userid',$this->user_id);
				$request = $request->withAttribute('redirect',$redirect);
				return $this->getPassword($request,$response);
				
			}
			
			
			/*
			 * Redirect to homepage
			 */
			return $response->withHeader('Location',$redirect);
			
	    }
		
		public function getPassword($request,$response,$args=null)
		{
			$data = array(
				'router' 	=> $this->router,
			    'userid'	=> $request->getAttribute('userid'),
				'redirect'	=> $request->getAttribute('redirect'),
				'fields' 	=> $this->getPasswordFields()
			);	
			return $this->view->render($response, 'reset-password.php',$data);
		}
		
		private function getPasswordFields()
		{
			
			$elements = [];
			foreach( $this->passwordFields as $groupName => $field)
			{	
				$elements[] = new HtmlElement($field);
			}
			return $elements;
			
		}
		
		public function patchPassword($request,$response)
		{
						
			// get form data
		 	$post = $request->getParsedBody();
					
			// update data
			$sth = $this->db->prepare(
				"UPDATE users 
					SET 
						hash = :hash, 
						password_valid_until = :valid_until
					WHERE user_id = :userid"
			);

			// execure query
			$sth->execute(
				array(
			    	"hash" 			=> password_hash($post["hash"],PASSWORD_BCRYPT),
					"valid_until" 	=> date('Y-m-d', strtotime("+3 months", strtotime(date("Y-m-d")))),
					"userid" 		=>  $post["userid"]
				)
			);
			
			$_SESSION['reset_password'] = false;
			
			$this->showLogin($request,$response);
				
			//return $response->withRedirect( $post["redirect"] );			

		}
		
		private function failedLogin($request,$response)
		{
			// Clear the session data
		    $_SESSION['session_id'] = null;
			$_SESSION['user_id'] 	= null;
			$_SESSION['role'] 		= null;
			
			$attempts 	= $request->getAttribute('loginAttemps');
					
			// Set error to response
			$request 	= $request->withAttribute('loginError','Inloggen mislukt');
			$request 	= $request->withAttribute('loginAttemps',$attempts);
					
		    // return the login view
		    return $this->showLogin($request,$response);
		}
		
		private function loginAttempt()
		{
			
			return $this->currentAttempt;
		}
		
		private function confirmIPAddress($ipaddress)
		{
			$query	= "SELECT attempts, (CASE when lastlogin is not NULL and DATE_ADD(lastlogin, INTERVAL 10 MINUTE) > NOW() then 1 else 0 end) as denied FROM login_attempts WHERE ip = :ipaddr";
			$sth 	= $this->db->prepare($query);
			$sth->execute(array(
				"ipaddr" => $ipaddress
			));	
			
			$data = $sth->fetch();
							
			//Verify that at least one login attempt is in database
			if (!$data) {
				$this->currentAttempt = 0;
				return 0;
			}

			// set current login attempt
			$this->currentAttempt = $data["attempts"];  

			// check if user has been blocked
			if ($data["attempts"] >= 5)
			{
				if($data["denied"] == 1) return 1;
				else
				{	
					
					$this->clearLoginAttempts($ipaddress);
					return 0;
				}
			}
			return 0;  
		}

		private function clearLoginAttempts($ipaddress)
		{
			$query	= "UPDATE login_attempts SET attempts = 0 WHERE ip = :ipaddr"; 
			$sth 	= $this->db->prepare($query);
			$sth->execute(array(
				"ipaddr" => $ipaddress
			));				
		}
		
		private function addLoginAttempt($ipaddress)
		{

			$sth 	= $this->db->prepare("SELECT * FROM login_attempts WHERE ip = :ipaddr");
			$sth->execute(array(
				"ipaddr" => $ipaddress
			));			
			
			$data = $sth->fetch();
						  

			if($data)
			{
				$attempts = $data["attempts"]+1;

				if($attempts == 3){
					$q 		= "UPDATE login_attempts SET attempts=". $attempts .", lastlogin=NOW() WHERE ip = :ipaddr";
				}
				else {
					$q 		= "UPDATE login_attempts SET attempts=". $attempts ." WHERE ip = :ipaddr";
				}
				
			}
			else{
				
				$q 			= "INSERT INTO login_attempts (attempts,IP,lastlogin) values (1,:ipaddr,NOW())";
				$attempts 	= 1;
			}
			 
			$sth 	= $this->db->prepare($q);
			$sth->execute(array(
				"ipaddr" => $ipaddress
			));	 
			
			return $attempts;
			
		}
		
		private function getLogin($username,$password)
		{
			//die()
			//die( password_hash($user_data["hash"],PASSWORD_BCRYPT) );
			
			$sth = $this->db->prepare("SELECT * FROM users WHERE username=:username AND status = 1");
			$sth->execute(array(
			    "username" => $username
			));

			// query results
			$user_data				= $sth->fetch();
			
			
			//echo $password;
			//echo '<br />';
			//die( password_hash($password,PASSWORD_BCRYPT) );

			// login is ok
			if($sth->rowCount() == 1 && password_verify($password, $user_data['hash']))
			{
				$user_permissions		= $this->getPermission($user_data["role"]);
				$routes_sorted 			= $user_permissions;
				
				$_SESSION['user_id'] 		= $user_data["user_id"];
				$_SESSION['role'] 			= $user_data["role"];		
				$_SESSION['full_name'] 		= $user_data["full_name"];
				$_SESSION['reset_password'] = $user_data["password_valid_until"] < date("Y-m-d") ? true : false;
				$_SESSION['user_access']	= $user_permissions;
			
				$first_route = reset($routes_sorted);
				$_SESSION['home_page']		= $first_route["route"];
			
				$user_browser 				= $_SERVER['HTTP_USER_AGENT'];
				$login_str					= hash('sha512',$password . $user_browser);
				
			
				$this->user_id				= $user_data["user_id"];
												
				return $login_str;
			}
			else return;
			
			
		}
		
		private function getPermission($role_id)
		{
			$sth = $this->db->prepare("SELECT * FROM role_permissions RIGHT JOIN app_routes ON role_permissions.route_id = app_routes.route_id WHERE role_id = :role_id OR app_routes.static = 1 ORDER BY app_routes.position ASC");
			
			$sth->execute(array(
			    "role_id" => $role_id
			));
			
			$rows = $sth->fetchAll();
			
			$new = [];
			
			foreach($rows as $i => $route)
			{
				$route["subs"] = [];

				if($route["sub_of"] == 0) $new[$route["route_id"]] = $route;
				else{
					$new[ $route["sub_of"] ]["subs"][] = $route;
				}
			}
			

			
			return $new;
		}
		
	    public function setLogoff($request,$response)
		{
		    unset($_SESSION['session_id']);
			unset($_SESSION['user_id']);
			unset($_SESSION['role']);
			
			//$response->withHeader('Location','/');
			return $response->withRedirect("/");
			
	    }
		
	}

?>