diff --git a/www/login.php b/www/login.php index 5ac6d15..0f4798b 100644 --- a/www/login.php +++ b/www/login.php @@ -39,7 +39,8 @@ if(isset($_POST) && !empty($_POST)){ } } - $err = loginUser($data['loginEmail'], $data['loginPwd']); + $stayLoggedIn = isset($_POST['stayLoggedIn']); + $err = loginUser($data['loginEmail'], $data['loginPwd'], $stayLoggedIn); if($err === true){ header("Location: ".$returnToPage); die(); @@ -94,6 +95,12 @@ if(isset($_POST) && !empty($_POST)){ I agree to save a temporary cookie in my browser for the logged in functions to work. +
+ + +

Do you not have an account? Register

diff --git a/www/logout.php b/www/logout.php index 37f5a9c..a43c6c4 100644 --- a/www/logout.php +++ b/www/logout.php @@ -1,13 +1,7 @@ "; // html += " "; html += "
"; - html += " "; + html += " "; html += " "; html += "
"; html += "
"; diff --git a/www/webdata/init.php b/www/webdata/init.php index 8bd802f..9fb3930 100644 --- a/www/webdata/init.php +++ b/www/webdata/init.php @@ -69,7 +69,7 @@ function getHtmlHeaders($prepend = ""){ \n"; } -function loginUser($email, $pass) { +function loginUser($email, $pass, $stayLoggedIn = false) { global $db; @@ -89,23 +89,27 @@ function loginUser($email, $pass) { } - if(password_verify(PwdGen($pass), $dbPass)){ if(!isset($_SESSION)){ session_start(); } - else { -// session_regenerate_id(true); - session_regenerate_id(); - } + session_regenerate_id(); - $_SESSION['user_id'] = $dbUserId; - $_SESSION['user_name'] = $dbUserName; - $_SESSION['user_agent'] = md5($_SERVER['HTTP_USER_AGENT']); + $md5agent = md5($_SERVER['HTTP_USER_AGENT']); $userKey = GenKey(); - $updateUserSQL = "UPDATE user SET ctime = ".time().", ckey = '$userKey' WHERE user_id = $dbUserId;"; + $shaUserKey = sha1($userKey); + $expire = $stayLoggedIn?30:0; // if "stay logged in", stay logged in for 30 days. + + $updateUserSQL = "INSERT INTO user_login (user_id, ckey, ctime, expire, agent) VALUES ('$dbUserId', '$userKey', '".time()."', $expire, '$md5agent');"; if($db->query($updateUserSQL)){ - $_SESSION['user_key'] = sha1($userKey); + $_SESSION['user_id'] = $dbUserId; + $_SESSION['user_name'] = $dbUserName; + $_SESSION['user_agent'] = $md5agent; + $_SESSION['user_key'] = $shaUserKey; + + if($stayLoggedIn){ + setcookie("auth", $shaUserKey.".".$dbUserId, time() + (30 * 24*60*60), "/", $_SERVER['HTTP_HOST'], isset($_SERVER['HTTPS']), true ); + } return true; } else { @@ -119,9 +123,46 @@ function loginUser($email, $pass) { return $err; } -function logoutUser(){ - if(checkLogin()){ +function loginFromAuth($auth): bool { + global $db; + $db = $db ?? database(); + $md5agent = md5($_SERVER['HTTP_USER_AGENT']); + + $cookieSplode = explode('.', $auth); + if(count($cookieSplode) == 2){ + $tkey = $cookieSplode[0]; + $tuid = $cookieSplode[1]; + $verifyLoginCookieRes = $db->query("SELECT ul.user_id, ul.ckey, ul.ctime, ul.expire, ul.agent, u.full_name FROM user_login ul INNER JOIN user u ON ul.user_id = u.user_id WHERE ul.user_id = '$tuid' ORDER BY ctime DESC"); + while($row = $verifyLoginCookieRes->fetch_assoc()){ + if($row['expire'] == 0){ $row['expire'] = 1; } + if( + sha1($row['ckey']) == $tkey && + $row['agent'] == $md5agent && + ($row['ctime']+($row['expire']*24*60*60) > time()) + ){ + session_regenerate_id(); + $_SESSION['user_id'] = $row['user_id']; + $_SESSION['user_name'] = $row['full_name']; + $_SESSION['user_agent'] = $md5agent; + $_SESSION['user_key'] = sha1($row['ckey']); + + return true; + } + } + } + return false; +} + +function logoutUser($everywhere = false){ + if(checkLogin()){ + global $db; + + $logoutSql = "DELETE FROM user_login WHERE user_id = $_SESSION[user_id]"; + if(!$everywhere){ $logoutSql .= " AND agent = '".md5($_SERVER['HTTP_USER_AGENT'])."'"; } + + $db = $db ?? database(); + $db->query($logoutSql); } // Delete session-cookie @@ -131,6 +172,8 @@ function logoutUser(){ $params["secure"], $params["httponly"] ); + setcookie('auth', '', time() - 42000, "/", $_SERVER['HTTP_HOST'], isset($_SERVER['HTTPS']), true ); + // Finally, destroy the session. session_destroy(); } @@ -147,7 +190,7 @@ function PwdGen($pass, $returnHashed = false): string { return password_hash($pwd_peppered, PASSWORD_ARGON2ID, ['threads' => 2]); } -function GenKey($length = 7): string{ +function GenKey($length = 21): string{ $password = ""; $possible = "0123456789abcdefghijkmnopqrstuvwxyz"; @@ -166,8 +209,8 @@ function GenKey($length = 7): string{ return $password; } -function checkLogin(): bool{ - global $db, $_SESSION; +function checkLogin(): bool { + global $db, $_SESSION, $_COOKIE; if($db == null){ $db = database(); @@ -177,16 +220,25 @@ function checkLogin(): bool{ session_start(); } - if(!isset($_SESSION['user_id'])){ - return false; + if(isset($_SESSION['user_id'])){ + $md5agent = md5($_SERVER['HTTP_USER_AGENT']); + if($md5agent == @$_SESSION['user_agent']){ + $verifyLoginSessionRes = $db->query("SELECT expire, ctime, ckey FROM user_login WHERE user_id = ".$_SESSION['user_id']." and agent = '$md5agent'"); + if($verifyLoginSessionRes->num_rows > 0){ + while ($row = $verifyLoginSessionRes->fetch_assoc()){ + if( + (sha1($row['ckey']) == $_SESSION['user_key']) && + ($row['expire'] == 0 || $row['ctime']+($row['expire']*24*60*60) > time()) + ){ + return true; + } + } + } + } } - if(md5($_SERVER['HTTP_USER_AGENT']) == @$_SESSION['user_agent']){ - $verifyLoginRes = $db->query("SELECT ckey FROM user WHERE user_id = ".$_SESSION['user_id']); - list($cKey) = $verifyLoginRes->fetch_row(); - if(sha1($cKey) == $_SESSION['user_key']){ - return true; - } + if(isset($_COOKIE['auth']) && loginFromAuth($_COOKIE['auth'])){ + return true; } unset($_SESSION['user_id']); diff --git a/www/webdata/setup.php b/www/webdata/setup.php index 2366fd0..69d7b9e 100644 --- a/www/webdata/setup.php +++ b/www/webdata/setup.php @@ -5,7 +5,7 @@ $msg = array(); $missingConfig = false; -if($_SERVER['HTTP_HOST'] != "localhost"){ +if($_SERVER['REMOTE_ADDR'] != "127.0.0.1"){ $err[] = "You need to use this page from localhost"; $fatalErr = true; } @@ -15,29 +15,50 @@ if($_SERVER['HTTP_HOST'] != "localhost"){ // CREATE TABLES $sql = "CREATE OR REPLACE TABLE `user` ( - `user_id` BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY, - `md5_id` VARCHAR(200) UNIQUE, - `full_name` TINYTEXT, - `user_email` VARCHAR(220) NOT NULL UNIQUE, - `user_level` TINYINT(4) NOT NULL DEFAULT 1, - `pwd` VARCHAR(220), - `date` DATE NOT NULL DEFAULT(CURRENT_DATE), - `ckey` VARCHAR(220), - `ctime` VARCHAR(220) + `user_id` BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY, + `md5_id` VARCHAR(200) UNIQUE, + `full_name` TINYTEXT, + `user_email` VARCHAR(220) NOT NULL UNIQUE, + `user_level` TINYINT(4) NOT NULL DEFAULT 1, + `pwd` VARCHAR(220), + `date` DATE NOT NULL DEFAULT(CURRENT_DATE) ) DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci; +CREATE OR REPLACE TABLE `user_login` ( + user_id bigint not null, + ckey varchar(220) not null, + ctime varchar(220) not null, + expire smallint default 0 not null, + agent varchar(255) null, + primary key (user_id, ctime), + constraint user_id_FK foreign key (user_id) references user (user_id) +); + +CREATE OR REPLACE TABLE `option` ( + `option` varchar(100) not null primary key +); + +CREATE OR REPLACE TABLE `user_option` ( + user_id BIGINT(20) NOT NULL, + `option` varchar(100) NOT NULL, + value varchar(100) NOT NULL, + PRIMARY KEY (user_id,`option`), + CONSTRAINT user_options_FK FOREIGN KEY (user_id) REFERENCES `user`(user_id), + CONSTRAINT option_FK FOREIGN KEY (`option`) REFERENCES `option`(`option`) +) CREATE OR REPLACE TABLE `plan_space` ( - `space_id` INT auto_increment PRIMARY KEY, - `space_name` tinytext, - `owner_id` BIGINT(20), + `space_id` INT auto_increment PRIMARY KEY, + `space_name` tinytext, + `owner_id` BIGINT(20), + `space_type` enum('STORE','CHECK','CALORIES') NOT NULL DEFAULT 'STORE', # not sure if needed CONSTRAINT plan_space_owner_FK FOREIGN KEY (`owner_id`) REFERENCES `user`(`user_id`) ); CREATE OR REPLACE TABLE `plan_space_member` ( - `space_id` INT auto_increment NOT NULL, - `member_id` BIGINT(20) NOT NULL, - `timestamp` DATETIME default current_timestamp() NOT NULL, + `space_id` INT auto_increment NOT NULL, + `member_id` BIGINT(20) NOT NULL, + `timestamp` DATETIME default current_timestamp() NOT NULL, PRIMARY KEY (`space_id`, `member_id`), CONSTRAINT space_member_FK FOREIGN KEY (`member_id`) REFERENCES `user`(`user_id`), CONSTRAINT space_member_space_FK FOREIGN KEY (`space_id`) REFERENCES `plan_space`(`space_id`) @@ -45,22 +66,22 @@ CREATE OR REPLACE TABLE `plan_space_member` ( CREATE OR REPLACE TABLE `plan_store` ( `plan_store_id` INT auto_increment, - `space_id` INT NOT NULL, - `name` varchar(100) NOT NULL, - `created` DATETIME default current_timestamp() NOT NULL, - `state` ENUM('planning', 'shopping', 'closed') default 'planning', + `space_id` INT NOT NULL, + `name` varchar(100) NOT NULL, + `created` DATETIME default current_timestamp() NOT NULL, + `state` ENUM('planning', 'shopping', 'closed') default 'planning', PRIMARY KEY (plan_store_id), CONSTRAINT plan_store_user_FK FOREIGN KEY (`space_id`) REFERENCES `plan_space`(`space_id`) ) DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci; CREATE OR REPLACE TABLE `plan_store_item` ( - `plan_item_id` INT auto_increment NOT NULL, - `plan_store_id` INT NOT NULL, - `pos` tinyint(3) unsigned, - `name` varchar(200) NOT NULL, - `price` decimal(8,2) NOT NULL, - `amount` tinyint(3) unsigned DEFAULT 1, - `checked` BOOLEAN default 0, + `plan_item_id` INT auto_increment NOT NULL, + `plan_store_id` INT NOT NULL, + `pos` tinyint(3) unsigned, + `name` varchar(200) NOT NULL, + `price` decimal(8,2) NOT NULL, + `amount` tinyint(3) unsigned DEFAULT 1, + `checked` BOOLEAN default 0, PRIMARY KEY (plan_item_id), CONSTRAINT plan_store_item_FK FOREIGN KEY (plan_store_id) REFERENCES `plan_store`(`plan_store_id`) ) DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;