|null */ public static function findByToken(string $token): ?array { $pdo = Database::pdo(); $stmt = $pdo->prepare( 'SELECT * FROM bearer_tokens WHERE token_hash = ? AND revoked_at IS NULL LIMIT 1' ); $stmt->execute([self::hashToken($token)]); $row = $stmt->fetch(); return $row === false ? null : $row; } public static function isTrusted(array $bearer): bool { return (int) ($bearer['trusted'] ?? 0) === 1; } public static function canTemporary(array $bearer): bool { return (int) ($bearer['can_temporary'] ?? 0) === 1; } public static function canPermanent(array $bearer): bool { return (int) ($bearer['can_permanent'] ?? 0) === 1; } public static function rateLimitPerHour(array $bearer): int { return max(1, (int) ($bearer['rate_limit_per_hour'] ?? 1000)); } public static function countCreatesLastHour(int $bearerId): int { $pdo = Database::pdo(); $stmt = $pdo->prepare( 'SELECT COUNT(*) AS c FROM links WHERE bearer_id = ? AND created_at >= (NOW() - INTERVAL 1 HOUR)' ); $stmt->execute([$bearerId]); $row = $stmt->fetch(); return (int) ($row['c'] ?? 0); } /** @return array{token: string, id: int} */ public static function createTrusted( string $label, bool $canTemporary = true, bool $canPermanent = false, int $rateLimit = 1000 ): array { $token = bin2hex(random_bytes(24)); $pdo = Database::pdo(); $stmt = $pdo->prepare( 'INSERT INTO bearer_tokens (token_hash, label, trusted, can_temporary, can_permanent, rate_limit_per_hour) VALUES (?, ?, 1, ?, ?, ?)' ); $stmt->execute([ self::hashToken($token), $label, $canTemporary ? 1 : 0, $canPermanent ? 1 : 0, $rateLimit, ]); return ['token' => $token, 'id' => (int) $pdo->lastInsertId()]; } }