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,32 @@
<?php
use Symfony\Component\Dotenv\Dotenv;
require dirname(__DIR__).'/../autoload.php';
if (!class_exists(Dotenv::class)) {
throw new LogicException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.');
}
$reflection = new ReflectionClass(Dotenv::class);
$vendorRootPath = dirname($reflection->getFileName(), 4);
// Load cached env vars if the .env.local.php file exists
// Run "composer dump-env prod" to create it (requires symfony/flex >=1.2)
if (is_array($env = @include $vendorRootPath.'/.env.local.php') && (!isset($env['APP_ENV']) || ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env['APP_ENV']) === $env['APP_ENV'])) {
(new Dotenv(false))->populate($env);
} else {
// load all the .env files
(new Dotenv())->loadEnv($vendorRootPath.'/.env', null, 'prod');
}
$_SERVER += $_ENV;
$_SERVER['MAUTIC_TABLE_PREFIX'] = $_ENV['MAUTIC_TABLE_PREFIX'] = ($_SERVER['MAUTIC_TABLE_PREFIX'] ?? $_ENV['MAUTIC_TABLE_PREFIX'] ?? null) ?: '';
$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'prod';
$_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV'];
$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0';
$_SERVER['IPS_ALLOWED'] = $_ENV['IPS_ALLOWED'] = ($_SERVER['IPS_ALLOWED'] ?? $_ENV['IPS_ALLOWED'] ?? null) ?: '127.0.0.1,::1,172.17.0.1';
if ('dev' === strtolower($_SERVER['APP_ENV']) && extension_loaded('apcu') && in_array(@$_SERVER['REMOTE_ADDR'], explode(',', $_SERVER['IPS_ALLOWED']))) {
@apcu_clear_cache();
}

View File

