Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions .github/workflows/testkit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,5 @@ jobs:

- name: Run integration tests
run: |
docker compose up -d --remove-orphans --wait --no-build \
server1 \
server2 \
server3 \
server4 \
testkit_backend

docker compose run --rm testkit ./testkit.sh
docker compose up -d --remove-orphans --wait --no-build testkit_backend neo4j
docker compose up testkit
6 changes: 4 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ services:

testkit:
image: python:3.13
command: ./testkit.sh
volumes:
- .:/opt/project
working_dir: /opt/project/testkit-backend
Expand All @@ -131,6 +132,9 @@ services:
TEST_DRIVER_NAME: php
TEST_DRIVER_REPO: /opt/project
TEST_BACKEND_HOST: testkit_backend
TEST_STUB_HOST: testkit
depends_on:
- testkit_backend

testkit_backend:
<<: *common-php
Expand All @@ -141,7 +145,5 @@ services:
- neo4j
extra_hosts:
- "host.docker.internal:host-gateway"
depends_on:
- neo4j
ports:
- "9876:9876"
23 changes: 18 additions & 5 deletions src/Authentication/BasicAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

namespace Laudis\Neo4j\Authentication;

use Bolt\enum\Signature;
use Bolt\protocol\Response;
use Bolt\protocol\V4_4;
use Bolt\protocol\V5;
use Bolt\protocol\V5_1;
Expand All @@ -22,8 +24,8 @@
use Exception;
use Laudis\Neo4j\Bolt\BoltMessageFactory;
use Laudis\Neo4j\Common\Neo4jLogger;
use Laudis\Neo4j\Common\ResponseHelper;
use Laudis\Neo4j\Contracts\AuthenticateInterface;
use Laudis\Neo4j\Exception\Neo4jException;
use Psr\Http\Message\UriInterface;

/**
Expand Down Expand Up @@ -51,7 +53,7 @@ public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $
$helloMetadata = ['user_agent' => $userAgent];

$factory->createHelloMessage($helloMetadata)->send();
$response = ResponseHelper::getResponse($protocol);
$response = self::getResponse($protocol);

$credentials = [
'scheme' => 'basic',
Expand All @@ -60,7 +62,7 @@ public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $
];

$factory->createLogonMessage($credentials)->send();
ResponseHelper::getResponse($protocol);
self::getResponse($protocol);

/** @var array{server: string, connection_id: string, hints: list} */
return $response->content;
Expand All @@ -74,9 +76,10 @@ public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $
];

$factory->createHelloMessage($helloMetadata)->send();
$response = self::getResponse($protocol);

/** @var array{server: string, connection_id: string, hints: list} */
return ResponseHelper::getResponse($protocol)->content;
return $response->content;
}

/**
Expand All @@ -86,7 +89,17 @@ public function logoff(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol): void
{
$factory = $this->createMessageFactory($protocol);
$factory->createLogoffMessage()->send();
ResponseHelper::getResponse($protocol);
$protocol->getResponse();
}

public static function getResponse(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol): Response
{
$response = $protocol->getResponse();
if ($response->signature === Signature::FAILURE) {
throw Neo4jException::fromBoltResponse($response);
}

return $response;
}

public function toString(UriInterface $uri): string
Expand Down
18 changes: 15 additions & 3 deletions src/Authentication/KerberosAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

namespace Laudis\Neo4j\Authentication;

use Bolt\enum\Signature;
use Bolt\protocol\Response;
use Bolt\protocol\V4_4;
use Bolt\protocol\V5;
use Bolt\protocol\V5_1;
Expand All @@ -22,8 +24,8 @@
use Exception;
use Laudis\Neo4j\Bolt\BoltMessageFactory;
use Laudis\Neo4j\Common\Neo4jLogger;
use Laudis\Neo4j\Common\ResponseHelper;
use Laudis\Neo4j\Contracts\AuthenticateInterface;
use Laudis\Neo4j\Exception\Neo4jException;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\UriInterface;
use Psr\Log\LogLevel;
Expand Down Expand Up @@ -62,7 +64,7 @@ public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $

$factory->createHelloMessage(['user_agent' => $userAgent])->send();

$response = ResponseHelper::getResponse($protocol);
$response = self::getResponse($protocol);

$this->logger?->log(LogLevel::DEBUG, 'LOGON', ['scheme' => 'kerberos', 'principal' => '']);

Expand All @@ -72,14 +74,24 @@ public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $
'credentials' => $this->token,
])->send();

ResponseHelper::getResponse($protocol);
self::getResponse($protocol);

/**
* @var array{server: string, connection_id: string, hints: list}
*/
return $response->content;
}

public static function getResponse(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol): Response
{
$response = $protocol->getResponse();
if ($response->signature === Signature::FAILURE) {
throw Neo4jException::fromBoltResponse($response);
}

return $response;
}

