Skip to content

Commit

Permalink
Reduce services.php by using attributes, and better structured config
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Metzner <[email protected]>
  • Loading branch information
dmetzner committed Sep 15, 2024
1 parent c7b6b94 commit 1621e11
Show file tree
Hide file tree
Showing 29 changed files with 168 additions and 169 deletions.
10 changes: 0 additions & 10 deletions config/features.php

This file was deleted.

11 changes: 11 additions & 0 deletions config/packages/bugsnag.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->extension('bugsnag', [
'api_key' => '%env(BUGSNAG_API_KEY)%',
]);
};
2 changes: 0 additions & 2 deletions config/packages/bugsnag.yaml

This file was deleted.

20 changes: 20 additions & 0 deletions config/packages/feature_flags.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(
'feature_flags',
[
'Test-Flag' => false,
'Sidebar-Studio-Link-Feature' => false,
'GET_projects_elastica' => false,
'remix-graph' => false, // performance issues
'sign-apk' => false, // not allowed by Google
'force-account-verification' => false,
]
);
};
4 changes: 2 additions & 2 deletions config/packages/fos_elastica.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
'url' => '%env(ELASTICSEARCH_URL)%',
],
[
'host' => '%es_host%',
'host' => '%env(ES_HOST)%',
],
[
'port' => '%es_port%',
'port' => '%env(ES_PORT)%',
],
],
],
Expand Down
142 changes: 20 additions & 122 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
use App\Admin\UserCommunication\Survey\AllSurveysAdmin;
use App\Admin\Users\ReportedUsers\ReportedUsersAdmin;
use App\Admin\Users\ReportedUsers\ReportedUsersController;
use App\Admin\Users\SecurityRolesBuilder;
use App\Admin\Users\UserAdmin;
use App\Admin\Users\UserDataReport\UserDataReportAdmin;
use App\Admin\Users\UserDataReport\UserDataReportController;
Expand All @@ -60,7 +59,6 @@
use App\Api\NotificationsApi;
use App\Api\ProjectsApi;
use App\Api\SearchApi;
use App\Api\Services\Authentication\JWTTokenRefreshService;
use App\Api\Services\OverwriteController;
use App\Api\StudioApi;
use App\Api\UserApi;
Expand All @@ -86,35 +84,14 @@
use App\DB\Entity\User\Comment\UserComment;
use App\DB\Entity\User\Notifications\BroadcastNotification;
use App\DB\Entity\User\User;
use App\Project\Apk\JenkinsDispatcher;
use App\Project\CatrobatFile\CatrobatFileExtractor;
use App\Project\EventListener\ExampleProjectImageListener;
use App\Project\EventListener\FeaturedProjectImageListener;
use App\Project\EventListener\ProjectPostUpdateNotifier;
use App\Project\Scratch\AsyncHttpClient;
use App\Security\Authentication\CookieService;
use App\Security\Authentication\JwtRefresh\RefreshTokenService;
use App\Security\OAuth\HwiOauthAccountConnector;
use App\Security\OAuth\HwiOauthUserProvider;
use App\System\Log\LoggerProcessor;
use App\Translation\GoogleTranslateApi;
use App\Translation\ItranslateApi;
use App\Translation\TranslationDelegate;
use App\User\EventListener\UserPostPersistNotifier;
use App\User\EventListener\UserPostUpdateNotifier;
use App\User\UserManager;
use App\User\UserProvider;
use Google\Cloud\Translate\V2\TranslateClient;
use Monolog\Formatter\LineFormatter;
use OpenAPI\Server\Service\SerializerInterface;
use Ramsey\Uuid\Doctrine\UuidGenerator;
use Sonata\AdminBundle\Security\Acl\Permission\AdminPermissionMap;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\Dotenv\Command\DotenvDumpCommand;
use Symfony\Component\Security\Core\User\UserProviderInterface;

use function Symfony\Component\DependencyInjection\Loader\Configurator\service;