@@ -0,0 +1,440 @@
<?php
use Doctrine\DBAL\Types\Types;
use Mautic\CoreBundle\Doctrine\Type;
use Mautic\CoreBundle\EventListener\ConsoleErrorListener;
use Mautic\CoreBundle\EventListener\ConsoleTerminateListener;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
/** @var Symfony\Component\DependencyInjection\ContainerBuilder $container */
// Include path settings
$root = $container->getParameter('mautic.application_dir').'/app';
$projectRoot = $container->getParameter('kernel.project_dir');
include __DIR__.'/paths_helper.php';
// Build and store Mautic bundle metadata
$symfonyBundles = $container->getParameter('kernel.bundles');
$bundleMetadataBuilder = new Mautic\CoreBundle\DependencyInjection\Builder\BundleMetadataBuilder($symfonyBundles, $paths);
$container->setParameter('mautic.bundles', $bundleMetadataBuilder->getCoreBundleMetadata());
$container->setParameter('mautic.plugin.bundles', $bundleMetadataBuilder->getPluginMetadata());
// Set IP lookup services
$container->setParameter('mautic.ip_lookup_services', $bundleMetadataBuilder->getIpLookupServices());
// Load parameters
include __DIR__.'/parameters.php';
$container->loadFromExtension('mautic_core');
$parameterLoader = new Mautic\CoreBundle\Loader\ParameterLoader();
$configParameterBag = $parameterLoader->getParameterBag();
$localConfigParameterBag = $parameterLoader->getLocalParameterBag();
// Decide on secure cookie based on site_url setting or the request if in installer
// This cannot be set dynamically
if (defined('MAUTIC_INSTALLER')) {
$request = Symfony\Component\HttpFoundation\Request::createFromGlobals();
$secureCookie = $request->isSecure();
} else {
$siteUrl = $configParameterBag->get('site_url');
$secureCookie = ($siteUrl && str_starts_with($siteUrl, 'https'));
}
$container->loadFromExtension('framework', [
'assets' => [
'base_path' => './',
],
'secret' => '%mautic.secret_key%',
'router' => [
'resource' => '%mautic.application_dir%/app/config/routing.php',
'strict_requirements' => null,
],
'form' => null,
'csrf_protection' => true,
'validation' => [
'enable_attributes' => false,
],
'default_locale' => '%mautic.locale%',
'translator' => [
'enabled' => true,
'fallback' => 'en_US',
],
'session' => [ // handler_id set to null will use default session handler from php.ini
'handler_id' => null,
'name' => '%env(MAUTIC_SESSION_NAME)%',
'cookie_secure' => $secureCookie,
'cookie_samesite' => 'lax',
],
'fragments' => null,
'http_method_override' => true,
'mailer' => [
'transports' => [
'main' => '%env(urlencoded-dsn:MAUTIC_MAILER_DSN)%',
],
],
'messenger' => [
'failure_transport' => 'failed',
'transports' => [
'email' => [
'dsn' => '%env(urlencoded-dsn:MAUTIC_MESSENGER_DSN_EMAIL)%',
'retry_strategy' => [
'service' => Mautic\MessengerBundle\Retry\RetryStrategy::class,
],
],
'hit' => [
'dsn' => '%env(urlencoded-dsn:MAUTIC_MESSENGER_DSN_HIT)%',
'retry_strategy' => [
'service' => Mautic\MessengerBundle\Retry\RetryStrategy::class,
],
],
'failed' => '%env(messenger-nullable:MAUTIC_MESSENGER_DSN_FAILED)%',
],
'routing' => [
Symfony\Component\Mailer\Messenger\SendEmailMessage::class => 'email',
Mautic\MessengerBundle\Message\TestEmail::class => 'email',
Mautic\MessengerBundle\Message\TestHit::class => 'hit',
Mautic\MessengerBundle\Message\TestFailed::class => 'failed',
Mautic\MessengerBundle\Message\PageHitNotification::class => 'hit',
Mautic\MessengerBundle\Message\EmailHitNotification::class => 'hit',
],
],
/*'validation' => array(
'static_method' => array('loadValidatorMetadata')
)*/
]);
$container->setParameter('mautic.famework.csrf_protection', true);
// Doctrine Configuration
$connectionSettings = [
'driver' => '%mautic.db_driver%',
'host' => '%mautic.db_host%',
'port' => '%mautic.db_port%',
'dbname' => '%mautic.db_name%',
'user' => '%mautic.db_user%',
'password' => '%mautic.db_password%',
'charset' => 'utf8mb4',
'default_table_options' => [
'charset' => 'utf8mb4',
'row_format' => 'DYNAMIC',
],
// Prevent Doctrine from crapping out with "unsupported type" errors due to it examining all tables in the database and not just Mautic's
'mapping_types' => [
'enum' => 'string',
'point' => 'string',
'bit' => 'string',
],
'server_version' => '%env(mauticconst:MAUTIC_DB_SERVER_VERSION)%',
'wrapper_class' => Mautic\CoreBundle\Doctrine\Connection\ConnectionWrapper::class,
'options' => [PDO::ATTR_STRINGIFY_FETCHES => true], // @see https://www.php.net/manual/en/migration81.incompatible.php#migration81.incompatible.pdo.mysql
];
if (!empty($localConfigParameterBag->get('db_host_ro'))) {
$connectionSettings['wrapper_class'] = Mautic\CoreBundle\Doctrine\Connection\PrimaryReadReplicaConnectionWrapper::class;
$connectionSettings['keep_replica'] = true;
$connectionSettings['replicas'] = [
'replica1' => [
'host' => '%mautic.db_host_ro%',
'port' => '%mautic.db_port%',
'dbname' => '%mautic.db_name%',
'user' => '%mautic.db_user%',
'password' => '%mautic.db_password%',
'charset' => 'utf8mb4',
],
];
}
$container->loadFromExtension('doctrine', [
'dbal' => [
'default_connection' => 'default',
'connections' => [
'default' => $connectionSettings,
'unbuffered' => array_merge($connectionSettings, [
'options' => [
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false,
PDO::ATTR_STRINGIFY_FETCHES => true, // @see https://www.php.net/manual/en/migration81.incompatible.php#migration81.incompatible.pdo.mysql
],
]),
],
'types' => [
Types::ARRAY => Type\ArrayType::class,
Types::DATETIME_MUTABLE => Type\UTCDateTimeType::class,
Types::DATETIME_IMMUTABLE => Type\UTCDateTimeImmutableType::class,
Type\GeneratedType::GENERATED => Type\GeneratedType::class,
],
],
'orm' => [
'auto_generate_proxy_classes' => '%kernel.debug%',
'auto_mapping' => true,
'mappings' => $bundleMetadataBuilder->getOrmConfig(),
'dql' => [
'string_functions' => [
'match' => DoctrineExtensions\Query\Mysql\MatchAgainst::class,
],
],
'result_cache_driver' => [
'type' => 'pool',
'pool' => 'doctrine_result_cache',
],
],
]);
// MigrationsBundle Configuration
$container->loadFromExtension('doctrine_migrations', [
'migrations_paths' => [
'Mautic\\Migrations' => '%mautic.application_dir%/app/migrations',
],
'storage' => [
'table_storage' => [
'table_name' => '%env(MAUTIC_MIGRATIONS_TABLE_NAME)%',
],
],
'custom_template' => '%mautic.application_dir%/app/migrations/Migration.template',
]);
// KnpMenu Configuration
$container->loadFromExtension('knp_menu', [
'default_renderer' => 'mautic',
]);
// OneupUploader Configuration
$container->loadFromExtension('oneup_uploader', [
// 'orphanage' => array(
// 'maxage' => 86400,
// 'directory' => $uploadDir . '/orphanage'
// ),
'mappings' => [
'asset' => [
'error_handler' => 'mautic.asset.upload.error.handler',
'frontend' => 'custom',
'custom_frontend' => [
'class' => 'Mautic\AssetBundle\Controller\UploadController',
'name' => 'mautic',
],
// 'max_size' => ($maxSize * 1000000),
// 'use_orphanage' => true,
'storage' => [
'directory' => '%mautic.upload_dir%',
],
],
],
]);
// FOS Rest for API
$container->loadFromExtension('fos_rest', [
'routing_loader' => false,
'body_listener' => true,
'view' => [
'formats' => [
'json' => true,
'xml' => false,
'html' => false,
],
],
'disable_csrf_role' => 'ROLE_API',
]);
// JMS Serializer for API and Webhooks
$container->loadFromExtension('jms_serializer', [
'handlers' => [
'datetime' => [
'default_format' => 'c',
'default_timezone' => 'UTC',
],
],
'property_naming' => [
'separator' => '',
'lower_case' => false,
],
'metadata' => [
'cache' => 'file',
'auto_detection' => false,
'directories' => $bundleMetadataBuilder->getSerializerConfig(),
],
'visitors' => [
'json_deserialization' => [
'options' => JSON_PRETTY_PRINT,
],
],
]);
$container->loadFromExtension('framework', [
'cache' => [
'pools' => [
'doctrine_result_cache' => [
'adapter' => 'cache.adapter.array',
],
],
],
]);
$container->setParameter(
'jms_serializer.camel_case_naming_strategy.class',
'JMS\Serializer\Naming\IdenticalPropertyNamingStrategy'
);
// Monolog formatter
$container->register('mautic.monolog.fulltrace.formatter', 'Monolog\Formatter\LineFormatter')
->addMethodCall('includeStacktraces', [true])
->addMethodCall('ignoreEmptyContextAndExtra', [true]);
// Register command line logging
$container->setParameter(
'console_error_listener.class',
ConsoleErrorListener::class
);
$definitionConsoleErrorListener = new Definition(
'%console_error_listener.class%',
[new Reference('monolog.logger.mautic')]
);
$definitionConsoleErrorListener->addTag(
'kernel.event_listener',
['event' => 'console.error']
);
$container->setDefinition(
'mautic.kernel.listener.command_exception',
$definitionConsoleErrorListener
);
$container->setParameter(
'console_terminate_listener.class',
ConsoleTerminateListener::class
);
$definitionConsoleErrorListener = new Definition(
'%console_terminate_listener.class%',
[new Reference('monolog.logger.mautic')]
);
$definitionConsoleErrorListener->addTag(
'kernel.event_listener',
['event' => 'console.terminate']
);
$container->setDefinition(
'mautic.kernel.listener.command_terminate',
$definitionConsoleErrorListener
);
// ElFinder File Manager
$container->loadFromExtension('fm_elfinder', [
'assets_path' => 'media/assets',
'instances' => [
'default' => [
'locale' => '%mautic.locale%',
'cors_support' => true,
'editor' => 'custom',
'editor_template' => '@bundles/CoreBundle/Assets/js/libraries/filemanager/index.html.twig',
'fullscreen' => true,
// 'include_assets' => true,
'relative_path' => false,
'connector' => [
'debug' => '%kernel.debug%',
'binds' => [
'upload.pre mkdir.pre mkfile.pre rename.pre archive.pre ls.pre' => [
'Plugin.Sanitizer.cmdPreprocess',
],
'upload.presave paste.copyfrom' => [
'Plugin.Sanitizer.onUpLoadPreSave',
],
],
'plugins' => [
'Sanitizer' => [
'enable' => true,
'callBack' => '\Mautic\CoreBundle\Helper\InputHelper::transliterateFilename',
],
],
'roots' => [
'local' => [
'driver' => 'Flysystem',
'path' => '',
'flysystem' => [
'type' => 'custom',
'adapter_service' => 'mautic.core.service.local_file_adapter',
'options' => [],
],
'upload_allow' => ['image/png', 'image/jpg', 'image/jpeg', 'image/gif'],
'upload_deny' => ['all'],
'accepted_name' => '/^[\w\x{0300}-\x{036F}][\w\x{0300}-\x{036F}\s\.\%\-]*$/u', // Supports diacritic symbols
'url' => '%env(resolve:MAUTIC_EL_FINDER_URL)%', // We need to specify URL in case mod_rewrite is disabled
'tmb_path' => '%env(resolve:MAUTIC_EL_FINDER_PATH)%/.tmb/',
'tmb_url' => '%env(resolve:MAUTIC_EL_FINDER_URL)%/.tmb/',
],
],
],
],
],
]);
// API Platform Configuration
$container->loadFromExtension('api_platform', [
'title' => 'Mautic API',
'description' => 'API endpoints for Mautic',
'version' => '1.0.0',
'show_webby' => false,
'enable_swagger' => true,
'enable_swagger_ui' => true,
'swagger' => [
'versions' => [3],
],
'enable_re_doc' => true,
'enable_entrypoint' => true,
'enable_docs' => true,
'enable_profiler' => false,
'collection' => [
'pagination' => [
'enabled' => true,
],
],
'patch_formats' => [
'json' => ['application/merge-patch+json'],
'jsonapi' => ['application/vnd.api+json'],
],
'formats' => [
'jsonld' => [
'mime_types' => [
'application/ld+json',
],
],
'json' => [
'mime_types' => [
'application/json',
],
],
'jsonapi' => [
'mime_types' => [
'application/vnd.api+json',
],
],
'html' => [
'mime_types' => [
'text/html',
],
],
],
'error_formats' => [
'jsonproblem' => [
'mime_types' => [
'application/problem+json',
],
],
'jsonapi' => [
'mime_types' => [
'application/vnd.api+json',
],
],
'jsonld' => [
'mime_types' => [
'application/ld+json',
],
],
],
'exception_to_status' => [
'Symfony\Component\Serializer\Exception\ExceptionInterface' => 400,
'ApiPlatform\Exception\InvalidArgumentException' => Symfony\Component\HttpFoundation\Response::HTTP_BAD_REQUEST,
'ApiPlatform\Validator\Exception\ValidationException' => 400,
'Doctrine\ORM\OptimisticLockException' => 409,
'Symfony\Component\Security\Core\Exception\AccessDeniedException' => 403,
],
]);

