diff --git a/.travis.yml b/.travis.yml index 67f98c7..7bf6b81 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ matrix: include: - php: "7.0" - php: "7.1" + - php: "7.2" - php: "nightly" allow_failures: - php: "nightly" diff --git a/bin/create-client.php b/bin/create-client.php index 582c752..ff0f5a4 100644 --- a/bin/create-client.php +++ b/bin/create-client.php @@ -10,6 +10,7 @@ }; $root = \dirname(__DIR__); +/** @psalm-suppress UnresolvableInclude */ require_once $root . '/cli-autoload.php'; if (!\is_readable($root . '/local/settings.json')) { diff --git a/bin/cross-sign.php b/bin/cross-sign.php index 09b1612..a1c280c 100644 --- a/bin/cross-sign.php +++ b/bin/cross-sign.php @@ -14,6 +14,7 @@ }; $root = \dirname(__DIR__); +/** @psalm-suppress UnresolvableInclude */ require_once $root . '/cli-autoload.php'; if (!\is_readable($root . '/local/settings.json')) { diff --git a/bin/fix-nulls.php b/bin/fix-nulls.php index 49e519d..2d51362 100644 --- a/bin/fix-nulls.php +++ b/bin/fix-nulls.php @@ -8,6 +8,7 @@ use ParagonIE\Chronicle\Chronicle; $root = \dirname(__DIR__); +/** @psalm-suppress UnresolvableInclude */ require_once $root . '/cli-autoload.php'; if (!\is_readable($root . '/local/settings.json')) { diff --git a/bin/install.php b/bin/install.php index 7f55dcc..0a5cc07 100644 --- a/bin/install.php +++ b/bin/install.php @@ -2,6 +2,7 @@ declare(strict_types=1); $root = \dirname(__DIR__); +/** @psalm-suppress UnresolvableInclude */ require_once $root . '/cli-autoload.php'; // Generate a signing key. diff --git a/bin/keygen.php b/bin/keygen.php index 623c031..37476d4 100644 --- a/bin/keygen.php +++ b/bin/keygen.php @@ -4,12 +4,13 @@ use ParagonIE\Sapient\CryptographyKeys\SigningSecretKey; $root = \dirname(__DIR__); +/** @psalm-suppress UnresolvableInclude */ require_once $root . '/cli-autoload.php'; /* This generates a new secret key from your kernel's CSPRNG */ $signingSecretKey = SigningSecretKey::generate(); -echo json_encode( +echo (string) json_encode( [ 'secret-key' => $signingSecretKey->getString(), 'public-key' => $signingSecretKey->getPublicKey()->getString() diff --git a/bin/make-tables.php b/bin/make-tables.php index 7db9bef..df90868 100644 --- a/bin/make-tables.php +++ b/bin/make-tables.php @@ -2,7 +2,9 @@ declare(strict_types=1); $root = \dirname(__DIR__); +/** @psalm-suppress UnresolvableInclude */ require_once $root . '/cli-autoload.php'; +/** @psalm-suppress UnresolvableInclude */ require_once $root . '/src/settings.php'; /** @@ -29,7 +31,7 @@ if (empty($settings['database'])) { echo "Please defined a database in local/settings.json. For example:\n\n"; - echo \json_encode( + echo (string) \json_encode( [ 'database' => [ 'dsn' => 'pgsql:rest-of-dsn-goes-here', diff --git a/bin/replicate.php b/bin/replicate.php index a6e9f36..15f0099 100644 --- a/bin/replicate.php +++ b/bin/replicate.php @@ -14,6 +14,7 @@ }; $root = \dirname(__DIR__); +/** @psalm-suppress UnresolvableInclude */ require_once $root . '/cli-autoload.php'; if (!\is_readable($root . '/local/settings.json')) { diff --git a/bin/scheduled-tasks.php b/bin/scheduled-tasks.php index 0db7305..b83e957 100644 --- a/bin/scheduled-tasks.php +++ b/bin/scheduled-tasks.php @@ -8,6 +8,7 @@ use ParagonIE\Chronicle\Chronicle; $root = \dirname(__DIR__); +/** @psalm-suppress UnresolvableInclude */ require_once $root . '/cli-autoload.php'; if (!\is_readable($root . '/local/settings.json')) { diff --git a/composer.json b/composer.json index 279b7ce..e31dcf0 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ }, "require-dev": { "phpunit/phpunit": "^6", - "vimeo/psalm": "^0.3" + "vimeo/psalm": "^0" }, "autoload-dev": { "psr-4": { @@ -37,7 +37,7 @@ } }, "scripts": { - "start": "php -S 0.0.0.0:8080 -t public public/index.php", + "start": "php -S 0.0.0.0:8080 -t public index.php", "static-analysis": "psalm", "test": "phpunit" } diff --git a/src/Chronicle/Handlers/Register.php b/src/Chronicle/Handlers/Register.php index 1674725..39f2b87 100644 --- a/src/Chronicle/Handlers/Register.php +++ b/src/Chronicle/Handlers/Register.php @@ -3,8 +3,8 @@ use ParagonIE\Chronicle\{ Chronicle, - Exception\AccessDenied, - Exception\HTTPException, + Exception\ChainAppendException, + Exception\FilesystemException, Exception\SecurityViolation, HandlerInterface, Scheduled @@ -32,9 +32,9 @@ class Register implements HandlerInterface * @param array $args * @return ResponseInterface * - * @throws AccessDenied - * @throws HTTPException - * @throws SecurityViolation + * @throws ChainAppendException + * @throws FilesystemException + * @throws \SodiumException * @throws \TypeError */ public function __invoke( @@ -105,6 +105,7 @@ public function __invoke( $settings = Chronicle::getSettings(); if (!empty($settings['publish-new-clients'])) { $serverKey = Chronicle::getSigningKey(); + /** @var string $message */ $message = \json_encode( [ 'server-action' => 'New Client Registration', @@ -114,6 +115,9 @@ public function __invoke( ], JSON_PRETTY_PRINT ); + if (!\is_string($message)) { + throw new \TypeError('Invalid messsage'); + } $signature = Base64UrlSafe::encode( \ParagonIE_Sodium_Compat::crypto_sign_detached( $message, diff --git a/src/Chronicle/Handlers/Replica.php b/src/Chronicle/Handlers/Replica.php index 93907b1..3d33d19 100644 --- a/src/Chronicle/Handlers/Replica.php +++ b/src/Chronicle/Handlers/Replica.php @@ -4,6 +4,7 @@ use ParagonIE\Chronicle\{ Chronicle, + Exception\FilesystemException, Exception\ReplicationSourceNotFound, Exception\HashNotFound, HandlerInterface @@ -93,6 +94,7 @@ public function __invoke( * Gets the entire Blakechain. * * @return ResponseInterface + * @throws FilesystemException */ public function exportChain(): ResponseInterface { @@ -115,6 +117,7 @@ public function exportChain(): ResponseInterface * @param array $args * @return ResponseInterface * @throws HashNotFound + * @throws FilesystemException */ public function getByHash(array $args = []): ResponseInterface { @@ -159,6 +162,7 @@ public function getByHash(array $args = []): ResponseInterface * List the latest current hash and summary hash for this replica * * @return ResponseInterface + * @throws FilesystemException */ public function getLastHash(): ResponseInterface { @@ -197,6 +201,7 @@ public function getLastHash(): ResponseInterface * List all replicated Chronicles and their respective URIs * * @return ResponseInterface + * @throws FilesystemException */ protected function getIndex(): ResponseInterface { @@ -243,6 +248,7 @@ protected function getIndex(): ResponseInterface * * @param array $args * @return ResponseInterface + * @throws FilesystemException * @throws HashNotFound */ public function getSince(array $args = []): ResponseInterface diff --git a/src/Chronicle/Handlers/Revoke.php b/src/Chronicle/Handlers/Revoke.php index 9ba22ad..d46ac3a 100644 --- a/src/Chronicle/Handlers/Revoke.php +++ b/src/Chronicle/Handlers/Revoke.php @@ -4,8 +4,8 @@ use ParagonIE\Chronicle\{ Chronicle, Exception\AccessDenied, - Exception\ClientNotFound, - Exception\HTTPException, + Exception\ChainAppendException, + Exception\FilesystemException, HandlerInterface, Scheduled }; @@ -32,8 +32,9 @@ class Revoke implements HandlerInterface * @return ResponseInterface * * @throws AccessDenied - * @throws ClientNotFound - * @throws HTTPException + * @throws ChainAppendException + * @throws FilesystemException + * @throws \SodiumException * @throws \TypeError */ public function __invoke( @@ -115,7 +116,7 @@ public function __invoke( ]; if (!$result['deleted']) { - $result['reason'] = 'Delete operatio nwas unsuccessful due to unknown reasons.'; + $result['reason'] = 'Delete operation was unsuccessful due to unknown reasons.'; } $now = (new \DateTime())->format(\DateTime::ATOM); @@ -126,11 +127,14 @@ public function __invoke( [ 'server-action' => 'Client Access Revocation', 'now' => $now, - 'clientid' => $result['client-id'], + 'clientid' => $post['clientid'], 'publickey' => $post['publickey'] ], JSON_PRETTY_PRINT ); + if (!\is_string($message)) { + throw new \TypeError('Invalid messsage'); + } $signature = Base64UrlSafe::encode( \ParagonIE_Sodium_Compat::crypto_sign_detached( $message, diff --git a/src/Chronicle/Process/Attest.php b/src/Chronicle/Process/Attest.php index 3221ddc..e8dade5 100644 --- a/src/Chronicle/Process/Attest.php +++ b/src/Chronicle/Process/Attest.php @@ -77,6 +77,10 @@ public function run() /** * @return array + * @throws FilesystemException + * @throws \ParagonIE\Chronicle\Exception\ChainAppendException + * @throws \SodiumException + * @throws \TypeError */ public function attestAll(): array { @@ -91,6 +95,7 @@ public function attestAll(): array } // Build the message + /** @var string $message */ $message = \json_encode( [ 'version' => Chronicle::VERSION, @@ -99,6 +104,9 @@ public function attestAll(): array ], JSON_PRETTY_PRINT ); + if (!\is_string($message)) { + throw new \TypeError('Invalid messsage'); + } // Sign the message: $signature = Base64UrlSafe::encode( diff --git a/src/routes.php b/src/routes.php index 40bd452..d348371 100644 --- a/src/routes.php +++ b/src/routes.php @@ -15,6 +15,7 @@ CheckClientSignature }; use Psr\Http\Message\{ + RequestInterface, ResponseInterface }; @@ -58,7 +59,7 @@ $this->get('', Index::class); }); -$app->get('/', function ($request, $response, $args): ResponseInterface { +$app->get('/', function (RequestInterface $request, ResponseInterface $response, array $args = []): ResponseInterface { /* UX enhancement: Automatically redirect to chronicle URI if client header is present: */ if ($request instanceof \Slim\Http\Request && $response instanceof \Slim\Http\Response) { if ($request->hasHeader(Chronicle::CLIENT_IDENTIFIER_HEADER)) {