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

164 lines
6.1 KiB
PHP

<?php
namespace Hanyuu\Users;
use RuntimeException;
use Index\Data\IDbConnection;
use Index\Data\IDbStatement;
use Index\Data\IDbResult;
use Hanyuu\StatementCache;
use Hanyuu\Auth\IAuthMethod;
use Hanyuu\Auth\Auth;
use Hanyuu\Users\UserInfo;
use Hanyuu\Users\UserPasswordInfo;
use Hanyuu\Users\UserTOTPInfo;
class Users {
private const USERS_TABLE = 'hau_users';
private const TFA_TABLE = 'hau_users_tfa';
private const BACKUP_TABLE = 'hau_users_backup';
private const EMAILS_TABLE = 'hau_users_emails';
private const PASSWORDS_TABLE = 'hau_users_passwords';
private const TOTP_TABLE = 'hau_users_totp';
private const USERS_FIELDS = [
'user_id', 'user_name', 'user_country', 'user_colour', 'user_super', 'user_time_zone',
'UNIX_TIMESTAMP(user_created)', 'UNIX_TIMESTAMP(user_updated)', 'UNIX_TIMESTAMP(user_deleted)',
];
private const TFA_FIELDS = [
'user_id', 'user_tfa_type', 'UNIX_TIMESTAMP(user_tfa_enabled)',
];
private const PASSWORDS_FIELDS = [
'user_id', 'user_password_hash', 'UNIX_TIMESTAMP(user_password_changed)',
];
private const TOTP_FIELDS = [
'user_id', 'user_totp_key', 'UNIX_TIMESTAMP(user_totp_changed)',
];
private const EMAILS_FIELDS = [
'user_id', 'user_email_address', 'UNIX_TIMESTAMP(user_email_created)', 'UNIX_TIMESTAMP(user_email_verified)', 'user_email_recovery',
];
private const BACKUP_FIELDS = [
'user_id', 'user_backup_code', 'UNIX_TIMESTAMP(user_backup_created)', 'UNIX_TIMESTAMP(user_backup_used)',
];
private StatementCache $stmts;
public function __construct(
private IDbConnection $conn
) {
$this->stmts = new StatementCache($conn);
}
private function fetchUserInfoSingle(IDbResult $result, string $exceptionText): UserInfo {
if(!$result->next())
throw new RuntimeException($exceptionText);
return new UserInfo($result);
}
public function getUserInfoById(string $userId): UserInfo {
$stmt = $this->stmts->getStatement('get info by id', fn() => ('SELECT ' . implode(',', self::USERS_FIELDS) . ' FROM ' . self::USERS_TABLE . ' WHERE user_id = ?'));
$stmt->addParameter(1, $userId);
$stmt->execute();
return $this->fetchUserInfoSingle($stmt->getResult(), 'no user with $userId found');
}
public function getUserInfoByName(string $userName): UserInfo {
$stmt = $this->stmts->getStatement('get info by name', fn() => ('SELECT ' . implode(',', self::USERS_FIELDS) . ' FROM ' . self::USERS_TABLE . ' WHERE user_name = ?'));
$stmt->addParameter(1, $userName);
$stmt->execute();
return $this->fetchUserInfoSingle($stmt->getResult(), 'no user with $userName found');
}
public function countUserTFAMethods(UserInfo $userInfo): int {
$stmt = $this->stmts->getStatement('count user tfa methods', fn() => ('SELECT COUNT(*) FROM ' . self::TFA_TABLE . ' WHERE user_id = ?'));
$stmt->addParameter(1, $userInfo->getId());
$stmt->execute();
$result = $stmt->getResult();
return $result->next() ? $result->getInteger(0) : 0;
}
public function getUserTFAMethods(UserInfo $userInfo): array {
$stmt = $this->stmts->getStatement('get user tfa methods', fn() => ('SELECT ' . implode(',', self::TFA_FIELDS) . ' FROM ' . self::TFA_TABLE . ' WHERE user_id = ?'));
$stmt->addParameter(1, $userInfo->getId());
$stmt->execute();
$result = $stmt->getResult();
$array = [];
while($result->next())
$array[] = new UserAuthInfo($result);
return $array;
}
public function checkUserTFAMethod(UserInfo $userInfo, IAuthMethod $method): bool {
$stmt = $this->stmts->getStatement('check user auth method', fn() => ('SELECT COUNT(*) FROM ' . self::TFA_TABLE . ' WHERE user_id = ? AND user_tfa_type = ?'));
$stmt->addParameter(1, $userInfo->getId());
$stmt->addParameter(2, $method->getName());
$stmt->execute();
$result = $stmt->getResult();
return $result->next() ? $result->getInteger(0) !== 0 : false;
}
public function getUserPasswordInfo(UserInfo $userInfo): UserPasswordInfo {
$stmt = $this->stmts->getStatement('get pwd', fn() => ('SELECT ' . implode(',', self::PASSWORDS_FIELDS) . ' FROM ' . self::PASSWORDS_TABLE . ' WHERE user_id = ?'));
$stmt->addParameter(1, $userInfo->getId());
$stmt->execute();
$result = $stmt->getResult();
if(!$result->next())
throw new RuntimeException('no password info for $userInfo found');
return new UserPasswordInfo($result);
}
public function getUserTOTPInfo(UserInfo $userInfo): UserTOTPInfo {
$stmt = $this->stmts->getStatement('get totp', fn() => ('SELECT ' . implode(',', self::TOTP_FIELDS) . ' FROM ' . self::TOTP_TABLE . ' WHERE user_id = ?'));
$stmt->addParameter(1, $userInfo->getId());
$stmt->execute();
$result = $stmt->getResult();
if(!$result->next())
throw new RuntimeException('no totp info for $userInfo found');
return new UserTOTPInfo($result);
}
public function getUserEMailInfos(UserInfo $userInfo): array {
$stmt = $this->stmts->getStatement('get emails', fn() => ('SELECT ' . implode(',', self::EMAILS_FIELDS) . ' FROM ' . self::EMAILS_TABLE . ' WHERE user_id = ?'));
$stmt->addParameter(1, $userInfo->getId());
$stmt->execute();
$result = $stmt->getResult();
$array = [];
while($result->next())
$array[] = new UserEMailInfo($result);
return $array;
}
public function getUserBackupInfos(UserInfo $userInfo): array {
$stmt = $this->stmts->getStatement('get backups', fn() => ('SELECT ' . implode(',', self::BACKUP_FIELDS) . ' FROM ' . self::BACKUP_TABLE . ' WHERE user_id = ?'));
$stmt->addParameter(1, $userInfo->getId());
$stmt->execute();
$result = $stmt->getResult();
$array = [];
while($result->next())
$array[] = new UserBackupInfo($result);
return $array;
}
}