return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();

Expand Down Expand Up @@ -154,66 +131,34 @@
$parameters->set('catrobat.translations.project_cache_threshold', 15);
$parameters->set('catrobat.upload.temp.dir', '%catrobat.pubdir%resources/tmp/uploads/');
$parameters->set('catrobat.upload.temp.path', 'resources/tmp/uploads/');
$parameters->set('es_host', '%env(ES_HOST)%');
$parameters->set('es_port', '%env(ES_PORT)%');
$parameters->set('dkim.private.key', '%kernel.project_dir%/.dkim/private.key');
$parameters->set('.container.dumper.inline_class_loader', true);
$parameters->set('features', '%kernel.project_dir%/config/features.php');
$parameters->set('reset_password.throttle_limit', 86400);

$services = $containerConfigurator->services();

$services->set('security.acl.permission.map', AdminPermissionMap::class);

$services->defaults()
->autowire()
->autoconfigure()
->bind('$program_finder', service('fos_elastica.finder.app_program'))
->bind('$user_finder', service('fos_elastica.finder.app_user'))
->bind('$refresh_token_ttl', '%lexik_jwt_authentication.token_ttl%')
->bind('$dkim_private_key_path', '%dkim.private.key%')
->autowire() // Automatically inject dependencies
->autoconfigure() // Automatically configure services with tags (e.g., listeners)

// Load all classes in the App namespace as services, making them available for DI
->load('App\\', __DIR__.'/../src/*')
// ->exclude([]) entity, system testing, ..?

// Exclude files and directories not meant for DI to improve performance and avoid misconfigurations
->exclude([
__DIR__.'/../src/Kernel.php', // Exclude Kernel, as it's not a service
__DIR__.'/../src/System/Testing', // Exclude testing classes
__DIR__.'/../src/DB/Entity', // Exclude Doctrine entities from DI container
])
;

// Register additional vendor classes as services
$services->set(UuidGenerator::class);
$services->alias(Sonata\AdminBundle\SonataConfiguration::class, 'sonata.admin.configuration');
$services->alias(UserProviderInterface::class, UserProvider::class);
$services->set('security.acl.permission.map', AdminPermissionMap::class);

$services->set(SecurityRolesBuilder::class)
->args([service('security.authorization_checker'), service('sonata.admin.configuration'), service('translator')])
;

$services->set(MaintenanceController::class)
->arg('$file_storage_dir', '%catrobat.file.storage.dir%')
->arg('$apk_dir', '%catrobat.apk.dir%')
->arg('$log_dir', '%catrobat.logs.dir%')
;

$services->set(JWTTokenRefreshService::class)
->args([service('gesdinet.jwtrefreshtoken')])
;

$services->set(JenkinsDispatcher::class)->args(['%jenkins%']);
$services->set(CookieService::class)->args(['%env(JWT_TTL)%', '%env(REFRESH_TOKEN_TTL)%']);
$services->set(RefreshTokenService::class)->args(['%env(REFRESH_TOKEN_TTL)%']);
$services->set(AsyncHttpClient::class)->args([['timeout' => 8.0], ['max_number_of_total_requests' => 12], ['max_number_of_concurrent_requests' => 4]]);
$services->set(CatrobatFileExtractor::class)->args(['%catrobat.file.extract.dir%', '%catrobat.file.extract.path%']);
$services->set(ProjectPostUpdateNotifier::class)
->tag('doctrine.orm.entity_listener', ['event' => 'postUpdate', 'entity' => Program::class])
->tag('doctrine.orm.entity_listener', ['event' => 'postPersist', 'entity' => Program::class])
;

$services->set(UserPostPersistNotifier::class)
->tag('doctrine.orm.entity_listener', ['event' => 'postPersist', 'entity' => User::class])
;

$services->set(UserPostUpdateNotifier::class)
->tag('doctrine.orm.entity_listener', ['event' => 'postUpdate', 'entity' => User::class])
;

