Initial commit: CloudOps infrastructure platform

This commit is contained in:
root
2026-04-09 19:58:57 +02:00
commit 1166a52f26
7762 changed files with 839452 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
# Workflow name:
name: Close Pull Requests
# Workflow triggers:
on:
pull_request_target:
types: [opened]
# Workflow jobs:
jobs:
run:
runs-on: ubuntu-latest
steps:
- uses: superbrothers/close-pull-request@v3
with:
comment: |
Thank you for submitting a pull request. :raised_hands:
We greatly appreciate your willingness to submit a contribution. However, we are not accepting pull requests against this repository, as all development happens on the [main project repository](https://github.com/mautic/mautic).
We kindly request that you submit this pull request against the [respective directory](https://github.com/mautic/mautic/blob/head/plugins/MauticCloudStorageBundle) of the main repository where we'll review and provide feedback. If this is your first Mautic contribution, be sure to read the [contributing guide](https://github.com/mautic/mautic/blob/4.x/.github/CONTRIBUTING.md) which provides guidelines and instructions for submitting contributions.
Thank you again, and we look forward to receiving your contribution! :smiley:
Best,
The Mautic team

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1,34 @@
<?php
return [
'name' => 'Cloud Storage',
'description' => 'Enables integrations with Mautic supported cloud storage services.',
'version' => '1.0',
'author' => 'Mautic',
'services' => [
'integrations' => [
'mautic.integration.amazons3' => [
'class' => MauticPlugin\MauticCloudStorageBundle\Integration\AmazonS3Integration::class,
'arguments' => [
'event_dispatcher',
'mautic.helper.cache_storage',
'doctrine.orm.entity_manager',
'request_stack',
'router',
'translator',
'monolog.logger.mautic',
'mautic.helper.encryption',
'mautic.lead.model.lead',
'mautic.lead.model.company',
'mautic.helper.paths',
'mautic.core.model.notification',
'mautic.lead.model.field',
'mautic.plugin.model.integration_entity',
'mautic.lead.model.dnc',
'mautic.lead.field.fields_with_unique_identifier',
],
],
],
],
];

View File

@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
use Mautic\CoreBundle\DependencyInjection\MauticCoreExtension;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return function (ContainerConfigurator $configurator): void {
$services = $configurator->services()
->defaults()
->autowire()
->autoconfigure()
->public();
$excludes = [
];
$services->load('MauticPlugin\\MauticCloudStorageBundle\\', '../')
->exclude('../{'.implode(',', array_merge(MauticCoreExtension::DEFAULT_EXCLUDES, $excludes)).'}');
};

View File

@@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace MauticPlugin\MauticCloudStorageBundle\DependencyInjection;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
class MauticCloudStorageExtension extends Extension
{
/**
* @param mixed[] $configs
*/
public function load(array $configs, ContainerBuilder $container): void
{
$loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../Config'));
$loader->load('services.php');
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace MauticPlugin\MauticCloudStorageBundle\EventListener;
use Mautic\AssetBundle\AssetEvents;
use Mautic\AssetBundle\Event as Events;
use MauticPlugin\MauticCloudStorageBundle\Exception\InvalidCredentialConfigurationException;
use MauticPlugin\MauticCloudStorageBundle\Integration\CloudStorageIntegration;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class RemoteAssetBrowseSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
AssetEvents::ASSET_ON_REMOTE_BROWSE => ['onAssetRemoteBrowse', 0],
];
}
/**
* Fetches the connector for an event's integration.
*/
public function onAssetRemoteBrowse(Events\RemoteAssetBrowseEvent $event): void
{
/** @var CloudStorageIntegration $integration */
$integration = $event->getIntegration();
try {
$event->setAdapter($integration->getAdapter());
} catch (InvalidCredentialConfigurationException $e) {
$event->setFailed($e->getMessage());
}
}
}

View File

@@ -0,0 +1,7 @@
<?php
namespace MauticPlugin\MauticCloudStorageBundle\Exception;
class InvalidCredentialConfigurationException extends \RuntimeException
{
}

View File

@@ -0,0 +1,7 @@
<?php
namespace MauticPlugin\MauticCloudStorageBundle\Exception;
class NoFormNeededException extends \Exception
{
}

View File

@@ -0,0 +1,138 @@
<?php
namespace MauticPlugin\MauticCloudStorageBundle\Integration;
use Aws\S3\S3Client;
use Gaufrette\Adapter\AwsS3;
use Gaufrette\Extras\Resolvable\ResolvableFilesystem;
use Gaufrette\Extras\Resolvable\Resolver\AwsS3PublicUrlResolver;
use Gaufrette\Filesystem;
use MauticPlugin\MauticCloudStorageBundle\Exception\InvalidCredentialConfigurationException;
use MauticPlugin\MauticCloudStorageBundle\Exception\NoFormNeededException;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormBuilder;
class AmazonS3Integration extends CloudStorageIntegration
{
private ?ResolvableFilesystem $fileSystem = null;
public function getName(): string
{
return 'AmazonS3';
}
public function getDisplayName(): string
{
return 'Amazon S3';
}
/**
* Get the array key for clientId.
*/
public function getClientIdKey(): string
{
return 'client_id';
}
/**
* Get the array key for client secret.
*/
public function getClientSecretKey(): string
{
return 'client_secret';
}
/**
* @return array<string, string>
*/
public function getRequiredKeyFields(): array
{
return [
'client_id' => 'mautic.integration.keyfield.clientid',
'client_secret' => 'mautic.integration.keyfield.clientsecret',
'bucket' => 'mautic.integration.keyfield.amazons3.bucket',
];
}
/**
* @param Form|FormBuilder $builder
* @param array $data
* @param string $formArea
*/
public function appendToForm(&$builder, $data, $formArea): void
{
if ('keys' === $formArea) {
$builder->add(
'region',
TextType::class,
[
'label' => 'mautic.integration.Amazon.region',
'attr' => ['class' => 'form-control'],
'data' => empty($data['region']) ? 'us-east-1' : $data['region'],
'required' => false,
]
);
$builder->add(
'endpoint',
TextType::class,
[
'label' => 'mautic.integration.Amazon.endpoint',
'attr' => ['class' => 'form-control'],
'data' => empty($data['endpoint']) ? null : $data['endpoint'],
'required' => false,
]
);
}
}
/**
* @return AwsS3
*/
public function getAdapter()
{
if (!$this->adapter || !$this->fileSystem) {
$keys = $this->getDecryptedApiKeys();
if (empty($keys['client_id']) || empty($keys['client_secret'])) {
$errorMessage = 'Configuration error: client_id and client_secret are not set!';
throw new InvalidCredentialConfigurationException('AmazonS3Integration misconfigured: client_id or client_secret missing.');
}
$s3Args = [
'version' => 'latest',
'region' => (empty($keys['region'])) ? 'us-east-1' : $keys['region'],
'credentials' => [
'key' => $keys['client_id'],
'secret' => $keys['client_secret'],
],
];
if (!empty($keys['endpoint'])) {
$s3Args['endpoint'] = $keys['endpoint'];
}
$service = new S3Client($s3Args);
$this->adapter = new AwsS3($service, $keys['bucket']);
$decorated = new Filesystem($this->adapter);
$this->fileSystem = new ResolvableFilesystem(
$decorated,
new AwsS3PublicUrlResolver($service, $keys['bucket'])
);
}
return $this->adapter;
}
public function getForm(): string
{
throw new NoFormNeededException();
}
public function getPublicUrl($key)
{
$this->getAdapter();
return $this->fileSystem->resolve($key);
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace MauticPlugin\MauticCloudStorageBundle\Integration;
use Gaufrette\Adapter;
use Mautic\PluginBundle\Integration\AbstractIntegration;
use MauticPlugin\MauticCloudStorageBundle\Exception\NoFormNeededException;
abstract class CloudStorageIntegration extends AbstractIntegration
{
/**
* @var Adapter
*/
protected $adapter;
public function appendToForm(&$builder, $data, $formArea): void
{
if ('features' !== $formArea) {
return;
}
try {
$builder->add(
'provider',
$this->getForm(),
[
'label' => 'mautic.integration.form.provider.settings',
'required' => false,
'data' => $data['provider'] ?? [],
]
);
} catch (NoFormNeededException) {
}
}
public function getAuthenticationType()
{
return 'api';
}
/**
* Retrieves an Adapter object for this integration.
*
* @return Adapter
*/
abstract public function getAdapter();
/**
* Retrieves FQCN form type class name.
*
* @throws NoFormNeededException
*/
abstract public function getForm(): string;
/**
* Retrieves the public URL for a given key.
*
* @param string $key
*
* @return string
*/
abstract public function getPublicUrl($key);
public function getSupportedFeatures()
{
return ['cloud_storage'];
}
}

View File

@@ -0,0 +1,9 @@
<?php
namespace MauticPlugin\MauticCloudStorageBundle;
use Mautic\PluginBundle\Bundle\PluginBundleBase;
class MauticCloudStorageBundle extends PluginBundleBase
{
}

View File

@@ -0,0 +1,5 @@
# Mautic bundle for Cloud storage plugin
## This plugin is managed centrally in https://github.com/mautic/mautic/blob/head/plugins/MauticCloudStorageBundle and this is a read-only mirror repository.
**📣 Please make PRs and issues against Mautic Core, not here!**

View File

@@ -0,0 +1,6 @@
mautic.integration.form.feature.cloud_storage="Connect to cloud storage provider"
mautic.integration.form.provider.settings="Provider Settings"
mautic.integration.keyfield.amazons3.bucket="Bucket Path"
mautic.integration.keyfield.OpenCloud.containerName="Container Storage Path"
mautic.integration.Amazon.region="S3 Region"
mautic.integration.Amazon.endpoint="S3 Endpoint"

View File

@@ -0,0 +1,17 @@
{
"name": "mautic/plugin-cloudstorage",
"description": "Cloudstorage Plugin",
"type": "mautic-plugin",
"keywords": [
"mautic",
"plugin",
"integration"
],
"extra": {
"install-directory-name": "MauticCloudStorageBundle"
},
"minimum-stability": "dev",
"require": {
"mautic/core-lib": "^7.0"
}
}