hanyuu/src/Auth/Db/DbAuth.php
2023-10-18 10:34:30 +00:00

87 lines
3 KiB
PHP

<?php
namespace Hanyuu\Auth\Db;
use Index\XString;
use Index\Data\IDbConnection;
use Index\Data\IDbResult;
use Index\Data\DbType;
use Hanyuu\StatementCache;
use Hanyuu\Auth\IAuthLogin;
use Hanyuu\Auth\IAuthMethod;
use Hanyuu\Auth\Auth;
use Hanyuu\Users\IUserInfo;
class DbAuth extends Auth {
private const LOGINS_TABLE = 'hau_auth_logins';
private const LOGINS_FIELDS = [
'auth_login_id', 'user_id', 'auth_login_ip', 'auth_login_country',
'auth_login_factors_required', 'auth_login_factors_done',
'UNIX_TIMESTAMP(auth_login_started)', 'UNIX_TIMESTAMP(auth_login_valid)', 'UNIX_TIMESTAMP(auth_login_completed)',
];
private StatementCache $stmts;
public function __construct(
private IDbConnection $conn
) {
$this->stmts = new StatementCache($conn);
}
public function createLoginSession(
IUserInfo $userInfo,
string $remoteAddr,
string $countryCode,
int $factors
): string {
$loginId = XString::random(48);
$stmt = $this->stmts->getStatement('create login', function() {
return 'INSERT INTO ' . self::LOGINS_TABLE
. ' (auth_login_id, user_id, auth_login_ip, auth_login_country, auth_login_factors_required)'
. ' VALUES (?, ?, INET6_ATON(?), ?, ?)';
});
$stmt->addParameter(1, $loginId, DbType::STRING);
$stmt->addParameter(2, $userInfo->getId(), DbType::STRING);
$stmt->addParameter(3, $remoteAddr, DbType::STRING);
$stmt->addParameter(4, $countryCode, DbType::STRING);
$stmt->addParameter(5, $factors, DbType::INTEGER);
$stmt->execute();
return $loginId;
}
public function destroyLoginSession(IAuthLogin $loginInfo): void {
$stmt = $this->stmts->getStatement('destroy login', fn() => ('DELETE FROM ' . self::LOGINS_TABLE . ' WHERE auth_login_id = ?'));
$stmt->addParameter(1, $loginInfo->getId(), DbType::STRING);
$stmt->execute();
}
private function fetchLoginSingle(IDbResult $result, string $exceptionText): IUserInfo {
if(!$result->next())
throw new AuthLoginNotFoundException($exceptionText);
return new DbUserInfo($result);
}
public function getLoginSessionById(string $loginId): ?IAuthLogin {
$stmt = $this->stmts->getStatement('get login by id', fn() => ('SELECT ' . implode(',', self::LOGINS_FIELDS) . ' FROM ' . self::LOGINS_TABLE . ' WHERE auth_login_id = ?'));
$stmt->addParameter(1, $loginId, DbType::STRING);
$stmt->execute();
$result = $stmt->getResult();
if(!$result->next())
return null;
return new DbAuthLogin($result);
}
public function incrementLoginSessionDone(IAuthLogin $login): void {
$stmt = $this->stmts->getStatement('increment login done', fn() => ('UPDATE ' . self::LOGINS_TABLE . ' SET auth_login_factors_done = auth_login_factors_done + 1 WHERE auth_login_id = ?'));
$stmt->addParameter(1, $login->getId(), DbType::STRING);
$stmt->execute();
}
}