mince/src/Verifications.php
2024-02-21 16:08:45 +00:00

110 lines
3.4 KiB
PHP

<?php
namespace Mince;
use InvalidArgumentException;
use RuntimeException;
use Index\Data\{DbStatementCache,IDbConnection};
use Index\Net\IPAddress;
use Index\Serialisation\Base32;
use Ramsey\Uuid\UuidInterface;
class Verifications {
private IDbConnection $dbConn;
private DbStatementCache $cache;
public function __construct(IDbConnection $dbConn) {
$this->dbConn = $dbConn;
$this->cache = new DbStatementCache($dbConn);
}
public static function generateCode(): string {
return Base32::encode(random_bytes(6));
}
public function prune(): void {
$this->dbConn->execute('DELETE FROM verifications WHERE verify_created < NOW() - INTERVAL 15 MINUTE');
}
public function getVerification(
?string $code = null,
UuidInterface|string|null $uuid = null,
IPAddress|string|null $remoteAddr = null
): VerificationInfo {
$hasCode = $code !== null;
$hasUuid = $uuid !== null;
$hasRemoteAddr = $remoteAddr !== null;
$values = [];
$query = 'SELECT verify_code, verify_uuid, verify_name, INET6_NTOA(verify_addr), UNIX_TIMESTAMP(verify_created) FROM verifications';
if($hasCode) {
$query .= ' WHERE verify_code = ?';
$values[] = $code;
} else {
$args = 0;
if($hasUuid) {
if($uuid instanceof UuidInterface)
$uuid = $uuid->getBytes();
++$args;
$query .= ' WHERE verify_uuid = ?';
$values[] = $uuid;
}
if($hasRemoteAddr) {
if($remoteAddr instanceof IPAddress)
$remoteAddr = (string)$remoteAddr;
$query .= sprintf(' %s verify_addr = INET6_ATON(?)', ++$args > 1 ? 'AND' : 'WHERE');
$values[] = $remoteAddr;
}
}
if(empty($values))
throw new InvalidArgumentException('Not enough arguments specified.');
$args = 0;
$stmt = $this->cache->get($query);
foreach($values as $value)
$stmt->addParameter(++$args, $value);
$stmt->execute();
$result = $stmt->getResult();
if(!$result->next())
throw new RuntimeException('Verification info not found.');
return VerificationInfo::fromResult($result);
}
public function createVerification(
UuidInterface|string $uuid,
string $name,
IPAddress|string $remoteAddr
): string {
if($uuid instanceof UuidInterface)
$uuid = $uuid->getBytes();
if($remoteAddr instanceof IPAddress)
$remoteAddr = (string)$remoteAddr;
$code = self::generateCode();
$stmt = $this->cache->get('REPLACE INTO verifications (verify_code, verify_uuid, verify_name, verify_addr) VALUES (?, ?, ?, INET6_ATON(?))');
$stmt->addParameter(1, $code);
$stmt->addParameter(2, $uuid);
$stmt->addParameter(3, $name);
$stmt->addParameter(4, $remoteAddr);
$stmt->execute();
return $code;
}
public function deleteVerification(VerificationInfo|string $code): void {
if($code instanceof VerificationInfo)
$code = $code->getCode();
$stmt = $this->cache->get('DELETE FROM verifications WHERE verify_code = ?');
$stmt->addParameter(1, $code);
$stmt->execute();
}
}