This commit is contained in:
2024-01-29 10:39:53 +07:00
parent 545c404fdf
commit 72170f373a
143 changed files with 20188 additions and 3 deletions

View File

@@ -0,0 +1,297 @@
<?php
namespace Hura8\System\Model;
use Hura8\Database\iConnectDB;
use Hura8\System\IDGenerator;
class AuthModel
{
/* @var iConnectDB $db */
protected $db;
private $tb_login = '';
private $tb_access_code = '';
private $tb_onetime_key = '';
public function __construct($tb_login, $tb_access_code)
{
$this->tb_login = $tb_login;
$this->tb_access_code = $tb_access_code;
$this->db = get_db('', ENABLE_DB_DEBUG);
}
private const ACCESS_CODE_LENGTH = 30;
const ONE_TIME_KEY_LENGTH = 15;
public function checkOneTimeKey($auth_key) {
$db_response = $this->db->select(
$this->tb_onetime_key,
['user_id', 'user_name', 'client_id', 'create_time'],
[
'auth_key' => ["=", $auth_key],
],
'',
1
);
if($db_response->getCode()) {
return null;
}
$info = $db_response->getData();
if($info) {
// used ONCE and delete the key
$this->db->runQuery("DELETE FROM `".$this->tb_onetime_key."` WHERE `user_id` = ? ", ['s'], [$info['user_id']]);
return $info;
}
return false;
}
// auth key allows users to export data (i.e. export to excel) for offline use
public function createNewOneTimeKey($user_id) {
// and make a new one
$auth_key = IDGenerator::createStringId(self::ONE_TIME_KEY_LENGTH);
$this->db->insert($this->tb_onetime_key, [
'user_id' => $user_id,
'auth_key' => $auth_key,
'create_time' => CURRENT_TIME,
]);
return $auth_key;
}
// for all subsequent requests, API need to provide access-code in the request's header
// the server will verify the code
public function checkAccessCode($access_code) {
return $this->db->select(
$this->tb_access_code,
['user_id', 'create_time'],
[
'access_code' => ["=", $access_code],
],
'',
1
);
}
public function deleteAllAccessCode($user_id) {
$this->db->runQuery("DELETE FROM `".$this->tb_access_code."` WHERE `user_id` = ? ", ['s'], [$user_id]);
}
protected function createNewAccessCode($user_id) {
// when use login here, delete all other access code
$this->deleteAllAccessCode($user_id);
// and make a new one
$access_code = IDGenerator::createStringId(self::ACCESS_CODE_LENGTH);
$user_device = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown';
$db_response = $this->db->insert($this->tb_access_code, [
'user_id' => $user_id,
'access_code' => $access_code,
'user_device' => substr($user_device, 0, 150),
'create_time' => CURRENT_TIME,
]);
return $access_code;
}
/**
* allow to login via mobile
* - step 1: sms an OTP code to mobile number
* - step 2: verify OTP code (mobile number and otp code sent along in the form)
*/
public function checkLoginViaMobile($mobile, $otp) {
// todo
}
/**
* @description An OTP code is sent to user's email. This method helps user need not remember the password
* @param $email string
* @param $otp string
*/
public function checkLoginByOTP($user_id, $otp) {
$info = $this->db->select(
$this->tb_login,
[],
[
'user_id' => ["=", $user_id],
'login_otp' => ["=", $otp],
],
'',
1
);
if($info) {
// return to browser
return array(
'user_id' => $user_id,
'access_code' => $this->createNewAccessCode($user_id),
);
}
return false;
}
public function createLoginOTP($user_id) {
// check email exist
$info = $this->db->select(
$this->tb_login,
[],
[
'user_id' => ["=", $user_id],
],
'',
1
);
if($info) {
$otp = IDGenerator::createStringId(6);
$this->db->update(
$this->tb_login,
[
'login_otp' => $otp
],
[
'user_id' => $info['user_id'],
]
);
return $otp;
}
return false;
}
public function createOrUpdatePassword($user_id, $new_password) {
$query = $this->db->runQuery(
"SELECT `user_id` FROM `".$this->tb_login."` WHERE `user_id` = ? LIMIT 1 ",
['d'], [ $user_id ]
);
if($this->db->fetchAssoc($query)) {
return $this->updatePassword($user_id, $new_password);
}
return $this->createPassword($user_id, $new_password);
}
protected function createPassword($user_id, $new_password) {
return $this->db->insert(
$this->tb_login,
[
'user_id' => $user_id,
'password_hash' => $this->hashPassword($new_password),
'create_time' => CURRENT_TIME,
'create_by' => '',
]
);
}
protected function updatePassword($user_id, $new_password) {
return $this->db->update(
$this->tb_login,
[
'password_hash' => $this->hashPassword($new_password),
'last_update' => CURRENT_TIME,
'last_update_by' => ADMIN_NAME,
],
[
'user_id' => $user_id,
]
);
}
/**
* @param $user_id int
* @param $password string
* @return array|false
*/
public function checkLogin($user_id, $password) {
$info = $this->db->select(
$this->tb_login,
[ 'password_hash'],
[
'user_id' => ["=", $user_id],
],
'',
1
);
//test password
if($info && $this->verifyHash($password, $info['password_hash'])) {
$this->updateUserLogin($user_id);
// return to browser
return array(
'user_id' => $user_id,
'access_code' => $this->createNewAccessCode($user_id),
);
}
return false;
}
private function updateUserLogin($user_id){
return $this->db->update(
$this->tb_login,
[
'last_login_time' => CURRENT_TIME,
'last_login_ip' => USER_IP,
'last_login_device' => '',
'last_login_session_id' => \Hura8\System\Security\Session::id() ?: '',
'last_login_browser' => USER_AGENT,
],
[
'user_id' => $user_id,
]
);
}
/**
* @param $str string
* @return string
*/
private function hashPassword($str) {
return password_hash($str, PASSWORD_BCRYPT, array('cost' => 12 ));
}
/**
* 15-04-2016 verify string with given hash
* @param $str_to_verify string
* @param $hash string
* @return boolean
*/
private function verifyHash($str_to_verify, $hash) {
return (password_verify($str_to_verify, $hash));
}
}