Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POC for MP multi-file uploader to S3 #404

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
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
29 changes: 29 additions & 0 deletions config/Shared/config_default.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
use Generated\Shared\Transfer\SearchEndpointRemovedTransfer;
use Generated\Shared\Transfer\SubmitPaymentTaxInvoiceTransfer;
use Monolog\Logger;
use Pyz\Shared\AwsS3\AwsS3Config;
use Pyz\Shared\AwsS3\AwsS3Constants;
use Pyz\Shared\Console\ConsoleConstants;
use Pyz\Shared\Scheduler\SchedulerConfig;
use Pyz\Yves\ShopApplication\YvesBootstrap;
Expand Down Expand Up @@ -927,3 +929,30 @@
$config[PushNotificationWebPushPhpConstants::VAPID_PUBLIC_KEY] = getenv('SPRYKER_PUSH_NOTIFICATION_WEB_PUSH_PHP_VAPID_PUBLIC_KEY');
$config[PushNotificationWebPushPhpConstants::VAPID_PRIVATE_KEY] = getenv('SPRYKER_PUSH_NOTIFICATION_WEB_PUSH_PHP_VAPID_PRIVATE_KEY');
$config[PushNotificationWebPushPhpConstants::VAPID_SUBJECT] = getenv('SPRYKER_PUSH_NOTIFICATION_WEB_PUSH_PHP_VAPID_SUBJECT');

