2019-11-09 22:33:47 +01:00
< ? php
$SESSION_COOKIE_NAME = " connection_id " ;
2019-11-12 00:07:28 +01:00
$MAX_COOKIE_LIFE = 86400 * 30 ; // 30 days max
2019-11-26 23:46:33 +01:00
$MAX_RESET_TOKEN_LIFE = 1200 ; // 20 minutes max
$MAX_TOKENS = 3 ;
2019-11-10 00:17:21 +01:00
$MINIMAL_PASSWORD_LENGTH = 8 ;
2019-11-09 22:33:47 +01:00
2019-11-09 23:56:28 +01:00
$config_array = json_decode ( file_get_contents ( " config.json " , true ));
2019-11-09 22:33:47 +01:00
2019-11-09 23:56:28 +01:00
$dsn = $config_array -> { " kind " } . " :dbname= "
. $config_array -> { " dbname " } . " ;host= " . $config_array -> { " host " };
$PDO = new PDO ( $dsn , $config_array -> { " user " }, $config_array -> { " password " });
2019-11-09 22:33:47 +01:00
$PDO -> query ( 'SET CHARSET UTF8' );
function is_https ()
{
return ( ! empty ( $_SERVER [ 'HTTPS' ]) && $_SERVER [ 'HTTPS' ] !== 'off' );
}
function generate_random_string ()
{
return substr ( str_shuffle ( MD5 ( microtime ())), 0 , 32 );
}
function connect_user ( $user_id , $long_expiration = true )
{
global $PDO , $SESSION_COOKIE_NAME , $MAX_COOKIE_LIFE ;
2019-11-11 13:51:40 +01:00
// Set the session max lifespan
$delay = $long_expiration === true ? $MAX_COOKIE_LIFE : 86400 ;
// Set the cookie lifespan
$cookie_life = $long_expiration === true ? time () + $MAX_COOKIE_LIFE : 0 ;
2019-11-09 22:33:47 +01:00
// The session id is a 32-chars random string
$session_id = generate_random_string ();
$sql = " INSERT INTO sessions(user_id, connection_eol, session_id)
VALUES ( : user_id , : connection_eol , : session_id ); " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :user_id " , $user_id );
2019-11-10 15:36:37 +01:00
$query -> bindValue (
" :connection_eol " ,
2019-11-10 16:04:24 +01:00
date ( 'Y-m-d H:i:s' , strtotime ( " now + $delay seconds " )),
PDO :: PARAM_STR
2019-11-10 15:36:37 +01:00
);
2019-11-09 22:33:47 +01:00
$query -> bindValue ( " :session_id " , $session_id );
if ( $query -> execute ()) {
return setcookie (
$SESSION_COOKIE_NAME ,
$session_id ,
2019-11-11 13:51:40 +01:00
$cookie_life ,
" " ,
" " ,
true ,
false
2019-11-09 22:33:47 +01:00
);
}
return false ;
}
function clean_old_sessions ()
{
global $PDO ;
2019-11-10 15:36:37 +01:00
$sql = " DELETE FROM sessions WHERE connection_eol < CURRENT_TIMESTAMP(); " ;
2019-11-09 22:33:47 +01:00
$query = $PDO -> prepare ( $sql );
return $query -> execute ();
}
2019-11-10 13:07:27 +01:00
function disconnect ()
{
global $PDO , $SESSION_COOKIE_NAME ;
if ( isset ( $_COOKIE [ $SESSION_COOKIE_NAME ])) {
$sql = " DELETE FROM sessions WHERE session_id = :session_id; " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :session_id " , $_COOKIE [ $SESSION_COOKIE_NAME ]);
$query -> execute ();
setcookie ( $SESSION_COOKIE_NAME , " " , time () - 3600 );
}
}
2019-11-09 22:33:47 +01:00
function is_connected ()
{
global $PDO , $SESSION_COOKIE_NAME ;
if ( isset ( $_COOKIE [ $SESSION_COOKIE_NAME ])) {
if ( ! clean_old_sessions ()) {
return false ;
}
$sql = " SELECT * FROM sessions INNER JOIN accounts ON sessions.user_id = accounts.id WHERE session_id = :session_id; " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :session_id " , $_COOKIE [ $SESSION_COOKIE_NAME ]);
if ( $query -> execute ()) {
if ( $query -> rowCount () === 1 ) {
return true ;
} else {
2019-11-10 13:07:27 +01:00
disconnect ();
2019-11-09 22:33:47 +01:00
return false ;
}
} else {
return false ;
}
}
return false ;
}
function get_username_count ( $email )
{
global $PDO ;
$sql = " SELECT email FROM accounts WHERE email = :email; " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :email " , $email );
if ( $query -> execute ()) {
return $query -> rowCount ();
}
return false ;
}
function correct_email_password ( $email , $password )
{
global $PDO ;
2019-11-10 13:07:27 +01:00
$sql = " SELECT email, password_hash FROM accounts WHERE email = :email; " ;
2019-11-09 22:33:47 +01:00
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :email " , $email );
if ( $query -> execute ()) {
foreach ( $query as $row ) {
2019-11-10 13:07:27 +01:00
return password_verify ( $password , $row [ " password_hash " ]);
2019-11-09 22:33:47 +01:00
}
}
return false ;
}
function get_user_id_from_email ( $email )
{
global $PDO ;
$sql = " SELECT id FROM accounts WHERE email = :email; " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :email " , $email );
if ( $query -> execute ()) {
foreach ( $query as $row ) {
return $row [ " id " ];
}
}
return false ;
}
2019-11-10 14:09:59 +01:00
function get_user_info_from_session_id ( $info )
2019-11-09 22:33:47 +01:00
{
global $PDO , $SESSION_COOKIE_NAME ;
if ( isset ( $_COOKIE [ $SESSION_COOKIE_NAME ])) {
2019-11-10 13:07:27 +01:00
$sql = " SELECT accounts.id AS id, email,
first_name , first_name ,
last_name , public_id FROM accounts
2019-11-09 22:33:47 +01:00
INNER JOIN sessions
ON sessions . user_id = accounts . id
WHERE session_id = : session_id ; " ;
$query = $PDO -> prepare ( $sql );
2019-11-10 14:09:59 +01:00
$query -> bindValue ( " :session_id " , $_COOKIE [ $SESSION_COOKIE_NAME ]);
2019-11-09 22:33:47 +01:00
if ( $query -> execute ())
foreach ( $query as $row ) {
switch ( $info ) {
2019-11-10 13:07:27 +01:00
case " id " :
2019-11-09 22:33:47 +01:00
case " email " :
case " first_name " :
case " last_name " :
case " public_id " :
return $row [ $info ];
default ;
break ;
}
}
}
return false ;
}
2019-11-10 00:15:03 +01:00
function add_user ( $email , $first_name , $last_name , $clear_password )
{
global $PDO ;
$password_hash = password_hash ( $clear_password , PASSWORD_DEFAULT );
2019-11-10 13:07:27 +01:00
$sql = " INSERT INTO accounts(email, first_name, last_name, password_hash, public_id)
2019-11-10 00:15:03 +01:00
VALUES ( : email , : first_name , : last_name , : password , : public_id ); " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :email " , $email );
$query -> bindValue ( " :first_name " , $first_name );
$query -> bindValue ( " :last_name " , $last_name );
$query -> bindValue ( " :password " , $password_hash );
$query -> bindValue ( " :public_id " , generate_random_string ());
return $query -> execute ();
}
2019-11-10 13:07:27 +01:00
function change_user_password ( $user_id , $new_clear_password )
{
global $PDO ;
$password_hash = password_hash ( $new_clear_password , PASSWORD_DEFAULT );
$sql = " UPDATE accounts SET password_hash = :password_hash WHERE accounts.id = :id " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :password_hash " , $password_hash );
$query -> bindValue ( " :id " , $user_id , PDO :: PARAM_INT );
return $query -> execute ();
}
2019-11-10 14:09:59 +01:00
function add_cupboard ( $name , $description )
{
global $PDO ;
$sql = " INSERT INTO cupboards (name, description, owner_id, public_id)
VALUES ( : name , : description , : owner_id , : public_id ); " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :name " , $name );
$query -> bindValue ( " :description " , $description );
$query -> bindValue ( " :owner_id " , get_user_info_from_session_id ( " id " ));
$query -> bindValue ( " :public_id " , generate_random_string ());
return $query -> execute ();
}
2019-11-17 23:44:38 +01:00
function is_users_cupboard ( $cupboard_public_id )
2019-11-10 14:09:59 +01:00
{
global $PDO ;
2019-11-17 23:44:38 +01:00
$sql = " SELECT cupboards.public_id FROM cupboards
INNER JOIN accounts ON cupboards . owner_id = accounts . id
WHERE cupboards . public_id = : public_id AND accounts . id = : accounts_id ; " ;
2019-11-10 14:09:59 +01:00
$query = $PDO -> prepare ( $sql );
2019-11-17 23:44:38 +01:00
$query -> bindValue ( " :public_id " , $cupboard_public_id );
$query -> bindValue ( " :accounts_id " , get_user_info_from_session_id ( " id " ));
2019-11-10 14:09:59 +01:00
if ( $query -> execute ()) {
return ( $query -> rowCount () === 1 );
}
return false ;
}
function add_product ( $name , $description , $expiration_date = NULL , $cupboard_id = NULL )
{
global $PDO ;
$sql = " INSERT INTO products
( name , description , expiration_date , owner_id , cupboard_id , public_id )
VALUES
( : name , : description , : expiration_date , : owner_id , : cupboard_id , : public_id ); " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :name " , $name );
$query -> bindValue ( " :description " , $description );
if ( $expiration_date === NULL ) {
$query -> bindValue ( " :expiration_date " , NULL , PDO :: PARAM_INT );
} else {
$query -> bindValue ( " :expiration_date " , $expiration_date );
}
if ( $cupboard_id === NULL ) {
$query -> bindValue ( " :cupboard_id " , NULL , PDO :: PARAM_INT );
} else {
$query -> bindValue ( " :cupboard_id " , $cupboard_id );
}
$query -> bindValue ( " :owner_id " , get_user_info_from_session_id ( " id " ));
$query -> bindValue ( " :public_id " , generate_random_string ());
return $query -> execute ();
}
function get_users_products_array ()
{
global $PDO ;
$user_products = array ();
$sql = " SELECT
2019-11-10 16:04:24 +01:00
products . id AS id , products . name AS name , products . description AS description ,
cupboards . id AS cupboard_id , cupboards . name AS cupboard_name ,
cupboards . description AS cupboard_description , expiration_date ,
2019-11-17 23:44:38 +01:00
added_date , products . public_id AS public_id , cupboards . public_id AS cupboard_public_id
2019-11-10 16:04:24 +01:00
FROM products
2019-11-11 14:53:08 +01:00
LEFT JOIN cupboards ON products . cupboard_id = cupboards . id
2019-11-10 16:04:24 +01:00
WHERE products . owner_id = : owner_id ; " ;
2019-11-10 14:09:59 +01:00
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :owner_id " , get_user_info_from_session_id ( " id " ));
if ( $query -> execute ()) {
foreach ( $query as $row ) {
array_push ( $user_products , $row );
}
}
return $user_products ;
}
function get_users_cupboards_array ()
{
global $PDO ;
$user_cupboards = array ();
$sql = " SELECT
2019-11-12 00:35:30 +01:00
id , name , description , cupboards . public_id AS public_id
2019-11-10 15:54:39 +01:00
FROM cupboards WHERE owner_id = : owner_id ; " ;
2019-11-10 14:09:59 +01:00
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :owner_id " , get_user_info_from_session_id ( " id " ));
if ( $query -> execute ()) {
foreach ( $query as $row ) {
array_push ( $user_cupboards , $row );
}
}
return $user_cupboards ;
}
2019-11-12 00:35:30 +01:00
function delete_cupboard ( $cupboard_public_id )
2019-11-16 23:12:11 +01:00
{
global $PDO ;
2019-11-12 00:35:30 +01:00
2019-11-12 10:41:10 +01:00
$sql = " DELETE cupboards
FROM cupboards
INNER JOIN accounts
ON cupboards . owner_id = accounts . id
WHERE cupboards . public_id = : id
AND cupboards . owner_id = : owner_id ; " ;
2019-11-12 00:35:30 +01:00
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :id " , $cupboard_public_id );
2019-11-12 10:41:10 +01:00
$query -> bindValue ( " :owner_id " , get_user_info_from_session_id ( " id " ));
return $query -> execute ();
}
function delete_product ( $product_public_id )
2019-11-16 23:12:11 +01:00
{
global $PDO ;
2019-11-12 10:41:10 +01:00
$sql = " DELETE products
FROM products
INNER JOIN accounts
ON products . owner_id = accounts . id
WHERE products . public_id = : id
AND products . owner_id = : owner_id ; " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :id " , $product_public_id );
$query -> bindValue ( " :owner_id " , get_user_info_from_session_id ( " id " ));
2019-11-12 00:35:30 +01:00
return $query -> execute ();
}
2019-11-16 23:12:11 +01:00
function update_product (
$product_public_id ,
$new_name ,
$new_description ,
2019-11-17 23:44:38 +01:00
$new_expiration_date ,
$new_cupboard_id
2019-11-16 23:12:11 +01:00
) {
global $PDO ;
$sql = " UPDATE products
INNER JOIN accounts
ON products . owner_id = accounts . id
SET products . name = : new_name ,
products . description = : new_description ,
2019-11-17 23:44:38 +01:00
products . expiration_date = : new_expiration_date ,
products . cupboard_id = : new_cupboard_id
2019-11-16 23:12:11 +01:00
WHERE products . public_id = : id
AND products . owner_id = : owner_id ; " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :new_name " , $new_name );
$query -> bindValue ( " :new_description " , $new_description );
2019-11-16 23:21:20 +01:00
if ( $new_expiration_date === null ) {
$query -> bindValue ( " :new_expiration_date " , $new_expiration_date , PDO :: PARAM_INT );
} else {
$query -> bindValue ( " :new_expiration_date " , $new_expiration_date );
}
2019-11-17 23:44:38 +01:00
if ( $new_cupboard_id === null ) {
$query -> bindValue ( " :new_cupboard_id " , $new_cupboard_id , PDO :: PARAM_INT );
} else {
$query -> bindValue ( " :new_cupboard_id " , $new_cupboard_id );
}
2019-11-16 23:12:11 +01:00
$query -> bindValue ( " :id " , $product_public_id );
$query -> bindValue ( " :owner_id " , get_user_info_from_session_id ( " id " ));
return $query -> execute ();
}
function update_cupboard (
$cupboard_public_id ,
$new_name ,
$new_description
) {
global $PDO ;
$sql = " UPDATE cupboards
INNER JOIN accounts
ON cupboards . owner_id = accounts . id
SET cupboards . name = : new_name ,
cupboards . description = : new_description
WHERE cupboards . public_id = : id
AND cupboards . owner_id = : owner_id ; " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :new_name " , $new_name );
$query -> bindValue ( " :new_description " , $new_description );
$query -> bindValue ( " :id " , $cupboard_public_id );
$query -> bindValue ( " :owner_id " , get_user_info_from_session_id ( " id " ));
return $query -> execute ();
}
2019-11-26 23:46:33 +01:00
function clean_old_reset_tokens ()
{
global $PDO ;
$sql = " DELETE FROM reset_password WHERE token_eol < CURRENT_TIMESTAMP(); " ;
$query = $PDO -> prepare ( $sql );
return $query -> execute ();
}
function is_reset_token_valid ( $token )
{
global $PDO ;
$sql = " SELECT * FROM reset_password WHERE token = :token; " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :token " , $token );
if ( $query -> execute ()) {
foreach ( $query as $row ) {
return $row ;
}
}
return false ;
}
function delete_reset_token ( $token )
{
global $PDO ;
$sql = " DELETE FROM reset_password WHERE token = :token; " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :token " , $token );
return $query -> execute ();
}
function get_user_id_from_reset_token ( $token )
{
global $PDO ;
$sql = " SELECT accounts.id AS id FROM accounts INNER JOIN reset_password
ON accounts . id = reset_password . user_id WHERE token = : token ; " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :token " , $token );
if ( $query -> execute ()) {
if ( $row = $query -> fetch ()) {
return $row [ " id " ];
}
}
return false ;
}
function get_token_count_from_email ( $email )
{
global $PDO ;
$sql = " SELECT token FROM reset_password
INNER JOIN accounts ON reset_password . user_id = accounts . id
WHERE accounts . email = : email ; " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :email " , $email );
if ( $query -> execute ()) {
return $query -> rowCount ();
}
return false ;
}
function generate_reset_password_token ( $email )
{
global $PDO , $MAX_RESET_TOKEN_LIFE , $MAX_TOKENS ;
$user_id = get_user_id_from_email ( $email );
if (
is_numeric ( $user_id )
&& get_token_count_from_email ( $email ) < $MAX_TOKENS
) {
$random_token = generate_random_string ();
$sql = " INSERT INTO reset_password(token, token_eol, user_id)
VALUES ( : token , : token_eol , : user_id ); " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :token " , $random_token );
$query -> bindValue (
" :token_eol " ,
date ( 'Y-m-d H:i:s' , strtotime ( " now + $MAX_RESET_TOKEN_LIFE seconds " )),
PDO :: PARAM_STR
);
$query -> bindValue ( " :user_id " , $user_id );
if ( $query -> execute ()) {
return $random_token ;
}
}
return false ;
}
function get_email_message ( $link , $first_name )
{
global $MAX_RESET_TOKEN_LIFE , $MAX_TOKENS ;
$email = " Hey $first_name ,<br> " ;
$email .= " <br> " ;
$email .= " Looks like you asked for a password reset, if so please click the link below (under " . $MAX_RESET_TOKEN_LIFE / 60 . " minutes from now) and reset you password on our website:<br> " ;
$email .= $link . " <br> " ;
$email .= " <br> " ;
$email .= " If it wasn't you who requested this, you can just ignore this message, and nothing will be done.<br> " ;
$email .= " <br> " ;
$email .= " Please remember that each link expires after " . $MAX_RESET_TOKEN_LIFE / 60 . " minutes, so this one will expire exactly at " . date ( 'Y-m-d H:i:s' , strtotime ( " now + $MAX_RESET_TOKEN_LIFE seconds " )) . " .<br> " ;
$email .= " You can generate $MAX_TOKENS at maximum. So if you ever want to generate one more after this limit, you'd have to wait for the previous links to be deactivated.<br> " ;
$email .= " <br> " ;
$email .= " Thanks,<br> " ;
$email .= " The Food Inventory system " ;
return [ " html " => $email , " alt " => str_replace ( " <br> " , " \n " , $email )];
}
function get_user_info_from_email ( $email )
{
global $PDO ;
$sql = " SELECT * FROM accounts WHERE email = :email; " ;
$query = $PDO -> prepare ( $sql );
$query -> bindValue ( " :email " , $email );
if ( $query -> execute ()) {
foreach ( $query as $row ) {
return $row ;
}
}
return false ;
}