Skip to content

Commit

Permalink
Merge pull request #6 from bedita/feat/cake4-bedita5
Browse files Browse the repository at this point in the history
Migrate to Cake 4 & BEdita 5
  • Loading branch information
batopa authored Aug 31, 2022
2 parents 098ea0d + fdacc94 commit fc507cb
Show file tree
Hide file tree
Showing 19 changed files with 266 additions and 250 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ jobs:
fail-fast: false
matrix:
php:
- '7.2'
- '7.3'
- '7.4'
- '8.0'
- '8.1'

env:
PHP_VERSION: '${{ matrix.php }}'
Expand Down
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,11 @@
/phpstan.neon
/phpunit.xml
/vendor
.vscode/
.history/
/coverage
/logs
/plugins
/tmp
.phpunit.result.cache
phinx.yml
31 changes: 16 additions & 15 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
{
"name": "bedita/aws",
"description": "BEdita 4 plugin for applications that use AWS resources such as S3",
"description": "BEdita 5 plugin for applications that use AWS resources such as S3",
"type": "cakephp-plugin",
"require": {
"php": ">=7.2.0",
"php": "^7.4 || ^8.0",
"ext-openssl": "*",
"aws/aws-sdk-php": "^3.0.0",
"bedita/core": "*",
"cakephp/cakephp": "^3.6.0",
"lcobucci/jwt": "^3.4",
"league/flysystem": "^1.0.53",
"league/flysystem-aws-s3-v3": "^1.0.0",
"aws/aws-sdk-php": "^3.222",
"bedita/core": "^5.0.0",
"cakephp/cakephp": "^4.4.1",
"lcobucci/jwt": "^4.1.5",
"league/flysystem": "^2.4.3",
"league/flysystem-aws-s3-v3": "^2.4.3",
"guzzlehttp/guzzle": "^7.4"
},
"require-dev": {
"cakephp/cakephp-codesniffer": "^3.0",
"cakephp/plugin-installer": "^1.0",
"phpunit/phpunit": "^5.7.14|^6.0",
"phpstan/phpstan": "^1.5",
"cakephp/authentication": "^1.0"
"cakephp/cakephp-codesniffer": "~4.5.1",
"phpunit/phpunit": "^9.5",
"dms/phpunit-arraysubset-asserts": "^0.4",
"phpstan/phpstan": "^1.7.1",
"cakephp/authentication": "^2.9"
},
"suggest": {
"cakephp/authentication": "^1.0"
"cakephp/authentication": "^2.9"
},
"autoload": {
"psr-4": {
Expand All @@ -41,7 +41,8 @@
},
"config": {
"allow-plugins": {
"cakephp/plugin-installer": true
"cakephp/plugin-installer": true,
"dealerdirect/phpcodesniffer-composer-installer": true
}
}
}
52 changes: 24 additions & 28 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,28 @@
~
~ See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
-->

<phpunit colors="true" processIsolation="false" stopOnFailure="false" bootstrap="tests/bootstrap.php">
<php>
<ini name="memory_limit" value="-1"/>
<ini name="apc.enable_cli" value="1"/>
</php>

<!-- Add any additional test suites you want to run here -->
<testsuites>
<testsuite name="BEdita/AWS">
<directory>tests/TestCase/</directory>
</testsuite>
</testsuites>

<!-- Setup a listener for fixtures -->
<listeners>
<listener class="Cake\TestSuite\Fixture\FixtureInjector">
<arguments>
<object class="Cake\TestSuite\Fixture\FixtureManager"/>
</arguments>
</listener>
</listeners>

<filter>
<whitelist>
<directory suffix=".php">src/</directory>
</whitelist>
</filter>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" colors="true" processIsolation="false" stopOnFailure="false" bootstrap="tests/bootstrap.php" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<coverage>
<include>
<directory suffix=".php">src/</directory>
</include>
</coverage>
<php>
<ini name="memory_limit" value="-1"/>
<ini name="apc.enable_cli" value="1"/>
</php>
<!-- Add any additional test suites you want to run here -->
<testsuites>
<testsuite name="BEdita/AWS">
<directory>tests/TestCase/</directory>
</testsuite>
</testsuites>
<!-- Setup a listener for fixtures -->
<listeners>
<listener class="Cake\TestSuite\Fixture\FixtureInjector">
<arguments>
<object class="Cake\TestSuite\Fixture\FixtureManager"/>
</arguments>
</listener>
</listeners>
</phpunit>
20 changes: 11 additions & 9 deletions src/Authenticator/AlbAuthenticator.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php
declare(strict_types=1);

/**
* BEdita, API-first content management framework
* Copyright 2022 Atlas Srl, Chialab Srl
Expand All @@ -24,14 +26,14 @@
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
use Lcobucci\Clock\FrozenClock;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Parsing\Decoder;
use Lcobucci\JWT\Encoding\JoseEncoder;
use Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter;
use Lcobucci\JWT\Signer\Ecdsa\Sha256;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Token\Parser as TokenParser;
use Lcobucci\JWT\Validation\Constraint\LooseValidAt;
use Lcobucci\JWT\Validation\Constraint\SignedWith;
use Lcobucci\JWT\Validation\Constraint\ValidAt;
use Lcobucci\JWT\Validation\Validator;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

/**
Expand Down Expand Up @@ -83,10 +85,9 @@ class AlbAuthenticator extends TokenAuthenticator
*
* @link https://jwt.io/
* @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information.
* @param \Psr\Http\Message\ResponseInterface $response Unused response object.
* @return \Authentication\Authenticator\ResultInterface
*/
public function authenticate(ServerRequestInterface $request, ResponseInterface $response): ResultInterface
public function authenticate(ServerRequestInterface $request): ResultInterface
{
$token = $this->getTokenFromHeader($request, $this->getConfigOrFail('header'));
if ($token === null) {
Expand Down Expand Up @@ -184,7 +185,8 @@ function () use ($keyId): string {
*/
protected function decodeToken(string $token): ?array
{
$parser = new Parser(new Decoder());
$parser = new TokenParser(new JoseEncoder());
/** @var \Lcobucci\JWT\UnencryptedToken $jwt */
$jwt = $parser->parse($token);

$kid = $jwt->headers()->get('kid');
Expand All @@ -194,8 +196,8 @@ protected function decodeToken(string $token): ?array

(new Validator())->assert(
$jwt,
new SignedWith(new Sha256(), $this->getKey($kid)),
new ValidAt(new FrozenClock(FrozenTime::now()))
new SignedWith(new Sha256(new MultibyteStringConverter()), $this->getKey($kid)),
new LooseValidAt(new FrozenClock(FrozenTime::now()))
);

return $jwt->claims()->all();
Expand Down
2 changes: 2 additions & 0 deletions src/AwsConfigTrait.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php
declare(strict_types=1);

/**
* BEdita, API-first content management framework
* Copyright 2022 Atlas Srl, Chialab Srl
Expand Down
62 changes: 28 additions & 34 deletions src/Filesystem/Adapter/AwsS3CloudFrontAdapter.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php
declare(strict_types=1);

/**
* BEdita, API-first content management framework
* Copyright 2022 Atlas Srl, Chialab Srl
Expand All @@ -17,13 +19,13 @@
use Aws\CloudFront\Exception\CloudFrontException;
use Aws\S3\S3ClientInterface;
use DomainException;
use League\Flysystem\AwsS3v3\AwsS3Adapter;
use League\Flysystem\AwsS3V3\AwsS3V3Adapter;
use League\Flysystem\Config;

/**
* AWS S3 adapter that creates a CloudFront invalidation every time an object is updated or deleted.
*/
class AwsS3CloudFrontAdapter extends AwsS3Adapter
class AwsS3CloudFrontAdapter extends AwsS3V3Adapter
{
/**
* CloudFront Client instance.
Expand All @@ -42,9 +44,9 @@ class AwsS3CloudFrontAdapter extends AwsS3Adapter
* @param bool $streamReads Whether reads should be streamed.
* @param \Aws\CloudFront\CloudFrontClient|null $cloudfrontClient CloudFront client instance, or `null`.
*/
public function __construct(S3ClientInterface $client, $bucket, $prefix = '', array $options = [], $streamReads = true, CloudFrontClient $cloudfrontClient = null)
public function __construct(S3ClientInterface $client, $bucket, $prefix = '', array $options = [], $streamReads = true, ?CloudFrontClient $cloudfrontClient = null)
{
parent::__construct($client, $bucket, $prefix, $options, $streamReads);
parent::__construct($client, $bucket, $prefix, null, null, $options, $streamReads);

if (!empty($options['distributionId']) && $cloudfrontClient === null) {
throw new DomainException('When `distributionId` is set, a CloudFront client instance is required');
Expand All @@ -67,10 +69,12 @@ public function getCloudFrontClient(): ?CloudFrontClient
*
* @return string|null
*/
public function getDistributionId(): ?string
{
return $this->options['distributionId'] ?? null;
}
// TODO: `options` attribute is now private in base class,
// and this method doesn't work anymore - see if there's a different way to obtain this ID.
// public function getDistributionId(): ?string
// {
// return $this->options['distributionId'] ?? null;
// }

/**
* Check whether CloudFront configuration is set.
Expand All @@ -79,62 +83,52 @@ public function getDistributionId(): ?string
*/
public function hasCloudFrontConfig(): bool
{
return !empty($this->options['distributionId']) && $this->cloudfrontClient !== null;
return $this->cloudfrontClient !== null;
}

/**
* @inheritDoc
*/
public function copy($path, $newpath)
public function copy(string $path, string $newpath, Config $config): void
{
$existed = $this->hasCloudFrontConfig() && $this->has($newpath);
$result = parent::copy($path, $newpath);
if ($result !== false && $existed) {
$existed = $this->hasCloudFrontConfig() && $this->fileExists($newpath);
parent::copy($path, $newpath, $config);
if ($existed) {
$this->createCloudFrontInvalidation($newpath);
}

return $result;
}

/**
* @inheritDoc
*/
public function delete($path)
public function delete(string $path): void
{
$existed = $this->hasCloudFrontConfig() && $this->has($path);
$result = parent::delete($path);
if ($result !== false && $existed) {
$existed = $this->hasCloudFrontConfig() && $this->fileExists($path);
parent::delete($path);
if ($existed) {
$this->createCloudFrontInvalidation($path);
}

return $result;
}

/**
* @inheritDoc
*/
public function deleteDir($dirname)
public function deleteDirectory(string $dirname): void
{
$result = parent::deleteDir($dirname);
if ($result !== false) {
$this->createCloudFrontInvalidation(rtrim($dirname, '/') . '/*');
}

return $result;
parent::deleteDirectory($dirname);
$this->createCloudFrontInvalidation(rtrim($dirname, '/') . '/*');
}

/**
* @inheritDoc
*/
protected function upload($path, $body, Config $config)
public function write(string $path, string $body, Config $config): void
{
$existed = $this->hasCloudFrontConfig() && $this->has($path);
$result = parent::upload($path, $body, $config);
if ($result !== false && $existed) {
$existed = $this->hasCloudFrontConfig() && $this->fileExists($path);
parent::write($path, $body, $config);
if ($existed) {
$this->createCloudFrontInvalidation($path);
}

return $result;
}

/**
Expand Down
6 changes: 4 additions & 2 deletions src/Filesystem/Adapter/S3Adapter.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php
declare(strict_types=1);

/**
* BEdita, API-first content management framework
* Copyright 2022 Atlas Srl, Chialab Srl
Expand All @@ -18,7 +20,7 @@
use BEdita\AWS\AwsConfigTrait;
use BEdita\Core\Filesystem\FilesystemAdapter;
use InvalidArgumentException;
use League\Flysystem\AdapterInterface;
use League\Flysystem\FilesystemAdapter as FlysystemAdapter;

/**
* AWS S3 adapter.
Expand Down Expand Up @@ -120,7 +122,7 @@ protected function getCloudFrontClient(): CloudFrontClient
/**
* @inheritDoc
*/
protected function buildAdapter(array $config): AdapterInterface
protected function buildAdapter(array $config): FlysystemAdapter
{
$cloudFrontClient = null;
$prefix = $this->getConfig('prefix');
Expand Down
15 changes: 7 additions & 8 deletions src/Mailer/Transport/SesTransport.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php
declare(strict_types=1);

/**
* BEdita, API-first content management framework
* Copyright 2022 Atlas Srl, Chialab Srl
Expand All @@ -16,7 +18,7 @@
use Aws\Ses\SesClient;
use BEdita\AWS\AwsConfigTrait;
use Cake\Mailer\AbstractTransport;
use Cake\Mailer\Email;
use Cake\Mailer\Message;

/**
* Send emails using Amazon SES.
Expand Down Expand Up @@ -76,15 +78,12 @@ protected function getClient(): SesClient
/**
* @inheritDoc
*/
public function send(Email $email): array
public function send(Message $email): array
{
$headers = $email->getHeaders(['from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc', 'subject']);
foreach ($headers as $key => $header) {
$headers[$key] = str_replace(str_split(static::EOL), '', $header);
}
$headers = $this->_headersToString($headers, static::EOL);
$headerList = ['from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc', 'subject'];
$headers = $email->getHeadersString($headerList, static::EOL);

$message = implode(static::EOL, (array)$email->message());
$message = $email->getBodyString(static::EOL);

$this->getClient()->sendRawEmail([
'RawMessage' => [
Expand Down
Loading

0 comments on commit fc507cb

Please sign in to comment.