View File

@@ -0,0 +1,104 @@
<?php
use Mautic\CoreBundle\Loader\ParameterLoader;
$root = $container->getParameter('mautic.application_dir').'/app';
$configBaseDir = ParameterLoader::getLocalConfigBaseDir($root);
$loader->import('config.php');
if (file_exists($configBaseDir.'/config/security_local.php')) {
$loader->import($configBaseDir.'/config/security_local.php');
} else {
$loader->import('security.php');
}
// Twig Configuration
$container->loadFromExtension('twig', [
'cache' => false,
'debug' => '%kernel.debug%',
'strict_variables' => true,
'paths' => [
'%mautic.application_dir%/app/bundles' => 'bundles',
'%mautic.application_dir%/app/bundles/CoreBundle' => 'MauticCore',
'%mautic.application_dir%/themes' => 'themes',
],
'form_themes' => [
// Can be found at bundles/CoreBundle/Resources/views/mautic_form_layout.html.twig
'@MauticCore/FormTheme/mautic_form_layout.html.twig',
],
]);
$container->loadFromExtension('framework', [
'router' => [
'resource' => '%mautic.application_dir%/app/config/routing_dev.php',
'strict_requirements' => true,
],
'profiler' => [
'only_exceptions' => false,
],
]);
$container->loadFromExtension('web_profiler', [
'toolbar' => true,
'intercept_redirects' => false,
]);
$container->loadFromExtension('monolog', [
'channels' => [
'mautic',
'chrome',
],
'handlers' => [
'main' => [
'formatter' => 'mautic.monolog.fulltrace.formatter',
'type' => 'rotating_file',
'path' => '%kernel.logs_dir%/%kernel.environment%.php',
'level' => 'debug',
'channels' => [
'!mautic',
],
'max_files' => 7,
],
'console' => [
'type' => 'console',
'bubble' => false,
],
'mautic' => [
'formatter' => 'mautic.monolog.fulltrace.formatter',
'type' => 'rotating_file',
'path' => '%kernel.logs_dir%/mautic_%kernel.environment%.php',
'level' => 'debug',
'channels' => [
'mautic',
],
'max_files' => 7,
],
'chrome' => [
'type' => 'chromephp',
'level' => 'debug',
'channels' => [
'chrome',
],
],
],
]);
$container->loadFromExtension('maker', [
'root_namespace' => 'Mautic',
]);
// API Platform Configuration
$container->loadFromExtension('api_platform', [
'enable_profiler' => true,
]);
// Allow overriding config without a requiring a full bundle or hacks
if (file_exists($configBaseDir.'/config/config_override.php')) {
$loader->import($configBaseDir.'/config/config_override.php');
}
// Allow local settings without committing to git such as swift mailer delivery address overrides
if (file_exists($configBaseDir.'/config/config_local.php')) {
$loader->import($configBaseDir.'/config/config_local.php');
}