public function toString(UriInterface $uri): string
{
return sprintf('Kerberos %s@%s:%s', $this->token, $uri->getHost(), $uri->getPort() ?? '');
Expand Down
22 changes: 17 additions & 5 deletions src/Authentication/NoAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

namespace Laudis\Neo4j\Authentication;

use Bolt\enum\Signature;
use Bolt\protocol\Response;
use Bolt\protocol\V4_4;
use Bolt\protocol\V5;
use Bolt\protocol\V5_1;
Expand All @@ -22,8 +24,8 @@
use Exception;
use Laudis\Neo4j\Bolt\BoltMessageFactory;
use Laudis\Neo4j\Common\Neo4jLogger;
use Laudis\Neo4j\Common\ResponseHelper;
use Laudis\Neo4j\Contracts\AuthenticateInterface;
use Laudis\Neo4j\Exception\Neo4jException;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\UriInterface;
use Psr\Log\LogLevel;
Expand Down Expand Up @@ -57,10 +59,10 @@ public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $
$helloMetadata = ['user_agent' => $userAgent];

$factory->createHelloMessage($helloMetadata)->send();
$response = ResponseHelper::getResponse($protocol);
$response = self::getResponse($protocol);

$factory->createLogonMessage(['scheme' => 'none'])->send();
ResponseHelper::getResponse($protocol);
self::getResponse($protocol);

/** @var array{server: string, connection_id: string, hints: list} */
return $response->content;
Expand All @@ -74,14 +76,24 @@ public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $
$factory->createHelloMessage($helloMetadata)->send();

/** @var array{server: string, connection_id: string, hints: list} */
return ResponseHelper::getResponse($protocol)->content;
return self::getResponse($protocol)->content;
}

public static function getResponse(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol): Response
{
$response = $protocol->getResponse();
if ($response->signature === Signature::FAILURE) {
throw Neo4jException::fromBoltResponse($response);
}

return $response;
}

public function logoff(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol): void
{
$factory = $this->createMessageFactory($protocol);
$factory->createLogoffMessage()->send();
ResponseHelper::getResponse($protocol);
$protocol->getResponse();
}

public function toString(UriInterface $uri): string
Expand Down
5 changes: 2 additions & 3 deletions src/Authentication/OpenIDConnectAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
use Exception;
use Laudis\Neo4j\Bolt\BoltMessageFactory;
use Laudis\Neo4j\Common\Neo4jLogger;
use Laudis\Neo4j\Common\ResponseHelper;
use Laudis\Neo4j\Contracts\AuthenticateInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\UriInterface;
Expand Down Expand Up @@ -59,7 +58,7 @@ public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $

$factory->createHelloMessage(['user_agent' => $userAgent])->send();

$response = ResponseHelper::getResponse($protocol);
$response = $protocol->getResponse();

$this->logger?->log(LogLevel::DEBUG, 'LOGON', ['scheme' => 'bearer']);

Expand All @@ -68,7 +67,7 @@ public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $
'credentials' => $this->token,
])->send();

ResponseHelper::getResponse($protocol);
$protocol->getResponse();

/**
* @var array{server: string, connection_id: string, hints: list}
Expand Down
40 changes: 29 additions & 11 deletions src/Bolt/BoltUnmanagedTransaction.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
use Laudis\Neo4j\Databags\SummarizedResult;
use Laudis\Neo4j\Databags\TransactionConfiguration;
use Laudis\Neo4j\Enum\TransactionState;
use Laudis\Neo4j\Exception\ClientException;
use Laudis\Neo4j\Exception\TransactionException;
use Laudis\Neo4j\Formatter\SummarizedResultFormatter;
use Laudis\Neo4j\ParameterHelper;
use Laudis\Neo4j\Types\CypherList;
Expand Down Expand Up @@ -58,23 +58,23 @@ public function __construct(
/**
* @param iterable<Statement> $statements
*
* @throws ClientException|Throwable
* @throws TransactionException|Throwable
*
* @return CypherList<SummarizedResult>
*/
public function commit(iterable $statements = []): CypherList
{
if ($this->isFinished()) {
if ($this->state === TransactionState::TERMINATED) {
throw new ClientException("Can't commit, transaction has been terminated");
throw new TransactionException("Can't commit, transaction has been terminated");
}

if ($this->state === TransactionState::COMMITTED) {
throw new ClientException("Can't commit, transaction has already been committed");
throw new TransactionException("Can't commit, transaction has already been committed");
}

if ($this->state === TransactionState::ROLLED_BACK) {
throw new ClientException("Can't commit, transaction has already been rolled back");
throw new TransactionException("Can't commit, transaction has already been rolled back");
}
}

Expand All @@ -93,16 +93,20 @@ public function commit(iterable $statements = []): CypherList
public function rollback(): void
{
if ($this->isFinished()) {
if ($this->state === TransactionState::TERMINATED) {
throw new ClientException("Can't rollback, transaction has been terminated");
}

if ($this->state === TransactionState::COMMITTED) {
throw new ClientException("Can't rollback, transaction has already been committed");
throw new TransactionException("Can't rollback, transaction has already been committed");
}

if ($this->state === TransactionState::ROLLED_BACK) {
throw new ClientException("Can't rollback, transaction has already been rolled back");
// Already rolled back, throw a TransactionException to be wrapped by DriverErrorResponse
throw new TransactionException('Transaction has already been rolled back');
}

if ($this->state === TransactionState::TERMINATED) {
// Transaction failed, allow rollback as a no-op
$this->state = TransactionState::ROLLED_BACK;

return;
}
}

Expand All @@ -115,6 +119,20 @@ public function rollback(): void
*/
public function run(string $statement, iterable $parameters = []): SummarizedResult
{
if ($this->isFinished()) {
if ($this->state === TransactionState::TERMINATED) {
throw new TransactionException("Can't rollback, transaction has been terminated");
}

if ($this->state === TransactionState::COMMITTED) {
throw new TransactionException("Can't rollback, transaction has already been committed");
}

if ($this->state === TransactionState::ROLLED_BACK) {
throw new TransactionException("Can't rollback, transaction has already been rolled back");
}
}

return $this->runStatement(new Statement($statement, $parameters));
}

Expand Down
37 changes: 0 additions & 37 deletions src/Common/ResponseHelper.php

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
*
* @psalm-suppress MutableDependency
*/
final class ClientException extends RuntimeException
final class TransactionException extends RuntimeException
{
public function __construct(string $message, ?Throwable $previous = null)
{
Expand Down
Loading