// ----------------------------------------------------------------------------
// ---------------------------- S3 Bucket -------------------------------------
// ----------------------------------------------------------------------------
$config[AwsS3Constants::BUCKETS_CONFIGURATION_MAP] = [
AwsS3Config::OBJECT_TYPE_CVS_IMPORT => [
'region' => getenv('AWS_REGION'),
'Bucket' => getenv('DATA_IMPORT_S3_BUCKET'),
'version' => 'latest',
'credentials' => [
'key' => getenv('DATA_IMPORT_S3_KEY'),
'secret' => getenv('DATA_IMPORT_S3_SECRET'),
],
AwsS3Config::CONFIG_PRE_SIGNED_URL_EXPIRATION => '30 minutes',
],
AwsS3Config::OBJECT_TYPE_ADDITIONAL_MEDIA => [
'region' => getenv('AWS_REGION'),
'Bucket' => getenv('ADDITIONAL_MEDIA_S3_BUCKET'),
'version' => 'latest',
'credentials' => [
'key' => getenv('ADDITIONAL_MEDIA_S3_KEY'),
'secret' => getenv('ADDITIONAL_MEDIA_S3_SECRET'),
],
AwsS3Config::CONFIG_PRE_SIGNED_URL_EXPIRATION => '15 minutes',
AwsS3Config::CONFIG_CDN_HOST => getenv('ADDITIONAL_MEDIA_CDN_URL'),
],
];
28 changes: 27 additions & 1 deletion config/Zed/navigation.xml
Original file line number Diff line number Diff line change
Expand Up @@ -640,10 +640,28 @@
<product-merchant-portal-gui>
<label>Products</label>
<title>Products</title>
<icon>products</icon>
<icon>offers</icon>
<bundle>product-merchant-portal-gui</bundle>
<controller>products</controller>
<action>index</action>
<pages>
<products>
<label>Products</label>
<title>Products</title>
<bundle>product-merchant-portal-gui</bundle>
<controller>products</controller>
<action>index</action>
<visible>1</visible>
</products>
<import-uploads>
<label>Import History</label>
<title>Import History</title>
<bundle>merchant-product-import-merchant-portal-gui</bundle>
<controller>imports</controller>
<action>index</action>
<visible>1</visible>
</import-uploads>
</pages>
</product-merchant-portal-gui>
<agent-dashboard-merchant-portal-gui>
<label>Merchant Users</label>
Expand Down Expand Up @@ -672,4 +690,12 @@
</onboarding>
</pages>
</merchant-portal-payment-settings>
<file-upload-merchant-portal-gui>
<label>Uploaded Files</label>
<title>Uploaded Files</title>
<icon>files</icon>
<bundle>file-upload-merchant-portal-gui</bundle>
<controller>list</controller>
<action>index</action>
</file-upload-merchant-portal-gui>
</config>
3 changes: 3 additions & 0 deletions project.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
"vendor/spryker/zed-ui/src/Spryker/Zed/ZedUi/Presentation/Components/styles.less",
"src/Pyz/Zed/ZedUi/Presentation/Components/styles.less"
],
"stylePreprocessorOptions": {
"includePaths": ["node_modules/"]
},
"scripts": []
},
"configurations": {
Expand Down
37 changes: 37 additions & 0 deletions src/Pyz/Service/AwsS3/AwsS3Config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

/**
* This file is part of the Spryker Commerce OS.
* For full license information, please view the LICENSE file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Pyz\Service\AwsS3;

use Pyz\Shared\AwsS3\AwsS3Constants;
use Spryker\Service\Kernel\AbstractBundleConfig;

class AwsS3Config extends AbstractBundleConfig
{
private const AWS_S3_URL_PATTERN = 's3://%s/%s';

private const CDN_URL_PATTERN = '{schema}://{cdnHost}/{fileName}';

public function getAwsS3UrlPattern(): string
{
return self::AWS_S3_URL_PATTERN;
}

public function getCdnUrlPattern(): string
{
return self::CDN_URL_PATTERN;
}

public function getClientConfigurationForObjectType(string $objectType): array
{
$bucketsConfigurationMap = $this->get(AwsS3Constants::BUCKETS_CONFIGURATION_MAP, []);

return $bucketsConfigurationMap[$objectType] ?? [];
}
}
41 changes: 41 additions & 0 deletions src/Pyz/Service/AwsS3/AwsS3DependencyProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

/**
* This file is part of the Spryker Commerce OS.
* For full license information, please view the LICENSE file that was distributed with this source code.
*/

namespace Pyz\Service\AwsS3;

use Pyz\Service\AwsS3\Dependency\S3ClientProviderPluginInterface;
use Pyz\Service\AwsS3\Plugin\AwsS3\S3ClientProviderPlugin;
use Spryker\Service\Kernel\AbstractBundleDependencyProvider;
use Spryker\Service\Kernel\Container;

/**
* @method \Pyz\Service\AwsS3\AwsS3Config getConfig()
*/
class AwsS3DependencyProvider extends AbstractBundleDependencyProvider
{
public const PLUGIN_S3_CLIENT_PROVIDER = 'PLUGIN_S3_CLIENT_PROVIDER_PLUGIN';

public function provideServiceDependencies(Container $container): Container
{
$container = parent::provideServiceDependencies($container);
$container = $this->addS3ClientProviderPlugin($container);

return $container;
}

private function addS3ClientProviderPlugin(Container $container): Container
{
$container->set(
static::PLUGIN_S3_CLIENT_PROVIDER,
static function (): S3ClientProviderPluginInterface {
return new S3ClientProviderPlugin();
},
);

return $container;
}
}
57 changes: 57 additions & 0 deletions src/Pyz/Service/AwsS3/AwsS3Service.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

/**
* This file is part of the Spryker Commerce OS.
* For full license information, please view the LICENSE file that was distributed with this source code.
*/

namespace Pyz\Service\AwsS3;

use Pyz\Shared\AwsS3\AwsS3Config as SharedAwsS3Config;
use Spryker\Service\Kernel\AbstractService;

/**
* @method \Pyz\Service\AwsS3\AwsS3ServiceFactory getFactory()
*/
class AwsS3Service extends AbstractService implements AwsS3ServiceInterface
{
public function getPresignedUrl(string $fileName, string $objectType): string
{
return $this->getFactory()
->createUrlCreator($objectType)
->getPresignedUrl($fileName);
}

public function getS3ObjectUrl(string $fileName, string $objectType): string
{
return $this->getFactory()
->createAwsS3ObjectReader($objectType)
->getS3ObjectUrl($fileName);
}

/**
* @param string $objectType
*
* @return void
*/
public function registerStreamWrapper(string $objectType = SharedAwsS3Config::OBJECT_TYPE_CVS_IMPORT): void
{
$this->getFactory()
->createUtilAws($objectType)
->registerStreamWrapper();
}

public function getCdnUrl(string $fileName, string $objectType): string
{
return $this->getFactory()
->createUrlCreator($objectType)
->getCdnUrl($fileName);
}

public function deleteS3Object(string $objectType, string $path): void
{
$this->getFactory()
->createAwsS3ObjectDeleter($objectType)
->deleteS3Object($path);
}
}
71 changes: 71 additions & 0 deletions src/Pyz/Service/AwsS3/AwsS3ServiceFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

/**
* This file is part of the Spryker Commerce OS.
* For full license information, please view the LICENSE file that was distributed with this source code.
*/

namespace Pyz\Service\AwsS3;

use Aws\S3\S3Client;
use Aws\S3\S3ClientInterface;
use Pyz\Service\AwsS3\Creator\UrlCreator;
use Pyz\Service\AwsS3\Creator\UrlCreatorInterface;
use Pyz\Service\AwsS3\Deleter\AwsS3ObjectDeleter;
use Pyz\Service\AwsS3\Deleter\AwsS3ObjectDeleterInterface;
use Pyz\Service\AwsS3\Dependency\S3ClientProviderPluginInterface;
use Pyz\Service\AwsS3\Reader\AwsS3ObjectReader;
use Pyz\Service\AwsS3\Reader\AwsS3ObjectReaderInterface;
use Pyz\Service\AwsS3\Util\UtilAws;
use Pyz\Service\AwsS3\Util\UtilAwsInterface;
use Spryker\Service\Kernel\AbstractServiceFactory;

/**
* @method \Pyz\Service\AwsS3\AwsS3Config getConfig()
*/
class AwsS3ServiceFactory extends AbstractServiceFactory
{
public function createUrlCreator(string $objectType): UrlCreatorInterface
{
$s3Client = $this
->getS3ClientProviderPlugin()
->provideConfiguredClientForObjectType($objectType);

return new UrlCreator(
$this->getConfig(),
$s3Client,
$objectType,
);
}

public function createAwsS3ObjectReader(string $objectType): AwsS3ObjectReaderInterface
{
return new AwsS3ObjectReader($this->getConfig(), $objectType);
}

public function createAwsS3ObjectDeleter(string $objectType): AwsS3ObjectDeleterInterface
{
return new AwsS3ObjectDeleter(
$this->createUtilAws($objectType),
);
}

public function createUtilAws(string $objectType): UtilAwsInterface
{
$s3Client = $this
->getS3ClientProviderPlugin()
->provideConfiguredClientForObjectType($objectType);

return new UtilAws($s3Client);
}

public function createS3Client(array $configuration): S3ClientInterface
{
return new S3Client($configuration);
}

public function getS3ClientProviderPlugin(): S3ClientProviderPluginInterface
{
return $this->getProvidedDependency(AwsS3DependencyProvider::PLUGIN_S3_CLIENT_PROVIDER);
}
}
75 changes: 75 additions & 0 deletions src/Pyz/Service/AwsS3/AwsS3ServiceInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

/**
* This file is part of the Spryker Commerce OS.
* For full license information, please view the LICENSE file that was distributed with this source code.
*/

namespace Pyz\Service\AwsS3;

interface AwsS3ServiceInterface
{
/**
* Specification:
* - Returns the presigned URL for the given file name.
*
* @api
*
* @param string $fileName
* @param string $objectType
*
* @return string
*/
public function getPresignedUrl(string $fileName, string $objectType): string;

/**
* Specification:
* - Returns the S3 object URL for the given file name.
*
* @api
*
* @param string $fileName
* @param string $objectType
*
* @return string
*/
public function getS3ObjectUrl(string $fileName, string $objectType): string;

/**
* Specification:
* - Deletes the S3 object for the given path.
*
* @api
*
* @param string $objectType
* @param string $path
*
* @return void
*/
public function deleteS3Object(string $objectType, string $path): void;

/**
* Specification:
* - Registers the stream wrapper for the S3 client.
*
* @api
*
* @param string $objectType
*
* @return void
*/
public function registerStreamWrapper(string $objectType): void;

/**
* Specification:
* - Returns the CDN URL for the given file name and object type.
*
* @api
*
* @param string $fileName
* @param string $objectType
*
* @return string
*/
public function getCdnUrl(string $fileName, string $objectType): string;
}
Loading
Loading