View File

@@ -0,0 +1,86 @@
<?php
use Mautic\CoreBundle\Loader\ParameterLoader;
$root = $container->getParameter('mautic.application_dir').'/app';
$configBaseDir = ParameterLoader::getLocalConfigBaseDir($root);
$loader->import('config.php');
if (file_exists($configBaseDir.'/config/security_local.php')) {
$loader->import($configBaseDir.'/config/security_local.php');
} else {
$loader->import('security.php');
}
/*
$container->loadFromExtension("framework", array(
"validation" => array(
"cache" => "apc"
)
));
$container->loadFromExtension("doctrine", array(
"orm" => array(
"metadata_cache_driver" => "apc",
"result_cache_driver" => "apc",
"query_cache_driver" => "apc"
)
));
*/
$container->loadFromExtension('monolog', [
'channels' => [
'mautic',
],
'handlers' => [
'main' => [
'type' => 'fingers_crossed',
'buffer_size' => '200',
'action_level' => 'error',
'handler' => 'nested',
'channels' => [
'!mautic',
],
],
'nested' => [
'type' => 'rotating_file',
'path' => '%kernel.logs_dir%/%kernel.environment%.php',
'level' => 'error',
'max_files' => 7,
],
'mautic' => [
'type' => 'service',
'id' => 'mautic.monolog.handler',
'channels' => [
'mautic',
],
],
],
]);
// Twig Configuration
$container->loadFromExtension('twig', [
'cache' => '%env(resolve:MAUTIC_TWIG_CACHE_DIR)%',
'auto_reload' => true,
'strict_variables' => true,
'paths' => [
'%mautic.application_dir%/app/bundles' => 'bundles',
'%mautic.application_dir%/app/bundles/CoreBundle' => 'MauticCore',
'%mautic.application_dir%/themes' => 'themes',
],
'form_themes' => [
// Can be found at bundles/CoreBundle/Resources/views/mautic_form_layout.html.twig
'@MauticCore/FormTheme/mautic_form_layout.html.twig',
],
]);
// Allow overriding config without a requiring a full bundle or hacks
if (file_exists($configBaseDir.'/config/config_override.php')) {
$loader->import($configBaseDir.'/config/config_override.php');
}
// Allow local settings without committing to git such as swift mailer delivery address overrides
if (file_exists($configBaseDir.'/config/config_local.php')) {
$loader->import($configBaseDir.'/config/config_local.php');
}