// Custom formatting for our logs
$logFormat = "[%%datetime%%] %%channel%%.%%level_name%%: %%message%% %%context%% %%extra%%\n[Client IP: %%extra.client_ip%%, User Agent: %%extra.user_agent%%, Session User: %%extra.session_user%%]";

$services->set('monolog.formatter.catrobat_custom_formatter', LineFormatter::class)
->args([$logFormat, null, true, false])
->call('includeStacktraces', [true])
Expand All @@ -222,19 +167,10 @@
->call('setMaxLevelNameLength', [5])
;

$services->set(LoggerProcessor::class)
->tag('monolog.processor')
;

$services->set(FeaturedProjectImageListener::class)
->tag('doctrine.orm.entity_listener')
;

$services->set(ExampleProjectImageListener::class)
->tag('doctrine.orm.entity_listener')
;

// CAPI: Api service tagging - Custom Tags not yet supported by attributes
// -------------------------------------------------------------------------------------------------------------------
// CAPI: Api service tagging
// - custom tags not yet supported by attributes
//
$services->set(MediaLibraryApi::class)->tag('open_api_server.api', ['api' => 'mediaLibrary']);
$services->set(ProjectsApi::class)->tag('open_api_server.api', ['api' => 'projects']);
$services->set(UserApi::class)->tag('open_api_server.api', ['api' => 'user']);
Expand All @@ -245,46 +181,8 @@
$services->set(StudioApi::class)->tag('open_api_server.api', ['api' => 'studio']);
$services->set(OverwriteController::class);
$services->alias(SerializerInterface::class, 'open_api_server.service.serializer');
// end CAPI

$services->set(HwiOauthUserProvider::class)
->args([service(UserManager::class), ['google' => 'google_id', 'facebook' => 'facebook_id', 'apple' => 'apple_id']])
;

$services->set(HwiOauthAccountConnector::class)
->args([service(UserManager::class), ['google' => 'google_id', 'facebook' => 'facebook_id', 'apple' => 'apple_id']])
;

$services->set(ItranslateApi::class)
->lazy()
->args([service('eight_points_guzzle.client.itranslate')])
;

$services->set(GoogleTranslateApi::class)
->lazy()
->arg('$client', service(TranslateClient::class))
->arg('$short_text_length', 20)
;

$services->set(TranslateClient::class)
->lazy()
;

$services->set(TranslationDelegate::class)
->lazy()
->arg('$apis', [
service(ItranslateApi::class),
service(GoogleTranslateApi::class),
])
;

$services->set(DotenvDumpCommand::class)
->tag('console.command')
->arg('$projectDir', '%kernel.project_dir%/.env')
->arg('$defaultEnv', '%kernel.environment%')
;

// --------------------------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------------
// Sonata admin service definitions:
// - used by config/packages/sonata_admin.php to build the navigation tree
// - each services defines a page in the admin interface - go to /admin
Expand Down Expand Up @@ -614,7 +512,7 @@
])
;

