├── .codeclimate.yml ├── .dockerignore ├── .editorconfig ├── .env ├── .env.dev ├── .env.gh-actions ├── .env.test ├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ ├── main.yml │ ├── scorecard.yml │ └── vulnerability-scan.yml ├── .gitignore ├── .idea ├── .gitignore ├── codeStyleSettings.xml ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── dataSources.xml ├── encodings.xml ├── externalDependencies.xml ├── inspectionProfiles │ └── Project_Default.xml ├── jsonSchemas.xml ├── modules.xml ├── php.xml ├── remote-mappings.xml ├── runConfigurations │ ├── Local_XDebug.xml │ ├── PHPUnit___All_tests.xml │ ├── PHPUnit___E2E_tests.xml │ ├── PHPUnit___Functional_tests.xml │ ├── PHPUnit___Integration_tests.xml │ └── PHPUnit___Unit_tests.xml ├── scopes │ └── src.xml ├── sqldialects.xml ├── symfony-flex-backend.iml ├── symfony2.xml ├── vcs.xml └── webResources.xml ├── .phan └── config.php ├── .php-cs-fixer.dist.php ├── .phplint.yml ├── CHANGELOG.md ├── Dockerfile ├── Dockerfile_dev ├── LICENSE ├── Makefile ├── README.md ├── bin ├── console └── phpunit ├── changelog-linker.yaml ├── compose.yaml ├── composer.json ├── composer.lock ├── config ├── bundles.php ├── jwt │ ├── .gitignore │ └── .gitkeep ├── packages │ ├── cache.yaml │ ├── debug.yaml │ ├── doctrine.yaml │ ├── doctrine_extensions.yaml │ ├── doctrine_migrations.yaml │ ├── event_listeners.yaml │ ├── framework.yaml │ ├── lexik_jwt_authentication.yaml │ ├── monolog.yaml │ ├── nelmio_api_doc.yaml │ ├── nelmio_cors.yaml │ ├── ramsey_uuid_doctrine.yaml │ ├── routing.yaml │ ├── security.yaml │ ├── translation.yaml │ ├── twig.yaml │ ├── validator.yaml │ └── web_profiler.yaml ├── preload.php ├── routes.yaml ├── routes │ ├── framework.yaml │ ├── nelmio_api_doc.yaml │ ├── security.yaml │ └── web_profiler.yaml └── services.yaml ├── doc ├── COMMANDS.md ├── CONCEPTS_AND_FEATURES.md ├── CUSTOM_CONFIGURATION.md ├── DEVELOPMENT.md ├── INSTALLATION_WITHOUT_DOCKER.md ├── PHPSTORM.md ├── README.md ├── SPEED_UP_DOCKER_COMPOSE.md ├── TESTING.md ├── USAGE_CHECKLIST.md ├── XDEBUG.md └── images │ ├── phpstorm_01.png │ ├── phpstorm_02.png │ ├── phpstorm_03.png │ ├── phpstorm_04.png │ ├── xdebug_01.png │ ├── xdebug_02.png │ ├── xdebug_03.png │ ├── xdebug_04.png │ └── xdebug_05.png ├── docker-entrypoint-dev.sh ├── docker-entrypoint.sh ├── docker-sync.yml ├── docker ├── README.md ├── fish │ ├── completions │ │ ├── composer.fish │ │ └── sf_console.fish │ ├── config.fish │ └── functions │ │ └── console.fish ├── mariadb │ ├── Dockerfile │ └── mysql_custom.cnf ├── nginx │ ├── Dockerfile │ ├── Dockerfile_dev │ ├── nginx-dev.conf │ ├── nginx.conf │ ├── php-upstream.conf │ └── ssl │ │ ├── README.md │ │ ├── create-keys.sh │ │ ├── openssl.cnf │ │ ├── rootCA.key │ │ ├── rootCA.pem │ │ ├── tls.crt │ │ ├── tls.csr │ │ └── tls.key └── php │ ├── php-dev.ini │ ├── php.ini │ ├── www-dev.conf │ └── www.conf ├── ecs.php ├── infection.json.dist ├── markdown-lint.yml ├── migrations ├── .gitignore ├── Version20211118171749.php ├── Version20220312135411.php ├── Version20220324162224.php ├── Version20220812161020.php └── Version20230930102814.php ├── phpinsights.php ├── phpmd_ruleset.xml ├── phpstan.neon.dist ├── phpunit.fastest.xml ├── phpunit.xml.dist ├── psalm.xml ├── public ├── check.php ├── favicon.ico ├── index.php ├── robots.txt └── site.webmanifest ├── rector.php ├── scripts ├── README.md └── project-stats.sh ├── secrets ├── README.md ├── application.json └── application_test.json ├── sonar-project.properties ├── src ├── AutoMapper │ ├── ApiKey │ │ ├── AutoMapperConfiguration.php │ │ └── RequestMapper.php │ ├── RestAutoMapperConfiguration.php │ ├── RestRequestMapper.php │ ├── User │ │ ├── AutoMapperConfiguration.php │ │ └── RequestMapper.php │ └── UserGroup │ │ ├── AutoMapperConfiguration.php │ │ └── RequestMapper.php ├── Collection │ └── CollectionTrait.php ├── Command │ ├── ApiKey │ │ ├── ApiKeyHelper.php │ │ ├── ApiKeyManagementCommand.php │ │ ├── ChangeTokenCommand.php │ │ ├── CreateApiKeyCommand.php │ │ ├── EditApiKeyCommand.php │ │ ├── ListApiKeysCommand.php │ │ └── RemoveApiKeyCommand.php │ ├── HelperConfigure.php │ ├── Traits │ │ ├── ApiKeyUserManagementHelperTrait.php │ │ ├── ExecuteMultipleCommandTrait.php │ │ ├── GetApplicationTrait.php │ │ └── SymfonyStyleTrait.php │ ├── User │ │ ├── CreateRolesCommand.php │ │ ├── CreateUserCommand.php │ │ ├── CreateUserGroupCommand.php │ │ ├── EditUserCommand.php │ │ ├── EditUserGroupCommand.php │ │ ├── ListUserGroupsCommand.php │ │ ├── ListUsersCommand.php │ │ ├── ManagementCommand.php │ │ ├── RemoveUserCommand.php │ │ ├── RemoveUserGroupCommand.php │ │ └── UserHelper.php │ └── Utils │ │ ├── CheckDependencies.php │ │ └── CreateDateDimensionEntitiesCommand.php ├── Compiler │ └── StopwatchCompilerPass.php ├── Controller │ ├── HealthzController.php │ ├── IndexController.php │ ├── VersionController.php │ └── v1 │ │ ├── ApiKey │ │ └── ApiKeyController.php │ │ ├── Auth │ │ └── GetTokenController.php │ │ ├── Localization │ │ ├── LanguageController.php │ │ ├── LocaleController.php │ │ └── TimeZoneController.php │ │ ├── Profile │ │ ├── GroupsController.php │ │ ├── IndexController.php │ │ └── RolesController.php │ │ ├── Role │ │ ├── FindOneRoleController.php │ │ ├── InheritedRolesController.php │ │ └── RoleController.php │ │ ├── User │ │ ├── AttachUserGroupController.php │ │ ├── DeleteUserController.php │ │ ├── DetachUserGroupController.php │ │ ├── UserController.php │ │ ├── UserGroupsController.php │ │ └── UserRolesController.php │ │ └── UserGroup │ │ ├── AttachUserController.php │ │ ├── DetachUserController.php │ │ ├── UserGroupController.php │ │ └── UsersController.php ├── DTO │ ├── ApiKey │ │ ├── ApiKey.php │ │ ├── ApiKeyCreate.php │ │ ├── ApiKeyPatch.php │ │ └── ApiKeyUpdate.php │ ├── RestDto.php │ ├── RestDtoInterface.php │ ├── Traits │ │ └── PatchUserGroups.php │ ├── User │ │ ├── User.php │ │ ├── UserCreate.php │ │ ├── UserPatch.php │ │ └── UserUpdate.php │ └── UserGroup │ │ ├── UserGroup.php │ │ ├── UserGroupCreate.php │ │ ├── UserGroupPatch.php │ │ └── UserGroupUpdate.php ├── Decorator │ └── StopwatchDecorator.php ├── Doctrine │ └── DBAL │ │ └── Types │ │ ├── EnumLanguageType.php │ │ ├── EnumLocaleType.php │ │ ├── EnumLogLoginType.php │ │ ├── EnumType.php │ │ ├── Types.php │ │ └── UTCDateTimeType.php ├── Entity │ ├── .gitignore │ ├── ApiKey.php │ ├── DateDimension.php │ ├── Healthz.php │ ├── Interfaces │ │ ├── EntityInterface.php │ │ ├── UserGroupAwareInterface.php │ │ └── UserInterface.php │ ├── LogLogin.php │ ├── LogLoginFailure.php │ ├── LogRequest.php │ ├── Role.php │ ├── Traits │ │ ├── Blameable.php │ │ ├── LogEntityTrait.php │ │ ├── LogRequestProcessRequestTrait.php │ │ ├── Timestampable.php │ │ ├── UserRelations.php │ │ └── Uuid.php │ ├── User.php │ └── UserGroup.php ├── Enum │ ├── Interfaces │ │ ├── DatabaseEnumInterface.php │ │ └── StringEnumInterface.php │ ├── Language.php │ ├── Locale.php │ ├── LogLogin.php │ ├── Role.php │ └── Traits │ │ └── GetValues.php ├── EventListener │ └── UserEntityEventListener.php ├── EventSubscriber │ ├── AcceptLanguageSubscriber.php │ ├── AuthenticationFailureSubscriber.php │ ├── AuthenticationSuccessSubscriber.php │ ├── BodySubscriber.php │ ├── DoctrineExtensionSubscriber.php │ ├── ExceptionSubscriber.php │ ├── JWTCreatedSubscriber.php │ ├── JWTDecodedSubscriber.php │ ├── LockedUserSubscriber.php │ ├── RequestLogSubscriber.php │ └── ResponseSubscriber.php ├── Exception │ ├── ValidatorException.php │ ├── interfaces │ │ └── ClientErrorInterface.php │ └── models │ │ └── ValidatorError.php ├── Form │ ├── DataTransformer │ │ ├── RoleTransformer.php │ │ └── UserGroupTransformer.php │ └── Type │ │ ├── Console │ │ ├── ApiKeyType.php │ │ ├── UserGroupType.php │ │ └── UserType.php │ │ ├── FormTypeLabelInterface.php │ │ └── Traits │ │ ├── AddBasicFieldToForm.php │ │ └── UserGroupChoices.php ├── Helpers │ ├── LoggerAwareTrait.php │ └── StopwatchAwareTrait.php ├── Kernel.php ├── Repository │ ├── .gitignore │ ├── ApiKeyRepository.php │ ├── BaseRepository.php │ ├── DateDimensionRepository.php │ ├── HealthzRepository.php │ ├── Interfaces │ │ └── BaseRepositoryInterface.php │ ├── LogLoginFailureRepository.php │ ├── LogLoginRepository.php │ ├── LogRequestRepository.php │ ├── RoleRepository.php │ ├── Traits │ │ ├── RepositoryMethodsTrait.php │ │ └── RepositoryWrappersTrait.php │ ├── UserGroupRepository.php │ └── UserRepository.php ├── Resource │ ├── ApiKeyResource.php │ ├── DateDimensionResource.php │ ├── HealthzResource.php │ ├── LogLoginFailureResource.php │ ├── LogLoginResource.php │ ├── LogRequestResource.php │ ├── ResourceCollection.php │ ├── RoleResource.php │ ├── UserGroupResource.php │ └── UserResource.php ├── Rest │ ├── Controller.php │ ├── ControllerCollection.php │ ├── Interfaces │ │ ├── ControllerInterface.php │ │ ├── ResponseHandlerInterface.php │ │ ├── RestResourceInterface.php │ │ └── SearchTermInterface.php │ ├── RepositoryHelper.php │ ├── RequestHandler.php │ ├── ResponseHandler.php │ ├── RestResource.php │ ├── SearchTerm.php │ ├── Traits │ │ ├── Actions │ │ │ ├── Admin │ │ │ │ ├── CountAction.php │ │ │ │ ├── CreateAction.php │ │ │ │ ├── DeleteAction.php │ │ │ │ ├── FindAction.php │ │ │ │ ├── FindOneAction.php │ │ │ │ ├── IdsAction.php │ │ │ │ ├── PatchAction.php │ │ │ │ └── UpdateAction.php │ │ │ ├── Anon │ │ │ │ ├── CountAction.php │ │ │ │ ├── CreateAction.php │ │ │ │ ├── DeleteAction.php │ │ │ │ ├── FindAction.php │ │ │ │ ├── FindOneAction.php │ │ │ │ ├── IdsAction.php │ │ │ │ ├── PatchAction.php │ │ │ │ └── UpdateAction.php │ │ │ ├── Authenticated │ │ │ │ ├── CountAction.php │ │ │ │ ├── CreateAction.php │ │ │ │ ├── DeleteAction.php │ │ │ │ ├── FindAction.php │ │ │ │ ├── FindOneAction.php │ │ │ │ ├── IdsAction.php │ │ │ │ ├── PatchAction.php │ │ │ │ └── UpdateAction.php │ │ │ ├── Logged │ │ │ │ ├── CountAction.php │ │ │ │ ├── CreateAction.php │ │ │ │ ├── DeleteAction.php │ │ │ │ ├── FindAction.php │ │ │ │ ├── FindOneAction.php │ │ │ │ ├── IdsAction.php │ │ │ │ ├── PatchAction.php │ │ │ │ └── UpdateAction.php │ │ │ ├── RestActionBase.php │ │ │ ├── Root │ │ │ │ ├── CountAction.php │ │ │ │ ├── CreateAction.php │ │ │ │ ├── DeleteAction.php │ │ │ │ ├── FindAction.php │ │ │ │ ├── FindOneAction.php │ │ │ │ ├── IdsAction.php │ │ │ │ ├── PatchAction.php │ │ │ │ └── UpdateAction.php │ │ │ └── User │ │ │ │ ├── CountAction.php │ │ │ │ ├── CreateAction.php │ │ │ │ ├── DeleteAction.php │ │ │ │ ├── FindAction.php │ │ │ │ ├── FindOneAction.php │ │ │ │ ├── IdsAction.php │ │ │ │ ├── PatchAction.php │ │ │ │ └── UpdateAction.php │ │ ├── Methods │ │ │ ├── CountMethod.php │ │ │ ├── CreateMethod.php │ │ │ ├── DeleteMethod.php │ │ │ ├── FindMethod.php │ │ │ ├── FindOneMethod.php │ │ │ ├── IdsMethod.php │ │ │ ├── PatchMethod.php │ │ │ ├── RestMethodProcessCriteria.php │ │ │ └── UpdateMethod.php │ │ ├── RestMethodHelper.php │ │ ├── RestResourceBaseMethods.php │ │ ├── RestResourceCount.php │ │ ├── RestResourceCreate.php │ │ ├── RestResourceDelete.php │ │ ├── RestResourceFind.php │ │ ├── RestResourceFindOne.php │ │ ├── RestResourceFindOneBy.php │ │ ├── RestResourceIds.php │ │ ├── RestResourceLifeCycles.php │ │ ├── RestResourcePatch.php │ │ ├── RestResourceSave.php │ │ └── RestResourceUpdate.php │ └── UuidHelper.php ├── Security │ ├── ApiKeyUser.php │ ├── Authenticator │ │ └── ApiKeyAuthenticator.php │ ├── Handler │ │ └── TranslatedAuthenticationFailureHandler.php │ ├── Interfaces │ │ ├── ApiKeyUserInterface.php │ │ ├── ApiKeyUserProviderInterface.php │ │ └── RolesServiceInterface.php │ ├── Provider │ │ ├── ApiKeyUserProvider.php │ │ └── SecurityUserFactory.php │ ├── RolesService.php │ ├── SecurityUser.php │ ├── UserTypeIdentification.php │ └── Voter │ │ └── IsUserHimselfVoter.php ├── Service │ ├── Localization.php │ └── Version.php ├── Utils │ ├── HealthzService.php │ ├── Interfaces │ │ ├── LoginLoggerInterface.php │ │ └── RequestLoggerInterface.php │ ├── JSON.php │ ├── LoginLogger.php │ └── RequestLogger.php ├── Validator │ └── Constraints │ │ ├── EntityReferenceExists.php │ │ ├── EntityReferenceExistsValidator.php │ │ ├── Language.php │ │ ├── LanguageValidator.php │ │ ├── Locale.php │ │ ├── LocaleValidator.php │ │ ├── Timezone.php │ │ ├── TimezoneValidator.php │ │ ├── UniqueEmail.php │ │ ├── UniqueEmailValidator.php │ │ ├── UniqueUsername.php │ │ └── UniqueUsernameValidator.php ├── ValueResolver │ ├── EntityValueResolver.php │ ├── LoggedInUserValueResolver.php │ └── RestDtoValueResolver.php └── favicon.ico ├── symfony.lock ├── templates ├── .gitignore ├── .gitkeep ├── Doctrine │ └── migration.tpl └── Swagger │ ├── parameter_criteria.twig │ ├── parameter_limit.twig │ ├── parameter_offset.twig │ ├── parameter_order.twig │ ├── parameter_populate.twig │ └── parameter_search.twig ├── tests ├── DataFixtures │ ├── AppFixtures.php │ └── ORM │ │ ├── LoadApiKeyData.php │ │ ├── LoadRoleData.php │ │ ├── LoadUserData.php │ │ └── LoadUserGroupData.php ├── E2E │ ├── Controller │ │ ├── HealthzControllerTest.php │ │ ├── IndexControllerTest.php │ │ ├── VersionControllerTest.php │ │ └── v1 │ │ │ ├── ApiKey │ │ │ └── ApiKeyControllerTest.php │ │ │ ├── Auth │ │ │ ├── GetTokenControllerTest.php │ │ │ └── LoginFailureTest.php │ │ │ ├── Localization │ │ │ ├── LanguageControllerTest.php │ │ │ ├── LocaleControllerTest.php │ │ │ └── TimeZoneControllerTest.php │ │ │ ├── Profile │ │ │ ├── GroupsControllerTest.php │ │ │ ├── IndexControllerTest.php │ │ │ └── RolesControllerTest.php │ │ │ ├── Role │ │ │ ├── FindOneRoleControllerTest.php │ │ │ ├── InheritedRolesControllerTest.php │ │ │ └── RoleControllerTest.php │ │ │ ├── User │ │ │ ├── AttachUserGroupControllerTest.php │ │ │ ├── DeleteUserControllerTest.php │ │ │ ├── DetachUserGroupControllerTest.php │ │ │ ├── UserControllerTest.php │ │ │ ├── UserCreateInvalidUserTest.php │ │ │ ├── UserGroupsControllerTest.php │ │ │ ├── UserManagementFlowTest.php │ │ │ ├── UserRolesControllerTest.php │ │ │ └── UserUpdateInvalidUserTest.php │ │ │ └── UserGroup │ │ │ ├── AttachUserControllerTest.php │ │ │ ├── DetachUserControllerTest.php │ │ │ ├── UserGroupControllerTest.php │ │ │ └── UsersControllerTest.php │ ├── DocumentationTest.php │ ├── Rest │ │ ├── ResourceLifeCycleTest.php │ │ ├── Traits │ │ │ └── Actions │ │ │ │ ├── AdminActionsTest.php │ │ │ │ ├── AnonActionsTest.php │ │ │ │ ├── AuthenticatedActionsTest.php │ │ │ │ ├── LoggedActionsTest.php │ │ │ │ ├── RootActionsTest.php │ │ │ │ ├── UserActionsTest.php │ │ │ │ └── src │ │ │ │ ├── AdminActionsController.php │ │ │ │ ├── AnonActionsController.php │ │ │ │ ├── AuthenticatedActionsController.php │ │ │ │ ├── LoggedActionsController.php │ │ │ │ ├── RootActionsController.php │ │ │ │ └── UserActionsController.php │ │ └── src │ │ │ ├── Controller │ │ │ └── ControllerForLifeCycleTests.php │ │ │ └── Resource │ │ │ └── ResourceForLifeCycleTests.php │ └── TestCase │ │ ├── Auth.php │ │ ├── RestTraitTestCase.php │ │ └── WebTestCase.php ├── Functional │ ├── Repository │ │ ├── HealthzRepositoryTest.php │ │ ├── LogLoginFailureRepositoryTest.php │ │ ├── LogRequestRepositoryTest.php │ │ ├── RoleRepositoryTest.php │ │ └── UserRepositoryTest.php │ ├── Security │ │ └── Provider │ │ │ ├── ApiKeyUserProviderTest.php │ │ │ └── SecurityUserFactoryTest.php │ └── ValueResolver │ │ └── LoggedInUserValueResolverTest.php ├── Integration │ ├── AutoMapper │ │ ├── ApiKey │ │ │ ├── AutoMapperConfigurationTest.php │ │ │ └── RequestMapperTest.php │ │ ├── GenericRestRequestMapperTest.php │ │ ├── User │ │ │ ├── AutoMapperConfigurationTest.php │ │ │ └── RequestMapperTest.php │ │ ├── UserGroup │ │ │ ├── AutoMapperConfigurationTest.php │ │ │ └── RequestMapperTest.php │ │ └── src │ │ │ ├── TestRestRequestMapper.php │ │ │ ├── TestRestRequestMapperDto.php │ │ │ └── TestRestRequestMapperWithoutProperties.php │ ├── Compiler │ │ └── StopwatchCompilerPassTest.php │ ├── Controller │ │ ├── HealthzControllerTest.php │ │ ├── IndexControllerTest.php │ │ ├── VersionControllerTest.php │ │ └── v1 │ │ │ ├── ApiKey │ │ │ └── ApiKeyControllerTest.php │ │ │ ├── Auth │ │ │ └── GetTokenControllerTest.php │ │ │ ├── Localization │ │ │ ├── LanguageControllerTest.php │ │ │ ├── LocaleControllerTest.php │ │ │ └── TimeZoneControllerTest.php │ │ │ ├── Profile │ │ │ ├── GroupsControllerTest.php │ │ │ ├── IndexControllerTest.php │ │ │ └── RolesControllerTest.php │ │ │ ├── Role │ │ │ ├── FindOneRoleControllerTest.php │ │ │ ├── InheritedRolesControllerTest.php │ │ │ └── RoleControllerTest.php │ │ │ ├── User │ │ │ ├── AttachUserGroupControllerTest.php │ │ │ ├── DeleteUserControllerTest.php │ │ │ ├── DetachUserGroupControllerTest.php │ │ │ ├── UserControllerTest.php │ │ │ ├── UserGroupsControllerTest.php │ │ │ └── UserRolesControllerTest.php │ │ │ └── UserGroup │ │ │ ├── AttachUserControllerTest.php │ │ │ ├── DetachUserControllerTest.php │ │ │ ├── UserGroupControllerTest.php │ │ │ └── UsersControllerTest.php │ ├── DTO │ │ ├── ApiKey │ │ │ ├── ApiKeyCreateTest.php │ │ │ ├── ApiKeyPatchTest.php │ │ │ ├── ApiKeyTest.php │ │ │ └── ApiKeyUpdateTest.php │ │ ├── GenericDtoTest.php │ │ ├── User │ │ │ ├── UserCreateTest.php │ │ │ ├── UserPatchTest.php │ │ │ ├── UserTest.php │ │ │ └── UserUpdateTest.php │ │ ├── UserGroup │ │ │ ├── UserGroupCreateTest.php │ │ │ ├── UserGroupPatchTest.php │ │ │ ├── UserGroupTest.php │ │ │ └── UserGroupUpdateTest.php │ │ └── src │ │ │ └── DummyDto.php │ ├── Decorator │ │ └── StopwatchDecoratorTest.php │ ├── Doctrine │ │ └── DBAL │ │ │ └── Types │ │ │ ├── EnumLanguageTypeTest.php │ │ │ ├── EnumLocaleTypeTest.php │ │ │ ├── EnumLogLoginTypeTest.php │ │ │ └── UTCDateTimeTypeTest.php │ ├── Entity │ │ ├── ApiKeyTest.php │ │ ├── DateDimensionTest.php │ │ ├── HealthzTest.php │ │ ├── LogLoginFailureTest.php │ │ ├── LogLoginTest.php │ │ ├── LogRequestTest.php │ │ ├── RoleTest.php │ │ ├── UserGroupTest.php │ │ └── UserTest.php │ ├── EventListener │ │ └── UserEntityEventListenerTest.php │ ├── EventSubscriber │ │ ├── AcceptLanguageSubscriberTest.php │ │ ├── AuthenticationFailureSubscriberTest.php │ │ ├── AuthenticationSuccessSubscriberTest.php │ │ ├── BodySubscriberTest.php │ │ ├── DoctrineExtensionSubscriberTest.php │ │ ├── ExceptionSubscriberTest.php │ │ ├── JWTCreatedSubscriberTest.php │ │ ├── JWTDecodedSubscriberTest.php │ │ ├── LockedUserSubscriberTest.php │ │ ├── RequestLogSubscriberTest.php │ │ └── ResponseSubscriberTest.php │ ├── Form │ │ ├── DataTransformer │ │ │ ├── RoleTransformerTest.php │ │ │ └── UserGroupTransformerTest.php │ │ └── Type │ │ │ └── Console │ │ │ ├── ApiKeyTypeTest.php │ │ │ ├── UserGroupTypeTest.php │ │ │ └── UserTypeTest.php │ ├── Helpers │ │ ├── LoggerAwareTraitTest.php │ │ ├── StopwatchAwareTraitTest.php │ │ └── src │ │ │ ├── LoggerAwareService.php │ │ │ └── StopwatchAwareService.php │ ├── Repository │ │ ├── ApiKeyRepositoryTest.php │ │ ├── DateDimensionRepositoryTest.php │ │ ├── GenericRepositoryTest.php │ │ ├── HealthzRepositoryTest.php │ │ ├── LogLoginFailureRepositoryTest.php │ │ ├── LogLoginRepositoryTest.php │ │ ├── LogRequestRepositoryTest.php │ │ ├── RoleRepositoryTest.php │ │ ├── UserGroupRepositoryTest.php │ │ └── UserRepositoryTest.php │ ├── Resource │ │ ├── ApiKeyResourceTest.php │ │ ├── DateDimensionResourceTest.php │ │ ├── GenericResourceTest.php │ │ ├── HealthzResourceTest.php │ │ ├── LogLoginFailureResourceTest.php │ │ ├── LogLoginResourceTest.php │ │ ├── LogRequestResourceTest.php │ │ ├── ResourceCollectionTest.php │ │ ├── RoleResourceTest.php │ │ ├── UserGroupResourceTest.php │ │ └── UserResourceTest.php │ ├── Rest │ │ ├── ControllerCollectionTest.php │ │ ├── ControllerTest.php │ │ ├── RepositoryHelperTest.php │ │ ├── ResponseHandlerTest.php │ │ └── Traits │ │ │ └── Methods │ │ │ ├── CountMethodTest.php │ │ │ ├── CreateMethodTest.php │ │ │ ├── DeleteMethodTest.php │ │ │ ├── FindMethodTest.php │ │ │ ├── FindOneMethodTest.php │ │ │ ├── IdsMethodTest.php │ │ │ ├── PatchMethodTest.php │ │ │ ├── UpdateMethodTest.php │ │ │ └── src │ │ │ ├── CountMethodInvalidTestClass.php │ │ │ ├── CountMethodTestClass.php │ │ │ ├── CreateMethodInvalidTestClass.php │ │ │ ├── CreateMethodTestClass.php │ │ │ ├── DeleteMethodInvalidTestClass.php │ │ │ ├── DeleteMethodTestClass.php │ │ │ ├── FindMethodInvalidTestClass.php │ │ │ ├── FindMethodTestClass.php │ │ │ ├── FindOneMethodInvalidTestClass.php │ │ │ ├── FindOneMethodTestClass.php │ │ │ ├── IdsMethodInvalidTestClass.php │ │ │ ├── IdsMethodTestClass.php │ │ │ ├── PatchMethodInvalidTestClass.php │ │ │ ├── PatchMethodTestClass.php │ │ │ ├── UpdateMethodInvalidTestClass.php │ │ │ └── UpdateMethodTestClass.php │ ├── SchemaTest.php │ ├── Security │ │ ├── Authenticator │ │ │ └── ApiKeyAuthenticatorTest.php │ │ ├── Handler │ │ │ └── TranslatedAuthenticationFailureHandlerTest.php │ │ ├── Provider │ │ │ ├── ApiKeyUserProviderTest.php │ │ │ └── SecurityUserFactoryTest.php │ │ ├── RolesServiceTest.php │ │ ├── UserTypeIdentificationTest.php │ │ └── Voter │ │ │ └── IsUserHimselfVoterTest.php │ ├── Service │ │ ├── LocalizationTest.php │ │ └── VersionTest.php │ ├── TestCase │ │ ├── DtoTestCase.php │ │ ├── EntityTestCase.php │ │ ├── RepositoryTestCase.php │ │ ├── ResourceTestCase.php │ │ ├── RestIntegrationControllerTestCase.php │ │ ├── RestRequestMapperConfigurationTestCase.php │ │ └── RestRequestMapperTestCase.php │ ├── Utils │ │ ├── HealthzServiceTest.php │ │ ├── LoginLoggerTest.php │ │ └── RequestLoggerTest.php │ ├── Validator │ │ └── Constraints │ │ │ ├── EntityReferenceExistsValidatorTest.php │ │ │ ├── LanguageValidatorTest.php │ │ │ ├── LocaleValidatorTest.php │ │ │ ├── TimezoneValidatorTest.php │ │ │ ├── UniqueEmailValidatorTest.php │ │ │ ├── UniqueUsernameValidatorTest.php │ │ │ └── src │ │ │ ├── TestConstraint.php │ │ │ └── TestEntityReference.php │ └── ValueResolver │ │ ├── EntityValueResolverTest.php │ │ ├── LoggedInUserValueResolverTest.php │ │ └── RestDtoValueResolverTest.php ├── Unit │ ├── Entity │ │ ├── ApiKeyTest.php │ │ ├── DateDimensionTest.php │ │ ├── LogLoginTest.php │ │ ├── LogRequestTest.php │ │ ├── RoleTest.php │ │ └── UserGroupTest.php │ ├── EventSubscriber │ │ ├── AcceptLanguageSubscriberTest.php │ │ ├── AuthenticationFailureSubscriberTest.php │ │ ├── AuthenticationSuccessSubscriberTest.php │ │ ├── BodySubscriberTest.php │ │ ├── DoctrineExtensionSubscriberTest.php │ │ ├── ExceptionSubscriberTest.php │ │ ├── JWTCreatedSubscriberTest.php │ │ ├── JWTDecodedSubscriberTest.php │ │ ├── LockedUserSubscriberTest.php │ │ ├── RequestLogSubscriberTest.php │ │ └── ResponseSubscriberTest.php │ ├── IntegrityTest.php │ ├── Rest │ │ ├── RequestHandlerTest.php │ │ ├── SearchTermTest.php │ │ └── UuidHelperTest.php │ ├── Security │ │ ├── ApiKeyUserTest.php │ │ └── SecurityUserTest.php │ ├── Utils │ │ ├── JSONTest.php │ │ └── Tests │ │ │ ├── PHPUnitUtilTest.php │ │ │ └── StringableArrayObjectTest.php │ └── Validator │ │ └── Constraints │ │ ├── EntityReferenceExistsTest.php │ │ ├── LanguageTest.php │ │ ├── LocaleTest.php │ │ ├── TimezoneTest.php │ │ ├── UniqueEmailTest.php │ │ └── UniqueUsernameTest.php ├── Utils │ ├── PhpUnitUtil.php │ └── StringableArrayObject.php ├── bootstrap.php └── bootstrap_fastest.php ├── tools ├── 02_phpstan │ ├── .gitignore │ ├── composer.json │ └── composer.lock ├── 03_psalm │ ├── .gitignore │ ├── composer.json │ └── composer.lock ├── 04_symplify │ ├── .gitignore │ ├── composer.json │ └── composer.lock ├── 05_infection │ ├── .gitignore │ ├── composer.json │ └── composer.lock ├── 06_php-coveralls │ ├── .gitignore │ ├── composer.json │ └── composer.lock ├── 07_phpinsights │ ├── .gitignore │ ├── composer.json │ └── composer.lock ├── 08_phpmetrics │ ├── .gitignore │ ├── composer.json │ └── composer.lock ├── 09_rector │ ├── .gitignore │ ├── composer.json │ └── composer.lock ├── 10_composer │ ├── .gitignore │ ├── composer.json │ └── composer.lock ├── 11_phplint │ ├── .gitignore │ ├── composer.json │ └── composer.lock └── 12_php-parallel-lint │ ├── .gitignore │ ├── composer.json │ └── composer.lock └── translations ├── .gitignore └── security+intl-icu.fi.xlf /.dockerignore: -------------------------------------------------------------------------------- 1 | ###> symfony/framework-bundle ### 2 | /.env.local 3 | /.env.*.local 4 | /.env.local.php 5 | /public/bundles/ 6 | /var/ 7 | /vendor/ 8 | ###< symfony/framework-bundle ### 9 | 10 | /secrets/application.*.json 11 | compose.*.yaml 12 | 13 | # User-specific stuff: 14 | .idea/**/workspace.xml 15 | .idea/**/tasks.xml 16 | .idea/dictionaries 17 | .idea/shelf 18 | 19 | ## File-based project format: 20 | *.iws 21 | 22 | .phpunit.result.cache 23 | phpunit.xml 24 | infection.json 25 | 26 | /build/ 27 | 28 | ###> symfony/web-server-bundle ### 29 | .web-server-pid 30 | ###< symfony/web-server-bundle ### 31 | 32 | ###> friendsofphp/php-cs-fixer ### 33 | .php_cs 34 | .php_cs.cache 35 | ###< friendsofphp/php-cs-fixer ### 36 | 37 | ###> lexik/jwt-authentication-bundle ### 38 | /config/jwt/*.pem 39 | ###< lexik/jwt-authentication-bundle ### 40 | 41 | ### Vendor bin dependencies 42 | /tools/*/vendor/ 43 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | end_of_line = lf 9 | indent_style = space 10 | indent_size = 4 11 | insert_final_newline = true 12 | 13 | [{composer.json,Makefile}] 14 | indent_style = tab 15 | 16 | [{.codeclimate.yml,main.yml,vulnerability-scan.yml,*.md}] 17 | indent_size = 2 18 | -------------------------------------------------------------------------------- /.env.dev: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarlepp/symfony-flex-backend/ea11d123bc3a063ea0362fcf110d7cd50246b290/.env.dev -------------------------------------------------------------------------------- /.env.gh-actions: -------------------------------------------------------------------------------- 1 | # This file is a "template" of which env vars needs to be defined in your configuration or in an .env file 2 | # Set variables here that may be different on each deployment target of the app, e.g. development, staging, production. 3 | # https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration 4 | 5 | ###> symfony/framework-bundle ### 6 | APP_ENV=test 7 | APP_SECRET=2edbe69f411744beb240bc58fff311bd 8 | ###< symfony/framework-bundle ### 9 | 10 | ###> symfony-flex-backend ### 11 | APPLICATION_CONFIG=./secrets/application_test.json 12 | ###< symfony-flex-backend ### 13 | -------------------------------------------------------------------------------- /.env.test: -------------------------------------------------------------------------------- 1 | # This file is a "template" of which env vars needs to be defined in your configuration or in an .env file 2 | # Set variables here that may be different on each deployment target of the app, e.g. development, staging, production. 3 | # https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration 4 | 5 | ###> symfony/framework-bundle ### 6 | APP_ENV=test 7 | APP_SECRET=2edbe69f411744beb240bc58fff311bd 8 | ###< symfony/framework-bundle ### 9 | 10 | ###> symfony-flex-backend ### 11 | APPLICATION_CONFIG=./secrets/application_test.json 12 | ###< symfony-flex-backend ### 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.php text eol=lf 2 | 3 | composer.lock binary -text diff 4 | symfony.lock binary -text diff 5 | -------------------------------------------------------------------------------- /.github/workflows/vulnerability-scan.yml: -------------------------------------------------------------------------------- 1 | # GitHub Actions docs 2 | # https://help.github.com/en/articles/about-github-actions 3 | # https://help.github.com/en/articles/workflow-syntax-for-github-actions 4 | name: Vulnerability Scan 5 | on: 6 | schedule: 7 | # Run every day at 12:00 UTC 8 | - cron: '0 12 * * *' 9 | workflow_dispatch: 10 | 11 | jobs: 12 | scan: 13 | name: Scan docker image with Trivy 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout code 18 | uses: actions/checkout@v4 19 | 20 | - name: Build the Docker image 21 | run: docker build . --file Dockerfile --tag symfony-flex-backend:master 22 | 23 | - name: Scan image with Trivy 24 | uses: lazy-actions/gitrivy@v3 25 | with: 26 | token: ${{ secrets.GITHUB_TOKEN }} 27 | image: symfony-flex-backend:master 28 | ignore-unfixed: true 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ###> symfony/framework-bundle ### 2 | /.env.local 3 | /.env.local.php 4 | /.env.*.local 5 | /config/secrets/prod/prod.decrypt.private.php 6 | /public/bundles/ 7 | /var/ 8 | /vendor/ 9 | ###< symfony/framework-bundle ### 10 | 11 | /secrets/application.*.json 12 | compose.*.yaml 13 | 14 | ## File-based project format: 15 | *.iws 16 | 17 | .phpunit.result.cache 18 | infection.json 19 | phpstan.neon 20 | 21 | /build/ 22 | ###> friendsofphp/php-cs-fixer ### 23 | .php-cs-fixer.cache 24 | .php_cs 25 | .php_cs.cache 26 | ###< friendsofphp/php-cs-fixer ### 27 | 28 | ###> lexik/jwt-authentication-bundle ### 29 | /config/jwt/*.pem 30 | ###< lexik/jwt-authentication-bundle ### 31 | 32 | ### Vendor bin dependencies 33 | /tools/*/vendor/ 34 | 35 | ### PHPUnit cache 36 | phpunit.xml 37 | .phpunit.cache 38 | 39 | ### PHPLint 40 | .phplint-cache 41 | .phplint.cache 42 | 43 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /commandlinetools/ 3 | /dictionaries/ 4 | /shelf/ 5 | /workspace.xml 6 | # Editor-based HTTP Client requests 7 | /httpRequests/ 8 | # Datasource local storage ignored files 9 | /dataSources/ 10 | /dataSources.local.xml 11 | # Other 12 | codeception.xml 13 | phpspec.xml 14 | # GitHub Copilot persisted chat sessions 15 | /copilot/chatSessions 16 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/dataSources.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | mysql.8 6 | true 7 | com.mysql.cj.jdbc.Driver 8 | jdbc:mysql://root:password@localhost:3310/symfony-flex-backend 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.idea/externalDependencies.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/remote-mappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/runConfigurations/Local_XDebug.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.idea/runConfigurations/PHPUnit___All_tests.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/runConfigurations/PHPUnit___E2E_tests.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/runConfigurations/PHPUnit___Functional_tests.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/runConfigurations/PHPUnit___Integration_tests.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/runConfigurations/PHPUnit___Unit_tests.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/scopes/src.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/sqldialects.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/symfony2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/webResources.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | in(__DIR__) 6 | ->exclude('somedir'); 7 | 8 | return (new PhpCsFixer\Config()) 9 | ->setRules([ 10 | '@Symfony' => true, 11 | 'array_syntax' => ['syntax' => 'short'], 12 | ]) 13 | ->setFinder($finder); 14 | -------------------------------------------------------------------------------- /.phplint.yml: -------------------------------------------------------------------------------- 1 | path: ./ 2 | jobs: 8 3 | extensions: 4 | - php 5 | exclude: 6 | - tools 7 | - var 8 | - vendor 9 | warning: true 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Tarmo Leppänen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | = 80000) { 10 | require dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit'; 11 | } else { 12 | define('PHPUNIT_COMPOSER_INSTALL', dirname(__DIR__).'/vendor/autoload.php'); 13 | require PHPUNIT_COMPOSER_INSTALL; 14 | PHPUnit\TextUI\Command::main(); 15 | } 16 | } else { 17 | if (!is_file(dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php')) { 18 | echo "Unable to find the `simple-phpunit.php` script in `vendor/symfony/phpunit-bridge/bin/`.\n"; 19 | exit(1); 20 | } 21 | 22 | require dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php'; 23 | } 24 | -------------------------------------------------------------------------------- /changelog-linker.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | authors_to_ignore: ['tarlepp'] 3 | -------------------------------------------------------------------------------- /config/bundles.php: -------------------------------------------------------------------------------- 1 | ['all' => true], 5 | Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], 6 | Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], 7 | Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], 8 | Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], 9 | Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], 10 | Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle::class => ['all' => true], 11 | Matthias\SymfonyConsoleForm\Bundle\SymfonyConsoleFormBundle::class => ['all' => true], 12 | Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], 13 | Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], 14 | Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['all' => true], 15 | Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true], 16 | Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true], 17 | Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], 18 | AutoMapperPlus\AutoMapperPlusBundle\AutoMapperPlusBundle::class => ['all' => true], 19 | ]; 20 | -------------------------------------------------------------------------------- /config/jwt/.gitignore: -------------------------------------------------------------------------------- 1 | private.pem 2 | public.pem 3 | -------------------------------------------------------------------------------- /config/jwt/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarlepp/symfony-flex-backend/ea11d123bc3a063ea0362fcf110d7cd50246b290/config/jwt/.gitkeep -------------------------------------------------------------------------------- /config/packages/cache.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | cache: 3 | # Unique name of your app: used to compute stable namespaces for cache keys. 4 | prefix_seed: tarlepp/symfony-flex-backend 5 | 6 | # The "app" cache stores to the filesystem by default. 7 | # The data in this cache should persist between deploys. 8 | # Other options include: 9 | 10 | # Redis 11 | #app: cache.adapter.redis 12 | #default_redis_provider: redis://localhost 13 | 14 | # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues) 15 | #app: cache.adapter.apcu 16 | 17 | # Namespaced pools use the above "app" backend by default 18 | #pools: 19 | #my.dedicated.cache: null 20 | pools: 21 | app.cache.apcu: 22 | adapter: cache.adapter.apcu 23 | -------------------------------------------------------------------------------- /config/packages/debug.yaml: -------------------------------------------------------------------------------- 1 | when@dev: 2 | debug: 3 | # Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser. 4 | # See the "server:dump" command to start a new server. 5 | dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%" 6 | -------------------------------------------------------------------------------- /config/packages/doctrine_extensions.yaml: -------------------------------------------------------------------------------- 1 | # See https://github.com/doctrine-extensions/DoctrineExtensions/blob/main/doc/symfony4.md 2 | services: 3 | Gedmo\Timestampable\TimestampableListener: 4 | tags: 5 | - { name: doctrine.event_listener, connection: default, event: 'prePersist' } 6 | - { name: doctrine.event_listener, connection: default, event: 'onFlush' } 7 | - { name: doctrine.event_listener, connection: default, event: 'loadClassMetadata' } 8 | 9 | Gedmo\Blameable\BlameableListener: 10 | tags: 11 | - { name: doctrine.event_listener, connection: default, event: 'prePersist' } 12 | - { name: doctrine.event_listener, connection: default, event: 'onFlush' } 13 | - { name: doctrine.event_listener, connection: default, event: 'loadClassMetadata' } 14 | -------------------------------------------------------------------------------- /config/packages/doctrine_migrations.yaml: -------------------------------------------------------------------------------- 1 | doctrine_migrations: 2 | migrations_paths: 3 | # namespace is arbitrary but should be different from App\Migrations 4 | # as migrations classes should NOT be autoloaded 5 | 'DoctrineMigrations': '%kernel.project_dir%/migrations' 6 | enable_profiler: '%kernel.debug%' 7 | storage: 8 | table_storage: 9 | table_name: 'migration_versions' 10 | version_column_name: 'version' 11 | version_column_length: 512 12 | executed_at_column_name: 'executed_at' 13 | all_or_nothing: true 14 | custom_template: '%kernel.project_dir%/templates/Doctrine/migration.tpl' 15 | -------------------------------------------------------------------------------- /config/packages/event_listeners.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | # default configuration for services in *this* file 3 | _defaults: 4 | # automatically injects dependencies in your services 5 | autowire: true 6 | # automatically registers your services as commands, form types, etc. 7 | autoconfigure: true 8 | # this means you cannot fetch services directly from the container via $container->get() 9 | # if you need to do this, you can override this setting on individual services 10 | public: false 11 | 12 | App\EventListener\UserEntityEventListener: 13 | tags: 14 | - { name: doctrine.event_listener, event: prePersist } 15 | - { name: doctrine.event_listener, event: preUpdate } 16 | -------------------------------------------------------------------------------- /config/packages/lexik_jwt_authentication.yaml: -------------------------------------------------------------------------------- 1 | lexik_jwt_authentication: 2 | secret_key: '%kernel.project_dir%/%env(resolve:JWT_PRIVATE_KEY_PATH)%' 3 | public_key: '%kernel.project_dir%/%env(resolve:JWT_PUBLIC_KEY_PATH)%' 4 | pass_phrase: '%env(JWT_PASSPHRASE)%' 5 | 6 | # token extraction settings 7 | token_extractors: 8 | authorization_header: # look for a token as Authorization Header 9 | enabled: true 10 | prefix: Bearer 11 | name: Authorization 12 | #cookie: # check token in a cookie 13 | # enabled: true 14 | # name: BEARER 15 | #query_parameter: # check token in query string parameter 16 | # enabled: true 17 | # name: bearer 18 | -------------------------------------------------------------------------------- /config/packages/nelmio_api_doc.yaml: -------------------------------------------------------------------------------- 1 | nelmio_api_doc: 2 | documentation: 3 | info: 4 | title: Symfony Flex Backend 5 | description: API documentation of this application. 6 | #securityDefinitions: 7 | # Bearer: 8 | # type: apiKey 9 | # description: 'Value: Bearer {JSON Web Token (JWT)}' 10 | # name: Authorization 11 | # in: header 12 | security: 13 | - Bearer: [] 14 | areas: 15 | default: 16 | path_patterns: 17 | - ^/api/doc 18 | - ^/api/doc.json 19 | - ^/(healthz|version|v1/auth|v1/profile|v1/localization) 20 | internal: 21 | path_patterns: # an array of regexps 22 | - ^/[a-z] 23 | -------------------------------------------------------------------------------- /config/packages/nelmio_cors.yaml: -------------------------------------------------------------------------------- 1 | nelmio_cors: 2 | defaults: 3 | origin_regex: true 4 | allow_origin: ['%env(CORS_ALLOW_ORIGIN)%'] 5 | allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE'] 6 | allow_headers: ['Content-Type', 'Authorization'] 7 | expose_headers: ['Link', 'X-API-VERSION'] 8 | max_age: 3600 9 | paths: 10 | '^/': null 11 | -------------------------------------------------------------------------------- /config/packages/ramsey_uuid_doctrine.yaml: -------------------------------------------------------------------------------- 1 | doctrine: 2 | dbal: 3 | types: 4 | uuid: 'Ramsey\Uuid\Doctrine\UuidType' 5 | uuid_binary: 'Ramsey\Uuid\Doctrine\UuidBinaryType' 6 | uuid_binary_ordered_time: 'Ramsey\Uuid\Doctrine\UuidBinaryOrderedTimeType' 7 | mapping_types: 8 | uuid_binary: 'binary' 9 | uuid_binary_ordered_time: 'binary' 10 | -------------------------------------------------------------------------------- /config/packages/routing.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | router: 3 | # Configure how to generate URLs in non-HTTP contexts, such as CLI commands. 4 | # See https://symfony.com/doc/current/routing.html#generating-urls-in-commands 5 | #default_uri: http://localhost 6 | 7 | when@prod: 8 | framework: 9 | router: 10 | strict_requirements: null 11 | -------------------------------------------------------------------------------- /config/packages/translation.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | default_locale: '%locale%' 3 | translator: 4 | default_path: '%kernel.project_dir%/translations' 5 | fallbacks: 6 | - '%locale%' 7 | # providers: 8 | # crowdin: 9 | # dsn: '%env(CROWDIN_DSN)%' 10 | # loco: 11 | # dsn: '%env(LOCO_DSN)%' 12 | # lokalise: 13 | # dsn: '%env(LOKALISE_DSN)%' 14 | # phrase: 15 | # dsn: '%env(PHRASE_DSN)%' 16 | -------------------------------------------------------------------------------- /config/packages/twig.yaml: -------------------------------------------------------------------------------- 1 | twig: 2 | file_name_pattern: '*.twig' 3 | 4 | when@test: 5 | twig: 6 | strict_variables: true 7 | -------------------------------------------------------------------------------- /config/packages/validator.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | validation: 3 | # Enables validator auto-mapping support. 4 | # For instance, basic validation constraints will be inferred from Doctrine's metadata. 5 | #auto_mapping: 6 | # App\Entity\: [] 7 | 8 | when@test: 9 | framework: 10 | validation: 11 | not_compromised_password: false 12 | -------------------------------------------------------------------------------- /config/packages/web_profiler.yaml: -------------------------------------------------------------------------------- 1 | when@dev: 2 | web_profiler: 3 | toolbar: true 4 | 5 | framework: 6 | profiler: 7 | collect_serializer_data: true 8 | 9 | when@test: 10 | framework: 11 | profiler: { collect: false } 12 | -------------------------------------------------------------------------------- /config/preload.php: -------------------------------------------------------------------------------- 1 | > /home/dev/.bashrc 42 | 43 | exec "$@" 44 | -------------------------------------------------------------------------------- /docker-sync.yml: -------------------------------------------------------------------------------- 1 | # 2 | # For osx users, see http://docker-sync.io/ 3 | # this file should be added to your VCS 4 | # 5 | version: '2' 6 | 7 | syncs: 8 | backend-code: 9 | src: ./ 10 | sync_args: 11 | - "-ignore='Path .idea'" # no need to send PHPStorm config to container 12 | - "-ignore='Path .git'" # ignore the main .git repo 13 | - "-ignore='BelowPath .git'" # also ignore .git repos in subfolders such as in composer vendor dirs 14 | - "-ignore='Path var/cache/*'" # don't share the cache 15 | - "-ignore='Path var/sessions/*'" # we don't need the sessions locally 16 | -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | # What is this? 2 | 3 | This folder contains necessary configuration files for Docker containers. 4 | -------------------------------------------------------------------------------- /docker/fish/completions/sf_console.fish: -------------------------------------------------------------------------------- 1 | # This file is part of the Symfony package. 2 | # 3 | # (c) Fabien Potencier 4 | # 5 | # For the full copyright and license information, please view 6 | # https://symfony.com/doc/current/contributing/code/license.html 7 | 8 | function _sf_console 9 | set sf_cmd (commandline -o) 10 | set c (count (commandline -oc)) 11 | 12 | set completecmd "$sf_cmd[1]" "_complete" "-sfish" "-S6.1.1" 13 | 14 | for i in $sf_cmd 15 | if [ $i != "" ] 16 | set completecmd $completecmd "-i$i" 17 | end 18 | end 19 | 20 | set completecmd $completecmd "-c$c" 21 | 22 | set sfcomplete ($completecmd) 23 | 24 | for i in $sfcomplete 25 | echo $i 26 | end 27 | end 28 | 29 | complete -c 'console' -a '(_sf_console)' -f 30 | -------------------------------------------------------------------------------- /docker/fish/config.fish: -------------------------------------------------------------------------------- 1 | source /home/dev/.config/fish/completions/sf_console.fish 2 | thefuck --alias | source 3 | -------------------------------------------------------------------------------- /docker/fish/functions/console.fish: -------------------------------------------------------------------------------- 1 | # Defined in - @ line 1 2 | function console --wraps=/app/bin/console --description 'alias console=/app/bin/console' 3 | /app/bin/console $argv; 4 | end 5 | -------------------------------------------------------------------------------- /docker/mariadb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mariadb:10.7.1 2 | 3 | ADD mysql_custom.cnf /etc/mysql/conf.d/mysql_custom.cnf 4 | 5 | RUN chmod 644 /etc/mysql/conf.d/mysql_custom.cnf 6 | -------------------------------------------------------------------------------- /docker/mariadb/mysql_custom.cnf: -------------------------------------------------------------------------------- 1 | [mysqld] 2 | log_output = TABLE 3 | log_slow_verbosity = query_plan,innodb,explain 4 | slow_query_log = 1 5 | long_query_time = 1 6 | 7 | ; pm.max_children = 5 * of app servers 8 | ;max_connections = 100 9 | 10 | ; 90% of server memory 11 | ;innodb_buffer_pool_size = 2GB 12 | 13 | ; Enterprise SSD = 50000 14 | ; Single consumer SSD = 10000 15 | ; Single 7200RPM drive = 200 16 | ;innodb_io_capacity = 200 17 | 18 | ;max_allowed_packet=60M 19 | ;group_concat_max_len=1048576 20 | -------------------------------------------------------------------------------- /docker/nginx/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:mainline-alpine-slim 2 | 3 | ADD nginx.conf /etc/nginx/conf.d/default.conf 4 | ADD php-upstream.conf /etc/nginx/conf.d/upstream.conf 5 | 6 | # https://cloud.google.com/monitoring/agent/plugins/nginx 7 | RUN apk update && apk add curl 8 | RUN cd /etc/nginx/conf.d/ \ 9 | && curl -O https://raw.githubusercontent.com/Stackdriver/stackdriver-agent-service-configs/master/etc/nginx/conf.d/status.conf \ 10 | && rm -rf /var/cache/apk/* 11 | -------------------------------------------------------------------------------- /docker/nginx/Dockerfile_dev: -------------------------------------------------------------------------------- 1 | FROM nginx:mainline-alpine-slim 2 | 3 | # Note that this `nginx-dev.conf` is also mounted within `compose.yaml` 4 | # so you don't need to build containers if you change something there, restart 5 | # should do the trick 6 | ADD nginx-dev.conf /etc/nginx/conf.d/default.conf 7 | ADD php-upstream.conf /etc/nginx/conf.d/upstream.conf 8 | 9 | # https://cloud.google.com/monitoring/agent/plugins/nginx 10 | RUN apk update && apk add curl 11 | RUN cd /etc/nginx/conf.d/ \ 12 | && curl -O https://raw.githubusercontent.com/Stackdriver/stackdriver-agent-service-configs/master/etc/nginx/conf.d/status.conf \ 13 | && rm -rf /var/cache/apk/* 14 | -------------------------------------------------------------------------------- /docker/nginx/php-upstream.conf: -------------------------------------------------------------------------------- 1 | upstream php-upstream { 2 | server php:9000; 3 | } 4 | -------------------------------------------------------------------------------- /docker/nginx/ssl/create-keys.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | openssl genrsa -passout pass: -des3 -out rootCA.key 2048 4 | openssl req -x509 -new -nodes -passin pass: -key rootCA.key -sha256 -days 10000 -out rootCA.pem 5 | openssl genrsa -out tls.key 2048 6 | openssl req -new -key tls.key -out tls.csr 7 | openssl x509 -req -in tls.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out tls.crt -days 10000 -sha256 -passin pass: -extfile openssl.cnf 8 | 9 | # To export p12 format 10 | #openssl pkcs12 -export -inkey ./rootCA.key -in ./rootCA.pem -out ./rootCA.p12 11 | #openssl pkcs12 -export -inkey ./tls.key -in ./tls.crt -out ./tls.p12 12 | -------------------------------------------------------------------------------- /docker/nginx/ssl/openssl.cnf: -------------------------------------------------------------------------------- 1 | # Extensions to add to a certificate request 2 | basicConstraints = CA:FALSE 3 | authorityKeyIdentifier = keyid:always, issuer:always 4 | keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment 5 | subjectAltName = @alt_names 6 | 7 | [v3_req] 8 | subjectAltName = @alt_names 9 | 10 | [alt_names] 11 | DNS.1 = *.localhost 12 | DNS.2 = localhost 13 | -------------------------------------------------------------------------------- /docker/nginx/ssl/tls.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIC8DCCAdgCAQAwgaoxCzAJBgNVBAYTAkZJMRMwEQYDVQQIDApTb21lLVN0YXRl 3 | MTgwNgYDVQQKDC9odHRwczovL2dpdGh1Yi5jb20vdGFybGVwcC9zeW1mb255LWZs 4 | ZXgtYmFja2VuZDE4MDYGA1UECwwvaHR0cHM6Ly9naXRodWIuY29tL3RhcmxlcHAv 5 | c3ltZm9ueS1mbGV4LWJhY2tlbmQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJ 6 | KoZIhvcNAQEBBQADggEPADCCAQoCggEBAM2kkqvjgYIPP/6o4QOvPLYwfcRNe3kh 7 | Ty9HZKO+pGwMH91rZnrdt1s1kAWZj1rNyGMvxpF1H1zopKL5fFT7UdjbnYz2mXpe 8 | yzX+Q7cSyCYfty2kkB1o0ONoJy1C5XssX1Wt02F1NXq6wbejb5CFTnSr8SIFcbQ8 9 | DIqXS66PLAcBB6xa9OzCKF7iCiKi1e9Qy4FZSdXJUDzUBnyiHEgoRCbDLdJvo5dc 10 | fNvd0X5IazRj37s1z0shTKRVi6bZ8Mu/z7V5UqNmWgBT0c+bj6qbW2q1oNEr8Efr 11 | JqjvNaQag9xCf59/o7cP7g/kLA0bzrAPE22//JTeJoLogetkVj4Rt9UCAwEAAaAA 12 | MA0GCSqGSIb3DQEBCwUAA4IBAQCo9AoNiObgFOiZpBCBPFco91qwQYUbboY6k9mX 13 | +kcEyYqAuJZVbMUfCBlpM3pqzNXkOXPOc7nZki8gS12qNrnDRhaKTHfmn3on8VJN 14 | ZFtjFWCYg5oajteEvPWJQjHjELRjW69XpSxLZJEMkAEsRYqxkYT9WRuliqEGVaVT 15 | 6ksuYMG1wLAK06lubq8lPLuXueHKLVVMavY6YxtpFMN/k+Uqx3Nb87VWvWVoYTA8 16 | NFjfMI0oRm3dV4Up4dl9eHcFWZWYpt7+Qlx2KOITGmV4mjjRDVTZTR1C5EQfMxSf 17 | PCHm0yMfNza1teBTacqyuw6mvumeOhrocetTINgtzhpqOJo1 18 | -----END CERTIFICATE REQUEST----- 19 | -------------------------------------------------------------------------------- /docker/php/php-dev.ini: -------------------------------------------------------------------------------- 1 | expose_php = off 2 | memory_limit = 2048M 3 | short_open_tag = off 4 | max_execution_time = 180 5 | post_max_size = 64M 6 | upload_max_filesize = 48M 7 | max_input_time = 60 8 | max_input_vars = 3000 9 | date.timezone = UTC 10 | 11 | ; maximum memory that OPcache can use to store compiled PHP files 12 | opcache.memory_consumption = 256 13 | 14 | ; maximum number of files that can be stored in the cache 15 | opcache.max_accelerated_files = 20000 16 | 17 | ; maximum memory allocated to store the results 18 | realpath_cache_size = 4096K 19 | 20 | ; save the results for 10 minutes (600 seconds) 21 | realpath_cache_ttl = 600 22 | 23 | ; Ensure worker stdout and stderr are sent to the main error log 24 | catch_workers_output = yes 25 | decorate_workers_output = no 26 | 27 | ; igbinary 28 | apc.serializer=igbinary 29 | 30 | ; Xdebug settings 31 | xdebug.mode = coverage,debug 32 | xdebug.start_with_request = yes 33 | xdebug.client_host = host.docker.internal 34 | -------------------------------------------------------------------------------- /docker/php/php.ini: -------------------------------------------------------------------------------- 1 | expose_php = off 2 | memory_limit = 256M 3 | short_open_tag = off 4 | max_execution_time = 180 5 | post_max_size = 64M 6 | upload_max_filesize = 48M 7 | max_input_time = 60 8 | max_input_vars = 3000 9 | date.timezone = UTC 10 | 11 | ; maximum memory that OPcache can use to store compiled PHP files 12 | opcache.memory_consumption = 256 13 | 14 | ; maximum number of files that can be stored in the cache 15 | opcache.max_accelerated_files = 20000 16 | 17 | ; maximum memory allocated to store the results 18 | realpath_cache_size = 4096K 19 | 20 | ; save the results for one hour (3600 seconds) 21 | realpath_cache_ttl = 3600 22 | 23 | ; in production we don't want to check file timestamps 24 | opcache.validate_timestamps = 0 25 | 26 | ; Ensure worker stdout and stderr are sent to the main error log 27 | catch_workers_output = yes 28 | decorate_workers_output = no 29 | 30 | ; igbinary 31 | apc.serializer=igbinary 32 | -------------------------------------------------------------------------------- /infection.json.dist: -------------------------------------------------------------------------------- 1 | { 2 | "timeout": 360, 3 | "source": { 4 | "directories": [ 5 | "src" 6 | ], 7 | "excludes": [ 8 | "*Maker/" 9 | ] 10 | }, 11 | "logs": { 12 | "text": "build/infection/infection-log.txt", 13 | "summary": "build/infection/summary.log", 14 | "debug": "build/infection/debug.log", 15 | "perMutator": "build/infection/per-mutator.md" 16 | }, 17 | "mutators": { 18 | "@default": true, 19 | "IdenticalEqual": false, 20 | "NotIdenticalNotEqual": false 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /markdown-lint.yml: -------------------------------------------------------------------------------- 1 | MD026: 2 | punctuation: '.,;:!' 3 | -------------------------------------------------------------------------------- /migrations/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarlepp/symfony-flex-backend/ea11d123bc3a063ea0362fcf110d7cd50246b290/migrations/.gitignore -------------------------------------------------------------------------------- /migrations/Version20220324162224.php: -------------------------------------------------------------------------------- 1 | addSql('ALTER TABLE log_login ADD username VARCHAR(255) NOT NULL AFTER type'); 28 | } 29 | 30 | /** 31 | * @noinspection PhpMissingParentCallCommonInspection 32 | */ 33 | #[Override] 34 | public function down(Schema $schema): void 35 | { 36 | $this->addSql('ALTER TABLE log_login DROP username'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /phpstan.neon.dist: -------------------------------------------------------------------------------- 1 | parameters: 2 | level: 9 3 | paths: 4 | - src 5 | - tests 6 | editorUrl: '%%file%%:%%line%%' 7 | symfony: 8 | containerXmlPath: var/cache/dev/App_KernelDevDebugContainer.xml 9 | checkExplicitMixed: false 10 | ignoreErrors: 11 | - 12 | identifier: missingType.generics 13 | - 14 | messages: 15 | - '#Access to constant on internal class Symfony\\Component\\Validator\\Context\\ExecutionContext\.#' 16 | - '#Method PHPUnit\\Framework\\MockObject\\InvocationStubber::with\(\) invoked with unpacked array with possibly string key(.*)#' 17 | paths: 18 | - tests/Integration/* 19 | - 20 | messages: 21 | - '#has PHPDoc tag \@method for method (.*)\(\) parameter \#(\d+) \$(.*) with no value type specified in iterable type array#' 22 | paths: 23 | - tests/* 24 | - src/* 25 | includes: 26 | - tools/02_phpstan/vendor/phpstan/phpstan/conf/bleedingEdge.neon 27 | - tools/02_phpstan/vendor/phpstan/phpstan-deprecation-rules/rules.neon 28 | - tools/02_phpstan/vendor/phpstan/phpstan-phpunit/extension.neon 29 | - tools/02_phpstan/vendor/phpstan/phpstan-symfony/extension.neon 30 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarlepp/symfony-flex-backend/ea11d123bc3a063ea0362fcf110d7cd50246b290/public/favicon.ico -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\AutoMapper\ApiKey; 10 | 11 | use App\AutoMapper\RestAutoMapperConfiguration; 12 | use App\DTO\ApiKey\ApiKeyCreate; 13 | use App\DTO\ApiKey\ApiKeyPatch; 14 | use App\DTO\ApiKey\ApiKeyUpdate; 15 | 16 | /** 17 | * @package App\AutoMapper 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | class AutoMapperConfiguration extends RestAutoMapperConfiguration 21 | { 22 | /** 23 | * Classes to use specified request mapper. 24 | * 25 | * @var array 26 | */ 27 | protected static array $requestMapperClasses = [ 28 | ApiKeyCreate::class, 29 | ApiKeyUpdate::class, 30 | ApiKeyPatch::class, 31 | ]; 32 | 33 | public function __construct( 34 | RequestMapper $requestMapper, 35 | ) { 36 | parent::__construct($requestMapper); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/AutoMapper/User/AutoMapperConfiguration.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\AutoMapper\User; 10 | 11 | use App\AutoMapper\RestAutoMapperConfiguration; 12 | use App\DTO\User\UserCreate; 13 | use App\DTO\User\UserPatch; 14 | use App\DTO\User\UserUpdate; 15 | 16 | /** 17 | * @package App\AutoMapper 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | class AutoMapperConfiguration extends RestAutoMapperConfiguration 21 | { 22 | /** 23 | * Classes to use specified request mapper. 24 | * 25 | * @var array 26 | */ 27 | protected static array $requestMapperClasses = [ 28 | UserCreate::class, 29 | UserUpdate::class, 30 | UserPatch::class, 31 | ]; 32 | 33 | public function __construct( 34 | RequestMapper $requestMapper, 35 | ) { 36 | parent::__construct($requestMapper); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/AutoMapper/UserGroup/AutoMapperConfiguration.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\AutoMapper\UserGroup; 10 | 11 | use App\AutoMapper\RestAutoMapperConfiguration; 12 | use App\DTO\UserGroup\UserGroupCreate; 13 | use App\DTO\UserGroup\UserGroupPatch; 14 | use App\DTO\UserGroup\UserGroupUpdate; 15 | 16 | /** 17 | * @package App\AutoMapper 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | class AutoMapperConfiguration extends RestAutoMapperConfiguration 21 | { 22 | /** 23 | * Classes to use specified request mapper. 24 | * 25 | * @var array 26 | */ 27 | protected static array $requestMapperClasses = [ 28 | UserGroupCreate::class, 29 | UserGroupUpdate::class, 30 | UserGroupPatch::class, 31 | ]; 32 | 33 | public function __construct( 34 | RequestMapper $requestMapper, 35 | ) { 36 | parent::__construct($requestMapper); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/AutoMapper/UserGroup/RequestMapper.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\AutoMapper\UserGroup; 10 | 11 | use App\AutoMapper\RestRequestMapper; 12 | use App\Entity\Role; 13 | use App\Resource\RoleResource; 14 | use Throwable; 15 | 16 | /** 17 | * @package App\AutoMapper 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | class RequestMapper extends RestRequestMapper 21 | { 22 | /** 23 | * @var array 24 | */ 25 | protected static array $properties = [ 26 | 'name', 27 | 'role', 28 | ]; 29 | 30 | public function __construct( 31 | private readonly RoleResource $roleResource, 32 | ) { 33 | } 34 | 35 | /** 36 | * @throws Throwable 37 | */ 38 | protected function transformRole(string $role): Role 39 | { 40 | return $this->roleResource->getReference($role); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Command/ApiKey/ApiKeyManagementCommand.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Command\ApiKey; 10 | 11 | use App\Command\Traits\ExecuteMultipleCommandTrait; 12 | use Symfony\Component\Console\Attribute\AsCommand; 13 | use Symfony\Component\Console\Command\Command; 14 | 15 | /** 16 | * @package App\Command\ApiKey 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | #[AsCommand( 20 | name: 'api-key:management', 21 | description: 'Console command to manage API keys', 22 | )] 23 | class ApiKeyManagementCommand extends Command 24 | { 25 | use ExecuteMultipleCommandTrait; 26 | 27 | public function __construct() 28 | { 29 | parent::__construct(); 30 | 31 | $this->setChoices([ 32 | ListApiKeysCommand::NAME => 'List API keys', 33 | CreateApiKeyCommand::NAME => 'Create API key', 34 | EditApiKeyCommand::NAME => 'Edit API key', 35 | ChangeTokenCommand::NAME => 'Change API key token', 36 | RemoveApiKeyCommand::NAME => 'Remove API key', 37 | '0' => 'Exit', 38 | ]); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Command/Traits/GetApplicationTrait.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Command\Traits; 10 | 11 | use Symfony\Component\Console\Application; 12 | use Symfony\Component\Console\Exception\RuntimeException; 13 | 14 | /** 15 | * @package App\Command\Traits 16 | * @author TLe, Tarmo Leppänen 17 | */ 18 | trait GetApplicationTrait 19 | { 20 | /** 21 | * @throws RuntimeException 22 | */ 23 | public function getApplication(): Application 24 | { 25 | return parent::getApplication() 26 | ?? throw new RuntimeException('Cannot determine application for console command to use.'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Command/Traits/SymfonyStyleTrait.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Command\Traits; 10 | 11 | use Symfony\Component\Console\Input\InputInterface; 12 | use Symfony\Component\Console\Output\OutputInterface; 13 | use Symfony\Component\Console\Style\SymfonyStyle; 14 | 15 | /** 16 | * @package App\Command\Traits 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | trait SymfonyStyleTrait 20 | { 21 | /** 22 | * Method to get SymfonyStyle object for console commands. 23 | */ 24 | protected function getSymfonyStyle( 25 | InputInterface $input, 26 | OutputInterface $output, 27 | ?bool $clearScreen = null, 28 | ): SymfonyStyle { 29 | $clearScreen ??= true; 30 | 31 | $io = new SymfonyStyle($input, $output); 32 | 33 | if ($clearScreen) { 34 | $io->write("\033\143"); 35 | } 36 | 37 | return $io; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Controller/IndexController.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Controller; 10 | 11 | use Symfony\Component\HttpFoundation\JsonResponse; 12 | use Symfony\Component\HttpFoundation\Request; 13 | use Symfony\Component\HttpKernel\Attribute\AsController; 14 | use Symfony\Component\Routing\Attribute\Route; 15 | 16 | /** 17 | * @package App\Controller 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | #[AsController] 21 | class IndexController 22 | { 23 | /** 24 | * Default application response when requested root. 25 | */ 26 | #[Route( 27 | path: '/', 28 | methods: [Request::METHOD_GET], 29 | )] 30 | public function __invoke(): JsonResponse 31 | { 32 | return new JsonResponse(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Controller/v1/Role/RoleController.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Controller\v1\Role; 10 | 11 | use App\Resource\RoleResource; 12 | use App\Rest\Controller; 13 | use App\Rest\Traits\Actions; 14 | use OpenApi\Attributes as OA; 15 | use Symfony\Component\HttpKernel\Attribute\AsController; 16 | use Symfony\Component\Routing\Attribute\Route; 17 | use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter; 18 | use Symfony\Component\Security\Http\Attribute\IsGranted; 19 | 20 | /** 21 | * @package App\Controller\v1\Role 22 | * @author TLe, Tarmo Leppänen 23 | * 24 | * @method RoleResource getResource() 25 | */ 26 | #[AsController] 27 | #[Route( 28 | path: '/v1/role', 29 | )] 30 | #[IsGranted(AuthenticatedVoter::IS_AUTHENTICATED_FULLY)] 31 | #[OA\Tag(name: 'Role Management')] 32 | class RoleController extends Controller 33 | { 34 | use Actions\Admin\CountAction; 35 | use Actions\Admin\FindAction; 36 | use Actions\Admin\IdsAction; 37 | 38 | public function __construct( 39 | RoleResource $resource, 40 | ) { 41 | parent::__construct($resource); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/DTO/ApiKey/ApiKeyCreate.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\DTO\ApiKey; 10 | 11 | /** 12 | * @package App\DTO\ApiKey 13 | * @author TLe, Tarmo Leppänen 14 | */ 15 | class ApiKeyCreate extends ApiKey 16 | { 17 | } 18 | -------------------------------------------------------------------------------- /src/DTO/ApiKey/ApiKeyPatch.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\DTO\ApiKey; 10 | 11 | use App\DTO\Traits\PatchUserGroups; 12 | 13 | /** 14 | * @package App\DTO\ApiKey 15 | * @author TLe, Tarmo Leppänen 16 | */ 17 | class ApiKeyPatch extends ApiKey 18 | { 19 | use PatchUserGroups; 20 | } 21 | -------------------------------------------------------------------------------- /src/DTO/ApiKey/ApiKeyUpdate.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\DTO\ApiKey; 10 | 11 | /** 12 | * @package App\DTO\ApiKey 13 | * @author TLe, Tarmo Leppänen 14 | */ 15 | class ApiKeyUpdate extends ApiKey 16 | { 17 | } 18 | -------------------------------------------------------------------------------- /src/DTO/RestDtoInterface.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\DTO; 10 | 11 | use App\Entity\Interfaces\EntityInterface; 12 | use Throwable; 13 | 14 | /** 15 | * @package App\DTO 16 | * @author TLe, Tarmo Leppänen 17 | */ 18 | interface RestDtoInterface 19 | { 20 | public function setId(string $id): self; 21 | 22 | /** 23 | * Getter method for visited setters. This is needed for dto patching. 24 | * 25 | * @return array 26 | */ 27 | public function getVisited(): array; 28 | 29 | /** 30 | * Setter for visited data. This is needed for dto patching. 31 | */ 32 | public function setVisited(string $property): self; 33 | 34 | /** 35 | * Method to load DTO data from specified entity. 36 | */ 37 | public function load(EntityInterface $entity): self; 38 | 39 | /** 40 | * Method to update specified entity with DTO data. 41 | */ 42 | public function update(EntityInterface $entity): EntityInterface; 43 | 44 | /** 45 | * Method to patch current dto with another one. 46 | * 47 | * @throws Throwable 48 | */ 49 | public function patch(self $dto): self; 50 | } 51 | -------------------------------------------------------------------------------- /src/DTO/Traits/PatchUserGroups.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\DTO\Traits; 10 | 11 | use App\Entity\Interfaces\UserGroupAwareInterface; 12 | use App\Entity\UserGroup as UserGroupEntity; 13 | use function array_map; 14 | 15 | /** 16 | * @package App\DTO\Traits 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | trait PatchUserGroups 20 | { 21 | /** 22 | * Method to patch entity user groups. 23 | * 24 | * @param array $value 25 | */ 26 | protected function updateUserGroups(UserGroupAwareInterface $entity, array $value): self 27 | { 28 | array_map( 29 | static fn (UserGroupEntity $userGroup): UserGroupAwareInterface => $entity->addUserGroup($userGroup), 30 | $value, 31 | ); 32 | 33 | return $this; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/DTO/User/UserCreate.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\DTO\User; 10 | 11 | use Symfony\Component\Validator\Constraints as Assert; 12 | 13 | /** 14 | * @package App\DTO\User 15 | * @author TLe, Tarmo Leppänen 16 | */ 17 | class UserCreate extends User 18 | { 19 | #[Assert\NotBlank] 20 | #[Assert\NotNull] 21 | #[Assert\Length(min: 8, max: 255)] 22 | protected string $password = ''; 23 | } 24 | -------------------------------------------------------------------------------- /src/DTO/User/UserPatch.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\DTO\User; 10 | 11 | use App\DTO\Traits\PatchUserGroups; 12 | 13 | /** 14 | * @package App\DTO\User 15 | * @author TLe, Tarmo Leppänen 16 | */ 17 | class UserPatch extends User 18 | { 19 | use PatchUserGroups; 20 | } 21 | -------------------------------------------------------------------------------- /src/DTO/User/UserUpdate.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\DTO\User; 10 | 11 | /** 12 | * @package App\DTO\User 13 | * @author TLe, Tarmo Leppänen 14 | */ 15 | class UserUpdate extends User 16 | { 17 | } 18 | -------------------------------------------------------------------------------- /src/DTO/UserGroup/UserGroupCreate.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\DTO\UserGroup; 10 | 11 | use App\Entity\Role; 12 | use App\Validator\Constraints as AppAssert; 13 | use Symfony\Component\Validator\Constraints as Assert; 14 | 15 | /** 16 | * @package App\DTO\UserGroup 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class UserGroupCreate extends UserGroup 20 | { 21 | #[Assert\NotBlank] 22 | #[Assert\NotNull] 23 | #[AppAssert\EntityReferenceExists(entityClass: Role::class)] 24 | protected ?Role $role = null; 25 | } 26 | -------------------------------------------------------------------------------- /src/DTO/UserGroup/UserGroupPatch.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\DTO\UserGroup; 10 | 11 | /** 12 | * @package App\DTO\UserGroup 13 | * @author TLe, Tarmo Leppänen 14 | */ 15 | class UserGroupPatch extends UserGroup 16 | { 17 | } 18 | -------------------------------------------------------------------------------- /src/DTO/UserGroup/UserGroupUpdate.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\DTO\UserGroup; 10 | 11 | use App\Entity\Role; 12 | use App\Validator\Constraints as AppAssert; 13 | use Symfony\Component\Validator\Constraints as Assert; 14 | 15 | /** 16 | * @package App\DTO\UserGroup 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class UserGroupUpdate extends UserGroup 20 | { 21 | #[Assert\NotBlank] 22 | #[Assert\NotNull] 23 | #[AppAssert\EntityReferenceExists(entityClass: Role::class)] 24 | protected ?Role $role = null; 25 | } 26 | -------------------------------------------------------------------------------- /src/Doctrine/DBAL/Types/EnumLanguageType.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Doctrine\DBAL\Types; 10 | 11 | use App\Enum\Interfaces\DatabaseEnumInterface; 12 | use App\Enum\Language; 13 | use BackedEnum; 14 | 15 | /** 16 | * @package App\Doctrine\DBAL\Types 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class EnumLanguageType extends EnumType 20 | { 21 | protected static string $name = Types::ENUM_LANGUAGE; 22 | 23 | /** 24 | * @psalm-var class-string 25 | */ 26 | protected static string $enum = Language::class; 27 | } 28 | -------------------------------------------------------------------------------- /src/Doctrine/DBAL/Types/EnumLocaleType.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Doctrine\DBAL\Types; 10 | 11 | use App\Enum\Interfaces\DatabaseEnumInterface; 12 | use App\Enum\Locale; 13 | use BackedEnum; 14 | 15 | /** 16 | * @package App\Doctrine\DBAL\Types 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class EnumLocaleType extends EnumType 20 | { 21 | protected static string $name = Types::ENUM_LOCALE; 22 | 23 | /** 24 | * @psalm-var class-string 25 | */ 26 | protected static string $enum = Locale::class; 27 | } 28 | -------------------------------------------------------------------------------- /src/Doctrine/DBAL/Types/EnumLogLoginType.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Doctrine\DBAL\Types; 10 | 11 | use App\Enum\Interfaces\DatabaseEnumInterface; 12 | use App\Enum\LogLogin; 13 | use BackedEnum; 14 | 15 | /** 16 | * @package App\Doctrine\DBAL\Types 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class EnumLogLoginType extends EnumType 20 | { 21 | protected static string $name = Types::ENUM_LOG_LOGIN; 22 | 23 | /** 24 | * @psalm-var class-string 25 | */ 26 | protected static string $enum = LogLogin::class; 27 | } 28 | -------------------------------------------------------------------------------- /src/Doctrine/DBAL/Types/Types.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Doctrine\DBAL\Types; 10 | 11 | /** 12 | * @package App\Doctrine\DBAL\Types 13 | * @author TLe, Tarmo Leppänen 14 | */ 15 | class Types 16 | { 17 | final public const string ENUM_LANGUAGE = 'EnumLanguage'; 18 | final public const string ENUM_LOCALE = 'EnumLocale'; 19 | final public const string ENUM_LOG_LOGIN = 'EnumLogLogin'; 20 | } 21 | -------------------------------------------------------------------------------- /src/Entity/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarlepp/symfony-flex-backend/ea11d123bc3a063ea0362fcf110d7cd50246b290/src/Entity/.gitignore -------------------------------------------------------------------------------- /src/Entity/Interfaces/EntityInterface.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Entity\Interfaces; 10 | 11 | use DateTimeImmutable; 12 | 13 | /** 14 | * @package App\Entity 15 | * @author TLe, Tarmo Leppänen 16 | */ 17 | interface EntityInterface 18 | { 19 | /** 20 | * @return non-empty-string 21 | */ 22 | public function getId(): string; 23 | public function getCreatedAt(): ?DateTimeImmutable; 24 | } 25 | -------------------------------------------------------------------------------- /src/Entity/Interfaces/UserGroupAwareInterface.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Entity\Interfaces; 10 | 11 | use App\Entity\UserGroup; 12 | use Doctrine\Common\Collections\ArrayCollection; 13 | use Doctrine\Common\Collections\Collection; 14 | 15 | /** 16 | * @package App\Entity 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | interface UserGroupAwareInterface extends EntityInterface 20 | { 21 | /** 22 | * @return Collection|ArrayCollection 23 | */ 24 | public function getUserGroups(): Collection | ArrayCollection; 25 | 26 | /** 27 | * Method to attach new userGroup to current user OR api key. 28 | */ 29 | public function addUserGroup(UserGroup $userGroup): mixed; 30 | 31 | /** 32 | * Method to remove specified userGroup from current user OR api key. 33 | */ 34 | public function removeUserGroup(UserGroup $userGroup): mixed; 35 | 36 | /** 37 | * Method to remove all many-to-many userGroup relations from current user 38 | * OR api key. 39 | */ 40 | public function clearUserGroups(): mixed; 41 | } 42 | -------------------------------------------------------------------------------- /src/Entity/Interfaces/UserInterface.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Entity\Interfaces; 10 | 11 | /** 12 | * @package App\Entity 13 | * @author TLe, Tarmo Leppänen 14 | */ 15 | interface UserInterface 16 | { 17 | /** 18 | * @return non-empty-string 19 | */ 20 | public function getId(): string; 21 | public function getUsername(): string; 22 | public function getEmail(): string; 23 | } 24 | -------------------------------------------------------------------------------- /src/Entity/Traits/Uuid.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Entity\Traits; 10 | 11 | use App\Rest\UuidHelper; 12 | use Ramsey\Uuid\UuidInterface; 13 | 14 | /** 15 | * @package App\Entity\Traits 16 | * @author TLe, Tarmo Leppänen 17 | */ 18 | trait Uuid 19 | { 20 | public function getUuid(): UuidInterface 21 | { 22 | return $this->id; 23 | } 24 | 25 | protected function createUuid(): UuidInterface 26 | { 27 | return UuidHelper::getFactory()->uuid1(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Enum/Interfaces/DatabaseEnumInterface.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Enum\Interfaces; 10 | 11 | /** 12 | * Enum StringEnumInterface 13 | * 14 | * @package App\Enum\Interfaces 15 | * @author TLe, Tarmo Leppänen 16 | */ 17 | interface DatabaseEnumInterface extends StringEnumInterface 18 | { 19 | } 20 | -------------------------------------------------------------------------------- /src/Enum/Interfaces/StringEnumInterface.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Enum\Interfaces; 10 | 11 | use BackedEnum; 12 | 13 | /** 14 | * Enum StringEnumInterface 15 | * 16 | * @package App\Enum\Interfaces 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | interface StringEnumInterface extends BackedEnum 20 | { 21 | /** 22 | * @return array 23 | */ 24 | public static function getValues(): array; 25 | } 26 | -------------------------------------------------------------------------------- /src/Enum/Language.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Enum; 10 | 11 | use App\Enum\Interfaces\DatabaseEnumInterface; 12 | use App\Enum\Traits\GetValues; 13 | 14 | /** 15 | * Language enum 16 | * 17 | * @package App\Enum 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | enum Language: string implements DatabaseEnumInterface 21 | { 22 | use GetValues; 23 | 24 | case EN = 'en'; 25 | case FI = 'fi'; 26 | 27 | public static function getDefault(): self 28 | { 29 | return self::EN; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Enum/Locale.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Enum; 10 | 11 | use App\Enum\Interfaces\DatabaseEnumInterface; 12 | use App\Enum\Traits\GetValues; 13 | 14 | /** 15 | * Locale enum 16 | * 17 | * @package App\Enum 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | enum Locale: string implements DatabaseEnumInterface 21 | { 22 | use GetValues; 23 | 24 | case EN = 'en'; 25 | case FI = 'fi'; 26 | 27 | public static function getDefault(): self 28 | { 29 | return self::EN; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Enum/LogLogin.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Enum; 10 | 11 | use App\Enum\Interfaces\DatabaseEnumInterface; 12 | use App\Enum\Traits\GetValues; 13 | 14 | /** 15 | * LogLogin enum 16 | * 17 | * @package App\Enum 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | enum LogLogin: string implements DatabaseEnumInterface 21 | { 22 | use GetValues; 23 | 24 | case FAILURE = 'failure'; 25 | case SUCCESS = 'success'; 26 | } 27 | -------------------------------------------------------------------------------- /src/Enum/Role.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Enum; 10 | 11 | /** 12 | * Enum Role 13 | * 14 | * @package App\Entity 15 | * @author TLe, Tarmo Leppänen 16 | */ 17 | enum Role: string 18 | { 19 | case LOGGED = 'ROLE_LOGGED'; 20 | case USER = 'ROLE_USER'; 21 | case ADMIN = 'ROLE_ADMIN'; 22 | case ROOT = 'ROLE_ROOT'; 23 | case API = 'ROLE_API'; 24 | 25 | public function label(): string 26 | { 27 | return match ($this) { 28 | self::LOGGED => 'Logged in users', 29 | self::USER => 'Normal users', 30 | self::ADMIN => 'Admin users', 31 | self::ROOT => 'Root users', 32 | self::API => 'API users', 33 | }; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Enum/Traits/GetValues.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Enum\Traits; 10 | 11 | use function array_column; 12 | 13 | /** 14 | * @package App\Enum\Traits 15 | * @author TLe, Tarmo Leppänen 16 | */ 17 | trait GetValues 18 | { 19 | /** 20 | * @return array 21 | */ 22 | public static function getValues(): array 23 | { 24 | return array_column(self::cases(), 'value'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Exception/interfaces/ClientErrorInterface.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Exception\interfaces; 10 | 11 | /** 12 | * If you want to expose _your_ exception class message as-is on `prod` 13 | * environment that should implement either this interface or 14 | * `Symfony\Component\HttpKernel\HttpKernelInterface` to get that message to 15 | * frontend side - otherwise you will just get `Internal server error.` message 16 | * with HTTP status 500. 17 | * 18 | * If your exception is not returning `code` properly, note that you will get 19 | * that HTTP status 500 on those - so it's _your_ responsibility to get 20 | * "proper" status code in your exception class. 21 | * 22 | * @package App\Exception\interfaces 23 | * @author TLe, Tarmo Leppänen 24 | */ 25 | interface ClientErrorInterface 26 | { 27 | /** 28 | * Method to get client response status code. 29 | */ 30 | public function getStatusCode(): int; 31 | } 32 | -------------------------------------------------------------------------------- /src/Exception/models/ValidatorError.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Exception\models; 10 | 11 | use Stringable; 12 | use Symfony\Component\Validator\ConstraintViolationInterface; 13 | use function str_replace; 14 | 15 | /** 16 | * @package App\Exception\models 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class ValidatorError 20 | { 21 | public string | Stringable $message; 22 | public string $propertyPath; 23 | public string $target; 24 | public string | null $code; 25 | 26 | public function __construct(ConstraintViolationInterface $error, string $target) 27 | { 28 | $this->message = $error->getMessage(); 29 | $this->propertyPath = $error->getPropertyPath(); 30 | $this->target = str_replace('\\', '.', $target); 31 | $this->code = $error->getCode(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Form/Type/FormTypeLabelInterface.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Form\Type; 10 | 11 | /** 12 | * @package App\Form\Type 13 | * @author TLe, Tarmo Leppänen 14 | */ 15 | interface FormTypeLabelInterface 16 | { 17 | // @codeCoverageIgnoreStart 18 | public const string LABEL = 'label'; 19 | public const string REQUIRED = 'required'; 20 | public const string EMPTY_DATA = 'empty_data'; 21 | public const string TYPE = 'type'; 22 | public const string FIRST_NAME = 'first_name'; 23 | public const string FIRST_OPTIONS = 'first_options'; 24 | public const string SECOND_NAME = 'second_name'; 25 | public const string SECOND_OPTIONS = 'second_options'; 26 | public const string CHOICES = 'choices'; 27 | public const string CHOICE_LABEL = 'choice_label'; 28 | public const string CLASS_NAME = 'class'; 29 | // @codeCoverageIgnoreEnd 30 | } 31 | -------------------------------------------------------------------------------- /src/Form/Type/Traits/AddBasicFieldToForm.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Form\Type\Traits; 10 | 11 | use Symfony\Component\Form\FormBuilderInterface; 12 | use function call_user_func_array; 13 | 14 | /** 15 | * @package App\Form\Type\Traits 16 | * @author TLe, Tarmo Leppänen 17 | */ 18 | trait AddBasicFieldToForm 19 | { 20 | /** 21 | * @param array> $fields 22 | */ 23 | protected function addBasicFieldToForm(FormBuilderInterface $builder, array $fields): void 24 | { 25 | foreach ($fields as $params) { 26 | call_user_func_array($builder->add(...), $params); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Helpers/LoggerAwareTrait.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Helpers; 10 | 11 | use Psr\Log\LoggerInterface; 12 | use Symfony\Contracts\Service\Attribute\Required; 13 | 14 | /** 15 | * NOTE: Do not use this in your services, just inject `LoggerInterface` to 16 | * service where you need it. This trait is just for quick debug purposes 17 | * and nothing else. 18 | * 19 | * @package App\Helpers 20 | * @author TLe, Tarmo Leppänen 21 | */ 22 | trait LoggerAwareTrait 23 | { 24 | protected ?LoggerInterface $logger = null; 25 | 26 | #[Required] 27 | public function setLogger(LoggerInterface $logger): self 28 | { 29 | $this->logger = $logger; 30 | 31 | return $this; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Helpers/StopwatchAwareTrait.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Helpers; 10 | 11 | use Symfony\Component\Stopwatch\Stopwatch; 12 | use Symfony\Contracts\Service\Attribute\Required; 13 | 14 | /** 15 | * NOTE: Do not use this in your services, just inject `Stopwatch` to service 16 | * where you need it. This trait is just for quick debug purposes and 17 | * nothing else. 18 | * 19 | * @package App\Helpers 20 | * @author TLe, Tarmo Leppänen 21 | */ 22 | trait StopwatchAwareTrait 23 | { 24 | protected ?Stopwatch $stopwatch = null; 25 | 26 | #[Required] 27 | public function setStopwatch(Stopwatch $stopwatch): self 28 | { 29 | $this->stopwatch = $stopwatch; 30 | 31 | return $this; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Kernel.php: -------------------------------------------------------------------------------- 1 | environment === 'dev') { 28 | $container->addCompilerPass(new StopwatchCompilerPass()); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Repository/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarlepp/symfony-flex-backend/ea11d123bc3a063ea0362fcf110d7cd50246b290/src/Repository/.gitignore -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/Admin/CountAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\Admin; 10 | 11 | use App\Enum\Role; 12 | use App\Rest\Traits\Methods\CountMethod; 13 | use Symfony\Component\HttpFoundation\Request; 14 | use Symfony\Component\HttpFoundation\Response; 15 | use Symfony\Component\Routing\Attribute\Route; 16 | use Symfony\Component\Security\Http\Attribute\IsGranted; 17 | use Throwable; 18 | 19 | /** 20 | * Trait to add 'countAction' for REST controllers for 'ROLE_ADMIN' users. 21 | * 22 | * @see \App\Rest\Traits\Methods\CountMethod for detailed documents. 23 | * 24 | * @package App\Rest\Traits\Actions\Admin 25 | * @author TLe, Tarmo Leppänen 26 | */ 27 | trait CountAction 28 | { 29 | use CountMethod; 30 | 31 | /** 32 | * @throws Throwable 33 | */ 34 | #[Route( 35 | path: '/count', 36 | methods: [Request::METHOD_GET], 37 | )] 38 | #[IsGranted(Role::ADMIN->value)] 39 | public function countAction(Request $request): Response 40 | { 41 | return $this->countMethod($request); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/Admin/CreateAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\Admin; 10 | 11 | use App\DTO\RestDtoInterface; 12 | use App\Enum\Role; 13 | use App\Rest\Traits\Methods\CreateMethod; 14 | use Symfony\Component\HttpFoundation\Request; 15 | use Symfony\Component\HttpFoundation\Response; 16 | use Symfony\Component\Routing\Attribute\Route; 17 | use Symfony\Component\Security\Http\Attribute\IsGranted; 18 | use Throwable; 19 | 20 | /** 21 | * Trait to add 'createAction' for REST controllers for 'ROLE_ADMIN' users. 22 | * 23 | * @see \App\Rest\Traits\Methods\CreateMethod for detailed documents. 24 | * 25 | * @package App\Rest\Traits\Actions\Admin 26 | * @author TLe, Tarmo Leppänen 27 | */ 28 | trait CreateAction 29 | { 30 | use CreateMethod; 31 | 32 | /** 33 | * @throws Throwable 34 | */ 35 | #[Route( 36 | path: '', 37 | methods: [Request::METHOD_POST], 38 | )] 39 | #[IsGranted(Role::ADMIN->value)] 40 | public function createAction(Request $request, RestDtoInterface $restDto): Response 41 | { 42 | return $this->createMethod($request, $restDto); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/Admin/FindAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\Admin; 10 | 11 | use App\Enum\Role; 12 | use App\Rest\Traits\Methods\FindMethod; 13 | use Symfony\Component\HttpFoundation\Request; 14 | use Symfony\Component\HttpFoundation\Response; 15 | use Symfony\Component\Routing\Attribute\Route; 16 | use Symfony\Component\Security\Http\Attribute\IsGranted; 17 | use Throwable; 18 | 19 | /** 20 | * Trait to add 'findAction' for REST controllers for 'ROLE_ADMIN' users. 21 | * 22 | * @see \App\Rest\Traits\Methods\FindMethod for detailed documents. 23 | * 24 | * @package App\Rest\Traits\Actions\Admin 25 | * @author TLe, Tarmo Leppänen 26 | */ 27 | trait FindAction 28 | { 29 | use FindMethod; 30 | 31 | /** 32 | * @throws Throwable 33 | */ 34 | #[Route( 35 | path: '', 36 | methods: [Request::METHOD_GET], 37 | )] 38 | #[IsGranted(Role::ADMIN->value)] 39 | public function findAction(Request $request): Response 40 | { 41 | return $this->findMethod($request); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/Admin/IdsAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\Admin; 10 | 11 | use App\Enum\Role; 12 | use App\Rest\Traits\Methods\IdsMethod; 13 | use Symfony\Component\HttpFoundation\Request; 14 | use Symfony\Component\HttpFoundation\Response; 15 | use Symfony\Component\Routing\Attribute\Route; 16 | use Symfony\Component\Security\Http\Attribute\IsGranted; 17 | use Throwable; 18 | 19 | /** 20 | * Trait to add 'idsAction' for REST controllers for 'ROLE_ADMIN' users. 21 | * 22 | * @see \App\Rest\Traits\Methods\IdsMethod for detailed documents. 23 | * 24 | * @package App\Rest\Traits\Actions\Admin 25 | * @author TLe, Tarmo Leppänen 26 | */ 27 | trait IdsAction 28 | { 29 | use IdsMethod; 30 | 31 | /** 32 | * @throws Throwable 33 | */ 34 | #[Route( 35 | path: '/ids', 36 | methods: [Request::METHOD_GET], 37 | )] 38 | #[IsGranted(Role::ADMIN->value)] 39 | public function idsAction(Request $request): Response 40 | { 41 | return $this->idsMethod($request); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/Anon/CountAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\Anon; 10 | 11 | use App\Rest\Traits\Methods\CountMethod; 12 | use Symfony\Component\HttpFoundation\Request; 13 | use Symfony\Component\HttpFoundation\Response; 14 | use Symfony\Component\Routing\Attribute\Route; 15 | use Throwable; 16 | 17 | /** 18 | * Trait to add 'countAction' for REST controllers for anonymous users. 19 | * 20 | * @see \App\Rest\Traits\Methods\CountMethod for detailed documents. 21 | * 22 | * @package App\Rest\Traits\Actions\Anon 23 | * @author TLe, Tarmo Leppänen 24 | */ 25 | trait CountAction 26 | { 27 | use CountMethod; 28 | 29 | /** 30 | * @throws Throwable 31 | */ 32 | #[Route( 33 | path: '/count', 34 | methods: [Request::METHOD_GET], 35 | )] 36 | public function countAction(Request $request): Response 37 | { 38 | return $this->countMethod($request); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/Anon/CreateAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\Anon; 10 | 11 | use App\DTO\RestDtoInterface; 12 | use App\Rest\Traits\Methods\CreateMethod; 13 | use Symfony\Component\HttpFoundation\Request; 14 | use Symfony\Component\HttpFoundation\Response; 15 | use Symfony\Component\Routing\Attribute\Route; 16 | use Throwable; 17 | 18 | /** 19 | * Trait to add 'createAction' for REST controllers for anonymous users. 20 | * 21 | * @see \App\Rest\Traits\Methods\CreateMethod for detailed documents. 22 | * 23 | * @package App\Rest\Traits\Actions\Anon 24 | * @author TLe, Tarmo Leppänen 25 | */ 26 | trait CreateAction 27 | { 28 | use CreateMethod; 29 | 30 | /** 31 | * @throws Throwable 32 | */ 33 | #[Route( 34 | path: '', 35 | methods: [Request::METHOD_POST], 36 | )] 37 | public function createAction(Request $request, RestDtoInterface $restDto): Response 38 | { 39 | return $this->createMethod($request, $restDto); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/Anon/DeleteAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\Anon; 10 | 11 | use App\Rest\Traits\Methods\DeleteMethod; 12 | use Symfony\Component\HttpFoundation\Request; 13 | use Symfony\Component\HttpFoundation\Response; 14 | use Symfony\Component\Routing\Attribute\Route; 15 | use Symfony\Component\Routing\Requirement\Requirement; 16 | use Throwable; 17 | 18 | /** 19 | * Trait to add 'deleteAction' for REST controllers for anonymous users. 20 | * 21 | * @see \App\Rest\Traits\Methods\DeleteMethod for detailed documents. 22 | * 23 | * @package App\Rest\Traits\Actions\Anon 24 | * @author TLe, Tarmo Leppänen 25 | */ 26 | trait DeleteAction 27 | { 28 | use DeleteMethod; 29 | 30 | /** 31 | * @throws Throwable 32 | */ 33 | #[Route( 34 | path: '/{id}', 35 | requirements: [ 36 | 'id' => Requirement::UUID_V1, 37 | ], 38 | methods: [Request::METHOD_DELETE], 39 | )] 40 | public function deleteAction(Request $request, string $id): Response 41 | { 42 | return $this->deleteMethod($request, $id); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/Anon/FindAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\Anon; 10 | 11 | use App\Rest\Traits\Methods\FindMethod; 12 | use Symfony\Component\HttpFoundation\Request; 13 | use Symfony\Component\HttpFoundation\Response; 14 | use Symfony\Component\Routing\Attribute\Route; 15 | use Throwable; 16 | 17 | /** 18 | * Trait to add 'findAction' for REST controllers for anonymous users. 19 | * 20 | * @see \App\Rest\Traits\Methods\FindMethod for detailed documents. 21 | * 22 | * @package App\Rest\Traits\Actions\Anon 23 | * @author TLe, Tarmo Leppänen 24 | */ 25 | trait FindAction 26 | { 27 | use FindMethod; 28 | 29 | /** 30 | * @throws Throwable 31 | */ 32 | #[Route( 33 | path: '', 34 | methods: [Request::METHOD_GET], 35 | )] 36 | public function findAction(Request $request): Response 37 | { 38 | return $this->findMethod($request); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/Anon/FindOneAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\Anon; 10 | 11 | use App\Rest\Traits\Methods\FindOneMethod; 12 | use Symfony\Component\HttpFoundation\Request; 13 | use Symfony\Component\HttpFoundation\Response; 14 | use Symfony\Component\Routing\Attribute\Route; 15 | use Symfony\Component\Routing\Requirement\Requirement; 16 | use Throwable; 17 | 18 | /** 19 | * Trait to add 'findOneAction' for REST controllers for anonymous users. 20 | * 21 | * @see \App\Rest\Traits\Methods\FindOneMethod for detailed documents. 22 | * 23 | * @package App\Rest\Traits\Actions\Anon 24 | * @author TLe, Tarmo Leppänen 25 | */ 26 | trait FindOneAction 27 | { 28 | use FindOneMethod; 29 | 30 | /** 31 | * @throws Throwable 32 | */ 33 | #[Route( 34 | path: '/{id}', 35 | requirements: [ 36 | 'id' => Requirement::UUID_V1, 37 | ], 38 | methods: [Request::METHOD_GET], 39 | )] 40 | public function findOneAction(Request $request, string $id): Response 41 | { 42 | return $this->findOneMethod($request, $id); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/Anon/IdsAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\Anon; 10 | 11 | use App\Rest\Traits\Methods\IdsMethod; 12 | use Symfony\Component\HttpFoundation\Request; 13 | use Symfony\Component\HttpFoundation\Response; 14 | use Symfony\Component\Routing\Attribute\Route; 15 | use Throwable; 16 | 17 | /** 18 | * Trait to add 'idsAction' for REST controllers for anonymous users. 19 | * 20 | * @see \App\Rest\Traits\Methods\IdsMethod for detailed documents. 21 | * 22 | * @package App\Rest\Traits\Actions\Anon 23 | * @author TLe, Tarmo Leppänen 24 | */ 25 | trait IdsAction 26 | { 27 | use IdsMethod; 28 | 29 | /** 30 | * @throws Throwable 31 | */ 32 | #[Route( 33 | path: '/ids', 34 | methods: [Request::METHOD_GET], 35 | )] 36 | public function idsAction(Request $request): Response 37 | { 38 | return $this->idsMethod($request); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/Logged/CountAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\Logged; 10 | 11 | use App\Enum\Role; 12 | use App\Rest\Traits\Methods\CountMethod; 13 | use Symfony\Component\HttpFoundation\Request; 14 | use Symfony\Component\HttpFoundation\Response; 15 | use Symfony\Component\Routing\Attribute\Route; 16 | use Symfony\Component\Security\Http\Attribute\IsGranted; 17 | use Throwable; 18 | 19 | /** 20 | * Trait to add 'countAction' for REST controllers for 'ROLE_LOGGED' users. 21 | * 22 | * @see \App\Rest\Traits\Methods\CountMethod for detailed documents. 23 | * 24 | * @package App\Rest\Traits\Actions\Logged 25 | * @author TLe, Tarmo Leppänen 26 | */ 27 | trait CountAction 28 | { 29 | use CountMethod; 30 | 31 | /** 32 | * @throws Throwable 33 | */ 34 | #[Route( 35 | path: '/count', 36 | methods: [Request::METHOD_GET], 37 | )] 38 | #[IsGranted(Role::LOGGED->value)] 39 | public function countAction(Request $request): Response 40 | { 41 | return $this->countMethod($request); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/Logged/FindAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\Logged; 10 | 11 | use App\Enum\Role; 12 | use App\Rest\Traits\Methods\FindMethod; 13 | use Symfony\Component\HttpFoundation\Request; 14 | use Symfony\Component\HttpFoundation\Response; 15 | use Symfony\Component\Routing\Attribute\Route; 16 | use Symfony\Component\Security\Http\Attribute\IsGranted; 17 | use Throwable; 18 | 19 | /** 20 | * Trait to add 'findAction' for REST controllers for 'ROLE_LOGGED' users. 21 | * 22 | * @see \App\Rest\Traits\Methods\FindMethod for detailed documents. 23 | * 24 | * @package App\Rest\Traits\Actions\Logged 25 | * @author TLe, Tarmo Leppänen 26 | */ 27 | trait FindAction 28 | { 29 | use FindMethod; 30 | 31 | /** 32 | * @throws Throwable 33 | */ 34 | #[Route( 35 | path: '', 36 | methods: [Request::METHOD_GET], 37 | )] 38 | #[IsGranted(Role::LOGGED->value)] 39 | public function findAction(Request $request): Response 40 | { 41 | return $this->findMethod($request); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/Logged/IdsAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\Logged; 10 | 11 | use App\Enum\Role; 12 | use App\Rest\Traits\Methods\IdsMethod; 13 | use Symfony\Component\HttpFoundation\Request; 14 | use Symfony\Component\HttpFoundation\Response; 15 | use Symfony\Component\Routing\Attribute\Route; 16 | use Symfony\Component\Security\Http\Attribute\IsGranted; 17 | use Throwable; 18 | 19 | /** 20 | * Trait to add 'idsAction' for REST controllers for 'ROLE_LOGGED' users. 21 | * 22 | * @see \App\Rest\Traits\Methods\IdsMethod for detailed documents. 23 | * 24 | * @package App\Rest\Traits\Actions\Logged 25 | * @author TLe, Tarmo Leppänen 26 | */ 27 | trait IdsAction 28 | { 29 | use IdsMethod; 30 | 31 | /** 32 | * @throws Throwable 33 | */ 34 | #[Route( 35 | path: '/ids', 36 | methods: [Request::METHOD_GET], 37 | )] 38 | #[IsGranted(Role::LOGGED->value)] 39 | public function idsAction(Request $request): Response 40 | { 41 | return $this->idsMethod($request); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/RestActionBase.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions; 10 | 11 | use App\Rest\Interfaces\RestResourceInterface; 12 | use Symfony\Component\HttpFoundation\Request; 13 | 14 | /** 15 | * @package App\Rest\Traits\Methods 16 | * @author TLe, Tarmo Leppänen 17 | */ 18 | trait RestActionBase 19 | { 20 | /** 21 | * @param array $allowedHttpMethods 22 | */ 23 | public function getResourceForMethod(Request $request, array $allowedHttpMethods): RestResourceInterface 24 | { 25 | // Make sure that we have everything we need to make this work 26 | $this->validateRestMethod($request, $allowedHttpMethods); 27 | 28 | // Get current resource service 29 | return $this->getResource(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/Root/CountAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\Root; 10 | 11 | use App\Enum\Role; 12 | use App\Rest\Traits\Methods\CountMethod; 13 | use Symfony\Component\HttpFoundation\Request; 14 | use Symfony\Component\HttpFoundation\Response; 15 | use Symfony\Component\Routing\Attribute\Route; 16 | use Symfony\Component\Security\Http\Attribute\IsGranted; 17 | use Throwable; 18 | 19 | /** 20 | * Trait to add 'countAction' for REST controllers for 'ROLE_ROOT' users. 21 | * 22 | * @see \App\Rest\Traits\Methods\CountMethod for detailed documents. 23 | * 24 | * @package App\Rest\Traits\Actions\Root 25 | * @author TLe, Tarmo Leppänen 26 | */ 27 | trait CountAction 28 | { 29 | use CountMethod; 30 | 31 | /** 32 | * @throws Throwable 33 | */ 34 | #[Route( 35 | path: '/count', 36 | methods: [Request::METHOD_GET], 37 | )] 38 | #[IsGranted(Role::ROOT->value)] 39 | public function countAction(Request $request): Response 40 | { 41 | return $this->countMethod($request); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/Root/CreateAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\Root; 10 | 11 | use App\DTO\RestDtoInterface; 12 | use App\Enum\Role; 13 | use App\Rest\Traits\Methods\CreateMethod; 14 | use Symfony\Component\HttpFoundation\Request; 15 | use Symfony\Component\HttpFoundation\Response; 16 | use Symfony\Component\Routing\Attribute\Route; 17 | use Symfony\Component\Security\Http\Attribute\IsGranted; 18 | use Throwable; 19 | 20 | /** 21 | * Trait to add 'createAction' for REST controllers for 'ROLE_ROOT' users. 22 | * 23 | * @see \App\Rest\Traits\Methods\CreateMethod for detailed documents. 24 | * 25 | * @package App\Rest\Traits\Actions\Root 26 | * @author TLe, Tarmo Leppänen 27 | */ 28 | trait CreateAction 29 | { 30 | use CreateMethod; 31 | 32 | /** 33 | * @throws Throwable 34 | */ 35 | #[Route( 36 | path: '', 37 | methods: [Request::METHOD_POST], 38 | )] 39 | #[IsGranted(Role::ROOT->value)] 40 | public function createAction(Request $request, RestDtoInterface $restDto): Response 41 | { 42 | return $this->createMethod($request, $restDto); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/Root/FindAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\Root; 10 | 11 | use App\Enum\Role; 12 | use App\Rest\Traits\Methods\FindMethod; 13 | use Symfony\Component\HttpFoundation\Request; 14 | use Symfony\Component\HttpFoundation\Response; 15 | use Symfony\Component\Routing\Attribute\Route; 16 | use Symfony\Component\Security\Http\Attribute\IsGranted; 17 | use Throwable; 18 | 19 | /** 20 | * Trait to add 'findAction' for REST controllers for 'ROLE_ROOT' users. 21 | * 22 | * @see \App\Rest\Traits\Methods\FindMethod for detailed documents. 23 | * 24 | * @package App\Rest\Traits\Actions\Root 25 | * @author TLe, Tarmo Leppänen 26 | */ 27 | trait FindAction 28 | { 29 | use FindMethod; 30 | 31 | /** 32 | * @throws Throwable 33 | */ 34 | #[Route( 35 | path: '', 36 | methods: [Request::METHOD_GET], 37 | )] 38 | #[IsGranted(Role::ROOT->value)] 39 | public function findAction(Request $request): Response 40 | { 41 | return $this->findMethod($request); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/Root/IdsAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\Root; 10 | 11 | use App\Enum\Role; 12 | use App\Rest\Traits\Methods\IdsMethod; 13 | use Symfony\Component\HttpFoundation\Request; 14 | use Symfony\Component\HttpFoundation\Response; 15 | use Symfony\Component\Routing\Attribute\Route; 16 | use Symfony\Component\Security\Http\Attribute\IsGranted; 17 | use Throwable; 18 | 19 | /** 20 | * Trait to add 'idsAction' for REST controllers for 'ROLE_ROOT' users. 21 | * 22 | * @see \App\Rest\Traits\Methods\IdsMethod for detailed documents. 23 | * 24 | * @package App\Rest\Traits\Actions\Root 25 | * @author TLe, Tarmo Leppänen 26 | */ 27 | trait IdsAction 28 | { 29 | use IdsMethod; 30 | 31 | /** 32 | * @throws Throwable 33 | */ 34 | #[Route( 35 | path: '/ids', 36 | methods: [Request::METHOD_GET], 37 | )] 38 | #[IsGranted(Role::ROOT->value)] 39 | public function idsAction(Request $request): Response 40 | { 41 | return $this->idsMethod($request); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/User/CountAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\User; 10 | 11 | use App\Enum\Role; 12 | use App\Rest\Traits\Methods\CountMethod; 13 | use Symfony\Component\HttpFoundation\Request; 14 | use Symfony\Component\HttpFoundation\Response; 15 | use Symfony\Component\Routing\Attribute\Route; 16 | use Symfony\Component\Security\Http\Attribute\IsGranted; 17 | use Throwable; 18 | 19 | /** 20 | * Trait to add 'countAction' for REST controllers for 'ROLE_USER' users. 21 | * 22 | * @see \App\Rest\Traits\Methods\CountMethod for detailed documents. 23 | * 24 | * @package App\Rest\Traits\Actions\User 25 | * @author TLe, Tarmo Leppänen 26 | */ 27 | trait CountAction 28 | { 29 | use CountMethod; 30 | 31 | /** 32 | * @throws Throwable 33 | */ 34 | #[Route( 35 | path: '/count', 36 | methods: [Request::METHOD_GET], 37 | )] 38 | #[IsGranted(Role::USER->value)] 39 | public function countAction(Request $request): Response 40 | { 41 | return $this->countMethod($request); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/User/CreateAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\User; 10 | 11 | use App\DTO\RestDtoInterface; 12 | use App\Enum\Role; 13 | use App\Rest\Traits\Methods\CreateMethod; 14 | use Symfony\Component\HttpFoundation\Request; 15 | use Symfony\Component\HttpFoundation\Response; 16 | use Symfony\Component\Routing\Attribute\Route; 17 | use Symfony\Component\Security\Http\Attribute\IsGranted; 18 | use Throwable; 19 | 20 | /** 21 | * Trait to add 'createAction' for REST controllers for 'ROLE_USER' users. 22 | * 23 | * @see \App\Rest\Traits\Methods\CreateMethod for detailed documents. 24 | * 25 | * @package App\Rest\Traits\Actions\User 26 | * @author TLe, Tarmo Leppänen 27 | */ 28 | trait CreateAction 29 | { 30 | use CreateMethod; 31 | 32 | /** 33 | * @throws Throwable 34 | */ 35 | #[Route( 36 | path: '', 37 | methods: [Request::METHOD_POST], 38 | )] 39 | #[IsGranted(Role::USER->value)] 40 | public function createAction(Request $request, RestDtoInterface $restDto): Response 41 | { 42 | return $this->createMethod($request, $restDto); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/User/FindAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\User; 10 | 11 | use App\Enum\Role; 12 | use App\Rest\Traits\Methods\FindMethod; 13 | use Symfony\Component\HttpFoundation\Request; 14 | use Symfony\Component\HttpFoundation\Response; 15 | use Symfony\Component\Routing\Attribute\Route; 16 | use Symfony\Component\Security\Http\Attribute\IsGranted; 17 | use Throwable; 18 | 19 | /** 20 | * Trait to add 'findAction' for REST controllers for 'ROLE_USER' users. 21 | * 22 | * @see \App\Rest\Traits\Methods\FindMethod for detailed documents. 23 | * 24 | * @package App\Rest\Traits\Actions\User 25 | * @author TLe, Tarmo Leppänen 26 | */ 27 | trait FindAction 28 | { 29 | use FindMethod; 30 | 31 | /** 32 | * @throws Throwable 33 | */ 34 | #[Route( 35 | path: '', 36 | methods: [Request::METHOD_GET], 37 | )] 38 | #[IsGranted(Role::USER->value)] 39 | public function findAction(Request $request): Response 40 | { 41 | return $this->findMethod($request); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Rest/Traits/Actions/User/IdsAction.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Actions\User; 10 | 11 | use App\Enum\Role; 12 | use App\Rest\Traits\Methods\IdsMethod; 13 | use Symfony\Component\HttpFoundation\Request; 14 | use Symfony\Component\HttpFoundation\Response; 15 | use Symfony\Component\Routing\Attribute\Route; 16 | use Symfony\Component\Security\Http\Attribute\IsGranted; 17 | use Throwable; 18 | 19 | /** 20 | * Trait to add 'idsAction' for REST controllers for 'ROLE_USER' users. 21 | * 22 | * @see \App\Rest\Traits\Methods\IdsMethod for detailed documents. 23 | * 24 | * @package App\Rest\Traits\Actions\User 25 | * @author TLe, Tarmo Leppänen 26 | */ 27 | trait IdsAction 28 | { 29 | use IdsMethod; 30 | 31 | /** 32 | * @throws Throwable 33 | */ 34 | #[Route( 35 | path: '/ids', 36 | methods: [Request::METHOD_GET], 37 | )] 38 | #[IsGranted(Role::USER->value)] 39 | public function idsAction(Request $request): Response 40 | { 41 | return $this->idsMethod($request); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Rest/Traits/Methods/DeleteMethod.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Methods; 10 | 11 | use Symfony\Component\HttpFoundation\Request; 12 | use Symfony\Component\HttpFoundation\Response; 13 | use Throwable; 14 | 15 | /** 16 | * @package App\Rest\Traits\Methods 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | trait DeleteMethod 20 | { 21 | /** 22 | * Generic 'deleteMethod' method for REST resources. 23 | * 24 | * @param array|null $allowedHttpMethods 25 | * 26 | * @throws Throwable 27 | */ 28 | public function deleteMethod(Request $request, string $id, ?array $allowedHttpMethods = null): Response 29 | { 30 | $resource = $this->getResourceForMethod($request, $allowedHttpMethods ?? [Request::METHOD_DELETE]); 31 | 32 | try { 33 | // Fetch data from database 34 | return $this 35 | ->getResponseHandler() 36 | ->createResponse($request, $resource->delete($id), $resource); 37 | } catch (Throwable $exception) { 38 | throw $this->handleRestMethodException($exception, $id); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Rest/Traits/Methods/RestMethodProcessCriteria.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits\Methods; 10 | 11 | use Symfony\Component\HttpFoundation\Request; 12 | 13 | /** 14 | * @package App\Rest\Traits\Methods 15 | * @author TLe, Tarmo Leppänen 16 | */ 17 | trait RestMethodProcessCriteria 18 | { 19 | /** 20 | * @param array> $criteria 21 | */ 22 | public function processCriteria(array &$criteria, Request $request, string $method): void 23 | { 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Rest/Traits/RestResourceCount.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits; 10 | 11 | /** 12 | * @SuppressWarnings("unused") 13 | * 14 | * @package App\Rest\Traits 15 | * @author TLe, Tarmo Leppänen 16 | */ 17 | trait RestResourceCount 18 | { 19 | /** 20 | * Before lifecycle method for count method. 21 | * 22 | * @param mixed[] $criteria 23 | * @param mixed[] $search 24 | */ 25 | public function beforeCount(array &$criteria, array &$search): void 26 | { 27 | } 28 | 29 | /** 30 | * Before lifecycle method for count method. 31 | * 32 | * @param mixed[] $criteria 33 | * @param mixed[] $search 34 | */ 35 | public function afterCount(array &$criteria, array &$search, int &$count): void 36 | { 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Rest/Traits/RestResourceFindOne.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits; 10 | 11 | use App\Entity\Interfaces\EntityInterface; 12 | 13 | /** 14 | * @SuppressWarnings("unused") 15 | * 16 | * @package App\Rest\Traits 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | trait RestResourceFindOne 20 | { 21 | /** 22 | * Before lifecycle method for findOne method. 23 | */ 24 | public function beforeFindOne(string &$id): void 25 | { 26 | } 27 | 28 | /** 29 | * After lifecycle method for findOne method. 30 | * 31 | * Notes: If you make changes to entity in this lifecycle method by default it will be saved on end of current 32 | * request. To prevent this you need to detach current entity from entity manager. 33 | * 34 | * Also note that if you've made some changes to entity and you eg. throw an exception within this method 35 | * your entity will be saved if it has eg Blameable / Timestampable traits attached. 36 | */ 37 | public function afterFindOne(string &$id, ?EntityInterface $entity = null): void 38 | { 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Rest/Traits/RestResourceIds.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits; 10 | 11 | /** 12 | * @SuppressWarnings("unused") 13 | * 14 | * @package App\Rest\Traits 15 | * @author TLe, Tarmo Leppänen 16 | */ 17 | trait RestResourceIds 18 | { 19 | /** 20 | * Before lifecycle method for ids method. 21 | * 22 | * @param mixed[] $criteria 23 | * @param mixed[] $search 24 | */ 25 | public function beforeIds(array &$criteria, array &$search): void 26 | { 27 | } 28 | 29 | /** 30 | * Before lifecycle method for ids method. 31 | * 32 | * @param mixed[] $criteria 33 | * @param mixed[] $search 34 | * @param string[] $ids 35 | */ 36 | public function afterIds(array &$criteria, array &$search, array &$ids): void 37 | { 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Rest/Traits/RestResourceLifeCycles.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Rest\Traits; 10 | 11 | /** 12 | * @package App\Rest\Traits 13 | * @author TLe, Tarmo Leppänen 14 | */ 15 | trait RestResourceLifeCycles 16 | { 17 | use RestResourceFind; 18 | use RestResourceFindOne; 19 | use RestResourceFindOneBy; 20 | use RestResourceCount; 21 | use RestResourceIds; 22 | use RestResourceCreate; 23 | use RestResourceUpdate; 24 | use RestResourcePatch; 25 | use RestResourceDelete; 26 | use RestResourceSave; 27 | } 28 | -------------------------------------------------------------------------------- /src/Security/Interfaces/ApiKeyUserInterface.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Security\Interfaces; 10 | 11 | use App\Entity\ApiKey; 12 | 13 | /** 14 | * @package App\Security 15 | * @author TLe, Tarmo Leppänen 16 | */ 17 | interface ApiKeyUserInterface 18 | { 19 | /** 20 | * @param array $roles 21 | */ 22 | public function __construct(ApiKey $apiKey, array $roles); 23 | } 24 | -------------------------------------------------------------------------------- /src/Security/Interfaces/ApiKeyUserProviderInterface.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Security\Interfaces; 10 | 11 | use App\Entity\ApiKey; 12 | use App\Repository\ApiKeyRepository; 13 | use App\Security\RolesService; 14 | 15 | /** 16 | * @package App\Security\Provider 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | interface ApiKeyUserProviderInterface 20 | { 21 | public function __construct(ApiKeyRepository $apiKeyRepository, RolesService $rolesService); 22 | 23 | /** 24 | * Method to fetch ApiKey entity for specified token. 25 | */ 26 | public function getApiKeyForToken(string $token): ?ApiKey; 27 | } 28 | -------------------------------------------------------------------------------- /src/Security/Interfaces/RolesServiceInterface.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Security\Interfaces; 10 | 11 | use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; 12 | 13 | /** 14 | * @package Security 15 | * @author TLe, Tarmo Leppänen 16 | */ 17 | interface RolesServiceInterface 18 | { 19 | public function __construct(RoleHierarchyInterface $roleHierarchy); 20 | 21 | /** 22 | * Getter method to return all roles in single dimensional array. 23 | * 24 | * @return array 25 | */ 26 | public function getRoles(): array; 27 | 28 | /** 29 | * Getter method for role label. 30 | */ 31 | public function getRoleLabel(string $role): string; 32 | 33 | /** 34 | * Getter method for short role. 35 | */ 36 | public function getShort(string $role): string; 37 | 38 | /** 39 | * Helper method to get inherited roles for given roles. 40 | * 41 | * @param array $roles 42 | * 43 | * @return array 44 | */ 45 | public function getInheritedRoles(array $roles): array; 46 | } 47 | -------------------------------------------------------------------------------- /src/Utils/HealthzService.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Utils; 10 | 11 | use App\Entity\Healthz; 12 | use App\Repository\HealthzRepository; 13 | use Throwable; 14 | 15 | /** 16 | * @package App\Utils 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | readonly class HealthzService 20 | { 21 | public function __construct( 22 | private HealthzRepository $repository, 23 | ) { 24 | } 25 | 26 | /** 27 | * Method to check that "all" is ok within our application. This will try 28 | * to do following: 29 | * 1) Remove data from database 30 | * 2) Create data to database 31 | * 3) Read data from database 32 | * 33 | * These steps should make sure that at least application database is 34 | * working as expected. 35 | * 36 | * @throws Throwable 37 | */ 38 | public function check(): ?Healthz 39 | { 40 | $this->repository->cleanup(); 41 | $this->repository->create(); 42 | 43 | return $this->repository->read(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Utils/Interfaces/LoginLoggerInterface.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Utils\Interfaces; 10 | 11 | use App\Entity\User; 12 | use App\Enum\LogLogin; 13 | use App\Resource\LogLoginResource; 14 | use Symfony\Component\HttpFoundation\RequestStack; 15 | use Throwable; 16 | 17 | /** 18 | * @package App\Utils 19 | * @author TLe, Tarmo Leppänen 20 | */ 21 | interface LoginLoggerInterface 22 | { 23 | public function __construct(LogLoginResource $logLoginFailureResource, RequestStack $requestStack); 24 | 25 | /** 26 | * Setter for User object (Entity). 27 | */ 28 | public function setUser(?User $user = null): self; 29 | 30 | /** 31 | * Method to handle login event. 32 | * 33 | * @throws Throwable 34 | */ 35 | public function process(LogLogin $type): void; 36 | } 37 | -------------------------------------------------------------------------------- /src/Validator/Constraints/Language.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Validator\Constraints; 10 | 11 | use Attribute; 12 | use Symfony\Component\Validator\Constraint; 13 | 14 | /** 15 | * Usage example; 16 | * App\Validator\Constraints\Language() 17 | * 18 | * Just add that to your property as an annotation and you're good to go. 19 | * 20 | * @Annotation 21 | * @Target({"PROPERTY"}) 22 | * 23 | * @package App\Validator\Constraints 24 | * @author TLe, Tarmo Leppänen 25 | */ 26 | #[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)] 27 | class Language extends Constraint 28 | { 29 | final public const string INVALID_LANGUAGE = '08bd61cf-ba27-45a3-9916-78c39253833a'; 30 | final public const string MESSAGE = 'This language "{{ language }}" is not valid.'; 31 | 32 | /** 33 | * {@inheritdoc} 34 | * 35 | * @psalm-var array 36 | */ 37 | protected const array ERROR_NAMES = [ 38 | self::INVALID_LANGUAGE => 'INVALID_LANGUAGE', 39 | ]; 40 | } 41 | -------------------------------------------------------------------------------- /src/Validator/Constraints/LanguageValidator.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Validator\Constraints; 10 | 11 | use App\Service\Localization; 12 | use Override; 13 | use Symfony\Component\Validator\Constraint; 14 | use Symfony\Component\Validator\ConstraintValidator; 15 | use function in_array; 16 | 17 | /** 18 | * @package App\Validator\Constraints 19 | * @author TLe, Tarmo Leppänen 20 | */ 21 | class LanguageValidator extends ConstraintValidator 22 | { 23 | public function __construct( 24 | private readonly Localization $localization, 25 | ) { 26 | } 27 | 28 | /** 29 | * {@inheritdoc} 30 | */ 31 | #[Override] 32 | public function validate(mixed $value, Constraint $constraint): void 33 | { 34 | if (in_array($value, $this->localization->getLanguages(), true) !== true) { 35 | $this->context 36 | ->buildViolation(Language::MESSAGE) 37 | ->setParameter('{{ language }}', (string)$value) 38 | ->setCode(Language::INVALID_LANGUAGE) 39 | ->addViolation(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Validator/Constraints/Locale.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Validator\Constraints; 10 | 11 | use Attribute; 12 | use Symfony\Component\Validator\Constraint; 13 | 14 | /** 15 | * Usage example; 16 | * App\Validator\Constraints\Locale() 17 | * 18 | * Just add that to your property as an annotation and you're good to go. 19 | * 20 | * @Annotation 21 | * @Target({"PROPERTY"}) 22 | * 23 | * @package App\Validator\Constraints 24 | * @author TLe, Tarmo Leppänen 25 | */ 26 | #[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)] 27 | class Locale extends Constraint 28 | { 29 | final public const string INVALID_LOCALE = '44e3862f-2d38-46d4-b1ae-632990814af6'; 30 | final public const string MESSAGE = 'This locale "{{ locale }}" is not valid.'; 31 | 32 | /** 33 | * {@inheritdoc} 34 | * 35 | * @psalm-var array 36 | */ 37 | protected const array ERROR_NAMES = [ 38 | self::INVALID_LOCALE => 'INVALID_LOCALE', 39 | ]; 40 | } 41 | -------------------------------------------------------------------------------- /src/Validator/Constraints/LocaleValidator.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Validator\Constraints; 10 | 11 | use App\Service\Localization; 12 | use Override; 13 | use Symfony\Component\Validator\Constraint; 14 | use Symfony\Component\Validator\ConstraintValidator; 15 | use function in_array; 16 | 17 | /** 18 | * @package App\Validator\Constraints 19 | * @author TLe, Tarmo Leppänen 20 | */ 21 | class LocaleValidator extends ConstraintValidator 22 | { 23 | public function __construct( 24 | private readonly Localization $localization, 25 | ) { 26 | } 27 | 28 | /** 29 | * {@inheritdoc} 30 | */ 31 | #[Override] 32 | public function validate(mixed $value, Constraint $constraint): void 33 | { 34 | if (in_array($value, $this->localization->getLocales(), true) !== true) { 35 | $this->context 36 | ->buildViolation(Locale::MESSAGE) 37 | ->setParameter('{{ locale }}', (string)$value) 38 | ->setCode(Locale::INVALID_LOCALE) 39 | ->addViolation(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Validator/Constraints/Timezone.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Validator\Constraints; 10 | 11 | use Attribute; 12 | use Symfony\Component\Validator\Constraint; 13 | 14 | /** 15 | * Usage example; 16 | * App\Validator\Constraints\Timezone() 17 | * 18 | * Just add that to your property as an annotation and you're good to go. 19 | * 20 | * @Annotation 21 | * @Target({"PROPERTY"}) 22 | * 23 | * @package App\Validator\Constraints 24 | * @author TLe, Tarmo Leppänen 25 | */ 26 | #[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)] 27 | class Timezone extends Constraint 28 | { 29 | final public const string INVALID_TIMEZONE = '1f8dd2a3-5b61-43ca-a6b2-af553f86ac17'; 30 | final public const string MESSAGE = 'This timezone "{{ timezone }}" is not valid.'; 31 | 32 | /** 33 | * {@inheritdoc} 34 | * 35 | * @psalm-var array 36 | */ 37 | protected const array ERROR_NAMES = [ 38 | self::INVALID_TIMEZONE => 'INVALID_TIMEZONE', 39 | ]; 40 | } 41 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarlepp/symfony-flex-backend/ea11d123bc3a063ea0362fcf110d7cd50246b290/src/favicon.ico -------------------------------------------------------------------------------- /templates/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarlepp/symfony-flex-backend/ea11d123bc3a063ea0362fcf110d7cd50246b290/templates/.gitignore -------------------------------------------------------------------------------- /templates/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarlepp/symfony-flex-backend/ea11d123bc3a063ea0362fcf110d7cd50246b290/templates/.gitkeep -------------------------------------------------------------------------------- /templates/Swagger/parameter_criteria.twig: -------------------------------------------------------------------------------- 1 | Used search criteria in request. 2 | 3 |