View File

@@ -0,0 +1,159 @@
<?php
use Doctrine\Bundle\FixturesBundle\DependencyInjection\CompilerPass\FixturesCompilerPass;
use Mautic\CoreBundle\Loader\ParameterLoader;
use Mautic\CoreBundle\Test\EnvLoader;
use Symfony\Component\DependencyInjection\Reference;
/** @var Symfony\Component\DependencyInjection\ContainerBuilder $container */
// Include path settings
$root = $container->getParameter('mautic.application_dir').'/app';
$configBaseDir = ParameterLoader::getLocalConfigBaseDir($root);
$loader->import('config.php');
EnvLoader::load();
// Define some constants from .env
defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', getenv('MAUTIC_DB_PREFIX') ?: '');
defined('MAUTIC_ENV') || define('MAUTIC_ENV', getenv('MAUTIC_ENV') ?: 'test');
// Twig Configuration
$container->loadFromExtension('twig', [
'cache' => false,
'debug' => '%kernel.debug%',
'strict_variables' => true,
'paths' => [
'%mautic.application_dir%/app/bundles' => 'bundles',
'%mautic.application_dir%/app/bundles/CoreBundle' => 'MauticCore',
'%mautic.application_dir%/themes' => 'themes',
],
'form_themes' => [
// Can be found at bundles/CoreBundle/Resources/views/mautic_form_layout.html.twig
'@MauticCore/FormTheme/mautic_form_layout.html.twig',
],
]);
$container->loadFromExtension('framework', [
'test' => true,
'session' => [
'storage_factory_id' => 'session.storage.factory.mock_file',
'name' => 'MOCKSESSION',
],
'profiler' => [
'collect' => false,
],
'translator' => [
'enabled' => true,
],
'csrf_protection' => [
'enabled' => true,
],
]);
$container->setParameter('mautic.famework.csrf_protection', true);
$container->loadFromExtension('web_profiler', [
'toolbar' => false,
'intercept_redirects' => false,
]);
$connectionSettings = [
'host' => '%env(DB_HOST)%' ?: '%mautic.db_host%',
'port' => '%env(DB_PORT)%' ?: '%mautic.db_port%',
'dbname' => '%env(DB_NAME)%' ?: '%mautic.db_name%',
'user' => '%env(DB_USER)%' ?: '%mautic.db_user%',
'password' => '%env(DB_PASSWD)%' ?: '%mautic.db_password%',
'options' => [PDO::ATTR_STRINGIFY_FETCHES => true], // @see https://www.php.net/manual/en/migration81.incompatible.php#migration81.incompatible.pdo.mysql
];
$container->loadFromExtension('doctrine', [
'dbal' => [
'connections' => [
'default' => $connectionSettings,
'unbuffered' => $connectionSettings,
],
],
]);
$container->setParameter('mautic.db_table_prefix', MAUTIC_TABLE_PREFIX);
$container->loadFromExtension('monolog', [
'channels' => [
'mautic',
],
'handlers' => [
'main' => [
'formatter' => 'mautic.monolog.fulltrace.formatter',
'type' => 'rotating_file',
'path' => '%kernel.logs_dir%/%kernel.environment%.php',
'level' => getenv('MAUTIC_DEBUG_LEVEL') ?: 'error',
'channels' => [
'!mautic',
],
'max_files' => 7,
],
'console' => [
'type' => 'console',
'bubble' => false,
],
'mautic' => [
'formatter' => 'mautic.monolog.fulltrace.formatter',
'type' => 'rotating_file',
'path' => '%kernel.logs_dir%/mautic_%kernel.environment%.php',
'level' => getenv('MAUTIC_DEBUG_LEVEL') ?: 'error',
'channels' => [
'mautic',
],
'max_files' => 7,
],
],
]);
$container->loadFromExtension('liip_test_fixtures', [
'cache_db' => [
'sqlite' => 'liip_functional_test.services_database_backup.sqlite',
],
'keep_database_and_schema' => true,
]);
$loader->import('security_test.php');
// Allow overriding config without a requiring a full bundle or hacks
if (file_exists($configBaseDir.'/config/config_override.php')) {
$loader->import($configBaseDir.'/config/config_override.php');
}
// Add required parameters
$container->setParameter('mautic.secret_key', '68c7e75470c02cba06dd543431411e0de94e04fdf2b3a2eac05957060edb66d0');
$container->setParameter('mautic.security.disableUpdates', true);
$container->setParameter('mautic.rss_notification_url', null);
$container->setParameter('mautic.batch_sleep_time', 0);
// Turn off creating of indexes in lead field fixtures
$container->register('mautic.install.fixture.lead_field', Mautic\InstallBundle\InstallFixtures\ORM\LeadFieldData::class)
->addArgument(new Reference('translator'))
->addTag(FixturesCompilerPass::FIXTURE_TAG)
->setPublic(true);
if (defined('IS_PHPUNIT')) {
$container->register('security.csrf.token_storage', Mautic\CoreBundle\Test\Session\InMemoryTokenStorage::class)->setAutowired(true);
}
// Use static namespace for token manager
$container->register('security.csrf.token_manager', Symfony\Component\Security\Csrf\CsrfTokenManager::class)
->addArgument(new Reference('security.csrf.token_generator'))
->addArgument(new Reference('security.csrf.token_storage'))
->addArgument('test')
->setPublic(true);
// HTTP client mock handler providing response queue
$container->register(GuzzleHttp\Handler\MockHandler::class)->setPublic(true);
$container->register('http_client', Symfony\Component\HttpClient\MockHttpClient::class)
->setPublic(true);
$container->register('test.service_container', Mautic\CoreBundle\Test\Container\TestContainer::class)
->setArgument('$kernel', new Reference('kernel'))
->setArgument('$privateServicesLocatorId', 'test.private_services_locator')
->setPublic(true);