// --------------------------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------------
// Load additional services, or overwrite them for the test environment by defining them in services_test.php
//
if ('test' === $_SERVER['APP_ENV']) {
Expand Down
2 changes: 0 additions & 2 deletions config/services_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
declare(strict_types=1);

use App\Project\Apk\JenkinsDispatcher;
use App\Project\CatrobatFile\CatrobatFileExtractor;
use App\Security\TokenGenerator;
use App\System\Testing\DataFixtures\ProjectDataFixtures;
use App\System\Testing\DataFixtures\UserDataFixtures;
Expand Down Expand Up @@ -47,7 +46,6 @@
$services->set('token_generator.inner', TokenGenerator::class);
$services->set(TokenGenerator::class, ProxyTokenGenerator::class)->autowire(false)->args([service('token_generator.inner')]);
$services->set(JenkinsDispatcher::class, FakeJenkinsDispatcher::class)->args(['%jenkins%']);
$services->set(CatrobatFileExtractor::class)->args(['%catrobat.file.extract.dir%', '%catrobat.file.extract.path%']);
$services->set(TranslationDelegate::class, FakeTranslationDelegate::class);

// Load additional test-only services:
Expand Down
7 changes: 4 additions & 3 deletions src/Admin/System/FeatureFlag/FeatureFlagManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use App\DB\Entity\FeatureFlag;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\RequestStack;

class FeatureFlagManager
Expand All @@ -16,10 +16,11 @@ class FeatureFlagManager
public function __construct(
protected RequestStack $requestStack,
protected EntityManagerInterface $entityManager,
protected ParameterBagInterface $parameter_bag,
#[Autowire('%feature_flags%')]
protected array $feature_flags,
) {
if ($this->entityManager->getConnection()->isConnected()) {
$this->defaultFlags = include $parameter_bag->get('features');
$this->defaultFlags = $this->feature_flags;

$flagMap = [];
foreach ($this->defaultFlags as $name => $value) {
Expand Down
4 changes: 4 additions & 0 deletions src/Admin/System/Maintenance/MaintenanceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
Expand All @@ -22,8 +23,11 @@ class MaintenanceController extends CRUDController
{
public function __construct(
protected KernelInterface $kernel,
#[Autowire('%catrobat.file.storage.dir%')]
private readonly string $file_storage_dir,
#[Autowire('%catrobat.apk.dir%')]
private readonly string $apk_dir,
#[Autowire('%catrobat.logs.dir%')]
private readonly string $log_dir,
) {
}
Expand Down
4 changes: 4 additions & 0 deletions src/Admin/Users/SecurityRolesBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace App\Admin\Users;

use Sonata\AdminBundle\SonataConfiguration;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

Expand All @@ -26,8 +27,11 @@
* @param array<string, array<string>> $rolesHierarchy
*/
public function __construct(
#[Autowire(service: 'security.authorization_checker')]
private AuthorizationCheckerInterface $authorizationChecker,
#[Autowire(service: 'sonata.admin.configuration')]
private SonataConfiguration $configuration,
#[Autowire(service: 'translator')]
private TranslatorInterface $translator,
private array $rolesHierarchy = [],
) {
Expand Down
7 changes: 5 additions & 2 deletions src/Api/Services/Authentication/JWTTokenRefreshService.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
namespace App\Api\Services\Authentication;

use Gesdinet\JWTRefreshTokenBundle\Service\RefreshToken;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

readonly class JWTTokenRefreshService
{
public function __construct(private RefreshToken $refreshToken)
{
public function __construct(
#[Autowire(service: 'gesdinet.jwtrefreshtoken')]
private RefreshToken $refreshToken,
) {
}

public function refresh(Request $request): Response
Expand Down
13 changes: 11 additions & 2 deletions src/Api/Services/AuthenticationManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,22 @@
use Gesdinet\JWTRefreshTokenBundle\Generator\RefreshTokenGeneratorInterface;
use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenManagerInterface;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;

class AuthenticationManager
{
public function __construct(private readonly TokenStorageInterface $token_storage, private readonly JWTTokenManagerInterface $jwt_manager, private readonly UserManager $user_manager, private readonly RefreshTokenGeneratorInterface $refresh_token_generator, private readonly RefreshTokenManagerInterface $refresh_manager, protected RequestHelper $request_helper, protected int $refresh_token_ttl)
{
public function __construct(
private readonly TokenStorageInterface $token_storage,
private readonly JWTTokenManagerInterface $jwt_manager,
private readonly UserManager $user_manager,
private readonly RefreshTokenGeneratorInterface $refresh_token_generator,
private readonly RefreshTokenManagerInterface $refresh_manager,
protected RequestHelper $request_helper,
#[Autowire('%lexik_jwt_authentication.token_ttl%')]
protected int $refresh_token_ttl,
) {
}

/**
Expand Down
Loading

0 comments on commit 1621e11

Please sign in to comment.