hanyuu/src/Auth/Auth.php
2023-10-20 22:11:43 +00:00

83 lines
2.8 KiB
PHP

<?php
namespace Hanyuu\Auth;
use Index\XString;
use Index\Data\IDbConnection;
use Index\Data\IDbResult;
use Hanyuu\StatementCache;
use Hanyuu\Users\UserInfo;
class 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(
UserInfo $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);
$stmt->addParameter(2, $userInfo->getId());
$stmt->addParameter(3, $remoteAddr);
$stmt->addParameter(4, $countryCode);
$stmt->addParameter(5, $factors);
$stmt->execute();
return $loginId;
}
public function destroyLoginSession(AuthLoginInfo $loginInfo): void {
$stmt = $this->stmts->getStatement('destroy login', fn() => ('DELETE FROM ' . self::LOGINS_TABLE . ' WHERE auth_login_id = ?'));
$stmt->addParameter(1, $loginInfo->getId());
$stmt->execute();
}
private function fetchLoginSingle(IDbResult $result, string $exceptionText): UserInfo {
if(!$result->next())
throw new AuthLoginNotFoundException($exceptionText);
return new UserInfo($result);
}
public function getLoginSessionById(string $loginId): ?AuthLoginInfo {
$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);
$stmt->execute();
$result = $stmt->getResult();
if(!$result->next())
return null;
return new AuthLoginInfo($result);
}
public function incrementLoginSessionDone(AuthLoginInfo $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());
$stmt->execute();
}
}