Usage examples:

4 |
{{ examples | join('
') | raw }}
5 | -------------------------------------------------------------------------------- /templates/Swagger/parameter_limit.twig: -------------------------------------------------------------------------------- 1 | Used limit option in request. 2 | 3 |

Usage examples:

4 |
{{ examples | join('
') | raw }}
5 | -------------------------------------------------------------------------------- /templates/Swagger/parameter_offset.twig: -------------------------------------------------------------------------------- 1 | Used offset option in request. 2 | 3 |

Usage examples:

4 |
{{ examples | join('
') | raw }}
5 | -------------------------------------------------------------------------------- /templates/Swagger/parameter_order.twig: -------------------------------------------------------------------------------- 1 | Used order in request. 2 | 3 |

Usage examples:

4 |
{{ examples | join('
') | raw }}
5 | 6 |

Advanced usage examples:

7 |
{{ advancedExamples | join('
') | raw }}
8 | -------------------------------------------------------------------------------- /templates/Swagger/parameter_populate.twig: -------------------------------------------------------------------------------- 1 | Used populate parts in request. 2 | 3 | {% if associations %} 4 |

Associations that can be used:

5 |
{{ associations | join('
') | raw }}
6 | {% endif %} 7 | 8 |

Usage examples:

9 |
{{ examples | join('
') | raw }}
10 | 11 |
12 | -------------------------------------------------------------------------------- /templates/Swagger/parameter_search.twig: -------------------------------------------------------------------------------- 1 | Used search terms in request. 2 | 3 |

Properties which affected:

4 |
{{ properties | join('
') | raw }}
5 | 6 |

Usage examples:

7 |
{{ examples | join('
') | raw }}
8 | -------------------------------------------------------------------------------- /tests/DataFixtures/AppFixtures.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\DataFixtures; 10 | 11 | use Doctrine\Bundle\FixturesBundle\Fixture; 12 | use Doctrine\Persistence\ObjectManager; 13 | use Override; 14 | 15 | /** 16 | * @package App\DataFixtures 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class AppFixtures extends Fixture 20 | { 21 | #[Override] 22 | public function load(ObjectManager $manager): void 23 | { 24 | $manager->flush(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/E2E/Controller/IndexControllerTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\E2E\Controller; 10 | 11 | use App\Tests\E2E\TestCase\WebTestCase; 12 | use PHPUnit\Framework\Attributes\TestDox; 13 | use Throwable; 14 | 15 | /** 16 | * @package App\Tests\E2E\Controller 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class IndexControllerTest extends WebTestCase 20 | { 21 | /** 22 | * @throws Throwable 23 | */ 24 | #[TestDox('Test that `GET /` request returns `200`')] 25 | public function testThatDefaultRouteReturns200(): void 26 | { 27 | $client = $this->getTestClient(); 28 | $client->request('GET', '/'); 29 | 30 | $response = $client->getResponse(); 31 | 32 | self::assertSame(200, $response->getStatusCode(), "Response:\n" . $response); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/E2E/DocumentationTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\E2E; 10 | 11 | use App\Tests\E2E\TestCase\WebTestCase; 12 | use PHPUnit\Framework\Attributes\TestDox; 13 | use Throwable; 14 | 15 | /** 16 | * @package App\Tests\Functional 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class DocumentationTest extends WebTestCase 20 | { 21 | /** 22 | * @throws Throwable 23 | */ 24 | #[TestDox('Test that `GET /api/doc` request returns `200`')] 25 | public function testThatDocumentationUiWorks(): void 26 | { 27 | $client = $this->getTestClient(); 28 | $client->request('GET', '/api/doc'); 29 | 30 | self::assertSame(200, $client->getResponse()->getStatusCode()); 31 | } 32 | 33 | /** 34 | * @throws Throwable 35 | */ 36 | #[TestDox('Test that `GET /api/doc.json` request returns `200`')] 37 | public function testThatDocumentationJsonWorks(): void 38 | { 39 | $client = $this->getTestClient(); 40 | $client->request('GET', '/api/doc.json'); 41 | 42 | self::assertSame(200, $client->getResponse()->getStatusCode()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/Functional/Repository/LogRequestRepositoryTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Functional\Repository; 10 | 11 | use App\Repository\LogRequestRepository; 12 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 13 | use Throwable; 14 | 15 | /** 16 | * @package App\Tests\Functional\Repository 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class LogRequestRepositoryTest extends KernelTestCase 20 | { 21 | /** 22 | * @throws Throwable 23 | */ 24 | public function testThatCleanHistoryReturnsExpected(): void 25 | { 26 | $repository = self::getContainer()->get(LogRequestRepository::class); 27 | 28 | self::assertSame(0, $repository->cleanHistory()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Integration/AutoMapper/User/AutoMapperConfigurationTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\AutoMapper\User; 10 | 11 | use App\AutoMapper\User\AutoMapperConfiguration; 12 | use App\AutoMapper\User\RequestMapper; 13 | use App\DTO\User\UserCreate; 14 | use App\DTO\User\UserPatch; 15 | use App\DTO\User\UserUpdate; 16 | use App\Tests\Integration\TestCase\RestRequestMapperConfigurationTestCase; 17 | 18 | /** 19 | * @package App\Tests\Integration\AutoMapper\User 20 | * @author TLe, Tarmo Leppänen 21 | */ 22 | class AutoMapperConfigurationTest extends RestRequestMapperConfigurationTestCase 23 | { 24 | /** 25 | * @var class-string 26 | */ 27 | protected string $autoMapperConfiguration = AutoMapperConfiguration::class; 28 | 29 | /** 30 | * @var class-string 31 | */ 32 | protected string $requestMapper = RequestMapper::class; 33 | 34 | /** 35 | * @var array 36 | */ 37 | protected static array $requestMapperClasses = [ 38 | UserCreate::class, 39 | UserUpdate::class, 40 | UserPatch::class, 41 | ]; 42 | } 43 | -------------------------------------------------------------------------------- /tests/Integration/AutoMapper/src/TestRestRequestMapper.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\AutoMapper\src; 10 | 11 | use App\AutoMapper\RestRequestMapper; 12 | use function str_rot13; 13 | 14 | /** 15 | * @package App\Tests\Integration\AutoMapper\src 16 | * @author TLe, Tarmo Leppänen 17 | */ 18 | class TestRestRequestMapper extends RestRequestMapper 19 | { 20 | /** 21 | * @var array 22 | */ 23 | protected static array $properties = [ 24 | 'someProperty', 25 | 'someTransformProperty', 26 | ]; 27 | 28 | public function transformSomeTransformProperty(string $input): string 29 | { 30 | return str_rot13($input); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/Integration/AutoMapper/src/TestRestRequestMapperWithoutProperties.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\AutoMapper\src; 10 | 11 | use App\AutoMapper\RestRequestMapper; 12 | 13 | /** 14 | * @package App\Tests\Integration\AutoMapper\src 15 | * @author TLe, Tarmo Leppänen 16 | */ 17 | class TestRestRequestMapperWithoutProperties extends RestRequestMapper 18 | { 19 | } 20 | -------------------------------------------------------------------------------- /tests/Integration/Controller/IndexControllerTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Controller; 10 | 11 | use App\Controller\IndexController; 12 | use PHPUnit\Framework\Attributes\TestDox; 13 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 14 | 15 | /** 16 | * @package App\Tests\Integration\Controller 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class IndexControllerTest extends KernelTestCase 20 | { 21 | #[TestDox('Test that `__invoke` method returns proper response')] 22 | public function testThatInvokeMethodReturnsExpectedResponse(): void 23 | { 24 | $response = (new IndexController())(); 25 | $content = $response->getContent(); 26 | 27 | self::assertSame(200, $response->getStatusCode()); 28 | self::assertNotFalse($content); 29 | self::assertJson($content); 30 | self::assertJsonStringEqualsJsonString('{}', $content); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/Integration/Controller/v1/ApiKey/ApiKeyControllerTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Controller\v1\ApiKey; 10 | 11 | use App\Controller\v1\ApiKey\ApiKeyController; 12 | use App\Resource\ApiKeyResource; 13 | use App\Tests\Integration\TestCase\RestIntegrationControllerTestCase; 14 | 15 | /** 16 | * @package App\Tests\Integration\Controller\v1 17 | * @author TLe, Tarmo Leppänen 18 | * 19 | * @method ApiKeyController getController() 20 | */ 21 | class ApiKeyControllerTest extends RestIntegrationControllerTestCase 22 | { 23 | /** 24 | * @var class-string 25 | */ 26 | protected string $controllerClass = ApiKeyController::class; 27 | 28 | /** 29 | * @var class-string 30 | */ 31 | protected string $resourceClass = ApiKeyResource::class; 32 | } 33 | -------------------------------------------------------------------------------- /tests/Integration/Controller/v1/Role/RoleControllerTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Controller\v1\Role; 10 | 11 | use App\Controller\v1\Role\RoleController; 12 | use App\Resource\RoleResource; 13 | use App\Tests\Integration\TestCase\RestIntegrationControllerTestCase; 14 | 15 | /** 16 | * @package App\Tests\Integration\Controller\v1\Role 17 | * @author TLe, Tarmo Leppänen 18 | * 19 | * @method RoleController getController() 20 | */ 21 | class RoleControllerTest extends RestIntegrationControllerTestCase 22 | { 23 | /** 24 | * @var class-string 25 | */ 26 | protected string $controllerClass = RoleController::class; 27 | 28 | /** 29 | * @var class-string 30 | */ 31 | protected string $resourceClass = RoleResource::class; 32 | } 33 | -------------------------------------------------------------------------------- /tests/Integration/Controller/v1/User/UserControllerTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Controller\v1\User; 10 | 11 | use App\Controller\v1\User\UserController; 12 | use App\Resource\UserResource; 13 | use App\Tests\Integration\TestCase\RestIntegrationControllerTestCase; 14 | 15 | /** 16 | * @package App\Tests\Integration\Controller\v1\User 17 | * @author TLe, Tarmo Leppänen 18 | * 19 | * @method UserController getController() 20 | */ 21 | class UserControllerTest extends RestIntegrationControllerTestCase 22 | { 23 | /** 24 | * @var class-string 25 | */ 26 | protected string $controllerClass = UserController::class; 27 | 28 | /** 29 | * @var class-string 30 | */ 31 | protected string $resourceClass = UserResource::class; 32 | } 33 | -------------------------------------------------------------------------------- /tests/Integration/Controller/v1/UserGroup/UserGroupControllerTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Controller\v1\UserGroup; 10 | 11 | use App\Controller\v1\UserGroup\UserGroupController; 12 | use App\Resource\UserGroupResource; 13 | use App\Tests\Integration\TestCase\RestIntegrationControllerTestCase; 14 | 15 | /** 16 | * @package App\Tests\Integration\Controller\v1\UserGroup 17 | * @author TLe, Tarmo Leppänen 18 | * 19 | * @method \App\Controller\v1\UserGroup\UserGroupController getController() 20 | */ 21 | class UserGroupControllerTest extends RestIntegrationControllerTestCase 22 | { 23 | /** 24 | * @var class-string 25 | */ 26 | protected string $controllerClass = UserGroupController::class; 27 | 28 | /** 29 | * @var class-string 30 | */ 31 | protected string $resourceClass = UserGroupResource::class; 32 | } 33 | -------------------------------------------------------------------------------- /tests/Integration/DTO/ApiKey/ApiKeyCreateTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\DTO\ApiKey; 10 | 11 | use App\DTO\ApiKey\ApiKeyCreate; 12 | use App\Tests\Integration\TestCase\DtoTestCase; 13 | 14 | /** 15 | * @package App\Tests\Integration\DTO\ApiKey 16 | * @author TLe, Tarmo Leppänen 17 | */ 18 | class ApiKeyCreateTest extends DtoTestCase 19 | { 20 | /** 21 | * @psalm-var class-string 22 | * @phpstan-var class-string 23 | */ 24 | protected static string $dtoClass = ApiKeyCreate::class; 25 | } 26 | -------------------------------------------------------------------------------- /tests/Integration/DTO/User/UserCreateTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\DTO\User; 10 | 11 | use App\DTO\User\UserCreate; 12 | use App\Tests\Integration\TestCase\DtoTestCase; 13 | 14 | /** 15 | * @package App\Tests\Integration\DTO\User 16 | * @author TLe, Tarmo Leppänen 17 | */ 18 | class UserCreateTest extends DtoTestCase 19 | { 20 | /** 21 | * @psalm-var class-string 22 | * @phpstan-var class-string 23 | */ 24 | protected static string $dtoClass = UserCreate::class; 25 | } 26 | -------------------------------------------------------------------------------- /tests/Integration/DTO/UserGroup/UserGroupCreateTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\DTO\UserGroup; 10 | 11 | use App\DTO\UserGroup\UserGroupCreate; 12 | use App\Tests\Integration\TestCase\DtoTestCase; 13 | 14 | /** 15 | * @package App\Tests\Integration\DTO\UserGroup 16 | * @author TLe, Tarmo Leppänen 17 | */ 18 | class UserGroupCreateTest extends DtoTestCase 19 | { 20 | /** 21 | * @psalm-var class-string 22 | * @phpstan-var class-string 23 | */ 24 | protected static string $dtoClass = UserGroupCreate::class; 25 | } 26 | -------------------------------------------------------------------------------- /tests/Integration/DTO/UserGroup/UserGroupPatchTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\DTO\UserGroup; 10 | 11 | use App\DTO\UserGroup\UserGroupPatch; 12 | use App\Tests\Integration\TestCase\DtoTestCase; 13 | 14 | /** 15 | * @package App\Tests\Integration\DTO\UserGroup 16 | * @author TLe, Tarmo Leppänen 17 | */ 18 | class UserGroupPatchTest extends DtoTestCase 19 | { 20 | /** 21 | * @psalm-var class-string 22 | * @phpstan-var class-string 23 | */ 24 | protected static string $dtoClass = UserGroupPatch::class; 25 | } 26 | -------------------------------------------------------------------------------- /tests/Integration/DTO/UserGroup/UserGroupUpdateTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\DTO\UserGroup; 10 | 11 | use App\DTO\UserGroup\UserGroupUpdate; 12 | use App\Tests\Integration\TestCase\DtoTestCase; 13 | 14 | /** 15 | * @package App\Tests\Integration\DTO\UserGroup 16 | * @author TLe, Tarmo Leppänen 17 | */ 18 | class UserGroupUpdateTest extends DtoTestCase 19 | { 20 | /** 21 | * @psalm-var class-string 22 | * @phpstan-var class-string 23 | */ 24 | protected static string $dtoClass = UserGroupUpdate::class; 25 | } 26 | -------------------------------------------------------------------------------- /tests/Integration/Entity/HealthzTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Entity; 10 | 11 | use App\Entity\Healthz; 12 | use App\Tests\Integration\TestCase\EntityTestCase; 13 | 14 | /** 15 | * @package App\Tests\Integration\Entity 16 | * @author TLe, Tarmo Leppänen 17 | * 18 | * @method Healthz getEntity() 19 | */ 20 | class HealthzTest extends EntityTestCase 21 | { 22 | /** 23 | * @var class-string 24 | */ 25 | protected static string $entityName = Healthz::class; 26 | } 27 | -------------------------------------------------------------------------------- /tests/Integration/Entity/RoleTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Entity; 10 | 11 | use App\Entity\Role; 12 | use App\Tests\Integration\TestCase\EntityTestCase; 13 | use Override; 14 | 15 | /** 16 | * @package App\Tests\Integration\Entity 17 | * @author TLe, Tarmo Leppänen 18 | * 19 | * @method Role getEntity() 20 | */ 21 | class RoleTest extends EntityTestCase 22 | { 23 | /** 24 | * @var class-string 25 | */ 26 | protected static string $entityName = Role::class; 27 | 28 | /** 29 | * @noinspection PhpMissingParentCallCommonInspection 30 | */ 31 | #[Override] 32 | public function testThatGetIdReturnsCorrectUuid(): void 33 | { 34 | self::markTestSkipped(); 35 | } 36 | 37 | /** 38 | * @noinspection PhpMissingParentCallCommonInspection 39 | */ 40 | #[Override] 41 | protected function createEntity(): Role 42 | { 43 | return new Role('Some role'); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/Integration/Entity/UserGroupTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Entity; 10 | 11 | use App\Entity\UserGroup; 12 | use App\Tests\Integration\TestCase\EntityTestCase; 13 | 14 | /** 15 | * @package App\Tests\Integration\Entity 16 | * @author TLe, Tarmo Leppänen 17 | * 18 | * @method UserGroup getEntity() 19 | */ 20 | class UserGroupTest extends EntityTestCase 21 | { 22 | /** 23 | * @var class-string 24 | */ 25 | protected static string $entityName = UserGroup::class; 26 | } 27 | -------------------------------------------------------------------------------- /tests/Integration/Helpers/src/LoggerAwareService.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Helpers\src; 10 | 11 | use App\Helpers\LoggerAwareTrait; 12 | 13 | /** 14 | * @package App\Tests\Integration\Helpers\src 15 | * @author TLe, Tarmo Leppänen 16 | */ 17 | class LoggerAwareService 18 | { 19 | use LoggerAwareTrait; 20 | 21 | public function __construct() 22 | { 23 | $this->logger = null; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/Integration/Helpers/src/StopwatchAwareService.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Helpers\src; 10 | 11 | use App\Helpers\StopwatchAwareTrait; 12 | 13 | /** 14 | * @package App\Tests\Integration\Helpers\src 15 | * @author TLe, Tarmo Leppänen 16 | */ 17 | class StopwatchAwareService 18 | { 19 | use StopwatchAwareTrait; 20 | 21 | public function __construct() 22 | { 23 | $this->stopwatch = null; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/Integration/Resource/ApiKeyResourceTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Resource; 10 | 11 | use App\Entity\ApiKey; 12 | use App\Entity\Interfaces\EntityInterface; 13 | use App\Repository\ApiKeyRepository; 14 | use App\Repository\BaseRepository; 15 | use App\Resource\ApiKeyResource; 16 | use App\Rest\RestResource; 17 | use App\Tests\Integration\TestCase\ResourceTestCase; 18 | 19 | /** 20 | * @package App\Tests\Integration\Resource 21 | * @author TLe, Tarmo Leppänen 22 | */ 23 | class ApiKeyResourceTest extends ResourceTestCase 24 | { 25 | /** 26 | * @var class-string 27 | */ 28 | protected string $entityClass = ApiKey::class; 29 | 30 | /** 31 | * @var class-string 32 | */ 33 | protected string $repositoryClass = ApiKeyRepository::class; 34 | 35 | /** 36 | * @var class-string 37 | */ 38 | protected string $resourceClass = ApiKeyResource::class; 39 | } 40 | -------------------------------------------------------------------------------- /tests/Integration/Resource/DateDimensionResourceTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Resource; 10 | 11 | use App\Entity\DateDimension; 12 | use App\Entity\Interfaces\EntityInterface; 13 | use App\Repository\BaseRepository; 14 | use App\Repository\DateDimensionRepository; 15 | use App\Resource\DateDimensionResource; 16 | use App\Rest\RestResource; 17 | use App\Tests\Integration\TestCase\ResourceTestCase; 18 | 19 | /** 20 | * @package App\Tests\Integration\Resource 21 | * @author TLe, Tarmo Leppänen 22 | */ 23 | class DateDimensionResourceTest extends ResourceTestCase 24 | { 25 | /** 26 | * @var class-string 27 | */ 28 | protected string $entityClass = DateDimension::class; 29 | 30 | /** 31 | * @var class-string 32 | */ 33 | protected string $repositoryClass = DateDimensionRepository::class; 34 | 35 | /** 36 | * @var class-string 37 | */ 38 | protected string $resourceClass = DateDimensionResource::class; 39 | } 40 | -------------------------------------------------------------------------------- /tests/Integration/Resource/HealthzResourceTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Resource; 10 | 11 | use App\Entity\Healthz; 12 | use App\Entity\Interfaces\EntityInterface; 13 | use App\Repository\BaseRepository; 14 | use App\Repository\HealthzRepository; 15 | use App\Resource\HealthzResource; 16 | use App\Rest\RestResource; 17 | use App\Tests\Integration\TestCase\ResourceTestCase; 18 | 19 | /** 20 | * @package App\Tests\Integration\Resource 21 | * @author TLe, Tarmo Leppänen 22 | */ 23 | class HealthzResourceTest extends ResourceTestCase 24 | { 25 | /** 26 | * @var class-string 27 | */ 28 | protected string $entityClass = Healthz::class; 29 | 30 | /** 31 | * @var class-string 32 | */ 33 | protected string $repositoryClass = HealthzRepository::class; 34 | 35 | /** 36 | * @var class-string 37 | */ 38 | protected string $resourceClass = HealthzResource::class; 39 | } 40 | -------------------------------------------------------------------------------- /tests/Integration/Resource/LogLoginResourceTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Resource; 10 | 11 | use App\Entity\Interfaces\EntityInterface; 12 | use App\Entity\LogLogin; 13 | use App\Repository\BaseRepository; 14 | use App\Repository\LogLoginRepository; 15 | use App\Resource\LogLoginResource; 16 | use App\Rest\RestResource; 17 | use App\Tests\Integration\TestCase\ResourceTestCase; 18 | 19 | /** 20 | * @package App\Tests\Integration\Resource 21 | * @author TLe, Tarmo Leppänen 22 | */ 23 | class LogLoginResourceTest extends ResourceTestCase 24 | { 25 | /** 26 | * @var class-string 27 | */ 28 | protected string $entityClass = LogLogin::class; 29 | 30 | /** 31 | * @var class-string 32 | */ 33 | protected string $repositoryClass = LogLoginRepository::class; 34 | 35 | /** 36 | * @var class-string 37 | */ 38 | protected string $resourceClass = LogLoginResource::class; 39 | } 40 | -------------------------------------------------------------------------------- /tests/Integration/Resource/LogRequestResourceTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Resource; 10 | 11 | use App\Entity\Interfaces\EntityInterface; 12 | use App\Entity\LogRequest; 13 | use App\Repository\BaseRepository; 14 | use App\Repository\LogRequestRepository; 15 | use App\Resource\LogRequestResource; 16 | use App\Rest\RestResource; 17 | use App\Tests\Integration\TestCase\ResourceTestCase; 18 | 19 | /** 20 | * @package App\Tests\Integration\Resource 21 | * @author TLe, Tarmo Leppänen 22 | */ 23 | class LogRequestResourceTest extends ResourceTestCase 24 | { 25 | /** 26 | * @var class-string 27 | */ 28 | protected string $entityClass = LogRequest::class; 29 | 30 | /** 31 | * @var class-string 32 | */ 33 | protected string $repositoryClass = LogRequestRepository::class; 34 | 35 | /** 36 | * @var class-string 37 | */ 38 | protected string $resourceClass = LogRequestResource::class; 39 | } 40 | -------------------------------------------------------------------------------- /tests/Integration/Resource/RoleResourceTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Resource; 10 | 11 | use App\Entity\Interfaces\EntityInterface; 12 | use App\Entity\Role; 13 | use App\Repository\BaseRepository; 14 | use App\Repository\RoleRepository; 15 | use App\Resource\RoleResource; 16 | use App\Rest\RestResource; 17 | use App\Tests\Integration\TestCase\ResourceTestCase; 18 | 19 | /** 20 | * @package App\Tests\Integration\Resource 21 | * @author TLe, Tarmo Leppänen 22 | */ 23 | class RoleResourceTest extends ResourceTestCase 24 | { 25 | /** 26 | * @var class-string 27 | */ 28 | protected string $entityClass = Role::class; 29 | 30 | /** 31 | * @var class-string 32 | */ 33 | protected string $repositoryClass = RoleRepository::class; 34 | 35 | /** 36 | * @var class-string 37 | */ 38 | protected string $resourceClass = RoleResource::class; 39 | } 40 | -------------------------------------------------------------------------------- /tests/Integration/Resource/UserGroupResourceTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Resource; 10 | 11 | use App\Entity\Interfaces\EntityInterface; 12 | use App\Entity\UserGroup; 13 | use App\Repository\BaseRepository; 14 | use App\Repository\UserGroupRepository; 15 | use App\Resource\UserGroupResource; 16 | use App\Rest\RestResource; 17 | use App\Tests\Integration\TestCase\ResourceTestCase; 18 | 19 | /** 20 | * @package App\Tests\Integration\Resource 21 | * @author TLe, Tarmo Leppänen 22 | */ 23 | class UserGroupResourceTest extends ResourceTestCase 24 | { 25 | /** 26 | * @var class-string 27 | */ 28 | protected string $entityClass = UserGroup::class; 29 | 30 | /** 31 | * @var class-string 32 | */ 33 | protected string $repositoryClass = UserGroupRepository::class; 34 | 35 | /** 36 | * @var class-string 37 | */ 38 | protected string $resourceClass = UserGroupResource::class; 39 | } 40 | -------------------------------------------------------------------------------- /tests/Integration/Rest/Traits/Methods/src/CountMethodTestClass.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Rest\Traits\Methods\src; 10 | 11 | use App\Rest\Controller; 12 | use App\Rest\Interfaces\ResponseHandlerInterface; 13 | use App\Rest\Interfaces\RestResourceInterface; 14 | use App\Rest\Traits\Methods\CountMethod; 15 | 16 | /** 17 | * Class CountMethodTestClass - just a dummy class so that we can actually test that trait. 18 | * 19 | * @package App\Tests\Integration\Rest\Traits\Methods\src 20 | * @author TLe, Tarmo Leppänen 21 | */ 22 | class CountMethodTestClass extends Controller 23 | { 24 | use CountMethod; 25 | 26 | public function __construct( 27 | RestResourceInterface $resource, 28 | ResponseHandlerInterface $responseHandler, 29 | ) { 30 | parent::__construct($resource); 31 | 32 | $this->responseHandler = $responseHandler; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Integration/Rest/Traits/Methods/src/CreateMethodTestClass.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Rest\Traits\Methods\src; 10 | 11 | use App\Rest\Controller; 12 | use App\Rest\Interfaces\ResponseHandlerInterface; 13 | use App\Rest\Interfaces\RestResourceInterface; 14 | use App\Rest\Traits\Methods\CreateMethod; 15 | 16 | /** 17 | * Class CreateMethodTestClass - just a dummy class so that we can actually test that trait. 18 | * 19 | * @package App\Tests\Integration\Rest\Traits\Methods\src 20 | * @author TLe, Tarmo Leppänen 21 | */ 22 | class CreateMethodTestClass extends Controller 23 | { 24 | use CreateMethod; 25 | 26 | public function __construct( 27 | RestResourceInterface $resource, 28 | ResponseHandlerInterface $responseHandler, 29 | ) { 30 | parent::__construct($resource); 31 | 32 | $this->responseHandler = $responseHandler; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Integration/Rest/Traits/Methods/src/DeleteMethodTestClass.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Rest\Traits\Methods\src; 10 | 11 | use App\Rest\Controller; 12 | use App\Rest\Interfaces\ResponseHandlerInterface; 13 | use App\Rest\Interfaces\RestResourceInterface; 14 | use App\Rest\Traits\Methods\DeleteMethod; 15 | 16 | /** 17 | * Class DeleteMethodTestClass - just a dummy class so that we can actually test that trait. 18 | * 19 | * @package App\Tests\Integration\Rest\Traits\Methods\src 20 | * @author TLe, Tarmo Leppänen 21 | */ 22 | class DeleteMethodTestClass extends Controller 23 | { 24 | use DeleteMethod; 25 | 26 | public function __construct( 27 | RestResourceInterface $resource, 28 | ResponseHandlerInterface $responseHandler, 29 | ) { 30 | parent::__construct($resource); 31 | 32 | $this->responseHandler = $responseHandler; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Integration/Rest/Traits/Methods/src/FindMethodTestClass.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Rest\Traits\Methods\src; 10 | 11 | use App\Rest\Controller; 12 | use App\Rest\Interfaces\ResponseHandlerInterface; 13 | use App\Rest\Interfaces\RestResourceInterface; 14 | use App\Rest\Traits\Methods\FindMethod; 15 | 16 | /** 17 | * Class FindMethodTestClass - just a dummy class so that we can actually test that trait. 18 | * 19 | * @package App\Tests\Integration\Rest\Traits\Methods\src 20 | * @author TLe, Tarmo Leppänen 21 | */ 22 | class FindMethodTestClass extends Controller 23 | { 24 | use FindMethod; 25 | 26 | public function __construct( 27 | RestResourceInterface $resource, 28 | ResponseHandlerInterface $responseHandler, 29 | ) { 30 | parent::__construct($resource); 31 | 32 | $this->responseHandler = $responseHandler; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Integration/Rest/Traits/Methods/src/FindOneMethodTestClass.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Rest\Traits\Methods\src; 10 | 11 | use App\Rest\Controller; 12 | use App\Rest\Interfaces\ResponseHandlerInterface; 13 | use App\Rest\Interfaces\RestResourceInterface; 14 | use App\Rest\Traits\Methods\FindOneMethod; 15 | 16 | /** 17 | * Class FindOneMethodTestClass - just a dummy class so that we can actually test that trait. 18 | * 19 | * @package App\Tests\Integration\Rest\Traits\Methods\src 20 | * @author TLe, Tarmo Leppänen 21 | */ 22 | class FindOneMethodTestClass extends Controller 23 | { 24 | use FindOneMethod; 25 | 26 | public function __construct( 27 | RestResourceInterface $resource, 28 | ResponseHandlerInterface $responseHandler, 29 | ) { 30 | parent::__construct($resource); 31 | 32 | $this->responseHandler = $responseHandler; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Integration/Rest/Traits/Methods/src/IdsMethodInvalidTestClass.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Rest\Traits\Methods\src; 10 | 11 | use App\Rest\Interfaces\ResponseHandlerInterface; 12 | use App\Rest\Interfaces\RestResourceInterface; 13 | use App\Rest\Traits\Actions\RestActionBase; 14 | use App\Rest\Traits\Methods\IdsMethod; 15 | use App\Rest\Traits\RestMethodHelper; 16 | use BadMethodCallException; 17 | 18 | /** 19 | * Class IdsMethodInvalidTestClass - just a dummy class so that we can actually test that trait. 20 | * 21 | * @package App\Tests\Integration\Rest\Traits\Methods\src 22 | * @author TLe, Tarmo Leppänen 23 | */ 24 | class IdsMethodInvalidTestClass 25 | { 26 | use IdsMethod; 27 | use RestActionBase; 28 | use RestMethodHelper; 29 | 30 | public function getResource(): RestResourceInterface 31 | { 32 | throw new BadMethodCallException('This method should not be called.'); 33 | } 34 | 35 | public function getResponseHandler(): ResponseHandlerInterface 36 | { 37 | throw new BadMethodCallException('This method should not be called.'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/Integration/Rest/Traits/Methods/src/IdsMethodTestClass.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Rest\Traits\Methods\src; 10 | 11 | use App\Rest\Controller; 12 | use App\Rest\Interfaces\ResponseHandlerInterface; 13 | use App\Rest\Interfaces\RestResourceInterface; 14 | use App\Rest\Traits\Methods\IdsMethod; 15 | 16 | /** 17 | * Class IdsMethodTestClass - just a dummy class so that we can actually test that trait. 18 | * 19 | * @package App\Tests\Integration\Rest\Traits\Methods\src 20 | * @author TLe, Tarmo Leppänen 21 | */ 22 | class IdsMethodTestClass extends Controller 23 | { 24 | use IdsMethod; 25 | 26 | public function __construct( 27 | RestResourceInterface $resource, 28 | ResponseHandlerInterface $responseHandler, 29 | ) { 30 | parent::__construct($resource); 31 | 32 | $this->responseHandler = $responseHandler; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Integration/Rest/Traits/Methods/src/PatchMethodTestClass.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Rest\Traits\Methods\src; 10 | 11 | use App\Rest\Controller; 12 | use App\Rest\Interfaces\ResponseHandlerInterface; 13 | use App\Rest\Interfaces\RestResourceInterface; 14 | use App\Rest\Traits\Methods\PatchMethod; 15 | 16 | /** 17 | * Class PatchMethodTestClass - just a dummy class so that we can actually test that trait. 18 | * 19 | * @package App\Tests\Integration\Rest\Traits\Methods\src 20 | * @author TLe, Tarmo Leppänen 21 | */ 22 | class PatchMethodTestClass extends Controller 23 | { 24 | use PatchMethod; 25 | 26 | public function __construct( 27 | RestResourceInterface $resource, 28 | ResponseHandlerInterface $responseHandler, 29 | ) { 30 | parent::__construct($resource); 31 | 32 | $this->responseHandler = $responseHandler; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Integration/Rest/Traits/Methods/src/UpdateMethodTestClass.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Rest\Traits\Methods\src; 10 | 11 | use App\Rest\Controller; 12 | use App\Rest\Interfaces\ResponseHandlerInterface; 13 | use App\Rest\Interfaces\RestResourceInterface; 14 | use App\Rest\Traits\Methods\UpdateMethod; 15 | 16 | /** 17 | * Class UpdateMethodTestClass - just a dummy class so that we can actually test that trait. 18 | * 19 | * @package App\Tests\Integration\Rest\Traits\Methods\src 20 | * @author TLe, Tarmo Leppänen 21 | */ 22 | class UpdateMethodTestClass extends Controller 23 | { 24 | use UpdateMethod; 25 | 26 | public function __construct( 27 | RestResourceInterface $resource, 28 | ResponseHandlerInterface $responseHandler, 29 | ) { 30 | parent::__construct($resource); 31 | 32 | $this->responseHandler = $responseHandler; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Integration/Validator/Constraints/src/TestConstraint.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Validator\Constraints\src; 10 | 11 | use Symfony\Component\Validator\Constraint; 12 | 13 | /** 14 | * @package App\Tests\Integration\Validator\Constraints\src 15 | * @author TLe, Tarmo Leppänen 16 | */ 17 | class TestConstraint extends Constraint 18 | { 19 | } 20 | -------------------------------------------------------------------------------- /tests/Integration/Validator/Constraints/src/TestEntityReference.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Integration\Validator\Constraints\src; 10 | 11 | use App\Entity\Interfaces\EntityInterface; 12 | use DateTimeImmutable; 13 | use Doctrine\ORM\EntityNotFoundException; 14 | use Override; 15 | 16 | /** 17 | * @package App\Tests\Integration\Validator\Constraints\src 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | class TestEntityReference implements EntityInterface 21 | { 22 | public function __construct( 23 | private readonly bool $throwException = false 24 | ) { 25 | } 26 | 27 | #[Override] 28 | public function getId(): string 29 | { 30 | return 'xxx'; 31 | } 32 | 33 | #[Override] 34 | public function getCreatedAt(): ?DateTimeImmutable 35 | { 36 | if ($this->throwException) { 37 | throw new EntityNotFoundException('Entity not found'); 38 | } 39 | 40 | return null; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/Unit/Entity/ApiKeyTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\Entity; 10 | 11 | use App\Entity\ApiKey; 12 | use App\Enum\Role; 13 | use PHPUnit\Framework\Attributes\TestDox; 14 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 15 | use function strlen; 16 | 17 | /** 18 | * @package App\Tests\Unit\Entity 19 | * @author TLe, Tarmo Leppänen 20 | */ 21 | class ApiKeyTest extends KernelTestCase 22 | { 23 | #[TestDox('Test that token is generated on creation of ApiKey entity')] 24 | public function testThatTokenIsGenerated(): void 25 | { 26 | self::assertSame(40, strlen((new ApiKey())->getToken())); 27 | } 28 | 29 | #[TestDox('Test that ApiKey entity has `ROLE_API` role')] 30 | public function testThatGetRolesContainsExpectedRole(): void 31 | { 32 | self::assertContainsEquals(Role::API->value, (new ApiKey())->getRoles()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Unit/Entity/RoleTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\Entity; 10 | 11 | use App\Entity\Role; 12 | use App\Entity\UserGroup; 13 | use PHPUnit\Framework\Attributes\TestDox; 14 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 15 | 16 | /** 17 | * @package App\Tests\Unit\Entity 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | class RoleTest extends KernelTestCase 21 | { 22 | #[TestDox('Test that `Role::getUserGroups` returns expected')] 23 | public function testThatGetUserGroupsWorksLikeExpected(): void 24 | { 25 | $userGroup = (new UserGroup()) 26 | ->setName('some name'); 27 | 28 | $role = new Role('some role'); 29 | $role->getUserGroups()->add($userGroup); 30 | 31 | self::assertTrue($role->getUserGroups()->contains($userGroup)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/Unit/Entity/UserGroupTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\Entity; 10 | 11 | use App\Entity\UserGroup; 12 | use PHPUnit\Framework\Attributes\TestDox; 13 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 14 | 15 | /** 16 | * @package App\Tests\Unit\Entity 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class UserGroupTest extends KernelTestCase 20 | { 21 | #[TestDox('Test that `UserGroup::__toString` method returns expected')] 22 | public function testThatToStringMethodReturnsExpected(): void 23 | { 24 | self::assertSame(UserGroup::class, (string)(new UserGroup())); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Unit/EventSubscriber/AcceptLanguageSubscriberTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\EventSubscriber; 10 | 11 | use App\EventSubscriber\AcceptLanguageSubscriber; 12 | use PHPUnit\Framework\Attributes\TestDox; 13 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 14 | use Symfony\Component\HttpKernel\Event\RequestEvent; 15 | 16 | /** 17 | * @package App\Tests\Unit\EventSubscriber 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | class AcceptLanguageSubscriberTest extends KernelTestCase 21 | { 22 | #[TestDox('Test that `getSubscribedEvents` method returns expected')] 23 | public function testThatGetSubscribedEventsReturnsExpected(): void 24 | { 25 | $expected = [ 26 | RequestEvent::class => [ 27 | 'onKernelRequest', 28 | 100, 29 | ], 30 | ]; 31 | 32 | self::assertSame($expected, AcceptLanguageSubscriber::getSubscribedEvents()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Unit/EventSubscriber/AuthenticationFailureSubscriberTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\EventSubscriber; 10 | 11 | use App\EventSubscriber\AuthenticationFailureSubscriber; 12 | use Lexik\Bundle\JWTAuthenticationBundle\Event\AuthenticationFailureEvent; 13 | use PHPUnit\Framework\Attributes\TestDox; 14 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 15 | 16 | /** 17 | * @package App\Tests\Unit\EventSubscriber 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | class AuthenticationFailureSubscriberTest extends KernelTestCase 21 | { 22 | #[TestDox('Test that `getSubscribedEvents` method returns expected')] 23 | public function testThatGetSubscribedEventsReturnsExpected(): void 24 | { 25 | $expected = [ 26 | AuthenticationFailureEvent::class => 'onAuthenticationFailure', 27 | 'lexik_jwt_authentication.on_authentication_failure' => 'onAuthenticationFailure', 28 | ]; 29 | 30 | self::assertSame($expected, AuthenticationFailureSubscriber::getSubscribedEvents()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/Unit/EventSubscriber/AuthenticationSuccessSubscriberTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\EventSubscriber; 10 | 11 | use App\EventSubscriber\AuthenticationSuccessSubscriber; 12 | use Lexik\Bundle\JWTAuthenticationBundle\Event\AuthenticationSuccessEvent; 13 | use PHPUnit\Framework\Attributes\TestDox; 14 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 15 | 16 | /** 17 | * @package App\Tests\Unit\EventSubscriber 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | class AuthenticationSuccessSubscriberTest extends KernelTestCase 21 | { 22 | #[TestDox('Test that `getSubscribedEvents` method returns expected')] 23 | public function testThatGetSubscribedEventsReturnsExpected(): void 24 | { 25 | $expected = [ 26 | AuthenticationSuccessEvent::class => 'onAuthenticationSuccess', 27 | 'lexik_jwt_authentication.on_authentication_success' => 'onAuthenticationSuccess', 28 | ]; 29 | 30 | self::assertSame($expected, AuthenticationSuccessSubscriber::getSubscribedEvents()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/Unit/EventSubscriber/BodySubscriberTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\EventSubscriber; 10 | 11 | use App\EventSubscriber\BodySubscriber; 12 | use PHPUnit\Framework\Attributes\TestDox; 13 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 14 | use Symfony\Component\HttpKernel\Event\RequestEvent; 15 | 16 | /** 17 | * @package App\Tests\Unit\EventSubscriber 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | class BodySubscriberTest extends KernelTestCase 21 | { 22 | #[TestDox('Test that `getSubscribedEvents` method returns expected')] 23 | public function testThatGetSubscribedEventsReturnsExpected(): void 24 | { 25 | $expected = [ 26 | RequestEvent::class => [ 27 | 'onKernelRequest', 28 | 10, 29 | ], 30 | ]; 31 | 32 | self::assertSame($expected, BodySubscriber::getSubscribedEvents()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Unit/EventSubscriber/DoctrineExtensionSubscriberTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\EventSubscriber; 10 | 11 | use App\EventSubscriber\DoctrineExtensionSubscriber; 12 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 13 | use Symfony\Component\HttpKernel\Event\RequestEvent; 14 | 15 | /** 16 | * @package App\Tests\Unit\EventSubscriber 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class DoctrineExtensionSubscriberTest extends KernelTestCase 20 | { 21 | public function testThatGetSubscribedEventsReturnsExpected(): void 22 | { 23 | $expected = [ 24 | RequestEvent::class => 'onKernelRequest', 25 | ]; 26 | 27 | self::assertSame($expected, DoctrineExtensionSubscriber::getSubscribedEvents()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/Unit/EventSubscriber/ExceptionSubscriberTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\EventSubscriber; 10 | 11 | use App\EventSubscriber\ExceptionSubscriber; 12 | use PHPUnit\Framework\Attributes\TestDox; 13 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 14 | use Symfony\Component\HttpKernel\Event\ExceptionEvent; 15 | 16 | /** 17 | * @package App\Tests\Unit\EventSubscriber 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | class ExceptionSubscriberTest extends KernelTestCase 21 | { 22 | #[TestDox('Test that `getSubscribedEvents` method returns expected')] 23 | public function testThatGetSubscribedEventsReturnsExpected(): void 24 | { 25 | $expected = [ 26 | ExceptionEvent::class => [ 27 | 'onKernelException', 28 | -100, 29 | ], 30 | ]; 31 | 32 | self::assertSame($expected, ExceptionSubscriber::getSubscribedEvents()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Unit/EventSubscriber/JWTCreatedSubscriberTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\EventSubscriber; 10 | 11 | use App\EventSubscriber\JWTCreatedSubscriber; 12 | use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTCreatedEvent; 13 | use PHPUnit\Framework\Attributes\TestDox; 14 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 15 | 16 | /** 17 | * @package App\Tests\Unit\EventSubscriber 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | class JWTCreatedSubscriberTest extends KernelTestCase 21 | { 22 | #[TestDox('Test that `getSubscribedEvents` method returns expected')] 23 | public function testThatGetSubscribedEventsReturnsExpected(): void 24 | { 25 | $expected = [ 26 | JWTCreatedEvent::class => 'onJWTCreated', 27 | 'lexik_jwt_authentication.on_jwt_created' => 'onJWTCreated', 28 | ]; 29 | 30 | self::assertSame($expected, JWTCreatedSubscriber::getSubscribedEvents()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/Unit/EventSubscriber/JWTDecodedSubscriberTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\EventSubscriber; 10 | 11 | use App\EventSubscriber\JWTDecodedSubscriber; 12 | use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTDecodedEvent; 13 | use PHPUnit\Framework\Attributes\TestDox; 14 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 15 | 16 | /** 17 | * @package App\Tests\Unit\EventSubscriber 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | class JWTDecodedSubscriberTest extends KernelTestCase 21 | { 22 | #[TestDox('Test that `getSubscribedEvents` method returns expected')] 23 | public function testThatGetSubscribedEventsReturnsExpected(): void 24 | { 25 | $expected = [ 26 | JWTDecodedEvent::class => 'onJWTDecoded', 27 | 'lexik_jwt_authentication.on_jwt_decoded' => 'onJWTDecoded', 28 | ]; 29 | 30 | self::assertSame($expected, JWTDecodedSubscriber::getSubscribedEvents()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/Unit/EventSubscriber/RequestLogSubscriberTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\EventSubscriber; 10 | 11 | use App\EventSubscriber\RequestLogSubscriber; 12 | use PHPUnit\Framework\Attributes\TestDox; 13 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 14 | use Symfony\Component\HttpKernel\Event\TerminateEvent; 15 | 16 | /** 17 | * @package App\Tests\Unit\EventSubscriber 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | class RequestLogSubscriberTest extends KernelTestCase 21 | { 22 | #[TestDox('Test that `getSubscribedEvents` method returns expected')] 23 | public function testThatGetSubscribedEventsReturnsExpected(): void 24 | { 25 | $expected = [ 26 | TerminateEvent::class => [ 27 | 'onTerminateEvent', 28 | 15, 29 | ], 30 | ]; 31 | 32 | self::assertSame($expected, RequestLogSubscriber::getSubscribedEvents()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Unit/EventSubscriber/ResponseSubscriberTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\EventSubscriber; 10 | 11 | use App\EventSubscriber\ResponseSubscriber; 12 | use PHPUnit\Framework\Attributes\TestDox; 13 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 14 | use Symfony\Component\HttpKernel\Event\ResponseEvent; 15 | 16 | /** 17 | * @package App\Tests\Unit\EventSubscriber 18 | * @author TLe, Tarmo Leppänen 19 | */ 20 | class ResponseSubscriberTest extends KernelTestCase 21 | { 22 | #[TestDox('Test that `getSubscribedEvents` method returns expected')] 23 | public function testThatGetSubscribedEventsReturnsExpected(): void 24 | { 25 | $expected = [ 26 | ResponseEvent::class => [ 27 | 'onKernelResponse', 28 | 10, 29 | ], 30 | ]; 31 | 32 | self::assertSame($expected, ResponseSubscriber::getSubscribedEvents()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Unit/Validator/Constraints/EntityReferenceExistsTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\Validator\Constraints; 10 | 11 | use App\Validator\Constraints\EntityReferenceExists; 12 | use PHPUnit\Framework\Attributes\TestDox; 13 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 14 | 15 | /** 16 | * @package App\Tests\Unit\Validator\Constraints 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class EntityReferenceExistsTest extends KernelTestCase 20 | { 21 | #[TestDox('Test that `getTargets` method returns expected')] 22 | public function testThatGetTargetsReturnsExpected(): void 23 | { 24 | self::assertSame('property', (new EntityReferenceExists())->getTargets()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Unit/Validator/Constraints/LanguageTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\Validator\Constraints; 10 | 11 | use App\Validator\Constraints\Language; 12 | use PHPUnit\Framework\Attributes\TestDox; 13 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 14 | 15 | /** 16 | * @package App\Tests\Unit\Validator\Constraints 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class LanguageTest extends KernelTestCase 20 | { 21 | #[TestDox('Test that `getTargets` method returns expected')] 22 | public function testThatGetTargetsReturnsExpected(): void 23 | { 24 | self::assertSame('property', (new Language())->getTargets()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Unit/Validator/Constraints/LocaleTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\Validator\Constraints; 10 | 11 | use App\Validator\Constraints\Locale; 12 | use PHPUnit\Framework\Attributes\TestDox; 13 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 14 | 15 | /** 16 | * @package App\Tests\Unit\Validator\Constraints 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class LocaleTest extends KernelTestCase 20 | { 21 | #[TestDox('Test that `getTargets` method returns expected')] 22 | public function testThatGetTargetsReturnsExpected(): void 23 | { 24 | self::assertSame('property', (new Locale())->getTargets()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Unit/Validator/Constraints/TimezoneTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\Validator\Constraints; 10 | 11 | use App\Validator\Constraints\Timezone; 12 | use PHPUnit\Framework\Attributes\TestDox; 13 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 14 | 15 | /** 16 | * @package App\Tests\Unit\Validator\Constraints 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class TimezoneTest extends KernelTestCase 20 | { 21 | #[TestDox('Test that `getTargets` method returns expected')] 22 | public function testThatGetTargetsReturnsExpected(): void 23 | { 24 | self::assertSame('property', (new Timezone())->getTargets()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Unit/Validator/Constraints/UniqueEmailTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\Validator\Constraints; 10 | 11 | use App\Validator\Constraints\UniqueEmail; 12 | use PHPUnit\Framework\Attributes\TestDox; 13 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 14 | 15 | /** 16 | * @package App\Tests\Unit\Validator\Constraints 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class UniqueEmailTest extends KernelTestCase 20 | { 21 | #[TestDox('Test that `getTargets` method returns expected')] 22 | public function testThatGetTargetsReturnsExpected(): void 23 | { 24 | self::assertSame('class', (new UniqueEmail())->getTargets()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Unit/Validator/Constraints/UniqueUsernameTest.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Unit\Validator\Constraints; 10 | 11 | use App\Validator\Constraints\UniqueUsername; 12 | use PHPUnit\Framework\Attributes\TestDox; 13 | use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 14 | 15 | /** 16 | * @package App\Tests\Unit\Validator\Constraints 17 | * @author TLe, Tarmo Leppänen 18 | */ 19 | class UniqueUsernameTest extends KernelTestCase 20 | { 21 | #[TestDox('Test that `getTargets` method returns expected')] 22 | public function testThatGetTargetsReturnsExpected(): void 23 | { 24 | self::assertSame('class', (new UniqueUsername())->getTargets()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Utils/StringableArrayObject.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace App\Tests\Utils; 10 | 11 | use App\Utils\JSON; 12 | use ArrayObject; 13 | use JsonException; 14 | use Override; 15 | use Stringable; 16 | 17 | /** 18 | * @psalm-suppress MissingTemplateParam 19 | * 20 | * @package App\Tests\Utils 21 | * @author TLe, Tarmo Leppänen 22 | */ 23 | class StringableArrayObject extends ArrayObject implements Stringable 24 | { 25 | /** 26 | * @throws JsonException 27 | */ 28 | #[Override] 29 | public function __toString(): string 30 | { 31 | $iterator = static fn (mixed $input): mixed => $input instanceof Stringable ? (string)$input : $input; 32 | 33 | return JSON::encode(array_map($iterator, $this->getArrayCopy())); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/bootstrap_fastest.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | $files = glob(sprintf('%s%stest_database_cache*', sys_get_temp_dir(), DIRECTORY_SEPARATOR)); 10 | 11 | is_array($files) ? array_map('unlink', $files) : throw new RuntimeException('Cannot real cache files...'); 12 | -------------------------------------------------------------------------------- /tools/02_phpstan/.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /tools/02_phpstan/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tarlepp/symfony-flex-backend-tools", 3 | "description": "", 4 | "version": "1.0.0", 5 | "require": { 6 | "php": "^8.4.0" 7 | }, 8 | "require-dev": { 9 | "phpstan/phpstan": "2.1.17", 10 | "phpstan/phpstan-deprecation-rules": "2.0.3", 11 | "phpstan/phpstan-phpunit": "2.0.6", 12 | "phpstan/phpstan-symfony": "2.0.6", 13 | "roave/security-advisories": "dev-latest" 14 | }, 15 | "config": { 16 | "allow-plugins": true, 17 | "platform": { 18 | "php": "8.4.6" 19 | }, 20 | "preferred-install": { 21 | "*": "dist" 22 | }, 23 | "sort-packages": true 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tools/03_psalm/.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /tools/03_psalm/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tarlepp/symfony-flex-backend-tools", 3 | "description": "", 4 | "version": "1.0.0", 5 | "require": { 6 | "php": "^8.3.0" 7 | }, 8 | "require-dev": { 9 | "roave/security-advisories": "dev-latest", 10 | "psalm/plugin-phpunit": "0.19.5", 11 | "psalm/plugin-symfony": "5.2.7", 12 | "vimeo/psalm": "6.11.0", 13 | "weirdan/doctrine-psalm-plugin": "2.10.0" 14 | }, 15 | "config": { 16 | "allow-plugins": true, 17 | "platform": { 18 | "php": "8.4.6" 19 | }, 20 | "preferred-install": { 21 | "*": "dist" 22 | }, 23 | "sort-packages": true 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tools/04_symplify/.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /tools/04_symplify/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tarlepp/symfony-flex-backend-tools", 3 | "description": "", 4 | "version": "1.0.0", 5 | "require": { 6 | "php": "^8.4.0" 7 | }, 8 | "require-dev": { 9 | "friendsofphp/php-cs-fixer": "3.75.0", 10 | "roave/security-advisories": "dev-latest", 11 | "symplify/config-transformer": "12.4.0", 12 | "symplify/easy-coding-standard": "12.5.18" 13 | }, 14 | "config": { 15 | "allow-plugins": true, 16 | "platform": { 17 | "php": "8.4.6" 18 | }, 19 | "preferred-install": { 20 | "*": "dist" 21 | }, 22 | "sort-packages": true 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tools/05_infection/.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /tools/05_infection/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tarlepp/symfony-flex-backend-tools", 3 | "description": "", 4 | "version": "1.0.0", 5 | "require": { 6 | "php": "^8.4.0" 7 | }, 8 | "require-dev": { 9 | "infection/infection": "0.29.14", 10 | "roave/security-advisories": "dev-latest" 11 | }, 12 | "config": { 13 | "allow-plugins": true, 14 | "platform": { 15 | "php": "8.4.6" 16 | }, 17 | "preferred-install": { 18 | "*": "dist" 19 | }, 20 | "sort-packages": true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tools/06_php-coveralls/.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /tools/06_php-coveralls/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tarlepp/symfony-flex-backend-tools", 3 | "description": "", 4 | "version": "1.0.0", 5 | "require": { 6 | "php": "^8.4.0" 7 | }, 8 | "require-dev": { 9 | "php-coveralls/php-coveralls": "2.8.0", 10 | "roave/security-advisories": "dev-latest" 11 | }, 12 | "config": { 13 | "allow-plugins": true, 14 | "platform": { 15 | "php": "8.4.6" 16 | }, 17 | "preferred-install": { 18 | "*": "dist" 19 | }, 20 | "sort-packages": true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tools/07_phpinsights/.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /tools/07_phpinsights/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tarlepp/symfony-flex-backend-tools", 3 | "description": "", 4 | "version": "1.0.0", 5 | "require": { 6 | "php": "^8.4.0" 7 | }, 8 | "require-dev": { 9 | "nunomaduro/phpinsights": "2.13.1", 10 | "roave/security-advisories": "dev-latest" 11 | }, 12 | "config": { 13 | "allow-plugins": true, 14 | "platform": { 15 | "php": "8.4.6" 16 | }, 17 | "preferred-install": { 18 | "*": "dist" 19 | }, 20 | "sort-packages": true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tools/08_phpmetrics/.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /tools/08_phpmetrics/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tarlepp/symfony-flex-backend-tools", 3 | "description": "", 4 | "version": "1.0.0", 5 | "require": { 6 | "php": "^8.4.0" 7 | }, 8 | "require-dev": { 9 | "phpmetrics/phpmetrics": "2.8.2", 10 | "roave/security-advisories": "dev-latest" 11 | }, 12 | "config": { 13 | "allow-plugins": true, 14 | "platform": { 15 | "php": "8.4.6" 16 | }, 17 | "preferred-install": { 18 | "*": "dist" 19 | }, 20 | "sort-packages": true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tools/09_rector/.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /tools/09_rector/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tarlepp/symfony-flex-backend-tools", 3 | "description": "", 4 | "version": "1.0.0", 5 | "require": { 6 | "php": "^8.4.0" 7 | }, 8 | "require-dev": { 9 | "rector/rector": "2.0.16", 10 | "roave/security-advisories": "dev-latest" 11 | }, 12 | "config": { 13 | "allow-plugins": true, 14 | "platform": { 15 | "php": "8.4.6" 16 | }, 17 | "preferred-install": { 18 | "*": "dist" 19 | }, 20 | "sort-packages": true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tools/10_composer/.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /tools/10_composer/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tarlepp/symfony-flex-backend-tools", 3 | "description": "", 4 | "version": "1.0.0", 5 | "require": { 6 | "php": "^8.4.0" 7 | }, 8 | "require-dev": { 9 | "ergebnis/composer-normalize": "2.47.0", 10 | "icanhazstring/composer-unused": "0.9.3", 11 | "maglnet/composer-require-checker": "4.16.1", 12 | "roave/security-advisories": "dev-latest" 13 | }, 14 | "config": { 15 | "allow-plugins": true, 16 | "platform": { 17 | "php": "8.4.6" 18 | }, 19 | "preferred-install": { 20 | "*": "dist" 21 | }, 22 | "sort-packages": true 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tools/11_phplint/.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /tools/11_phplint/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tarlepp/symfony-flex-backend-tools", 3 | "description": "", 4 | "version": "1.0.0", 5 | "require": { 6 | "php": "^8.4.0" 7 | }, 8 | "require-dev": { 9 | "overtrue/phplint": "9.6.2", 10 | "roave/security-advisories": "dev-latest" 11 | }, 12 | "config": { 13 | "allow-plugins": true, 14 | "platform": { 15 | "php": "8.4.6" 16 | }, 17 | "preferred-install": { 18 | "*": "dist" 19 | }, 20 | "sort-packages": true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tools/12_php-parallel-lint/.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /tools/12_php-parallel-lint/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tarlepp/symfony-flex-backend-tools", 3 | "description": "", 4 | "version": "1.0.0", 5 | "require": { 6 | "php": "^8.4.0" 7 | }, 8 | "require-dev": { 9 | "php-parallel-lint/php-console-highlighter": "1.0.0", 10 | "php-parallel-lint/php-parallel-lint": "1.4.0", 11 | "roave/security-advisories": "dev-latest" 12 | }, 13 | "config": { 14 | "allow-plugins": true, 15 | "platform": { 16 | "php": "8.4.6" 17 | }, 18 | "preferred-install": { 19 | "*": "dist" 20 | }, 21 | "sort-packages": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /translations/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarlepp/symfony-flex-backend/ea11d123bc3a063ea0362fcf110d7cd50246b290/translations/.gitignore -------------------------------------------------------------------------------- /translations/security+intl-icu.fi.xlf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 |
7 | 8 | 9 | Invalid credentials. 10 | Virheelliset käyttäjätunnukset. 11 | 12 | 13 |
14 |
15 | --------------------------------------------------------------------------------