View File

@@ -0,0 +1,58 @@
<?php
$root = $container->getParameter('mautic.application_dir').'/app';
include __DIR__.'/paths_helper.php';
// load default parameters from bundle files
$core = $container->getParameter('mautic.bundles');
$plugins = $container->getParameter('mautic.plugin.bundles');
$bundles = array_merge($core, $plugins);
unset($core, $plugins);
$mauticParams = [];
foreach ($bundles as $bundle) {
if (!empty($bundle['config']['parameters'])) {
$mauticParams = array_merge($mauticParams, $bundle['config']['parameters']);
}
}
// Set the parameters in the container with env processors
foreach ($mauticParams as $k => $v) {
switch (true) {
case is_bool($v):
$type = 'bool:';
break;
case is_int($v):
// some configuration entries require processor to return explicit int, instead of string|int type,
// which is returned by \Mautic\CoreBundle\DependencyInjection\EnvProcessor\IntNullableProcessor
if ('rememberme_lifetime' === $k) {
$type = 'int:';
break;
}
$type = 'intNullable:';
break;
case is_array($v):
$type = 'json:';
break;
case is_float($v):
$type = 'float:';
break;
default:
$type = 'nullable:';
}
// Add to the container with the applicable processor
$container->setParameter("mautic.{$k}", sprintf('%%env(%sresolve:MAUTIC_%s)%%', $type, mb_strtoupper($k)));
}
// Set the router URI for CLI
$container->setParameter('router.request_context.host', '%env(MAUTIC_REQUEST_CONTEXT_HOST)%');
$container->setParameter('router.request_context.scheme', '%env(MAUTIC_REQUEST_CONTEXT_SCHEME)%');
$container->setParameter('router.request_context.base_url', '%env(MAUTIC_REQUEST_CONTEXT_BASE_URL)%');
$container->setParameter('request_listener.http_port', '%env(MAUTIC_REQUEST_CONTEXT_HTTP_PORT)%');
$container->setParameter('request_listener.https_port', '%env(MAUTIC_REQUEST_CONTEXT_HTTPS_PORT)%');
unset($mauticParams, $replaceRootPlaceholder, $bundles);

View File

@@ -0,0 +1,31 @@
<?php
$paths = [
// customizable
'themes' => 'themes',
'assets' => 'app/assets',
'media' => 'media',
'asset_prefix' => '',
'plugins' => 'plugins',
'translations' => 'translations',
'local_config' => '%kernel.project_dir%/config/local.php',
];
$root = $root ?? realpath(__DIR__.'/..');
$projectRoot = $projectRoot ?? Mautic\CoreBundle\Loader\ParameterLoader::getProjectDirByRoot($root);
// allow easy overrides of the above
if (file_exists($projectRoot.'/config/paths_local.php')) {
include $projectRoot.'/config/paths_local.php';
} elseif (file_exists($root.'/config/paths_local.php')) {
include $root.'/config/paths_local.php';
}
// fixed
$paths = array_merge($paths, [
// remove /app from the root
'root' => substr($root, 0, -4),
'app' => 'app',
'bundles' => 'app/bundles',
'vendor' => 'vendor',
]);

View File

@@ -0,0 +1,17 @@
<?php
include 'paths.php';
// Closure to replace kernel.project_dir placeholders
$replaceRootPlaceholder = function (&$value) use ($projectRoot, &$replaceRootPlaceholder) {
if (is_array($value)) {
foreach ($value as &$v) {
$replaceRootPlaceholder($v);
}
} elseif (false !== strpos($value, '%kernel.project_dir%')) {
$value = str_replace('%kernel.project_dir%', $projectRoot, $value);
}
};
// Handle paths
$replaceRootPlaceholder($paths);

View File

@@ -0,0 +1,19 @@
<?php
use Symfony\Component\Routing\RouteCollection;
// loads Mautic's custom routing in src/Mautic/BaseBundle/Routing/MauticLoader.php which
// loads all of the Mautic bundles' routing.php files
$collection = new RouteCollection();
// loads api_platform
$apiCollection = $loader->import('.', 'api_platform');
$apiCollection->addPrefix('/api/v2/');
$collection->addCollection($apiCollection);
// loads Mautic's custom routing in src/Mautic/BaseBundle/Routing/MauticLoader.php which
// loads all of the Mautic bundles' routing.php files. It must be the LAST one in the
// collection
$collection->addCollection($loader->import('.', 'mautic'));
return $collection;

View File

@@ -0,0 +1,20 @@
<?php
use Symfony\Component\Routing\RouteCollection;
$collection = new RouteCollection();
// wdt
$wdt = $loader->import('@WebProfilerBundle/Resources/config/routing/wdt.xml');
$wdt->addPrefix('/_wdt');
$collection->addCollection($wdt);
// profiler
$profiler = $loader->import('@WebProfilerBundle/Resources/config/routing/profiler.xml');
$profiler->addPrefix('/_profiler');
$collection->addCollection($profiler);
// main
$collection->addCollection($loader->import(__DIR__.'/routing.php'));
return $collection;

View File

@@ -0,0 +1,203 @@
<?php
use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter;
$firewalls = [
'install' => [
'pattern' => '^/installer',
'lazy' => true,
'context' => 'mautic',
'security' => false,
],
'dev' => [
'pattern' => '^/(_(profiler|wdt)|css|images|js)/',
'security' => true,
'lazy' => true,
],
'login' => [
'pattern' => '^/s/login$',
'lazy' => true,
'context' => 'mautic',
],
'sso_login' => [
'pattern' => '^/s/sso_login',
'lazy' => true,
'mautic_plugin_auth' => true,
'context' => 'mautic',
],
'saml_login' => [
'pattern' => '^/s/saml/login$',
'lazy' => true,
'context' => 'mautic',
],
'saml_discovery' => [
'pattern' => '^/saml/discovery$',
'lazy' => true,
'context' => 'mautic',
],
'oauth2_token' => [
'pattern' => '^/oauth/v2/token',
'security' => false,
],
'oauth2_area' => [
'pattern' => '^/oauth/v2/authorize',
'form_login' => [
'provider' => 'user_provider',
'check_path' => '/oauth/v2/authorize_login_check',
'login_path' => '/oauth/v2/authorize_login',
],
'lazy' => true,
],
'v2api' => [
'pattern' => '^/api/v2',
'fos_oauth' => true,
'mautic_plugin_auth' => true,
'http_basic' => true,
'context' => 'mautic',
'provider' => 'user_provider',
'entry_point' => 'fos_oauth_server.security.entry_point',
],
'api' => [
'pattern' => '^/api/',
'fos_oauth' => true,
'mautic_plugin_auth' => true,
'stateless' => true,
'http_basic' => true,
'entry_point' => 'fos_oauth_server.security.entry_point',
],
'main' => [
'pattern' => '^/(s/|elfinder|efconnect)',
'light_saml_sp' => [
'provider' => 'user_provider',
'success_handler' => 'mautic.security.authentication_handler',
'failure_handler' => 'mautic.security.authentication_handler',
'user_creator' => 'mautic.security.saml.user_creator',
'username_mapper' => 'mautic.security.saml.username_mapper',
// If saml is disabled, these still must contain a proper saml login URLs.
// Otherwise, this prevents handling of the
// \LightSaml\SpBundle\Security\Http\Authenticator\SamlServiceProviderAuthenticator::supports
'login_path' => '%env(MAUTIC_SAML_LOGIN_PATH)%', // '/s/saml/login',
'check_path' => '%env(MAUTIC_SAML_LOGIN_CHECK_PATH)%', // '/s/saml/login_check',
],
'form_login' => [
'enable_csrf' => true,
'success_handler' => 'mautic.security.authentication_handler',
'failure_handler' => 'mautic.security.authentication_handler',
'login_path' => '/s/login',
'check_path' => '/s/login_check',
],
'logout' => [
'path' => '/s/logout',
'target' => '/s/login',
],
'remember_me' => [
'secret' => '%mautic.rememberme_key%',
'lifetime' => '%mautic.rememberme_lifetime%',
'path' => '%mautic.rememberme_path%',
'domain' => '%mautic.rememberme_domain%',
'samesite' => 'lax',
],
'entry_point' => Mautic\UserBundle\Security\EntryPoint\MainEntryPoint::class,
'mautic_sso' => [], // options are copied from `form_login` in \Mautic\UserBundle\DependencyInjection\Firewall\Factory\MauticSsoFactory
'fos_oauth' => true,
'context' => 'mautic',
],
'public' => [
'pattern' => '^/',
'lazy' => true,
'context' => 'mautic',
],
];
if (!$container->getParameter('mautic.famework.csrf_protection')) {
unset($firewalls['main']['simple_form']['csrf_token_generator']);
}
$container->loadFromExtension(
'security',
[
'providers' => [
'user_provider' => [
'id' => 'mautic.user.provider',
],
],
'password_hashers' => [
Symfony\Component\Security\Core\User\UserInterface::class => [
'algorithm' => 'bcrypt',
'iterations' => 12,
],
Mautic\UserBundle\Entity\User::class => [
'algorithm' => 'bcrypt',
'iterations' => 12,
],
],
'role_hierarchy' => [
'ROLE_ADMIN' => 'ROLE_USER',
],
'firewalls' => $firewalls,
'access_control' => [
// First there should be URIs for login or definitely public ones.
['path' => '^/installer', 'roles' => AuthenticatedVoter::PUBLIC_ACCESS],
['path' => '^/(_(profiler|wdt)|css|images|js)/', 'roles' => AuthenticatedVoter::PUBLIC_ACCESS],
['path' => '^/s/login$', 'roles' => AuthenticatedVoter::PUBLIC_ACCESS],
['path' => '^/s/sso_login', 'roles' => AuthenticatedVoter::PUBLIC_ACCESS],
['path' => '^/s/saml/login$', 'roles' => AuthenticatedVoter::PUBLIC_ACCESS],
['path' => '^/saml/discovery$', 'roles' => AuthenticatedVoter::PUBLIC_ACCESS],
['path' => '^/oauth/v2/authorize', 'roles' => AuthenticatedVoter::PUBLIC_ACCESS],
// Second should be URIs that are defined as non-public.
['path' => '^/api', 'roles' => AuthenticatedVoter::IS_AUTHENTICATED_FULLY],
['path' => '^/(s/|elfinder|efconnect)', 'roles' => AuthenticatedVoter::IS_AUTHENTICATED],
// Last the URIs that are none of the above.
['path' => '^/', 'roles' => AuthenticatedVoter::PUBLIC_ACCESS],
],
]
);
$container->setParameter('mautic.saml_idp_entity_id', '%env(MAUTIC_SAML_ENTITY_ID)%');
$container->setParameter('mautic.saml_enabled', '%env(bool:MAUTIC_SAML_ENABLED)%');
$container->loadFromExtension(
'light_saml_symfony_bridge',
[
'own' => [
'entity_descriptor_provider' => [
'id' => 'mautic.security.saml.entity_descriptor_provider',
],
'entity_id' => '%mautic.saml_idp_entity_id%',
],
'store' => [
'id_state' => 'mautic.security.saml.id_store',
'request' => Mautic\UserBundle\Security\SAML\Store\Request\RequestStateStore::class,
],
]
);
$loader->import('security_api.php');
// List config keys we do not want the user to change via the config UI
$restrictedConfigFields = [
'db_driver',
'db_host',
'db_table_prefix',
'db_name',
'db_user',
'db_password',
'db_path',
'db_port',
'secret_key',
];
// List config keys that are dev mode only
if ('prod' == $container->getParameter('kernel.environment')) {
$restrictedConfigFields = array_merge($restrictedConfigFields, ['transifex_username', 'transifex_password']);
}
$container->setParameter('mautic.security.restrictedConfigFields', $restrictedConfigFields);
$container->setParameter('mautic.security.restrictedConfigFields.displayMode', Mautic\ConfigBundle\Form\Helper\RestrictionHelper::MODE_REMOVE);
/*
* Optional security parameters
* mautic.security.disableUpdates = disables remote checks for updates
* mautic.security.restrictedConfigFields.displayMode = accepts either remove or mask; mask will disable the input with a "Set by system" message
*/
$container->setParameter('mautic.security.disableUpdates', false);

View File

@@ -0,0 +1,17 @@
<?php
$container->loadFromExtension('fos_oauth_server', [
'db_driver' => 'orm',
'client_class' => 'Mautic\ApiBundle\Entity\oAuth2\Client',
'access_token_class' => 'Mautic\ApiBundle\Entity\oAuth2\AccessToken',
'refresh_token_class' => 'Mautic\ApiBundle\Entity\oAuth2\RefreshToken',
'auth_code_class' => 'Mautic\ApiBundle\Entity\oAuth2\AuthCode',
'service' => [
'user_provider' => 'mautic.user.provider',
'options' => [
// 'supported_scopes' => 'user'
'access_token_lifetime' => '%env(int:MAUTIC_API_OAUTH2_ACCESS_TOKEN_LIFETIME)%',
'refresh_token_lifetime' => '%env(int:MAUTIC_API_OAUTH2_REFRESH_TOKEN_LIFETIME)%',
],
],
]);

View File

@@ -0,0 +1,27 @@
<?php
$loader->import('security.php');
// Support HTTP basic auth for test logins
$container->loadFromExtension('security',
[
'firewalls' => [
'main' => [
// Support HTTP basic auth for test logins
'http_basic' => true,
],
],
'password_hashers' => [
Symfony\Component\Security\Core\User\UserInterface::class => [
'algorithm' => 'md5',
'encode_as_base64' => false,
'iterations' => 0,
],
Mautic\UserBundle\Entity\User::class => [
'algorithm' => 'md5',
'encode_as_base64' => false,
'iterations' => 0,
],
],
]
);

View File

@@ -0,0 +1,32 @@
<?php
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
use Mautic\CoreBundle\DependencyInjection\MauticCoreExtension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
// This is loaded by \Mautic\CoreBundle\DependencyInjection\MauticCoreExtension to auto-wire services
// if the bundle do not cover it itself by their own *Extension and services.php which is prefered.
return function (ContainerConfigurator $configurator, ContainerBuilder $container) {
$services = $configurator->services()
->defaults()
->autowire()
->autoconfigure()
->public();
$bundles = array_merge($container->getParameter('mautic.bundles'), $container->getParameter('mautic.plugin.bundles'));
// Autoconfigure services for bundles that do not have its own Config/services.php
foreach ($bundles as $bundle) {
if (file_exists($bundle['directory'].'/Config/services.php')) {
continue;
}
$services->load($bundle['namespace'].'\\', $bundle['directory'])
->exclude($bundle['directory'].'/{'.implode(',', MauticCoreExtension::DEFAULT_EXCLUDES).'}');
if (is_dir($bundle['directory'].'/Entity')) {
$services->load($bundle['namespace'].'\\Entity\\', $bundle['directory'].'/Entity/*Repository.php');
}
}
};