From cd97f672a616b2c8b52e794fbd4bb052ea996a84 Mon Sep 17 00:00:00 2001 From: Jan Cizmar Date: Sat, 30 Dec 2023 18:04:50 +0100 Subject: [PATCH] fix: Snyk security issues (minor), updated ktlint --- .editorconfig | 6 +- .github/workflows/test.yml | 2 +- .../controllers/AdministrationController.kt | 37 +- .../api/v2/controllers/AllKeysController.kt | 2 +- .../v2/controllers/AnnouncementController.kt | 4 +- .../api/v2/controllers/ApiKeyController.kt | 100 +- .../controllers/AutoTranslationController.kt | 38 +- .../api/v2/controllers/BigMetaController.kt | 9 +- .../v2/controllers/BusinessEventController.kt | 8 +- .../v2/controllers/ConfigurationController.kt | 78 +- .../v2/controllers/InitialDataController.kt | 17 +- .../api/v2/controllers/KeyController.kt | 84 +- .../v2/controllers/KeyScreenshotController.kt | 17 +- .../MachineTranslationSettingsController.kt | 6 +- .../api/v2/controllers/MtCreditsController.kt | 21 +- .../api/v2/controllers/NamespaceController.kt | 19 +- .../api/v2/controllers/PatController.kt | 29 +- .../PreferredOrganizationController.kt | 9 +- .../controllers/ProjectActivityController.kt | 4 +- .../v2/controllers/ProjectStatsController.kt | 11 +- .../v2/controllers/QuickStartController.kt | 15 +- .../api/v2/controllers/ScopeInfoController.kt | 8 +- .../api/v2/controllers/SlugController.kt | 11 +- .../api/v2/controllers/TagsController.kt | 25 +- .../api/v2/controllers/UserMfaController.kt | 19 +- .../controllers/UserPreferencesController.kt | 6 +- .../v2/controllers/V2ImageUploadController.kt | 10 +- .../api/v2/controllers/V2ImportController.kt | 145 +- .../v2/controllers/V2InvitationController.kt | 17 +- .../v2/controllers/V2LanguagesController.kt | 24 +- .../v2/controllers/V2ProjectsController.kt | 97 +- .../V2ProjectsInvitationController.kt | 35 +- .../api/v2/controllers/V2UserController.kt | 36 +- .../batch/BatchJobManagementController.kt | 47 +- .../batch/StartBatchJobController.kt | 55 +- .../controllers/batch/V2ExportController.kt | 39 +- .../ConfigurationDocumentationProvider.kt | 61 +- .../ConfigurationPropsController.kt | 2 +- .../v2/controllers/configurationProps/data.kt | 2 +- .../ContentDeliveryConfigController.kt | 28 +- .../organization/OrganizationController.kt | 91 +- .../OrganizationProjectController.kt | 24 +- .../MachineTranslationSuggestionFacade.kt | 40 +- .../suggestion/MtResultStreamer.kt | 22 +- .../TranslationSuggestionController.kt | 43 +- .../TranslationCommentController.kt | 49 +- .../translation/TranslationsController.kt | 170 +- .../tolgee/component/KeyComplexEditHelper.kt | 75 +- .../io/tolgee/component/LanguageValidator.kt | 30 +- .../component/PreferredOrganizationFacade.kt | 5 +- .../ProjectTranslationLastModifiedManager.kt | 3 +- .../component/TolgeeCacheErrorHandler.kt | 6 +- .../TransferEncodingHeaderDebugFilter.kt | 6 +- .../io/tolgee/component/VersionFilter.kt | 8 +- .../RedissonLockingProvider.kt | 5 +- .../lockingProvider/SimpleLockingProvider.kt | 6 +- .../CaffeineCacheConfiguration.kt | 7 +- .../ConditionalRedissonAutoConfiguration.kt | 2 +- .../configuration/LockingConfiguration.kt | 2 +- .../configuration/PublicConfigurationDTO.kt | 29 +- .../io/tolgee/controllers/ExportController.kt | 36 +- .../controllers/ImageStorageController.kt | 21 +- .../io/tolgee/controllers/PublicController.kt | 89 +- .../tolgee/facade/ProjectWithStatsFacade.kt | 86 +- .../io/tolgee/hateoas/InitialDataModel.kt | 2 +- .../hateoas/activity/ModifiedEntityModel.kt | 2 +- .../activity/ProjectActivityAuthorModel.kt | 2 +- .../activity/ProjectActivityModelAssembler.kt | 56 +- .../io/tolgee/hateoas/apiKey/ApiKeyModel.kt | 9 +- .../hateoas/apiKey/ApiKeyModelAssembler.kt | 26 +- .../hateoas/apiKey/ApiKeyPermissionsModel.kt | 12 +- .../apiKey/ApiKeyWithLanguagesModel.kt | 2 +- .../apiKey/RevealedApiKeyModelAssembler.kt | 18 +- .../AutoTranslationConfigModel.kt | 25 +- .../AutoTranslationSettingsModelAssembler.kt | 3 +- .../automation/AutomationActionModelFiller.kt | 5 +- .../automation/AutomationTriggerModel.kt | 2 +- .../io/tolgee/hateoas/batch/BatchJobModel.kt | 11 +- .../hateoas/batch/BatchJobModelAssembler.kt | 11 +- .../ContentDeliveryConfigModel.kt | 2 +- .../ContentDeliveryConfigModelAssembler.kt | 9 +- .../dataImport/ImportAddFilesResultModel.kt | 2 +- .../dataImport/ImportFileIssueModel.kt | 2 +- .../ImportFileIssueModelAssembler.kt | 9 +- .../dataImport/ImportFileIssueParamModel.kt | 2 +- .../ImportFileIssueParamModelAssembler.kt | 5 +- .../ImportLanguageModelAssembler.kt | 5 +- .../dataImport/ImportNamespaceModel.kt | 3 +- .../dataImport/ImportTranslationModel.kt | 2 +- .../ImportTranslationModelAssembler.kt | 5 +- .../invitation/OrganizationInvitationModel.kt | 2 +- .../OrganizationInvitationModelAssembler.kt | 5 +- .../invitation/ProjectInvitationModel.kt | 2 +- .../ProjectInvitationModelAssembler.kt | 9 +- .../key/KeyImportResolvableResultModel.kt | 1 - .../kotlin/io/tolgee/hateoas/key/KeyModel.kt | 2 - .../tolgee/hateoas/key/KeyModelAssembler.kt | 14 +- .../io/tolgee/hateoas/key/KeyModifiedModel.kt | 2 +- .../key/KeySearchResultModelAssembler.kt | 3 +- .../key/KeyWithBaseTranslationModel.kt | 5 +- .../KeyWithBaseTranslationModelAssembler.kt | 3 +- .../io/tolgee/hateoas/key/KeyWithDataModel.kt | 8 +- .../hateoas/key/KeyWithDataModelAssembler.kt | 29 +- .../key/KeyWithScreenshotsModelAssembler.kt | 16 +- .../hateoas/key/namespace/NamespaceModel.kt | 1 - .../key/namespace/NamespaceModelAssembler.kt | 12 +- .../key/namespace/UsedNamespaceModel.kt | 1 - .../namespace/UsedNamespaceModelAssembler.kt | 12 +- .../tolgee/hateoas/language/LanguageModel.kt | 7 +- .../language/LanguageModelAssembler.kt | 5 +- .../machineTranslation/CreditBalanceModel.kt | 2 +- .../LanguageConfigItemModel.kt | 12 +- .../LanguageConfigItemModelAssembler.kt | 21 +- .../machineTranslation/LanguageInfoModel.kt | 2 +- .../StreamedSuggestionInfo.kt | 2 +- .../machineTranslation/SuggestResultModel.kt | 8 +- .../TranslationItemModel.kt | 2 +- .../organization/IOrganizationModel.kt | 2 +- .../hateoas/organization/OrganizationModel.kt | 6 - .../OrganizationModelAssembler.kt | 5 +- .../organization/PrivateOrganizationModel.kt | 4 +- .../PrivateOrganizationModelAssembler.kt | 6 +- .../hateoas/organization/PublicUsageModel.kt | 46 +- .../organization/SimpleOrganizationModel.kt | 6 +- .../SimpleOrganizationModelAssembler.kt | 9 +- .../UserAccountWithOrganizationRoleModel.kt | 2 +- ...countWithOrganizationRoleModelAssembler.kt | 19 +- .../kotlin/io/tolgee/hateoas/pat/PatModel.kt | 2 +- .../tolgee/hateoas/pat/PatModelAssembler.kt | 5 +- .../io/tolgee/hateoas/pat/PatWithUserModel.kt | 4 +- .../hateoas/pat/PatWithUserModelAssembler.kt | 11 +- .../io/tolgee/hateoas/pat/RevealedPatModel.kt | 2 +- .../hateoas/pat/RevealedPatModelAssembler.kt | 9 +- .../permission/ComputedPermissionModel.kt | 2 +- .../ComputedPermissionModelAssembler.kt | 9 +- .../permission/IDeprecatedPermissionModel.kt | 2 +- .../hateoas/permission/IPermissionModel.kt | 18 +- .../permission/PermissionModelAssembler.kt | 3 +- .../io/tolgee/hateoas/project/ProjectModel.kt | 2 +- .../hateoas/project/ProjectModelAssembler.kt | 14 +- .../project/ProjectTransferOptionModel.kt | 2 +- .../hateoas/project/ProjectWithStatsModel.kt | 6 +- .../project/ProjectWithStatsModelAssembler.kt | 25 +- .../project/SimpleProjectModelAssembler.kt | 16 +- .../project/stats/LanguageStatsModel.kt | 2 +- .../stats/LanguageStatsModelAssembler.kt | 5 +- .../project/stats/ProjectStatsModel.kt | 2 +- .../hateoas/quickStart/QuickStartModel.kt | 2 +- .../quickStart/QuickStartModelAssembler.kt | 5 +- .../screenshot/KeyInScreenshotModel.kt | 2 +- .../hateoas/screenshot/ScreenshotModel.kt | 1 - .../screenshot/ScreenshotModelAssembler.kt | 60 +- .../kotlin/io/tolgee/hateoas/tag/TagModel.kt | 2 +- .../tolgee/hateoas/tag/TagModelAssembler.kt | 3 +- .../TranslationMemoryItemModel.kt | 2 +- .../TranslationMemoryItemModelAssembler.kt | 5 +- .../translations/KeyWithTranslationsModel.kt | 12 +- .../KeyWithTranslationsModelAssembler.kt | 40 +- .../KeysWithTranslationsPageModel.kt | 6 +- ...WithTranslationsPagedResourcesAssembler.kt | 17 +- .../SetTranslationsResponseModel.kt | 7 +- .../translations/TranslationHistoryModel.kt | 7 +- .../TranslationHistoryModelAssembler.kt | 30 +- .../hateoas/translations/TranslationModel.kt | 5 - .../translations/TranslationModelAssembler.kt | 5 +- .../translations/TranslationSocketModel.kt | 8 +- .../translations/TranslationViewModel.kt | 10 +- .../TranslationViewModelAssembler.kt | 5 +- .../translations/TranslationWithKeyModel.kt | 5 +- .../comments/TranslationCommentModel.kt | 7 +- .../TranslationCommentModelAssembler.kt | 11 +- .../comments/TranslationWithCommentModel.kt | 2 +- .../uploadedImage/UploadedImageModel.kt | 2 +- .../UploadedImageModelAssembler.kt | 29 +- .../PrivateUserAccountModel.kt | 2 +- .../PrivateUserAccountModelAssembler.kt | 7 +- .../SimpleUserAccountModel.kt | 4 +- .../SimpleUserAccountModelAssembler.kt | 13 +- .../UserAccountInProjectModel.kt | 4 +- .../UserAccountInProjectModelAssembler.kt | 24 +- .../UserAccountModel.kt | 2 +- .../UserAccountModelAssembler.kt | 9 +- .../userPreferences/UserPreferencesModel.kt | 2 +- .../GithubOAuthDelegate.kt | 72 +- .../GoogleOAuthDelegate.kt | 46 +- .../OAuth2Delegate.kt | 76 +- .../io/tolgee/util/ApplicationStopper.kt | 3 +- .../websocket/ActivityWebsocketListener.kt | 82 +- .../websocket/RedisWebsocketEventPublisher.kt | 9 +- .../SimpleWebsocketEventPublisher.kt | 5 +- .../io/tolgee/websocket/WebSocketConfig.kt | 53 +- .../WebsocketPublisherConfiguration.kt | 2 +- .../src/main/kotlin/io/tolgee/Application.kt | 2 +- .../kotlin/io/tolgee/ExceptionHandlers.kt | 71 +- .../InitialUserCreatorCommandLineRunner.kt | 23 +- .../MigrationJobsCommandLineRunner.kt | 3 +- .../StartupImportCommandLineRunner.kt | 2 +- .../component/ExceptionHandlerFilter.kt | 6 +- .../kotlin/io/tolgee/configuration/Banner.kt | 6 +- .../io/tolgee/configuration/EmailConfig.kt | 2 +- .../tolgee/configuration/EventStreamConfig.kt | 6 +- .../configuration/FileStorageConfiguration.kt | 1 - .../configuration/OpenApiConfiguration.kt | 78 +- .../PostgresAutoStartConfiguration.kt | 8 +- .../RestTemplateConfiguration.kt | 3 +- .../tolgee/configuration/WebSecurityConfig.kt | 16 +- .../postgresRunners/PostgresDockerRunner.kt | 45 +- .../postgresRunners/PostgresEmbeddedRunner.kt | 41 +- .../PostgresRunnerConfiguration.kt | 2 +- .../tolgee/postgresRunners/PostgresStopper.kt | 2 +- .../src/main/resources/application-e2e.yaml | 4 +- .../app/src/test/kotlin/io/tolgee/AuthTest.kt | 37 +- .../test/kotlin/io/tolgee/HealthCheckTest.kt | 1 - .../io/tolgee/MachineTranslationTest.kt | 25 +- .../src/test/kotlin/io/tolgee/PatAuthTest.kt | 17 +- .../StartupImportCommandLineRunnerTest.kt | 3 +- .../StreamingBodyDatabasePoolHealthTest.kt | 4 +- .../kotlin/io/tolgee/VersionHeaderTest.kt | 2 +- .../io/tolgee/activity/ActivityLogTest.kt | 44 +- .../AdministrationControllerTest.kt | 8 +- .../v2/controllers/ApiKeyControllerTest.kt | 27 +- .../AutoTranslationControllerTest.kt | 12 +- .../v2/controllers/BigMetaControllerTest.kt | 41 +- .../BusinessEventControllerTest.kt | 9 +- .../controllers/InitialDataControllerTest.kt | 1 - ...achineTranslationSettingsControllerTest.kt | 96 +- .../v2/controllers/NamespaceControllerTest.kt | 11 +- .../api/v2/controllers/PatControllerTest.kt | 17 +- .../PreferredOrganizationControllerTest.kt | 1 - .../controllers/ProjectStatsControllerTest.kt | 5 +- .../api/v2/controllers/SlugControllerTest.kt | 21 +- .../api/v2/controllers/TagsControllerTest.kt | 1 - .../v2/controllers/UserMfaControllerTest.kt | 88 +- .../UserPreferencesControllerTest.kt | 1 - .../v2/controllers/V2ExportControllerTest.kt | 82 +- .../controllers/V2InvitationControllerTest.kt | 47 +- .../controllers/V2LanguageControllerTest.kt | 34 +- .../v2/controllers/V2UserControllerTest.kt | 111 +- .../batch/BatchJobManagementControllerTest.kt | 37 +- .../batch/StartBatchJobControllerTest.kt | 145 +- .../ContentDeliveryConfigControllerTest.kt | 19 +- .../BaseOrganizationControllerTest.kt | 26 +- .../OrganizationControllerInvitingTest.kt | 75 +- .../OrganizationControllerLeavingTest.kt | 5 +- .../OrganizationControllerMembersTest.kt | 6 +- .../OrganizationControllerTest.kt | 43 +- .../OrganizationProjectsControllerTest.kt | 8 +- ...lationSuggestionControllerStreamingTest.kt | 77 +- .../TranslationSuggestionControllerTest.kt | 72 +- .../TranslationCommentControllerTest.kt | 35 +- .../TranslationsControllerCachingTest.kt | 11 +- .../TranslationsControllerCursorTest.kt | 6 +- .../TranslationsControllerFilterTest.kt | 1 - .../TranslationsControllerHistoryTest.kt | 30 +- ...lationsControllerLanguagePermissionTest.kt | 21 +- .../TranslationsControllerModificationTest.kt | 63 +- .../TranslationsControllerNamespacesTest.kt | 5 +- .../TranslationsControllerViewTest.kt | 10 +- .../AbstractV2ImageUploadControllerTest.kt | 15 +- .../SecuredV2ImageUploadControllerTest.kt | 35 +- .../V2ImageUploadControllerTest.kt | 44 +- .../V2ImportControllerAddFilesTest.kt | 34 +- .../V2ImportControllerApplicationTest.kt | 5 +- .../V2ImportControllerManipulationTest.kt | 35 +- .../V2ImportControllerResultTest.kt | 28 +- .../KeyControllerComplexUpdateTest.kt | 147 +- .../KeyControllerCreationTest.kt | 96 +- .../KeyControllerDeleteManyKeysTest.kt | 12 +- .../v2KeyController/KeyControllerInfoTest.kt | 22 +- .../KeyControllerKeySearchTest.kt | 39 +- .../KeyControllerLanguageDisablingTest.kt | 9 +- .../KeyControllerLanguagePermissionTest.kt | 5 +- .../KeyControllerResolvableImportTest.kt | 315 +- .../v2KeyController/KeyControllerTest.kt | 36 +- .../V2ProjectsControllerCreateTest.kt | 94 +- .../V2ProjectsControllerEditTest.kt | 27 +- .../V2ProjectsControllerInvitationTest.kt | 70 +- .../V2ProjectsControllerLeavingTest.kt | 1 - .../V2ProjectsControllerPermissionsTest.kt | 19 +- .../V2ProjectsControllerTest.kt | 21 +- .../V2ProjectsControllerWithCacheTest.kt | 2 +- .../AbstractV2ScreenshotControllerTest.kt | 31 +- .../KeyScreenshotControllerTest.kt | 106 +- .../SecuredKeyScreenshotControllerTest.kt | 70 +- .../autoTranslating/AutoTranslatingTest.kt | 80 +- .../automation/AutomationCachingTest.kt | 18 +- .../automation/AutomationIntegrationTest.kt | 19 +- .../batch/AbstractBatchJobsGeneralTest.kt | 1 - .../io/tolgee/batch/BatchJobTestUtil.kt | 97 +- .../batch/BatchJobsGeneralWithRedisTest.kt | 8 +- .../batch/BatchJobsGeneralWithoutRedisTest.kt | 2 +- .../batch/TolgeeTranslatorWithBatchTest.kt | 18 +- .../io/tolgee/cache/AbstractCacheTest.kt | 26 +- .../io/tolgee/cache/CacheWithRedisTest.kt | 4 +- .../io/tolgee/cache/CacheWithoutRedisTest.kt | 2 +- .../kotlin/io/tolgee/component/AesTest.kt | 26 +- .../component/LanguageStatsListenerTest.kt | 9 +- .../bucket/AbstractTokenBucketManagerTest.kt | 12 +- .../bucket/TokenBucketManagerTestWithRedis.kt | 2 +- .../AbstractFileStorageServiceTest.kt | 1 - .../fileStorage/FileStorageFsTest.kt | 1 - .../fileStorage/FileStorageS3Test.kt | 4 +- .../tolgee/controllers/AbstractApiKeyTest.kt | 4 +- .../io/tolgee/controllers/DemoProjectTest.kt | 41 +- .../controllers/ExportControllerTest.kt | 25 +- .../controllers/MarketingEmailingTest.kt | 28 +- .../controllers/PublicControllerTest.kt | 54 +- .../controllers/internal/SqlControllerTest.kt | 25 +- .../postgres/CustomPostgreSQLDialectTest.kt | 8 +- .../CreateEnabledTest.kt | 6 +- .../LegacyMigrationTest.kt | 10 +- .../AllOrganizationOwnerJobTest.kt | 40 +- .../TranslationStatsJobTest.kt | 182 +- .../kotlin/io/tolgee/openapi/OpenApiTest.kt | 1 - .../repository/ProjectRepositoryTest.kt | 1 - .../repository/UserAccountRepositoryTest.kt | 1 - .../ImportFileIssueRepositoryTest.kt | 9 +- .../dataImport/ImportFileRepositoryTest.kt | 12 +- .../ImportLanguageRepositoryTest.kt | 6 +- .../dataImport/ImportRepositoryTest.kt | 1 - .../ImportTranslationRepositoryTest.kt | 11 +- .../io/tolgee/security/DenyInternalTest.kt | 22 +- .../tolgee/security/EmailVerificationTest.kt | 3 +- .../ProjectApiKeyAuthenticationTest.kt | 25 +- .../tolgee/security/ServerAdminFilterTest.kt | 13 +- .../security/rateLimits/RateLimitsTest.kt | 2 +- .../rateLimits/RedisRateLimitsTest.kt | 2 +- .../io/tolgee/service/BigMetaServiceTest.kt | 20 +- .../io/tolgee/service/DbPopulatorTest.kt | 6 +- .../io/tolgee/service/ExportServiceTest.kt | 1 + .../tolgee/service/ImageUploadServiceTest.kt | 6 +- .../service/LanguageDeletePermissionTest.kt | 6 +- .../tolgee/service/OrganizationServiceTest.kt | 1 - .../tolgee/service/ProjectStatsServiceTest.kt | 1 - .../io/tolgee/service/SoftDeleteTest.kt | 10 +- .../io/tolgee/service/TelemetryServiceTest.kt | 22 +- .../tolgee/service/TranslationServiceTest.kt | 44 +- .../service/dataImport/ImportServiceTest.kt | 35 +- .../dataImport/StoredDataImporterTest.kt | 53 +- .../export/exporters/JsonFileExporterTest.kt | 38 +- .../export/exporters/XliffFileExporterTest.kt | 95 +- .../service/project/ProjectServiceTest.kt | 49 +- .../CursorUtilUnitTest.kt | 59 +- .../TranslationViewDataProviderTest.kt | 61 +- .../RecaptchaValidationDisabledTest.kt | 9 +- .../RecaptchaValidationTest.kt | 19 +- .../component/SimpleLockingProviderTest.kt | 7 +- .../test/kotlin/io/tolgee/util/BatchDumper.kt | 33 +- .../kotlin/io/tolgee/util/GitHubAuthUtil.kt | 32 +- .../kotlin/io/tolgee/util/GoogleAuthUtil.kt | 20 +- .../kotlin/io/tolgee/util/OAuth2AuthUtil.kt | 20 +- .../kotlin/io/tolgee/util/generateImage.kt | 5 +- .../tolgee/websocket/AbstractWebsocketTest.kt | 38 +- .../tolgee/websocket/WebsocketTestHelper.kt | 36 +- .../websocket/WebsocketWithRedisTest.kt | 4 +- .../websocket/WebsocketWithoutRedisTest.kt | 2 +- backend/data/build.gradle | 10 +- .../main/java/io/tolgee/helpers/TextHelper.kt | 12 +- .../tolgee/security/InitialPasswordManager.kt | 17 +- .../data/src/main/kotlin/io/tolgee/Metrics.kt | 2 +- .../io/tolgee/MtServicesConfiguration.kt | 27 +- .../main/kotlin/io/tolgee/PostgresRunner.kt | 1 + .../activity/ActivityHandlerInterceptor.kt | 8 +- .../io/tolgee/activity/ActivityHolder.kt | 2 +- .../io/tolgee/activity/ActivityService.kt | 29 +- .../activity/EntityDescriptionProvider.kt | 20 +- .../io/tolgee/activity/RequestActivity.kt | 2 +- .../ActivityEntityDescribingPaths.kt | 2 +- .../activity/annotation/ActivityLoggedProp.kt | 2 +- .../io/tolgee/activity/data/ActivityType.kt | 5 +- .../activity/data/EntityDescriptionRef.kt | 2 +- .../data/EntityDescriptionWithRelations.kt | 10 +- .../data/ExistenceEntityDescription.kt | 2 +- .../activity/data/PropertyModification.kt | 2 +- .../io/tolgee/activity/data/RevisionType.kt | 5 +- .../iterceptor/ActivityDatabaseInterceptor.kt | 36 +- .../iterceptor/InterceptedEventsManager.kt | 137 +- .../iterceptor/PreCommitEventPublisher.kt | 1 - .../ActivityViewByRevisionsProvider.kt | 49 +- .../ProjectActivityViewByPageableProvider.kt | 9 +- .../ProjectActivityViewByRevisionProvider.kt | 2 +- .../RelationDescriptionExtractor.kt | 11 +- .../DefaultPropChangesProvider.kt | 7 +- .../PropChangesProvider.kt | 5 +- .../TagsPropChangesProvider.kt | 6 +- .../batch/BatchActivityParamsProvider.kt | 4 +- .../io/tolgee/batch/BatchJobActionService.kt | 122 +- .../tolgee/batch/BatchJobActivityFinalizer.kt | 76 +- .../batch/BatchJobCancellationManager.kt | 54 +- .../batch/BatchJobChunkExecutionQueue.kt | 48 +- .../batch/BatchJobConcurrentLauncher.kt | 72 +- .../batch/BatchJobProjectLockingManager.kt | 35 +- .../kotlin/io/tolgee/batch/BatchJobService.kt | 120 +- .../io/tolgee/batch/CachingBatchJobService.kt | 11 +- .../io/tolgee/batch/ChunkProcessingUtil.kt | 45 +- .../kotlin/io/tolgee/batch/ChunkProcessor.kt | 8 +- .../kotlin/io/tolgee/batch/JobCharacter.kt | 2 +- .../kotlin/io/tolgee/batch/ProgressManager.kt | 52 +- .../io/tolgee/batch/ScheduledJobCleaner.kt | 3 +- .../batch/data/AllIncompleteJobsResult.kt | 2 +- .../io/tolgee/batch/data/BatchJobType.kt | 5 +- .../io/tolgee/batch/data/JobUnlockedChunk.kt | 2 +- .../io/tolgee/batch/data/QueueEventType.kt | 3 +- .../io/tolgee/batch/events/JobCancelEvent.kt | 2 +- .../tolgee/batch/events/JobQueueItemsEvent.kt | 2 +- .../batch/events/OnBatchJobStatusUpdated.kt | 2 +- .../main/kotlin/io/tolgee/batch/exceptions.kt | 6 +- .../processors/AutoTranslateChunkProcessor.kt | 9 +- .../processors/AutomationChunkProcessor.kt | 4 +- .../ClearTranslationsChunkProcessor.kt | 4 +- .../CopyTranslationsChunkProcessor.kt | 4 +- .../processors/DeleteKeysChunkProcessor.kt | 4 +- .../GenericAutoTranslationChunkProcessor.kt | 8 +- .../MachineTranslationChunkProcessor.kt | 11 +- .../PreTranslationByTmChunkProcessor.kt | 22 +- .../SetKeysNamespaceChunkProcessor.kt | 4 +- .../SetTranslationsStateChunkProcessor.kt | 4 +- .../batch/processors/TagKeysChunkProcessor.kt | 4 +- .../processors/UntagKeysChunkProcessor.kt | 4 +- .../batch/request/AutomationBjRequest.kt | 2 +- .../batch/state/BatchJobStateProvider.kt | 45 +- .../component/ActivityHolderProvider.kt | 3 +- .../main/kotlin/io/tolgee/component/Aes.kt | 48 +- .../component/ContentStorageProvider.kt | 5 +- .../tolgee/component/CurrentDateProvider.kt | 13 +- .../tolgee/component/FrontendUrlProvider.kt | 2 +- .../kotlin/io/tolgee/component/HttpClient.kt | 27 +- .../io/tolgee/component/KeyGenerator.kt | 2 +- .../io/tolgee/component/LockingProvider.kt | 5 +- .../component/MarketingEmailServiceManager.kt | 23 +- .../tolgee/component/OutdatedFlagListener.kt | 2 +- .../io/tolgee/component/SavePointManager.kt | 7 +- .../component/SentryBeforeSendCallback.kt | 5 +- .../io/tolgee/component/UsingRedisProvider.kt | 2 +- .../atomicLong/AtomicLongProvider.kt | 7 +- .../atomicLong/MemoryTolgeeAtomicLong.kt | 2 +- .../atomicLong/RedisTolgeeAtomicLong.kt | 2 +- .../AutoTranslationEventHandler.kt | 17 +- .../AutoTranslationListener.kt | 3 +- .../automations/AutomationActivityListener.kt | 4 +- .../automations/AutomationProcessor.kt | 5 +- .../component/automations/AutomationRunner.kt | 7 +- .../automations/AutomationsBatchJobCreator.kt | 21 +- .../ContentDeliveryPublishProcessor.kt | 8 +- .../processors/WebhookEventType.kt | 3 +- .../automations/processors/WebhookExecutor.kt | 12 +- .../processors/WebhookProcessor.kt | 23 +- .../automations/processors/WebhookRequest.kt | 2 +- .../processors/webhookExceptions.kt | 1 + .../io/tolgee/component/bucket/TokenBucket.kt | 8 +- .../component/bucket/TokenBucketManager.kt | 41 +- .../CacheWithExpiration.kt | 13 +- .../CacheWithExpirationManager.kt | 2 +- .../CachedWithExpiration.kt | 2 +- .../ContentDeliveryFileStorageProvider.kt | 2 +- .../ContentDeliveryUploader.kt | 23 +- .../AzureContentDeliveryCachePurging.kt | 29 +- ...AzureContentDeliveryCachePurgingFactory.kt | 2 +- .../ContentDeliveryCachePurging.kt | 5 +- .../ContentDeliveryCachePurgingProvider.kt | 11 +- .../demoProject/DemoProjectCreator.kt | 43 +- .../component/demoProject/DemoProjectData.kt | 177 +- .../email/EmailVerificationSender.kt | 34 +- .../component/email/InvitationEmailSender.kt | 52 +- .../email/MimeMessageHelperFactory.kt | 2 +- .../component/email/TolgeeEmailSender.kt | 12 +- .../EnabledFeaturesProvider.kt | 10 +- .../eventListeners/LanguageStatsListener.kt | 12 +- .../eventListeners/MailServiceUserListener.kt | 9 +- .../fileStorage/AzureBlobFileStorage.kt | 5 +- .../fileStorage/AzureFileStorageFactory.kt | 7 +- .../component/fileStorage/FileStorage.kt | 9 +- .../component/fileStorage/LocalFileStorage.kt | 6 +- .../component/fileStorage/S3ClientProvider.kt | 32 +- .../component/fileStorage/S3FileStorage.kt | 7 +- .../component/fileStorage/TolgeeBlobClient.kt | 9 +- .../LanguageTagConvertor.kt | 5 +- .../machineTranslation/MtEventListener.kt | 2 +- .../machineTranslation/MtServiceManager.kt | 109 +- .../machineTranslation/MtValueProvider.kt | 2 +- .../machineTranslation/TranslateResult.kt | 2 +- .../machineTranslation/TranslationParams.kt | 8 +- .../metadata/ExampleItem.kt | 2 +- .../providers/AbstractMtValueProvider.kt | 7 +- .../providers/AwsMtValueProvider.kt | 208 +- .../providers/AzureCognitiveApiService.kt | 21 +- .../AzureCognitiveTranslationProvider.kt | 36 +- .../providers/BaiduApiService.kt | 16 +- .../providers/BaiduTranslationProvider.kt | 283 +- .../providers/DeeplApiService.kt | 33 +- .../providers/DeeplTranslationProvider.kt | 114 +- .../providers/GoogleTranslationProvider.kt | 244 +- .../providers/ProviderTranslateParams.kt | 1 - .../providers/TolgeeTranslateApiService.kt | 69 +- .../providers/TolgeeTranslationProvider.kt | 6 +- .../FreeMtBucketSizeProvider.kt | 5 +- .../MtBucketSizeProvider.kt | 2 + .../reporting/BusinessEventPublisher.kt | 28 +- .../reporting/BusinessEventReporter.kt | 44 +- .../BusinessEventReportingActivityListener.kt | 4 +- .../component/reporting/OnIdentifyEvent.kt | 2 +- .../component/reporting/SdkInfoProvider.kt | 2 +- .../component/reporting/SignUpListener.kt | 6 +- .../BaseTranslationsLimitProvider.kt | 3 + .../TranslationsLimitProvider.kt | 1 + .../configuration/LiquibaseConfiguration.kt | 5 +- .../configuration/PostHogConfiguration.kt | 3 +- .../configuration/SendInBlueConfiguration.kt | 3 +- .../configuration/annotations/DocProperty.kt | 2 +- .../tolgee/AuthenticationProperties.kt | 114 +- .../configuration/tolgee/CacheProperties.kt | 50 +- .../tolgee/ContentDeliveryProperties.kt | 10 +- .../tolgee/FileStorageProperties.kt | 3 +- .../tolgee/GithubAuthenticationProperties.kt | 19 +- .../tolgee/GoogleAuthenticationProperties.kt | 12 +- .../tolgee/HibernateConfiguration.kt | 1 - .../configuration/tolgee/ImportProperties.kt | 49 +- .../tolgee/OAuth2AuthenticationProperties.kt | 18 +- .../tolgee/PostgresAutostartProperties.kt | 36 +- .../tolgee/RabbitmqAutostartProperties.kt | 2 +- .../tolgee/RateLimitProperties.kt | 51 +- .../tolgee/ReCaptchaProperties.kt | 13 +- .../tolgee/configuration/tolgee/S3Settings.kt | 27 +- .../configuration/tolgee/SentryProperties.kt | 2 +- .../configuration/tolgee/SmtpProperties.kt | 29 +- .../tolgee/TelemetryProperties.kt | 2 +- .../configuration/tolgee/TolgeeProperties.kt | 61 +- .../AwsMachineTranslationProperties.kt | 31 +- .../AzureCognitiveTranslationProperties.kt | 16 +- .../BaiduMachineTranslationProperties.kt | 17 +- .../DeeplMachineTranslationProperties.kt | 4 +- .../GoogleMachineTranslationProperties.kt | 11 +- .../MachineTranslationProperties.kt | 8 +- .../io/tolgee/constants/BillingPeriod.kt | 3 +- .../main/kotlin/io/tolgee/constants/Caches.kt | 29 +- .../constants/ComputedPermissionOrigin.kt | 6 +- .../kotlin/io/tolgee/constants/Message.kt | 2 +- .../io/tolgee/constants/MtServiceType.kt | 4 +- .../main/kotlin/io/tolgee/development/Base.kt | 2 +- .../io/tolgee/development/DbPopulatorReal.kt | 157 +- .../AdditionalTestDataSaver.kt | 1 + .../testDataBuilder/TestDataService.kt | 29 +- .../testDataBuilder/builders/ApiKeyBuilder.kt | 18 +- .../builders/AutoTranslationConfigBuilder.kt | 2 +- .../builders/AutomationBuilder.kt | 1 - .../builders/BaseEntityDataBuilder.kt | 4 +- .../testDataBuilder/builders/ImportBuilder.kt | 9 +- .../builders/ImportFileBuilder.kt | 18 +- .../builders/ImportKeyBuilder.kt | 10 +- .../builders/ImportLanguageBuilder.kt | 2 +- .../builders/ImportTranslationBuilder.kt | 2 +- .../testDataBuilder/builders/KeyBuilder.kt | 62 +- .../builders/KeyMetaBuilder.kt | 23 +- .../builders/KeysDistanceBuilder.kt | 11 +- .../builders/LanguageBuilder.kt | 9 +- .../builders/MtServiceConfigBuilder.kt | 11 +- .../builders/NamespaceBuilder.kt | 2 +- .../builders/OrganizationBuilder.kt | 16 +- .../builders/OrganizationRoleBuilder.kt | 12 +- .../testDataBuilder/builders/PatBuilder.kt | 2 +- .../builders/PermissionBuilder.kt | 9 +- .../builders/ProjectBuilder.kt | 46 +- .../builders/TestDataBuilder.kt | 18 +- .../builders/TranslationBuilder.kt | 3 +- .../builders/TranslationCommentBuilder.kt | 15 +- .../builders/UserAccountBuilder.kt | 7 +- .../builders/UserPreferencesBuilder.kt | 2 +- .../data/AdministrationTestData.kt | 27 +- .../AllOrganizationOwnerMigrationTestData.kt | 47 +- .../testDataBuilder/data/ApiKeysTestData.kt | 19 +- .../data/AutoTranslateTestData.kt | 11 +- .../testDataBuilder/data/BaseTestData.kt | 65 +- .../testDataBuilder/data/BatchJobsTestData.kt | 1 - .../testDataBuilder/data/BigMetaTestData.kt | 33 +- .../data/ContentDeliveryConfigTestData.kt | 93 +- .../data/FormerUserTestData.kt | 78 +- .../data/KeyLanguageDisablingTestData.kt | 41 +- .../testDataBuilder/data/KeySearchTestData.kt | 9 +- .../testDataBuilder/data/KeysInfoTestData.kt | 8 +- .../testDataBuilder/data/KeysTestData.kt | 146 +- .../data/LanguagePermissionsTestData.kt | 153 +- .../data/MtSettingsTestData.kt | 22 +- .../data/NamespacesTestData.kt | 26 +- .../data/OrganizationTestData.kt | 33 +- .../testDataBuilder/data/PatTestData.kt | 53 +- .../data/PermissionsTestData.kt | 103 +- .../data/ProjectStatsTestData.kt | 47 +- .../testDataBuilder/data/ProjectsTestData.kt | 20 +- .../data/ResolvableImportTestData.kt | 8 +- .../SensitiveOperationProtectionTestData.kt | 45 +- .../data/SuggestionTestData.kt | 26 +- .../data/TranslationCommentsTestData.kt | 187 +- .../data/TranslationNsAndTagsData.kt | 102 +- .../data/TranslationSingleTestData.kt | 161 +- .../data/TranslationsTestData.kt | 119 +- .../data/UserDeletionTestData.kt | 89 +- .../testDataBuilder/data/WebhooksTestData.kt | 41 +- .../data/dataImport/ImportCleanTestData.kt | 74 +- .../dataImport/ImportNamespacesTestData.kt | 242 +- .../data/dataImport/ImportTestData.kt | 317 +- .../postgres/CustomPostgreSQLDialect.kt | 3 +- .../src/main/kotlin/io/tolgee/dtos/Avatar.kt | 2 +- .../io/tolgee/dtos/ComputedPermissionDto.kt | 76 +- .../io/tolgee/dtos/CreateScreenshotResult.kt | 2 +- .../kotlin/io/tolgee/dtos/IExportParams.kt | 4 +- .../io/tolgee/dtos/MtCreditBalanceDto.kt | 2 +- .../src/main/kotlin/io/tolgee/dtos/PathDTO.kt | 26 +- .../io/tolgee/dtos/ProjectPermissionData.kt | 2 +- .../kotlin/io/tolgee/dtos/RelatedKeyDto.kt | 3 +- .../io/tolgee/dtos/WithRelatedKeysInOrder.kt | 7 +- .../io/tolgee/dtos/cacheable/PermissionDto.kt | 2 +- .../io/tolgee/dtos/cacheable/ProjectDto.kt | 15 +- .../tolgee/dtos/cacheable/UserAccountDto.kt | 21 +- .../automations/AutomationActionDto.kt | 2 +- .../cacheable/automations/AutomationDto.kt | 22 +- .../automations/AutomationTriggerDto.kt | 5 +- .../contentDelivery/ContentStorageRequest.kt | 2 +- .../dtos/dataImport/ImportAddFilesParams.kt | 5 +- .../dataImport/SetFileNamespaceRequest.kt | 2 +- .../CreateOrganizationInvitationParams.kt | 2 +- .../misc/CreateProjectInvitationParams.kt | 2 +- .../io/tolgee/dtos/misc/EmailAttachment.kt | 2 +- .../kotlin/io/tolgee/dtos/misc/EmailParams.kt | 2 +- .../KeyIdFindResult.kt | 2 +- .../KeyWithTranslationsDto.kt | 3 +- .../ProjectStatistics.kt | 4 +- .../TranslationHistoryView.kt | 2 +- .../request/AutoTranslationSettingsDto.kt | 25 +- .../request/BusinessEventReportRequest.kt | 6 +- .../request/ContentDeliveryConfigRequest.kt | 16 +- .../io/tolgee/dtos/request/GenerateSlugDto.kt | 1 - .../tolgee/dtos/request/GetKeysRequestDto.kt | 1 + .../io/tolgee/dtos/request/IdentifyRequest.kt | 2 +- .../tolgee/dtos/request/ImageUploadInfoDto.kt | 2 +- .../request/KeyInScreenshotPositionDto.kt | 2 +- .../io/tolgee/dtos/request/LanguageDto.kt | 15 +- .../MachineTranslationLanguagePropsDto.kt | 7 +- .../tolgee/dtos/request/ScreenshotInfoDto.kt | 2 +- .../request/SetDisabledLanguagesRequest.kt | 2 +- .../SetMachineTranslationSettingsDto.kt | 2 +- .../io/tolgee/dtos/request/SetPropertyDto.kt | 2 +- .../tolgee/dtos/request/SuggestRequestDto.kt | 2 +- .../tolgee/dtos/request/SuperTokenRequest.kt | 3 +- .../dtos/request/UserMfaRecoveryRequestDto.kt | 2 +- .../dtos/request/UserTotpDisableRequestDto.kt | 2 +- .../dtos/request/UserTotpEnableRequestDto.kt | 4 +- .../request/UserUpdatePasswordRequestDto.kt | 3 +- .../dtos/request/UserUpdateRequestDto.kt | 10 +- .../dtos/request/apiKey/CreateApiKeyDto.kt | 15 +- .../request/apiKey/RegenerateApiKeyDto.kt | 9 +- .../dtos/request/apiKey/V2EditApiKeyDto.kt | 5 +- .../tolgee/dtos/request/auth/ResetPassword.kt | 2 - .../dtos/request/auth/ResetPasswordRequest.kt | 3 +- .../io/tolgee/dtos/request/auth/SignUpDto.kt | 5 - .../dtos/request/export/ExportParams.kt | 26 +- .../dtos/request/key/ComplexEditKeyDto.kt | 10 +- .../tolgee/dtos/request/key/CreateKeyDto.kt | 9 +- .../tolgee/dtos/request/key/DeleteKeysDto.kt | 2 +- .../dtos/request/key/DeprecatedEditKeyDTO.kt | 2 +- .../io/tolgee/dtos/request/key/EditKeyDto.kt | 2 - .../dtos/request/key/KeyScreenshotDto.kt | 1 + .../tolgee/dtos/request/key/OldEditKeyDto.kt | 2 +- .../io/tolgee/dtos/request/key/TagKeyDto.kt | 2 +- .../request/organization/OrganizationDto.kt | 5 +- .../organization/OrganizationInviteUserDto.kt | 8 +- .../OrganizationRequestParamsDto.kt | 2 +- .../organization/SetOrganizationRoleDto.kt | 2 +- .../tolgee/dtos/request/pat/CreatePatDto.kt | 10 +- .../dtos/request/pat/RegeneratePatDto.kt | 4 +- .../dtos/request/project/CreateProjectDTO.kt | 21 +- .../dtos/request/project/EditProjectDTO.kt | 6 +- .../request/project/LanguagePermissions.kt | 4 +- .../request/project/ProjectInviteUserDto.kt | 15 +- .../screenshot/GetScreenshotsByKeyDto.kt | 2 +- .../request/screenshot/UploadScreenshotDto.kt | 2 +- .../translation/GetTranslationsParams.kt | 3 +- .../dtos/request/translation/ImportKeysDto.kt | 2 +- .../request/translation/ImportKeysItemDto.kt | 9 +- .../request/translation/SelectAllResponse.kt | 2 +- .../translation/SetTranslationsWithKeyDto.kt | 9 +- .../request/translation/TranslationFilters.kt | 16 +- .../comment/TranslationCommentDto.kt | 3 +- .../TranslationCommentWithLangKeyDto.kt | 5 +- .../ImportKeysResolvableDto.kt | 2 +- .../ImportKeysResolvableItemDto.kt | 3 - .../ImportTranslationResolution.kt | 2 +- .../ImportTranslationResolvableDto.kt | 3 +- .../request/validators/ValidationErrorType.kt | 3 +- .../response/{ApiKeyDTO => }/ApiKeyDTO.kt | 12 +- .../io/tolgee/dtos/response/CursorValue.kt | 2 +- .../tolgee/dtos/response/DeprecatedKeyDto.kt | 2 +- .../KeyWithTranslationsResponseDto.kt | 6 +- .../io/tolgee/dtos/response/ProjectDTO.kt | 8 +- .../response/PublicBillingConfigurationDTO.kt | 2 +- .../io/tolgee/dtos/response/ScreenshotDTO.kt | 2 +- .../io/tolgee/dtos/security/LoginRequest.kt | 1 + .../events/BeforeOrganizationDeleteEvent.kt | 2 +- .../tolgee/events/MachineTranslationEvent.kt | 1 - .../events/OnAfterMachineTranslationEvent.kt | 3 +- .../events/OnConsumePayAsYouGoMtCredits.kt | 2 +- .../io/tolgee/events/OnEntityPreDelete.kt | 2 +- .../io/tolgee/events/OnEntityPrePersist.kt | 2 +- .../io/tolgee/events/OnEntityPreUpdate.kt | 2 +- .../io/tolgee/events/OnImportSoftDeleted.kt | 2 +- .../io/tolgee/events/OnKeyPrePersist.kt | 2 +- .../kotlin/io/tolgee/events/OnKeyPreRemove.kt | 2 +- .../io/tolgee/events/OnLanguagePrePersist.kt | 2 +- .../io/tolgee/events/OnLanguagePreRemove.kt | 2 +- .../tolgee/events/OnProjectActivityEvent.kt | 2 +- .../events/OnProjectActivityStoredEvent.kt | 2 +- .../io/tolgee/events/OnTranslationsSet.kt | 5 +- .../io/tolgee/events/OnUserCountChanged.kt | 2 +- .../io/tolgee/events/user/OnUserCreated.kt | 2 +- .../events/user/OnUserEmailVerifiedFirst.kt | 2 +- .../io/tolgee/events/user/OnUserUpdated.kt | 2 +- .../io/tolgee/events/user/UserAccountEvent.kt | 2 +- .../exceptions/AuthenticationException.kt | 1 - .../tolgee/exceptions/ExceptionWithMessage.kt | 5 +- .../tolgee/exceptions/FileIssueException.kt | 2 +- .../tolgee/exceptions/FileStoreException.kt | 2 +- .../FormalityNotSupportedException.kt | 2 +- .../LanguageNotPermittedException.kt | 2 +- .../LanguageNotSupportedException.kt | 2 +- .../exceptions/OutOfCreditsException.kt | 2 +- .../tolgee/exceptions/PermissionException.kt | 2 +- .../io/tolgee/exceptions/PoParserException.kt | 1 - .../TranslationSpendingLimitExceeded.kt | 3 +- .../UnexpectedGoogleApiResponseException.kt | 2 +- .../tolgee/facade/ProjectPermissionFacade.kt | 27 +- .../AllOrganizationOwnerJobConfiguration.kt | 93 +- .../AllOrganizationOwnerJobRunner.kt | 3 +- .../translationStats/TranslationProcessor.kt | 5 +- .../translationStats/TranslationStats.kt | 2 +- .../TranslationStatsJobConfiguration.kt | 49 +- .../TranslationsStatsUpdateJobRunner.kt | 3 +- .../src/main/kotlin/io/tolgee/model/ApiKey.kt | 18 +- .../io/tolgee/model/DismissedAnnouncement.kt | 11 +- .../tolgee/model/DismissedAnnouncementId.kt | 2 +- .../io/tolgee/model/EmailVerification.kt | 10 +- .../main/kotlin/io/tolgee/model/Invitation.kt | 13 +- .../main/kotlin/io/tolgee/model/Language.kt | 28 +- .../kotlin/io/tolgee/model/LanguageStats.kt | 3 +- .../kotlin/io/tolgee/model/MtCreditBucket.kt | 6 +- .../kotlin/io/tolgee/model/Organization.kt | 20 +- .../io/tolgee/model/OrganizationRole.kt | 12 +- .../src/main/kotlin/io/tolgee/model/Pat.kt | 7 +- .../main/kotlin/io/tolgee/model/Permission.kt | 20 +- .../main/kotlin/io/tolgee/model/Project.kt | 7 +- .../main/kotlin/io/tolgee/model/QuickStart.kt | 1 - .../io/tolgee/model/StandardAuditModel.kt | 4 +- .../kotlin/io/tolgee/model/UploadedImage.kt | 6 +- .../kotlin/io/tolgee/model/UserAccount.kt | 14 +- .../kotlin/io/tolgee/model/UserPreferences.kt | 1 - .../activity/ActivityDescribingEntity.kt | 5 +- .../activity/ActivityDescribingEntityId.kt | 2 +- .../model/activity/ActivityModifiedEntity.kt | 5 +- .../activity/ActivityModifiedEntityId.kt | 2 +- .../tolgee/model/activity/ActivityRevision.kt | 9 +- .../io/tolgee/model/automations/Automation.kt | 1 - .../model/automations/AutomationActionType.kt | 4 +- .../kotlin/io/tolgee/model/batch/BatchJob.kt | 6 +- .../model/batch/BatchJobChunkExecution.kt | 2 +- .../batch/BatchJobChunkExecutionStatus.kt | 2 +- .../io/tolgee/model/batch/BatchJobStatus.kt | 2 +- .../params/PreTranslationByTmJobParams.kt | 1 - .../contentDelivery/AzureFrontDoorConfig.kt | 5 +- .../ContentDeliveryCachePurgingType.kt | 2 +- .../contentDelivery/ContentDeliveryConfig.kt | 11 +- .../model/contentDelivery/ContentStorage.kt | 4 +- .../contentDelivery/ContentStorageType.kt | 2 +- .../io/tolgee/model/dataImport/Import.kt | 3 +- .../io/tolgee/model/dataImport/ImportFile.kt | 43 +- .../io/tolgee/model/dataImport/ImportKey.kt | 4 +- .../tolgee/model/dataImport/ImportLanguage.kt | 3 +- .../model/dataImport/ImportTranslation.kt | 12 +- .../dataImport/issues/ImportFileIssue.kt | 2 - .../dataImport/issues/ImportFileIssueParam.kt | 4 +- .../issues/issueTypes/FileIssueType.kt | 2 +- .../issues/paramTypes/FileIssueParamType.kt | 2 +- .../io/tolgee/model/enums/Announcement.kt | 3 +- .../model/enums/AssignableTranslationState.kt | 2 +- .../model/enums/OrganizationRoleType.kt | 2 +- .../model/enums/ProjectPermissionType.kt | 17 +- .../kotlin/io/tolgee/model/enums/Scope.kt | 148 +- .../model/enums/TranslationCommentState.kt | 2 +- .../io/tolgee/model/enums/TranslationState.kt | 2 +- .../main/kotlin/io/tolgee/model/key/Key.kt | 2 +- .../io/tolgee/model/key/KeyCodeReference.kt | 1 - .../kotlin/io/tolgee/model/key/KeyComment.kt | 4 +- .../kotlin/io/tolgee/model/key/KeyMeta.kt | 12 +- .../kotlin/io/tolgee/model/key/Namespace.kt | 5 +- .../KeyInScreenshotPosition.kt | 2 +- .../KeyScreenshotReferenceId.kt | 2 +- .../tolgee/model/keyBigMeta/KeysDistance.kt | 6 +- .../tolgee/model/keyBigMeta/KeysDistanceId.kt | 2 +- .../tolgee/model/mtServiceConfig/Formality.kt | 4 +- .../model/mtServiceConfig/MtServiceConfig.kt | 15 +- .../tolgee/model/translation/Translation.kt | 8 +- .../model/translation/TranslationComment.kt | 6 +- .../io/tolgee/model/views/BatchJobView.kt | 2 +- .../views/ExtendedUserAccountInProject.kt | 2 +- .../model/views/KeyWithTranslationsView.kt | 43 +- .../io/tolgee/model/views/OrganizationView.kt | 5 +- .../model/views/ProjectWithLanguagesView.kt | 9 +- .../model/views/ProjectWithStatsView.kt | 24 +- .../io/tolgee/model/views/TranslationView.kt | 2 +- .../views/activity/ProjectActivityView.kt | 2 +- .../views/projectStats/ProjectStatsView.kt | 2 +- .../io/tolgee/pubSub/RedisPubSubReceiver.kt | 3 +- .../RedisPubSubReceiverConfiguration.kt | 5 +- .../repository/AnnouncementRepository.kt | 7 +- .../io/tolgee/repository/ApiKeyRepository.kt | 21 +- .../AutoTranslationConfigRepository.kt | 13 +- .../tolgee/repository/AutomationRepository.kt | 14 +- .../tolgee/repository/BatchJobRepository.kt | 25 +- .../tolgee/repository/InvitationRepository.kt | 19 +- .../repository/KeyCodeReferenceRepository.kt | 6 +- .../tolgee/repository/KeyCommentRepository.kt | 7 +- .../io/tolgee/repository/KeyMetaRepository.kt | 5 +- .../io/tolgee/repository/KeyRepository.kt | 55 +- .../KeyScreenshotReferenceRepository.kt | 12 +- .../repository/KeysDistanceRepository.kt | 13 +- .../tolgee/repository/LanguageRepository.kt | 48 +- .../repository/LanguageStatsRepository.kt | 6 +- .../tolgee/repository/NamespaceRepository.kt | 31 +- .../repository/OrganizationRepository.kt | 46 +- .../repository/OrganizationRoleRepository.kt | 7 +- .../io/tolgee/repository/PatRepository.kt | 10 +- .../tolgee/repository/PermissionRepository.kt | 32 +- .../io/tolgee/repository/ProjectRepository.kt | 35 +- .../tolgee/repository/QuickStartRepository.kt | 6 +- .../tolgee/repository/ScreenshotRepository.kt | 21 +- .../io/tolgee/repository/TagRepository.kt | 33 +- .../repository/TranslationRepository.kt | 78 +- .../repository/UserAccountRepository.kt | 40 +- .../repository/WebhookConfigRepository.kt | 15 +- .../ActivityModifiedEntityRepository.kt | 7 +- .../activity/ActivityRevisionRepository.kt | 21 +- .../ContentDeliveryConfigRepository.kt | 22 +- .../ContentStorageRepository.kt | 13 +- .../dataImport/ImportKeyRepository.kt | 2 +- .../dataImport/ImportLanguageRepository.kt | 14 +- .../repository/dataImport/ImportRepository.kt | 14 +- .../dataImport/ImportTranslationRepository.kt | 8 +- .../issues/ImportFileIssueParamRepository.kt | 3 +- .../issues/ImportFileIssueRepository.kt | 8 +- .../MtServiceConfigRepository.kt | 9 +- .../TranslationCommentRepository.kt | 9 +- .../io/tolgee/security/OrganizationHolder.kt | 2 +- .../io/tolgee/security/ProjectHolder.kt | 2 +- .../authentication/AuthenticationConfig.kt | 6 +- .../authentication/AuthenticationFacade.kt | 18 +- .../security/authentication/JwtService.kt | 70 +- .../authentication/TicketAuthentication.kt | 2 +- .../authentication/TolgeeAuthentication.kt | 9 +- .../TolgeeAuthenticationDetails.kt | 2 +- .../io/tolgee/security/ratelimit/Bucket.kt | 2 +- .../security/ratelimit/RateLimitService.kt | 19 +- .../io/tolgee/service/AnnouncementService.kt | 17 +- .../kotlin/io/tolgee/service/AvatarService.kt | 30 +- .../tolgee/service/CachedPermissionService.kt | 25 +- .../service/EmailVerificationService.kt | 23 +- .../io/tolgee/service/ImageUploadService.kt | 27 +- .../io/tolgee/service/InstanceIdService.kt | 17 +- .../io/tolgee/service/InvitationService.kt | 54 +- .../io/tolgee/service/LanguageService.kt | 101 +- .../io/tolgee/service/QuickStartService.kt | 37 +- .../io/tolgee/service/StartupImportService.kt | 76 +- .../io/tolgee/service/TelemetryService.kt | 14 +- .../service/automations/AutomationService.kt | 69 +- .../tolgee/service/bigMeta/BigMetaService.kt | 48 +- .../tolgee/service/bigMeta/KeysDistanceDto.kt | 2 +- .../service/bigMeta/KeysDistanceUtil.kt | 19 +- .../ContentDeliveryConfigService.kt | 45 +- .../dataImport/AsyncImportHardDeleter.kt | 2 +- .../dataImport/CoreImportFilesProcessor.kt | 41 +- .../io/tolgee/service/dataImport/ForceMode.kt | 2 +- .../service/dataImport/ImportDataManager.kt | 44 +- .../service/dataImport/ImportDeleteService.kt | 68 +- .../service/dataImport/ImportService.kt | 143 +- .../dataImport/RemoveExpiredImportService.kt | 3 +- .../service/dataImport/StoredDataImporter.kt | 40 +- .../service/dataImport/SupportedFormats.kt | 4 +- .../processors/FileProcessorContext.kt | 18 +- .../processors/ImportFileProcessor.kt | 16 +- .../dataImport/processors/ProcessorFactory.kt | 5 +- .../dataImport/processors/ZipTypeProcessor.kt | 2 +- .../messageFormat/FormatDetector.kt | 11 +- .../messageFormat/SupportedFormat.kt | 5 +- .../messageFormat/ToICUConverter.kt | 110 +- .../messageFormat/data/PluralData.kt | 5158 +++++++++-------- .../messageFormat/data/PluralExample.kt | 2 +- .../messageFormat/data/PluralLanguage.kt | 2 +- .../processors/po/PoFileProcessor.kt | 38 +- .../dataImport/processors/po/PoParser.kt | 6 +- .../processors/po/data/PoParsedTranslation.kt | 16 +- .../processors/po/data/PoParserResult.kt | 2 +- .../processors/po/data/PoTranslationMeta.kt | 3 +- .../processors/xliff/Xliff12FileProcessor.kt | 25 +- .../io/tolgee/service/export/ExportService.kt | 30 +- .../service/export/FileExporterFactory.kt | 2 +- .../export/dataProvider/ExportDataProvider.kt | 30 +- .../export/dataProvider/ExportDataView.kt | 2 +- .../export/dataProvider/ExportKeyView.kt | 2 +- .../dataProvider/ExportTranslationView.kt | 2 +- .../export/exporters/JsonFileExporter.kt | 18 +- .../export/exporters/XliffFileExporter.kt | 35 +- .../io/tolgee/service/key/KeyMetaService.kt | 64 +- .../io/tolgee/service/key/KeyService.kt | 166 +- .../service/key/KeyWithBaseTranslationView.kt | 1 + .../io/tolgee/service/key/NamespaceService.kt | 52 +- .../service/key/ResolvingKeyImporter.kt | 80 +- .../tolgee/service/key/ScreenshotService.kt | 136 +- .../io/tolgee/service/key/TagService.kt | 110 +- .../service/key/utils/KeyInfoProvider.kt | 20 +- .../tolgee/service/key/utils/KeysImporter.kt | 30 +- .../service/machineTranslation/MetaMapper.kt | 3 +- .../MtCreditBucketService.kt | 49 +- .../machineTranslation/MtLanguageInfo.kt | 2 +- .../service/machineTranslation/MtService.kt | 177 +- .../MtServiceConfigService.kt | 82 +- .../machineTranslation/MtServiceInfo.kt | 2 +- .../machineTranslation/MtSupportedService.kt | 2 +- .../organization/OrganizationRoleService.kt | 114 +- .../organization/OrganizationService.kt | 109 +- .../organization/OrganizationStatsService.kt | 49 +- .../service/project/LanguageStatsService.kt | 30 +- .../tolgee/service/project/ProjectService.kt | 107 +- .../service/project/ProjectStatsService.kt | 18 +- .../CursorUtil.kt | 26 +- .../LanguageStatsProvider.kt | 50 +- .../ProjectStatsProvider.kt | 20 +- .../CursorPredicateProvider.kt | 30 +- .../translationViewBuilder/QueryBase.kt | 23 +- .../QueryGlobalFiltering.kt | 33 +- .../translationViewBuilder/QuerySelection.kt | 8 +- .../QueryTranslationFiltering.kt | 24 +- .../TranslationViewDataProvider.kt | 29 +- .../TranslationsViewQueryBuilder.kt | 24 +- .../tolgee/service/security/ApiKeyService.kt | 64 +- .../LanguageDeletedPermissionUpdater.kt | 28 +- .../io/tolgee/service/security/MfaService.kt | 41 +- .../io/tolgee/service/security/PatService.kt | 53 +- .../service/security/PermissionService.kt | 213 +- .../security/ReCaptchaValidationService.kt | 14 +- .../service/security/SecurityService.kt | 151 +- .../tolgee/service/security/SignUpService.kt | 8 +- .../service/security/UserAccountService.kt | 93 +- .../security/UserCredentialsService.kt | 23 +- .../security/UserPreferencesService.kt | 41 +- .../translation/AutoTranslationService.kt | 182 +- .../translation/TranslationCommentService.kt | 25 +- .../translation/TranslationMemoryService.kt | 9 +- .../service/translation/TranslationService.kt | 227 +- .../main/kotlin/io/tolgee/util/EntityUtil.kt | 3 +- .../kotlin/io/tolgee/util/ImageConverter.kt | 40 +- .../io/tolgee/util/SequenceIdProvider.kt | 3 +- .../kotlin/io/tolgee/util/SlugGenerator.kt | 11 +- .../util/StreamingResponseBodyProvider.kt | 2 +- .../io/tolgee/util/TranslationStatsUtil.kt | 5 +- .../main/kotlin/io/tolgee/util/WordCounter.kt | 5 +- .../io/tolgee/util/criteriaBuilderExt.kt | 12 +- .../kotlin/io/tolgee/util/loggerExtension.kt | 31 +- .../kotlin/io/tolgee/util/transactionUtil.kt | 10 +- .../util/tryUntilItDoesntBreakContraint.kt | 5 +- .../io/tolgee/util/withTimeoutRetrying.kt | 6 +- .../kotlin/io/tolgee/websocket/ActorInfo.kt | 2 +- .../kotlin/io/tolgee/websocket/ActorType.kt | 2 +- .../websocket/RedisWebsocketEventWrapper.kt | 2 +- .../io/tolgee/websocket/WebsocketEvent.kt | 2 +- .../websocket/WebsocketEventPublisher.kt | 5 +- .../io/tolgee/websocket/WebsocketEventType.kt | 3 +- .../security/RequestContextServiceTest.kt | 5 +- .../security/authentication/JwtServiceTest.kt | 25 +- .../ratelimit/RateLimitServiceTest.kt | 28 +- .../unit/CoreImportFileProcessorUnitTest.kt | 15 +- .../io/tolgee/unit/KeysDistanceUtilTest.kt | 23 +- .../test/kotlin/io/tolgee/unit/PathDTOTest.kt | 9 +- .../kotlin/io/tolgee/unit/TextHelperTest.kt | 34 +- ...ureContentStorageConfigCachePurgingTest.kt | 39 +- .../LanguageTagConvertorTest.kt | 1 - .../processors/PropertiesParserTest.kt | 11 +- .../messageFormat/FormatDetectorTest.kt | 11 +- .../messageFormat/ToICUConverterTest.kt | 61 +- .../processors/po/PoFileProcessorTest.kt | 22 +- .../processors/processors/po/PoParserTest.kt | 11 +- .../xliff/Xliff12FileProcessorTest.kt | 39 +- .../xliff/XliffFileProcessorTest.kt | 11 +- .../io/tolgee/unit/util/SlugGeneratorTest.kt | 1 - .../kotlin/io/tolgee/util/WordCounterTest.kt | 1 - .../internal/DebugFeaturesController.kt | 20 +- .../internal/PropertiesController.kt | 7 +- .../controllers/internal/SqlController.kt | 11 +- .../internal/TestClockController.kt | 4 +- .../internal/WebhookTestingController.kt | 2 +- .../AbstractE2eDataController.kt | 31 +- .../AdministrationE2eDataController.kt | 2 +- .../ApiKeysE2eDataController.kt | 2 +- .../AvatarsE2eDataController.kt | 4 +- .../BatchJobsE2eDataController.kt | 2 +- .../ContentDeliveryE2eDataController.kt | 2 +- .../FormerUserE2eDataController.kt | 9 +- .../ImportE2eDataController.kt | 43 +- .../ImportNamespacesE2eDataController.kt | 2 +- .../LanguageE2eDataController.kt | 65 +- .../LanguagePermissionsE2eDataController.kt | 2 +- .../NamespacesE2eDataController.kt | 2 +- .../NewOrganizationE2eDataController.kt | 2 +- .../OrganizationE2eDataController.kt | 147 +- .../PatE2eDataController.kt | 2 +- .../PermissionsE2eDataController.kt | 7 +- .../ProjectLeavingE2eDataController.kt | 4 +- .../ProjectListDashboardE2eDataController.kt | 4 +- .../ProjectTransferringE2eDataController.kt | 4 +- .../e2eData/ProjectsE2eDataController.kt | 310 + ...iveOperationProtectionE2eDataController.kt | 4 +- .../TranslationCommentsE2eDataController.kt | 2 +- .../TranslationDisabledE2eDataController.kt | 2 +- .../TranslationNsAndTagsE2eDataController.kt | 2 +- .../TranslationSingleE2eDataController.kt | 2 +- .../TranslationsE2eDataController.kt | 15 +- .../UserDeletionE2eDataController.kt | 2 +- .../WebsocketTranslationsE2eDataController.kt | 2 +- .../e2e_data/ProjectsE2eDataController.kt | 294 - .../tolgee/fixtures/verifySignatureHeader.kt | 28 +- .../main/kotlin/io/tolgee/fixtures/waitFor.kt | 9 +- .../dockerRunner/DockerContainerRunner.kt | 19 +- .../security/authentication/AllowApiAccess.kt | 4 +- .../AuthenticationDisabledFilter.kt | 22 +- .../authentication/AuthenticationFilter.kt | 53 +- .../AuthenticationInterceptor.kt | 8 +- .../AbstractAuthorizationInterceptor.kt | 120 +- .../OrganizationAuthorizationInterceptor.kt | 22 +- .../ProjectAuthorizationInterceptor.kt | 39 +- .../RequiresProjectPermissions.kt | 2 +- .../ratelimit/GlobalIpRateLimitFilter.kt | 6 +- .../ratelimit/GlobalUserRateLimitFilter.kt | 6 +- .../ratelimit/RateLimitInterceptor.kt | 19 +- .../AuthenticationFilterTest.kt | 36 +- .../AuthenticationInterceptorTest.kt | 7 +- ...rganizationAuthorizationInterceptorTest.kt | 36 +- .../ProjectAuthorizationInterceptorTest.kt | 46 +- .../ratelimit/RateLimitInterceptorTest.kt | 39 +- .../kotlin/io/tolgee/AbstractSpringTest.kt | 17 +- .../kotlin/io/tolgee/CleanDbTestListener.kt | 70 +- .../io/tolgee/ProjectAuthControllerTest.kt | 30 +- .../tolgee/fixtures/AuthRequestPerformer.kt | 21 +- .../fixtures/AuthorizedRequestPerformer.kt | 18 +- .../tolgee/fixtures/BaseRequestPerformer.kt | 20 +- .../io/tolgee/fixtures/EmailTestUtil.kt | 14 +- .../io/tolgee/fixtures/HttpClientMocker.kt | 6 +- .../io/tolgee/fixtures/MimeMessageParser.kt | 56 +- .../ProjectApiKeyAuthRequestPerformer.kt | 30 +- .../fixtures/ProjectAuthRequestPerformer.kt | 24 +- .../ProjectJwtAuthRequestPerformer.kt | 20 +- .../kotlin/io/tolgee/fixtures/RedisRunner.kt | 15 +- .../io/tolgee/fixtures/RequestPerformer.kt | 27 +- .../io/tolgee/fixtures/mockHttpRequests.kt | 5 +- .../main/kotlin/io/tolgee/fixtures/retry.kt | 5 +- .../kotlin/io/tolgee/fixtures/scopeAssert.kt | 4 +- .../io/tolgee/fixtures/statusExpectations.kt | 16 +- .../tolgee/testing/AbstractControllerTest.kt | 63 +- .../testing/AbstractTransactionalTest.kt | 4 +- .../testing/AuthorizedControllerTest.kt | 45 +- .../io/tolgee/testing/InvitationTestUtil.kt | 6 +- .../io/tolgee/testing/PermissionTestUtil.kt | 40 +- .../testing/annotations/ApiKeyPresentMode.kt | 3 +- .../ProjectApiKeyAuthTestMethod.kt | 2 +- .../testing/assertions/ErrorResponseAssert.kt | 12 +- .../StandardValidationMessageAssert.kt | 8 +- .../testing/utils/InMemoryFileStorage.kt | 5 +- build.gradle | 43 +- .../AdvancedPermissionController.kt | 16 +- .../controllers/ContentStorageController.kt | 48 +- .../api/v2/controllers/EeLicenseController.kt | 10 +- .../v2/controllers/WebhookConfigController.kt | 38 +- .../v2/hateoas/PrepareSetLicenseKeyModel.kt | 2 +- .../AzureContentStorageConfigModel.kt | 2 +- .../contentStorage/ContentStorageModel.kt | 2 +- .../ContentStorageModelAssembler.kt | 25 +- .../S3ContentStorageConfigModel.kt | 2 +- .../eeSubscription/EeSubscriptionModel.kt | 2 +- .../EeSubscriptionModelAssembler.kt | 5 +- .../ee/api/v2/hateoas/uasge/UsageModel.kt | 5 +- .../v2/hateoas/webhooks/WebhookConfigModel.kt | 10 +- .../webhooks/WebhookConfigModelAssembler.kt | 5 +- .../component/OnUserCountChangedListener.kt | 3 +- .../PublicEnabledFeaturesProvider.kt | 2 +- .../AzureContentStorageConfigProcessor.kt | 12 +- .../ContentStorageConfigProcessor.kt | 19 +- .../EeContentStorageProvider.kt | 7 +- .../S3ContentStorageConfigProcessor.kt | 12 +- .../configuration/EeLiquibaseConfiguration.kt | 6 +- .../io/tolgee/ee/data/GetMySubscriptionDto.kt | 3 +- .../tolgee/ee/data/PrepareSetLicenseKeyDto.kt | 1 - .../tolgee/ee/data/ProportionalUsagePeriod.kt | 2 +- .../io/tolgee/ee/data/ReportErrorDto.kt | 1 - .../io/tolgee/ee/data/ReportUsageDto.kt | 3 +- .../ee/data/SetLicenseKeyLicensingDto.kt | 4 +- .../io/tolgee/ee/data/StorageTestResult.kt | 2 +- .../io/tolgee/ee/data/SubscriptionStatus.kt | 3 +- .../kotlin/io/tolgee/ee/data/SumUsageItem.kt | 2 +- .../kotlin/io/tolgee/ee/data/UsageData.kt | 8 +- .../ee/service/ContentStorageService.kt | 56 +- .../tolgee/ee/service/EeInvitationService.kt | 4 +- .../tolgee/ee/service/EePermissionService.kt | 26 +- .../ee/service/EeSubscriptionService.kt | 125 +- .../tolgee/ee/service/WebhookConfigService.kt | 33 +- .../tolgee/ee/EeLicensingMockRequestUtil.kt | 88 +- .../kotlin/io/tolgee/ee/UsageReportingTest.kt | 33 +- .../AdvancedPermissionControllerTest.kt | 20 +- .../ContentStorageControllerTest.kt | 107 +- .../v2/controllers/EeLicenseControllerTest.kt | 17 +- .../V2ProjectsInvitationControllerEeTest.kt | 17 +- .../WebhookConfigControllerTest.kt | 13 +- .../ee/service/EeSubscriptionServiceTest.kt | 13 +- 1116 files changed, 16983 insertions(+), 13209 deletions(-) rename backend/api/src/main/kotlin/io/tolgee/hateoas/{user_account => userAccount}/PrivateUserAccountModel.kt (94%) rename backend/api/src/main/kotlin/io/tolgee/hateoas/{user_account => userAccount}/PrivateUserAccountModelAssembler.kt (90%) rename backend/api/src/main/kotlin/io/tolgee/hateoas/{user_account => userAccount}/SimpleUserAccountModel.kt (80%) rename backend/api/src/main/kotlin/io/tolgee/hateoas/{user_account => userAccount}/SimpleUserAccountModelAssembler.kt (80%) rename backend/api/src/main/kotlin/io/tolgee/hateoas/{user_account => userAccount}/UserAccountInProjectModel.kt (93%) rename backend/api/src/main/kotlin/io/tolgee/hateoas/{user_account => userAccount}/UserAccountInProjectModelAssembler.kt (78%) rename backend/api/src/main/kotlin/io/tolgee/hateoas/{user_account => userAccount}/UserAccountModel.kt (93%) rename backend/api/src/main/kotlin/io/tolgee/hateoas/{user_account => userAccount}/UserAccountModelAssembler.kt (84%) rename backend/api/src/main/kotlin/io/tolgee/security/{third_party => thirdParty}/GithubOAuthDelegate.kt (61%) rename backend/api/src/main/kotlin/io/tolgee/security/{third_party => thirdParty}/GoogleOAuthDelegate.kt (74%) rename backend/api/src/main/kotlin/io/tolgee/security/{third_party => thirdParty}/OAuth2Delegate.kt (70%) rename backend/app/src/test/kotlin/io/tolgee/{initial_user_creation => initialUserCreation}/CreateEnabledTest.kt (97%) rename backend/app/src/test/kotlin/io/tolgee/{initial_user_creation => initialUserCreation}/LegacyMigrationTest.kt (93%) rename backend/app/src/test/kotlin/io/tolgee/service/{query_builders => queryBuilders}/CursorUtilUnitTest.kt (57%) rename backend/app/src/test/kotlin/io/tolgee/service/{query_builders => queryBuilders}/TranslationViewDataProviderTest.kt (64%) rename backend/data/src/main/kotlin/io/tolgee/dtos/{query_results => queryResults}/KeyIdFindResult.kt (71%) rename backend/data/src/main/kotlin/io/tolgee/dtos/{query_results => queryResults}/KeyWithTranslationsDto.kt (95%) rename backend/data/src/main/kotlin/io/tolgee/dtos/{query_results => queryResults}/ProjectStatistics.kt (85%) rename backend/data/src/main/kotlin/io/tolgee/dtos/{query_results => queryResults}/TranslationHistoryView.kt (91%) rename backend/data/src/main/kotlin/io/tolgee/dtos/response/{ApiKeyDTO => }/ApiKeyDTO.kt (79%) rename backend/data/src/main/kotlin/io/tolgee/service/{query_builders => queryBuilders}/CursorUtil.kt (75%) rename backend/data/src/main/kotlin/io/tolgee/service/{query_builders => queryBuilders}/LanguageStatsProvider.kt (78%) rename backend/data/src/main/kotlin/io/tolgee/service/{query_builders => queryBuilders}/ProjectStatsProvider.kt (90%) rename backend/data/src/main/kotlin/io/tolgee/service/{query_builders => queryBuilders}/translationViewBuilder/CursorPredicateProvider.kt (72%) rename backend/data/src/main/kotlin/io/tolgee/service/{query_builders => queryBuilders}/translationViewBuilder/QueryBase.kt (94%) rename backend/data/src/main/kotlin/io/tolgee/service/{query_builders => queryBuilders}/translationViewBuilder/QueryGlobalFiltering.kt (81%) rename backend/data/src/main/kotlin/io/tolgee/service/{query_builders => queryBuilders}/translationViewBuilder/QuerySelection.kt (69%) rename backend/data/src/main/kotlin/io/tolgee/service/{query_builders => queryBuilders}/translationViewBuilder/QueryTranslationFiltering.kt (81%) rename backend/data/src/main/kotlin/io/tolgee/service/{query_builders => queryBuilders}/translationViewBuilder/TranslationViewDataProvider.kt (79%) rename backend/data/src/main/kotlin/io/tolgee/service/{query_builders => queryBuilders}/translationViewBuilder/TranslationsViewQueryBuilder.kt (82%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/AbstractE2eDataController.kt (79%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/AdministrationE2eDataController.kt (95%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/ApiKeysE2eDataController.kt (94%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/AvatarsE2eDataController.kt (91%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/BatchJobsE2eDataController.kt (94%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/ContentDeliveryE2eDataController.kt (94%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/FormerUserE2eDataController.kt (85%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/ImportE2eDataController.kt (84%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/ImportNamespacesE2eDataController.kt (93%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/LanguageE2eDataController.kt (53%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/LanguagePermissionsE2eDataController.kt (95%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/NamespacesE2eDataController.kt (93%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/NewOrganizationE2eDataController.kt (95%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/OrganizationE2eDataController.kt (61%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/PatE2eDataController.kt (94%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/PermissionsE2eDataController.kt (92%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/ProjectLeavingE2eDataController.kt (94%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/ProjectListDashboardE2eDataController.kt (93%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/ProjectTransferringE2eDataController.kt (94%) create mode 100644 backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectsE2eDataController.kt rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/SensitiveOperationProtectionE2eDataController.kt (97%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/TranslationCommentsE2eDataController.kt (97%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/TranslationDisabledE2eDataController.kt (93%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/TranslationNsAndTagsE2eDataController.kt (93%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/TranslationSingleE2eDataController.kt (97%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/TranslationsE2eDataController.kt (88%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/UserDeletionE2eDataController.kt (94%) rename backend/development/src/main/kotlin/io/tolgee/controllers/internal/{e2e_data => e2eData}/WebsocketTranslationsE2eDataController.kt (95%) delete mode 100644 backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ProjectsE2eDataController.kt diff --git a/.editorconfig b/.editorconfig index 76b80915bc..3d85dd6197 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,7 +1,11 @@ [*.{kt, kts}] -disabled_rules = no-wildcard-imports +ktlint_standard_no-wildcard-imports = disabled +ktlint_standard_filename = disabled indent_size = 2 insert_final_newline = true # possible values: number (e.g. 120) (package name, imports & comments are ignored), "off" # it's automatically set to 100 on `ktlint --android ...` (per Android Kotlin Style Guide) max_line_length = 120 + +[backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/data/PluralData.kt] +max_line_length = 500 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bd10db573f..09f7da9686 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -435,4 +435,4 @@ jobs: key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} - name: Run ktlint - run: ./gradlew ktlint + run: ./gradlew ktlintCheck diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/AdministrationController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/AdministrationController.kt index 4cfec5a21b..bca52cb55e 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/AdministrationController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/AdministrationController.kt @@ -5,8 +5,8 @@ import io.tolgee.constants.Message import io.tolgee.exceptions.BadRequestException import io.tolgee.hateoas.organization.OrganizationModel import io.tolgee.hateoas.organization.OrganizationModelAssembler -import io.tolgee.hateoas.user_account.UserAccountModel -import io.tolgee.hateoas.user_account.UserAccountModelAssembler +import io.tolgee.hateoas.userAccount.UserAccountModel +import io.tolgee.hateoas.userAccount.UserAccountModelAssembler import io.tolgee.model.UserAccount import io.tolgee.model.views.OrganizationView import io.tolgee.security.authentication.AuthenticationFacade @@ -33,8 +33,8 @@ import io.swagger.v3.oas.annotations.tags.Tag as OpenApiTag @CrossOrigin(origins = ["*"]) @RequestMapping( value = [ - "/v2/administration" - ] + "/v2/administration", + ], ) @OpenApiTag(name = "Admin", description = "Server administration") class AdministrationController( @@ -45,15 +45,16 @@ class AdministrationController( private val userAccountService: UserAccountService, private val pagedResourcesAssembler: PagedResourcesAssembler, private val userAccountModelAssembler: UserAccountModelAssembler, - private val jwtService: JwtService + private val jwtService: JwtService, ) : IController { - @GetMapping(value = ["/organizations"]) @Operation(summary = "Get all server organizations") @RequiresSuperAuthentication fun getOrganizations( - @ParameterObject @SortDefault(sort = ["name"]) pageable: Pageable, - search: String? = null + @ParameterObject + @SortDefault(sort = ["name"]) + pageable: Pageable, + search: String? = null, ): PagedModel { val organizations = organizationService.findAllPaged(pageable, search, authenticationFacade.authenticatedUser.id) return pagedOrganizationResourcesAssembler.toModel(organizations, organizationModelAssembler) @@ -63,8 +64,10 @@ class AdministrationController( @Operation(summary = "Get all server users") @RequiresSuperAuthentication fun getUsers( - @ParameterObject @SortDefault(sort = ["name"]) pageable: Pageable, - search: String? = null + @ParameterObject + @SortDefault(sort = ["name"]) + pageable: Pageable, + search: String? = null, ): PagedModel { val users = userAccountService.findAllWithDisabledPaged(pageable, search) return pagedResourcesAssembler.toModel(users, userAccountModelAssembler) @@ -73,7 +76,9 @@ class AdministrationController( @DeleteMapping(value = ["/users/{userId}"]) @Operation(summary = "Deletes an user") @RequiresSuperAuthentication - fun deleteUser(@PathVariable userId: Long) { + fun deleteUser( + @PathVariable userId: Long, + ) { if (userId == authenticationFacade.authenticatedUser.id) { throw BadRequestException(Message.CANNOT_DELETE_YOUR_OWN_ACCOUNT) } @@ -83,7 +88,9 @@ class AdministrationController( @PutMapping(value = ["/users/{userId}/disable"]) @Operation(summary = "Deletes an user") @RequiresSuperAuthentication - fun disableUser(@PathVariable userId: Long) { + fun disableUser( + @PathVariable userId: Long, + ) { if (userId == authenticationFacade.authenticatedUser.id) { throw BadRequestException(Message.CANNOT_DISABLE_YOUR_OWN_ACCOUNT) } @@ -93,7 +100,9 @@ class AdministrationController( @PutMapping(value = ["/users/{userId}/enable"]) @Operation(summary = "Deletes an user") @RequiresSuperAuthentication - fun enableUser(@PathVariable userId: Long) { + fun enableUser( + @PathVariable userId: Long, + ) { userAccountService.enable(userId) } @@ -102,7 +111,7 @@ class AdministrationController( @RequiresSuperAuthentication fun setRole( @PathVariable userId: Long, - @PathVariable role: UserAccount.Role + @PathVariable role: UserAccount.Role, ) { val user = userAccountService.get(userId) user.role = role diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/AllKeysController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/AllKeysController.kt index 4554096c94..594f702485 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/AllKeysController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/AllKeysController.kt @@ -22,7 +22,7 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping( value = [ "/v2/projects/{projectId}/all-keys", - ] + ], ) @Tag(name = "All localization keys", description = "All localization keys in the project") class AllKeysController( diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/AnnouncementController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/AnnouncementController.kt index 0880d15acc..e6d7a73f28 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/AnnouncementController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/AnnouncementController.kt @@ -17,12 +17,12 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping( value = [ "/v2/announcement", - ] + ], ) @Tag(name = "New features announcements") class AnnouncementController( private val announcementService: AnnouncementService, - private val authenticationFacade: AuthenticationFacade + private val authenticationFacade: AuthenticationFacade, ) : IController { @GetMapping("") @Operation(description = "Get latest announcement") diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ApiKeyController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ApiKeyController.kt index f677a2ad35..31c5d1bfd0 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ApiKeyController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ApiKeyController.kt @@ -65,11 +65,13 @@ class ApiKeyController( private val pagedResourcesAssembler: PagedResourcesAssembler, private val permissionService: PermissionService, ) { - @PostMapping(path = ["/api-keys"]) @Operation(summary = "Creates new API key with provided scopes") @RequiresSuperAuthentication - fun create(@RequestBody @Valid dto: CreateApiKeyDto): RevealedApiKeyModel { + fun create( + @RequestBody @Valid + dto: CreateApiKeyDto, + ): RevealedApiKeyModel { val project = projectService.get(dto.projectId) if (authenticationFacade.authenticatedUser.role != UserAccount.Role.ADMIN) { securityService.checkApiKeyScopes(dto.scopes, project) @@ -79,7 +81,7 @@ class ApiKeyController( scopes = dto.scopes, project = project, expiresAt = dto.expiresAt, - description = dto.description + description = dto.description, ).let { revealedApiKeyModelAssembler.toModel(it) } @@ -87,14 +89,19 @@ class ApiKeyController( @Operation(summary = "Returns user's api keys") @GetMapping(path = ["/api-keys"]) - fun allByUser(pageable: Pageable, @RequestParam filterProjectId: Long?): PagedModel { + fun allByUser( + pageable: Pageable, + @RequestParam filterProjectId: Long?, + ): PagedModel { return apiKeyService.getAllByUser(authenticationFacade.authenticatedUser.id, filterProjectId, pageable) .let { pagedResourcesAssembler.toModel(it, apiKeyModelAssembler) } } @Operation(summary = "Returns specific API key info") @GetMapping(path = ["/api-keys/{keyId:[0-9]+}"]) - fun get(@PathVariable keyId: Long): ApiKeyModel { + fun get( + @PathVariable keyId: Long, + ): ApiKeyModel { val apiKey = apiKeyService.findOptional(keyId).orElseThrow { NotFoundException() } if (apiKey.userAccount.id != authenticationFacade.authenticatedUser.id) { securityService.checkProjectPermission(apiKey.project.id, Scope.ADMIN) @@ -112,17 +119,18 @@ class ApiKeyController( val apiKey = authenticationFacade.projectApiKeyEntity - val permissionData = permissionService.getProjectPermissionData( - apiKey.project.id, - authenticationFacade.authenticatedUser.id - ) + val permissionData = + permissionService.getProjectPermissionData( + apiKey.project.id, + authenticationFacade.authenticatedUser.id, + ) val translateLanguageIds = permissionData.computedPermissions.translateLanguageIds.toNormalizedPermittedLanguageSet() return ApiKeyWithLanguagesModel( apiKeyModelAssembler.toModel(apiKey), - permittedLanguageIds = translateLanguageIds + permittedLanguageIds = translateLanguageIds, ) } @@ -131,31 +139,35 @@ class ApiKeyController( @AllowApiAccess() fun getCurrentPermissions( @RequestParam - @Parameter(description = "Required when using with PAT") projectId: Long? + @Parameter(description = "Required when using with PAT") + projectId: Long?, ): ApiKeyPermissionsModel { val apiKeyAuthentication = authenticationFacade.isProjectApiKeyAuth val personalAccessTokenAuth = authenticationFacade.isPersonalAccessTokenAuth - val projectIdNotNull = when { - apiKeyAuthentication -> - authenticationFacade.projectApiKey.projectId + val projectIdNotNull = + when { + apiKeyAuthentication -> + authenticationFacade.projectApiKey.projectId - personalAccessTokenAuth -> - projectId ?: throw BadRequestException(Message.NO_PROJECT_ID_PROVIDED) + personalAccessTokenAuth -> + projectId ?: throw BadRequestException(Message.NO_PROJECT_ID_PROVIDED) - else -> throw BadRequestException(Message.INVALID_AUTHENTICATION_METHOD) - } + else -> throw BadRequestException(Message.INVALID_AUTHENTICATION_METHOD) + } - val permissionData = permissionService.getProjectPermissionData( - projectIdNotNull, - authenticationFacade.authenticatedUser.id - ) + val permissionData = + permissionService.getProjectPermissionData( + projectIdNotNull, + authenticationFacade.authenticatedUser.id, + ) val computed = permissionData.computedPermissions - val scopes = when { - apiKeyAuthentication -> authenticationFacade.projectApiKey.scopes.toTypedArray() - else -> computed.scopes - } + val scopes = + when { + apiKeyAuthentication -> authenticationFacade.projectApiKey.scopes.toTypedArray() + else -> computed.scopes + } return ApiKeyPermissionsModel( projectIdNotNull, @@ -163,7 +175,7 @@ class ApiKeyController( translateLanguageIds = computed.translateLanguageIds.toNormalizedPermittedLanguageSet(), viewLanguageIds = computed.viewLanguageIds.toNormalizedPermittedLanguageSet(), stateChangeLanguageIds = computed.stateChangeLanguageIds.toNormalizedPermittedLanguageSet(), - scopes = scopes + scopes = scopes, ) } @@ -185,7 +197,11 @@ class ApiKeyController( @PutMapping(path = ["/api-keys/{apiKeyId:[0-9]+}"]) @Operation(summary = "Edits existing API key") @RequiresSuperAuthentication - fun update(@RequestBody @Valid dto: V2EditApiKeyDto, @PathVariable apiKeyId: Long): ApiKeyModel { + fun update( + @RequestBody @Valid + dto: V2EditApiKeyDto, + @PathVariable apiKeyId: Long, + ): ApiKeyModel { val apiKey = apiKeyService.get(apiKeyId) checkOwner(apiKey) securityService.checkApiKeyScopes(dto.scopes, apiKey.project) @@ -195,12 +211,13 @@ class ApiKeyController( @PutMapping(value = ["/api-keys/{apiKeyId:[0-9]+}/regenerate"]) @Operation( - summary = "Regenerates API key. It generates new API key value and updates its time of expiration." + summary = "Regenerates API key. It generates new API key value and updates its time of expiration.", ) @RequiresSuperAuthentication fun regenerate( - @RequestBody @Valid dto: RegenerateApiKeyDto, - @PathVariable apiKeyId: Long + @RequestBody @Valid + dto: RegenerateApiKeyDto, + @PathVariable apiKeyId: Long, ): RevealedApiKeyModel { checkOwner(apiKeyId) return revealedApiKeyModelAssembler.toModel(apiKeyService.regenerate(apiKeyId, dto.expiresAt)) @@ -209,7 +226,9 @@ class ApiKeyController( @DeleteMapping(path = ["/api-keys/{apiKeyId:[0-9]+}"]) @Operation(summary = "Deletes API key") @RequiresSuperAuthentication - fun delete(@PathVariable apiKeyId: Long) { + fun delete( + @PathVariable apiKeyId: Long, + ) { val apiKey = apiKeyService.findOptional(apiKeyId).orElseThrow { NotFoundException(Message.API_KEY_NOT_FOUND) } checkOwner(apiKey) apiKeyService.deleteApiKey(apiKey) @@ -239,8 +258,9 @@ class ApiKeyController( content = [ Content( mediaType = "application/json", - schema = Schema( - example = """ + schema = + Schema( + example = """ { "TRANSLATE":[ "translations.view", @@ -267,12 +287,12 @@ class ApiKeyController( "translations.view", "screenshots.view" ] - }""" - ) - ) - ] - ) - ] + }""", + ), + ), + ], + ), + ], ) @Deprecated(message = "Don't use this endpoint, it's useless.") val scopes: Map> by lazy { diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/AutoTranslationController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/AutoTranslationController.kt index 0170697702..c84eb43ae2 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/AutoTranslationController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/AutoTranslationController.kt @@ -26,8 +26,8 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping( value = [ "/v2/projects/{projectId:[0-9]+}/keys/{keyId:[0-9]+}/auto-translate", - "/v2/projects/keys/{keyId:[0-9]+}/auto-translate" - ] + "/v2/projects/keys/{keyId:[0-9]+}/auto-translate", + ], ) @Tag(name = "Auto Translation") @Suppress("MVCPathVariableInspection") @@ -35,7 +35,7 @@ class AutoTranslationController( private val autoTranslationService: AutoTranslationService, private val keyService: KeyService, private val projectHolder: ProjectHolder, - private val securityService: SecurityService + private val securityService: SecurityService, ) { @PutMapping("") @Operation( @@ -44,7 +44,7 @@ class AutoTranslationController( You need to set at least one of useMachineTranslation or useTranslationMemory to true. This will replace the the existing translation with the result obtained from specified source! - """ + """, ) @RequiresProjectPermissions([ Scope.TRANSLATIONS_EDIT ]) @AllowApiAccess @@ -52,17 +52,19 @@ This will replace the the existing translation with the result obtained from spe @PathVariable keyId: Long, @Parameter( description = """Tags of languages to auto-translate. -When no languages provided, it translates only untranslated languages.""" +When no languages provided, it translates only untranslated languages.""", ) - @RequestParam languages: Set?, + @RequestParam + languages: Set?, @RequestParam useMachineTranslation: Boolean?, - @RequestParam useTranslationMemory: Boolean? + @RequestParam useTranslationMemory: Boolean?, ) { val key = keyService.get(keyId) - val languagesToTranslate = securityService.filterViewPermissionByTag( - projectHolder.project.id, - languages ?: getAllLanguagesToTranslate() - ) + val languagesToTranslate = + securityService.filterViewPermissionByTag( + projectHolder.project.id, + languages ?: getAllLanguagesToTranslate(), + ) checkPermissions(key, languagesToTranslate) validateServices(useMachineTranslation, useTranslationMemory) @@ -76,17 +78,23 @@ When no languages provided, it translates only untranslated languages.""" forcedLanguageTags = languages?.toList(), useTranslationMemory = useTranslationMemory ?: false, useMachineTranslation = useMachineTranslation ?: false, - isBatch = true + isBatch = true, ) } - private fun validateServices(useMachineTranslation: Boolean?, useTranslationMemory: Boolean?) { + private fun validateServices( + useMachineTranslation: Boolean?, + useTranslationMemory: Boolean?, + ) { if (useMachineTranslation != true && useTranslationMemory != true) { throw BadRequestException(Message.NO_AUTO_TRANSLATION_METHOD) } } - private fun checkPermissions(key: Key, languagesToTranslate: Set) { + private fun checkPermissions( + key: Key, + languagesToTranslate: Set, + ) { keyService.checkInProject(key, projectHolder.project.id) securityService.checkLanguageTranslatePermissionsByTag(languagesToTranslate, projectHolder.project.id) } @@ -100,7 +108,7 @@ When no languages provided, it translates only untranslated languages.""" private fun getBaseLanguageTag(): String { return projectHolder.projectEntity.baseLanguage?.tag ?: throw NotFoundException( - Message.BASE_LANGUAGE_NOT_FOUND + Message.BASE_LANGUAGE_NOT_FOUND, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/BigMetaController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/BigMetaController.kt index c929ed6fcf..bc5178dacf 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/BigMetaController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/BigMetaController.kt @@ -23,7 +23,7 @@ import org.springframework.web.bind.annotation.RestController @Suppress("MVCPathVariableInspection") @RestController @RequestMapping( - value = ["/v2/projects/{projectId:\\d+}", "/v2/projects"] + value = ["/v2/projects/{projectId:\\d+}", "/v2/projects"], ) @Tag(name = "Big Meta data about the keys in project") class BigMetaController( @@ -35,7 +35,10 @@ class BigMetaController( @Operation(summary = "Stores a bigMeta for a project") @RequiresProjectPermissions([Scope.TRANSLATIONS_EDIT]) @AllowApiAccess - fun store(@RequestBody @Valid data: BigMetaDto) { + fun store( + @RequestBody @Valid + data: BigMetaDto, + ) { bigMetaService.store(data, projectHolder.projectEntity) } @@ -44,7 +47,7 @@ class BigMetaController( @RequiresProjectPermissions([Scope.TRANSLATIONS_VIEW]) @AllowApiAccess fun getBigMeta( - @PathVariable("id") id: Long + @PathVariable("id") id: Long, ): CollectionModel { val projectId = projectHolder.project.id val result = bigMetaService.getCloseKeysWithBaseTranslation(id, projectId) diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/BusinessEventController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/BusinessEventController.kt index 2d8c61c5dc..24fbad3c2b 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/BusinessEventController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/BusinessEventController.kt @@ -28,7 +28,9 @@ class BusinessEventController( ) : Logging { @PostMapping("/report") @Operation(summary = "Reports business event") - fun report(@RequestBody eventData: BusinessEventReportRequest) { + fun report( + @RequestBody eventData: BusinessEventReportRequest, + ) { try { eventData.projectId?.let { securityService.checkAnyProjectPermission(it) } eventData.organizationId?.let { organizationRoleService.checkUserCanView(it) } @@ -44,7 +46,9 @@ class BusinessEventController( @PostMapping("/identify") @Operation(summary = "Identifies user") - fun identify(@RequestBody eventData: IdentifyRequest) { + fun identify( + @RequestBody eventData: IdentifyRequest, + ) { try { businessEventPublisher.publish(eventData) } catch (e: Throwable) { diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ConfigurationController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ConfigurationController.kt index 6ae0e52710..8b37f46ff6 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ConfigurationController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ConfigurationController.kt @@ -18,44 +18,48 @@ import org.springframework.web.bind.annotation.RestController @CrossOrigin(origins = ["*"]) @RequestMapping("/api/public/") @Tag(name = "Public configuration controller") -class ConfigurationController @Autowired constructor( - private val configuration: TolgeeProperties, - private val applicationContext: ApplicationContext, - private val publicBillingConfProvider: PublicBillingConfProvider, - private val versionProvider: VersionProvider -) : IController { - - @GetMapping(value = ["configuration"]) - @Operation(summary = "Returns server configuration information") - fun getPublicConfiguration(): PublicConfigurationDTO { - val machineTranslationServices = PublicConfigurationDTO.MtServicesDTO( - defaultPrimaryService = getPrimaryMtService(), - services = getMtServices() - ) - return PublicConfigurationDTO( - properties = configuration, - machineTranslationServices = machineTranslationServices, - billing = publicBillingConfProvider(), - versionProvider.version - ) - } +class ConfigurationController + @Autowired + constructor( + private val configuration: TolgeeProperties, + private val applicationContext: ApplicationContext, + private val publicBillingConfProvider: PublicBillingConfProvider, + private val versionProvider: VersionProvider, + ) : IController { + @GetMapping(value = ["configuration"]) + @Operation(summary = "Returns server configuration information") + fun getPublicConfiguration(): PublicConfigurationDTO { + val machineTranslationServices = + PublicConfigurationDTO.MtServicesDTO( + defaultPrimaryService = getPrimaryMtService(), + services = getMtServices(), + ) + return PublicConfigurationDTO( + properties = configuration, + machineTranslationServices = machineTranslationServices, + billing = publicBillingConfProvider(), + versionProvider.version, + ) + } - private fun getPrimaryMtService(): MtServiceType? { - val primaryMtService = MtServiceType.values().find { - applicationContext.getBean(it.propertyClass).defaultPrimary + private fun getPrimaryMtService(): MtServiceType? { + val primaryMtService = + MtServiceType.values().find { + applicationContext.getBean(it.propertyClass).defaultPrimary + } + return primaryMtService } - return primaryMtService - } - private fun getMtServices(): Map { - val mtServices = MtServiceType.values() - .sortedBy { it.order } - .associateWith { - PublicConfigurationDTO.MtServiceDTO( - applicationContext.getBean(it.providerClass).isEnabled, - applicationContext.getBean(it.propertyClass).defaultEnabled - ) - } - return mtServices + private fun getMtServices(): Map { + val mtServices = + MtServiceType.values() + .sortedBy { it.order } + .associateWith { + PublicConfigurationDTO.MtServiceDTO( + applicationContext.getBean(it.providerClass).isEnabled, + applicationContext.getBean(it.propertyClass).defaultEnabled, + ) + } + return mtServices + } } -} diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/InitialDataController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/InitialDataController.kt index ff63ea7e08..20f9a49689 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/InitialDataController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/InitialDataController.kt @@ -18,7 +18,7 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping( value = [ "/v2/public/initial-data", - ] + ], ) @Tag(name = "Initial data") class InitialDataController( @@ -34,11 +34,16 @@ class InitialDataController( @GetMapping(value = [""]) @Operation(description = "Returns initial data always required by frontend") fun get(): InitialDataModel { - - val data = InitialDataModel( - serverConfiguration = configurationController.getPublicConfiguration(), - eeSubscription = eeSubscriptionService.findSubscriptionEntity()?.let { eeSubscriptionModelAssembler.toModel(it) } - ) + val data = + InitialDataModel( + serverConfiguration = configurationController.getPublicConfiguration(), + eeSubscription = + eeSubscriptionService.findSubscriptionEntity()?.let { + eeSubscriptionModelAssembler.toModel( + it, + ) + }, + ) val userAccount = authenticationFacade.authenticatedUserOrNull if (userAccount != null) { diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/KeyController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/KeyController.kt index e7fe55ae82..085e3c06ae 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/KeyController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/KeyController.kt @@ -68,8 +68,8 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping( value = [ "/v2/projects/{projectId}/keys", - "/v2/projects/keys" - ] + "/v2/projects/keys", + ], ) @Tag(name = "Localization keys", description = "Manipulates localization keys and their translations and metadata") class KeyController( @@ -86,7 +86,7 @@ class KeyController( private val pagedResourcesAssembler: PagedResourcesAssembler, private val screenshotModelAssembler: ScreenshotModelAssembler, private val keyWithScreenshotsModelAssembler: KeyWithScreenshotsModelAssembler, - private val languageModelAssembler: LanguageModelAssembler + private val languageModelAssembler: LanguageModelAssembler, ) : IController { @PostMapping(value = ["/create", ""]) @Operation(summary = "Creates new key") @@ -94,7 +94,10 @@ class KeyController( @RequestActivity(ActivityType.CREATE_KEY) @RequiresProjectPermissions([Scope.KEYS_CREATE]) @AllowApiAccess - fun create(@RequestBody @Valid dto: CreateKeyDto): ResponseEntity { + fun create( + @RequestBody @Valid + dto: CreateKeyDto, + ): ResponseEntity { checkScrenshotUploadPermissions(dto) checkTranslatePermission(dto) checkCanStoreBigMeta(dto) @@ -136,7 +139,12 @@ class KeyController( @Operation(summary = "More") @UseDefaultPermissions // Security: key permissions are checked separately in method body @AllowApiAccess - fun complexEdit(@PathVariable id: Long, @RequestBody @Valid dto: ComplexEditKeyDto): KeyWithDataModel { + fun complexEdit( + @PathVariable + id: Long, + @RequestBody @Valid + dto: ComplexEditKeyDto, + ): KeyWithDataModel { return KeyComplexEditHelper(applicationContext, id, dto).doComplexUpdate() } @@ -145,7 +153,12 @@ class KeyController( @RequestActivity(ActivityType.KEY_NAME_EDIT) @RequiresProjectPermissions([Scope.KEYS_EDIT]) @AllowApiAccess - fun edit(@PathVariable id: Long, @RequestBody @Valid dto: EditKeyDto): KeyModel { + fun edit( + @PathVariable + id: Long, + @RequestBody @Valid + dto: EditKeyDto, + ): KeyModel { val key = keyService.findOptional(id).orElseThrow { NotFoundException() } key.checkInProject() return keyService.edit(id, dto).model @@ -157,7 +170,9 @@ class KeyController( @RequestActivity(ActivityType.KEY_DELETE) @RequiresProjectPermissions([Scope.KEYS_DELETE]) @AllowApiAccess - fun delete(@PathVariable ids: Set) { + fun delete( + @PathVariable ids: Set, + ) { keyService.findAllWithProjectsAndMetas(ids).forEach { it.checkInProject() } keyService.deleteMultiple(ids) } @@ -170,7 +185,7 @@ class KeyController( fun getAll( @ParameterObject @SortDefault("id") - pageable: Pageable + pageable: Pageable, ): PagedModel { val data = keyService.getPaged(projectHolder.project.id, pageable) return keyPagedResourcesAssembler.toModel(data, keyModelAssembler) @@ -182,22 +197,29 @@ class KeyController( @RequestActivity(ActivityType.KEY_DELETE) @RequiresProjectPermissions([Scope.KEYS_DELETE]) @AllowApiAccess - fun delete(@RequestBody @Valid dto: DeleteKeysDto) { + fun delete( + @RequestBody @Valid + dto: DeleteKeysDto, + ) { delete(dto.ids.toSet()) } @PostMapping("/import") @Operation( - summary = "Imports new keys with translations. If key already exists, its translations and tags" + - " are not updated." + summary = + "Imports new keys with translations. If key already exists, its translations and tags" + + " are not updated.", ) @RequestActivity(ActivityType.IMPORT) @RequiresProjectPermissions([Scope.KEYS_CREATE]) // Security: language translate permissions are handled in service @AllowApiAccess - fun importKeys(@RequestBody @Valid dto: ImportKeysDto) { + fun importKeys( + @RequestBody @Valid + dto: ImportKeysDto, + ) { securityService.checkLanguageTranslatePermissionByTag( projectHolder.project.id, - dto.keys.flatMap { it.translations.keys }.toSet() + dto.keys.flatMap { it.translations.keys }.toSet(), ) keyService.importKeys(dto.keys, projectHolder.projectEntity) @@ -208,24 +230,30 @@ class KeyController( @RequestActivity(ActivityType.IMPORT) @UseDefaultPermissions // Security: permissions are handled in service @AllowApiAccess - fun importKeys(@RequestBody @Valid dto: ImportKeysResolvableDto): KeyImportResolvableResultModel { + fun importKeys( + @RequestBody @Valid + dto: ImportKeysResolvableDto, + ): KeyImportResolvableResultModel { val uploadedImageToScreenshotMap = keyService.importKeysResolvable(dto.keys, projectHolder.projectEntity) - val screenshots = uploadedImageToScreenshotMap.screenshots - .map { (uploadedImageId, screenshot) -> - uploadedImageId to screenshotModelAssembler.toModel(screenshot) - }.toMap() + val screenshots = + uploadedImageToScreenshotMap.screenshots + .map { (uploadedImageId, screenshot) -> + uploadedImageId to screenshotModelAssembler.toModel(screenshot) + }.toMap() - val keys = uploadedImageToScreenshotMap.keys - .map { key -> keyModelAssembler.toModel(key) } + val keys = + uploadedImageToScreenshotMap.keys + .map { key -> keyModelAssembler.toModel(key) } return KeyImportResolvableResultModel(keys, screenshots) } @GetMapping("/search") @Operation( - summary = "This endpoint helps you to find desired key by keyName, " + - "base translation or translation in specified language." + summary = + "This endpoint helps you to find desired key by keyName, " + + "base translation or translation in specified language.", ) @RequiresProjectPermissions([Scope.KEYS_VIEW]) @AllowApiAccess @@ -250,8 +278,9 @@ class KeyController( @PostMapping("/info") @Operation( - summary = "Returns information about keys. (KeyData, Screenshots, Translation in specified language)" + - "If key is not found, it's not included in the response." + summary = + "Returns information about keys. (KeyData, Screenshots, Translation in specified language)" + + "If key is not found, it's not included in the response.", ) @RequiresProjectPermissions([Scope.KEYS_VIEW, Scope.SCREENSHOTS_VIEW, Scope.TRANSLATIONS_VIEW]) @AllowApiAccess @@ -268,7 +297,9 @@ class KeyController( @AllowApiAccess @RequiresProjectPermissions([Scope.KEYS_VIEW]) @Operation(summary = "Returns languages, in which key is disabled") - fun getDisabledLanguages(@PathVariable id: Long): CollectionModel { + fun getDisabledLanguages( + @PathVariable id: Long, + ): CollectionModel { val languages = keyService.getDisabledLanguages(projectHolder.project.id, id) return languageModelAssembler.toCollectionModel(languages.toViews()) } @@ -279,7 +310,8 @@ class KeyController( @Operation(summary = "Sets languages, in which key is disabled") fun setDisabledLanguages( @PathVariable id: Long, - @RequestBody @Valid dto: SetDisabledLanguagesRequest + @RequestBody @Valid + dto: SetDisabledLanguagesRequest, ): CollectionModel { val languages = keyService.setDisabledLanguages(projectHolder.project.id, id, dto.languageIds) return languageModelAssembler.toCollectionModel(languages.toViews()) diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/KeyScreenshotController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/KeyScreenshotController.kt index 6abb99f8ff..5fb04afe0d 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/KeyScreenshotController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/KeyScreenshotController.kt @@ -47,15 +47,15 @@ import org.springframework.web.multipart.MultipartFile @RequestMapping( value = [ "/v2/projects/keys/{keyId}/screenshots", - "/v2/projects/{projectId:[0-9]+}/keys/{keyId}/screenshots" - ] + "/v2/projects/{projectId:[0-9]+}/keys/{keyId}/screenshots", + ], ) @Tag(name = "Screenshots") class KeyScreenshotController( private val screenshotService: ScreenshotService, private val keyService: KeyService, private val projectHolder: ProjectHolder, - private val screenshotModelAssembler: ScreenshotModelAssembler + private val screenshotModelAssembler: ScreenshotModelAssembler, ) { @PostMapping("", consumes = [MediaType.MULTIPART_FORM_DATA_VALUE]) @Operation(summary = "Upload screenshot for specific key") @@ -67,7 +67,7 @@ class KeyScreenshotController( fun uploadScreenshot( @PathVariable keyId: Long, @RequestPart("screenshot") screenshot: MultipartFile, - @RequestPart("info", required = false) info: ScreenshotInfoDto? + @RequestPart("info", required = false) info: ScreenshotInfoDto?, ): ResponseEntity { val contentTypes = listOf("image/png", "image/jpeg", "image/gif") if (!contentTypes.contains(screenshot.contentType!!)) { @@ -83,7 +83,9 @@ class KeyScreenshotController( @Operation(summary = "Returns all screenshots for specified key") @RequiresProjectPermissions([ Scope.SCREENSHOTS_VIEW ]) @AllowApiAccess - fun getKeyScreenshots(@PathVariable keyId: Long): CollectionModel { + fun getKeyScreenshots( + @PathVariable keyId: Long, + ): CollectionModel { val keyEntity = keyService.findOptional(keyId).orElseThrow { NotFoundException() } keyEntity.checkInProject() return screenshotModelAssembler.toCollectionModel(screenshotService.findAll(keyEntity)) @@ -94,7 +96,10 @@ class KeyScreenshotController( @RequestActivity(ActivityType.SCREENSHOT_DELETE) @RequiresProjectPermissions([ Scope.SCREENSHOTS_DELETE ]) @AllowApiAccess - fun deleteScreenshots(@PathVariable("ids") ids: Set, @PathVariable keyId: Long) { + fun deleteScreenshots( + @PathVariable("ids") ids: Set, + @PathVariable keyId: Long, + ) { val screenshots = screenshotService.findByIdIn(ids) screenshots.forEach { it.checkInProject() diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/MachineTranslationSettingsController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/MachineTranslationSettingsController.kt index a8cfb3d0dd..e6b5692f5c 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/MachineTranslationSettingsController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/MachineTranslationSettingsController.kt @@ -47,7 +47,7 @@ class MachineTranslationSettingsController( @Operation(summary = "Sets machine translation settings for project") @RequiresProjectPermissions([ Scope.LANGUAGES_EDIT ]) fun setMachineTranslationSettings( - @RequestBody dto: SetMachineTranslationSettingsDto + @RequestBody dto: SetMachineTranslationSettingsDto, ): CollectionModel { mtServiceConfigService.setProjectSettings(projectHolder.projectEntity, dto) return getMachineTranslationSettings() @@ -63,9 +63,9 @@ class MachineTranslationSettingsController( LanguageInfoModel( it.language.id, it.language.tag, - supportedServices = it.supportedServices + supportedServices = it.supportedServices, ) - }.sortedBy { it.languageId } + }.sortedBy { it.languageId }, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/MtCreditsController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/MtCreditsController.kt index cf0113b2be..752c00823c 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/MtCreditsController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/MtCreditsController.kt @@ -23,13 +23,15 @@ import org.springframework.web.bind.annotation.RestController class MtCreditsController( private val projectHolder: ProjectHolder, private val mtCreditBucketService: MtCreditBucketService, - private val organizationService: OrganizationService + private val organizationService: OrganizationService, ) { @GetMapping("/projects/{projectId:\\d+}/machine-translation-credit-balance") @Operation(summary = "Returns machine translation credit balance for specified project") @UseDefaultPermissions @AllowApiAccess - fun getProjectCredits(@PathVariable projectId: Long): CreditBalanceModel { + fun getProjectCredits( + @PathVariable projectId: Long, + ): CreditBalanceModel { return mtCreditBucketService.getCreditBalances(projectHolder.projectEntity).model } @@ -37,15 +39,18 @@ class MtCreditsController( @Operation(summary = "Returns machine translation credit balance for organization") @RequiresOrganizationRole @AllowApiAccess - fun getOrganizationCredits(@PathVariable organizationId: Long): CreditBalanceModel { + fun getOrganizationCredits( + @PathVariable organizationId: Long, + ): CreditBalanceModel { val organization = organizationService.get(organizationId) return mtCreditBucketService.getCreditBalances(organization).model } private val MtCreditBalanceDto.model - get() = CreditBalanceModel( - creditBalance = this.creditBalance / 100, - bucketSize = this.bucketSize / 100, - extraCreditBalance = this.extraCreditBalance / 100 - ) + get() = + CreditBalanceModel( + creditBalance = this.creditBalance / 100, + bucketSize = this.bucketSize / 100, + extraCreditBalance = this.extraCreditBalance / 100, + ) } diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/NamespaceController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/NamespaceController.kt index 32f60e6a93..5f99b4175c 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/NamespaceController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/NamespaceController.kt @@ -37,8 +37,8 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping( value = [ "/v2/projects/{projectId}/", - "/v2/projects/" - ] + "/v2/projects/", + ], ) @Tag(name = "Namespaces", description = "Manipulates key namespaces") class NamespaceController( @@ -47,15 +47,16 @@ class NamespaceController( private val namespaceModelAssembler: NamespaceModelAssembler, @Suppress("SpringJavaInjectionPointsAutowiringInspection") private val pagedResourcesAssembler: PagedResourcesAssembler, - private val usedNamespaceModelAssembler: UsedNamespaceModelAssembler + private val usedNamespaceModelAssembler: UsedNamespaceModelAssembler, ) : IController { - @GetMapping(value = ["namespaces"]) @Operation(summary = "Returns all project namespaces") @UseDefaultPermissions @AllowApiAccess fun getAllNamespaces( - @ParameterObject @SortDefault("id") pageable: Pageable + @ParameterObject + @SortDefault("id") + pageable: Pageable, ): PagedModel { val namespaces = namespaceService.getAllInProject(projectHolder.project.id, pageable) return pagedResourcesAssembler.toModel(namespaces, namespaceModelAssembler) @@ -66,8 +67,9 @@ class NamespaceController( @UseDefaultPermissions @AllowApiAccess fun getUsedNamespaces(): CollectionModel { - val namespaces = namespaceService.getAllInProject(projectHolder.project.id) - .map { it.id as Long? to it.name as String? }.toMutableList() + val namespaces = + namespaceService.getAllInProject(projectHolder.project.id) + .map { it.id as Long? to it.name as String? }.toMutableList() val isDefaultUsed = namespaceService.isDefaultUsed(projectHolder.project.id) if (isDefaultUsed) { namespaces.add(0, null to null) @@ -82,7 +84,8 @@ class NamespaceController( @AllowApiAccess fun update( @PathVariable id: Long, - @RequestBody @Valid dto: UpdateNamespaceDto + @RequestBody @Valid + dto: UpdateNamespaceDto, ): NamespaceModel { val namespace = namespaceService.get(projectHolder.project.id, id) namespaceService.update(namespace, dto) diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/PatController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/PatController.kt index 36331392be..eca42a30b8 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/PatController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/PatController.kt @@ -48,22 +48,21 @@ class PatController( private val revealedPatModelAssembler: RevealedPatModelAssembler, private val patWithUserModelAssembler: PatWithUserModelAssembler, ) : IController { - @GetMapping(value = [""]) @Operation(summary = "Get all Personal Access Tokens") fun getAll( - @ParameterObject pageable: Pageable + @ParameterObject pageable: Pageable, ): PagedModel { return pagedResourcesAssembler.toModel( patService.findAll(authenticationFacade.authenticatedUser.id, pageable), - patModelAssembler + patModelAssembler, ) } @GetMapping(value = ["/{id:[0-9]+}"]) @Operation(summary = "Get Personal Access Token") fun get( - @PathVariable id: Long + @PathVariable id: Long, ): PatModel { checkOwner(id) return patModelAssembler.toModel(patService.get(id)) @@ -73,19 +72,24 @@ class PatController( @Operation(summary = "Creates new Personal Access Token") @ResponseStatus(HttpStatus.CREATED) @RequiresSuperAuthentication - fun create(@RequestBody @Valid dto: CreatePatDto): RevealedPatModel { + fun create( + @RequestBody @Valid + dto: CreatePatDto, + ): RevealedPatModel { return revealedPatModelAssembler.toModel(patService.create(dto, authenticationFacade.authenticatedUserEntity)) } @PutMapping(value = ["/{id:[0-9]+}/regenerate"]) @Operation( - summary = "Regenerates Personal Access Token. " + - "It generates new token value and updates its time of expiration." + summary = + "Regenerates Personal Access Token. " + + "It generates new token value and updates its time of expiration.", ) @RequiresSuperAuthentication fun regenerate( - @RequestBody @Valid dto: RegeneratePatDto, - @PathVariable id: Long + @RequestBody @Valid + dto: RegeneratePatDto, + @PathVariable id: Long, ): RevealedPatModel { checkOwner(id) return revealedPatModelAssembler.toModel(patService.regenerate(id, dto.expiresAt)) @@ -95,8 +99,9 @@ class PatController( @Operation(summary = "Updates Personal Access Token") @RequiresSuperAuthentication fun update( - @RequestBody @Valid dto: UpdatePatDto, - @PathVariable id: Long + @RequestBody @Valid + dto: UpdatePatDto, + @PathVariable id: Long, ): PatModel { checkOwner(id) return patModelAssembler.toModel(patService.update(id, dto)) @@ -106,7 +111,7 @@ class PatController( @Operation(summary = "Deletes Personal Access Token") @RequiresSuperAuthentication fun delete( - @PathVariable id: Long + @PathVariable id: Long, ) { val pat = checkOwner(id) return patService.delete(pat) diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/PreferredOrganizationController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/PreferredOrganizationController.kt index e7acc8fc2d..89db3a6dfb 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/PreferredOrganizationController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/PreferredOrganizationController.kt @@ -20,13 +20,14 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping(value = ["/v2/preferred-organization"]) @Tag(name = "Organizations") class PreferredOrganizationController( - private val preferredOrganizationFacade: PreferredOrganizationFacade + private val preferredOrganizationFacade: PreferredOrganizationFacade, ) { @GetMapping("") @Operation( - summary = "Returns preferred organization. " + - "If server allows users to create organization, preferred organization is automatically created " + - "if user doesn't have access to any organization." + summary = + "Returns preferred organization. " + + "If server allows users to create organization, preferred organization is automatically created " + + "if user doesn't have access to any organization.", ) fun getPreferred(): PrivateOrganizationModel { return preferredOrganizationFacade.getPreferred() ?: throw PermissionException(Message.CANNOT_CREATE_ORGANIZATION) diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ProjectActivityController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ProjectActivityController.kt index 357674368f..ce123841df 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ProjectActivityController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ProjectActivityController.kt @@ -33,14 +33,14 @@ class ProjectActivityController( private val activityService: ActivityService, private val projectHolder: ProjectHolder, private val pagedResourcesAssembler: PagedResourcesAssembler, - private val projectActivityModelAssembler: ProjectActivityModelAssembler + private val projectActivityModelAssembler: ProjectActivityModelAssembler, ) { @Operation(summary = "Returns project history") @GetMapping("", produces = [MediaTypes.HAL_JSON_VALUE]) @RequiresProjectPermissions([ Scope.ACTIVITY_VIEW ]) @AllowApiAccess fun getActivity( - @ParameterObject pageable: Pageable + @ParameterObject pageable: Pageable, ): PagedModel { val views = activityService.getProjectActivity(projectId = projectHolder.project.id, pageable) return pagedResourcesAssembler.toModel(views, projectActivityModelAssembler) diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ProjectStatsController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ProjectStatsController.kt index ad8c469029..805c3e87fc 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ProjectStatsController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ProjectStatsController.kt @@ -33,7 +33,7 @@ class ProjectStatsController( private val projectHolder: ProjectHolder, private val projectService: ProjectService, private val languageStatsService: LanguageStatsService, - private val languageStatsModelAssembler: LanguageStatsModelAssembler + private val languageStatsModelAssembler: LanguageStatsModelAssembler, ) { @Operation(summary = "Returns project stats") @GetMapping("", produces = [MediaTypes.HAL_JSON_VALUE]) @@ -42,9 +42,10 @@ class ProjectStatsController( fun getProjectStats(): ProjectStatsModel { val projectStats = projectStatsService.getProjectStats(projectHolder.project.id) val baseLanguage = projectService.getOrCreateBaseLanguage(projectHolder.project.id) - val languageStats = languageStatsService.getLanguageStats(projectHolder.project.id) - .sortedBy { it.language.name } - .sortedBy { it.language.id != baseLanguage?.id } + val languageStats = + languageStatsService.getLanguageStats(projectHolder.project.id) + .sortedBy { it.language.name } + .sortedBy { it.language.id != baseLanguage?.id } val totals = projectStatsService.computeProjectTotals(baseLanguage, languageStats) @@ -57,7 +58,7 @@ class ProjectStatsController( reviewedPercentage = totals.reviewedPercent, membersCount = projectStats.memberCount, tagCount = projectStats.tagCount, - languageStats = languageStats.map { languageStatsModelAssembler.toModel(it) } + languageStats = languageStats.map { languageStatsModelAssembler.toModel(it) }, ) } diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/QuickStartController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/QuickStartController.kt index 621bb09f36..6a272223f7 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/QuickStartController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/QuickStartController.kt @@ -15,18 +15,21 @@ import org.springframework.web.bind.annotation.RestController class QuickStartController( private val quickStartService: QuickStartService, private val quickStartModelAssembler: QuickStartModelAssembler, - private val authenticationFacade: AuthenticationFacade + private val authenticationFacade: AuthenticationFacade, ) { @PutMapping("/steps/{step}/complete") - fun completeGuideStep(@PathVariable("step") step: String): QuickStartModel { - val entity = quickStartService.completeStep(authenticationFacade.authenticatedUser, step) - ?: throw NotFoundException() + fun completeGuideStep( + @PathVariable("step") step: String, + ): QuickStartModel { + val entity = + quickStartService.completeStep(authenticationFacade.authenticatedUser, step) + ?: throw NotFoundException() return quickStartModelAssembler.toModel(entity) } @PutMapping("/set-finished/{finished}") fun setFinishedState( - @PathVariable finished: Boolean + @PathVariable finished: Boolean, ): QuickStartModel { val entity = quickStartService.setFinishState(authenticationFacade.authenticatedUser, finished) return quickStartModelAssembler.toModel(entity) @@ -34,7 +37,7 @@ class QuickStartController( @PutMapping("/set-open/{open}") fun setOpenState( - @PathVariable open: Boolean + @PathVariable open: Boolean, ): QuickStartModel { val entity = quickStartService.setOpenState(authenticationFacade.authenticatedUser, open) return quickStartModelAssembler.toModel(entity) diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ScopeInfoController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ScopeInfoController.kt index 8f2edbe9f5..d87e522aac 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ScopeInfoController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/ScopeInfoController.kt @@ -13,16 +13,14 @@ import io.swagger.v3.oas.annotations.tags.Tag as OpenApiTag @CrossOrigin(origins = ["*"]) @RequestMapping( value = [ - "/v2/public/scope-info" - ] + "/v2/public/scope-info", + ], ) @OpenApiTag(name = "Scope Info", description = "Returns info about permission scopes") class ScopeInfoController : IController { @GetMapping(value = ["/hierarchy"]) @Operation(summary = "Returns hierarchy of scopes") - fun getHierarchy( - search: String? = null - ): Scope.HierarchyItem { + fun getHierarchy(search: String? = null): Scope.HierarchyItem { return Scope.hierarchy } diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/SlugController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/SlugController.kt index 7e88bfa302..0d1be53678 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/SlugController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/SlugController.kt @@ -27,11 +27,10 @@ class SlugController( private val organizationService: OrganizationService, private val projectService: ProjectService, ) { - @GetMapping("/validate-organization/{slug}") @Operation(summary = "Validate organization address part") fun validateOrganizationSlug( - @PathVariable("slug") slug: String + @PathVariable("slug") slug: String, ): Boolean { return organizationService.validateSlugUniqueness(slug) } @@ -39,7 +38,7 @@ class SlugController( @GetMapping("/validate-project/{slug}") @Operation(summary = "Validate project address part") fun validateProjectSlug( - @PathVariable("slug") slug: String + @PathVariable("slug") slug: String, ): Boolean { return projectService.validateSlugUniqueness(slug) } @@ -47,7 +46,8 @@ class SlugController( @PostMapping("/generate-organization", produces = [MediaType.APPLICATION_JSON_VALUE]) @Operation(summary = "Generate organization address part") fun generateOrganizationSlug( - @RequestBody @Valid dto: GenerateSlugDto + @RequestBody @Valid + dto: GenerateSlugDto, ): String { return """"${organizationService.generateSlug(dto.name!!, dto.oldSlug)}"""" } @@ -55,7 +55,8 @@ class SlugController( @PostMapping("/generate-project", produces = [MediaType.APPLICATION_JSON_VALUE]) @Operation(summary = "Generate project address part") fun generateProjectSlug( - @RequestBody @Valid dto: GenerateSlugDto + @RequestBody @Valid + dto: GenerateSlugDto, ): String { return """"${projectService.generateSlug(dto.name!!, dto.oldSlug)}"""" } diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/TagsController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/TagsController.kt index 776aa2d53c..5bf3ea94b4 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/TagsController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/TagsController.kt @@ -40,8 +40,8 @@ import io.swagger.v3.oas.annotations.tags.Tag as OpenApiTag @RequestMapping( value = [ "/v2/projects/{projectId:\\d+}/", - "/v2/projects/" - ] + "/v2/projects/", + ], ) @OpenApiTag(name = "Tags", description = "Manipulates key tags") class TagsController( @@ -49,15 +49,19 @@ class TagsController( private val projectHolder: ProjectHolder, private val tagService: TagService, private val tagModelAssembler: TagModelAssembler, - private val pagedResourcesAssembler: PagedResourcesAssembler + private val pagedResourcesAssembler: PagedResourcesAssembler, ) : IController { - @PutMapping(value = ["keys/{keyId:[0-9]+}/tags"]) @Operation(summary = "Tags a key with tag. If tag with provided name doesn't exist, it is created") @RequestActivity(ActivityType.KEY_TAGS_EDIT) - @RequiresProjectPermissions([ Scope.KEYS_EDIT ]) + @RequiresProjectPermissions([Scope.KEYS_EDIT]) @AllowApiAccess - fun tagKey(@PathVariable keyId: Long, @Valid @RequestBody tagKeyDto: TagKeyDto): TagModel { + fun tagKey( + @PathVariable + keyId: Long, + @Valid @RequestBody + tagKeyDto: TagKeyDto, + ): TagModel { val key = keyService.findOptional(keyId).orElseThrow { NotFoundException() } key.checkInProject() return tagService.tagKey(key, tagKeyDto.name.trim()).model @@ -66,9 +70,12 @@ class TagsController( @DeleteMapping(value = ["keys/{keyId:[0-9]+}/tags/{tagId:[0-9]+}"]) @Operation(summary = "Removes tag with provided id from key with provided id") @RequestActivity(ActivityType.KEY_TAGS_EDIT) - @RequiresProjectPermissions([ Scope.KEYS_EDIT ]) + @RequiresProjectPermissions([Scope.KEYS_EDIT]) @AllowApiAccess - fun removeTag(@PathVariable keyId: Long, @PathVariable tagId: Long) { + fun removeTag( + @PathVariable keyId: Long, + @PathVariable tagId: Long, + ) { val key = keyService.findOptional(keyId).orElseThrow { NotFoundException() } val tag = tagService.find(tagId) ?: throw NotFoundException() tag.checkInProject() @@ -82,7 +89,7 @@ class TagsController( @AllowApiAccess fun getAll( @RequestParam search: String? = null, - @SortDefault("name") @ParameterObject pageable: Pageable + @SortDefault("name") @ParameterObject pageable: Pageable, ): PagedModel { val data = tagService.getProjectTags(projectHolder.project.id, search, pageable) return pagedResourcesAssembler.toModel(data, tagModelAssembler) diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/UserMfaController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/UserMfaController.kt index ae789b9394..d19a90d4f0 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/UserMfaController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/UserMfaController.kt @@ -26,25 +26,34 @@ class UserMfaController( ) { @PutMapping("/totp") @Operation(summary = "Enables TOTP-based two-factor authentication. Invalidates all previous sessions upon success.") - fun enableMfa(@RequestBody @Valid dto: UserTotpEnableRequestDto): JwtAuthenticationResponse { + fun enableMfa( + @RequestBody @Valid + dto: UserTotpEnableRequestDto, + ): JwtAuthenticationResponse { mfaService.enableTotpFor(authenticationFacade.authenticatedUserEntity, dto) return JwtAuthenticationResponse( - jwtService.emitToken(authenticationFacade.authenticatedUser.id, true) + jwtService.emitToken(authenticationFacade.authenticatedUser.id, true), ) } @DeleteMapping("/totp") @Operation(summary = "Disables TOTP-based two-factor authentication. Invalidates all previous sessions upon success.") - fun disableMfa(@RequestBody @Valid dto: UserTotpDisableRequestDto): JwtAuthenticationResponse { + fun disableMfa( + @RequestBody @Valid + dto: UserTotpDisableRequestDto, + ): JwtAuthenticationResponse { mfaService.disableTotpFor(authenticationFacade.authenticatedUserEntity, dto) return JwtAuthenticationResponse( - jwtService.emitToken(authenticationFacade.authenticatedUser.id, true) + jwtService.emitToken(authenticationFacade.authenticatedUser.id, true), ) } @PutMapping("/recovery") @Operation(summary = "Regenerates multi-factor authentication recovery codes") - fun regenerateRecoveryCodes(@RequestBody @Valid dto: UserMfaRecoveryRequestDto): List { + fun regenerateRecoveryCodes( + @RequestBody @Valid + dto: UserMfaRecoveryRequestDto, + ): List { return mfaService.regenerateRecoveryCodes(authenticationFacade.authenticatedUserEntity, dto) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/UserPreferencesController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/UserPreferencesController.kt index 32fbce7464..d44325843d 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/UserPreferencesController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/UserPreferencesController.kt @@ -26,7 +26,7 @@ class UserPreferencesController( private val userPreferencesService: UserPreferencesService, private val authenticationFacade: AuthenticationFacade, private val organizationRoleService: OrganizationRoleService, - private val organizationService: OrganizationService + private val organizationService: OrganizationService, ) { @GetMapping("") @Operation(summary = "Get user's preferences") @@ -39,7 +39,7 @@ class UserPreferencesController( @PutMapping("/set-language/{languageTag}") @Operation(summary = "Set user's UI language") fun setLanguage( - @PathVariable languageTag: String + @PathVariable languageTag: String, ) { userPreferencesService.setLanguage(languageTag, authenticationFacade.authenticatedUserEntity) } @@ -47,7 +47,7 @@ class UserPreferencesController( @PutMapping("/set-preferred-organization/{organizationId}") @Operation(summary = "Set user preferred organization") fun setPreferredOrganization( - @PathVariable organizationId: Long + @PathVariable organizationId: Long, ) { val organization = organizationService.get(organizationId) organizationRoleService.checkUserCanView(organization.id) diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2ImageUploadController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2ImageUploadController.kt index 22875dc055..9ee72c2d74 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2ImageUploadController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2ImageUploadController.kt @@ -34,13 +34,13 @@ import org.springframework.web.multipart.MultipartFile @RestController @CrossOrigin(origins = ["*"]) @RequestMapping( - value = ["/v2/image-upload"] + value = ["/v2/image-upload"], ) @Tag(name = "Image upload") class V2ImageUploadController( private val uploadedImageModelAssembler: UploadedImageModelAssembler, private val imageUploadService: ImageUploadService, - private val authenticationFacade: AuthenticationFacade + private val authenticationFacade: AuthenticationFacade, ) { @PostMapping("", consumes = [MediaType.MULTIPART_FORM_DATA_VALUE]) @Operation(summary = "Uploads an image for later use") @@ -49,7 +49,7 @@ class V2ImageUploadController( @AllowApiAccess fun upload( @RequestParam("image") image: MultipartFile, - @RequestPart("info", required = false) info: ImageUploadInfoDto? + @RequestPart("info", required = false) info: ImageUploadInfoDto?, ): ResponseEntity { imageUploadService.validateIsImage(image) val imageEntity = imageUploadService.store(image, authenticationFacade.authenticatedUserEntity, info) @@ -59,7 +59,9 @@ class V2ImageUploadController( @DeleteMapping("/{ids}") @Operation(summary = "Deletes uploaded images") @AllowApiAccess - fun delete(@PathVariable ids: Set) { + fun delete( + @PathVariable ids: Set, + ) { val images = imageUploadService.find(ids) images.forEach { if (it.userAccount.id != authenticationFacade.authenticatedUser.id) { diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2ImportController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2ImportController.kt index a0500e1ab8..bbe748a07d 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2ImportController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2ImportController.kt @@ -68,7 +68,7 @@ import org.springframework.web.multipart.MultipartFile @RequestMapping(value = ["/v2/projects/{projectId:\\d+}/import", "/v2/projects/import"]) @Tag( name = "Import", - description = "These endpoints handle multi-step data import" + description = "These endpoints handle multi-step data import", ) class V2ImportController( private val importService: ImportService, @@ -77,16 +77,14 @@ class V2ImportController( private val importTranslationModelAssembler: ImportTranslationModelAssembler, @Suppress("SpringJavaInjectionPointsAutowiringInspection") private val pagedLanguagesResourcesAssembler: PagedResourcesAssembler, - @Suppress("SpringJavaInjectionPointsAutowiringInspection") private val pagedTranslationsResourcesAssembler: PagedResourcesAssembler, - @Suppress("SpringJavaInjectionPointsAutowiringInspection") private val pagedImportFileIssueResourcesAssembler: PagedResourcesAssembler, private val projectHolder: ProjectHolder, private val languageService: LanguageService, private val namespaceService: NamespaceService, - private val importFileIssueModelAssembler: ImportFileIssueModelAssembler + private val importFileIssueModelAssembler: ImportFileIssueModelAssembler, ) { @PostMapping("", consumes = [MediaType.MULTIPART_FORM_DATA_VALUE]) @Operation(description = "Prepares provided files to import.", summary = "Add files") @@ -94,26 +92,26 @@ class V2ImportController( @AllowApiAccess fun addFiles( @RequestPart("files") files: Array, - @ParameterObject params: ImportAddFilesParams + @ParameterObject params: ImportAddFilesParams, ): ImportAddFilesResultModel { val fileDtos = files.map { ImportFileDto(it.originalFilename ?: "", it.inputStream) } - val errors = importService.addFiles( - files = fileDtos, - project = projectHolder.projectEntity, - userAccount = authenticationFacade.authenticatedUserEntity, - params = params - ) + val errors = + importService.addFiles( + files = fileDtos, + project = projectHolder.projectEntity, + userAccount = authenticationFacade.authenticatedUserEntity, + params = params, + ) return getImportAddFilesResultModel(errors) } - private fun getImportAddFilesResultModel( - errors: List - ): ImportAddFilesResultModel { - val result: PagedModel? = try { - this.getImportResult(PageRequest.of(0, 100)) - } catch (e: NotFoundException) { - null - } + private fun getImportAddFilesResultModel(errors: List): ImportAddFilesResultModel { + val result: PagedModel? = + try { + this.getImportResult(PageRequest.of(0, 100)) + } catch (e: NotFoundException) { + null + } return ImportAddFilesResultModel(errors, result) } @@ -136,7 +134,7 @@ class V2ImportController( @RequiresProjectPermissions([Scope.TRANSLATIONS_VIEW]) @AllowApiAccess fun getImportResult( - @ParameterObject pageable: Pageable + @ParameterObject pageable: Pageable, ): PagedModel { val projectId = projectHolder.project.id val userId = authenticationFacade.authenticatedUser.id @@ -164,18 +162,25 @@ class V2ImportController( @PathVariable("projectId") projectId: Long, @PathVariable("languageId") languageId: Long, @Parameter( - description = "Whether only translations, which are in conflict " + - "with existing translations should be returned" + description = + "Whether only translations, which are in conflict " + + "with existing translations should be returned", ) - @RequestParam("onlyConflicts", defaultValue = "false") onlyConflicts: Boolean = false, + @RequestParam("onlyConflicts", defaultValue = "false") + onlyConflicts: Boolean = false, @Parameter( - description = "Whether only translations with unresolved conflicts" + - "with existing translations should be returned" + description = + "Whether only translations with unresolved conflicts" + + "with existing translations should be returned", ) - @RequestParam("onlyUnresolved", defaultValue = "false") onlyUnresolved: Boolean = false, + @RequestParam("onlyUnresolved", defaultValue = "false") + onlyUnresolved: Boolean = false, @Parameter(description = "String to search in translation text or key") - @RequestParam("search") search: String? = null, - @ParameterObject @SortDefault("keyName") pageable: Pageable + @RequestParam("search") + search: String? = null, + @ParameterObject + @SortDefault("keyName") + pageable: Pageable, ): PagedModel { checkImportLanguageInProject(languageId) val translations = importService.getTranslationsView(languageId, pageable, onlyConflicts, onlyUnresolved, search) @@ -194,7 +199,9 @@ class V2ImportController( @Operation(description = "Deletes language prepared to import.", summary = "Delete language") @RequiresProjectPermissions([Scope.TRANSLATIONS_VIEW]) @AllowApiAccess - fun deleteLanguage(@PathVariable("languageId") languageId: Long) { + fun deleteLanguage( + @PathVariable("languageId") languageId: Long, + ) { val language = checkImportLanguageInProject(languageId) this.importService.deleteLanguage(language) } @@ -202,13 +209,13 @@ class V2ImportController( @PutMapping("/result/languages/{languageId}/translations/{translationId}/resolve/set-override") @Operation( description = "Resolves translation conflict. The old translation will be overridden.", - summary = "Resolve conflict (override)" + summary = "Resolve conflict (override)", ) @RequiresProjectPermissions([Scope.TRANSLATIONS_VIEW]) @AllowApiAccess fun resolveTranslationSetOverride( @PathVariable("languageId") languageId: Long, - @PathVariable("translationId") translationId: Long + @PathVariable("translationId") translationId: Long, ) { resolveTranslation(languageId, translationId, true) } @@ -216,13 +223,13 @@ class V2ImportController( @PutMapping("/result/languages/{languageId}/translations/{translationId}/resolve/set-keep-existing") @Operation( description = "Resolves translation conflict. The old translation will be kept.", - summary = "Resolve conflict (keep existing)" + summary = "Resolve conflict (keep existing)", ) @RequiresProjectPermissions([Scope.TRANSLATIONS_VIEW]) @AllowApiAccess fun resolveTranslationSetKeepExisting( @PathVariable("languageId") languageId: Long, - @PathVariable("translationId") translationId: Long + @PathVariable("translationId") translationId: Long, ) { resolveTranslation(languageId, translationId, false) } @@ -230,12 +237,12 @@ class V2ImportController( @PutMapping("/result/languages/{languageId}/resolve-all/set-override") @Operation( description = "Resolves all translation conflicts for provided language. The old translations will be overridden.", - summary = "Resolve all translation conflicts (override)" + summary = "Resolve all translation conflicts (override)", ) @RequiresProjectPermissions([Scope.TRANSLATIONS_VIEW]) @AllowApiAccess fun resolveTranslationSetOverride( - @PathVariable("languageId") languageId: Long + @PathVariable("languageId") languageId: Long, ) { resolveAllOfLanguage(languageId, true) } @@ -243,7 +250,7 @@ class V2ImportController( @PutMapping("/result/languages/{languageId}/resolve-all/set-keep-existing") @Operation( description = "Resolves all translation conflicts for provided language. The old translations will be kept.", - summary = "Resolve all translation conflicts (keep existing)" + summary = "Resolve all translation conflicts (keep existing)", ) @RequiresProjectPermissions([Scope.TRANSLATIONS_VIEW]) @AllowApiAccess @@ -256,14 +263,14 @@ class V2ImportController( @PutMapping("/result/files/{fileId}/select-namespace") @Operation( description = "Sets namespace for file to import.", - summary = "Select namespace" + summary = "Select namespace", ) @RequiresProjectPermissions([Scope.TRANSLATIONS_VIEW]) @AllowApiAccess fun selectNamespace( @PathVariable fileId: Long, @RequestBody req: SetFileNamespaceRequest, - request: HttpServletRequest + request: HttpServletRequest, ) { val file = checkFileFromProject(fileId) this.importService.selectNamespace(file, req.namespace) @@ -271,9 +278,10 @@ class V2ImportController( @PutMapping("/result/languages/{importLanguageId}/select-existing/{existingLanguageId}") @Operation( - description = "Sets existing language to pair with language to import. " + - "Data will be imported to selected existing language when applied.", - summary = "Pair existing language" + description = + "Sets existing language to pair with language to import. " + + "Data will be imported to selected existing language when applied.", + summary = "Pair existing language", ) @RequiresProjectPermissions([Scope.TRANSLATIONS_VIEW]) @AllowApiAccess @@ -289,7 +297,7 @@ class V2ImportController( @PutMapping("/result/languages/{importLanguageId}/reset-existing") @Operation( description = "Resets existing language paired with language to import.", - summary = "Reset existing language pairing" + summary = "Reset existing language pairing", ) @RequiresProjectPermissions([Scope.TRANSLATIONS_VIEW]) @AllowApiAccess @@ -303,13 +311,13 @@ class V2ImportController( @GetMapping("/result/files/{importFileId}/issues") @Operation( description = "Returns issues for uploaded file.", - summary = "Get file issues" + summary = "Get file issues", ) @RequiresProjectPermissions([Scope.TRANSLATIONS_VIEW]) @AllowApiAccess fun getImportFileIssues( @PathVariable("importFileId") importFileId: Long, - @ParameterObject pageable: Pageable + @ParameterObject pageable: Pageable, ): PagedModel { checkFileFromProject(importFileId) val page = importService.getFileIssues(importFileId, pageable) @@ -319,20 +327,22 @@ class V2ImportController( @GetMapping("/all-namespaces") @Operation( description = "Returns all existing and imported namespaces", - summary = "Get namespaces" + summary = "Get namespaces", ) @RequiresProjectPermissions([Scope.TRANSLATIONS_VIEW]) @AllowApiAccess fun getAllNamespaces(): CollectionModel { - val import = importService.get( - projectId = projectHolder.project.id, - authorId = authenticationFacade.authenticatedUser.id - ) + val import = + importService.get( + projectId = projectHolder.project.id, + authorId = authenticationFacade.authenticatedUser.id, + ) val importNamespaces = importService.getAllNamespaces(import.id) val existingNamespaces = namespaceService.getAllInProject(projectId = projectHolder.project.id) - val result = existingNamespaces - .map { it.name to ImportNamespaceModel(it.id, it.name) } - .toMap(mutableMapOf()) + val result = + existingNamespaces + .map { it.name to ImportNamespaceModel(it.id, it.name) } + .toMap(mutableMapOf()) importNamespaces.filterNotNull().forEach { importNamespace -> result.computeIfAbsent(importNamespace) { ImportNamespaceModel(id = null, name = importNamespace) @@ -343,24 +353,32 @@ class V2ImportController( } private fun getNamespacesCollectionModel( - result: MutableMap + result: MutableMap, ): CollectionModel { - val assembler = object : RepresentationModelAssemblerSupport( - this::class.java, - ImportNamespaceModel::class.java - ) { - override fun toModel(entity: ImportNamespaceModel): ImportNamespaceModel = entity - } + val assembler = + object : RepresentationModelAssemblerSupport( + this::class.java, + ImportNamespaceModel::class.java, + ) { + override fun toModel(entity: ImportNamespaceModel): ImportNamespaceModel = entity + } return assembler.toCollectionModel(result.values.sortedBy { it.name }) } - private fun resolveAllOfLanguage(languageId: Long, override: Boolean) { + private fun resolveAllOfLanguage( + languageId: Long, + override: Boolean, + ) { val language = checkImportLanguageInProject(languageId) importService.resolveAllOfLanguage(language, override) } - private fun resolveTranslation(languageId: Long, translationId: Long, override: Boolean) { + private fun resolveTranslation( + languageId: Long, + translationId: Long, + override: Boolean, + ) { checkImportLanguageInProject(languageId) val translation = checkTranslationOfLanguage(translationId, languageId) return importService.resolveTranslationConflict(translation, override) @@ -391,7 +409,10 @@ class V2ImportController( return language } - private fun checkTranslationOfLanguage(translationId: Long, languageId: Long): ImportTranslation { + private fun checkTranslationOfLanguage( + translationId: Long, + languageId: Long, + ): ImportTranslation { val translation = importService.findTranslation(translationId) ?: throw NotFoundException() if (translation.language.id != languageId) { diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2InvitationController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2InvitationController.kt index b84e3c0f21..a07cb9cc1b 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2InvitationController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2InvitationController.kt @@ -25,21 +25,26 @@ class V2InvitationController( ) { @GetMapping("/{code}/accept") @Operation(summary = "Accepts invitation to project or organization") - fun acceptInvitation(@PathVariable("code") code: String?): ResponseEntity { + fun acceptInvitation( + @PathVariable("code") code: String?, + ): ResponseEntity { invitationService.accept(code) return ResponseEntity(HttpStatus.OK) } @DeleteMapping("/{invitationId}") @Operation(summary = "Deletes invitation by ID") - fun deleteInvitation(@PathVariable("invitationId") id: Long): ResponseEntity { - val invitation = invitationService.findById(id).orElseThrow { - NotFoundException() - } + fun deleteInvitation( + @PathVariable("invitationId") id: Long, + ): ResponseEntity { + val invitation = + invitationService.findById(id).orElseThrow { + NotFoundException() + } invitation.permission?.let { securityService.checkProjectPermission( invitation.permission!!.project!!.id, - Scope.ADMIN + Scope.ADMIN, ) } diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2LanguagesController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2LanguagesController.kt index 3df42eaf36..e3c8ee4d14 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2LanguagesController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2LanguagesController.kt @@ -46,13 +46,13 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping( value = [ "/v2/projects/{projectId:[0-9]+}/languages", - "/v2/projects/languages" - ] + "/v2/projects/languages", + ], ) @Tags( value = [ Tag(name = "Languages", description = "Languages"), - ] + ], ) class V2LanguagesController( private val languageService: LanguageService, @@ -70,7 +70,8 @@ class V2LanguagesController( @AllowApiAccess fun createLanguage( @PathVariable("projectId") projectId: Long, - @RequestBody @Valid dto: LanguageDto + @RequestBody @Valid + dto: LanguageDto, ): LanguageModel { val project = projectService.get(projectId) languageValidator.validateCreate(dto, project) @@ -84,8 +85,9 @@ class V2LanguagesController( @RequiresProjectPermissions([Scope.LANGUAGES_EDIT]) @AllowApiAccess fun editLanguage( - @RequestBody @Valid dto: LanguageDto, - @PathVariable("languageId") languageId: Long + @RequestBody @Valid + dto: LanguageDto, + @PathVariable("languageId") languageId: Long, ): LanguageModel { languageValidator.validateEdit(languageId, dto) val view = languageService.getView(languageId) @@ -100,7 +102,7 @@ class V2LanguagesController( @AllowApiAccess fun getAll( @PathVariable("projectId") pathProjectId: Long?, - @ParameterObject pageable: Pageable + @ParameterObject pageable: Pageable, ): PagedModel { val data = languageService.getPaged(projectHolder.project.id, pageable) return pagedAssembler.toModel(data, languageModelAssembler) @@ -110,7 +112,9 @@ class V2LanguagesController( @Operation(summary = "Returns specific language") @UseDefaultPermissions @AllowApiAccess - fun get(@PathVariable("languageId") id: Long): LanguageModel { + fun get( + @PathVariable("languageId") id: Long, + ): LanguageModel { val languageView = languageService.getView(id) return languageModelAssembler.toModel(languageView) } @@ -120,7 +124,9 @@ class V2LanguagesController( @RequestActivity(ActivityType.DELETE_LANGUAGE) @RequiresProjectPermissions([Scope.LANGUAGES_EDIT]) @AllowApiAccess - fun deleteLanguage(@PathVariable languageId: Long) { + fun deleteLanguage( + @PathVariable languageId: Long, + ) { val language = languageService.get(languageId) securityService.checkProjectPermission(language.project.id, Scope.LANGUAGES_EDIT) diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2ProjectsController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2ProjectsController.kt index f7cb0cacaf..ce00b30a4a 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2ProjectsController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2ProjectsController.kt @@ -24,8 +24,8 @@ import io.tolgee.hateoas.project.ProjectModel import io.tolgee.hateoas.project.ProjectModelAssembler import io.tolgee.hateoas.project.ProjectTransferOptionModel import io.tolgee.hateoas.project.ProjectWithStatsModel -import io.tolgee.hateoas.user_account.UserAccountInProjectModel -import io.tolgee.hateoas.user_account.UserAccountInProjectModelAssembler +import io.tolgee.hateoas.userAccount.UserAccountInProjectModel +import io.tolgee.hateoas.userAccount.UserAccountInProjectModelAssembler import io.tolgee.model.enums.ProjectPermissionType import io.tolgee.model.enums.Scope import io.tolgee.model.views.ExtendedUserAccountInProject @@ -92,7 +92,7 @@ class V2ProjectsController( private val autoTranslateService: AutoTranslationService, private val projectPermissionFacade: ProjectPermissionFacade, private val projectWithStatsFacade: ProjectWithStatsFacade, - private val autoTranslationSettingsModelAssembler: AutoTranslationSettingsModelAssembler + private val autoTranslationSettingsModelAssembler: AutoTranslationSettingsModelAssembler, ) { @Operation(summary = "Returns all projects where current user has any permission") @GetMapping("", produces = [MediaTypes.HAL_JSON_VALUE]) @@ -100,7 +100,7 @@ class V2ProjectsController( @AllowApiAccess(tokenType = AuthTokenType.ONLY_PAT) fun getAll( @ParameterObject pageable: Pageable, - @RequestParam("search") search: String? + @RequestParam("search") search: String?, ): PagedModel { val projects = projectService.findPermittedInOrganizationPaged(pageable, search) return arrayResourcesAssembler.toModel(projects, projectModelAssembler) @@ -111,7 +111,7 @@ class V2ProjectsController( @IsGlobalRoute fun getAllWithStatistics( @ParameterObject pageable: Pageable, - @RequestParam("search") search: String? + @RequestParam("search") search: String?, ): PagedModel { val projects = projectService.findPermittedInOrganizationPaged(pageable, search) return projectWithStatsFacade.getPagedModelWithStats(projects) @@ -121,7 +121,9 @@ class V2ProjectsController( @Operation(summary = "Returns project by id") @UseDefaultPermissions @AllowApiAccess - fun get(@PathVariable("projectId") projectId: Long): ProjectModel { + fun get( + @PathVariable("projectId") projectId: Long, + ): ProjectModel { return projectService.getView(projectId).let { projectModelAssembler.toModel(it) } @@ -134,7 +136,7 @@ class V2ProjectsController( fun getAllUsers( @PathVariable("projectId") projectId: Long, @ParameterObject pageable: Pageable, - @RequestParam("search", required = false) search: String? + @RequestParam("search", required = false) search: String?, ): PagedModel { return userAccountService.getAllInProjectWithPermittedLanguages(projectId, pageable, search).let { users -> userArrayResourcesAssembler.toModel(users, userAccountInProjectModelAssembler) @@ -147,7 +149,7 @@ class V2ProjectsController( @RequiresProjectPermissions([ Scope.PROJECT_EDIT ]) fun uploadAvatar( @RequestParam("avatar") avatar: MultipartFile, - @PathVariable projectId: Long + @PathVariable projectId: Long, ): ProjectModel { imageUploadService.validateIsImage(avatar) projectService.setAvatar(projectHolder.projectEntity, avatar.inputStream) @@ -159,7 +161,7 @@ class V2ProjectsController( @ResponseStatus(HttpStatus.OK) @RequiresProjectPermissions([ Scope.PROJECT_EDIT ]) fun removeAvatar( - @PathVariable projectId: Long + @PathVariable projectId: Long, ): ProjectModel { projectService.removeAvatar(projectHolder.projectEntity) return projectModelAssembler.toModel(projectService.getView(projectId)) @@ -172,14 +174,14 @@ class V2ProjectsController( fun setUsersPermissions( @PathVariable("userId") userId: Long, @PathVariable("permissionType") permissionType: ProjectPermissionType, - @ParameterObject params: SetPermissionLanguageParams + @ParameterObject params: SetPermissionLanguageParams, ) { projectPermissionFacade.checkNotCurrentUser(userId) permissionService.setUserDirectPermission( projectId = projectHolder.project.id, userId = userId, newPermissionType = permissionType, - languages = projectPermissionFacade.getLanguages(params, projectHolder.project.id) + languages = projectPermissionFacade.getLanguages(params, projectHolder.project.id), ) } @@ -203,7 +205,7 @@ class V2ProjectsController( @RequiresSuperAuthentication fun revokePermission( @PathVariable("projectId") projectId: Long, - @PathVariable("userId") userId: Long + @PathVariable("userId") userId: Long, ) { if (userId == authenticationFacade.authenticatedUser.id) { throw BadRequestException(Message.CAN_NOT_REVOKE_OWN_PERMISSIONS) @@ -216,7 +218,10 @@ class V2ProjectsController( @RequestActivity(ActivityType.CREATE_PROJECT) @IsGlobalRoute @AllowApiAccess(tokenType = AuthTokenType.ONLY_PAT) - fun createProject(@RequestBody @Valid dto: CreateProjectDTO): ProjectModel { + fun createProject( + @RequestBody @Valid + dto: CreateProjectDTO, + ): ProjectModel { organizationRoleService.checkUserIsOwner(dto.organizationId) val project = projectService.createProject(dto) return projectModelAssembler.toModel(projectService.getView(project.id)) @@ -227,7 +232,10 @@ class V2ProjectsController( @RequestActivity(ActivityType.EDIT_PROJECT) @RequiresProjectPermissions([ Scope.PROJECT_EDIT ]) @RequiresSuperAuthentication - fun editProject(@RequestBody @Valid dto: EditProjectDTO): ProjectModel { + fun editProject( + @RequestBody @Valid + dto: EditProjectDTO, + ): ProjectModel { val project = projectService.editProject(projectHolder.project.id, dto) return projectModelAssembler.toModel(projectService.getView(project.id)) } @@ -236,7 +244,9 @@ class V2ProjectsController( @Operation(summary = "Deletes project by id") @RequiresProjectPermissions([ Scope.PROJECT_EDIT ]) @RequiresSuperAuthentication - fun deleteProject(@PathVariable projectId: Long) { + fun deleteProject( + @PathVariable projectId: Long, + ) { projectService.deleteProject(projectId) } @@ -244,7 +254,10 @@ class V2ProjectsController( @Operation(summary = "Transfers project's ownership to organization") @RequiresProjectPermissions([ Scope.PROJECT_EDIT ]) @RequiresSuperAuthentication - fun transferProjectToOrganization(@PathVariable projectId: Long, @PathVariable organizationId: Long) { + fun transferProjectToOrganization( + @PathVariable projectId: Long, + @PathVariable organizationId: Long, + ) { organizationRoleService.checkUserIsOwner(organizationId) projectService.transferToOrganization(projectId, organizationId) } @@ -260,21 +273,25 @@ class V2ProjectsController( @GetMapping(value = ["/{projectId:[0-9]+}/transfer-options"]) @Operation(summary = "Returns transfer option") @RequiresProjectPermissions([ Scope.PROJECT_EDIT ]) - fun getTransferOptions(@RequestParam search: String? = ""): CollectionModel { + fun getTransferOptions( + @RequestParam search: String? = "", + ): CollectionModel { val project = projectHolder.project - val organizations = organizationService.findPermittedPaged( - PageRequest.of(0, 10), - true, - search, - project.organizationOwnerId - ) - val options = organizations.content.map { - ProjectTransferOptionModel( - name = it.organization.name, - slug = it.organization.slug, - id = it.organization.id, + val organizations = + organizationService.findPermittedPaged( + PageRequest.of(0, 10), + true, + search, + project.organizationOwnerId, ) - }.toMutableList() + val options = + organizations.content.map { + ProjectTransferOptionModel( + name = it.organization.name, + slug = it.organization.slug, + id = it.organization.id, + ) + }.toMutableList() options.sortBy { it.name } return CollectionModel.of(options) } @@ -283,7 +300,9 @@ class V2ProjectsController( @Operation(summary = "Returns all invitations to project") @RequiresProjectPermissions([ Scope.MEMBERS_VIEW ]) @RequiresSuperAuthentication - fun getProjectInvitations(@PathVariable("projectId") id: Long): CollectionModel { + fun getProjectInvitations( + @PathVariable("projectId") id: Long, + ): CollectionModel { val project = projectService.get(id) val invitations = invitationService.getForProject(project) return projectInvitationModelAssembler.toCollectionModel(invitations) @@ -294,7 +313,7 @@ class V2ProjectsController( @RequiresProjectPermissions([ Scope.LANGUAGES_EDIT ]) @AllowApiAccess fun setPerLanguageAutoTranslationSettings( - @RequestBody dto: List + @RequestBody dto: List, ): CollectionModel { val config = autoTranslateService.saveConfig(projectHolder.projectEntity, dto) return autoTranslationSettingsModelAssembler.toCollectionModel(config) @@ -311,14 +330,15 @@ class V2ProjectsController( @PutMapping("/{projectId}/auto-translation-settings") @Operation( - summary = "Sets default auto translation settings for project " + - "(deprecated: use per language config with null language id)", - deprecated = true + summary = + "Sets default auto translation settings for project " + + "(deprecated: use per language config with null language id)", + deprecated = true, ) @RequiresProjectPermissions([ Scope.LANGUAGES_EDIT ]) @AllowApiAccess fun setAutoTranslationSettings( - @RequestBody dto: AutoTranslationSettingsDto + @RequestBody dto: AutoTranslationSettingsDto, ): AutoTranslationConfigModel { val config = autoTranslateService.saveDefaultConfig(projectHolder.projectEntity, dto) return autoTranslationSettingsModelAssembler.toModel(config) @@ -326,9 +346,10 @@ class V2ProjectsController( @GetMapping("/{projectId}/auto-translation-settings") @Operation( - summary = "Returns default auto translation settings for project " + - "(deprecated: use per language config with null language id)", - deprecated = true + summary = + "Returns default auto translation settings for project " + + "(deprecated: use per language config with null language id)", + deprecated = true, ) @UseDefaultPermissions @AllowApiAccess diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2ProjectsInvitationController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2ProjectsInvitationController.kt index df14c911dc..260753f4b8 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2ProjectsInvitationController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2ProjectsInvitationController.kt @@ -36,31 +36,36 @@ class V2ProjectsInvitationController( private val invitationService: InvitationService, private val projectInvitationModelAssembler: ProjectInvitationModelAssembler, private val projectPermissionFacade: ProjectPermissionFacade, - private val eeInvitationService: EeInvitationService + private val eeInvitationService: EeInvitationService, ) { @PutMapping("/{projectId}/invite") @Operation(summary = "Generates user invitation link for project") @RequiresProjectPermissions([ Scope.MEMBERS_EDIT ]) @RequiresSuperAuthentication - fun inviteUser(@RequestBody @Valid invitation: ProjectInviteUserDto): ProjectInvitationModel { + fun inviteUser( + @RequestBody @Valid + invitation: ProjectInviteUserDto, + ): ProjectInvitationModel { validatePermissions(invitation) val languagesPermissions = projectPermissionFacade.getLanguages(invitation, projectHolder.project.id) - val params = CreateProjectInvitationParams( - project = projectHolder.projectEntity, - type = invitation.type, - scopes = invitation.scopes, - email = invitation.email, - name = invitation.name, - languagePermissions = languagesPermissions - ) + val params = + CreateProjectInvitationParams( + project = projectHolder.projectEntity, + type = invitation.type, + scopes = invitation.scopes, + email = invitation.email, + name = invitation.name, + languagePermissions = languagesPermissions, + ) - val created = if (!params.scopes.isNullOrEmpty()) { - eeInvitationService.create(params) - } else { - invitationService.create(params) - } + val created = + if (!params.scopes.isNullOrEmpty()) { + eeInvitationService.create(params) + } else { + invitationService.create(params) + } return projectInvitationModelAssembler.toModel(created) } diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2UserController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2UserController.kt index ee6c745eac..9dcde6cc69 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2UserController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/V2UserController.kt @@ -9,8 +9,8 @@ import io.tolgee.dtos.request.UserUpdateRequestDto import io.tolgee.exceptions.AuthenticationException import io.tolgee.hateoas.organization.SimpleOrganizationModel import io.tolgee.hateoas.organization.SimpleOrganizationModelAssembler -import io.tolgee.hateoas.user_account.PrivateUserAccountModel -import io.tolgee.hateoas.user_account.PrivateUserAccountModelAssembler +import io.tolgee.hateoas.userAccount.PrivateUserAccountModel +import io.tolgee.hateoas.userAccount.PrivateUserAccountModelAssembler import io.tolgee.security.authentication.AllowApiAccess import io.tolgee.security.authentication.AuthenticationFacade import io.tolgee.security.authentication.JwtService @@ -26,7 +26,15 @@ import org.springframework.http.HttpStatus import org.springframework.http.MediaType import org.springframework.http.ResponseEntity import org.springframework.security.crypto.password.PasswordEncoder -import org.springframework.web.bind.annotation.* +import org.springframework.web.bind.annotation.DeleteMapping +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.PutMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam +import org.springframework.web.bind.annotation.ResponseStatus +import org.springframework.web.bind.annotation.RestController import org.springframework.web.multipart.MultipartFile @RestController @@ -60,21 +68,30 @@ class V2UserController( @PostMapping("") @Operation(summary = "Updates current user's data.", deprecated = true) - fun updateUserOld(@RequestBody @Valid dto: UserUpdateRequestDto?): PrivateUserAccountModel = updateUser(dto) + fun updateUserOld( + @RequestBody @Valid + dto: UserUpdateRequestDto?, + ): PrivateUserAccountModel = updateUser(dto) @PutMapping("") @Operation(summary = "Updates current user's data.") - fun updateUser(@RequestBody @Valid dto: UserUpdateRequestDto?): PrivateUserAccountModel { + fun updateUser( + @RequestBody @Valid + dto: UserUpdateRequestDto?, + ): PrivateUserAccountModel { val userAccount = userAccountService.update(authenticationFacade.authenticatedUserEntity, dto!!) return privateUserAccountModelAssembler.toModel(userAccount) } @PutMapping("/password") @Operation(summary = "Updates current user's password. Invalidates all previous sessions upon success.") - fun updateUserPassword(@RequestBody @Valid dto: UserUpdatePasswordRequestDto?): JwtAuthenticationResponse { + fun updateUserPassword( + @RequestBody @Valid + dto: UserUpdatePasswordRequestDto?, + ): JwtAuthenticationResponse { userAccountService.updatePassword(authenticationFacade.authenticatedUserEntity, dto!!) return JwtAuthenticationResponse( - jwtService.emitToken(authenticationFacade.authenticatedUser.id, true) + jwtService.emitToken(authenticationFacade.authenticatedUser.id, true), ) } @@ -109,7 +126,10 @@ class V2UserController( @PostMapping("/generate-super-token") @Operation(summary = "Generates new JWT token permitted to sensitive operations") - fun getSuperToken(@RequestBody @Valid req: SuperTokenRequest): ResponseEntity { + fun getSuperToken( + @RequestBody @Valid + req: SuperTokenRequest, + ): ResponseEntity { val entity = authenticationFacade.authenticatedUserEntity if (entity.isMfaEnabled) { mfaService.checkMfa(entity, req.otp) diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/batch/BatchJobManagementController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/batch/BatchJobManagementController.kt index 48c5e3d09b..1cb4cefa64 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/batch/BatchJobManagementController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/batch/BatchJobManagementController.kt @@ -42,13 +42,18 @@ class BatchJobManagementController( private val batchJobModelAssembler: BatchJobModelAssembler, private val pagedResourcesAssembler: PagedResourcesAssembler, private val authenticationFacade: AuthenticationFacade, - private val securityService: SecurityService + private val securityService: SecurityService, ) { @GetMapping(value = ["batch-jobs"]) @Operation(summary = "Lists all batch operations in project") @RequiresProjectPermissions([ Scope.BATCH_JOBS_VIEW ]) @AllowApiAccess - fun list(@Valid @ParameterObject @SortDefault("id") pageable: Pageable): PagedModel { + fun list( + @Valid + @ParameterObject + @SortDefault("id") + pageable: Pageable, + ): PagedModel { val views = batchJobService.getViews(projectHolder.project.id, null, pageable) return pagedResourcesAssembler.toModel(views, batchJobModelAssembler) } @@ -57,27 +62,35 @@ class BatchJobManagementController( @Operation(summary = "Lists all batch operations in project started by current user") @UseDefaultPermissions @AllowApiAccess - fun myList(@Valid @ParameterObject @SortDefault("id") pageable: Pageable): PagedModel { - val views = batchJobService.getViews( - projectId = projectHolder.project.id, - userAccount = authenticationFacade.authenticatedUser, - pageable = pageable - ) + fun myList( + @Valid + @ParameterObject + @SortDefault("id") + pageable: Pageable, + ): PagedModel { + val views = + batchJobService.getViews( + projectId = projectHolder.project.id, + userAccount = authenticationFacade.authenticatedUser, + pageable = pageable, + ) return pagedResourcesAssembler.toModel(views, batchJobModelAssembler) } @GetMapping(value = ["current-batch-jobs"]) @Operation( summary = "Returns all running and pending batch operations", - description = "Completed batch operations are returned only if they are not older than 1 hour. " + - "If user doesn't have permission to view all batch operations, only their operations are returned." + description = + "Completed batch operations are returned only if they are not older than 1 hour. " + + "If user doesn't have permission to view all batch operations, only their operations are returned.", ) @UseDefaultPermissions @AllowApiAccess fun currentJobs(): CollectionModel { - val views = batchJobService.getCurrentJobViews( - projectId = projectHolder.project.id, - ) + val views = + batchJobService.getCurrentJobViews( + projectId = projectHolder.project.id, + ) return batchJobModelAssembler.toCollectionModel(views) } @@ -85,7 +98,9 @@ class BatchJobManagementController( @Operation(summary = "Returns batch operation") @UseDefaultPermissions // Security: permission checked internally @AllowApiAccess - fun get(@PathVariable id: Long): BatchJobModel { + fun get( + @PathVariable id: Long, + ): BatchJobModel { val view = batchJobService.getView(id) checkViewPermission(view.batchJob) return batchJobModelAssembler.toModel(view) @@ -95,7 +110,9 @@ class BatchJobManagementController( @Operation(summary = "Stops batch operation (if possible)") @UseDefaultPermissions // Security: permission checked internally @AllowApiAccess - fun cancel(@PathVariable id: Long) { + fun cancel( + @PathVariable id: Long, + ) { checkCancelPermission(batchJobService.getJobDto(id)) batchJobCancellationManager.cancel(id) } diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/batch/StartBatchJobController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/batch/StartBatchJobController.kt index 7b58d8d8b2..15b400ecb5 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/batch/StartBatchJobController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/batch/StartBatchJobController.kt @@ -41,16 +41,19 @@ class StartBatchJobController( private val projectHolder: ProjectHolder, private val batchJobService: BatchJobService, private val authenticationFacade: AuthenticationFacade, - private val batchJobModelAssembler: BatchJobModelAssembler + private val batchJobModelAssembler: BatchJobModelAssembler, ) { @PostMapping(value = ["/pre-translate-by-tm"]) @Operation( summary = "Pre-translate by TM", - description = "Pre-translate provided keys to provided languages by TM." + description = "Pre-translate provided keys to provided languages by TM.", ) @RequiresProjectPermissions([ Scope.BATCH_PRE_TRANSLATE_BY_TM ]) @AllowApiAccess - fun translate(@Valid @RequestBody data: PreTranslationByTmRequest): BatchJobModel { + fun translate( + @Valid @RequestBody + data: PreTranslationByTmRequest, + ): BatchJobModel { securityService.checkLanguageTranslatePermission(projectHolder.project.id, data.targetLanguageIds) securityService.checkKeyIdsExistAndIsFromProject(data.keyIds, projectHolder.project.id) return batchJobService.startJob( @@ -64,11 +67,14 @@ class StartBatchJobController( @PostMapping(value = ["/machine-translate"]) @Operation( summary = "Machine Translation", - description = "Translate provided keys to provided languages through primary MT provider." + description = "Translate provided keys to provided languages through primary MT provider.", ) @RequiresProjectPermissions([ Scope.BATCH_MACHINE_TRANSLATE ]) @AllowApiAccess - fun machineTranslation(@Valid @RequestBody data: MachineTranslationRequest): BatchJobModel { + fun machineTranslation( + @Valid @RequestBody + data: MachineTranslationRequest, + ): BatchJobModel { securityService.checkLanguageTranslatePermission(projectHolder.project.id, data.targetLanguageIds) securityService.checkKeyIdsExistAndIsFromProject(data.keyIds, projectHolder.project.id) return batchJobService.startJob( @@ -83,7 +89,10 @@ class StartBatchJobController( @Operation(summary = "Delete keys") @RequiresProjectPermissions([ Scope.KEYS_DELETE ]) @AllowApiAccess - fun deleteKeys(@Valid @RequestBody data: DeleteKeysRequest): BatchJobModel { + fun deleteKeys( + @Valid @RequestBody + data: DeleteKeysRequest, + ): BatchJobModel { securityService.checkKeyIdsExistAndIsFromProject(data.keyIds, projectHolder.project.id) return batchJobService.startJob( data, @@ -97,7 +106,10 @@ class StartBatchJobController( @Operation(summary = "Set translation state") @RequiresProjectPermissions([ Scope.TRANSLATIONS_STATE_EDIT ]) @AllowApiAccess - fun setTranslationState(@Valid @RequestBody data: SetTranslationsStateStateRequest): BatchJobModel { + fun setTranslationState( + @Valid @RequestBody + data: SetTranslationsStateStateRequest, + ): BatchJobModel { securityService.checkKeyIdsExistAndIsFromProject(data.keyIds, projectHolder.project.id) securityService.checkLanguageStateChangePermission(projectHolder.project.id, data.languageIds) return batchJobService.startJob( @@ -111,11 +123,14 @@ class StartBatchJobController( @PostMapping(value = ["/clear-translations"]) @Operation( summary = "Clear translation values", - description = "Clear translation values for provided keys in selected languages." + description = "Clear translation values for provided keys in selected languages.", ) @RequiresProjectPermissions([ Scope.TRANSLATIONS_EDIT ]) @AllowApiAccess - fun clearTranslations(@Valid @RequestBody data: ClearTranslationsRequest): BatchJobModel { + fun clearTranslations( + @Valid @RequestBody + data: ClearTranslationsRequest, + ): BatchJobModel { securityService.checkKeyIdsExistAndIsFromProject(data.keyIds, projectHolder.project.id) securityService.checkLanguageTranslatePermission(projectHolder.project.id, data.languageIds) return batchJobService.startJob( @@ -129,11 +144,14 @@ class StartBatchJobController( @PostMapping(value = ["/copy-translations"]) @Operation( summary = "Copy translation values", - description = "Copy translation values from one language to other languages." + description = "Copy translation values from one language to other languages.", ) @RequiresProjectPermissions([ Scope.TRANSLATIONS_EDIT ]) @AllowApiAccess - fun copyTranslations(@Valid @RequestBody data: CopyTranslationRequest): BatchJobModel { + fun copyTranslations( + @Valid @RequestBody + data: CopyTranslationRequest, + ): BatchJobModel { securityService.checkKeyIdsExistAndIsFromProject(data.keyIds, projectHolder.project.id) securityService.checkLanguageTranslatePermission(projectHolder.project.id, data.targetLanguageIds) securityService.checkLanguageViewPermission(projectHolder.project.id, listOf(data.sourceLanguageId)) @@ -149,7 +167,10 @@ class StartBatchJobController( @Operation(summary = "Add tags") @RequiresProjectPermissions([ Scope.KEYS_EDIT ]) @AllowApiAccess - fun tagKeys(@Valid @RequestBody data: TagKeysRequest): BatchJobModel { + fun tagKeys( + @Valid @RequestBody + data: TagKeysRequest, + ): BatchJobModel { data.tags.validate() securityService.checkKeyIdsExistAndIsFromProject(data.keyIds, projectHolder.project.id) return batchJobService.startJob( @@ -164,7 +185,10 @@ class StartBatchJobController( @Operation(summary = "Remove tags") @RequiresProjectPermissions([ Scope.KEYS_EDIT ]) @AllowApiAccess - fun untagKeys(@Valid @RequestBody data: UntagKeysRequest): BatchJobModel { + fun untagKeys( + @Valid @RequestBody + data: UntagKeysRequest, + ): BatchJobModel { securityService.checkKeyIdsExistAndIsFromProject(data.keyIds, projectHolder.project.id) return batchJobService.startJob( data, @@ -178,7 +202,10 @@ class StartBatchJobController( @Operation(summary = "Set keys namespace") @RequiresProjectPermissions([ Scope.KEYS_EDIT ]) @AllowApiAccess - fun setKeysNamespace(@Valid @RequestBody data: SetKeysNamespaceRequest): BatchJobModel { + fun setKeysNamespace( + @Valid @RequestBody + data: SetKeysNamespaceRequest, + ): BatchJobModel { securityService.checkKeyIdsExistAndIsFromProject(data.keyIds, projectHolder.project.id) return batchJobService.startJob( data, diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/batch/V2ExportController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/batch/V2ExportController.kt index 3cd30a5400..0f3bdd8693 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/batch/V2ExportController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/batch/V2ExportController.kt @@ -48,13 +48,14 @@ class V2ExportController( @RequiresProjectPermissions([ Scope.TRANSLATIONS_VIEW ]) @AllowApiAccess fun export( - @ParameterObject params: ExportParams + @ParameterObject params: ExportParams, ): ResponseEntity { - params.languages = languageService - .getLanguagesForExport(params.languages, projectHolder.project.id, authenticationFacade.authenticatedUser.id) - .toList() - .map { language -> language.tag } - .toSet() + params.languages = + languageService + .getLanguagesForExport(params.languages, projectHolder.project.id, authenticationFacade.authenticatedUser.id) + .toList() + .map { language -> language.tag } + .toSet() val exported = exportService.export(projectHolder.project.id, params) checkExportNotEmpty(exported) return getExportResponse(params, exported) @@ -63,12 +64,12 @@ class V2ExportController( @PostMapping(value = [""]) @Operation( summary = """Exports data (post). Useful when providing params exceeding allowed query size. - """ + """, ) @RequiresProjectPermissions([ Scope.TRANSLATIONS_VIEW ]) @AllowApiAccess fun exportPost( - @RequestBody params: ExportParams + @RequestBody params: ExportParams, ): ResponseEntity { return export(params) } @@ -77,18 +78,22 @@ class V2ExportController( return getHeaders("$projectName.zip", "application/zip") } - private fun getHeaders(fileName: String, mediaType: String): HttpHeaders { + private fun getHeaders( + fileName: String, + mediaType: String, + ): HttpHeaders { val httpHeaders = HttpHeaders() httpHeaders.contentType = MediaType.valueOf(mediaType) - httpHeaders.contentDisposition = ContentDisposition.parse( - """attachment; filename="$fileName"""", - ) + httpHeaders.contentDisposition = + ContentDisposition.parse( + """attachment; filename="$fileName"""", + ) return httpHeaders } private fun getExportResponse( params: ExportParams, - exported: Map + exported: Map, ): ResponseEntity { if (params.zip) { return getZipResponseEntity(exported) @@ -106,7 +111,7 @@ class V2ExportController( private fun exportSingleFile( exported: Map, - params: ExportParams + params: ExportParams, ): ResponseEntity { val (fileName, stream) = exported.entries.first() val fileNameWithoutSlash = fileName.replace("^/(.*)".toRegex(), "$1") @@ -117,7 +122,7 @@ class V2ExportController( IOUtils.copy(stream, out) stream.close() out.close() - } + }, ) } @@ -127,13 +132,13 @@ class V2ExportController( return ResponseEntity.ok().headers(httpHeaders).body( streamingResponseBodyProvider.createStreamingResponseBody { out: OutputStream -> streamZipResponse(out, exported) - } + }, ) } private fun streamZipResponse( out: OutputStream, - exported: Map + exported: Map, ) { val zipOutputStream = ZipOutputStream(out) diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/configurationProps/ConfigurationDocumentationProvider.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/configurationProps/ConfigurationDocumentationProvider.kt index aa65c4cac2..d1eee75b80 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/configurationProps/ConfigurationDocumentationProvider.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/configurationProps/ConfigurationDocumentationProvider.kt @@ -20,7 +20,10 @@ class ConfigurationDocumentationProvider { globalItems + listOf(handleObject(TolgeeProperties(), null)) } - private fun handleObject(obj: Any, parent: KProperty<*>?): Group { + private fun handleObject( + obj: Any, + parent: KProperty<*>?, + ): Group { val additionalProps: MutableList = mutableListOf() obj::class.findAnnotations(AdditionalDocsProperties::class).forEach { additionalProp -> if (additionalProp.global) { @@ -36,33 +39,40 @@ class ConfigurationDocumentationProvider { val objDef = obj::class.findAnnotations(DocProperty::class).singleOrNull() val confPropsDef = obj::class.findAnnotations(ConfigurationProperties::class).singleOrNull() - val props = obj::class.declaredMemberProperties.mapNotNull { - handleProperty(it, obj) - }.sortedWith( - compareBy( - { it is Group }, - { it.name }, + val props = + obj::class.declaredMemberProperties.mapNotNull { + handleProperty(it, obj) + }.sortedWith( + compareBy( + { it is Group }, + { it.name }, + ), ) - ) - val name = objDef?.name?.nullIfEmpty ?: parent?.name ?: confPropsDef?.prefix?.replace( - "(.*)\\.(.+?)\$".toRegex(), - "$1" - )?.nullIfEmpty - ?: throw RuntimeException("No name for $obj with parent $parent") + val name = + objDef?.name?.nullIfEmpty ?: parent?.name ?: confPropsDef?.prefix?.replace( + "(.*)\\.(.+?)\$".toRegex(), + "$1", + )?.nullIfEmpty + ?: throw RuntimeException("No name for $obj with parent $parent") return Group( name = name, displayName = objDef?.displayName?.nullIfEmpty, description = objDef?.description?.nullIfEmpty, children = props + additionalProps, - prefix = objDef?.prefix?.nullIfEmpty ?: confPropsDef?.prefix?.nullIfEmpty - ?: throw NullPointerException("No prefix for ${obj::class.simpleName}") + prefix = + objDef?.prefix?.nullIfEmpty ?: confPropsDef?.prefix?.nullIfEmpty + ?: throw NullPointerException("No prefix for ${obj::class.simpleName}"), ) } - private fun handleProperty(it: KProperty1, obj: Any): DocItem? { - val annotation = it.javaField?.getAnnotation(DocProperty::class.java) - ?: it.findAnnotations().singleOrNull() + private fun handleProperty( + it: KProperty1, + obj: Any, + ): DocItem? { + val annotation = + it.javaField?.getAnnotation(DocProperty::class.java) + ?: it.findAnnotations().singleOrNull() if (annotation?.hidden == true) { return null } @@ -88,8 +98,9 @@ class ConfigurationDocumentationProvider { } else -> { - val child = it.getter.call(obj) - ?: throw RuntimeException("Property ${it.name} is null") + val child = + it.getter.call(obj) + ?: throw RuntimeException("Property ${it.name} is null") handleObject(child, it) } } @@ -106,10 +117,14 @@ class ConfigurationDocumentationProvider { private fun getPropertyName( annotation: DocProperty?, - it: KProperty1 + it: KProperty1, ) = annotation?.name?.nullIfEmpty ?: it.name - private fun getDefaultValue(annotation: DocProperty?, obj: Any, property: KProperty<*>): String { + private fun getDefaultValue( + annotation: DocProperty?, + obj: Any, + property: KProperty<*>, + ): String { if (!annotation?.defaultValue.isNullOrEmpty()) { return annotation?.defaultValue ?: "" } @@ -125,7 +140,7 @@ class ConfigurationDocumentationProvider { displayName = docProperty.displayName, description = docProperty.description, children = docProperty.children.map { getPropertyTree(it) }, - prefix = docProperty.prefix.nullIfEmpty + prefix = docProperty.prefix.nullIfEmpty, ) } return Property( diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/configurationProps/ConfigurationPropsController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/configurationProps/ConfigurationPropsController.kt index 9e0c6455ee..17b48a836a 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/configurationProps/ConfigurationPropsController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/configurationProps/ConfigurationPropsController.kt @@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping( value = [ "/v2/public/configuration-properties", - ] + ], ) class ConfigurationPropsController : IController { val docs get() = ConfigurationDocumentationProvider().docs diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/configurationProps/data.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/configurationProps/data.kt index 8c49b7b6a4..eabd9992ab 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/configurationProps/data.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/configurationProps/data.kt @@ -21,5 +21,5 @@ data class Group( override val displayName: String?, override val description: String?, val children: List, - val prefix: String? + val prefix: String?, ) : DocItem diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/contentDelivery/ContentDeliveryConfigController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/contentDelivery/ContentDeliveryConfigController.kt index b2d03fa352..5e19d46f31 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/contentDelivery/ContentDeliveryConfigController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/contentDelivery/ContentDeliveryConfigController.kt @@ -34,7 +34,7 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping( value = [ "/v2/projects/{projectId}/content-delivery-configs", - ] + ], ) @Tag(name = "Content Delivery", description = "Endpoints for Content Delivery management") class ContentDeliveryConfigController( @@ -43,13 +43,16 @@ class ContentDeliveryConfigController( private val contentDeliveryConfigModelAssembler: ContentDeliveryConfigModelAssembler, @Suppress("SpringJavaInjectionPointsAutowiringInspection") private val pagedContentDeliveryConfigModelAssemblerExporter: PagedResourcesAssembler, - private val contentDeliveryUploader: ContentDeliveryUploader + private val contentDeliveryUploader: ContentDeliveryUploader, ) : IController { @PostMapping("") @Operation(description = "Create Content Delivery Config") @RequiresProjectPermissions([Scope.CONTENT_DELIVERY_MANAGE]) @AllowApiAccess - fun create(@Valid @RequestBody dto: ContentDeliveryConfigRequest): ContentDeliveryConfigModel { + fun create( + @Valid @RequestBody + dto: ContentDeliveryConfigRequest, + ): ContentDeliveryConfigModel { val contentDeliveryConfig = contentDeliveryService.create(projectHolder.project.id, dto) return contentDeliveryConfigModelAssembler.toModel(contentDeliveryConfig) } @@ -60,7 +63,8 @@ class ContentDeliveryConfigController( @AllowApiAccess fun update( @PathVariable id: Long, - @Valid @RequestBody dto: ContentDeliveryConfigRequest + @Valid @RequestBody + dto: ContentDeliveryConfigRequest, ): ContentDeliveryConfigModel { val contentDeliveryConfig = contentDeliveryService.update(projectId = projectHolder.project.id, id, dto) return contentDeliveryConfigModelAssembler.toModel(contentDeliveryConfig) @@ -70,7 +74,9 @@ class ContentDeliveryConfigController( @GetMapping("") @Operation(description = "List existing Content Delivery Configs") @AllowApiAccess - fun list(@ParameterObject pageable: Pageable): PagedModel { + fun list( + @ParameterObject pageable: Pageable, + ): PagedModel { val page = contentDeliveryService.getAllInProject(projectHolder.project.id, pageable) return pagedContentDeliveryConfigModelAssemblerExporter.toModel(page, contentDeliveryConfigModelAssembler) } @@ -79,7 +85,9 @@ class ContentDeliveryConfigController( @DeleteMapping("/{id}") @Operation(description = "Delete Content Delivery Config") @AllowApiAccess - fun delete(@PathVariable id: Long) { + fun delete( + @PathVariable id: Long, + ) { contentDeliveryService.delete(projectHolder.project.id, id) } @@ -87,7 +95,9 @@ class ContentDeliveryConfigController( @GetMapping("/{id}") @Operation(description = "Get Content Delivery Config") @AllowApiAccess - fun get(@PathVariable id: Long): ContentDeliveryConfigModel { + fun get( + @PathVariable id: Long, + ): ContentDeliveryConfigModel { return contentDeliveryConfigModelAssembler.toModel(contentDeliveryService.get(projectHolder.project.id, id)) } @@ -95,7 +105,9 @@ class ContentDeliveryConfigController( @PostMapping("/{id}") @Operation(description = "Publish to Content Delivery") @AllowApiAccess - fun post(@PathVariable id: Long) { + fun post( + @PathVariable id: Long, + ) { val exporter = contentDeliveryService.get(projectHolder.project.id, id) contentDeliveryUploader.upload(exporter.id) } diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/organization/OrganizationController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/organization/OrganizationController.kt index 8a2f4d7368..2c686afcd0 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/organization/OrganizationController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/organization/OrganizationController.kt @@ -83,7 +83,7 @@ class OrganizationController( private val organizationService: OrganizationService, private val arrayResourcesAssembler: PagedResourcesAssembler, private val arrayUserResourcesAssembler: PagedResourcesAssembler< - Pair> + Pair>, >, private val organizationModelAssembler: OrganizationModelAssembler, private val userAccountWithOrganizationRoleModelAssembler: UserAccountWithOrganizationRoleModelAssembler, @@ -98,14 +98,17 @@ class OrganizationController( private val organizationStatsService: OrganizationStatsService, private val translationsLimitProvider: TranslationsLimitProvider, private val projectService: ProjectService, - private val mtBucketSizeProvider: MtBucketSizeProvider + private val mtBucketSizeProvider: MtBucketSizeProvider, ) { @PostMapping @Transactional @Operation(summary = "Creates organization") @AllowApiAccess(AuthTokenType.ONLY_PAT) @IsGlobalRoute - fun create(@RequestBody @Valid dto: OrganizationDto): ResponseEntity { + fun create( + @RequestBody @Valid + dto: OrganizationDto, + ): ResponseEntity { if (!this.tolgeeProperties.authentication.userCanCreateOrganizations && authenticationFacade.authenticatedUser.role != UserAccount.Role.ADMIN ) { @@ -113,7 +116,8 @@ class OrganizationController( } this.organizationService.create(dto).let { return ResponseEntity( - organizationModelAssembler.toModel(OrganizationView.of(it, OrganizationRoleType.OWNER)), HttpStatus.CREATED + organizationModelAssembler.toModel(OrganizationView.of(it, OrganizationRoleType.OWNER)), + HttpStatus.CREATED, ) } } @@ -122,7 +126,9 @@ class OrganizationController( @Operation(summary = "Returns organization by ID") @AllowApiAccess(AuthTokenType.ONLY_PAT) @UseDefaultPermissions - fun get(@PathVariable("id") id: Long): OrganizationModel? { + fun get( + @PathVariable("id") id: Long, + ): OrganizationModel? { val organization = organizationService.get(id) val roleType = organizationRoleService.findType(id) return OrganizationView.of(organization, roleType).toModel() @@ -132,7 +138,9 @@ class OrganizationController( @Operation(summary = "Returns organization by address part") @AllowApiAccess(AuthTokenType.ONLY_PAT) @UseDefaultPermissions - fun get(@PathVariable("slug") slug: String): OrganizationModel { + fun get( + @PathVariable("slug") slug: String, + ): OrganizationModel { val organization = organizationService.get(slug) val roleType = organizationRoleService.findType(organization.id) return OrganizationView.of(organization, roleType).toModel() @@ -143,8 +151,10 @@ class OrganizationController( @AllowApiAccess(AuthTokenType.ONLY_PAT) @IsGlobalRoute fun getAll( - @ParameterObject @SortDefault(sort = ["id"]) pageable: Pageable, - params: OrganizationRequestParamsDto + @ParameterObject + @SortDefault(sort = ["id"]) + pageable: Pageable, + params: OrganizationRequestParamsDto, ): PagedModel? { val organizations = organizationService.findPermittedPaged(pageable, params) return arrayResourcesAssembler.toModel(organizations, organizationModelAssembler) @@ -154,7 +164,12 @@ class OrganizationController( @Operation(summary = "Updates organization data") @RequiresOrganizationRole(OrganizationRoleType.OWNER) @RequiresSuperAuthentication - fun update(@PathVariable("id") id: Long, @RequestBody @Valid dto: OrganizationDto): OrganizationModel { + fun update( + @PathVariable("id") + id: Long, + @RequestBody @Valid + dto: OrganizationDto, + ): OrganizationModel { return this.organizationService.edit(id, editDto = dto).toModel() } @@ -162,7 +177,9 @@ class OrganizationController( @Operation(summary = "Deletes organization and all its projects") @RequiresOrganizationRole(OrganizationRoleType.OWNER) @RequiresSuperAuthentication - fun delete(@PathVariable("id") id: Long) { + fun delete( + @PathVariable("id") id: Long, + ) { val org = organizationService.get(id) organizationService.delete(org) } @@ -173,15 +190,18 @@ class OrganizationController( @RequiresSuperAuthentication fun getAllUsers( @PathVariable("id") id: Long, - @ParameterObject @SortDefault(sort = ["name", "username"], direction = Sort.Direction.ASC) pageable: Pageable, - @RequestParam("search") search: String? + @ParameterObject + @SortDefault(sort = ["name", "username"], direction = Sort.Direction.ASC) + pageable: Pageable, + @RequestParam("search") search: String?, ): PagedModel { val allInOrganization = userAccountService.getAllInOrganization(id, pageable, search) val userIds = allInOrganization.content.map { it.id } val projectsWithDirectPermission = projectService.getProjectsWithDirectPermissions(id, userIds) - val pairs = allInOrganization.content.map { user -> - user to (projectsWithDirectPermission[user.id] ?: emptyList()) - } + val pairs = + allInOrganization.content.map { user -> + user to (projectsWithDirectPermission[user.id] ?: emptyList()) + } val data = PageImpl(pairs, allInOrganization.pageable, allInOrganization.totalElements) @@ -192,7 +212,9 @@ class OrganizationController( @Operation(summary = "Removes current user from organization") @UseDefaultPermissions @RequiresSuperAuthentication - fun leaveOrganization(@PathVariable("id") id: Long) { + fun leaveOrganization( + @PathVariable("id") id: Long, + ) { organizationService.find(id)?.let { if (!organizationService.isThereAnotherOwner(id)) { throw ValidationException(Message.ORGANIZATION_HAS_NO_OTHER_OWNER) @@ -208,7 +230,7 @@ class OrganizationController( fun setUserRole( @PathVariable("organizationId") organizationId: Long, @PathVariable("userId") userId: Long, - @RequestBody dto: SetOrganizationRoleDto + @RequestBody dto: SetOrganizationRoleDto, ) { if (authenticationFacade.authenticatedUser.id == userId) { throw BadRequestException(Message.CANNOT_SET_YOUR_OWN_ROLE) @@ -222,7 +244,7 @@ class OrganizationController( @RequiresSuperAuthentication fun removeUser( @PathVariable("organizationId") organizationId: Long, - @PathVariable("userId") userId: Long + @PathVariable("userId") userId: Long, ) { organizationRoleService.removeUser(organizationId, userId) } @@ -232,19 +254,21 @@ class OrganizationController( @RequiresOrganizationRole(OrganizationRoleType.OWNER) @RequiresSuperAuthentication fun inviteUser( - @RequestBody @Valid dto: OrganizationInviteUserDto, - @PathVariable("id") id: Long + @RequestBody @Valid + dto: OrganizationInviteUserDto, + @PathVariable("id") id: Long, ): OrganizationInvitationModel { val organization = organizationService.get(id) - val invitation = invitationService.create( - CreateOrganizationInvitationParams( - organization = organization, - type = dto.roleType, - email = dto.email, - name = dto.name + val invitation = + invitationService.create( + CreateOrganizationInvitationParams( + organization = organization, + type = dto.roleType, + email = dto.email, + name = dto.name, + ), ) - ) return organizationInvitationModelAssembler.toModel(invitation) } @@ -253,8 +277,9 @@ class OrganizationController( @Operation(summary = "Returns all invitations to organization") @RequiresOrganizationRole(OrganizationRoleType.OWNER) @RequiresSuperAuthentication - fun getInvitations(@PathVariable("organizationId") id: Long): - CollectionModel { + fun getInvitations( + @PathVariable("organizationId") id: Long, + ): CollectionModel { val organization = organizationService.find(id) ?: throw NotFoundException() return invitationService.getForOrganization(organization).let { organizationInvitationModelAssembler.toCollectionModel(it) @@ -267,7 +292,7 @@ class OrganizationController( @RequiresOrganizationRole(OrganizationRoleType.OWNER) fun uploadAvatar( @RequestParam("avatar") avatar: MultipartFile, - @PathVariable id: Long + @PathVariable id: Long, ): OrganizationModel { imageUploadService.validateIsImage(avatar) val organization = organizationService.get(id) @@ -281,7 +306,7 @@ class OrganizationController( @ResponseStatus(HttpStatus.OK) @RequiresOrganizationRole(OrganizationRoleType.OWNER) fun removeAvatar( - @PathVariable id: Long + @PathVariable id: Long, ): OrganizationModel { val organization = organizationService.get(id) val roleType = organizationRoleService.getType(organization.id) @@ -303,7 +328,7 @@ class OrganizationController( @Operation(description = "Returns current organization usage") @RequiresOrganizationRole fun getUsage( - @PathVariable organizationId: Long + @PathVariable organizationId: Long, ): PublicUsageModel { val organization = organizationService.get(organizationId) val creditBalances = mtCreditBucketService.getCreditBalances(organization) @@ -325,7 +350,7 @@ class OrganizationController( includedTranslations = translationsLimitProvider.getPlanTranslations(organization), includedTranslationSlots = translationsLimitProvider.getPlanTranslationSlots(organization), translationSlotsLimit = translationsLimitProvider.getTranslationSlotsLimit(organization), - translationsLimit = translationsLimitProvider.getTranslationLimit(organization) + translationsLimit = translationsLimitProvider.getTranslationLimit(organization), ) } diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/organization/OrganizationProjectController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/organization/OrganizationProjectController.kt index 4c9076a9e4..a7f350d4cc 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/organization/OrganizationProjectController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/organization/OrganizationProjectController.kt @@ -38,7 +38,7 @@ class OrganizationProjectController( private val pagedProjectResourcesAssembler: PagedResourcesAssembler, private val projectService: ProjectService, private val projectModelAssembler: ProjectModelAssembler, - private val projectWithStatsFacade: ProjectWithStatsFacade + private val projectWithStatsFacade: ProjectWithStatsFacade, ) { @GetMapping("/{id:[0-9]+}/projects") @Operation(summary = "Returns all organization projects the user has access to") @@ -46,7 +46,7 @@ class OrganizationProjectController( fun getAllProjects( @PathVariable("id") id: Long, @ParameterObject pageable: Pageable, - @RequestParam("search") search: String? + @RequestParam("search") search: String?, ): PagedModel { return organizationService.find(id)?.let { organization -> projectService.findPermittedInOrganizationPaged(pageable, search, organizationId = organization.id) @@ -62,7 +62,7 @@ class OrganizationProjectController( fun getAllProjects( @PathVariable("slug") slug: String, @ParameterObject pageable: Pageable, - @RequestParam("search") search: String? + @RequestParam("search") search: String?, ): PagedModel { return organizationService.find(slug)?.let { getAllProjects(it.id, pageable, search) @@ -70,30 +70,34 @@ class OrganizationProjectController( } @Operation( - summary = "Returns all projects (including statistics)" + - " where current user has any permission (except none)" + summary = + "Returns all projects (including statistics)" + + " where current user has any permission (except none)", ) @GetMapping("/{organizationId:[0-9]+}/projects-with-stats", produces = [MediaTypes.HAL_JSON_VALUE]) @UseDefaultPermissions fun getAllWithStatistics( @ParameterObject pageable: Pageable, @RequestParam("search") search: String?, - @PathVariable organizationId: Long + @PathVariable organizationId: Long, ): PagedModel { val projects = projectService.findPermittedInOrganizationPaged(pageable, search, organizationId = organizationId) return projectWithStatsFacade.getPagedModelWithStats(projects) } @Operation( - summary = "Returns all projects (including statistics) " + - "where current user has any permission (except none)" + summary = + "Returns all projects (including statistics) " + + "where current user has any permission (except none)", ) @GetMapping("/{slug:.*[a-z].*}/projects-with-stats", produces = [MediaTypes.HAL_JSON_VALUE]) @UseDefaultPermissions fun getAllWithStatistics( - @ParameterObject @SortDefault("id") pageable: Pageable, + @ParameterObject + @SortDefault("id") + pageable: Pageable, @RequestParam("search") search: String?, - @PathVariable("slug") organizationSlug: String + @PathVariable("slug") organizationSlug: String, ): PagedModel { return organizationService.find(organizationSlug)?.let { organization -> return getAllWithStatistics(pageable, search, organization.id) diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/suggestion/MachineTranslationSuggestionFacade.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/suggestion/MachineTranslationSuggestionFacade.kt index 123000fc92..92ca1488df 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/suggestion/MachineTranslationSuggestionFacade.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/suggestion/MachineTranslationSuggestionFacade.kt @@ -39,7 +39,7 @@ class MachineTranslationSuggestionFacade( securityService.checkLanguageTranslatePermission( projectHolder.project.id, - listOf(targetLanguage.id) + listOf(targetLanguage.id), ) val balanceBefore = mtCreditBucketService.getCreditBalances(projectHolder.projectEntity) @@ -51,7 +51,7 @@ class MachineTranslationSuggestionFacade( SuggestResultModel( machineTranslations = resultData?.map { it.key to it.value.output }?.toMap(), result = resultData, - baseBlank = baseBlank + baseBlank = baseBlank, ) } } @@ -68,22 +68,24 @@ class MachineTranslationSuggestionFacade( */ private fun getTranslationResults( dto: SuggestRequestDto, - targetLanguage: Language + targetLanguage: Language, ): Map? { val key = dto.key val resultMap = mtService.getMachineTranslations( projectHolder.projectEntity, - key, dto.baseText, + key, + dto.baseText, targetLanguage, - dto.services + dto.services, ) - val resultData = resultMap - .map { (key, value) -> - key to TranslationItemModel(value.translatedText.orEmpty(), value.contextDescription) - }.toMap() + val resultData = + resultMap + .map { (key, value) -> + key to TranslationItemModel(value.translatedText.orEmpty(), value.contextDescription) + }.toMap() if (resultMap.values.all { it.baseBlank }) { return null @@ -92,7 +94,10 @@ class MachineTranslationSuggestionFacade( return resultData } - fun catchingOutOfCredits(balanceBefore: MtCreditBalanceDto, fn: () -> T): T { + fun catchingOutOfCredits( + balanceBefore: MtCreditBalanceDto, + fn: () -> T, + ): T { try { return fn() } catch (e: OutOfCreditsException) { @@ -103,19 +108,20 @@ class MachineTranslationSuggestionFacade( } throw BadRequestException( Message.OUT_OF_CREDITS, - listOf(balanceBefore.creditBalance, balanceBefore.extraCreditBalance) + listOf(balanceBefore.creditBalance, balanceBefore.extraCreditBalance), ) } } val SuggestRequestDto.key - get() = if (this.baseText != null) { - null - } else { - keyService.findOptional(this.keyId).orElseThrow { NotFoundException(Message.KEY_NOT_FOUND) }?.also { - it.checkInProject() + get() = + if (this.baseText != null) { + null + } else { + keyService.findOptional(this.keyId).orElseThrow { NotFoundException(Message.KEY_NOT_FOUND) }?.also { + it.checkInProject() + } } - } val SuggestRequestDto.targetLanguage get() = languageService.get(this.targetLanguageId) diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/suggestion/MtResultStreamer.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/suggestion/MtResultStreamer.kt index 865d28961f..89fe906058 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/suggestion/MtResultStreamer.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/suggestion/MtResultStreamer.kt @@ -36,7 +36,6 @@ class MtResultStreamer( private val applicationContext: ApplicationContext, private val streamingResponseBodyProvider: StreamingResponseBodyProvider, ) : Logging { - private lateinit var outputStream: OutputStream fun stream(): StreamingResponseBody { @@ -98,16 +97,17 @@ class MtResultStreamer( private fun writeTranslatedValue( writer: OutputStreamWriter, service: MtServiceType, - translated: Map? + translated: Map?, ) { - val model = translated?.get(service) - ?.let { it.translatedText?.let { text -> TranslationItemModel(text, it.contextDescription) } } + val model = + translated?.get(service) + ?.let { it.translatedText?.let { text -> TranslationItemModel(text, it.contextDescription) } } writer.writeJson( StreamedSuggestionItem( service, model, - ) + ), ) } @@ -115,21 +115,21 @@ class MtResultStreamer( project: Project, key: Key?, dto: SuggestRequestDto, - service: MtServiceType + service: MtServiceType, ): Map { return mtService.getMachineTranslations( project, key, dto.baseText, with(machineTranslationSuggestionFacade) { dto.targetLanguage }, - setOf(service) + setOf(service), ) } private fun writeException( e: Exception, writer: OutputStreamWriter, - service: MtServiceType + service: MtServiceType, ) { val exceptionWithMessage = (e as? ExceptionWithMessage) writer.writeJson( @@ -138,8 +138,8 @@ class MtResultStreamer( null, errorMessage = exceptionWithMessage?.tolgeeMessage, errorParams = exceptionWithMessage?.params, - errorException = e::class.qualifiedName - ) + errorException = e::class.qualifiedName, + ), ) if (e !is BadRequestException && e !is NotFoundException) { Sentry.captureException(e) @@ -186,7 +186,7 @@ class MtResultStreamer( mtService.getBaseTranslation( key = key, baseTranslationText = dto.baseText, - baseLanguage = baseLanguage + baseLanguage = baseLanguage, ).isNullOrBlank() } } diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/suggestion/TranslationSuggestionController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/suggestion/TranslationSuggestionController.kt index 51950cfcaa..07db3a5964 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/suggestion/TranslationSuggestionController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/suggestion/TranslationSuggestionController.kt @@ -45,56 +45,63 @@ class TranslationSuggestionController( @Suppress("SpringJavaInjectionPointsAutowiringInspection") private val arraytranslationMemoryItemModelAssembler: PagedResourcesAssembler, private val securityService: SecurityService, - private val machineTranslationSuggestionFacade: MachineTranslationSuggestionFacade + private val machineTranslationSuggestionFacade: MachineTranslationSuggestionFacade, ) { @PostMapping("/machine-translations") @Operation(summary = "Suggests machine translations from enabled services") @RequiresProjectPermissions([ Scope.TRANSLATIONS_EDIT ]) @AllowApiAccess - fun suggestMachineTranslations(@RequestBody @Valid dto: SuggestRequestDto): SuggestResultModel { + fun suggestMachineTranslations( + @RequestBody @Valid + dto: SuggestRequestDto, + ): SuggestResultModel { return machineTranslationSuggestionFacade.suggestSync(dto) } @PostMapping("/machine-translations-streaming", produces = ["application/x-ndjson"]) @Operation( - summary = "Suggests machine translations from enabled services (streaming).\n" + - "If an error occurs when any of the services is used," + - " the error information is returned as a part of the result item, while the response has 200 status code." + summary = + "Suggests machine translations from enabled services (streaming).\n" + + "If an error occurs when any of the services is used," + + " the error information is returned as a part of the result item, while the response has 200 status code.", ) - @RequiresProjectPermissions([ Scope.TRANSLATIONS_EDIT ]) @AllowApiAccess fun suggestMachineTranslationsStreaming( - @RequestBody @Valid dto: SuggestRequestDto + @RequestBody @Valid + dto: SuggestRequestDto, ): ResponseEntity { return ResponseEntity.ok().headers { it.add("X-Accel-Buffering", "no") }.body( - machineTranslationSuggestionFacade.suggestStreaming(dto) + machineTranslationSuggestionFacade.suggestStreaming(dto), ) } @PostMapping("/translation-memory") @Operation( - summary = "Suggests machine translations from translation memory." + - "\n\nThe result is always sorted by similarity, so sorting is not supported." + summary = + "Suggests machine translations from translation memory." + + "\n\nThe result is always sorted by similarity, so sorting is not supported.", ) @RequiresProjectPermissions([ Scope.TRANSLATIONS_EDIT ]) @AllowApiAccess fun suggestTranslationMemory( - @RequestBody @Valid dto: SuggestRequestDto, - @ParameterObject pageable: Pageable + @RequestBody @Valid + dto: SuggestRequestDto, + @ParameterObject pageable: Pageable, ): PagedModel { val targetLanguage = languageService.get(dto.targetLanguageId) securityService.checkLanguageTranslatePermission(projectHolder.project.id, listOf(targetLanguage.id)) - val data = dto.baseText?.let { baseText -> translationMemoryService.suggest(baseText, targetLanguage, pageable) } - ?: let { - val key = keyService.findOptional(dto.keyId).orElseThrow { NotFoundException(Message.KEY_NOT_FOUND) } - key.checkInProject() - translationMemoryService.suggest(key, targetLanguage, pageable) - } + val data = + dto.baseText?.let { baseText -> translationMemoryService.suggest(baseText, targetLanguage, pageable) } + ?: let { + val key = keyService.findOptional(dto.keyId).orElseThrow { NotFoundException(Message.KEY_NOT_FOUND) } + key.checkInProject() + translationMemoryService.suggest(key, targetLanguage, pageable) + } return arraytranslationMemoryItemModelAssembler.toModel(data, translationMemoryItemModelAssembler) } diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/translation/TranslationCommentController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/translation/TranslationCommentController.kt index 86857432d4..7d593c9d52 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/translation/TranslationCommentController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/translation/TranslationCommentController.kt @@ -55,13 +55,13 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping( value = [ "/v2/projects/{projectId:[0-9]+}/translations/", - "/v2/projects/translations/" - ] + "/v2/projects/translations/", + ], ) @Tags( value = [ Tag(name = "Translation Comments", description = "Operations related to translation comments"), - ] + ], ) class TranslationCommentController( private val projectHolder: ProjectHolder, @@ -71,22 +71,21 @@ class TranslationCommentController( private val translationCommentModelAssembler: TranslationCommentModelAssembler, private val authenticationFacade: AuthenticationFacade, private val securityService: SecurityService, - private val translationModelAssembler: TranslationModelAssembler + private val translationModelAssembler: TranslationModelAssembler, ) { - @GetMapping(value = ["{translationId}/comments"]) @Operation(summary = "Returns translation comments of translation") @UseDefaultPermissions @AllowApiAccess fun getAll( @PathVariable translationId: Long, - @ParameterObject pageable: Pageable + @ParameterObject pageable: Pageable, ): PagedModel { val translation = translationService.find(translationId) ?: throw NotFoundException() translation.checkFromProject() return pagedResourcesAssembler.toModel( translationCommentService.getPaged(translation, pageable), - translationCommentModelAssembler + translationCommentModelAssembler, ) } @@ -94,7 +93,10 @@ class TranslationCommentController( @Operation(summary = "Returns single translation comment") @UseDefaultPermissions @AllowApiAccess - fun get(@PathVariable translationId: Long, @PathVariable commentId: Long): TranslationCommentModel { + fun get( + @PathVariable translationId: Long, + @PathVariable commentId: Long, + ): TranslationCommentModel { val comment = translationCommentService.getWithAuthorFetched(commentId) comment.checkFromProject() return translationCommentModelAssembler.toModel(comment) @@ -105,7 +107,12 @@ class TranslationCommentController( @RequestActivity(ActivityType.TRANSLATION_COMMENT_EDIT) @UseDefaultPermissions // Security: Permission check done inside; users should be able to edit their comments @AllowApiAccess - fun update(@PathVariable commentId: Long, @RequestBody @Valid dto: TranslationCommentDto): TranslationCommentModel { + fun update( + @PathVariable + commentId: Long, + @RequestBody @Valid + dto: TranslationCommentDto, + ): TranslationCommentModel { val comment = translationCommentService.getWithAuthorFetched(commentId) if (comment.author.id != authenticationFacade.authenticatedUser.id) { throw BadRequestException(io.tolgee.constants.Message.CAN_EDIT_ONLY_OWN_COMMENT) @@ -117,11 +124,11 @@ class TranslationCommentController( @PutMapping(value = ["{translationId}/comments/{commentId}/set-state/{state}"]) @Operation(summary = "Sets state of translation comment") @RequestActivity(ActivityType.TRANSLATION_COMMENT_SET_STATE) - @RequiresProjectPermissions([ Scope.TRANSLATIONS_COMMENTS_SET_STATE ]) + @RequiresProjectPermissions([Scope.TRANSLATIONS_COMMENTS_SET_STATE]) @AllowApiAccess fun setState( @PathVariable commentId: Long, - @PathVariable state: TranslationCommentState + @PathVariable state: TranslationCommentState, ): TranslationCommentModel { val comment = translationCommentService.getWithAuthorFetched(commentId) comment.checkFromProject() @@ -135,7 +142,9 @@ class TranslationCommentController( @RequestActivity(ActivityType.TRANSLATION_COMMENT_DELETE) @UseDefaultPermissions // Security: Permission check done inside; users should be able to delete their comments @AllowApiAccess - fun delete(@PathVariable commentId: Long) { + fun delete( + @PathVariable commentId: Long, + ) { val comment = translationCommentService.get(commentId) comment.checkFromProject() if (comment.author.id != authenticationFacade.authenticatedUser.id) { @@ -151,7 +160,7 @@ class TranslationCommentController( private fun checkEditPermission() { securityService.checkProjectPermission( projectHolder.project.id, - Scope.TRANSLATIONS_COMMENTS_EDIT + Scope.TRANSLATIONS_COMMENTS_EDIT, ) } @@ -159,10 +168,11 @@ class TranslationCommentController( @ResponseStatus(HttpStatus.CREATED) @Operation(summary = "Creates a translation comment. Empty translation is stored, when not exists.") @RequestActivity(ActivityType.TRANSLATION_COMMENT_ADD) - @RequiresProjectPermissions([ Scope.TRANSLATIONS_COMMENTS_ADD ]) + @RequiresProjectPermissions([Scope.TRANSLATIONS_COMMENTS_ADD]) @AllowApiAccess fun create( - @RequestBody @Valid dto: TranslationCommentWithLangKeyDto + @RequestBody @Valid + dto: TranslationCommentWithLangKeyDto, ): ResponseEntity { val translation = translationService.getOrCreate(dto.keyId, dto.languageId) if (translation.key.project.id != projectHolder.project.id) { @@ -184,9 +194,9 @@ class TranslationCommentController( return ResponseEntity( TranslationWithCommentModel( comment = translationCommentModelAssembler.toModel(comment), - translation = translationModelAssembler.toModel(translation) + translation = translationModelAssembler.toModel(translation), ), - HttpStatus.CREATED + HttpStatus.CREATED, ) } @@ -194,11 +204,12 @@ class TranslationCommentController( @ResponseStatus(HttpStatus.CREATED) @Operation(summary = "Creates a translation comment") @RequestActivity(ActivityType.TRANSLATION_COMMENT_ADD) - @RequiresProjectPermissions([ Scope.TRANSLATIONS_COMMENTS_ADD ]) + @RequiresProjectPermissions([Scope.TRANSLATIONS_COMMENTS_ADD]) @AllowApiAccess fun create( @PathVariable translationId: Long, - @RequestBody @Valid dto: TranslationCommentDto + @RequestBody @Valid + dto: TranslationCommentDto, ): ResponseEntity { val translation = translationService.find(translationId) ?: throw NotFoundException() translation.checkFromProject() diff --git a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/translation/TranslationsController.kt b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/translation/TranslationsController.kt index 50b99a9997..321b695304 100644 --- a/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/translation/TranslationsController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/translation/TranslationsController.kt @@ -17,7 +17,7 @@ import io.tolgee.activity.RequestActivity import io.tolgee.activity.data.ActivityType import io.tolgee.api.v2.controllers.IController import io.tolgee.component.ProjectTranslationLastModifiedManager -import io.tolgee.dtos.query_results.TranslationHistoryView +import io.tolgee.dtos.queryResults.TranslationHistoryView import io.tolgee.dtos.request.translation.GetTranslationsParams import io.tolgee.dtos.request.translation.SelectAllResponse import io.tolgee.dtos.request.translation.SetTranslationsWithKeyDto @@ -45,7 +45,7 @@ import io.tolgee.security.authorization.UseDefaultPermissions import io.tolgee.service.LanguageService import io.tolgee.service.key.KeyService import io.tolgee.service.key.ScreenshotService -import io.tolgee.service.query_builders.CursorUtil +import io.tolgee.service.queryBuilders.CursorUtil import io.tolgee.service.security.SecurityService import io.tolgee.service.translation.TranslationService import jakarta.validation.Valid @@ -81,13 +81,13 @@ import java.util.concurrent.TimeUnit @RequestMapping( value = [ "/v2/projects/{projectId:[0-9]+}/translations", - "/v2/projects/translations" - ] + "/v2/projects/translations", + ], ) @Tags( value = [ Tag(name = "Translations", description = "Operations related to translations in project"), - ] + ], ) class TranslationsController( private val projectHolder: ProjectHolder, @@ -103,7 +103,7 @@ class TranslationsController( private val screenshotService: ScreenshotService, private val activityHolder: ActivityHolder, private val activityService: ActivityService, - private val projectTranslationLastModifiedManager: ProjectTranslationLastModifiedManager + private val projectTranslationLastModifiedManager: ProjectTranslationLastModifiedManager, ) : IController { @GetMapping(value = ["/{languages}"]) @Operation( @@ -113,24 +113,28 @@ class TranslationsController( responseCode = "200", content = [ Content( - schema = Schema( - example = """{"en": {"what a key": "Translated value", "another key": "Another key translated"},""" + - """"cs": {"what a key": "Překlad", "another key": "Další překlad"}}""" - ) - ) - ] - ) - ] + schema = + Schema( + example = + """{"en": {"what a key": "Translated value", "another key": "Another key translated"},""" + + """"cs": {"what a key": "Překlad", "another key": "Další překlad"}}""", + ), + ), + ], + ), + ], ) @UseDefaultPermissions // Security: check performed in the handler @AllowApiAccess fun getAllTranslations( @Parameter( - description = "Comma-separated language tags to return translations in. " + - "Languages you are not permitted to see will be silently dropped and not returned.", - example = "en,de,fr" + description = + "Comma-separated language tags to return translations in. " + + "Languages you are not permitted to see will be silently dropped and not returned.", + example = "en,de,fr", ) - @PathVariable("languages") languages: Set, + @PathVariable("languages") + languages: Set, @Parameter(description = "Namespace to return") ns: String? = "", @Parameter( @@ -143,7 +147,7 @@ When null, resulting file will be a flat key-value object. ) @RequestParam(value = "structureDelimiter", defaultValue = ".", required = false) structureDelimiter: Char?, - request: WebRequest + request: WebRequest, ): ResponseEntity>? { val lastModified: Long = projectTranslationLastModifiedManager.getLastModified(projectHolder.project.id) @@ -151,21 +155,23 @@ When null, resulting file will be a flat key-value object. return null } - val permittedTags = securityService - .filterViewPermissionByTag(projectId = projectHolder.project.id, languageTags = languages) + val permittedTags = + securityService + .filterViewPermissionByTag(projectId = projectHolder.project.id, languageTags = languages) - val response = translationService.getTranslations( - languageTags = permittedTags, - namespace = ns, - projectId = projectHolder.project.id, - structureDelimiter = request.getStructureDelimiter() - ) + val response = + translationService.getTranslations( + languageTags = permittedTags, + namespace = ns, + projectId = projectHolder.project.id, + structureDelimiter = request.getStructureDelimiter(), + ) return ResponseEntity.ok() .lastModified(lastModified) .cacheControl(CacheControl.maxAge(0, TimeUnit.SECONDS)) .body( - response + response, ) } @@ -174,18 +180,22 @@ When null, resulting file will be a flat key-value object. @RequestActivity(ActivityType.SET_TRANSLATIONS) @RequiresProjectPermissions([Scope.TRANSLATIONS_EDIT]) @AllowApiAccess - fun setTranslations(@RequestBody @Valid dto: SetTranslationsWithKeyDto): SetTranslationsResponseModel { + fun setTranslations( + @RequestBody @Valid + dto: SetTranslationsWithKeyDto, + ): SetTranslationsResponseModel { val key = keyService.get(projectHolder.project.id, dto.key, dto.namespace) securityService.checkLanguageTranslatePermissionsByTag(dto.translations.keys, projectHolder.project.id) val modifiedTranslations = translationService.setForKey(key, dto.translations) - val translations = dto.languagesToReturn - ?.let { languagesToReturn -> - translationService.findForKeyByLanguages(key, languagesToReturn) - .associateBy { it.language.tag } - } - ?: modifiedTranslations + val translations = + dto.languagesToReturn + ?.let { languagesToReturn -> + translationService.findForKeyByLanguages(key, languagesToReturn) + .associateBy { it.language.tag } + } + ?: modifiedTranslations return getSetTranslationsResponse(key, translations) } @@ -195,14 +205,18 @@ When null, resulting file will be a flat key-value object. @RequestActivity(ActivityType.SET_TRANSLATIONS) @RequiresProjectPermissions([Scope.TRANSLATIONS_EDIT]) @AllowApiAccess - fun createOrUpdateTranslations(@RequestBody @Valid dto: SetTranslationsWithKeyDto): SetTranslationsResponseModel { - val key = keyService.find(projectHolder.projectEntity.id, dto.key, dto.namespace)?.also { - activityHolder.activity = ActivityType.SET_TRANSLATIONS - } ?: let { - checkKeyEditScope() - activityHolder.activity = ActivityType.CREATE_KEY - keyService.create(projectHolder.projectEntity, dto.key, dto.namespace) - } + fun createOrUpdateTranslations( + @RequestBody @Valid + dto: SetTranslationsWithKeyDto, + ): SetTranslationsResponseModel { + val key = + keyService.find(projectHolder.projectEntity.id, dto.key, dto.namespace)?.also { + activityHolder.activity = ActivityType.SET_TRANSLATIONS + } ?: let { + checkKeyEditScope() + activityHolder.activity = ActivityType.CREATE_KEY + keyService.create(projectHolder.projectEntity, dto.key, dto.namespace) + } val translations = translationService.setForKey(key, dto.translations) return getSetTranslationsResponse(key, translations) } @@ -214,7 +228,7 @@ When null, resulting file will be a flat key-value object. @AllowApiAccess fun setTranslationState( @PathVariable translationId: Long, - @PathVariable state: AssignableTranslationState + @PathVariable state: AssignableTranslationState, ): TranslationModel { val translation = translationService.get(translationId) translation.checkFromProject() @@ -227,7 +241,7 @@ When null, resulting file will be a flat key-value object. binder.registerCustomEditor( List::class.java, TranslationFilters::filterKeyName.name, - CustomCollectionEditor(List::class.java) + CustomCollectionEditor(List::class.java), ) } @@ -237,21 +251,25 @@ When null, resulting file will be a flat key-value object. @AllowApiAccess @Transactional fun getTranslations( - @ParameterObject @ModelAttribute("translationFilters") params: GetTranslationsParams, - @ParameterObject pageable: Pageable + @ParameterObject + @ModelAttribute("translationFilters") + params: GetTranslationsParams, + @ParameterObject pageable: Pageable, ): KeysWithTranslationsPageModel { val baseLanguage = projectHolder.projectEntity.baseLanguage - val languages: Set = languageService.getLanguagesForTranslationsView( - params.languages, - projectHolder.project.id, - authenticationFacade.authenticatedUser.id - ) + val languages: Set = + languageService.getLanguagesForTranslationsView( + params.languages, + projectHolder.project.id, + authenticationFacade.authenticatedUser.id, + ) val pageableWithSort = getSafeSortPageable(pageable) - val data = translationService - .getViewData(projectHolder.project.id, pageableWithSort, params, languages) + val data = + translationService + .getViewData(projectHolder.project.id, pageableWithSort, params, languages) val keysWithScreenshots = getScreenshots(data.map { it.keyId }.toList()) @@ -268,20 +286,23 @@ When null, resulting file will be a flat key-value object. @RequiresProjectPermissions([Scope.KEYS_VIEW]) @AllowApiAccess fun getSelectAllKeyIds( - @ParameterObject @ModelAttribute("translationFilters") params: TranslationFilters, + @ParameterObject + @ModelAttribute("translationFilters") + params: TranslationFilters, ): SelectAllResponse { - val languages: Set = languageService.getLanguagesForTranslationsView( - params.languages, - projectHolder.project.id, - authenticationFacade.authenticatedUser.id - ) + val languages: Set = + languageService.getLanguagesForTranslationsView( + params.languages, + projectHolder.project.id, + authenticationFacade.authenticatedUser.id, + ) return SelectAllResponse( translationService.getSelectAllKeys( projectId = projectHolder.project.id, params = params, - languages = languages - ) + languages = languages, + ), ) } @@ -291,7 +312,7 @@ When null, resulting file will be a flat key-value object. @RequiresProjectPermissions([Scope.TRANSLATIONS_STATE_EDIT]) @AllowApiAccess fun dismissAutoTranslatedState( - @PathVariable translationId: Long + @PathVariable translationId: Long, ): TranslationModel { val translation = translationService.get(translationId) translation.checkFromProject() @@ -307,7 +328,7 @@ When null, resulting file will be a flat key-value object. @AllowApiAccess fun setOutdated( @PathVariable translationId: Long, - @PathVariable state: Boolean + @PathVariable state: Boolean, ): TranslationModel { val translation = translationService.get(translationId) translation.checkFromProject() @@ -319,13 +340,15 @@ When null, resulting file will be a flat key-value object. @Operation( summary = """Returns history of specific translation. -Sorting is not supported for supported. It is automatically sorted from newest to oldest.""" +Sorting is not supported for supported. It is automatically sorted from newest to oldest.""", ) @RequiresProjectPermissions([Scope.TRANSLATIONS_VIEW]) @AllowApiAccess fun getTranslationHistory( @PathVariable translationId: Long, - @ParameterObject @SortDefault(sort = ["timestamp"], direction = Sort.Direction.DESC) pageable: Pageable + @ParameterObject + @SortDefault(sort = ["timestamp"], direction = Sort.Direction.DESC) + pageable: Pageable, ): PagedModel { val translation = translationService.get(translationId) translation.checkFromProject() @@ -344,22 +367,25 @@ Sorting is not supported for supported. It is automatically sorted from newest t return null } - private fun getSetTranslationsResponse(key: Key, translations: Map): - SetTranslationsResponseModel { + private fun getSetTranslationsResponse( + key: Key, + translations: Map, + ): SetTranslationsResponseModel { return SetTranslationsResponseModel( keyId = key.id, keyName = key.name, keyNamespace = key.namespace?.name, - translations = translations.entries.associate { (languageTag, translation) -> - languageTag to translationModelAssembler.toModel(translation) - } + translations = + translations.entries.associate { (languageTag, translation) -> + languageTag to translationModelAssembler.toModel(translation) + }, ) } private fun checkKeyEditScope() { securityService.checkProjectPermission( projectHolder.project.id, - Scope.KEYS_EDIT + Scope.KEYS_EDIT, ) } diff --git a/backend/api/src/main/kotlin/io/tolgee/component/KeyComplexEditHelper.kt b/backend/api/src/main/kotlin/io/tolgee/component/KeyComplexEditHelper.kt index 75d08eecbd..f2a89ea116 100644 --- a/backend/api/src/main/kotlin/io/tolgee/component/KeyComplexEditHelper.kt +++ b/backend/api/src/main/kotlin/io/tolgee/component/KeyComplexEditHelper.kt @@ -29,7 +29,7 @@ import kotlin.properties.Delegates class KeyComplexEditHelper( applicationContext: ApplicationContext, private val keyId: Long, - private val dto: ComplexEditKeyDto + private val dto: ComplexEditKeyDto, ) { private val keyWithDataModelAssembler: KeyWithDataModelAssembler = applicationContext.getBean(KeyWithDataModelAssembler::class.java) @@ -73,7 +73,7 @@ class KeyComplexEditHelper( translationService.getKeyTranslations( languages, projectHolder.projectEntity, - key + key, ).associateBy { it.language.tag }.toMutableMap() } @@ -128,13 +128,15 @@ class KeyComplexEditHelper( if (areStatesModified) { securityService.checkLanguageChangeStatePermissionsByLanguageId(modifiedStates!!.keys, projectHolder.project.id) translationService.setStateBatch( - states = modifiedStates!!.map { - val translation = existingTranslations[languageById(it.key).tag] ?: throw NotFoundException( - Message.TRANSLATION_NOT_FOUND - ) - - translation to it.value - }.toMap() + states = + modifiedStates!!.map { + val translation = + existingTranslations[languageById(it.key).tag] ?: throw NotFoundException( + Message.TRANSLATION_NOT_FOUND, + ) + + translation to it.value + }.toMap(), ) } } @@ -144,20 +146,22 @@ class KeyComplexEditHelper( projectHolder.projectEntity.checkTranslationsEditPermission() securityService.checkLanguageTranslatePermissionsByLanguageId( modifiedTranslations!!.keys, - projectHolder.project.id + projectHolder.project.id, ) val modifiedTranslations = getModifiedTranslationsByTag() val existingTranslationsByTag = getExistingTranslationsByTag() - val oldTranslations = modifiedTranslations.map { - it.key to existingTranslationsByTag[it.key] - }.toMap() - - val translations = translationService.setForKey( - key, - oldTranslations = oldTranslations, - translations = modifiedTranslations - ) + val oldTranslations = + modifiedTranslations.map { + it.key to existingTranslationsByTag[it.key] + }.toMap() + + val translations = + translationService.setForKey( + key, + oldTranslations = oldTranslations, + translations = modifiedTranslations, + ) translations.forEach { if (existingTranslations[it.key.tag] == null) { @@ -170,9 +174,10 @@ class KeyComplexEditHelper( private fun getExistingTranslationsByTag() = existingTranslations.map { languageByTag(it.key) to it.value.text }.toMap() - private fun getModifiedTranslationsByTag() = modifiedTranslations!! - .map { languageById(it.key) to it.value } - .toMap() + private fun getModifiedTranslationsByTag() = + modifiedTranslations!! + .map { languageById(it.key) to it.value } + .toMap() private fun setActivityHolder() { if (!isSingleOperation) { @@ -219,7 +224,7 @@ class KeyComplexEditHelper( areTagsModified, isKeyModified, isScreenshotAdded, - isScreenshotDeleted + isScreenshotDeleted, ).sumOf { if (it) 1 as Int else 0 } == 0 } @@ -242,7 +247,7 @@ class KeyComplexEditHelper( private fun areTagsModified( key: Key, - dtoTags: List + dtoTags: List, ): Boolean { val currentTags = key.keyMeta?.tags?.map { it.name } ?: listOf() val currentTagsContainAllNewTags = currentTags.containsAll(dtoTags) @@ -252,13 +257,15 @@ class KeyComplexEditHelper( } private fun prepareModifiedTranslations() { - modifiedTranslations = dto.translations?.filter { it.value != existingTranslations[it.key]?.text } - ?.mapKeys { languageByTag(it.key).id } + modifiedTranslations = + dto.translations?.filter { it.value != existingTranslations[it.key]?.text } + ?.mapKeys { languageByTag(it.key).id } } private fun prepareModifiedStates() { - modifiedStates = dto.states?.filter { it.value.translationState != existingTranslations[it.key]?.state } - ?.map { languageByTag(it.key).id to it.value.translationState }?.toMap() + modifiedStates = + dto.states?.filter { it.value.translationState != existingTranslations[it.key]?.state } + ?.map { languageByTag(it.key).id to it.value.translationState }?.toMap() } private fun languageByTag(tag: String): io.tolgee.model.Language { @@ -269,7 +276,10 @@ class KeyComplexEditHelper( return languages.find { it.id == id } ?: throw NotFoundException(Message.LANGUAGE_NOT_FOUND) } - private fun updateScreenshotsWithPermissionCheck(dto: ComplexEditKeyDto, key: Key) { + private fun updateScreenshotsWithPermissionCheck( + dto: ComplexEditKeyDto, + key: Key, + ) { dto.screenshotIdsToDelete?.let { screenshotIds -> deleteScreenshots(screenshotIds, key) } @@ -277,7 +287,10 @@ class KeyComplexEditHelper( addScreenshots(key, dto) } - private fun addScreenshots(key: Key, dto: ComplexEditKeyDto) { + private fun addScreenshots( + key: Key, + dto: ComplexEditKeyDto, + ) { if (isScreenshotAdded) { key.project.checkScreenshotsUploadPermission() } @@ -296,7 +309,7 @@ class KeyComplexEditHelper( private fun deleteScreenshots( screenshotIds: List, - key: Key + key: Key, ) { if (screenshotIds.isNotEmpty()) { key.project.checkScreenshotsDeletePermission() diff --git a/backend/api/src/main/kotlin/io/tolgee/component/LanguageValidator.kt b/backend/api/src/main/kotlin/io/tolgee/component/LanguageValidator.kt index 61cc2995dc..6acac73b75 100644 --- a/backend/api/src/main/kotlin/io/tolgee/component/LanguageValidator.kt +++ b/backend/api/src/main/kotlin/io/tolgee/component/LanguageValidator.kt @@ -13,9 +13,12 @@ import java.util.* @Component class LanguageValidator( - private val languageService: LanguageService + private val languageService: LanguageService, ) { - fun validateEdit(id: Long, dto: LanguageDto) { + fun validateEdit( + id: Long, + dto: LanguageDto, + ) { val validationErrors = LinkedHashSet() // handle edit validation @@ -32,7 +35,10 @@ class LanguageValidator( } } - fun validateCreate(dto: LanguageDto, project: Project?) { + fun validateCreate( + dto: LanguageDto, + project: Project?, + ) { val validationErrors = LinkedHashSet() // handle create validation @@ -43,15 +49,25 @@ class LanguageValidator( } } - private fun validateNameUniqueness(dto: LanguageDto, project: Project?): Optional { + private fun validateNameUniqueness( + dto: LanguageDto, + project: Project?, + ): Optional { return if (languageService.findByName(dto.name, project!!).isPresent) { Optional.of(ValidationError(ValidationErrorType.CUSTOM_VALIDATION, Message.LANGUAGE_NAME_EXISTS)) - } else Optional.empty() + } else { + Optional.empty() + } } - private fun validateTagUniqueness(dto: LanguageDto, project: Project?): Optional { + private fun validateTagUniqueness( + dto: LanguageDto, + project: Project?, + ): Optional { return if (languageService.findByTag(dto.tag, project!!).isPresent) { Optional.of(ValidationError(ValidationErrorType.CUSTOM_VALIDATION, Message.LANGUAGE_TAG_EXISTS)) - } else Optional.empty() + } else { + Optional.empty() + } } } diff --git a/backend/api/src/main/kotlin/io/tolgee/component/PreferredOrganizationFacade.kt b/backend/api/src/main/kotlin/io/tolgee/component/PreferredOrganizationFacade.kt index 395d091b7d..8756bd6305 100644 --- a/backend/api/src/main/kotlin/io/tolgee/component/PreferredOrganizationFacade.kt +++ b/backend/api/src/main/kotlin/io/tolgee/component/PreferredOrganizationFacade.kt @@ -17,9 +17,8 @@ class PreferredOrganizationFacade( private val userPreferencesService: UserPreferencesService, private val privateOrganizationModelAssembler: PrivateOrganizationModelAssembler, private val enabledFeaturesProvider: EnabledFeaturesProvider, - private val quickStartService: QuickStartService + private val quickStartService: QuickStartService, ) { - fun getPreferred(): PrivateOrganizationModel? { val preferences = userPreferencesService.findOrCreate(authenticationFacade.authenticatedUser.id) val preferredOrganization = preferences.preferredOrganization @@ -29,7 +28,7 @@ class PreferredOrganizationFacade( return this.privateOrganizationModelAssembler.toModel( view, enabledFeaturesProvider.get(view.organization.id), - quickStartService.find(authenticationFacade.authenticatedUser.id, view.organization.id) + quickStartService.find(authenticationFacade.authenticatedUser.id, view.organization.id), ) } return null diff --git a/backend/api/src/main/kotlin/io/tolgee/component/ProjectTranslationLastModifiedManager.kt b/backend/api/src/main/kotlin/io/tolgee/component/ProjectTranslationLastModifiedManager.kt index 02457a4bbd..b710d41be1 100644 --- a/backend/api/src/main/kotlin/io/tolgee/component/ProjectTranslationLastModifiedManager.kt +++ b/backend/api/src/main/kotlin/io/tolgee/component/ProjectTranslationLastModifiedManager.kt @@ -10,9 +10,8 @@ import org.springframework.stereotype.Component @Component class ProjectTranslationLastModifiedManager( val currentDateProvider: CurrentDateProvider, - val cacheManager: CacheManager + val cacheManager: CacheManager, ) { - fun getLastModified(projectId: Long): Long { return getCache()?.get(projectId)?.get() as? Long ?: let { diff --git a/backend/api/src/main/kotlin/io/tolgee/component/TolgeeCacheErrorHandler.kt b/backend/api/src/main/kotlin/io/tolgee/component/TolgeeCacheErrorHandler.kt index b3d6355222..be28461c4b 100644 --- a/backend/api/src/main/kotlin/io/tolgee/component/TolgeeCacheErrorHandler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/component/TolgeeCacheErrorHandler.kt @@ -24,7 +24,11 @@ import org.springframework.cache.interceptor.SimpleCacheErrorHandler class TolgeeCacheErrorHandler : SimpleCacheErrorHandler() { private val logger = LoggerFactory.getLogger(TolgeeCacheErrorHandler::class.java) - override fun handleCacheGetError(exception: RuntimeException, cache: Cache, key: Any) { + override fun handleCacheGetError( + exception: RuntimeException, + cache: Cache, + key: Any, + ) { if (exception is RedisException) { logger.warn( "Suppressing RedisException for cache {} on key {}. " + diff --git a/backend/api/src/main/kotlin/io/tolgee/component/TransferEncodingHeaderDebugFilter.kt b/backend/api/src/main/kotlin/io/tolgee/component/TransferEncodingHeaderDebugFilter.kt index a57290c61c..3c6b8715b8 100644 --- a/backend/api/src/main/kotlin/io/tolgee/component/TransferEncodingHeaderDebugFilter.kt +++ b/backend/api/src/main/kotlin/io/tolgee/component/TransferEncodingHeaderDebugFilter.kt @@ -15,7 +15,11 @@ class TransferEncodingHeaderDebugFilter : OncePerRequestFilter(), Logging { return !this.logger.isDebugEnabled } - override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) { + override fun doFilterInternal( + request: HttpServletRequest, + response: HttpServletResponse, + filterChain: FilterChain, + ) { filterChain.doFilter(request, response) val value = response.getHeader("Transport-Encoding") if (value != null) { diff --git a/backend/api/src/main/kotlin/io/tolgee/component/VersionFilter.kt b/backend/api/src/main/kotlin/io/tolgee/component/VersionFilter.kt index 165b214b79..8b7092f743 100644 --- a/backend/api/src/main/kotlin/io/tolgee/component/VersionFilter.kt +++ b/backend/api/src/main/kotlin/io/tolgee/component/VersionFilter.kt @@ -9,13 +9,17 @@ import org.springframework.web.filter.OncePerRequestFilter @Component class VersionFilter( - private val versionProvider: VersionProvider + private val versionProvider: VersionProvider, ) : OncePerRequestFilter() { companion object { const val TOLGEE_VERSION_HEADER_NAME = "X-Tolgee-Version" } - override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) { + override fun doFilterInternal( + request: HttpServletRequest, + response: HttpServletResponse, + filterChain: FilterChain, + ) { response.addHeader(TOLGEE_VERSION_HEADER_NAME, versionProvider.version) filterChain.doFilter(request, response) } diff --git a/backend/api/src/main/kotlin/io/tolgee/component/lockingProvider/RedissonLockingProvider.kt b/backend/api/src/main/kotlin/io/tolgee/component/lockingProvider/RedissonLockingProvider.kt index d0331d235e..c447a39bd8 100644 --- a/backend/api/src/main/kotlin/io/tolgee/component/lockingProvider/RedissonLockingProvider.kt +++ b/backend/api/src/main/kotlin/io/tolgee/component/lockingProvider/RedissonLockingProvider.kt @@ -9,7 +9,10 @@ class RedissonLockingProvider(private val redissonClient: RedissonClient) : Lock return redissonClient.getLock(name) } - override fun withLocking(name: String, fn: () -> T): T { + override fun withLocking( + name: String, + fn: () -> T, + ): T { val lock = this.getLock(name) lock.lock() try { diff --git a/backend/api/src/main/kotlin/io/tolgee/component/lockingProvider/SimpleLockingProvider.kt b/backend/api/src/main/kotlin/io/tolgee/component/lockingProvider/SimpleLockingProvider.kt index ce8f4067fe..765b5155ff 100644 --- a/backend/api/src/main/kotlin/io/tolgee/component/lockingProvider/SimpleLockingProvider.kt +++ b/backend/api/src/main/kotlin/io/tolgee/component/lockingProvider/SimpleLockingProvider.kt @@ -6,7 +6,6 @@ import java.util.concurrent.locks.Lock import java.util.concurrent.locks.ReentrantLock class SimpleLockingProvider : LockingProvider { - companion object { val map = WeakHashMap() } @@ -16,7 +15,10 @@ class SimpleLockingProvider : LockingProvider { return map.getOrPut(name) { ReentrantLock() } } - override fun withLocking(name: String, fn: () -> T): T { + override fun withLocking( + name: String, + fn: () -> T, + ): T { val lock = this.getLock(name) lock.lock() try { diff --git a/backend/api/src/main/kotlin/io/tolgee/configuration/CaffeineCacheConfiguration.kt b/backend/api/src/main/kotlin/io/tolgee/configuration/CaffeineCacheConfiguration.kt index b9b9997dda..d8d18130f1 100644 --- a/backend/api/src/main/kotlin/io/tolgee/configuration/CaffeineCacheConfiguration.kt +++ b/backend/api/src/main/kotlin/io/tolgee/configuration/CaffeineCacheConfiguration.kt @@ -23,9 +23,10 @@ import java.util.concurrent.TimeUnit class CaffeineCacheConfiguration(val tolgeeProperties: TolgeeProperties) { @Bean fun caffeineConfig(): Caffeine { - val builder = Caffeine.newBuilder() - .expireAfterWrite(tolgeeProperties.cache.defaultTtl, TimeUnit.MILLISECONDS) - .expireAfterAccess(tolgeeProperties.cache.defaultTtl, TimeUnit.MILLISECONDS) + val builder = + Caffeine.newBuilder() + .expireAfterWrite(tolgeeProperties.cache.defaultTtl, TimeUnit.MILLISECONDS) + .expireAfterAccess(tolgeeProperties.cache.defaultTtl, TimeUnit.MILLISECONDS) if (tolgeeProperties.cache.caffeineMaxSize > 0) { builder.maximumSize(tolgeeProperties.cache.caffeineMaxSize) } diff --git a/backend/api/src/main/kotlin/io/tolgee/configuration/ConditionalRedissonAutoConfiguration.kt b/backend/api/src/main/kotlin/io/tolgee/configuration/ConditionalRedissonAutoConfiguration.kt index 5201a22a87..6fc37b8582 100644 --- a/backend/api/src/main/kotlin/io/tolgee/configuration/ConditionalRedissonAutoConfiguration.kt +++ b/backend/api/src/main/kotlin/io/tolgee/configuration/ConditionalRedissonAutoConfiguration.kt @@ -18,6 +18,6 @@ import org.springframework.data.redis.core.RedisOperations @EnableConfigurationProperties(RedissonProperties::class, RedisProperties::class) @ConditionalOnExpression( "\${tolgee.websocket.use-redis:false} or " + - "(\${tolgee.cache.use-redis:false} and \${tolgee.cache.enabled:false})" + "(\${tolgee.cache.use-redis:false} and \${tolgee.cache.enabled:false})", ) class ConditionalRedissonAutoConfiguration : RedissonAutoConfiguration() diff --git a/backend/api/src/main/kotlin/io/tolgee/configuration/LockingConfiguration.kt b/backend/api/src/main/kotlin/io/tolgee/configuration/LockingConfiguration.kt index 69f6f47abe..9ea29670c6 100644 --- a/backend/api/src/main/kotlin/io/tolgee/configuration/LockingConfiguration.kt +++ b/backend/api/src/main/kotlin/io/tolgee/configuration/LockingConfiguration.kt @@ -12,7 +12,7 @@ import org.springframework.context.annotation.Configuration @Configuration class LockingConfiguration( val usingRedisProvider: UsingRedisProvider, - val applicationContext: ApplicationContext + val applicationContext: ApplicationContext, ) { @Bean fun redisLockingProvider(): LockingProvider { diff --git a/backend/api/src/main/kotlin/io/tolgee/configuration/PublicConfigurationDTO.kt b/backend/api/src/main/kotlin/io/tolgee/configuration/PublicConfigurationDTO.kt index fec97e547a..fb1d928042 100644 --- a/backend/api/src/main/kotlin/io/tolgee/configuration/PublicConfigurationDTO.kt +++ b/backend/api/src/main/kotlin/io/tolgee/configuration/PublicConfigurationDTO.kt @@ -38,7 +38,7 @@ class PublicConfigurationDTO( class AuthMethodsDTO( val github: OAuthPublicConfigDTO, val google: OAuthPublicConfigDTO, - val oauth2: OAuthPublicExtendsConfigDTO + val oauth2: OAuthPublicExtendsConfigDTO, ) data class OAuthPublicConfigDTO(val clientId: String?) { @@ -48,34 +48,35 @@ class PublicConfigurationDTO( data class OAuthPublicExtendsConfigDTO( val clientId: String?, val authorizationUrl: String?, - val scopes: List? + val scopes: List?, ) { val enabled: Boolean = !clientId.isNullOrEmpty() } data class MtServicesDTO( val defaultPrimaryService: MtServiceType?, - val services: Map + val services: Map, ) data class MtServiceDTO( val enabled: Boolean, - val defaultEnabledForProject: Boolean + val defaultEnabledForProject: Boolean, ) init { if (authentication) { - authMethods = AuthMethodsDTO( - OAuthPublicConfigDTO( - properties.authentication.github.clientId - ), - OAuthPublicConfigDTO(properties.authentication.google.clientId), - OAuthPublicExtendsConfigDTO( - properties.authentication.oauth2.clientId, - properties.authentication.oauth2.authorizationUrl, - properties.authentication.oauth2.scopes + authMethods = + AuthMethodsDTO( + OAuthPublicConfigDTO( + properties.authentication.github.clientId, + ), + OAuthPublicConfigDTO(properties.authentication.google.clientId), + OAuthPublicExtendsConfigDTO( + properties.authentication.oauth2.clientId, + properties.authentication.oauth2.authorizationUrl, + properties.authentication.oauth2.scopes, + ), ) - ) } passwordResettable = properties.authentication.nativeEnabled allowRegistrations = properties.authentication.registrationsAllowed diff --git a/backend/api/src/main/kotlin/io/tolgee/controllers/ExportController.kt b/backend/api/src/main/kotlin/io/tolgee/controllers/ExportController.kt index 3dc05afb5b..94911fd267 100644 --- a/backend/api/src/main/kotlin/io/tolgee/controllers/ExportController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/controllers/ExportController.kt @@ -28,8 +28,10 @@ import java.util.zip.ZipOutputStream @RestController @CrossOrigin(origins = ["*"]) @RequestMapping( - "/api/project/{projectId}/export", "/api/project/export", - "/api/repository/{projectId}/export", "/api/repository/export" + "/api/project/{projectId}/export", + "/api/project/export", + "/api/repository/{projectId}/export", + "/api/repository/export", ) @Tag(name = "Export") class ExportController( @@ -44,27 +46,31 @@ class ExportController( @RequiresProjectPermissions([ Scope.TRANSLATIONS_VIEW ]) @AllowApiAccess @Deprecated("Use v2 export controller") - fun doExportJsonZip(@PathVariable("projectId") projectId: Long?): ResponseEntity { - val allLanguages = permissionService.getPermittedViewLanguages( - projectHolder.project.id, - authenticationFacade.authenticatedUser.id - ) + fun doExportJsonZip( + @PathVariable("projectId") projectId: Long?, + ): ResponseEntity { + val allLanguages = + permissionService.getPermittedViewLanguages( + projectHolder.project.id, + authenticationFacade.authenticatedUser.id, + ) return ResponseEntity .ok() .header( "Content-Disposition", - String.format("attachment; filename=\"%s.zip\"", projectHolder.project.name) + String.format("attachment; filename=\"%s.zip\"", projectHolder.project.name), ) .body( streamingResponseBodyProvider.createStreamingResponseBody { out: OutputStream -> val zipOutputStream = ZipOutputStream(out) - val translations = translationService.getTranslations( - allLanguages.map { it.tag }.toSet(), - null, - projectHolder.project.id, - '.' - ) + val translations = + translationService.getTranslations( + allLanguages.map { it.tag }.toSet(), + null, + projectHolder.project.id, + '.', + ) for ((key, value) in translations) { zipOutputStream.putNextEntry(ZipEntry(String.format("%s.json", key))) val data = jacksonObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsBytes(value) @@ -74,7 +80,7 @@ class ExportController( zipOutputStream.closeEntry() } zipOutputStream.close() - } + }, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/controllers/ImageStorageController.kt b/backend/api/src/main/kotlin/io/tolgee/controllers/ImageStorageController.kt index 29cc430daf..13ec1c5df5 100644 --- a/backend/api/src/main/kotlin/io/tolgee/controllers/ImageStorageController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/controllers/ImageStorageController.kt @@ -35,14 +35,14 @@ class ImageStorageController( fun getScreenshot( request: HttpServletRequest, @RequestParam("token") token: String?, - response: HttpServletResponse + response: HttpServletResponse, ): ByteArray { return getFile( urlPathPrefix = FileStoragePath.SCREENSHOTS, storageFolderName = SCREENSHOTS_STORAGE_FOLDER_NAME, token, request, - response + response, ) } @@ -50,28 +50,28 @@ class ImageStorageController( fun getUploadedImage( request: HttpServletRequest, @RequestParam("token") token: String?, - response: HttpServletResponse + response: HttpServletResponse, ): ByteArray { return getFile( urlPathPrefix = FileStoragePath.UPLOADED_IMAGES, storageFolderName = UPLOADED_IMAGES_STORAGE_FOLDER_NAME, token, request, - response + response, ) } @GetMapping(value = ["/${FileStoragePath.AVATARS}/*"]) fun getAvatar( request: HttpServletRequest, - response: HttpServletResponse + response: HttpServletResponse, ): ByteArray { val fileName = getFileName(request, urlPathPrefix = "avatars") return getFile( fileName = fileName, storageFolderName = FileStoragePath.AVATARS, - response + response, ) } @@ -80,7 +80,7 @@ class ImageStorageController( storageFolderName: String, token: String?, request: HttpServletRequest, - response: HttpServletResponse + response: HttpServletResponse, ): ByteArray { val fileName = getFileName(request, urlPathPrefix) @@ -115,7 +115,7 @@ class ImageStorageController( return getFile( fileName = fileName, response = response, - storageFolderName = storageFolderName + storageFolderName = storageFolderName, ) } @@ -128,7 +128,10 @@ class ImageStorageController( return fileStorage.readFile("$storageFolderName/$fileName") } - private fun getFileName(request: HttpServletRequest, urlPathPrefix: String): String { + private fun getFileName( + request: HttpServletRequest, + urlPathPrefix: String, + ): String { return request.requestURI.split(request.contextPath + "/$urlPathPrefix/")[1] } } diff --git a/backend/api/src/main/kotlin/io/tolgee/controllers/PublicController.kt b/backend/api/src/main/kotlin/io/tolgee/controllers/PublicController.kt index ff2b19e7f7..555cd03ef1 100644 --- a/backend/api/src/main/kotlin/io/tolgee/controllers/PublicController.kt +++ b/backend/api/src/main/kotlin/io/tolgee/controllers/PublicController.kt @@ -17,9 +17,9 @@ import io.tolgee.model.UserAccount import io.tolgee.security.authentication.JwtService import io.tolgee.security.payload.JwtAuthenticationResponse import io.tolgee.security.ratelimit.RateLimited -import io.tolgee.security.third_party.GithubOAuthDelegate -import io.tolgee.security.third_party.GoogleOAuthDelegate -import io.tolgee.security.third_party.OAuth2Delegate +import io.tolgee.security.thirdParty.GithubOAuthDelegate +import io.tolgee.security.thirdParty.GoogleOAuthDelegate +import io.tolgee.security.thirdParty.OAuth2Delegate import io.tolgee.service.EmailVerificationService import io.tolgee.service.security.MfaService import io.tolgee.service.security.ReCaptchaValidationService @@ -61,7 +61,10 @@ class PublicController( @Operation(summary = "Generates JWT token") @PostMapping("/generatetoken") @RateLimited(5, isAuthentication = true) - fun authenticateUser(@RequestBody @Valid loginRequest: LoginRequest): JwtAuthenticationResponse { + fun authenticateUser( + @RequestBody @Valid + loginRequest: LoginRequest, + ): JwtAuthenticationResponse { val userAccount = userCredentialsService.checkUserCredentials(loginRequest.username, loginRequest.password) emailVerificationService.check(userAccount) mfaService.checkMfa(userAccount, loginRequest.otp) @@ -73,7 +76,10 @@ class PublicController( @Operation(summary = "Reset password request") @PostMapping("/reset_password_request") - fun resetPasswordRequest(@RequestBody @Valid request: ResetPasswordRequest) { + fun resetPasswordRequest( + @RequestBody @Valid + request: ResetPasswordRequest, + ) { val userAccount = userAccountService.findActive(request.email!!) ?: return val code = RandomStringUtils.randomAlphabetic(50) userAccountService.setResetPasswordCode(userAccount, code) @@ -82,19 +88,21 @@ class PublicController( val url = request.callbackUrl + "/" + Base64.getEncoder().encodeToString(callbackString.toByteArray()) val isInitial = userAccount.accountType == UserAccount.AccountType.THIRD_PARTY - val params = EmailParams( - to = request.email!!, - subject = if (isInitial) "Initial password configuration" else "Password reset", - text = """ - Hello! 👋

- ${if (isInitial) "To set a password for your account, follow this link:
" else "To reset your password, follow this link:
"} - $url

- If you have not requested this e-mail, please ignore it.

- - Regards,
- Tolgee

- """.trimIndent() - ) + val params = + EmailParams( + to = request.email!!, + subject = if (isInitial) "Initial password configuration" else "Password reset", + text = + """ + Hello! 👋

+ ${if (isInitial) "To set a password for your account, follow this link:
" else "To reset your password, follow this link:
"} + $url

+ If you have not requested this e-mail, please ignore it.

+ + Regards,
+ Tolgee

+ """.trimIndent(), + ) tolgeeEmailSender.sendEmail(params) } @@ -103,17 +111,21 @@ class PublicController( @Operation(summary = "Validates key sent by email") fun resetPasswordValidate( @PathVariable("code") code: String, - @PathVariable("email") email: String + @PathVariable("email") email: String, ) { validateEmailCode(code, email) } @PostMapping("/reset_password_set") @Operation(summary = "Sets new password with password reset code from e-mail") - fun resetPasswordSet(@RequestBody @Valid request: ResetPassword) { + fun resetPasswordSet( + @RequestBody @Valid + request: ResetPassword, + ) { val userAccount = validateEmailCode(request.code!!, request.email!!) - if (userAccount.accountType === UserAccount.AccountType.THIRD_PARTY) + if (userAccount.accountType === UserAccount.AccountType.THIRD_PARTY) { userAccountService.setAccountType(userAccount, UserAccount.AccountType.LOCAL) + } userAccountService.setUserPassword(userAccount, request.password) userAccountService.removeResetCode(userAccount) } @@ -125,9 +137,12 @@ class PublicController( Creates new user account. When E-mail verification is enabled, null is returned. Otherwise JWT token is provided. - """ + """, ) - fun signUp(@RequestBody @Valid dto: SignUpDto): JwtAuthenticationResponse? { + fun signUp( + @RequestBody @Valid + dto: SignUpDto, + ): JwtAuthenticationResponse? { if (!reCaptchaValidationService.validate(dto.recaptchaToken, "")) { throw BadRequestException(Message.INVALID_RECAPTCHA_TOKEN) } @@ -138,7 +153,7 @@ When E-mail verification is enabled, null is returned. Otherwise JWT token is pr @Operation(summary = "Sets user account as verified, when code from email is OK") fun verifyEmail( @PathVariable("userId") @NotNull userId: Long, - @PathVariable("code") @NotBlank code: String + @PathVariable("code") @NotBlank code: String, ): JwtAuthenticationResponse { emailVerificationService.verify(userId, code) return JwtAuthenticationResponse(jwtService.emitToken(userId)) @@ -146,7 +161,9 @@ When E-mail verification is enabled, null is returned. Otherwise JWT token is pr @PostMapping(value = ["/validate_email"], consumes = [MediaType.APPLICATION_JSON_VALUE]) @Operation(summary = "Validates if email is not in use") - fun validateEmail(@RequestBody email: TextNode): Boolean { + fun validateEmail( + @RequestBody email: TextNode, + ): Boolean { return userAccountService.findActive(email.asText()) == null } @@ -157,7 +174,7 @@ When E-mail verification is enabled, null is returned. Otherwise JWT token is pr @PathVariable("serviceType") serviceType: String?, @RequestParam(value = "code", required = true) code: String?, @RequestParam(value = "redirect_uri", required = true) redirectUri: String?, - @RequestParam(value = "invitationCode", required = false) invitationCode: String? + @RequestParam(value = "invitationCode", required = false) invitationCode: String?, ): JwtAuthenticationResponse { if (properties.internal.fakeGithubLogin && code == "this_is_dummy_code") { val user = getFakeGithubUser() @@ -184,18 +201,22 @@ When E-mail verification is enabled, null is returned. Otherwise JWT token is pr private fun getFakeGithubUser(): UserAccount { val username = "johndoe@doe.com" - val user = userAccountService.findActive(username) ?: let { - UserAccount().apply { - this.username = username - name = "john" - accountType = UserAccount.AccountType.THIRD_PARTY - userAccountService.save(this) + val user = + userAccountService.findActive(username) ?: let { + UserAccount().apply { + this.username = username + name = "john" + accountType = UserAccount.AccountType.THIRD_PARTY + userAccountService.save(this) + } } - } return user } - private fun validateEmailCode(code: String, email: String): UserAccount { + private fun validateEmailCode( + code: String, + email: String, + ): UserAccount { val userAccount = userAccountService.findActive(email) ?: throw BadRequestException(Message.BAD_CREDENTIALS) val resetCodeValid = userAccountService.isResetCodeValid(userAccount, code) if (!resetCodeValid) { diff --git a/backend/api/src/main/kotlin/io/tolgee/facade/ProjectWithStatsFacade.kt b/backend/api/src/main/kotlin/io/tolgee/facade/ProjectWithStatsFacade.kt index 1b7c0cd50c..08882f88a0 100644 --- a/backend/api/src/main/kotlin/io/tolgee/facade/ProjectWithStatsFacade.kt +++ b/backend/api/src/main/kotlin/io/tolgee/facade/ProjectWithStatsFacade.kt @@ -1,7 +1,7 @@ package io.tolgee.facade import io.sentry.Sentry -import io.tolgee.dtos.query_results.ProjectStatistics +import io.tolgee.dtos.queryResults.ProjectStatistics import io.tolgee.hateoas.project.ProjectWithStatsModel import io.tolgee.hateoas.project.ProjectWithStatsModelAssembler import io.tolgee.model.enums.TranslationState @@ -25,56 +25,60 @@ class ProjectWithStatsFacade( private val pagedWithStatsResourcesAssembler: PagedResourcesAssembler, private val projectWithStatsModelAssembler: ProjectWithStatsModelAssembler, private val languageStatsService: LanguageStatsService, - private val languageService: LanguageService + private val languageService: LanguageService, ) { - fun getPagedModelWithStats( - projects: Page, - ): PagedModel { + fun getPagedModelWithStats(projects: Page): PagedModel { val projectIds = projects.content.map { it.id } val totals = projectStatsService.getProjectsTotals(projectIds) - val languages = languageService.getViewsOfProjects(projectIds) - .groupBy { it.language.project.id } + val languages = + languageService.getViewsOfProjects(projectIds) + .groupBy { it.language.project.id } val languageStats = languageStatsService.getLanguageStats(projectIds) - val projectsWithStatsContent = projects.content.map { projectWithLanguagesView -> - val projectTotals = totals[projectWithLanguagesView.id] - val baseLanguage = projectWithLanguagesView.baseLanguage - val projectLanguageStats = languageStats[projectWithLanguagesView.id] + val projectsWithStatsContent = + projects.content.map { projectWithLanguagesView -> + val projectTotals = totals[projectWithLanguagesView.id] + val baseLanguage = projectWithLanguagesView.baseLanguage + val projectLanguageStats = languageStats[projectWithLanguagesView.id] - var stateTotals: ProjectStatsService.ProjectStateTotals? = null - if (baseLanguage != null && projectLanguageStats != null) { - stateTotals = projectStatsService.computeProjectTotals( - baseLanguage, - projectLanguageStats - .sortedBy { it.language.name } - .sortedBy { it.language.id != baseLanguage.id } - ) - } + var stateTotals: ProjectStatsService.ProjectStateTotals? = null + if (baseLanguage != null && projectLanguageStats != null) { + stateTotals = + projectStatsService.computeProjectTotals( + baseLanguage, + projectLanguageStats + .sortedBy { it.language.name } + .sortedBy { it.language.id != baseLanguage.id }, + ) + } - val translatedPercent = stateTotals?.translatedPercent.toPercentValue() - val reviewedPercent = stateTotals?.reviewedPercent.toPercentValue() - val untranslatedPercent = (BigDecimal(100) - translatedPercent - reviewedPercent).setScale( - 2, - RoundingMode.HALF_UP - ) + val translatedPercent = stateTotals?.translatedPercent.toPercentValue() + val reviewedPercent = stateTotals?.reviewedPercent.toPercentValue() + val untranslatedPercent = + (BigDecimal(100) - translatedPercent - reviewedPercent).setScale( + 2, + RoundingMode.HALF_UP, + ) - val projectStatistics = ProjectStatistics( - projectId = projectWithLanguagesView.id, - keyCount = projectTotals?.keyCount ?: 0, - languageCount = projectTotals?.languageCount ?: 0, - translationStatePercentages = mapOf( - TranslationState.TRANSLATED to translatedPercent, - TranslationState.REVIEWED to reviewedPercent, - TranslationState.UNTRANSLATED to untranslatedPercent + val projectStatistics = + ProjectStatistics( + projectId = projectWithLanguagesView.id, + keyCount = projectTotals?.keyCount ?: 0, + languageCount = projectTotals?.languageCount ?: 0, + translationStatePercentages = + mapOf( + TranslationState.TRANSLATED to translatedPercent, + TranslationState.REVIEWED to reviewedPercent, + TranslationState.UNTRANSLATED to untranslatedPercent, + ), + ) + ProjectWithStatsView( + view = projectWithLanguagesView, + stats = projectStatistics, + languages = languages[projectWithLanguagesView.id] ?: listOf(), ) - ) - ProjectWithStatsView( - view = projectWithLanguagesView, - stats = projectStatistics, - languages = languages[projectWithLanguagesView.id] ?: listOf() - ) - } + } val page = PageImpl(projectsWithStatsContent, projects.pageable, projects.totalElements) return pagedWithStatsResourcesAssembler.toModel(page, projectWithStatsModelAssembler) } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/InitialDataModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/InitialDataModel.kt index ca29a0a39e..b09b905059 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/InitialDataModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/InitialDataModel.kt @@ -4,7 +4,7 @@ import io.tolgee.configuration.PublicConfigurationDTO import io.tolgee.dtos.response.AnnouncementDto import io.tolgee.ee.api.v2.hateoas.eeSubscription.EeSubscriptionModel import io.tolgee.hateoas.organization.PrivateOrganizationModel -import io.tolgee.hateoas.user_account.PrivateUserAccountModel +import io.tolgee.hateoas.userAccount.PrivateUserAccountModel class InitialDataModel( val serverConfiguration: PublicConfigurationDTO, diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ModifiedEntityModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ModifiedEntityModel.kt index 9d1a3d3130..2eadbbee88 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ModifiedEntityModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ModifiedEntityModel.kt @@ -9,5 +9,5 @@ data class ModifiedEntityModel( override val description: Map? = null, override var modifications: Map? = null, override var relations: Map? = null, - override val exists: Boolean? = null + override val exists: Boolean? = null, ) : IModifiedEntityModel diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ProjectActivityAuthorModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ProjectActivityAuthorModel.kt index 4a5135586e..93332009bc 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ProjectActivityAuthorModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ProjectActivityAuthorModel.kt @@ -9,5 +9,5 @@ data class ProjectActivityAuthorModel( override val username: String?, override var name: String?, override var avatar: Avatar?, - override var deleted: Boolean + override var deleted: Boolean, ) : RepresentationModel(), IProjectActivityAuthorModel diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ProjectActivityModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ProjectActivityModelAssembler.kt index 87ad89f586..e7c7954120 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ProjectActivityModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/activity/ProjectActivityModelAssembler.kt @@ -9,43 +9,47 @@ import org.springframework.stereotype.Component @Component class ProjectActivityModelAssembler( - private val avatarService: AvatarService + private val avatarService: AvatarService, ) : RepresentationModelAssemblerSupport( - ApiKeyController::class.java, ProjectActivityModel::class.java -), + ApiKeyController::class.java, + ProjectActivityModel::class.java, + ), IProjectActivityModelAssembler { override fun toModel(view: ProjectActivityView): ProjectActivityModel { return ProjectActivityModel( revisionId = view.revisionId, timestamp = view.timestamp, type = view.type, - author = view.authorId?.let { - ProjectActivityAuthorModel( - id = view.authorId!!, - name = view.authorName, - username = view.authorUsername!!, - avatar = avatarService.getAvatarLinks(view.authorAvatarHash), - deleted = view.authorDeleted - ) - }, + author = + view.authorId?.let { + ProjectActivityAuthorModel( + id = view.authorId!!, + name = view.authorName, + username = view.authorUsername!!, + avatar = avatarService.getAvatarLinks(view.authorAvatarHash), + deleted = view.authorDeleted, + ) + }, modifiedEntities = getModifiedEntities(view), meta = view.meta, counts = view.counts, - params = view.params + params = view.params, ) } - private fun getModifiedEntities(view: ProjectActivityView) = view.modifications - ?.groupBy { it.entityClass } - ?.map { entry -> - entry.key to entry.value.map { - ModifiedEntityModel( - entityId = it.entityId, - description = it.description, - modifications = it.modifications, - relations = it.describingRelations, - exists = it.exists - ) - } - }?.toMap() + private fun getModifiedEntities(view: ProjectActivityView) = + view.modifications + ?.groupBy { it.entityClass } + ?.map { entry -> + entry.key to + entry.value.map { + ModifiedEntityModel( + entityId = it.entityId, + description = it.description, + modifications = it.modifications, + relations = it.describingRelations, + exists = it.exists, + ) + } + }?.toMap() } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyModel.kt index 3205f3e065..6bfeba424b 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyModel.kt @@ -20,17 +20,14 @@ open class ApiKeyModel( override var projectId: Long = 0, @Schema(description = "Api key's project name") override var projectName: String = "", - @Schema(description = "Timestamp of API key expiraion") override val expiresAt: Long? = null, - @Schema(description = "Timestamp of API key last usage") override val lastUsedAt: Long? = null, - @Schema( description = "Api key's permission scopes", example = - """ + """ [ "screenshots.upload", "screenshots.delete", @@ -39,7 +36,7 @@ open class ApiKeyModel( "translations.view", "keys.edit" ] - """ + """, ) - override var scopes: Set = setOf() + override var scopes: Set = setOf(), ) : RepresentationModel(), Serializable, IApiKeyModel diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyModelAssembler.kt index 8a433451f5..02dc2789a3 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyModelAssembler.kt @@ -7,17 +7,19 @@ import org.springframework.stereotype.Component @Component class ApiKeyModelAssembler : RepresentationModelAssemblerSupport( - ApiKeyController::class.java, ApiKeyModel::class.java + ApiKeyController::class.java, + ApiKeyModel::class.java, ) { - override fun toModel(entity: ApiKey) = ApiKeyModel( - id = entity.id, - description = entity.description, - username = entity.userAccount.username, - userFullName = entity.userAccount.name, - projectId = entity.project.id, - projectName = entity.project.name, - scopes = entity.scopesEnum.mapNotNull { it?.value }.toSet(), - expiresAt = entity.expiresAt?.time, - lastUsedAt = entity.lastUsedAt?.time - ) + override fun toModel(entity: ApiKey) = + ApiKeyModel( + id = entity.id, + description = entity.description, + username = entity.userAccount.username, + userFullName = entity.userAccount.name, + projectId = entity.project.id, + projectName = entity.project.name, + scopes = entity.scopesEnum.mapNotNull { it?.value }.toSet(), + expiresAt = entity.expiresAt?.time, + lastUsedAt = entity.lastUsedAt?.time, + ) } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyPermissionsModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyPermissionsModel.kt index 7828fccbd2..4863bb2056 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyPermissionsModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyPermissionsModel.kt @@ -12,18 +12,14 @@ import org.springframework.hateoas.server.core.Relation class ApiKeyPermissionsModel( @Schema(description = """The API key's project id or the one provided as query param""") val projectId: Long, - override var viewLanguageIds: Set?, - override val translateLanguageIds: Set?, - override var stateChangeLanguageIds: Set?, - override var scopes: Array = arrayOf(), - @get:Schema( - description = "The user's permission type. This field is null if user has assigned " + - "granular permissions or if returning API key's permissions", + description = + "The user's permission type. This field is null if user has assigned " + + "granular permissions or if returning API key's permissions", ) - override val type: ProjectPermissionType? + override val type: ProjectPermissionType?, ) : RepresentationModel(), IPermissionModel diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyWithLanguagesModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyWithLanguagesModel.kt index 8a922dba75..0dfd82bc1a 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyWithLanguagesModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/ApiKeyWithLanguagesModel.kt @@ -11,7 +11,7 @@ open class ApiKeyWithLanguagesModel( apiKeyModel: ApiKeyModel, @Schema( description = """Languages for which user has translate permission.""", - deprecated = true + deprecated = true, ) val permittedLanguageIds: Set?, ) : RepresentationModel(), IApiKeyModel by apiKeyModel diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/RevealedApiKeyModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/RevealedApiKeyModelAssembler.kt index a710aee6a2..9c596c4455 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/RevealedApiKeyModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/apiKey/RevealedApiKeyModelAssembler.kt @@ -8,12 +8,16 @@ import org.springframework.stereotype.Component @Component class RevealedApiKeyModelAssembler( - private val apiKeyModelAssembler: ApiKeyModelAssembler + private val apiKeyModelAssembler: ApiKeyModelAssembler, ) : RepresentationModelAssemblerSupport( - ApiKeyController::class.java, RevealedApiKeyModel::class.java -) { - override fun toModel(entity: ApiKey) = RevealedApiKeyModel( - apiKeyModel = apiKeyModelAssembler.toModel(entity), - key = entity.encodedKey?.let { PROJECT_API_KEY_PREFIX + it } ?: throw IllegalStateException("Api key not present"), - ) + ApiKeyController::class.java, + RevealedApiKeyModel::class.java, + ) { + override fun toModel(entity: ApiKey) = + RevealedApiKeyModel( + apiKeyModel = apiKeyModelAssembler.toModel(entity), + key = + entity.encodedKey?.let { PROJECT_API_KEY_PREFIX + it } + ?: throw IllegalStateException("Api key not present"), + ) } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/autoTranslationConfig/AutoTranslationConfigModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/autoTranslationConfig/AutoTranslationConfigModel.kt index 2bdc289550..519d4fd97f 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/autoTranslationConfig/AutoTranslationConfigModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/autoTranslationConfig/AutoTranslationConfigModel.kt @@ -7,24 +7,25 @@ import org.springframework.hateoas.server.core.Relation @Relation(collectionRelation = "configs", itemRelation = "config") data class AutoTranslationConfigModel( val languageId: Long? = null, - @Schema( - description = "If true, new keys will be automatically translated via batch operation using translation memory" + - " when 100% match is found" + description = + "If true, new keys will be automatically translated via batch operation using translation memory" + + " when 100% match is found", ) var usingTranslationMemory: Boolean = false, @Schema( - description = "If true, new keys will be automatically translated via batch operation" + - "using primary machine translation service." + - "" + - "When \"usingTranslationMemory\" is enabled, it tries to translate it with translation memory first." + description = + "If true, new keys will be automatically translated via batch operation" + + "using primary machine translation service." + + "" + + "When \"usingTranslationMemory\" is enabled, it tries to translate it with translation memory first.", ) var usingMachineTranslation: Boolean = false, - @Schema( - description = "If true, import will trigger batch operation to translate the new new keys." + - "\n" + - "It includes also the data imported via CLI, Figma, or other integrations using batch key import." + description = + "If true, import will trigger batch operation to translate the new new keys." + + "\n" + + "It includes also the data imported via CLI, Figma, or other integrations using batch key import.", ) - var enableForImport: Boolean = false + var enableForImport: Boolean = false, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/autoTranslationConfig/AutoTranslationSettingsModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/autoTranslationConfig/AutoTranslationSettingsModelAssembler.kt index 2aeef9d9f8..1076ba5d2b 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/autoTranslationConfig/AutoTranslationSettingsModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/autoTranslationConfig/AutoTranslationSettingsModelAssembler.kt @@ -8,7 +8,8 @@ import org.springframework.stereotype.Component @Component class AutoTranslationSettingsModelAssembler : RepresentationModelAssemblerSupport( - AutoTranslationController::class.java, AutoTranslationConfigModel::class.java + AutoTranslationController::class.java, + AutoTranslationConfigModel::class.java, ) { override fun toModel(entity: AutoTranslationConfig): AutoTranslationConfigModel { return AutoTranslationConfigModel( diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/automation/AutomationActionModelFiller.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/automation/AutomationActionModelFiller.kt index 8b95dfcbad..999b03a567 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/automation/AutomationActionModelFiller.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/automation/AutomationActionModelFiller.kt @@ -4,7 +4,10 @@ import io.tolgee.model.automations.AutomationAction import io.tolgee.model.automations.AutomationActionType interface AutomationActionModelFiller { - fun fill(model: AutomationActionModel, entity: AutomationAction) + fun fill( + model: AutomationActionModel, + entity: AutomationAction, + ) val type: AutomationActionType } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/automation/AutomationTriggerModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/automation/AutomationTriggerModel.kt index c6c10f04d6..c36075d5f7 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/automation/AutomationTriggerModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/automation/AutomationTriggerModel.kt @@ -7,5 +7,5 @@ class AutomationTriggerModel( var id: Long, var type: AutomationTriggerType = AutomationTriggerType.TRANSLATION_DATA_MODIFICATION, var activityType: ActivityType? = null, - var debounceDurationInMs: Long? = null + var debounceDurationInMs: Long? = null, ) diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/batch/BatchJobModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/batch/BatchJobModel.kt index ac79921126..4bf97ba0e8 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/batch/BatchJobModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/batch/BatchJobModel.kt @@ -2,7 +2,7 @@ package io.tolgee.hateoas.batch import io.swagger.v3.oas.annotations.media.Schema import io.tolgee.batch.data.BatchJobType -import io.tolgee.hateoas.user_account.SimpleUserAccountModel +import io.tolgee.hateoas.userAccount.SimpleUserAccountModel import io.tolgee.model.batch.BatchJobStatus import org.springframework.hateoas.RepresentationModel import org.springframework.hateoas.server.core.Relation @@ -13,31 +13,22 @@ import java.io.Serializable open class BatchJobModel( @Schema(description = "Batch job id") val id: Long, - @Schema(description = "Status of the batch job") val status: BatchJobStatus, - @Schema(description = "Type of the batch job") val type: BatchJobType, - @Schema(description = "Total items, that have been processed so far") val progress: Int, - @Schema(description = "Total items") val totalItems: Int, - @Schema(description = "The user who started the job") val author: SimpleUserAccountModel?, - @Schema(description = "The time when the job created") val createdAt: Long, - @Schema(description = "The time when the job was last updated (status change)") val updatedAt: Long, - @Schema(description = "The activity revision id, that stores the activity details of the job") val activityRevisionId: Long?, - @Schema(description = "If the job failed, this is the error message") val errorMessage: String?, ) : RepresentationModel(), Serializable diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/batch/BatchJobModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/batch/BatchJobModelAssembler.kt index e483e46251..e2eca9064f 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/batch/BatchJobModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/batch/BatchJobModelAssembler.kt @@ -1,17 +1,18 @@ package io.tolgee.hateoas.batch import io.tolgee.api.v2.controllers.batch.BatchJobManagementController -import io.tolgee.hateoas.user_account.SimpleUserAccountModelAssembler +import io.tolgee.hateoas.userAccount.SimpleUserAccountModelAssembler import io.tolgee.model.views.BatchJobView import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport import org.springframework.stereotype.Component @Component class BatchJobModelAssembler( - val simpleUserAccountModelAssembler: SimpleUserAccountModelAssembler + val simpleUserAccountModelAssembler: SimpleUserAccountModelAssembler, ) : RepresentationModelAssemblerSupport( - BatchJobManagementController::class.java, BatchJobModel::class.java -) { + BatchJobManagementController::class.java, + BatchJobModel::class.java, + ) { override fun toModel(view: BatchJobView): BatchJobModel { return BatchJobModel( id = view.batchJob.id, @@ -23,7 +24,7 @@ class BatchJobModelAssembler( createdAt = view.batchJob.createdAt?.time ?: 0, updatedAt = view.batchJob.updatedAt?.time ?: 0, activityRevisionId = view.batchJob.activityRevision?.id, - errorMessage = view.errorMessage?.code + errorMessage = view.errorMessage?.code, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/contentDelivery/ContentDeliveryConfigModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/contentDelivery/ContentDeliveryConfigModel.kt index 26a141cf8d..b799c14eef 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/contentDelivery/ContentDeliveryConfigModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/contentDelivery/ContentDeliveryConfigModel.kt @@ -17,7 +17,7 @@ class ContentDeliveryConfigModel( val storage: ContentStorageModel?, val publicUrl: String?, val autoPublish: Boolean, - val lastPublished: Long? + val lastPublished: Long?, ) : RepresentationModel(), Serializable, IExportParams { override var languages: Set? = null override var format: ExportFormat = ExportFormat.JSON diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/contentDelivery/ContentDeliveryConfigModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/contentDelivery/ContentDeliveryConfigModelAssembler.kt index 62c598a045..f4f5ba68dd 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/contentDelivery/ContentDeliveryConfigModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/contentDelivery/ContentDeliveryConfigModelAssembler.kt @@ -10,10 +10,11 @@ import org.springframework.stereotype.Component @Component class ContentDeliveryConfigModelAssembler( private val contentStorageModelAssembler: ContentStorageModelAssembler, - private val tolgeeProperties: TolgeeProperties + private val tolgeeProperties: TolgeeProperties, ) : RepresentationModelAssemblerSupport( - ContentDeliveryConfigController::class.java, ContentDeliveryConfigModel::class.java -) { + ContentDeliveryConfigController::class.java, + ContentDeliveryConfigModel::class.java, + ) { override fun toModel(entity: ContentDeliveryConfig): ContentDeliveryConfigModel { return ContentDeliveryConfigModel( id = entity.id, @@ -22,7 +23,7 @@ class ContentDeliveryConfigModelAssembler( storage = entity.contentStorage?.let { contentStorageModelAssembler.toModel(it) }, publicUrl = getPublicUrl(entity), autoPublish = entity.automationActions.isNotEmpty(), - lastPublished = entity.lastPublished?.time + lastPublished = entity.lastPublished?.time, ).also { it.copyPropsFrom(entity) } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportAddFilesResultModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportAddFilesResultModel.kt index 48e02d6fd8..2aeb65c315 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportAddFilesResultModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportAddFilesResultModel.kt @@ -8,5 +8,5 @@ import org.springframework.hateoas.server.core.Relation @Relation(collectionRelation = "fileIssues", itemRelation = "fileIssue") open class ImportAddFilesResultModel( val errors: List, - val result: PagedModel? + val result: PagedModel?, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportFileIssueModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportFileIssueModel.kt index c88827270b..96868a39d1 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportFileIssueModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportFileIssueModel.kt @@ -9,5 +9,5 @@ import org.springframework.hateoas.server.core.Relation open class ImportFileIssueModel( override val id: Long, override val type: FileIssueType, - override val params: List + override val params: List, ) : RepresentationModel(), ImportFileIssueView diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportFileIssueModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportFileIssueModelAssembler.kt index 5481eb1515..fd8d43a3ac 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportFileIssueModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportFileIssueModelAssembler.kt @@ -7,15 +7,16 @@ import org.springframework.stereotype.Component @Component class ImportFileIssueModelAssembler( - val importFileIssueParamModelAssembler: ImportFileIssueParamModelAssembler + val importFileIssueParamModelAssembler: ImportFileIssueParamModelAssembler, ) : RepresentationModelAssemblerSupport( - V2ImportController::class.java, ImportFileIssueModel::class.java -) { + V2ImportController::class.java, + ImportFileIssueModel::class.java, + ) { override fun toModel(view: ImportFileIssueView): ImportFileIssueModel { return ImportFileIssueModel( id = view.id, type = view.type, - params = view.params.map { importFileIssueParamModelAssembler.toModel(it) } + params = view.params.map { importFileIssueParamModelAssembler.toModel(it) }, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportFileIssueParamModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportFileIssueParamModel.kt index c339ea2c99..f599787755 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportFileIssueParamModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportFileIssueParamModel.kt @@ -8,5 +8,5 @@ import org.springframework.hateoas.server.core.Relation @Relation(collectionRelation = "fileIssueParams", itemRelation = "fileIssueParamModel") open class ImportFileIssueParamModel( override val type: FileIssueParamType, - override val value: String? + override val value: String?, ) : RepresentationModel(), ImportFileIssueParamView diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportFileIssueParamModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportFileIssueParamModelAssembler.kt index d97b2ab70f..f31916ad75 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportFileIssueParamModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportFileIssueParamModelAssembler.kt @@ -8,12 +8,13 @@ import org.springframework.stereotype.Component @Component class ImportFileIssueParamModelAssembler : RepresentationModelAssemblerSupport( - V2ImportController::class.java, ImportFileIssueParamModel::class.java + V2ImportController::class.java, + ImportFileIssueParamModel::class.java, ) { override fun toModel(view: ImportFileIssueParamView): ImportFileIssueParamModel { return ImportFileIssueParamModel( type = view.type, - value = view.value + value = view.value, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportLanguageModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportLanguageModelAssembler.kt index 6026bb1d8b..0708bcef95 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportLanguageModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportLanguageModelAssembler.kt @@ -7,7 +7,8 @@ import org.springframework.stereotype.Component @Component class ImportLanguageModelAssembler : RepresentationModelAssemblerSupport( - V2ImportController::class.java, ImportLanguageModel::class.java + V2ImportController::class.java, + ImportLanguageModel::class.java, ) { override fun toModel(view: ImportLanguageView): ImportLanguageModel { return ImportLanguageModel( @@ -23,7 +24,7 @@ class ImportLanguageModelAssembler : RepresentationModelAssemblerSupport(), Serializable diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportTranslationModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportTranslationModel.kt index a412066a47..242b075b8c 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportTranslationModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportTranslationModel.kt @@ -12,5 +12,5 @@ open class ImportTranslationModel( val conflictId: Long?, val conflictText: String?, val override: Boolean, - val resolved: Boolean + val resolved: Boolean, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportTranslationModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportTranslationModelAssembler.kt index 9a13e5333e..97a3613f64 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportTranslationModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/dataImport/ImportTranslationModelAssembler.kt @@ -8,7 +8,8 @@ import org.springframework.stereotype.Component @Component class ImportTranslationModelAssembler : RepresentationModelAssemblerSupport( - V2ImportController::class.java, ImportTranslationModel::class.java + V2ImportController::class.java, + ImportTranslationModel::class.java, ) { override fun toModel(view: ImportTranslationView): ImportTranslationModel { return ImportTranslationModel( @@ -19,7 +20,7 @@ class ImportTranslationModelAssembler : conflictId = view.conflictId, conflictText = view.conflictText, override = view.override, - resolved = view.resolvedHash != null + resolved = view.resolvedHash != null, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/invitation/OrganizationInvitationModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/invitation/OrganizationInvitationModel.kt index 59dc32db04..1e3b1e12b4 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/invitation/OrganizationInvitationModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/invitation/OrganizationInvitationModel.kt @@ -12,5 +12,5 @@ open class OrganizationInvitationModel( val type: OrganizationRoleType, val createdAt: Date, val invitedUserName: String?, - val invitedUserEmail: String? + val invitedUserEmail: String?, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/invitation/OrganizationInvitationModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/invitation/OrganizationInvitationModelAssembler.kt index 6d0d7327c2..c55486816a 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/invitation/OrganizationInvitationModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/invitation/OrganizationInvitationModelAssembler.kt @@ -9,7 +9,8 @@ import org.springframework.stereotype.Component @Component class OrganizationInvitationModelAssembler : RepresentationModelAssemblerSupport( - V2InvitationController::class.java, OrganizationInvitationModel::class.java + V2InvitationController::class.java, + OrganizationInvitationModel::class.java, ) { override fun toModel(entity: Invitation): OrganizationInvitationModel { return OrganizationInvitationModel( @@ -18,7 +19,7 @@ class OrganizationInvitationModelAssembler : entity.organizationRole!!.type!!, entity.createdAt!!, invitedUserName = entity.name, - invitedUserEmail = entity.email + invitedUserEmail = entity.email, ) .add(linkTo { acceptInvitation(entity.code) }.withRel("accept")) .add(linkTo { deleteInvitation(entity.id!!) }.withRel("delete")) diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/invitation/ProjectInvitationModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/invitation/ProjectInvitationModel.kt index cf7550f221..54ac017282 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/invitation/ProjectInvitationModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/invitation/ProjectInvitationModel.kt @@ -17,5 +17,5 @@ open class ProjectInvitationModel( val createdAt: Date, val invitedUserName: String?, val invitedUserEmail: String?, - val permission: PermissionModel + val permission: PermissionModel, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/invitation/ProjectInvitationModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/invitation/ProjectInvitationModelAssembler.kt index a0a2d71f47..5c21759753 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/invitation/ProjectInvitationModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/invitation/ProjectInvitationModelAssembler.kt @@ -9,11 +9,12 @@ import org.springframework.stereotype.Component @Component class ProjectInvitationModelAssembler( - private val permissionModelAssembler: PermissionModelAssembler + private val permissionModelAssembler: PermissionModelAssembler, ) : RepresentationModelAssemblerSupport( - V2InvitationController::class.java, ProjectInvitationModel::class.java - ) { + V2InvitationController::class.java, + ProjectInvitationModel::class.java, + ) { override fun toModel(entity: Invitation): ProjectInvitationModel { return ProjectInvitationModel( id = entity.id!!, @@ -23,7 +24,7 @@ class ProjectInvitationModelAssembler( createdAt = entity.createdAt!!, invitedUserName = entity.name, invitedUserEmail = entity.email, - permission = permissionModelAssembler.toModel(entity.permission!!) + permission = permissionModelAssembler.toModel(entity.permission!!), ) .add(linkTo { acceptInvitation(entity.code) }.withRel("accept")) .add(linkTo { deleteInvitation(entity.id!!) }.withRel("delete")) diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyImportResolvableResultModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyImportResolvableResultModel.kt index 5198495b95..a76f2a0b71 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyImportResolvableResultModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyImportResolvableResultModel.kt @@ -11,7 +11,6 @@ import java.io.Serializable open class KeyImportResolvableResultModel( @Schema(description = "List of keys") val keys: List, - @Schema(description = "Map uploadedImageId to screenshot") val screenshots: Map, ) : RepresentationModel(), Serializable diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyModel.kt index e3c4721b38..1399c7cc41 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyModel.kt @@ -10,10 +10,8 @@ import java.io.Serializable open class KeyModel( @Schema(description = "Id of key record") val id: Long, - @Schema(description = "Name of key", example = "this_is_super_key") val name: String, - @Schema(description = "Namespace of key", example = "homepage") val namespace: String?, ) : RepresentationModel(), Serializable diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyModelAssembler.kt index 5734a79afb..a2173f7923 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyModelAssembler.kt @@ -7,11 +7,13 @@ import org.springframework.stereotype.Component @Component class KeyModelAssembler : RepresentationModelAssemblerSupport( - TranslationsController::class.java, KeyModel::class.java + TranslationsController::class.java, + KeyModel::class.java, ) { - override fun toModel(entity: Key) = KeyModel( - id = entity.id, - name = entity.name, - namespace = entity.namespace?.name - ) + override fun toModel(entity: Key) = + KeyModel( + id = entity.id, + name = entity.name, + namespace = entity.namespace?.name, + ) } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyModifiedModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyModifiedModel.kt index 7328412113..0a9eacee8a 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyModifiedModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyModifiedModel.kt @@ -13,5 +13,5 @@ open class KeyModifiedModel( @Schema(description = "Name of key", example = "this_is_super_key") val name: String, @Schema(description = "Old name of key", example = "this_is_super_key_old") - val oldName: String + val oldName: String, ) : RepresentationModel(), Serializable diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeySearchResultModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeySearchResultModelAssembler.kt index 753196e9f9..63968647a3 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeySearchResultModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeySearchResultModelAssembler.kt @@ -8,7 +8,8 @@ import org.springframework.stereotype.Component @Component class KeySearchResultModelAssembler : RepresentationModelAssemblerSupport( - KeyController::class.java, KeySearchSearchResultModel::class.java + KeyController::class.java, + KeySearchSearchResultModel::class.java, ) { override fun toModel(view: KeySearchResultView): KeySearchSearchResultModel { return KeySearchSearchResultModel(view) diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithBaseTranslationModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithBaseTranslationModel.kt index a8bd2450ef..5fd321483f 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithBaseTranslationModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithBaseTranslationModel.kt @@ -10,13 +10,10 @@ import java.io.Serializable open class KeyWithBaseTranslationModel( @Schema(description = "Id of key record") val id: Long, - @Schema(description = "Name of key", example = "this_is_super_key") val name: String, - @Schema(description = "Namespace of key", example = "homepage") val namespace: String?, - @Schema(description = "Base translation", example = "This is translation") - val baseTranslation: String? + val baseTranslation: String?, ) : RepresentationModel(), Serializable diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithBaseTranslationModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithBaseTranslationModelAssembler.kt index f3cf68b0dc..2e5147482e 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithBaseTranslationModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithBaseTranslationModelAssembler.kt @@ -7,7 +7,8 @@ import org.springframework.stereotype.Component @Component class KeyWithBaseTranslationModelAssembler : RepresentationModelAssemblerSupport( - KeyWithBaseTranslationView::class.java, KeyWithBaseTranslationModel::class.java + KeyWithBaseTranslationView::class.java, + KeyWithBaseTranslationModel::class.java, ) { override fun toModel(entity: KeyWithBaseTranslationView): KeyWithBaseTranslationModel { return KeyWithBaseTranslationModel(entity.id, entity.name, entity.namespace, entity.baseTranslation) diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithDataModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithDataModel.kt index 42d26c570c..3bcf34ae22 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithDataModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithDataModel.kt @@ -15,19 +15,15 @@ open class KeyWithDataModel( val id: Long, @Schema(description = "Name of key", example = "this_is_super_key") val name: String, - @Schema(description = "Namespace of key", example = "homepage") val namespace: String?, - @Schema( description = "Translations object containing values updated in this request", - example = "{\"en\": {\"id\": 100000003, \"text\": \"This is super translation!\" }}" + example = "{\"en\": {\"id\": 100000003, \"text\": \"This is super translation!\" }}", ) val translations: Map, - @Schema(description = "Tags of key") val tags: Set, - @Schema(description = "Screenshots of the key") - val screenshots: List + val screenshots: List, ) : RepresentationModel(), Serializable diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithDataModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithDataModelAssembler.kt index a3da4dfcd2..2a4949d8c1 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithDataModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithDataModelAssembler.kt @@ -12,18 +12,21 @@ import org.springframework.stereotype.Component class KeyWithDataModelAssembler( private val tagModelAssembler: TagModelAssembler, private val translationModelAssembler: TranslationModelAssembler, - private val screenshotModelAssembler: ScreenshotModelAssembler + private val screenshotModelAssembler: ScreenshotModelAssembler, ) : RepresentationModelAssemblerSupport( - TranslationsController::class.java, KeyWithDataModel::class.java -) { - override fun toModel(entity: Key) = KeyWithDataModel( - id = entity.id, - name = entity.name, - namespace = entity.namespace?.name, - translations = entity.translations.map { - it.language.tag to translationModelAssembler.toModel(it) - }.toMap(), - tags = entity.keyMeta?.tags?.map { tagModelAssembler.toModel(it) }?.toSet() ?: setOf(), - screenshots = entity.keyScreenshotReferences.map { it.screenshot }.map { screenshotModelAssembler.toModel(it) } - ) + TranslationsController::class.java, + KeyWithDataModel::class.java, + ) { + override fun toModel(entity: Key) = + KeyWithDataModel( + id = entity.id, + name = entity.name, + namespace = entity.namespace?.name, + translations = + entity.translations.map { + it.language.tag to translationModelAssembler.toModel(it) + }.toMap(), + tags = entity.keyMeta?.tags?.map { tagModelAssembler.toModel(it) }?.toSet() ?: setOf(), + screenshots = entity.keyScreenshotReferences.map { it.screenshot }.map { screenshotModelAssembler.toModel(it) }, + ) } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithScreenshotsModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithScreenshotsModelAssembler.kt index 0a8dbc71aa..6cde7ee10a 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithScreenshotsModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/KeyWithScreenshotsModelAssembler.kt @@ -13,21 +13,23 @@ import org.springframework.stereotype.Component class KeyWithScreenshotsModelAssembler( private val tagModelAssembler: TagModelAssembler, private val translationModelAssembler: TranslationModelAssembler, - private val screenshotModelAssembler: ScreenshotModelAssembler + private val screenshotModelAssembler: ScreenshotModelAssembler, ) : RepresentationModelAssemblerSupport>, KeyWithDataModel>( - TranslationsController::class.java, KeyWithDataModel::class.java -) { + TranslationsController::class.java, + KeyWithDataModel::class.java, + ) { override fun toModel(data: Pair>): KeyWithDataModel { val (entity, screenshots) = data return KeyWithDataModel( id = entity.id, name = entity.name, namespace = entity.namespace?.name, - translations = entity.translations.associate { - it.language.tag to translationModelAssembler.toModel(it) - }, + translations = + entity.translations.associate { + it.language.tag to translationModelAssembler.toModel(it) + }, tags = entity.keyMeta?.tags?.map { tagModelAssembler.toModel(it) }?.toSet() ?: setOf(), - screenshots = screenshots.map { screenshotModelAssembler.toModel(it) } + screenshots = screenshots.map { screenshotModelAssembler.toModel(it) }, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/namespace/NamespaceModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/namespace/NamespaceModel.kt index 2857a53926..799690f75c 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/namespace/NamespaceModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/namespace/NamespaceModel.kt @@ -10,7 +10,6 @@ import java.io.Serializable open class NamespaceModel( @Schema(description = "The id of namespace", example = "10000048") val id: Long, - @Schema(description = "", example = "homepage") val name: String, ) : RepresentationModel(), Serializable diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/namespace/NamespaceModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/namespace/NamespaceModelAssembler.kt index 8c1904d309..21c1c59094 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/namespace/NamespaceModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/namespace/NamespaceModelAssembler.kt @@ -7,10 +7,12 @@ import org.springframework.stereotype.Component @Component class NamespaceModelAssembler : RepresentationModelAssemblerSupport( - NamespaceController::class.java, NamespaceModel::class.java + NamespaceController::class.java, + NamespaceModel::class.java, ) { - override fun toModel(entity: Namespace) = NamespaceModel( - id = entity.id, - name = entity.name, - ) + override fun toModel(entity: Namespace) = + NamespaceModel( + id = entity.id, + name = entity.name, + ) } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/namespace/UsedNamespaceModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/namespace/UsedNamespaceModel.kt index cae64e6da3..1cf35d1d11 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/namespace/UsedNamespaceModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/namespace/UsedNamespaceModel.kt @@ -10,7 +10,6 @@ import java.io.Serializable open class UsedNamespaceModel( @Schema(description = "The id of namespace. Null for default namespace.", example = "10000048") val id: Long?, - @Schema(description = "Name of namespace. Null if default.", example = "homepage") val name: String?, ) : RepresentationModel(), Serializable diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/namespace/UsedNamespaceModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/namespace/UsedNamespaceModelAssembler.kt index 56bd8cde3c..3e3ccef385 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/key/namespace/UsedNamespaceModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/key/namespace/UsedNamespaceModelAssembler.kt @@ -6,10 +6,12 @@ import org.springframework.stereotype.Component @Component class UsedNamespaceModelAssembler : RepresentationModelAssemblerSupport, UsedNamespaceModel>( - NamespaceController::class.java, UsedNamespaceModel::class.java + NamespaceController::class.java, + UsedNamespaceModel::class.java, ) { - override fun toModel(entity: Pair) = UsedNamespaceModel( - id = entity.first, - name = entity.second, - ) + override fun toModel(entity: Pair) = + UsedNamespaceModel( + id = entity.first, + name = entity.second, + ) } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/language/LanguageModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/language/LanguageModel.kt index efe45d0b3c..cb7b7ebe4c 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/language/LanguageModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/language/LanguageModel.kt @@ -8,19 +8,14 @@ import org.springframework.hateoas.server.core.Relation @Relation(collectionRelation = "languages", itemRelation = "language") open class LanguageModel( val id: Long, - @Schema(example = "Czech", description = "Language name in english") val name: String, - @Schema(example = "cs-CZ", description = "Language tag according to BCP 47 definition") var tag: String, - @Schema(example = "čeština", description = "Language name in this language") var originalName: String? = null, - @Schema(example = "\uD83C\uDDE8\uD83C\uDDFF", description = "Language flag emoji as UTF-8 emoji") var flagEmoji: String? = null, - @Schema(example = "false", description = "Whether is base language of project") - var base: Boolean + var base: Boolean, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/language/LanguageModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/language/LanguageModelAssembler.kt index a796b4e4a3..f31695d46b 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/language/LanguageModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/language/LanguageModelAssembler.kt @@ -7,7 +7,8 @@ import org.springframework.stereotype.Component @Component class LanguageModelAssembler : RepresentationModelAssemblerSupport( - V2LanguagesController::class.java, LanguageModel::class.java + V2LanguagesController::class.java, + LanguageModel::class.java, ) { override fun toModel(view: LanguageView): LanguageModel { return LanguageModel( @@ -16,7 +17,7 @@ class LanguageModelAssembler : RepresentationModelAssemblerSupport(), Serializable diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/LanguageConfigItemModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/LanguageConfigItemModel.kt index 2649476bb2..5a36b47e3c 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/LanguageConfigItemModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/LanguageConfigItemModel.kt @@ -12,28 +12,22 @@ import java.io.Serializable class LanguageConfigItemModel( @Schema(description = "When null, its a default configuration applied to not configured languages") val targetLanguageId: Long?, - @Schema(description = "When null, its a default configuration applied to not configured languages") val targetLanguageTag: String?, - @Schema(description = "When null, its a default configuration applied to not configured languages") val targetLanguageName: String?, - @Schema( description = "Service used for automated translating (deprecated: use primaryServiceInfo)", - deprecated = true + deprecated = true, ) val primaryService: MtServiceType?, - @Schema(description = "Service info used for automated translating") val primaryServiceInfo: MtServiceInfo?, - @Schema( description = "Services to be used for suggesting (deprecated: use enabledServicesInfo)", - deprecated = true + deprecated = true, ) val enabledServices: Set, - @Schema(description = "Info about enabled services") - var enabledServicesInfo: Set + var enabledServicesInfo: Set, ) : RepresentationModel(), Serializable diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/LanguageConfigItemModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/LanguageConfigItemModelAssembler.kt index f479b5e153..b6e7ca9c2a 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/LanguageConfigItemModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/LanguageConfigItemModelAssembler.kt @@ -9,15 +9,16 @@ import org.springframework.stereotype.Component @Component class LanguageConfigItemModelAssembler : RepresentationModelAssemblerSupport( V2ProjectsController::class.java, - LanguageConfigItemModel::class.java + LanguageConfigItemModel::class.java, ) { - override fun toModel(entity: MtServiceConfig) = LanguageConfigItemModel( - targetLanguageId = entity.targetLanguage?.id, - targetLanguageTag = entity.targetLanguage?.tag, - targetLanguageName = entity.targetLanguage?.name, - primaryService = entity.primaryService, - enabledServices = entity.enabledServices, - enabledServicesInfo = entity.enabledServicesInfo.toSet(), - primaryServiceInfo = entity.primaryServiceInfo - ) + override fun toModel(entity: MtServiceConfig) = + LanguageConfigItemModel( + targetLanguageId = entity.targetLanguage?.id, + targetLanguageTag = entity.targetLanguage?.tag, + targetLanguageName = entity.targetLanguage?.name, + primaryService = entity.primaryService, + enabledServices = entity.enabledServices, + enabledServicesInfo = entity.enabledServicesInfo.toSet(), + primaryServiceInfo = entity.primaryServiceInfo, + ) } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/LanguageInfoModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/LanguageInfoModel.kt index 5d913aa849..cc4ceb6bdb 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/LanguageInfoModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/LanguageInfoModel.kt @@ -10,5 +10,5 @@ import java.io.Serializable class LanguageInfoModel( val languageId: Long, val languageTag: String, - val supportedServices: List + val supportedServices: List, ) : RepresentationModel(), Serializable diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/StreamedSuggestionInfo.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/StreamedSuggestionInfo.kt index 6e0a7121ad..f30483cac5 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/StreamedSuggestionInfo.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/StreamedSuggestionInfo.kt @@ -4,5 +4,5 @@ import io.tolgee.constants.MtServiceType class StreamedSuggestionInfo( val servicesTypes: List, - val baseBlank: Boolean + val baseBlank: Boolean, ) diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/SuggestResultModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/SuggestResultModel.kt index d87b131896..9aff999e76 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/SuggestResultModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/SuggestResultModel.kt @@ -16,10 +16,9 @@ class SuggestResultModel( "TOLGEE": "This was translated by Tolgee Translator", } """, - deprecated = true + deprecated = true, ) val machineTranslations: Map?, - @Schema( description = "Results provided by enabled services.", example = """ @@ -33,12 +32,11 @@ class SuggestResultModel( "contextDescription": "This is an example in swagger" } } - """ + """, ) val result: Map?, - @Schema( - description = "If true, the base translation was empty and no translation was provided." + description = "If true, the base translation was empty and no translation was provided.", ) val baseBlank: Boolean, ) : RepresentationModel(), Serializable diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/TranslationItemModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/TranslationItemModel.kt index 4cc8311d96..f3904a6f6f 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/TranslationItemModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/machineTranslation/TranslationItemModel.kt @@ -3,5 +3,5 @@ package io.tolgee.hateoas.machineTranslation @Suppress("unused") class TranslationItemModel( val output: String, - val contextDescription: String? + val contextDescription: String?, ) diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/IOrganizationModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/IOrganizationModel.kt index 73dc4f3112..03ef25aa5d 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/IOrganizationModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/IOrganizationModel.kt @@ -21,7 +21,7 @@ interface IOrganizationModel { @get:Schema( description = """The role of currently authorized user. -Can be null when user has direct access to one of the projects owned by the organization.""" +Can be null when user has direct access to one of the projects owned by the organization.""", ) val currentUserRole: OrganizationRoleType? diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/OrganizationModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/OrganizationModel.kt index 28308288de..ab12869963 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/OrganizationModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/OrganizationModel.kt @@ -9,16 +9,10 @@ import org.springframework.hateoas.server.core.Relation @Relation(collectionRelation = "organizations", itemRelation = "organization") open class OrganizationModel( override val id: Long, - override val name: String, - override val slug: String, - override val description: String?, - override val basePermissions: PermissionModel, - override val currentUserRole: OrganizationRoleType?, - override var avatar: Avatar?, ) : RepresentationModel(), IOrganizationModel diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/OrganizationModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/OrganizationModelAssembler.kt index ef912c3478..e34ada0969 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/OrganizationModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/OrganizationModelAssembler.kt @@ -13,8 +13,9 @@ class OrganizationModelAssembler( private val avatarService: AvatarService, private val permissionModelAssembler: PermissionModelAssembler, ) : RepresentationModelAssemblerSupport( - OrganizationController::class.java, OrganizationModel::class.java -) { + OrganizationController::class.java, + OrganizationModel::class.java, + ) { override fun toModel(view: OrganizationView): OrganizationModel { val link = linkTo { get(view.organization.slug) }.withSelfRel() val basePermission = view.organization.basePermission diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/PrivateOrganizationModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/PrivateOrganizationModel.kt index e68c9bede3..01561f0ebd 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/PrivateOrganizationModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/PrivateOrganizationModel.kt @@ -10,10 +10,8 @@ import org.springframework.hateoas.server.core.Relation @Relation(collectionRelation = "organizations", itemRelation = "organization") open class PrivateOrganizationModel( organizationModel: OrganizationModel, - @get:Schema(example = "Features organization has enabled") val enabledFeatures: Array, - @get:Schema(example = "Quick start data for current user") - val quickStart: QuickStartModel? + val quickStart: QuickStartModel?, ) : IOrganizationModel by organizationModel, RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/PrivateOrganizationModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/PrivateOrganizationModelAssembler.kt index 6ec635d5e3..f016573e59 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/PrivateOrganizationModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/PrivateOrganizationModelAssembler.kt @@ -9,17 +9,17 @@ import org.springframework.stereotype.Component @Component class PrivateOrganizationModelAssembler( private val organizationModelAssembler: OrganizationModelAssembler, - private val quickStartModelAssembler: QuickStartModelAssembler + private val quickStartModelAssembler: QuickStartModelAssembler, ) { fun toModel( organization: OrganizationView, features: Array, - quickStart: QuickStart? + quickStart: QuickStart?, ): PrivateOrganizationModel { return PrivateOrganizationModel( organizationModel = organizationModelAssembler.toModel(organization), enabledFeatures = features, - quickStart = quickStart?.let { quickStartModelAssembler.toModel(it) } + quickStart = quickStart?.let { quickStartModelAssembler.toModel(it) }, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/PublicUsageModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/PublicUsageModel.kt index d332e3589b..1ddae759db 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/PublicUsageModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/PublicUsageModel.kt @@ -9,66 +9,58 @@ import java.io.Serializable @Relation(collectionRelation = "plans", itemRelation = "plan") open class PublicUsageModel( val organizationId: Long, - @Schema(description = "Current balance of standard credits. Standard credits are refilled every month") val creditBalance: Long, - @Schema( - description = """How many credits are included in your current plan""" + description = """How many credits are included in your current plan""", ) val includedMtCredits: Long, - @Schema(description = "Date when credits were refilled. (In epoch format)") val creditBalanceRefilledAt: Long, - @Schema(description = "Date when credits will be refilled. (In epoch format)") val creditBalanceNextRefillAt: Long, - @Schema(description = "Currently used credits over credits included in plan and extra credits") val currentPayAsYouGoMtCredits: Long, - @Schema( - description = "The maximum amount organization can spend" + - " on MT credit usage before they reach the spending limit" + description = + "The maximum amount organization can spend" + + " on MT credit usage before they reach the spending limit", ) val availablePayAsYouGoMtCredits: Long, - @Schema( - description = "Extra credits, which are neither refilled nor reset every month. These credits are " + - "used when there are no standard credits" + description = + "Extra credits, which are neither refilled nor reset every month. These credits are " + + "used when there are no standard credits", ) val extraCreditBalance: Long, - @Schema( - description = """How many translations can be stored within your organization""" + description = """How many translations can be stored within your organization""", ) val translationSlotsLimit: Long, - @Schema( - description = "How many translation slots are included in current subscription plan. " + - "How many translation slots can organization use without additional costs" + description = + "How many translation slots are included in current subscription plan. " + + "How many translation slots can organization use without additional costs", ) val includedTranslationSlots: Long, - @Schema( - description = "How many translations are included in current subscription plan. " + - "How many translations can organization use without additional costs" + description = + "How many translations are included in current subscription plan. " + + "How many translations can organization use without additional costs", ) val includedTranslations: Long, - @Schema( - description = """How many translations slots are currently used by organization""" + description = """How many translations slots are currently used by organization""", ) val currentTranslationSlots: Long, - @Schema( - description = """How many non-empty translations are currently stored by organization""" + description = """How many non-empty translations are currently stored by organization""", ) val currentTranslations: Long, - @Schema( - description = "How many translations can be stored until reaching the limit. " + - "(For pay us you go, the top limit is the spending limit)" + description = + "How many translations can be stored until reaching the limit. " + + "(For pay us you go, the top limit is the spending limit)", ) val translationsLimit: Long, ) : RepresentationModel(), Serializable diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/SimpleOrganizationModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/SimpleOrganizationModel.kt index 2b5cef8bf0..baf45e2b51 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/SimpleOrganizationModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/SimpleOrganizationModel.kt @@ -9,17 +9,13 @@ import org.springframework.hateoas.server.core.Relation @Relation(collectionRelation = "organizations", itemRelation = "organization") open class SimpleOrganizationModel( val id: Long, - @Schema(example = "Beautiful organization") val name: String, - @Schema(example = "btforg") val slug: String, - @Schema(example = "This is a beautiful organization full of beautiful and clever people") val description: String?, val basePermissions: PermissionModel, - @Schema(example = "Links to avatar images") - var avatar: Avatar? + var avatar: Avatar?, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/SimpleOrganizationModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/SimpleOrganizationModelAssembler.kt index ee3ee6c787..1f07f4e867 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/SimpleOrganizationModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/SimpleOrganizationModelAssembler.kt @@ -11,10 +11,11 @@ import org.springframework.stereotype.Component @Component class SimpleOrganizationModelAssembler( private val avatarService: AvatarService, - private val permissionModelAssembler: PermissionModelAssembler + private val permissionModelAssembler: PermissionModelAssembler, ) : RepresentationModelAssemblerSupport( - OrganizationController::class.java, SimpleOrganizationModel::class.java -) { + OrganizationController::class.java, + SimpleOrganizationModel::class.java, + ) { override fun toModel(entity: Organization): SimpleOrganizationModel { val link = linkTo { get(entity.slug ?: "") }.withSelfRel() return SimpleOrganizationModel( @@ -23,7 +24,7 @@ class SimpleOrganizationModelAssembler( entity.slug, entity.description, permissionModelAssembler.toModel(entity.basePermission), - avatarService.getAvatarLinks(entity.avatarHash) + avatarService.getAvatarLinks(entity.avatarHash), ).add(link) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/UserAccountWithOrganizationRoleModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/UserAccountWithOrganizationRoleModel.kt index 224de4d846..467cdbdb09 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/UserAccountWithOrganizationRoleModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/UserAccountWithOrganizationRoleModel.kt @@ -13,5 +13,5 @@ data class UserAccountWithOrganizationRoleModel( var username: String, var organizationRole: OrganizationRoleType?, var projectsWithDirectPermission: List, - var avatar: Avatar? + var avatar: Avatar?, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/UserAccountWithOrganizationRoleModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/UserAccountWithOrganizationRoleModelAssembler.kt index ce612c03b8..d3ba43e3e6 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/UserAccountWithOrganizationRoleModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/organization/UserAccountWithOrganizationRoleModelAssembler.kt @@ -11,22 +11,25 @@ import org.springframework.stereotype.Component @Component class UserAccountWithOrganizationRoleModelAssembler( private val simpleProjectModelAssembler: SimpleProjectModelAssembler, - private val avatarService: AvatarService + private val avatarService: AvatarService, ) : RepresentationModelAssemblerSupport< - Pair>, UserAccountWithOrganizationRoleModel - >( - V2UserController::class.java, UserAccountWithOrganizationRoleModel::class.java - ) { - override fun toModel(data: Pair>): - UserAccountWithOrganizationRoleModel { + Pair>, + UserAccountWithOrganizationRoleModel, + >( + V2UserController::class.java, + UserAccountWithOrganizationRoleModel::class.java, + ) { + override fun toModel( + data: Pair>, + ): UserAccountWithOrganizationRoleModel { return UserAccountWithOrganizationRoleModel( id = data.first.id, name = data.first.name, username = data.first.username, organizationRole = data.first.organizationRole, projectsWithDirectPermission = data.second.map { simpleProjectModelAssembler.toModel(it) }, - avatar = avatarService.getAvatarLinks(data.first.avatarHash) + avatar = avatarService.getAvatarLinks(data.first.avatarHash), ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/PatModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/PatModel.kt index 5a9a0e9d83..568545a004 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/PatModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/PatModel.kt @@ -10,5 +10,5 @@ open class PatModel( override val expiresAt: Long?, override val createdAt: Long, override val updatedAt: Long, - override val lastUsedAt: Long? + override val lastUsedAt: Long?, ) : RepresentationModel(), IPatModel diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/PatModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/PatModelAssembler.kt index 6385198555..d7d17538d8 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/PatModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/PatModelAssembler.kt @@ -8,7 +8,8 @@ import java.util.* @Component class PatModelAssembler() : RepresentationModelAssemblerSupport( - PatController::class.java, PatModel::class.java + PatController::class.java, + PatModel::class.java, ) { override fun toModel(entity: Pat): PatModel { return PatModel( @@ -17,7 +18,7 @@ class PatModelAssembler() : RepresentationModelAssemblerSupport( expiresAt = entity.expiresAt?.time, createdAt = entity.createdAt?.time ?: Date().time, updatedAt = entity.updatedAt?.time ?: Date().time, - lastUsedAt = entity.lastUsedAt?.time + lastUsedAt = entity.lastUsedAt?.time, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/PatWithUserModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/PatWithUserModel.kt index 14b425c9b2..8f4f75c9dc 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/PatWithUserModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/PatWithUserModel.kt @@ -1,7 +1,7 @@ package io.tolgee.hateoas.pat import io.swagger.v3.oas.annotations.media.Schema -import io.tolgee.hateoas.user_account.SimpleUserAccountModel +import io.tolgee.hateoas.userAccount.SimpleUserAccountModel import org.springframework.hateoas.RepresentationModel import org.springframework.hateoas.server.core.Relation @@ -9,5 +9,5 @@ import org.springframework.hateoas.server.core.Relation open class PatWithUserModel( @Schema(hidden = true) patModel: PatModel, - val user: SimpleUserAccountModel + val user: SimpleUserAccountModel, ) : IPatModel by patModel, RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/PatWithUserModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/PatWithUserModelAssembler.kt index f3c8fefad0..dc7a49a89a 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/PatWithUserModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/PatWithUserModelAssembler.kt @@ -1,7 +1,7 @@ package io.tolgee.hateoas.pat import io.tolgee.api.v2.controllers.PatController -import io.tolgee.hateoas.user_account.SimpleUserAccountModelAssembler +import io.tolgee.hateoas.userAccount.SimpleUserAccountModelAssembler import io.tolgee.model.Pat import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport import org.springframework.stereotype.Component @@ -9,14 +9,15 @@ import org.springframework.stereotype.Component @Component class PatWithUserModelAssembler( private val patModelAssembler: PatModelAssembler, - private val simpleUserAccountModelAssembler: SimpleUserAccountModelAssembler + private val simpleUserAccountModelAssembler: SimpleUserAccountModelAssembler, ) : RepresentationModelAssemblerSupport( - PatController::class.java, PatWithUserModel::class.java -) { + PatController::class.java, + PatWithUserModel::class.java, + ) { override fun toModel(entity: Pat): PatWithUserModel { return PatWithUserModel( patModel = patModelAssembler.toModel(entity), - user = simpleUserAccountModelAssembler.toModel(entity.userAccount) + user = simpleUserAccountModelAssembler.toModel(entity.userAccount), ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/RevealedPatModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/RevealedPatModel.kt index 75f899b942..b3f3aa20cf 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/RevealedPatModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/RevealedPatModel.kt @@ -8,5 +8,5 @@ import org.springframework.hateoas.server.core.Relation open class RevealedPatModel( @Schema(hidden = true) patModel: PatModel, - val token: String + val token: String, ) : IPatModel by patModel, RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/RevealedPatModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/RevealedPatModelAssembler.kt index 33e76cad59..65d01d10ab 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/RevealedPatModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/pat/RevealedPatModelAssembler.kt @@ -8,15 +8,16 @@ import org.springframework.stereotype.Component @Component class RevealedPatModelAssembler( - private val patModelAssembler: PatModelAssembler + private val patModelAssembler: PatModelAssembler, ) : RepresentationModelAssemblerSupport( - PatController::class.java, RevealedPatModel::class.java -) { + PatController::class.java, + RevealedPatModel::class.java, + ) { override fun toModel(entity: Pat): RevealedPatModel { val token = entity.token ?: throw IllegalStateException("Token not regenerated.") return RevealedPatModel( patModel = patModelAssembler.toModel(entity), - token = "$PAT_PREFIX$token" + token = "$PAT_PREFIX$token", ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/ComputedPermissionModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/ComputedPermissionModel.kt index e646f42ff6..5875034539 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/ComputedPermissionModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/ComputedPermissionModel.kt @@ -5,5 +5,5 @@ import org.springframework.hateoas.RepresentationModel open class ComputedPermissionModel( permissionModel: PermissionModel, - val origin: ComputedPermissionOrigin + val origin: ComputedPermissionOrigin, ) : RepresentationModel(), IDeprecatedPermissionModel by permissionModel diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/ComputedPermissionModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/ComputedPermissionModelAssembler.kt index 94b640a620..ba210f25d4 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/ComputedPermissionModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/ComputedPermissionModelAssembler.kt @@ -7,14 +7,15 @@ import org.springframework.stereotype.Component @Component class ComputedPermissionModelAssembler( - private val permissionModelAssembler: PermissionModelAssembler + private val permissionModelAssembler: PermissionModelAssembler, ) : RepresentationModelAssemblerSupport( - V2UserController::class.java, ComputedPermissionModel::class.java -) { + V2UserController::class.java, + ComputedPermissionModel::class.java, + ) { override fun toModel(dto: ComputedPermissionDto): ComputedPermissionModel { return ComputedPermissionModel( permissionModelAssembler.toModel(dto), - dto.origin + dto.origin, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/IDeprecatedPermissionModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/IDeprecatedPermissionModel.kt index 34e9679062..4c3d7ebf05 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/IDeprecatedPermissionModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/IDeprecatedPermissionModel.kt @@ -8,7 +8,7 @@ interface IDeprecatedPermissionModel : IPermissionModel { List of languages current user has TRANSLATE permission to. If null, all languages edition is permitted.""", deprecated = true, - example = "[200001, 200004]" + example = "[200001, 200004]", ) val permittedLanguageIds: Collection? } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/IPermissionModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/IPermissionModel.kt index 88f7a40825..fc7e845bee 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/IPermissionModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/IPermissionModel.kt @@ -6,9 +6,10 @@ import io.tolgee.model.enums.Scope interface IPermissionModel { @get:Schema( - description = "Granted scopes to the user. When user has type permissions, " + - "this field contains permission scopes of the type.", - example = """["KEYS_EDIT", "TRANSLATIONS_VIEW"]""" + description = + "Granted scopes to the user. When user has type permissions, " + + "this field contains permission scopes of the type.", + example = """["KEYS_EDIT", "TRANSLATIONS_VIEW"]""", ) val scopes: Array @@ -19,20 +20,21 @@ interface IPermissionModel { @get:Schema( description = """List of languages user can translate to. If null, all languages editing is permitted.""", - example = "[200001, 200004]" + example = "[200001, 200004]", ) val translateLanguageIds: Collection? @get:Schema( description = """List of languages user can view. If null, all languages view is permitted.""", - example = "[200001, 200004]" + example = "[200001, 200004]", ) val viewLanguageIds: Collection? @get:Schema( - description = "List of languages user can change state to. If null, changing state " + - "of all language values is permitted.", - example = "[200001, 200004]" + description = + "List of languages user can change state to. If null, changing state " + + "of all language values is permitted.", + example = "[200001, 200004]", ) val stateChangeLanguageIds: Collection? } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModelAssembler.kt index 8ad502ec0d..758e57bb63 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/permission/PermissionModelAssembler.kt @@ -8,7 +8,8 @@ import org.springframework.stereotype.Component @Component class PermissionModelAssembler() : RepresentationModelAssemblerSupport( - V2UserController::class.java, PermissionModel::class.java + V2UserController::class.java, + PermissionModel::class.java, ) { override fun toModel(entity: IPermission): PermissionModel { return PermissionModel( diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModel.kt index c58ee75777..5fc3b06fa3 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModel.kt @@ -23,5 +23,5 @@ open class ProjectModel( val organizationRole: OrganizationRoleType?, @Schema(description = "Current user's direct permission", example = "MANAGE") val directPermission: PermissionModel?, - val computedPermission: ComputedPermissionModel + val computedPermission: ComputedPermissionModel, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModelAssembler.kt index 3747287a7a..82aeb5199d 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectModelAssembler.kt @@ -29,13 +29,15 @@ class ProjectModelAssembler( private val computedPermissionModelAssembler: ComputedPermissionModelAssembler, private val authenticationFacade: AuthenticationFacade, ) : RepresentationModelAssemblerSupport( - V2ProjectsController::class.java, ProjectModel::class.java -) { + V2ProjectsController::class.java, + ProjectModel::class.java, + ) { override fun toModel(view: ProjectWithLanguagesView): ProjectModel { val link = linkTo { get(view.id) }.withSelfRel() - val baseLanguage = view.baseLanguage ?: let { - projectService.getOrCreateBaseLanguage(view.id) - } + val baseLanguage = + view.baseLanguage ?: let { + projectService.getOrCreateBaseLanguage(view.id) + } val computedPermissions = getComputedPermissions(view) @@ -60,7 +62,7 @@ class ProjectModelAssembler( view.organizationRole, view.organizationOwner.basePermission, view.directPermission, - UserAccount.Role.USER + UserAccount.Role.USER, ).getAdminPermissions(authenticationFacade.authenticatedUserOrNull?.role) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectTransferOptionModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectTransferOptionModel.kt index 0529df420b..03de39f4a1 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectTransferOptionModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectTransferOptionModel.kt @@ -8,5 +8,5 @@ import org.springframework.hateoas.server.core.Relation open class ProjectTransferOptionModel( val name: String, val slug: String, - val id: Long + val id: Long, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModel.kt index 1d37f8ad17..0d1312c4e8 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModel.kt @@ -2,7 +2,7 @@ package io.tolgee.hateoas.project import io.swagger.v3.oas.annotations.media.Schema import io.tolgee.dtos.Avatar -import io.tolgee.dtos.query_results.ProjectStatistics +import io.tolgee.dtos.queryResults.ProjectStatistics import io.tolgee.hateoas.language.LanguageModel import io.tolgee.hateoas.organization.SimpleOrganizationModel import io.tolgee.hateoas.permission.ComputedPermissionModel @@ -26,9 +26,9 @@ open class ProjectWithStatsModel( val directPermission: PermissionModel?, @Schema( description = "Actual current user's permissions on this project. You can not sort data by this column!", - example = "EDIT" + example = "EDIT", ) val computedPermission: ComputedPermissionModel, val stats: ProjectStatistics, - val languages: List + val languages: List, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModelAssembler.kt index 2bf0714f0d..0e72aaaa5a 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/project/ProjectWithStatsModelAssembler.kt @@ -28,19 +28,22 @@ class ProjectWithStatsModelAssembler( private val computedPermissionModelAssembler: ComputedPermissionModelAssembler, private val authenticationFacade: AuthenticationFacade, ) : RepresentationModelAssemblerSupport( - V2ProjectsController::class.java, ProjectWithStatsModel::class.java -) { + V2ProjectsController::class.java, + ProjectWithStatsModel::class.java, + ) { override fun toModel(view: ProjectWithStatsView): ProjectWithStatsModel { val link = linkTo { get(view.id) }.withSelfRel() - val baseLanguage = view.baseLanguage ?: let { - projectService.getOrCreateBaseLanguage(view.id) - } - val computedPermissions = permissionService.computeProjectPermission( - view.organizationRole, - view.organizationOwner.basePermission, - view.directPermission, - UserAccount.Role.USER - ).getAdminPermissions(userRole = authenticationFacade.authenticatedUserOrNull?.role) + val baseLanguage = + view.baseLanguage ?: let { + projectService.getOrCreateBaseLanguage(view.id) + } + val computedPermissions = + permissionService.computeProjectPermission( + view.organizationRole, + view.organizationOwner.basePermission, + view.directPermission, + UserAccount.Role.USER, + ).getAdminPermissions(userRole = authenticationFacade.authenticatedUserOrNull?.role) return ProjectWithStatsModel( id = view.id, diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/project/SimpleProjectModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/project/SimpleProjectModelAssembler.kt index cdaf96ccb0..520d5ecd41 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/project/SimpleProjectModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/project/SimpleProjectModelAssembler.kt @@ -13,8 +13,9 @@ class SimpleProjectModelAssembler( private val languageModelAssembler: LanguageModelAssembler, private val avatarService: AvatarService, ) : RepresentationModelAssemblerSupport( - V2ProjectsController::class.java, SimpleProjectModel::class.java -) { + V2ProjectsController::class.java, + SimpleProjectModel::class.java, + ) { override fun toModel(entity: Project): SimpleProjectModel { return SimpleProjectModel( id = entity.id, @@ -22,11 +23,12 @@ class SimpleProjectModelAssembler( description = entity.description, slug = entity.slug, avatar = avatarService.getAvatarLinks(entity.avatarHash), - baseLanguage = entity.baseLanguage?.let { - languageModelAssembler.toModel( - LanguageViewImpl(it, true) - ) - }, + baseLanguage = + entity.baseLanguage?.let { + languageModelAssembler.toModel( + LanguageViewImpl(it, true), + ) + }, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/project/stats/LanguageStatsModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/project/stats/LanguageStatsModel.kt index d30ccedd02..a564862e1d 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/project/stats/LanguageStatsModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/project/stats/LanguageStatsModel.kt @@ -16,5 +16,5 @@ open class LanguageStatsModel( val reviewedPercentage: Double, val untranslatedKeyCount: Long, val untranslatedWordCount: Long, - val untranslatedPercentage: Double + val untranslatedPercentage: Double, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/project/stats/LanguageStatsModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/project/stats/LanguageStatsModelAssembler.kt index 0cab4176f7..0b1f6b8659 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/project/stats/LanguageStatsModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/project/stats/LanguageStatsModelAssembler.kt @@ -7,7 +7,8 @@ import org.springframework.stereotype.Component @Component class LanguageStatsModelAssembler : RepresentationModelAssemblerSupport( - V2ProjectsController::class.java, LanguageStatsModel::class.java + V2ProjectsController::class.java, + LanguageStatsModel::class.java, ) { override fun toModel(it: LanguageStats): LanguageStatsModel { return LanguageStatsModel( @@ -24,7 +25,7 @@ class LanguageStatsModelAssembler : RepresentationModelAssemblerSupport + val languageStats: List, ) diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/quickStart/QuickStartModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/quickStart/QuickStartModel.kt index 0139f3483f..0ae69af672 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/quickStart/QuickStartModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/quickStart/QuickStartModel.kt @@ -5,5 +5,5 @@ import org.springframework.hateoas.RepresentationModel data class QuickStartModel( val finished: Boolean, val completedSteps: MutableList, - val open: Boolean + val open: Boolean, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/quickStart/QuickStartModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/quickStart/QuickStartModelAssembler.kt index ca60f5666c..8fc9a17614 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/quickStart/QuickStartModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/quickStart/QuickStartModelAssembler.kt @@ -6,13 +6,14 @@ import org.springframework.stereotype.Component @Component class QuickStartModelAssembler() : RepresentationModelAssemblerSupport( - QuickStart::class.java, QuickStartModel::class.java + QuickStart::class.java, + QuickStartModel::class.java, ) { override fun toModel(entity: QuickStart): QuickStartModel { return QuickStartModel( finished = entity.finished, completedSteps = entity.completedSteps.toMutableList(), - open = entity.open + open = entity.open, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/screenshot/KeyInScreenshotModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/screenshot/KeyInScreenshotModel.kt index ea0281025f..3745f3f601 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/screenshot/KeyInScreenshotModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/screenshot/KeyInScreenshotModel.kt @@ -7,5 +7,5 @@ class KeyInScreenshotModel( val position: KeyInScreenshotPosition?, val keyName: String, val keyNamespace: String?, - val originalText: String? + val originalText: String?, ) diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/screenshot/ScreenshotModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/screenshot/ScreenshotModel.kt index 7785def57a..98b7d01855 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/screenshot/ScreenshotModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/screenshot/ScreenshotModel.kt @@ -16,7 +16,6 @@ When images are secured. Encrypted timestamp is appended to the filename. """, ) val filename: String, - @Schema( description = """Thumbnail file name, which may be downloaded from the screenshot path. diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/screenshot/ScreenshotModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/screenshot/ScreenshotModelAssembler.kt index 7766a3a755..3d37f1f6dc 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/screenshot/ScreenshotModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/screenshot/ScreenshotModelAssembler.kt @@ -19,8 +19,9 @@ class ScreenshotModelAssembler( private val projectHolder: ProjectHolder, private val jwtService: JwtService, ) : RepresentationModelAssemblerSupport( - TranslationsController::class.java, ScreenshotModel::class.java -) { + TranslationsController::class.java, + ScreenshotModel::class.java, + ) { override fun toModel(entity: Screenshot): ScreenshotModel { val filenameWithSignature = getFilenameWithSignature(entity.filename) val thumbnailFilenameWithSignature = getFilenameWithSignature(entity.thumbnailFilename) @@ -35,22 +36,25 @@ class ScreenshotModelAssembler( fileUrl = fileUrl, thumbnailUrl = thumbnailUrl, createdAt = entity.createdAt, - keyReferences = entity.keyScreenshotReferences.flatMap { reference -> - val positions = if (reference.positions.isNullOrEmpty()) - listOf(null) - else - reference.positions!! + keyReferences = + entity.keyScreenshotReferences.flatMap { reference -> + val positions = + if (reference.positions.isNullOrEmpty()) { + listOf(null) + } else { + reference.positions!! + } - positions.map { position -> - KeyInScreenshotModel( - reference.key.id, - position, - reference.key.name, - reference.key.namespace?.name, - reference.originalText - ) - } - }, + positions.map { position -> + KeyInScreenshotModel( + reference.key.id, + position, + reference.key.name, + reference.key.namespace?.name, + reference.originalText, + ) + } + }, location = entity.location, width = entity.width, height = entity.height, @@ -63,8 +67,9 @@ class ScreenshotModelAssembler( var fileUrl = "${tolgeeProperties.fileStorageUrl}/${FileStoragePath.SCREENSHOTS}/$filename" if (!fileUrl.matches(Regex("^https?://.*$"))) { val builder = ServletUriComponentsBuilder.fromCurrentRequestUri() - fileUrl = builder.replacePath(fileUrl) - .replaceQuery("").build().toUriString() + fileUrl = + builder.replacePath(fileUrl) + .replaceQuery("").build().toUriString() } return fileUrl } @@ -72,15 +77,16 @@ class ScreenshotModelAssembler( private fun getFilenameWithSignature(filename: String): String { var filenameWithSignature = filename if (tolgeeProperties.authentication.securedImageRetrieval) { - val token = jwtService.emitTicket( - authenticationFacade.authenticatedUser.id, - JwtService.TicketType.IMG_ACCESS, - tolgeeProperties.authentication.securedImageTimestampMaxAge, - mapOf( - "fileName" to filename, - "projectId" to projectHolder.projectOrNull?.id?.toString(), + val token = + jwtService.emitTicket( + authenticationFacade.authenticatedUser.id, + JwtService.TicketType.IMG_ACCESS, + tolgeeProperties.authentication.securedImageTimestampMaxAge, + mapOf( + "fileName" to filename, + "projectId" to projectHolder.projectOrNull?.id?.toString(), + ), ) - ) filenameWithSignature = "$filenameWithSignature?token=$token" } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/tag/TagModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/tag/TagModel.kt index 52a9c51608..0dc98dc3b8 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/tag/TagModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/tag/TagModel.kt @@ -6,7 +6,7 @@ import org.springframework.hateoas.server.core.Relation @Relation(collectionRelation = "tags", itemRelation = "tag") open class TagModel( val id: Long, - val name: String + val name: String, ) : RepresentationModel() { override fun equals(other: Any?): Boolean { if (this === other) return true diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/tag/TagModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/tag/TagModelAssembler.kt index fcb42c45f1..4bde09daaf 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/tag/TagModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/tag/TagModelAssembler.kt @@ -7,7 +7,8 @@ import org.springframework.stereotype.Component @Component class TagModelAssembler : RepresentationModelAssemblerSupport( - TagsController::class.java, TagModel::class.java + TagsController::class.java, + TagModel::class.java, ) { override fun toModel(entity: Tag): TagModel { return TagModel(entity.id, entity.name) diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/translationMemory/TranslationMemoryItemModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/translationMemory/TranslationMemoryItemModel.kt index b4722c6075..e421a94cd0 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/translationMemory/TranslationMemoryItemModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/translationMemory/TranslationMemoryItemModel.kt @@ -8,5 +8,5 @@ open class TranslationMemoryItemModel( var targetText: String, var baseText: String, var keyName: String, - var similarity: Float + var similarity: Float, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/translationMemory/TranslationMemoryItemModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/translationMemory/TranslationMemoryItemModelAssembler.kt index 4784d9731c..5b40f036d5 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/translationMemory/TranslationMemoryItemModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/translationMemory/TranslationMemoryItemModelAssembler.kt @@ -9,14 +9,15 @@ import org.springframework.stereotype.Component @Component class TranslationMemoryItemModelAssembler : RepresentationModelAssemblerSupport( - TagsController::class.java, TranslationMemoryItemModel::class.java + TagsController::class.java, + TranslationMemoryItemModel::class.java, ) { override fun toModel(entity: TranslationMemoryItemView): TranslationMemoryItemModel { return TranslationMemoryItemModel( targetText = entity.targetTranslationText, baseText = entity.baseTranslationText, keyName = entity.keyName, - similarity = entity.similarity + similarity = entity.similarity, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/KeyWithTranslationsModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/KeyWithTranslationsModel.kt index 1926598d23..efe7e1b7b4 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/KeyWithTranslationsModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/KeyWithTranslationsModel.kt @@ -11,28 +11,20 @@ import org.springframework.hateoas.server.core.Relation open class KeyWithTranslationsModel( @Schema(description = "Id of key record") val keyId: Long, - @Schema(description = "Name of key", example = "this_is_super_key") val keyName: String, - @Schema(description = "The namespace id of the key", example = "100000282") val keyNamespaceId: Long?, - @Schema(description = "The namespace of the key", example = "homepage") val keyNamespace: String?, - @Schema(description = "Tags of key") val keyTags: List, - @Schema(description = "Count of screenshots provided for the key", example = "1") val screenshotCount: Long, - @Schema(description = "Key screenshots. Not provided when API key hasn't screenshots.view scope permission.") val screenshots: List?, - @Schema(description = "There is a context available for this key") val contextPresent: Boolean, - @Schema( description = "Translations object", example = """ @@ -44,7 +36,7 @@ open class KeyWithTranslationsModel( "commentCount": 1 } } - """ + """, ) - val translations: Map + val translations: Map, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/KeyWithTranslationsModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/KeyWithTranslationsModelAssembler.kt index 3149ed02c8..af81345733 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/KeyWithTranslationsModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/KeyWithTranslationsModelAssembler.kt @@ -11,23 +11,27 @@ import org.springframework.stereotype.Component class KeyWithTranslationsModelAssembler( private val translationViewModelAssembler: TranslationViewModelAssembler, private val tagModelAssembler: TagModelAssembler, - private val screenshotModelAssembler: ScreenshotModelAssembler + private val screenshotModelAssembler: ScreenshotModelAssembler, ) : RepresentationModelAssemblerSupport( - TranslationsController::class.java, KeyWithTranslationsModel::class.java -) { - override fun toModel(view: KeyWithTranslationsView) = KeyWithTranslationsModel( - keyId = view.keyId, - keyName = view.keyName, - keyNamespaceId = view.keyNamespaceId, - keyNamespace = view.keyNamespace, - keyTags = view.keyTags.map { tagModelAssembler.toModel(it) }, - contextPresent = view.contextPresent, - translations = view.translations.map { - it.key to translationViewModelAssembler.toModel(it.value) - }.toMap(), - screenshotCount = view.screenshotCount, - screenshots = view.screenshots?.map { - screenshotModelAssembler.toModel(it) - } - ) + TranslationsController::class.java, + KeyWithTranslationsModel::class.java, + ) { + override fun toModel(view: KeyWithTranslationsView) = + KeyWithTranslationsModel( + keyId = view.keyId, + keyName = view.keyName, + keyNamespaceId = view.keyNamespaceId, + keyNamespace = view.keyNamespace, + keyTags = view.keyTags.map { tagModelAssembler.toModel(it) }, + contextPresent = view.contextPresent, + translations = + view.translations.map { + it.key to translationViewModelAssembler.toModel(it.value) + }.toMap(), + screenshotCount = view.screenshotCount, + screenshots = + view.screenshots?.map { + screenshotModelAssembler.toModel(it) + }, + ) } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/KeysWithTranslationsPageModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/KeysWithTranslationsPageModel.kt index 91ff0b4bc1..fbb31926ae 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/KeysWithTranslationsPageModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/KeysWithTranslationsPageModel.kt @@ -11,12 +11,12 @@ class KeysWithTranslationsPageModel( metadata: PageMetadata?, vararg links: Link, @field:Schema( - description = "Provided languages data" + description = "Provided languages data", ) val selectedLanguages: Collection, @field:Schema( description = "Cursor to get next data", - example = "eyJrZXlJZCI6eyJkaXJlY3Rpb24iOiJBU0MiLCJ2YWx1ZSI6IjEwMDAwMDAxMjAifX0=" + example = "eyJrZXlJZCI6eyJkaXJlY3Rpb24iOiJBU0MiLCJ2YWx1ZSI6IjEwMDAwMDAxMjAifX0=", ) - val nextCursor: String? + val nextCursor: String?, ) : PagedModel(content, metadata, links.toList()) diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/KeysWithTranslationsPagedResourcesAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/KeysWithTranslationsPagedResourcesAssembler.kt index c16ae2b84a..aab524e287 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/KeysWithTranslationsPagedResourcesAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/KeysWithTranslationsPagedResourcesAssembler.kt @@ -22,21 +22,22 @@ class KeysWithTranslationsPagedResourcesAssembler( entities: Page, selectedLanguages: Collection, nextCursor: String?, - baseLanguage: Language? + baseLanguage: Language?, ): KeysWithTranslationsPageModel { val pageModel = toModel(entities, keyWithTranslationsModelAssembler) return KeysWithTranslationsPageModel( content = pageModel.content, metadata = pageModel.metadata, links = pageModel.links.toList().toTypedArray(), - selectedLanguages = selectedLanguages.map { - languageModelAssembler.toModel( - LanguageViewImpl( - it, - it.id == baseLanguage?.id + selectedLanguages = + selectedLanguages.map { + languageModelAssembler.toModel( + LanguageViewImpl( + it, + it.id == baseLanguage?.id, + ), ) - ) - }, + }, nextCursor = nextCursor, ) } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/SetTranslationsResponseModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/SetTranslationsResponseModel.kt index 079819704b..c77091a8de 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/SetTranslationsResponseModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/SetTranslationsResponseModel.kt @@ -9,16 +9,13 @@ import org.springframework.hateoas.server.core.Relation open class SetTranslationsResponseModel( @Schema(description = "Id of key record") val keyId: Long, - @Schema(description = "Name of key", example = "this_is_super_key") val keyName: String, - @Schema(description = "The namespace of the key", example = "homepage") val keyNamespace: String?, - @Schema( description = "Translations object containing values updated in this request", - example = "{\"en\": {\"id\": 100000003, \"text\": \"This is super translation!\" }}" + example = "{\"en\": {\"id\": 100000003, \"text\": \"This is super translation!\" }}", ) - val translations: Map + val translations: Map, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationHistoryModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationHistoryModel.kt index 0198280d0b..927a256224 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationHistoryModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationHistoryModel.kt @@ -3,7 +3,7 @@ package io.tolgee.hateoas.translations import io.swagger.v3.oas.annotations.media.Schema import io.tolgee.activity.data.PropertyModification import io.tolgee.activity.data.RevisionType -import io.tolgee.hateoas.user_account.SimpleUserAccountModel +import io.tolgee.hateoas.userAccount.SimpleUserAccountModel import org.springframework.hateoas.RepresentationModel import org.springframework.hateoas.server.core.Relation @@ -12,12 +12,9 @@ import org.springframework.hateoas.server.core.Relation open class TranslationHistoryModel( @Schema(description = "Modified fields") val modifications: Map? = null, - @Schema(description = "Unix timestamp of the revision") val timestamp: Long, - @Schema(description = "Author of the change") val author: SimpleUserAccountModel?, - - val revisionType: RevisionType + val revisionType: RevisionType, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationHistoryModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationHistoryModelAssembler.kt index 6d20441ca2..0ad5b01ec8 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationHistoryModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationHistoryModelAssembler.kt @@ -1,8 +1,8 @@ package io.tolgee.hateoas.translations import io.tolgee.api.v2.controllers.translation.TranslationsController -import io.tolgee.dtos.query_results.TranslationHistoryView -import io.tolgee.hateoas.user_account.SimpleUserAccountModel +import io.tolgee.dtos.queryResults.TranslationHistoryView +import io.tolgee.hateoas.userAccount.SimpleUserAccountModel import io.tolgee.service.AvatarService import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport import org.springframework.stereotype.Component @@ -11,24 +11,26 @@ import org.springframework.stereotype.Component class TranslationHistoryModelAssembler( private val avatarService: AvatarService, ) : RepresentationModelAssemblerSupport( - TranslationsController::class.java, TranslationHistoryModel::class.java -) { + TranslationsController::class.java, + TranslationHistoryModel::class.java, + ) { override fun toModel(view: TranslationHistoryView): TranslationHistoryModel { val avatar = avatarService.getAvatarLinks(view.authorAvatarHash) return TranslationHistoryModel( modifications = view.modifications, - author = view.authorId?.let { - SimpleUserAccountModel( - id = it, - name = view.authorName, - username = view.authorEmail ?: "", - avatar = avatar, - deleted = view.authorDeletedAt != null - ) - }, + author = + view.authorId?.let { + SimpleUserAccountModel( + id = it, + name = view.authorName, + username = view.authorEmail ?: "", + avatar = avatar, + deleted = view.authorDeletedAt != null, + ) + }, timestamp = view.timestamp.time, - revisionType = view.revisionType + revisionType = view.revisionType, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationModel.kt index 9a5f7fa3c1..bd160f241a 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationModel.kt @@ -11,19 +11,14 @@ import org.springframework.hateoas.server.core.Relation open class TranslationModel( @Schema(description = "Id of translation record") val id: Long, - @Schema(description = "Translation text") val text: String?, - @Schema(description = "State of translation") val state: TranslationState, - @Schema(description = "Whether base language translation was changed after this translation was updated") val outdated: Boolean, - @Schema(description = "Was translated using Translation Memory or Machine translation service?") val auto: Boolean, - @Schema(description = "Which machine translation service was used to auto translate this") val mtProvider: MtServiceType?, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationModelAssembler.kt index c2da230d92..9cef64b8af 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationModelAssembler.kt @@ -7,7 +7,8 @@ import org.springframework.stereotype.Component @Component class TranslationModelAssembler : RepresentationModelAssemblerSupport( - TranslationsController::class.java, TranslationModel::class.java + TranslationsController::class.java, + TranslationModel::class.java, ) { override fun toModel(entity: Translation): TranslationModel { return TranslationModel( @@ -16,7 +17,7 @@ class TranslationModelAssembler : RepresentationModelAssemblerSupport(), Serializable diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationViewModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationViewModel.kt index 62f4c8f418..af29a9ebe7 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationViewModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationViewModel.kt @@ -11,29 +11,21 @@ import org.springframework.hateoas.server.core.Relation open class TranslationViewModel( @Schema(description = "Id of translation record") val id: Long, - @Schema(description = "Translation text") val text: String?, - @Schema(description = "State of translation") val state: TranslationState, - @Schema(description = "Whether base language translation was changed after this translation was updated") val outdated: Boolean, - @Schema(description = "Was translated using Translation Memory or Machine translation service?") val auto: Boolean, - @Schema(description = "Which machine translation service was used to auto translate this") val mtProvider: MtServiceType?, - @Schema(description = "Count of translation comments") val commentCount: Long, - @Schema(description = "Count of unresolved translation comments") - val unresolvedCommentCount: Long + val unresolvedCommentCount: Long, ) : RepresentationModel() { - @get:Schema(description = "Was translation memory used to translate this?") val fromTranslationMemory: Boolean get() = auto && mtProvider == null diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationViewModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationViewModelAssembler.kt index 7eda8e12f5..fbd2c4763d 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationViewModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/TranslationViewModelAssembler.kt @@ -7,7 +7,8 @@ import org.springframework.stereotype.Component @Component class TranslationViewModelAssembler : RepresentationModelAssemblerSupport( - TranslationsController::class.java, TranslationViewModel::class.java + TranslationsController::class.java, + TranslationViewModel::class.java, ) { override fun toModel(view: TranslationView): TranslationViewModel { return TranslationViewModel( @@ -18,7 +19,7 @@ class TranslationViewModelAssembler : RepresentationModelAssemblerSupport(), Serializable diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/comments/TranslationCommentModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/comments/TranslationCommentModel.kt index dfe6d0e11d..5cf0b21541 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/comments/TranslationCommentModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/comments/TranslationCommentModel.kt @@ -1,7 +1,7 @@ package io.tolgee.hateoas.translations.comments import io.swagger.v3.oas.annotations.media.Schema -import io.tolgee.hateoas.user_account.SimpleUserAccountModel +import io.tolgee.hateoas.userAccount.SimpleUserAccountModel import io.tolgee.model.enums.TranslationCommentState import org.springframework.hateoas.RepresentationModel import org.springframework.hateoas.server.core.Relation @@ -12,19 +12,14 @@ import java.util.* open class TranslationCommentModel( @Schema(description = "Id of translation comment record") val id: Long, - @Schema(description = "Text of comment") val text: String, - @Schema(description = "State of translation") val state: TranslationCommentState, - @Schema(description = "User who created the comment") val author: SimpleUserAccountModel, - @Schema(description = "Date when it was created") val createdAt: Date, - @Schema(description = "Date when it was updated") val updatedAt: Date, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/comments/TranslationCommentModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/comments/TranslationCommentModelAssembler.kt index ae623a6dcb..837eee67ca 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/comments/TranslationCommentModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/comments/TranslationCommentModelAssembler.kt @@ -1,7 +1,7 @@ package io.tolgee.hateoas.translations.comments import io.tolgee.api.v2.controllers.translation.TranslationCommentController -import io.tolgee.hateoas.user_account.SimpleUserAccountModelAssembler +import io.tolgee.hateoas.userAccount.SimpleUserAccountModelAssembler import io.tolgee.model.translation.TranslationComment import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport import org.springframework.stereotype.Component @@ -9,10 +9,11 @@ import java.util.* @Component class TranslationCommentModelAssembler( - private val simpleUserAccountModelAssembler: SimpleUserAccountModelAssembler + private val simpleUserAccountModelAssembler: SimpleUserAccountModelAssembler, ) : RepresentationModelAssemblerSupport( - TranslationCommentController::class.java, TranslationCommentModel::class.java -) { + TranslationCommentController::class.java, + TranslationCommentModel::class.java, + ) { override fun toModel(entity: TranslationComment): TranslationCommentModel { return TranslationCommentModel( id = entity.id, @@ -20,7 +21,7 @@ class TranslationCommentModelAssembler( state = entity.state, author = entity.author.let { simpleUserAccountModelAssembler.toModel(it) }, createdAt = entity.createdAt ?: Date(), - updatedAt = entity.updatedAt ?: Date() + updatedAt = entity.updatedAt ?: Date(), ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/comments/TranslationWithCommentModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/comments/TranslationWithCommentModel.kt index fef98ffe07..a63231b03f 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/comments/TranslationWithCommentModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/translations/comments/TranslationWithCommentModel.kt @@ -4,5 +4,5 @@ import io.tolgee.hateoas.translations.TranslationModel data class TranslationWithCommentModel( val translation: TranslationModel, - val comment: TranslationCommentModel + val comment: TranslationCommentModel, ) diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/uploadedImage/UploadedImageModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/uploadedImage/UploadedImageModel.kt index 7f0052077c..272e1c27d9 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/uploadedImage/UploadedImageModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/uploadedImage/UploadedImageModel.kt @@ -12,5 +12,5 @@ open class UploadedImageModel( val fileUrl: String, val requestFilename: String, val createdAt: Date, - val location: String? = null + val location: String? = null, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/uploadedImage/UploadedImageModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/uploadedImage/UploadedImageModelAssembler.kt index 7547ea1dff..b2c6fefbbc 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/uploadedImage/UploadedImageModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/uploadedImage/UploadedImageModelAssembler.kt @@ -18,21 +18,23 @@ class UploadedImageModelAssembler( private val projectHolder: ProjectHolder, private val jwtService: JwtService, ) : RepresentationModelAssemblerSupport( - TranslationsController::class.java, UploadedImageModel::class.java -) { + TranslationsController::class.java, + UploadedImageModel::class.java, + ) { override fun toModel(entity: UploadedImage): UploadedImageModel { var filename = entity.filenameWithExtension if (tolgeeProperties.authentication.securedImageRetrieval) { - val token = jwtService.emitTicket( - authenticationFacade.authenticatedUser.id, - JwtService.TicketType.IMG_ACCESS, - tolgeeProperties.authentication.securedImageTimestampMaxAge, - mapOf( - "fileName" to entity.filenameWithExtension, - "projectId" to projectHolder.projectOrNull?.id?.toString(), + val token = + jwtService.emitTicket( + authenticationFacade.authenticatedUser.id, + JwtService.TicketType.IMG_ACCESS, + tolgeeProperties.authentication.securedImageTimestampMaxAge, + mapOf( + "fileName" to entity.filenameWithExtension, + "projectId" to projectHolder.projectOrNull?.id?.toString(), + ), ) - ) filename = "$filename?token=$token" } @@ -40,8 +42,9 @@ class UploadedImageModelAssembler( var fileUrl = "${tolgeeProperties.fileStorageUrl}/${FileStoragePath.UPLOADED_IMAGES}/$filename" if (!fileUrl.matches(Regex("^https?://.*$"))) { val builder = ServletUriComponentsBuilder.fromCurrentRequestUri() - fileUrl = builder.replacePath(fileUrl) - .replaceQuery("").build().toUriString() + fileUrl = + builder.replacePath(fileUrl) + .replaceQuery("").build().toUriString() } return UploadedImageModel( @@ -50,7 +53,7 @@ class UploadedImageModelAssembler( fileUrl = fileUrl, filename = entity.filename, createdAt = entity.createdAt!!, - location = entity.location + location = entity.location, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/PrivateUserAccountModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/PrivateUserAccountModel.kt similarity index 94% rename from backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/PrivateUserAccountModel.kt rename to backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/PrivateUserAccountModel.kt index 7b03ba6f3e..2f9c3a6a9a 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/PrivateUserAccountModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/PrivateUserAccountModel.kt @@ -1,4 +1,4 @@ -package io.tolgee.hateoas.user_account +package io.tolgee.hateoas.userAccount import io.tolgee.dtos.Avatar import io.tolgee.model.UserAccount diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/PrivateUserAccountModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/PrivateUserAccountModelAssembler.kt similarity index 90% rename from backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/PrivateUserAccountModelAssembler.kt rename to backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/PrivateUserAccountModelAssembler.kt index e3b5d75904..54264f74d0 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/PrivateUserAccountModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/PrivateUserAccountModelAssembler.kt @@ -1,4 +1,4 @@ -package io.tolgee.hateoas.user_account +package io.tolgee.hateoas.userAccount import io.tolgee.api.v2.controllers.V2UserController import io.tolgee.model.UserAccount @@ -12,8 +12,9 @@ class PrivateUserAccountModelAssembler( private val avatarService: AvatarService, private val mfaService: MfaService, ) : RepresentationModelAssemblerSupport( - V2UserController::class.java, PrivateUserAccountModel::class.java -) { + V2UserController::class.java, + PrivateUserAccountModel::class.java, + ) { override fun toModel(entity: UserAccount): PrivateUserAccountModel { val avatar = avatarService.getAvatarLinks(entity.avatarHash) diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/SimpleUserAccountModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/SimpleUserAccountModel.kt similarity index 80% rename from backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/SimpleUserAccountModel.kt rename to backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/SimpleUserAccountModel.kt index c9c561efb4..ecf53b02e4 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/SimpleUserAccountModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/SimpleUserAccountModel.kt @@ -1,4 +1,4 @@ -package io.tolgee.hateoas.user_account +package io.tolgee.hateoas.userAccount import io.tolgee.dtos.Avatar import org.springframework.hateoas.RepresentationModel @@ -8,5 +8,5 @@ data class SimpleUserAccountModel( val username: String, var name: String?, var avatar: Avatar?, - var deleted: Boolean + var deleted: Boolean, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/SimpleUserAccountModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/SimpleUserAccountModelAssembler.kt similarity index 80% rename from backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/SimpleUserAccountModelAssembler.kt rename to backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/SimpleUserAccountModelAssembler.kt index 97a04929c4..f7c10b3a56 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/SimpleUserAccountModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/SimpleUserAccountModelAssembler.kt @@ -1,4 +1,4 @@ -package io.tolgee.hateoas.user_account +package io.tolgee.hateoas.userAccount import io.tolgee.api.v2.controllers.V2UserController import io.tolgee.dtos.cacheable.UserAccountDto @@ -9,10 +9,11 @@ import org.springframework.stereotype.Component @Component class SimpleUserAccountModelAssembler( - private val avatarService: AvatarService + private val avatarService: AvatarService, ) : RepresentationModelAssemblerSupport( - V2UserController::class.java, SimpleUserAccountModel::class.java -) { + V2UserController::class.java, + SimpleUserAccountModel::class.java, + ) { override fun toModel(entity: UserAccount): SimpleUserAccountModel { val avatar = avatarService.getAvatarLinks(entity.avatarHash) @@ -21,7 +22,7 @@ class SimpleUserAccountModelAssembler( username = entity.username, name = entity.name, avatar = avatar, - deleted = entity.deletedAt != null + deleted = entity.deletedAt != null, ) } @@ -33,7 +34,7 @@ class SimpleUserAccountModelAssembler( username = dto.username, name = dto.name, avatar = avatar, - deleted = dto.deleted + deleted = dto.deleted, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/UserAccountInProjectModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountInProjectModel.kt similarity index 93% rename from backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/UserAccountInProjectModel.kt rename to backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountInProjectModel.kt index 12139601d3..53b3169e97 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/UserAccountInProjectModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountInProjectModel.kt @@ -1,4 +1,4 @@ -package io.tolgee.hateoas.user_account +package io.tolgee.hateoas.userAccount import io.swagger.v3.oas.annotations.media.Schema import io.tolgee.dtos.Avatar @@ -19,7 +19,7 @@ data class UserAccountInProjectModel( val directPermission: PermissionModel?, @Schema( description = "Actual user's permissions on selected project. You can not sort data by this column!", - example = "EDIT" + example = "EDIT", ) val computedPermission: ComputedPermissionModel, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/UserAccountInProjectModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountInProjectModelAssembler.kt similarity index 78% rename from backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/UserAccountInProjectModelAssembler.kt rename to backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountInProjectModelAssembler.kt index ee61096e6a..64fdfd529d 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/UserAccountInProjectModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountInProjectModelAssembler.kt @@ -1,4 +1,4 @@ -package io.tolgee.hateoas.user_account +package io.tolgee.hateoas.userAccount import io.tolgee.api.v2.controllers.V2UserController import io.tolgee.hateoas.permission.ComputedPermissionModelAssembler @@ -15,17 +15,19 @@ class UserAccountInProjectModelAssembler( private val permissionService: PermissionService, private val permissionModelAssembler: PermissionModelAssembler, private val computedPermissionModelAssembler: ComputedPermissionModelAssembler, - private val avatarService: AvatarService + private val avatarService: AvatarService, ) : RepresentationModelAssemblerSupport( - V2UserController::class.java, UserAccountInProjectModel::class.java -) { + V2UserController::class.java, + UserAccountInProjectModel::class.java, + ) { override fun toModel(view: ExtendedUserAccountInProject): UserAccountInProjectModel { - val computedPermissions = permissionService.computeProjectPermission( - view.organizationRole, - view.organizationBasePermission, - view.directPermission, - UserAccount.Role.USER - ) + val computedPermissions = + permissionService.computeProjectPermission( + view.organizationRole, + view.organizationBasePermission, + view.directPermission, + UserAccount.Role.USER, + ) val avatar = avatarService.getAvatarLinks(view.avatarHash) return UserAccountInProjectModel( id = view.id, @@ -35,7 +37,7 @@ class UserAccountInProjectModelAssembler( organizationBasePermission = permissionModelAssembler.toModel(view.organizationBasePermission), directPermission = view.directPermission?.let { permissionModelAssembler.toModel(it) }, computedPermission = computedPermissionModelAssembler.toModel(computedPermissions), - avatar = avatar + avatar = avatar, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/UserAccountModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountModel.kt similarity index 93% rename from backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/UserAccountModel.kt rename to backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountModel.kt index 8f20c400cd..e71686d37c 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/UserAccountModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountModel.kt @@ -1,4 +1,4 @@ -package io.tolgee.hateoas.user_account +package io.tolgee.hateoas.userAccount import io.tolgee.dtos.Avatar import io.tolgee.model.UserAccount diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/UserAccountModelAssembler.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountModelAssembler.kt similarity index 84% rename from backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/UserAccountModelAssembler.kt rename to backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountModelAssembler.kt index 7d647814e5..d620ddd7d6 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/user_account/UserAccountModelAssembler.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/userAccount/UserAccountModelAssembler.kt @@ -1,4 +1,4 @@ -package io.tolgee.hateoas.user_account +package io.tolgee.hateoas.userAccount import io.tolgee.api.v2.controllers.V2UserController import io.tolgee.model.UserAccount @@ -8,10 +8,11 @@ import org.springframework.stereotype.Component @Component class UserAccountModelAssembler( - private val avatarService: AvatarService + private val avatarService: AvatarService, ) : RepresentationModelAssemblerSupport( - V2UserController::class.java, UserAccountModel::class.java -) { + V2UserController::class.java, + UserAccountModel::class.java, + ) { override fun toModel(entity: UserAccount): UserAccountModel { val avatar = avatarService.getAvatarLinks(entity.avatarHash) diff --git a/backend/api/src/main/kotlin/io/tolgee/hateoas/userPreferences/UserPreferencesModel.kt b/backend/api/src/main/kotlin/io/tolgee/hateoas/userPreferences/UserPreferencesModel.kt index b5fba81939..652fb43cf6 100644 --- a/backend/api/src/main/kotlin/io/tolgee/hateoas/userPreferences/UserPreferencesModel.kt +++ b/backend/api/src/main/kotlin/io/tolgee/hateoas/userPreferences/UserPreferencesModel.kt @@ -4,5 +4,5 @@ import org.springframework.hateoas.RepresentationModel class UserPreferencesModel( var language: String?, - var preferredOrganizationId: Long? + var preferredOrganizationId: Long?, ) : RepresentationModel() diff --git a/backend/api/src/main/kotlin/io/tolgee/security/third_party/GithubOAuthDelegate.kt b/backend/api/src/main/kotlin/io/tolgee/security/thirdParty/GithubOAuthDelegate.kt similarity index 61% rename from backend/api/src/main/kotlin/io/tolgee/security/third_party/GithubOAuthDelegate.kt rename to backend/api/src/main/kotlin/io/tolgee/security/thirdParty/GithubOAuthDelegate.kt index 37dba03450..0bc883c9aa 100644 --- a/backend/api/src/main/kotlin/io/tolgee/security/third_party/GithubOAuthDelegate.kt +++ b/backend/api/src/main/kotlin/io/tolgee/security/thirdParty/GithubOAuthDelegate.kt @@ -1,4 +1,4 @@ -package io.tolgee.security.third_party +package io.tolgee.security.thirdParty import io.tolgee.configuration.tolgee.GithubAuthenticationProperties import io.tolgee.configuration.tolgee.TolgeeProperties @@ -24,64 +24,74 @@ class GithubOAuthDelegate( private val userAccountService: UserAccountService, private val restTemplate: RestTemplate, properties: TolgeeProperties, - private val signUpService: SignUpService + private val signUpService: SignUpService, ) { private val githubConfigurationProperties: GithubAuthenticationProperties = properties.authentication.github - fun getTokenResponse(receivedCode: String?, invitationCode: String?): JwtAuthenticationResponse { + fun getTokenResponse( + receivedCode: String?, + invitationCode: String?, + ): JwtAuthenticationResponse { val body = HashMap() body["client_id"] = githubConfigurationProperties.clientId body["client_secret"] = githubConfigurationProperties.clientSecret body["code"] = receivedCode // get token to authorize to github api - val response: MutableMap<*, *>? = restTemplate - .postForObject(githubConfigurationProperties.authorizationUrl, body, MutableMap::class.java) + val response: MutableMap<*, *>? = + restTemplate + .postForObject(githubConfigurationProperties.authorizationUrl, body, MutableMap::class.java) if (response != null && response.containsKey("access_token")) { val headers = HttpHeaders() headers["Authorization"] = "token " + response["access_token"] val entity = HttpEntity(null, headers) // get github user data - val exchange = restTemplate - .exchange(githubConfigurationProperties.userUrl, HttpMethod.GET, entity, GithubUserResponse::class.java) + val exchange = + restTemplate + .exchange(githubConfigurationProperties.userUrl, HttpMethod.GET, entity, GithubUserResponse::class.java) if (exchange.statusCode != HttpStatus.OK || exchange.body == null) { throw AuthenticationException(Message.THIRD_PARTY_UNAUTHORIZED) } val userResponse = exchange.body // get github user emails - val emails = restTemplate.exchange( - githubConfigurationProperties.userUrl + "/emails", HttpMethod.GET, entity, - Array::class.java - ).body - ?: throw AuthenticationException(Message.THIRD_PARTY_AUTH_NO_EMAIL) + val emails = + restTemplate.exchange( + githubConfigurationProperties.userUrl + "/emails", + HttpMethod.GET, + entity, + Array::class.java, + ).body + ?: throw AuthenticationException(Message.THIRD_PARTY_AUTH_NO_EMAIL) val verifiedEmails = Arrays.stream(emails).filter { it.verified }.collect(Collectors.toList()) - val githubEmail = ( - verifiedEmails.firstOrNull { it.primary } - ?: verifiedEmails.firstOrNull() + val githubEmail = + ( + verifiedEmails.firstOrNull { it.primary } + ?: verifiedEmails.firstOrNull() )?.email - ?: throw AuthenticationException(Message.THIRD_PARTY_AUTH_NO_EMAIL) + ?: throw AuthenticationException(Message.THIRD_PARTY_AUTH_NO_EMAIL) val userAccountOptional = userAccountService.findByThirdParty("github", userResponse!!.id!!) - val user = userAccountOptional.orElseGet { - userAccountService.findActive(githubEmail)?.let { - throw AuthenticationException(Message.USERNAME_ALREADY_EXISTS) + val user = + userAccountOptional.orElseGet { + userAccountService.findActive(githubEmail)?.let { + throw AuthenticationException(Message.USERNAME_ALREADY_EXISTS) + } + + val newUserAccount = UserAccount() + newUserAccount.username = githubEmail + newUserAccount.name = userResponse.name ?: userResponse.login + newUserAccount.thirdPartyAuthId = userResponse.id + newUserAccount.thirdPartyAuthType = "github" + newUserAccount.accountType = UserAccount.AccountType.THIRD_PARTY + + signUpService.signUp(newUserAccount, invitationCode, null) + + newUserAccount } - - val newUserAccount = UserAccount() - newUserAccount.username = githubEmail - newUserAccount.name = userResponse.name ?: userResponse.login - newUserAccount.thirdPartyAuthId = userResponse.id - newUserAccount.thirdPartyAuthType = "github" - newUserAccount.accountType = UserAccount.AccountType.THIRD_PARTY - - signUpService.signUp(newUserAccount, invitationCode, null) - - newUserAccount - } val jwt = jwtService.emitToken(user.id) return JwtAuthenticationResponse(jwt) } diff --git a/backend/api/src/main/kotlin/io/tolgee/security/third_party/GoogleOAuthDelegate.kt b/backend/api/src/main/kotlin/io/tolgee/security/thirdParty/GoogleOAuthDelegate.kt similarity index 74% rename from backend/api/src/main/kotlin/io/tolgee/security/third_party/GoogleOAuthDelegate.kt rename to backend/api/src/main/kotlin/io/tolgee/security/thirdParty/GoogleOAuthDelegate.kt index 290d2cd381..464d89b5f7 100644 --- a/backend/api/src/main/kotlin/io/tolgee/security/third_party/GoogleOAuthDelegate.kt +++ b/backend/api/src/main/kotlin/io/tolgee/security/thirdParty/GoogleOAuthDelegate.kt @@ -1,4 +1,4 @@ -package io.tolgee.security.third_party +package io.tolgee.security.thirdParty import io.tolgee.configuration.tolgee.GoogleAuthenticationProperties import io.tolgee.configuration.tolgee.TolgeeProperties @@ -23,14 +23,14 @@ class GoogleOAuthDelegate( private val userAccountService: UserAccountService, private val restTemplate: RestTemplate, properties: TolgeeProperties, - private val signUpService: SignUpService + private val signUpService: SignUpService, ) { private val googleConfigurationProperties: GoogleAuthenticationProperties = properties.authentication.google fun getTokenResponse( receivedCode: String?, invitationCode: String?, - redirectUri: String? + redirectUri: String?, ): JwtAuthenticationResponse { try { val body = HashMap() @@ -41,8 +41,9 @@ class GoogleOAuthDelegate( body["redirect_uri"] = redirectUri // get token to authorize to google api - val response: MutableMap<*, *>? = restTemplate - .postForObject(googleConfigurationProperties.authorizationUrl, body, MutableMap::class.java) + val response: MutableMap<*, *>? = + restTemplate + .postForObject(googleConfigurationProperties.authorizationUrl, body, MutableMap::class.java) if (response != null && response.containsKey("access_token")) { val headers = HttpHeaders() headers["Authorization"] = "Bearer " + response["access_token"] @@ -50,8 +51,9 @@ class GoogleOAuthDelegate( // get google user data - val exchange = restTemplate - .exchange(googleConfigurationProperties.userUrl, HttpMethod.GET, entity, GoogleUserResponse::class.java) + val exchange = + restTemplate + .exchange(googleConfigurationProperties.userUrl, HttpMethod.GET, entity, GoogleUserResponse::class.java) if (exchange.statusCode != HttpStatus.OK || exchange.body == null) { throw AuthenticationException(Message.THIRD_PARTY_UNAUTHORIZED) } @@ -72,22 +74,23 @@ class GoogleOAuthDelegate( val googleEmail = userResponse.email ?: throw AuthenticationException(Message.THIRD_PARTY_AUTH_NO_EMAIL) val userAccountOptional = userAccountService.findByThirdParty("google", userResponse!!.sub!!) - val user = userAccountOptional.orElseGet { - userAccountService.findActive(googleEmail)?.let { - throw AuthenticationException(Message.USERNAME_ALREADY_EXISTS) - } + val user = + userAccountOptional.orElseGet { + userAccountService.findActive(googleEmail)?.let { + throw AuthenticationException(Message.USERNAME_ALREADY_EXISTS) + } - val newUserAccount = UserAccount() - newUserAccount.username = userResponse.email - ?: throw AuthenticationException(Message.THIRD_PARTY_AUTH_NO_EMAIL) - newUserAccount.name = userResponse.name ?: (userResponse.given_name + " " + userResponse.family_name) - newUserAccount.thirdPartyAuthId = userResponse.sub - newUserAccount.thirdPartyAuthType = "google" - newUserAccount.accountType = UserAccount.AccountType.THIRD_PARTY - signUpService.signUp(newUserAccount, invitationCode, null) + val newUserAccount = UserAccount() + newUserAccount.username = userResponse.email + ?: throw AuthenticationException(Message.THIRD_PARTY_AUTH_NO_EMAIL) + newUserAccount.name = userResponse.name ?: (userResponse.given_name + " " + userResponse.family_name) + newUserAccount.thirdPartyAuthId = userResponse.sub + newUserAccount.thirdPartyAuthType = "google" + newUserAccount.accountType = UserAccount.AccountType.THIRD_PARTY + signUpService.signUp(newUserAccount, invitationCode, null) - newUserAccount - } + newUserAccount + } val jwt = jwtService.emitToken(user.id) return JwtAuthenticationResponse(jwt) } @@ -104,6 +107,7 @@ class GoogleOAuthDelegate( } } + @Suppress("PropertyName") class GoogleUserResponse { var sub: String? = null var name: String? = null diff --git a/backend/api/src/main/kotlin/io/tolgee/security/third_party/OAuth2Delegate.kt b/backend/api/src/main/kotlin/io/tolgee/security/thirdParty/OAuth2Delegate.kt similarity index 70% rename from backend/api/src/main/kotlin/io/tolgee/security/third_party/OAuth2Delegate.kt rename to backend/api/src/main/kotlin/io/tolgee/security/thirdParty/OAuth2Delegate.kt index 0d352cf008..11fd179c85 100644 --- a/backend/api/src/main/kotlin/io/tolgee/security/third_party/OAuth2Delegate.kt +++ b/backend/api/src/main/kotlin/io/tolgee/security/thirdParty/OAuth2Delegate.kt @@ -1,4 +1,4 @@ -package io.tolgee.security.third_party +package io.tolgee.security.thirdParty import io.tolgee.configuration.tolgee.OAuth2AuthenticationProperties import io.tolgee.configuration.tolgee.TolgeeProperties @@ -27,17 +27,17 @@ class OAuth2Delegate( private val userAccountService: UserAccountService, private val restTemplate: RestTemplate, properties: TolgeeProperties, - private val signUpService: SignUpService + private val signUpService: SignUpService, ) { private val oauth2ConfigurationProperties: OAuth2AuthenticationProperties = properties.authentication.oauth2 private val logger = LoggerFactory.getLogger(this::class.java) + fun getTokenResponse( receivedCode: String?, invitationCode: String?, - redirectUri: String? + redirectUri: String?, ): JwtAuthenticationResponse { try { - val body: MultiValueMap = LinkedMultiValueMap() body["client_id"] = oauth2ConfigurationProperties.clientId body["client_secret"] = oauth2ConfigurationProperties.clientSecret @@ -59,7 +59,7 @@ class OAuth2Delegate( restTemplate.postForObject( oauth2ConfigurationProperties.tokenUrl!!, HttpEntity(body, requestHeaders), - MutableMap::class.java + MutableMap::class.java, ) if (response != null && response.containsKey("access_token")) { @@ -67,12 +67,13 @@ class OAuth2Delegate( headers["Authorization"] = "Bearer ${response["access_token"]}" val entity = HttpEntity(null, headers) - val exchange = restTemplate.exchange( - oauth2ConfigurationProperties.userUrl!!, - HttpMethod.GET, - entity, - GenericUserResponse::class.java - ) + val exchange = + restTemplate.exchange( + oauth2ConfigurationProperties.userUrl!!, + HttpMethod.GET, + entity, + GenericUserResponse::class.java, + ) if (exchange.statusCode != HttpStatus.OK || exchange.body == null) { logger.error("Failed to get user info from OAuth2 provider") throw AuthenticationException(Message.THIRD_PARTY_UNAUTHORIZED) @@ -84,36 +85,38 @@ class OAuth2Delegate( throw AuthenticationException(Message.THIRD_PARTY_AUTH_NO_SUB) } - val email = userResponse.email ?: let { - logger.info("Third party user email is null. Missing scope email?") - throw AuthenticationException(Message.THIRD_PARTY_AUTH_NO_EMAIL) - } + val email = + userResponse.email ?: let { + logger.info("Third party user email is null. Missing scope email?") + throw AuthenticationException(Message.THIRD_PARTY_AUTH_NO_EMAIL) + } val userAccountOptional = userAccountService.findByThirdParty("oauth2", userResponse.sub!!) - val user = userAccountOptional.orElseGet { - userAccountService.findActive(email)?.let { - throw AuthenticationException(Message.USERNAME_ALREADY_EXISTS) - } + val user = + userAccountOptional.orElseGet { + userAccountService.findActive(email)?.let { + throw AuthenticationException(Message.USERNAME_ALREADY_EXISTS) + } - val newUserAccount = UserAccount() - newUserAccount.username = - userResponse.email ?: throw AuthenticationException(Message.THIRD_PARTY_AUTH_NO_EMAIL) + val newUserAccount = UserAccount() + newUserAccount.username = + userResponse.email ?: throw AuthenticationException(Message.THIRD_PARTY_AUTH_NO_EMAIL) - // build name for userAccount based on available fields by third party - var name = userResponse.email!!.split("@")[0] - if (userResponse.name != null) { - name = userResponse.name!! - } else if (userResponse.given_name != null && userResponse.family_name != null) { - name = "${userResponse.given_name} ${userResponse.family_name}" - } - newUserAccount.name = name - newUserAccount.thirdPartyAuthId = userResponse.sub - newUserAccount.thirdPartyAuthType = "oauth2" - newUserAccount.accountType = UserAccount.AccountType.THIRD_PARTY - signUpService.signUp(newUserAccount, invitationCode, null) + // build name for userAccount based on available fields by third party + var name = userResponse.email!!.split("@")[0] + if (userResponse.name != null) { + name = userResponse.name!! + } else if (userResponse.given_name != null && userResponse.family_name != null) { + name = "${userResponse.given_name} ${userResponse.family_name}" + } + newUserAccount.name = name + newUserAccount.thirdPartyAuthId = userResponse.sub + newUserAccount.thirdPartyAuthType = "oauth2" + newUserAccount.accountType = UserAccount.AccountType.THIRD_PARTY + signUpService.signUp(newUserAccount, invitationCode, null) - newUserAccount - } + newUserAccount + } val jwt = jwtService.emitToken(user.id) return JwtAuthenticationResponse(jwt) } @@ -132,6 +135,7 @@ class OAuth2Delegate( } } + @Suppress("PropertyName") class GenericUserResponse { var sub: String? = null var name: String? = null diff --git a/backend/api/src/main/kotlin/io/tolgee/util/ApplicationStopper.kt b/backend/api/src/main/kotlin/io/tolgee/util/ApplicationStopper.kt index d679cab147..cc0eb39118 100644 --- a/backend/api/src/main/kotlin/io/tolgee/util/ApplicationStopper.kt +++ b/backend/api/src/main/kotlin/io/tolgee/util/ApplicationStopper.kt @@ -13,9 +13,8 @@ import kotlin.system.exitProcess @Component class ApplicationStopper( val internalProperties: InternalProperties, - val applicationContext: ApplicationContext + val applicationContext: ApplicationContext, ) { - private val log = LoggerFactory.getLogger(ApplicationStopper::class.java) @EventListener(ApplicationReadyEvent::class) diff --git a/backend/api/src/main/kotlin/io/tolgee/websocket/ActivityWebsocketListener.kt b/backend/api/src/main/kotlin/io/tolgee/websocket/ActivityWebsocketListener.kt index 8e5bdb2b94..33a29574f0 100644 --- a/backend/api/src/main/kotlin/io/tolgee/websocket/ActivityWebsocketListener.kt +++ b/backend/api/src/main/kotlin/io/tolgee/websocket/ActivityWebsocketListener.kt @@ -10,7 +10,7 @@ import io.tolgee.batch.events.OnBatchJobSucceeded import io.tolgee.component.CurrentDateProvider import io.tolgee.constants.Message import io.tolgee.events.OnProjectActivityStoredEvent -import io.tolgee.hateoas.user_account.SimpleUserAccountModelAssembler +import io.tolgee.hateoas.userAccount.SimpleUserAccountModelAssembler import io.tolgee.model.activity.ActivityModifiedEntity import io.tolgee.model.activity.ActivityRevision import io.tolgee.model.batch.BatchJobStatus @@ -29,22 +29,22 @@ class ActivityWebsocketListener( private val simpleUserAccountModelAssembler: SimpleUserAccountModelAssembler, private val userAccountService: UserAccountService, private val relationDescriptionExtractor: RelationDescriptionExtractor, - private val currentDateProvider: CurrentDateProvider + private val currentDateProvider: CurrentDateProvider, ) { - @Async @EventListener fun onActivity(event: OnProjectActivityStoredEvent) { event.activityRevision.projectId ?: return - val translationDataModifications = event.activityRevision.modifiedEntities.filter { - it.entityClass == Key::class.simpleName || it.entityClass == Translation::class.simpleName - } + val translationDataModifications = + event.activityRevision.modifiedEntities.filter { + it.entityClass == Key::class.simpleName || it.entityClass == Translation::class.simpleName + } if (translationDataModifications.isNotEmpty()) { onTranslationDataModified( event.activityRevision, - translationDataModifications + translationDataModifications, ) } } @@ -54,7 +54,7 @@ class ActivityWebsocketListener( val user = userAccountService.findDto(userId) ?: return@let null ActorInfo( type = ActorType.USER, - data = simpleUserAccountModelAssembler.toModel(user) + data = simpleUserAccountModelAssembler.toModel(user), ) } ?: ActorInfo(type = ActorType.UNKNOWN, data = null) } @@ -63,16 +63,21 @@ class ActivityWebsocketListener( activityRevision: ActivityRevision, translationDataModifications: List, ) { - val data = if (translationDataModifications.size < 500) { - mapOf( - "keys" to translationDataModifications.filter { it.entityClass == Key::class.simpleName }.map { - getModifiedEntityView(it) - }, - "translations" to translationDataModifications.filter { it.entityClass == Translation::class.simpleName }.map { - getModifiedEntityView(it) - } - ) - } else null + val data = + if (translationDataModifications.size < 500) { + mapOf( + "keys" to + translationDataModifications.filter { it.entityClass == Key::class.simpleName }.map { + getModifiedEntityView(it) + }, + "translations" to + translationDataModifications.filter { it.entityClass == Translation::class.simpleName }.map { + getModifiedEntityView(it) + }, + ) + } else { + null + } websocketEventPublisher( "/projects/${activityRevision.projectId!!}/${WebsocketEventType.TRANSLATION_DATA_MODIFIED.typeName}", @@ -82,8 +87,8 @@ class ActivityWebsocketListener( sourceActivity = activityRevision.type, activityId = activityRevision.id, dataCollapsed = data == null, - timestamp = currentDateProvider.date.time - ) + timestamp = currentDateProvider.date.time, + ), ) } @@ -91,10 +96,12 @@ class ActivityWebsocketListener( fun onBatchJobProgress(event: OnBatchJobProgress) { if (event.job.hidden) return - val realStatus = if (event.job.status == BatchJobStatus.PENDING) - BatchJobStatus.RUNNING - else - event.job.status + val realStatus = + if (event.job.status == BatchJobStatus.PENDING) { + BatchJobStatus.RUNNING + } else { + event.job.status + } websocketEventPublisher( "/projects/${event.job.projectId}/${WebsocketEventType.BATCH_JOB_PROGRESS.typeName}", @@ -104,8 +111,8 @@ class ActivityWebsocketListener( sourceActivity = null, activityId = null, dataCollapsed = false, - timestamp = currentDateProvider.date.time - ) + timestamp = currentDateProvider.date.time, + ), ) } @@ -124,7 +131,10 @@ class ActivityWebsocketListener( onBatchJobCompleted(event) } - fun onBatchJobCompleted(event: OnBatchJobCompleted, errorMessage: Message? = null) { + fun onBatchJobCompleted( + event: OnBatchJobCompleted, + errorMessage: Message? = null, + ) { if (event.job.hidden && event.job.status != BatchJobStatus.FAILED) return websocketEventPublisher( @@ -135,8 +145,8 @@ class ActivityWebsocketListener( sourceActivity = null, activityId = null, dataCollapsed = false, - timestamp = currentDateProvider.date.time - ) + timestamp = currentDateProvider.date.time, + ), ) } @@ -145,12 +155,14 @@ class ActivityWebsocketListener( it.describingData?.let { describingData -> data.putAll(describingData) } data["modifications"] = it.modifications data["changeType"] = it.revisionType - data["relations"] = it.describingRelations?.map { relationsEntry -> - relationsEntry.key to relationDescriptionExtractor.extract( - relationsEntry.value, - it.activityRevision.describingRelations - ) - }?.toMap() + data["relations"] = + it.describingRelations?.map { relationsEntry -> + relationsEntry.key to + relationDescriptionExtractor.extract( + relationsEntry.value, + it.activityRevision.describingRelations, + ) + }?.toMap() return data } } diff --git a/backend/api/src/main/kotlin/io/tolgee/websocket/RedisWebsocketEventPublisher.kt b/backend/api/src/main/kotlin/io/tolgee/websocket/RedisWebsocketEventPublisher.kt index 5b4c326223..135aadea55 100644 --- a/backend/api/src/main/kotlin/io/tolgee/websocket/RedisWebsocketEventPublisher.kt +++ b/backend/api/src/main/kotlin/io/tolgee/websocket/RedisWebsocketEventPublisher.kt @@ -4,13 +4,16 @@ import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import org.springframework.data.redis.core.StringRedisTemplate class RedisWebsocketEventPublisher( - private val redisTemplate: StringRedisTemplate + private val redisTemplate: StringRedisTemplate, ) : WebsocketEventPublisher { - override operator fun invoke(destination: String, message: WebsocketEvent) { + override operator fun invoke( + destination: String, + message: WebsocketEvent, + ) { val messageString = jacksonObjectMapper().writeValueAsString(RedisWebsocketEventWrapper(destination, message)) redisTemplate.convertAndSend( "websocket", - messageString + messageString, ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/websocket/SimpleWebsocketEventPublisher.kt b/backend/api/src/main/kotlin/io/tolgee/websocket/SimpleWebsocketEventPublisher.kt index ad56cb073c..a4738bf957 100644 --- a/backend/api/src/main/kotlin/io/tolgee/websocket/SimpleWebsocketEventPublisher.kt +++ b/backend/api/src/main/kotlin/io/tolgee/websocket/SimpleWebsocketEventPublisher.kt @@ -5,7 +5,10 @@ import org.springframework.messaging.simp.SimpMessagingTemplate class SimpleWebsocketEventPublisher( private val websocketTemplate: SimpMessagingTemplate, ) : WebsocketEventPublisher { - override operator fun invoke(destination: String, message: WebsocketEvent) { + override operator fun invoke( + destination: String, + message: WebsocketEvent, + ) { websocketTemplate.convertAndSend(destination, message) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/websocket/WebSocketConfig.kt b/backend/api/src/main/kotlin/io/tolgee/websocket/WebSocketConfig.kt index 04955b9ede..92556cef47 100644 --- a/backend/api/src/main/kotlin/io/tolgee/websocket/WebSocketConfig.kt +++ b/backend/api/src/main/kotlin/io/tolgee/websocket/WebSocketConfig.kt @@ -33,35 +33,42 @@ class WebSocketConfig( } override fun configureClientInboundChannel(registration: ChannelRegistration) { - registration.interceptors(object : ChannelInterceptor { - override fun preSend(message: Message<*>, channel: MessageChannel): Message<*> { - val accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor::class.java) + registration.interceptors( + object : ChannelInterceptor { + override fun preSend( + message: Message<*>, + channel: MessageChannel, + ): Message<*> { + val accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor::class.java) - if (accessor?.command == StompCommand.CONNECT) { - val tokenString = accessor.getNativeHeader("jwtToken")?.firstOrNull() - accessor.user = if (tokenString == null) null else jwtService.validateToken(tokenString) - } - - if (accessor?.command == StompCommand.SUBSCRIBE) { - val projectId = accessor.destination?.let { - "/projects/([0-9]+)".toRegex().find(it)?.groupValues - ?.getOrNull(1)?.toLong() + if (accessor?.command == StompCommand.CONNECT) { + val tokenString = accessor.getNativeHeader("jwtToken")?.firstOrNull() + accessor.user = if (tokenString == null) null else jwtService.validateToken(tokenString) } - if (projectId != null) { - val user = (accessor.user as? TolgeeAuthentication)?.principal - ?: throw MessagingException("Unauthenticated") + if (accessor?.command == StompCommand.SUBSCRIBE) { + val projectId = + accessor.destination?.let { + "/projects/([0-9]+)".toRegex().find(it)?.groupValues + ?.getOrNull(1)?.toLong() + } + + if (projectId != null) { + val user = + (accessor.user as? TolgeeAuthentication)?.principal + ?: throw MessagingException("Unauthenticated") - try { - securityService.checkProjectPermissionNoApiKey(projectId = projectId, Scope.KEYS_VIEW, user) - } catch (e: Exception) { - throw MessagingException("Forbidden") + try { + securityService.checkProjectPermissionNoApiKey(projectId = projectId, Scope.KEYS_VIEW, user) + } catch (e: Exception) { + throw MessagingException("Forbidden") + } } } - } - return message - } - }) + return message + } + }, + ) } } diff --git a/backend/api/src/main/kotlin/io/tolgee/websocket/WebsocketPublisherConfiguration.kt b/backend/api/src/main/kotlin/io/tolgee/websocket/WebsocketPublisherConfiguration.kt index ec03f09fd0..e5d1b3b1e1 100644 --- a/backend/api/src/main/kotlin/io/tolgee/websocket/WebsocketPublisherConfiguration.kt +++ b/backend/api/src/main/kotlin/io/tolgee/websocket/WebsocketPublisherConfiguration.kt @@ -10,7 +10,7 @@ import org.springframework.messaging.simp.SimpMessagingTemplate @Configuration class WebsocketPublisherConfiguration( private val websocketProperties: WebsocketProperties, - private val applicationContext: ApplicationContext + private val applicationContext: ApplicationContext, ) { @Bean fun websocketEventPublisher(): WebsocketEventPublisher { diff --git a/backend/app/src/main/kotlin/io/tolgee/Application.kt b/backend/app/src/main/kotlin/io/tolgee/Application.kt index d7c1577690..b5f6e432c0 100644 --- a/backend/app/src/main/kotlin/io/tolgee/Application.kt +++ b/backend/app/src/main/kotlin/io/tolgee/Application.kt @@ -11,7 +11,7 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories @SpringBootApplication( scanBasePackages = ["io.tolgee"], - exclude = [LdapAutoConfiguration::class] + exclude = [LdapAutoConfiguration::class], ) @EnableJpaAuditing @EntityScan("io.tolgee.model") diff --git a/backend/app/src/main/kotlin/io/tolgee/ExceptionHandlers.kt b/backend/app/src/main/kotlin/io/tolgee/ExceptionHandlers.kt index 969cd6b3f1..0e31267797 100644 --- a/backend/app/src/main/kotlin/io/tolgee/ExceptionHandlers.kt +++ b/backend/app/src/main/kotlin/io/tolgee/ExceptionHandlers.kt @@ -45,7 +45,7 @@ class ExceptionHandlers { @ExceptionHandler(MethodArgumentNotValidException::class) fun handleValidationExceptions( - ex: MethodArgumentNotValidException + ex: MethodArgumentNotValidException, ): ResponseEntity>> { val errors: MutableMap = HashMap() ex.bindingResult.allErrors.forEach( @@ -53,27 +53,25 @@ class ExceptionHandlers { val fieldName = (error as FieldError).field val errorMessage = error.getDefaultMessage() errors[fieldName] = errorMessage ?: "" - } + }, ) return ResponseEntity( Collections.singletonMap>(ValidationErrorType.STANDARD_VALIDATION.name, errors), - HttpStatus.BAD_REQUEST + HttpStatus.BAD_REQUEST, ) } @ExceptionHandler(MethodArgumentTypeMismatchException::class) - fun handleValidationExceptions( - ex: MethodArgumentTypeMismatchException - ): ResponseEntity { + fun handleValidationExceptions(ex: MethodArgumentTypeMismatchException): ResponseEntity { return ResponseEntity( ErrorResponseBody(Message.WRONG_PARAM_TYPE.code, listOf(ex.parameter.parameterName) as List?), - HttpStatus.BAD_REQUEST + HttpStatus.BAD_REQUEST, ) } @ExceptionHandler(ValidationException::class) fun handleCustomValidationExceptions( - ex: ValidationException + ex: ValidationException, ): ResponseEntity>>> { val errors: MutableMap> = HashMap() for (validationError in ex.validationErrors) { @@ -81,14 +79,12 @@ class ExceptionHandlers { } return ResponseEntity( Collections.singletonMap>>(ValidationErrorType.CUSTOM_VALIDATION.name, errors), - HttpStatus.BAD_REQUEST + HttpStatus.BAD_REQUEST, ) } @ExceptionHandler(BindException::class) - fun handleBindExceptions( - ex: BindException - ): ResponseEntity>> { + fun handleBindExceptions(ex: BindException): ResponseEntity>> { val errors: MutableMap = HashMap() ex.bindingResult.allErrors.forEach { error: ObjectError -> @@ -99,27 +95,29 @@ class ExceptionHandlers { return ResponseEntity( Collections.singletonMap(ValidationErrorType.STANDARD_VALIDATION.name, errors), - HttpStatus.BAD_REQUEST + HttpStatus.BAD_REQUEST, ) } @ExceptionHandler(MissingServletRequestParameterException::class) fun handleMissingServletRequestParameterException( - ex: MissingServletRequestParameterException + ex: MissingServletRequestParameterException, ): ResponseEntity>> { val errors = Collections.singletonMap(ex.parameterName, ex.message) return ResponseEntity( - Collections.singletonMap(ValidationErrorType.STANDARD_VALIDATION.name, errors), HttpStatus.BAD_REQUEST + Collections.singletonMap(ValidationErrorType.STANDARD_VALIDATION.name, errors), + HttpStatus.BAD_REQUEST, ) } @ExceptionHandler(MissingServletRequestPartException::class) fun handleMissingServletRequestPartException( - ex: MissingServletRequestPartException + ex: MissingServletRequestPartException, ): ResponseEntity>> { val errors = Collections.singletonMap(ex.requestPartName, ex.message) return ResponseEntity( - Collections.singletonMap(ValidationErrorType.STANDARD_VALIDATION.name, errors), HttpStatus.BAD_REQUEST + Collections.singletonMap(ValidationErrorType.STANDARD_VALIDATION.name, errors), + HttpStatus.BAD_REQUEST, ) } @@ -127,11 +125,12 @@ class ExceptionHandlers { responseCode = "400", content = [ Content( - schema = Schema( - example = """{"code": "you_did_something_wrong", "params": ["something", "wrong"]}""" - ) - ) - ] + schema = + Schema( + example = """{"code": "you_did_something_wrong", "params": ["something", "wrong"]}""", + ), + ), + ], ) @ExceptionHandler(ErrorException::class) fun handleServerError(ex: ErrorException): ResponseEntity { @@ -147,11 +146,12 @@ class ExceptionHandlers { responseCode = "404", content = [ Content( - schema = Schema( - example = """{"code": "resource_not_found", "params": null}""" - ) - ) - ] + schema = + Schema( + example = """{"code": "resource_not_found", "params": null}""", + ), + ), + ], ) @ExceptionHandler(NotFoundException::class) fun handleNotFound(ex: NotFoundException): ResponseEntity { @@ -162,7 +162,7 @@ class ExceptionHandlers { fun handleFileSizeLimitExceeded(ex: MaxUploadSizeExceededException): ResponseEntity { return ResponseEntity( ErrorResponseBody(Message.FILE_TOO_BIG.code, listOf()), - HttpStatus.BAD_REQUEST + HttpStatus.BAD_REQUEST, ) } @@ -171,7 +171,7 @@ class ExceptionHandlers { val params = ex.rootCause?.message?.let { listOf(it) } return ResponseEntity( ErrorResponseBody(Message.REQUEST_PARSE_ERROR.code, params), - HttpStatus.BAD_REQUEST + HttpStatus.BAD_REQUEST, ) } @@ -187,7 +187,7 @@ class ExceptionHandlers { if (contains) { return ResponseEntity( ErrorResponseBody(Message.UNKNOWN_SORT_PROPERTY.code, null), - HttpStatus.BAD_REQUEST + HttpStatus.BAD_REQUEST, ) } throw ex @@ -205,7 +205,7 @@ class ExceptionHandlers { fun handleRateLimited(ex: RateLimitedException): ResponseEntity { return ResponseEntity( RateLimitResponseBody(Message.RATE_LIMITED, ex.retryAfter, ex.global), - HttpStatus.TOO_MANY_REQUESTS + HttpStatus.TOO_MANY_REQUESTS, ) } @@ -216,9 +216,9 @@ class ExceptionHandlers { return ResponseEntity( ErrorResponseBody( "unexpected_error_occurred", - listOf(ex::class.java.name) + listOf(ex::class.java.name), ), - HttpStatus.INTERNAL_SERVER_ERROR + HttpStatus.INTERNAL_SERVER_ERROR, ) } @@ -235,7 +235,10 @@ class ExceptionHandlers { } @ExceptionHandler(ClientAbortException::class) - fun handleClientAbortException(exception: ClientAbortException?, request: HttpServletRequest) { + fun handleClientAbortException( + exception: ClientAbortException?, + request: HttpServletRequest, + ) { val message = "ClientAbortException generated by request {} {} from remote address {} with X-FORWARDED-FOR {}" val headerXFF = request.getHeader("X-FORWARDED-FOR") logger.warn(message, request.method, request.requestURL, request.remoteAddr, headerXFF) diff --git a/backend/app/src/main/kotlin/io/tolgee/commandLineRunners/InitialUserCreatorCommandLineRunner.kt b/backend/app/src/main/kotlin/io/tolgee/commandLineRunners/InitialUserCreatorCommandLineRunner.kt index 9954786e42..f3e9926fa0 100644 --- a/backend/app/src/main/kotlin/io/tolgee/commandLineRunners/InitialUserCreatorCommandLineRunner.kt +++ b/backend/app/src/main/kotlin/io/tolgee/commandLineRunners/InitialUserCreatorCommandLineRunner.kt @@ -24,7 +24,7 @@ class InitialUserCreatorCommandLineRunner( private val initialPasswordManager: InitialPasswordManager, private val organizationService: OrganizationService, private val passwordEncoder: PasswordEncoder, - private val internalProperties: InternalProperties + private val internalProperties: InternalProperties, ) : CommandLineRunner, ApplicationListener { private val logger = LoggerFactory.getLogger(this::class.java) @@ -55,15 +55,16 @@ class InitialUserCreatorCommandLineRunner( } val initialPassword = initialPasswordManager.initialPassword - val user = UserAccount( - username = initialUsername, - password = passwordEncoder.encode(initialPassword), - name = initialUsername, - role = UserAccount.Role.ADMIN, - ).apply { - passwordChanged = false - isInitialUser = true - } + val user = + UserAccount( + username = initialUsername, + password = passwordEncoder.encode(initialPassword), + name = initialUsername, + role = UserAccount.Role.ADMIN, + ).apply { + passwordChanged = false + isInitialUser = true + } userAccountService.createUser(userAccount = user) userAccountService.transferLegacyNoAuthUser() @@ -74,7 +75,7 @@ class InitialUserCreatorCommandLineRunner( OrganizationDto( properties.authentication.initialUsername, ), - userAccount = user + userAccount = user, ) } diff --git a/backend/app/src/main/kotlin/io/tolgee/commandLineRunners/MigrationJobsCommandLineRunner.kt b/backend/app/src/main/kotlin/io/tolgee/commandLineRunners/MigrationJobsCommandLineRunner.kt index 4aa0dd2c7f..348911aafb 100644 --- a/backend/app/src/main/kotlin/io/tolgee/commandLineRunners/MigrationJobsCommandLineRunner.kt +++ b/backend/app/src/main/kotlin/io/tolgee/commandLineRunners/MigrationJobsCommandLineRunner.kt @@ -8,9 +8,8 @@ import org.springframework.stereotype.Component @Component class MigrationJobsCommandLineRunner( - val jobRunners: List + val jobRunners: List, ) : CommandLineRunner, ApplicationListener { - override fun run(vararg args: String) { jobRunners.forEach { it.run() } } diff --git a/backend/app/src/main/kotlin/io/tolgee/commandLineRunners/StartupImportCommandLineRunner.kt b/backend/app/src/main/kotlin/io/tolgee/commandLineRunners/StartupImportCommandLineRunner.kt index eba8dd79f3..4ef54b8294 100644 --- a/backend/app/src/main/kotlin/io/tolgee/commandLineRunners/StartupImportCommandLineRunner.kt +++ b/backend/app/src/main/kotlin/io/tolgee/commandLineRunners/StartupImportCommandLineRunner.kt @@ -11,7 +11,7 @@ import org.springframework.stereotype.Component @Component class StartupImportCommandLineRunner( val tolgeeProperties: TolgeeProperties, - val startupImportService: StartupImportService + val startupImportService: StartupImportService, ) : CommandLineRunner, ApplicationListener, Ordered { override fun run(vararg args: String) { diff --git a/backend/app/src/main/kotlin/io/tolgee/component/ExceptionHandlerFilter.kt b/backend/app/src/main/kotlin/io/tolgee/component/ExceptionHandlerFilter.kt index 6ef00ba15c..9b5846a966 100644 --- a/backend/app/src/main/kotlin/io/tolgee/component/ExceptionHandlerFilter.kt +++ b/backend/app/src/main/kotlin/io/tolgee/component/ExceptionHandlerFilter.kt @@ -28,7 +28,11 @@ import org.springframework.web.servlet.HandlerExceptionResolver class ExceptionHandlerFilter( @Lazy private val handlerExceptionResolver: HandlerExceptionResolver, ) : OncePerRequestFilter() { - override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) { + override fun doFilterInternal( + request: HttpServletRequest, + response: HttpServletResponse, + filterChain: FilterChain, + ) { try { filterChain.doFilter(request, response) } catch (ex: Exception) { diff --git a/backend/app/src/main/kotlin/io/tolgee/configuration/Banner.kt b/backend/app/src/main/kotlin/io/tolgee/configuration/Banner.kt index a043c21ebe..e6acfcabff 100644 --- a/backend/app/src/main/kotlin/io/tolgee/configuration/Banner.kt +++ b/backend/app/src/main/kotlin/io/tolgee/configuration/Banner.kt @@ -6,7 +6,11 @@ import java.io.PrintStream import org.springframework.boot.Banner as SpringBanner class Banner : SpringBanner { - override fun printBanner(arg0: Environment, arg1: Class<*>?, arg2: PrintStream) { + override fun printBanner( + arg0: Environment, + arg1: Class<*>?, + arg2: PrintStream, + ) { val blue = "\u001B[34m" val red = "\u001B[31m" val off = "\u001B[0m" diff --git a/backend/app/src/main/kotlin/io/tolgee/configuration/EmailConfig.kt b/backend/app/src/main/kotlin/io/tolgee/configuration/EmailConfig.kt index 6521acff6f..7421ecf194 100644 --- a/backend/app/src/main/kotlin/io/tolgee/configuration/EmailConfig.kt +++ b/backend/app/src/main/kotlin/io/tolgee/configuration/EmailConfig.kt @@ -8,7 +8,7 @@ import org.springframework.mail.javamail.JavaMailSenderImpl @Configuration class EmailConfig( - private val properties: TolgeeProperties + private val properties: TolgeeProperties, ) { @Bean fun mailSender(): JavaMailSender { diff --git a/backend/app/src/main/kotlin/io/tolgee/configuration/EventStreamConfig.kt b/backend/app/src/main/kotlin/io/tolgee/configuration/EventStreamConfig.kt index 403258f603..52ac03a599 100644 --- a/backend/app/src/main/kotlin/io/tolgee/configuration/EventStreamConfig.kt +++ b/backend/app/src/main/kotlin/io/tolgee/configuration/EventStreamConfig.kt @@ -9,7 +9,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer @Configuration class EventStreamConfig( - private val objectMapper: ObjectMapper + private val objectMapper: ObjectMapper, ) : WebMvcConfigurer { override fun configureMessageConverters(converters: MutableList?>) { converters.add(EventStreamHttpMessageConverter(objectMapper)) @@ -18,9 +18,9 @@ class EventStreamConfig( } class EventStreamHttpMessageConverter( - objectMapper: ObjectMapper + objectMapper: ObjectMapper, ) : AbstractJackson2HttpMessageConverter(objectMapper, MediaType.TEXT_EVENT_STREAM) class JavascriptHttpMessageConverter( - objectMapper: ObjectMapper + objectMapper: ObjectMapper, ) : AbstractJackson2HttpMessageConverter(objectMapper, MediaType("application", "javascript")) diff --git a/backend/app/src/main/kotlin/io/tolgee/configuration/FileStorageConfiguration.kt b/backend/app/src/main/kotlin/io/tolgee/configuration/FileStorageConfiguration.kt index 3267ffe837..a704b1f30d 100644 --- a/backend/app/src/main/kotlin/io/tolgee/configuration/FileStorageConfiguration.kt +++ b/backend/app/src/main/kotlin/io/tolgee/configuration/FileStorageConfiguration.kt @@ -16,7 +16,6 @@ import org.springframework.context.annotation.Configuration class FileStorageConfiguration( private val properties: TolgeeProperties, ) { - private val s3config = properties.fileStorage.s3 @Bean diff --git a/backend/app/src/main/kotlin/io/tolgee/configuration/OpenApiConfiguration.kt b/backend/app/src/main/kotlin/io/tolgee/configuration/OpenApiConfiguration.kt index 57ec880356..64021992af 100644 --- a/backend/app/src/main/kotlin/io/tolgee/configuration/OpenApiConfiguration.kt +++ b/backend/app/src/main/kotlin/io/tolgee/configuration/OpenApiConfiguration.kt @@ -21,7 +21,6 @@ private const val BILLING_EXCLUSION = "/v2/**/billing/**" @Configuration class OpenApiConfiguration { - companion object { private const val PROJECT_ID_PARAMETER = "projectId" } @@ -32,12 +31,12 @@ class OpenApiConfiguration { .info( Info().title("Tolgee API ") .description("Tolgee Server API reference") - .version("v1.0") + .version("v1.0"), ) .externalDocs( ExternalDocumentation() .description("Tolgee documentation") - .url("https://tolgee.io") + .url("https://tolgee.io"), ) } @@ -46,7 +45,7 @@ class OpenApiConfiguration { return internalGroupForPaths( paths = arrayOf("/api/**"), excludedPaths = arrayOf(BILLING_EXCLUSION, API_REPOSITORY_EXCLUDE), - name = "V1 Internal - for Tolgee Web application" + name = "V1 Internal - for Tolgee Web application", ) } @@ -55,7 +54,7 @@ class OpenApiConfiguration { return internalGroupForPaths( paths = arrayOf("/v2/**"), excludedPaths = arrayOf(BILLING_EXCLUSION, API_REPOSITORY_EXCLUDE), - name = "V2 Internal - for Tolgee Web application" + name = "V2 Internal - for Tolgee Web application", ) } @@ -64,7 +63,7 @@ class OpenApiConfiguration { return internalGroupForPaths( paths = arrayOf("/v2/**", "/api/**"), excludedPaths = arrayOf(BILLING_EXCLUSION, API_REPOSITORY_EXCLUDE), - name = "All Internal - for Tolgee Web application" + name = "All Internal - for Tolgee Web application", ) } @@ -73,7 +72,7 @@ class OpenApiConfiguration { return apiKeyGroupForPaths( paths = arrayOf("/api/**", "/v2/**"), excludedPaths = arrayOf(BILLING_EXCLUSION, API_REPOSITORY_EXCLUDE), - name = "Accessible with API key" + name = "Accessible with API key", ) } @@ -82,7 +81,7 @@ class OpenApiConfiguration { return apiKeyGroupForPaths( paths = arrayOf("/api/**"), excludedPaths = arrayOf(BILLING_EXCLUSION, API_REPOSITORY_EXCLUDE), - name = "V1 Accessible with API key" + name = "V1 Accessible with API key", ) } @@ -91,7 +90,7 @@ class OpenApiConfiguration { return apiKeyGroupForPaths( paths = arrayOf("/v2/**"), excludedPaths = arrayOf(BILLING_EXCLUSION, API_REPOSITORY_EXCLUDE), - name = "V2 Accessible with API key V2" + name = "V2 Accessible with API key V2", ) } @@ -100,14 +99,14 @@ class OpenApiConfiguration { return internalGroupForPaths( paths = arrayOf("/v2/**/billing/**"), excludedPaths = arrayOf("/v2/public/billing/webhook"), - name = "V2 Billing" + name = "V2 Billing", ) } private fun internalGroupForPaths( paths: Array, excludedPaths: Array = arrayOf(), - name: String + name: String, ): GroupedOpenApi? { val operationHandlers = HashMap() val handlerPaths = HashMap>() @@ -123,12 +122,13 @@ class OpenApiConfiguration { openApi.paths.forEach { (path, value) -> value.readOperations().forEach { operation -> operationHandlers[operation.operationId]?.method?.let { method -> - handlerPaths[method] = handlerPaths[method].let { - it?.run { - add(path) - this - } ?: mutableListOf(path) - } + handlerPaths[method] = + handlerPaths[method].let { + it?.run { + add(path) + this + } ?: mutableListOf(path) + } } } } @@ -140,16 +140,18 @@ class OpenApiConfiguration { val newPathItem = PathItem() val oldPathItem = pathEntry.value oldPathItem.readOperations().forEach { operation -> - val isParameterConsumed = operation?.parameters?.any { - it.name == PROJECT_ID_PARAMETER - } == true + val isParameterConsumed = + operation?.parameters?.any { + it.name == PROJECT_ID_PARAMETER + } == true val pathContainsProjectId = pathEntry.key.contains("{$PROJECT_ID_PARAMETER}") val parameterIsMissingAtAll = !pathContainsProjectId && !isParameterConsumed - val otherMethodPathContainsProjectId = handlerPaths[ - operationHandlers[operation.operationId] - ?.method - ]?.any { it.contains("{projectId}") } - ?: false + val otherMethodPathContainsProjectId = + handlerPaths[ + operationHandlers[operation.operationId] + ?.method, + ]?.any { it.contains("{projectId}") } + ?: false // If controller method has another method which request mapping path contains {projectId}, // this operation is then considered as one for access for API key and removed from // internal operations @@ -160,13 +162,14 @@ class OpenApiConfiguration { } if (!isParameterConsumed && pathContainsProjectId) { - val param = Parameter().apply { - name(PROJECT_ID_PARAMETER) - `in` = "path" - required = true - allowEmptyValue = false - schema = IntegerSchema().apply { format = "int64" } - } + val param = + Parameter().apply { + name(PROJECT_ID_PARAMETER) + `in` = "path" + required = true + allowEmptyValue = false + schema = IntegerSchema().apply { format = "int64" } + } operation.parameters?.apply { add(param) } ?: let { @@ -194,7 +197,11 @@ class OpenApiConfiguration { .build() } - fun apiKeyGroupForPaths(paths: Array, excludedPaths: Array, name: String): GroupedOpenApi? { + fun apiKeyGroupForPaths( + paths: Array, + excludedPaths: Array, + name: String, + ): GroupedOpenApi? { val operationHandlers = HashMap() return GroupedOpenApi.builder().group(name) @@ -212,8 +219,9 @@ class OpenApiConfiguration { val annotation = handler?.getMethodAnnotation(AllowApiAccess::class.java) if (annotation != null) { - val containsProjectIdParam = pathEntry.key - .contains("{$PROJECT_ID_PARAMETER}") + val containsProjectIdParam = + pathEntry.key + .contains("{$PROJECT_ID_PARAMETER}") if (!pathEntry.key.matches("^/(?:api|v2)/projects?/\\{$PROJECT_ID_PARAMETER}.*".toRegex())) { if (!containsProjectIdParam) { operation.parameters.removeIf { it.name == PROJECT_ID_PARAMETER && it.`in` != "query" } diff --git a/backend/app/src/main/kotlin/io/tolgee/configuration/PostgresAutoStartConfiguration.kt b/backend/app/src/main/kotlin/io/tolgee/configuration/PostgresAutoStartConfiguration.kt index b1d3f8a5c3..b7ac84beeb 100644 --- a/backend/app/src/main/kotlin/io/tolgee/configuration/PostgresAutoStartConfiguration.kt +++ b/backend/app/src/main/kotlin/io/tolgee/configuration/PostgresAutoStartConfiguration.kt @@ -14,16 +14,16 @@ import javax.sql.DataSource class PostgresAutoStartConfiguration( val postgresAutostartProperties: PostgresAutostartProperties, ) { - private var _dataSource: DataSource? = null + private var dataSource: DataSource? = null @Bean("dataSource") @ConfigurationProperties(prefix = "spring.datasource") fun getDataSource(postgresRunner: PostgresRunner?): DataSource { postgresRunner ?: throw IllegalStateException("Postgres runner is not initialized") - _dataSource?.let { return it } + dataSource?.let { return it } postgresRunner.run() - _dataSource = buildDataSource(postgresRunner) - return _dataSource!! + dataSource = buildDataSource(postgresRunner) + return dataSource!! } private fun buildDataSource(postgresRunner: PostgresRunner): DataSource { diff --git a/backend/app/src/main/kotlin/io/tolgee/configuration/RestTemplateConfiguration.kt b/backend/app/src/main/kotlin/io/tolgee/configuration/RestTemplateConfiguration.kt index 1d047305d0..a9971e84d1 100644 --- a/backend/app/src/main/kotlin/io/tolgee/configuration/RestTemplateConfiguration.kt +++ b/backend/app/src/main/kotlin/io/tolgee/configuration/RestTemplateConfiguration.kt @@ -12,7 +12,6 @@ import org.springframework.web.client.RestTemplate @Component class RestTemplateConfiguration { - @Bean @Lazy @Primary @@ -20,7 +19,7 @@ class RestTemplateConfiguration { return RestTemplate( HttpComponentsClientHttpRequestFactory().apply { this.httpClient = HttpClientBuilder.create().disableCookieManagement().useSystemProperties().build() - } + }, ).removeXmlConverter() } diff --git a/backend/app/src/main/kotlin/io/tolgee/configuration/WebSecurityConfig.kt b/backend/app/src/main/kotlin/io/tolgee/configuration/WebSecurityConfig.kt index 3025d029fb..5f134cbaa0 100644 --- a/backend/app/src/main/kotlin/io/tolgee/configuration/WebSecurityConfig.kt +++ b/backend/app/src/main/kotlin/io/tolgee/configuration/WebSecurityConfig.kt @@ -70,13 +70,15 @@ class WebSecurityConfig( .addFilterBefore(globalUserRateLimitFilter, UsernamePasswordAuthenticationFilter::class.java) .addFilterBefore(globalIpRateLimitFilter, UsernamePasswordAuthenticationFilter::class.java) .authorizeHttpRequests { - it.withObjectPostProcessor(object : ObjectPostProcessor { - override fun postProcess(filter: O): O { - // otherwise it throws error when using StreamingResponseBody - filter?.setFilterAsyncDispatch(false) - return filter - } - }) + it.withObjectPostProcessor( + object : ObjectPostProcessor { + override fun postProcess(filter: O): O { + // otherwise it throws error when using StreamingResponseBody + filter?.setFilterAsyncDispatch(false) + return filter + } + }, + ) it.requestMatchers("/api/public/**", "/v2/public/**").permitAll() it.requestMatchers("/v2/administration/**", "/v2/ee-license/**").hasRole("ADMIN") it.requestMatchers("/api/**", "/v2/**") diff --git a/backend/app/src/main/kotlin/io/tolgee/postgresRunners/PostgresDockerRunner.kt b/backend/app/src/main/kotlin/io/tolgee/postgresRunners/PostgresDockerRunner.kt index bd24805fa8..90470a780f 100644 --- a/backend/app/src/main/kotlin/io/tolgee/postgresRunners/PostgresDockerRunner.kt +++ b/backend/app/src/main/kotlin/io/tolgee/postgresRunners/PostgresDockerRunner.kt @@ -12,27 +12,30 @@ class PostgresDockerRunner( private val logger = LoggerFactory.getLogger(javaClass) override fun run() { - instance = DockerContainerRunner( - image = "postgres:13", - expose = mapOf(postgresAutostartProperties.port to "5432"), - waitForLog = "database system is ready to accept connections", - waitForLogTimesForNewContainer = 2, - waitForLogTimesForExistingContainer = 1, - rm = false, - name = postgresAutostartProperties.containerName, - stopBeforeStart = false, - env = mapOf( - "POSTGRES_PASSWORD" to postgresAutostartProperties.password, - "POSTGRES_USER" to postgresAutostartProperties.user, - "POSTGRES_DB" to postgresAutostartProperties.databaseName, - ), - command = "postgres -c max_connections=10000 -c random_page_cost=1.0 " + - "-c fsync=off -c synchronous_commit=off -c full_page_writes=off", - timeout = 300000, - ).also { - logger.info("Starting Postgres Docker container") - it.run() - } + instance = + DockerContainerRunner( + image = "postgres:13", + expose = mapOf(postgresAutostartProperties.port to "5432"), + waitForLog = "database system is ready to accept connections", + waitForLogTimesForNewContainer = 2, + waitForLogTimesForExistingContainer = 1, + rm = false, + name = postgresAutostartProperties.containerName, + stopBeforeStart = false, + env = + mapOf( + "POSTGRES_PASSWORD" to postgresAutostartProperties.password, + "POSTGRES_USER" to postgresAutostartProperties.user, + "POSTGRES_DB" to postgresAutostartProperties.databaseName, + ), + command = + "postgres -c max_connections=10000 -c random_page_cost=1.0 " + + "-c fsync=off -c synchronous_commit=off -c full_page_writes=off", + timeout = 300000, + ).also { + logger.info("Starting Postgres Docker container") + it.run() + } } override fun stop() { diff --git a/backend/app/src/main/kotlin/io/tolgee/postgresRunners/PostgresEmbeddedRunner.kt b/backend/app/src/main/kotlin/io/tolgee/postgresRunners/PostgresEmbeddedRunner.kt index 0eae6fd2e0..6638c97da3 100644 --- a/backend/app/src/main/kotlin/io/tolgee/postgresRunners/PostgresEmbeddedRunner.kt +++ b/backend/app/src/main/kotlin/io/tolgee/postgresRunners/PostgresEmbeddedRunner.kt @@ -13,7 +13,7 @@ import kotlin.concurrent.thread class PostgresEmbeddedRunner( private val postgresAutostartProperties: PostgresAutostartProperties, - private val storageProperties: FileStorageProperties + private val storageProperties: FileStorageProperties, ) : PostgresRunner { private val logger = LoggerFactory.getLogger(javaClass) private lateinit var proc: Process @@ -43,8 +43,9 @@ class PostgresEmbeddedRunner( } private fun buildProcess(): ProcessBuilder { - val processBuilder = ProcessBuilder() - .command("bash", "-c", "postgres-entrypoint.sh postgres") + val processBuilder = + ProcessBuilder() + .command("bash", "-c", "postgres-entrypoint.sh postgres") initProcessEnv(processBuilder) return processBuilder @@ -58,8 +59,8 @@ class PostgresEmbeddedRunner( "POSTGRES_PASSWORD" to postgresAutostartProperties.password, "POSTGRES_USER" to postgresAutostartProperties.user, "POSTGRES_DB" to postgresAutostartProperties.databaseName, - "PGDATA" to storageProperties.fsDataPath + "/postgres" - ) + "PGDATA" to storageProperties.fsDataPath + "/postgres", + ), ) } @@ -68,8 +69,8 @@ class PostgresEmbeddedRunner( logOutput( mapOf( proc.inputStream to logger::info, - proc.errorStream to logger::error - ) + proc.errorStream to logger::error, + ), ) if (proc.exitValue() != 0) { throw Exception("Postgres failed to start...") @@ -96,10 +97,12 @@ class PostgresEmbeddedRunner( } catch (e: java.lang.Exception) { false } finally { - if (s != null) try { - s.close() - } catch (e: java.lang.Exception) { - e.printStackTrace() + if (s != null) { + try { + s.close() + } catch (e: java.lang.Exception) { + e.printStackTrace() + } } } } @@ -107,11 +110,12 @@ class PostgresEmbeddedRunner( private fun logOutput(loggerMap: Map Unit>) { while (running.get()) { try { - val allNull = loggerMap.entries.map { (inputStream, logger) -> - val line = inputStream.bufferedReader().readLine() - logLine(line, logger) - line == null - }.all { it } + val allNull = + loggerMap.entries.map { (inputStream, logger) -> + val line = inputStream.bufferedReader().readLine() + logLine(line, logger) + line == null + }.all { it } if (allNull) { break } @@ -121,7 +125,10 @@ class PostgresEmbeddedRunner( } } - private fun logLine(line: String?, logger: (message: String) -> Unit) { + private fun logLine( + line: String?, + logger: (message: String) -> Unit, + ) { if (line != null) { logger("Postgres: $line") } diff --git a/backend/app/src/main/kotlin/io/tolgee/postgresRunners/PostgresRunnerConfiguration.kt b/backend/app/src/main/kotlin/io/tolgee/postgresRunners/PostgresRunnerConfiguration.kt index bd4e00ab23..b3822a4d4f 100644 --- a/backend/app/src/main/kotlin/io/tolgee/postgresRunners/PostgresRunnerConfiguration.kt +++ b/backend/app/src/main/kotlin/io/tolgee/postgresRunners/PostgresRunnerConfiguration.kt @@ -11,7 +11,7 @@ class PostgresRunnerConfiguration { @Bean fun postgresRunner( postgresAutostartProperties: PostgresAutostartProperties, - storageProperties: FileStorageProperties + storageProperties: FileStorageProperties, ): PostgresRunner? { if (!postgresAutostartProperties.enabled) { return null diff --git a/backend/app/src/main/kotlin/io/tolgee/postgresRunners/PostgresStopper.kt b/backend/app/src/main/kotlin/io/tolgee/postgresRunners/PostgresStopper.kt index 65476454d2..23aa0c8400 100644 --- a/backend/app/src/main/kotlin/io/tolgee/postgresRunners/PostgresStopper.kt +++ b/backend/app/src/main/kotlin/io/tolgee/postgresRunners/PostgresStopper.kt @@ -9,7 +9,7 @@ import org.springframework.stereotype.Component @Component class PostgresStopper( private val postgresAutostartProperties: PostgresAutostartProperties, - private val postgresRunner: PostgresRunner? + private val postgresRunner: PostgresRunner?, ) { @EventListener(ContextClosedEvent::class) fun onAppStop() { diff --git a/backend/app/src/main/resources/application-e2e.yaml b/backend/app/src/main/resources/application-e2e.yaml index a11fff3249..e712acd1e9 100644 --- a/backend/app/src/main/resources/application-e2e.yaml +++ b/backend/app/src/main/resources/application-e2e.yaml @@ -69,5 +69,5 @@ server: logging: level: io.tolgee.service: TRACE - io.tolgee.controllers.internal.e2e_data.OrganizationE2eDataController: TRACE - io.tolgee.controllers.internal.e2e_data.ProjectsE2eDataController: TRACE + io.tolgee.controllers.internal.e2eData.OrganizationE2eDataController: TRACE + io.tolgee.controllers.internal.e2eData.ProjectsE2eDataController: TRACE diff --git a/backend/app/src/test/kotlin/io/tolgee/AuthTest.kt b/backend/app/src/test/kotlin/io/tolgee/AuthTest.kt index dec8263581..bb0b12b217 100644 --- a/backend/app/src/test/kotlin/io/tolgee/AuthTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/AuthTest.kt @@ -11,7 +11,7 @@ import io.tolgee.fixtures.generateUniqueString import io.tolgee.fixtures.mapResponseTo import io.tolgee.model.Project import io.tolgee.security.authentication.JwtService -import io.tolgee.security.third_party.GithubOAuthDelegate.GithubEmailResponse +import io.tolgee.security.thirdParty.GithubOAuthDelegate.GithubEmailResponse import io.tolgee.testing.AbstractControllerTest import io.tolgee.util.GitHubAuthUtil import io.tolgee.util.GoogleAuthUtil @@ -82,16 +82,18 @@ class AuthTest : AbstractControllerTest() { @Test fun userWithTokenHasAccess() { - val response = doAuthentication(initialUsername, initialPassword) - .andReturn().response.contentAsString + val response = + doAuthentication(initialUsername, initialPassword) + .andReturn().response.contentAsString val token = mapper.readValue(response, HashMap::class.java)["accessToken"] as String? - val mvcResult = mvc.perform( - MockMvcRequestBuilders.get("/api/projects") - .accept(MediaType.ALL) - .header("Authorization", String.format("Bearer %s", token)) - .contentType(MediaType.APPLICATION_JSON) - ) - .andReturn() + val mvcResult = + mvc.perform( + MockMvcRequestBuilders.get("/api/projects") + .accept(MediaType.ALL) + .header("Authorization", String.format("Bearer %s", token)) + .contentType(MediaType.APPLICATION_JSON), + ) + .andReturn() assertThat(mvcResult.response.status).isEqualTo(200) } @@ -106,12 +108,13 @@ class AuthTest : AbstractControllerTest() { currentDateProvider.forcedDate = baseline - val mvcResult = mvc.perform( - MockMvcRequestBuilders.get("/api/projects") - .accept(MediaType.ALL) - .header("Authorization", String.format("Bearer %s", token)) - .contentType(MediaType.APPLICATION_JSON) - ).andReturn() + val mvcResult = + mvc.perform( + MockMvcRequestBuilders.get("/api/projects") + .accept(MediaType.ALL) + .header("Authorization", String.format("Bearer %s", token)) + .contentType(MediaType.APPLICATION_JSON), + ).andReturn() assertThat(mvcResult.response.status).isEqualTo(401) assertThat(mvcResult.response.contentAsString).contains(Message.EXPIRED_JWT_TOKEN.code) @@ -273,7 +276,7 @@ class AuthTest : AbstractControllerTest() { MockMvcRequestBuilders.put("/v2/projects/${project.id}/users/${project.id}/revoke-access") .accept(MediaType.ALL) .header("Authorization", String.format("Bearer %s", token)) - .contentType(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON), ).andIsForbidden.andAssertThatJson { node("code").isEqualTo(Message.EXPIRED_SUPER_JWT_TOKEN.code) } diff --git a/backend/app/src/test/kotlin/io/tolgee/HealthCheckTest.kt b/backend/app/src/test/kotlin/io/tolgee/HealthCheckTest.kt index c1c298a566..0edb5ba766 100644 --- a/backend/app/src/test/kotlin/io/tolgee/HealthCheckTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/HealthCheckTest.kt @@ -10,7 +10,6 @@ import io.tolgee.testing.AbstractControllerTest import org.junit.jupiter.api.Test class HealthCheckTest : AbstractControllerTest() { - @Test fun `health check works`() { performGet("/actuator/health").andPrettyPrint.andIsOk diff --git a/backend/app/src/test/kotlin/io/tolgee/MachineTranslationTest.kt b/backend/app/src/test/kotlin/io/tolgee/MachineTranslationTest.kt index 9ad0abd77e..fa04cc49ce 100644 --- a/backend/app/src/test/kotlin/io/tolgee/MachineTranslationTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/MachineTranslationTest.kt @@ -31,16 +31,17 @@ class MachineTranslationTest : ProjectAuthControllerTest("/v2/projects/") { Mockito.reset(googleTranslate) Mockito.reset(amazonTranslate) val googleTranslationMock = mock() as Translation - val awsTranslateTextResult = TranslateTextResponse - .builder().translatedText("Translated with Amazon").build() + val awsTranslateTextResult = + TranslateTextResponse + .builder().translatedText("Translated with Amazon").build() whenever( googleTranslate.translate( any(), any(), any(), - any() - ) + any(), + ), ).thenReturn(googleTranslationMock) whenever(googleTranslationMock.translatedText).then { @@ -61,19 +62,23 @@ class MachineTranslationTest : ProjectAuthControllerTest("/v2/projects/") { protected fun createAnotherThisIsBeautifulKey() { performCreateKey( - translations = mapOf( - "en" to "This is beautiful", - ) + translations = + mapOf( + "en" to "This is beautiful", + ), ).andIsCreated } - protected fun performCreateKey(keyName: String = CREATE_KEY_NAME, translations: Map): ResultActions { + protected fun performCreateKey( + keyName: String = CREATE_KEY_NAME, + translations: Map, + ): ResultActions { return performProjectAuthPost( "keys", CreateKeyDto( name = keyName, - translations = translations - ) + translations = translations, + ), ) } diff --git a/backend/app/src/test/kotlin/io/tolgee/PatAuthTest.kt b/backend/app/src/test/kotlin/io/tolgee/PatAuthTest.kt index d60bf7296c..0684dae6b6 100644 --- a/backend/app/src/test/kotlin/io/tolgee/PatAuthTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/PatAuthTest.kt @@ -23,7 +23,7 @@ class PatAuthTest : AbstractControllerTest() { "/v2/user", HttpHeaders().apply { add("X-API-Key", "tgpat_${pat.token}") - } + }, ).andIsOk.andAssertThatJson { node("username").isEqualTo("franta") } @@ -41,7 +41,7 @@ class PatAuthTest : AbstractControllerTest() { "/v2/projects/translations/en", HttpHeaders().apply { add("X-API-Key", "tgpat_${pat.token}") - } + }, ).andIsBadRequest.andHasErrorMessage(Message.PROJECT_NOT_SELECTED) } @@ -53,7 +53,7 @@ class PatAuthTest : AbstractControllerTest() { "/v2/user", HttpHeaders().apply { add("X-API-Key", "tgpat_${pat.token}") - } + }, ).andIsOk } @@ -63,7 +63,7 @@ class PatAuthTest : AbstractControllerTest() { "/v2/user", HttpHeaders().apply { add("X-API-Key", "tgpat_nopat") - } + }, ).andIsUnauthorized } @@ -74,7 +74,7 @@ class PatAuthTest : AbstractControllerTest() { "/v2/user", HttpHeaders().apply { add("X-API-Key", "tgpat_${pat.token}") - } + }, ).andIsUnauthorized } @@ -84,9 +84,10 @@ class PatAuthTest : AbstractControllerTest() { performDelete( "/v2/pats/${pat.id}", content = null, - httpHeaders = HttpHeaders().apply { - add("X-API-Key", "tgpat_${pat.token}") - } + httpHeaders = + HttpHeaders().apply { + add("X-API-Key", "tgpat_${pat.token}") + }, ).andIsForbidden } diff --git a/backend/app/src/test/kotlin/io/tolgee/StartupImportCommandLineRunnerTest.kt b/backend/app/src/test/kotlin/io/tolgee/StartupImportCommandLineRunnerTest.kt index c3bb844021..75dc71110d 100644 --- a/backend/app/src/test/kotlin/io/tolgee/StartupImportCommandLineRunnerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/StartupImportCommandLineRunnerTest.kt @@ -21,7 +21,6 @@ import org.springframework.core.io.Resource @Suppress("LateinitVarOverridesLateinitVar") @CleanDbBeforeClass class StartupImportCommandLineRunnerTest : AbstractSpringTest() { - private lateinit var base: Base @Value("classpath:startup-import") @@ -42,7 +41,7 @@ class StartupImportCommandLineRunnerTest : AbstractSpringTest() { dir = importDir.file.absolutePath createImplicitApiKey = true baseLanguageTag = "de" - } + }, ) base = dbPopulator.createBase("labaala", "admin") startupImportCommandLineRunner.run() diff --git a/backend/app/src/test/kotlin/io/tolgee/StreamingBodyDatabasePoolHealthTest.kt b/backend/app/src/test/kotlin/io/tolgee/StreamingBodyDatabasePoolHealthTest.kt index 1ad1c70c75..22cf5b6966 100644 --- a/backend/app/src/test/kotlin/io/tolgee/StreamingBodyDatabasePoolHealthTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/StreamingBodyDatabasePoolHealthTest.kt @@ -34,7 +34,7 @@ import javax.sql.DataSource "tolgee.rate-limits.global-limits = false", "tolgee.rate-limits.endpoint-limits = false", "tolgee.rate-limits.authentication-limits = false", - ] + ], ) class StreamingBodyDatabasePoolHealthTest : ProjectAuthControllerTest("/v2/projects/") { lateinit var testData: TranslationsTestData @@ -63,7 +63,7 @@ class StreamingBodyDatabasePoolHealthTest : ProjectAuthControllerTest("/v2/proje var sleepBetweenMs = 0L retry( retries = 100, - exceptionMatcher = { it is ConcurrentModificationException || it is IllegalStateException } + exceptionMatcher = { it is ConcurrentModificationException || it is IllegalStateException }, ) { try { val hikariDataSource = dataSource as HikariDataSource diff --git a/backend/app/src/test/kotlin/io/tolgee/VersionHeaderTest.kt b/backend/app/src/test/kotlin/io/tolgee/VersionHeaderTest.kt index 76dc62bd0e..23fd7d22e4 100644 --- a/backend/app/src/test/kotlin/io/tolgee/VersionHeaderTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/VersionHeaderTest.kt @@ -22,7 +22,7 @@ class VersionHeaderTest : AbstractControllerTest() { "/v2/user", HttpHeaders().apply { add("X-API-Key", "tgpat_nopat") - } + }, ).andIsUnauthorized.andReturn().response.getHeader("X-Tolgee-Version").assert.isEqualTo("??") } } diff --git a/backend/app/src/test/kotlin/io/tolgee/activity/ActivityLogTest.kt b/backend/app/src/test/kotlin/io/tolgee/activity/ActivityLogTest.kt index bc66f9fc28..754fd417ae 100644 --- a/backend/app/src/test/kotlin/io/tolgee/activity/ActivityLogTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/activity/ActivityLogTest.kt @@ -32,7 +32,6 @@ import java.math.BigDecimal import java.util.function.Consumer class ActivityLogTest : ProjectAuthControllerTest("/v2/projects/") { - private lateinit var testData: BaseTestData @MockBean @@ -67,7 +66,6 @@ class ActivityLogTest : ProjectAuthControllerTest("/v2/projects/") { performProjectAuthPut( "translations", mapOf("key" to "key", "translations" to mapOf(testData.englishLanguage.tag to "Test")), - ).andIsOk performProjectAuthGet("activity").andIsOk.andPrettyPrint.andAssertThatJson { @@ -109,10 +107,11 @@ class ActivityLogTest : ProjectAuthControllerTest("/v2/projects/") { "start-batch-job/machine-translate", mapOf( "keyIds" to keyIds, - "targetLanguageIds" to listOf( - csLanguageId - ) - ) + "targetLanguageIds" to + listOf( + csLanguageId, + ), + ), ).andIsOk.waitForJobCompleted() performProjectAuthGet("activity").andIsOk.andPrettyPrint.andAssertThatJson { @@ -137,17 +136,18 @@ class ActivityLogTest : ProjectAuthControllerTest("/v2/projects/") { it["X-Tolgee-Utm"] = "eyJ1dG1faGVsbG8iOiJoZWxsbyJ9" it["X-Tolgee-SDK-Type"] = "Unreal" it["X-Tolgee-SDK-Version"] = "1.0.0" - } + }, ).andIsOk var params: Map? = null waitForNotThrowing(timeout = 10000) { verify(postHog, times(1)).capture( - any(), eq("SET_TRANSLATIONS"), + any(), + eq("SET_TRANSLATIONS"), argThat { params = this true - } + }, ) } params!!["utm_hello"].assert.isEqualTo("hello") @@ -191,7 +191,10 @@ class ActivityLogTest : ProjectAuthControllerTest("/v2/projects/") { node("exists").isEqualTo(true) } - private fun JsonAssert.isLanguageRelation(name: String, tag: String) { + private fun JsonAssert.isLanguageRelation( + name: String, + tag: String, + ) { node("entityClass").isEqualTo("Language") node("entityId").isValidId node("data") { @@ -201,14 +204,15 @@ class ActivityLogTest : ProjectAuthControllerTest("/v2/projects/") { node("exists").isEqualTo(true) } - private fun ResultActions.waitForJobCompleted() = andAssertThatJson { - node("id").isNumber.satisfies( - Consumer { - waitFor(pollTime = 2000) { - val job = batchJobService.findJobDto(it.toLong()) - job?.status?.completed == true - } - } - ) - } + private fun ResultActions.waitForJobCompleted() = + andAssertThatJson { + node("id").isNumber.satisfies( + Consumer { + waitFor(pollTime = 2000) { + val job = batchJobService.findJobDto(it.toLong()) + job?.status?.completed == true + } + }, + ) + } } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/AdministrationControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/AdministrationControllerTest.kt index ea3202b80f..343abe144c 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/AdministrationControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/AdministrationControllerTest.kt @@ -19,7 +19,6 @@ import org.springframework.http.HttpHeaders @SpringBootTest @AutoConfigureMockMvc class AdministrationControllerTest : AuthorizedControllerTest() { - lateinit var testData: AdministrationTestData @BeforeEach @@ -63,14 +62,15 @@ class AdministrationControllerTest : AuthorizedControllerTest() { @Test fun `generates user jwt token`() { - val token = performAuthGet("/v2/administration/users/${testData.user.id}/generate-token") - .andIsOk.andGetContentAsString + val token = + performAuthGet("/v2/administration/users/${testData.user.id}/generate-token") + .andIsOk.andGetContentAsString performGet( "/v2/organizations", HttpHeaders().apply { set("Authorization", "Bearer $token") - } + }, ).andIsOk } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/ApiKeyControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/ApiKeyControllerTest.kt index 4e442a2a1a..fbbc82f8dd 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/ApiKeyControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/ApiKeyControllerTest.kt @@ -26,7 +26,6 @@ import java.util.* @SpringBootTest @AutoConfigureMockMvc class ApiKeyControllerTest : AuthorizedControllerTest() { - lateinit var testData: ApiKeysTestData @BeforeEach @@ -42,8 +41,8 @@ class ApiKeyControllerTest : AuthorizedControllerTest() { "/v2/api-keys", mapOf( "projectId" to testData.projectBuilder.self.id, - "scopes" to setOf(Scope.TRANSLATIONS_VIEW.value, Scope.SCREENSHOTS_UPLOAD.value) - ) + "scopes" to setOf(Scope.TRANSLATIONS_VIEW.value, Scope.SCREENSHOTS_UPLOAD.value), + ), ).andIsOk.andPrettyPrint.andAssertThatJson { node("key").isString.hasSizeGreaterThan(10) node("username").isEqualTo("test_username") @@ -61,8 +60,8 @@ class ApiKeyControllerTest : AuthorizedControllerTest() { "/v2/api-keys", mapOf( "projectId" to testData.projectBuilder.self.id, - "scopes" to setOf(Scope.TRANSLATIONS_VIEW.value, Scope.SCREENSHOTS_UPLOAD.value) - ) + "scopes" to setOf(Scope.TRANSLATIONS_VIEW.value, Scope.SCREENSHOTS_UPLOAD.value), + ), ).andIsOk.andPrettyPrint.andAssertThatJson { node("key").isString.hasSizeGreaterThan(10) node("username").isEqualTo("test_username") @@ -82,7 +81,7 @@ class ApiKeyControllerTest : AuthorizedControllerTest() { CreateApiKeyDto().apply { projectId = testData.projectBuilder.self.id scopes = setOf(Scope.TRANSLATIONS_VIEW, Scope.SCREENSHOTS_UPLOAD) - } + }, ).andIsForbidden } @@ -94,7 +93,7 @@ class ApiKeyControllerTest : AuthorizedControllerTest() { CreateApiKeyDto().apply { projectId = testData.projectBuilder.self.id scopes = setOf(Scope.TRANSLATIONS_VIEW, Scope.SCREENSHOTS_UPLOAD, Scope.KEYS_EDIT) - } + }, ).andIsForbidden } @@ -105,20 +104,20 @@ class ApiKeyControllerTest : AuthorizedControllerTest() { CreateApiKeyDto().apply { projectId = testData.frantasProject.id scopes = setOf() - } + }, ).andIsBadRequest performAuthPost( "/v2/api-keys", mapOf( - "projectId" to testData.frantasProject.id - ) + "projectId" to testData.frantasProject.id, + ), ).andIsBadRequest performAuthPost( "/v2/api-keys", mapOf( "projectId" to null, - "scopes" to listOf("translations.edit") - ) + "scopes" to listOf("translations.edit"), + ), ).andIsBadRequest } @@ -300,8 +299,8 @@ class ApiKeyControllerTest : AuthorizedControllerTest() { performAuthPut( "/v2/api-keys/${testData.expiredKey.id}/regenerate", mapOf( - "expiresAt" to expiresAt - ) + "expiresAt" to expiresAt, + ), ).andIsOk.andAssertThatJson { node("key").isString.startsWith("tgpak_").hasSizeGreaterThan(20) node("expiresAt").isEqualTo(expiresAt) diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/AutoTranslationControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/AutoTranslationControllerTest.kt index e5783556d4..9028bb8246 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/AutoTranslationControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/AutoTranslationControllerTest.kt @@ -39,7 +39,7 @@ class AutoTranslationControllerTest : MachineTranslationTest() { "useMachineTranslation=true" + "&languages=de" + "&languages=es", - null + null, ).andIsOk assertThat(testData.thisIsBeautifulKey.getLangTranslation(testData.spanishLanguage).text) .isEqualTo("Translated with Google") @@ -55,7 +55,7 @@ class AutoTranslationControllerTest : MachineTranslationTest() { "keys/${testData.thisIsBeautifulKey.id}/auto-translate?" + "languages=${testData.spanishLanguage.tag}&" + "useMachineTranslation=true", - null + null, ).andIsOk assertThat(testData.thisIsBeautifulKey.getLangTranslation(testData.spanishLanguage).text) .isEqualTo("Translated with Google") @@ -72,7 +72,7 @@ class AutoTranslationControllerTest : MachineTranslationTest() { "keys/${another.id}/auto-translate?" + "languages=${testData.germanLanguage.tag}&" + "useTranslationMemory=true", - null + null, ).andIsOk val translation = another.getLangTranslation(testData.germanLanguage) assertThat(translation.mtProvider).isEqualTo(null) @@ -88,7 +88,7 @@ class AutoTranslationControllerTest : MachineTranslationTest() { "useMachineTranslation=true" + "&languages=de" + "&languages=es", - null + null, ).andIsOk assertThat(testData.thisIsBeautifulKey.getLangTranslation(testData.spanishLanguage).text) .isEqualTo("Translated with Google") @@ -105,7 +105,7 @@ class AutoTranslationControllerTest : MachineTranslationTest() { "useMachineTranslation=true" + "&languages=de" + "&languages=es", - null + null, ).andIsForbidden } @@ -118,7 +118,7 @@ class AutoTranslationControllerTest : MachineTranslationTest() { "keys/${another.id}/auto-translate?" + "languages=en&" + "useTranslationMemory=true", - null + null, ).andIsBadRequest.andHasErrorMessage(Message.CANNOT_TRANSLATE_BASE_LANGUAGE) } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/BigMetaControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/BigMetaControllerTest.kt index 8871f02c03..1a1ae71ce0 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/BigMetaControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/BigMetaControllerTest.kt @@ -18,7 +18,6 @@ import kotlin.time.ExperimentalTime import kotlin.time.measureTime class BigMetaControllerTest : ProjectAuthControllerTest("/v2/projects/"), Logging { - lateinit var testData: BigMetaTestData @Autowired @@ -42,16 +41,17 @@ class BigMetaControllerTest : ProjectAuthControllerTest("/v2/projects/"), Loggin performProjectAuthPost( "big-meta", mapOf( - "relatedKeysInOrder" to listOf( - mapOf( - "keyName" to "key" - ), - mapOf( - "namespace" to "yep", - "keyName" to "key" + "relatedKeysInOrder" to + listOf( + mapOf( + "keyName" to "key", + ), + mapOf( + "namespace" to "yep", + "keyName" to "key", + ), ), - ) - ) + ), ).andIsOk bigMetaService.findExistingKeysDistancesDtosByIds(listOf(testData.yepKey.id)).assert.hasSize(1) @@ -87,17 +87,22 @@ class BigMetaControllerTest : ProjectAuthControllerTest("/v2/projects/"), Loggin bigMetaService.findExistingKeysDistancesDtosByIds(keys.map { it.id }).assert.hasSize(104790) } - private fun storeLogOfBigMeta(keys: List, drop: Int, take: Int) { + private fun storeLogOfBigMeta( + keys: List, + drop: Int, + take: Int, + ) { performProjectAuthPost( "big-meta", mapOf( - "relatedKeysInOrder" to keys.drop(drop).take(take).map { - mapOf( - "namespace" to it.namespace, - "keyName" to it.name - ) - } - ) + "relatedKeysInOrder" to + keys.drop(drop).take(take).map { + mapOf( + "namespace" to it.namespace, + "keyName" to it.name, + ) + }, + ), ).andIsOk } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/BusinessEventControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/BusinessEventControllerTest.kt index 888b751d1a..68b4a1558d 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/BusinessEventControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/BusinessEventControllerTest.kt @@ -43,21 +43,22 @@ class BusinessEventControllerTest : ProjectAuthControllerTest("/v2/projects/") { "eventName" to "TEST_EVENT", "organizationId" to testData.userAccountBuilder.defaultOrganizationBuilder.self.id, "projectId" to testData.projectBuilder.self.id, - "data" to mapOf("test" to "test") + "data" to mapOf("test" to "test"), ), HttpHeaders().also { it["Authorization"] = listOf(AuthorizedRequestFactory.getBearerTokenString(generateJwtToken(userAccount!!.id))) - } + }, ).andIsOk var params: Map? = null waitForNotThrowing(timeout = 10000) { verify(postHog, times(1)).capture( - any(), eq("TEST_EVENT"), + any(), + eq("TEST_EVENT"), argThat { params = this true - } + }, ) } params!!["organizationId"].assert.isNotNull diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/InitialDataControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/InitialDataControllerTest.kt index 49e7251ac1..9346a63708 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/InitialDataControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/InitialDataControllerTest.kt @@ -11,7 +11,6 @@ import org.springframework.boot.test.context.SpringBootTest @SpringBootTest @AutoConfigureMockMvc class InitialDataControllerTest : AuthorizedControllerTest() { - @Test fun `returns initial data when authenticated`() { performAuthGet("/v2/public/initial-data").andPrettyPrint.andIsOk.andAssertThatJson { diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/MachineTranslationSettingsControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/MachineTranslationSettingsControllerTest.kt index 0d15eff5bb..86d41ac4d0 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/MachineTranslationSettingsControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/MachineTranslationSettingsControllerTest.kt @@ -24,7 +24,6 @@ import org.springframework.boot.test.context.SpringBootTest @SpringBootTest @AutoConfigureMockMvc class MachineTranslationSettingsControllerTest : ProjectAuthControllerTest() { - lateinit var testData: MtSettingsTestData @BeforeEach @@ -60,18 +59,19 @@ class MachineTranslationSettingsControllerTest : ProjectAuthControllerTest() { MachineTranslationLanguagePropsDto( targetLanguageId = null, primaryService = MtServiceType.GOOGLE, - enabledServices = setOf(MtServiceType.AWS, MtServiceType.GOOGLE) + enabledServices = setOf(MtServiceType.AWS, MtServiceType.GOOGLE), ), MachineTranslationLanguagePropsDto( targetLanguageId = testData.englishLanguage.id, primaryService = MtServiceType.GOOGLE, - enabledServicesInfo = setOf( - MtServiceInfo(MtServiceType.GOOGLE, null), - MtServiceInfo(MtServiceType.AWS, Formality.DEFAULT) - ) - ) - ) - ) + enabledServicesInfo = + setOf( + MtServiceInfo(MtServiceType.GOOGLE, null), + MtServiceInfo(MtServiceType.AWS, Formality.DEFAULT), + ), + ), + ), + ), ).andIsOk.andAssertThatJson { node("_embedded.languageConfigs") { node("[0]") { @@ -122,23 +122,25 @@ class MachineTranslationSettingsControllerTest : ProjectAuthControllerTest() { MachineTranslationLanguagePropsDto( targetLanguageId = null, primaryService = MtServiceType.GOOGLE, - enabledServices = setOf(MtServiceType.AWS, MtServiceType.GOOGLE) + enabledServices = setOf(MtServiceType.AWS, MtServiceType.GOOGLE), ), MachineTranslationLanguagePropsDto( targetLanguageId = testData.germanLanguage.id, primaryService = MtServiceType.AWS, - enabledServicesInfo = setOf( - MtServiceInfo(MtServiceType.GOOGLE, null), - MtServiceInfo(MtServiceType.AWS, Formality.FORMAL) - ) - ) - ) - ) + enabledServicesInfo = + setOf( + MtServiceInfo(MtServiceType.GOOGLE, null), + MtServiceInfo(MtServiceType.AWS, Formality.FORMAL), + ), + ), + ), + ), ) executeInNewTransaction { - val germanSetting = mtServiceConfigService.getProjectSettings(testData.projectBuilder.self) - .find { it.targetLanguage?.id == testData.germanLanguage.id } + val germanSetting = + mtServiceConfigService.getProjectSettings(testData.projectBuilder.self) + .find { it.targetLanguage?.id == testData.germanLanguage.id } germanSetting!!.awsFormality.assert.isEqualTo(Formality.FORMAL) } } @@ -154,9 +156,9 @@ class MachineTranslationSettingsControllerTest : ProjectAuthControllerTest() { targetLanguageId = testData.germanLanguage.id, primaryService = MtServiceType.AWS, primaryServiceInfo = MtServiceInfo(MtServiceType.TOLGEE, Formality.FORMAL), - ) - ) - ) + ), + ), + ), ).andAssertThatJson { node("_embedded.languageConfigs") { node("[1]") { @@ -178,34 +180,40 @@ class MachineTranslationSettingsControllerTest : ProjectAuthControllerTest() { performSet( MachineTranslationLanguagePropsDto( testData.englishLanguage.id, - primaryServiceInfo = MtServiceInfo(MtServiceType.TOLGEE, Formality.FORMAL) - ) + primaryServiceInfo = MtServiceInfo(MtServiceType.TOLGEE, Formality.FORMAL), + ), ).andIsOk } - private fun performSet(language: Language?, mtServiceType: MtServiceType, formality: Formality) = performAuthPut( + private fun performSet( + language: Language?, + mtServiceType: MtServiceType, + formality: Formality, + ) = performAuthPut( "/v2/projects/${project.id}/machine-translation-service-settings", SetMachineTranslationSettingsDto( listOf( MachineTranslationLanguagePropsDto( targetLanguageId = language?.id, primaryServiceInfo = MtServiceInfo(mtServiceType, Formality.DEFAULT), - enabledServicesInfo = setOf( - MtServiceInfo(mtServiceType, formality) - ) - ) - ) - ) + enabledServicesInfo = + setOf( + MtServiceInfo(mtServiceType, formality), + ), + ), + ), + ), ) - private fun performSet(props: MachineTranslationLanguagePropsDto) = performAuthPut( - "/v2/projects/${project.id}/machine-translation-service-settings", - SetMachineTranslationSettingsDto( - listOf( - props - ) + private fun performSet(props: MachineTranslationLanguagePropsDto) = + performAuthPut( + "/v2/projects/${project.id}/machine-translation-service-settings", + SetMachineTranslationSettingsDto( + listOf( + props, + ), + ), ) - ) @Test @ProjectJWTAuthTestMethod @@ -217,10 +225,10 @@ class MachineTranslationSettingsControllerTest : ProjectAuthControllerTest() { MachineTranslationLanguagePropsDto( targetLanguageId = testData.spanishLanguage.id, primaryService = MtServiceType.GOOGLE, - enabledServices = setOf(MtServiceType.AWS) - ) - ) - ) + enabledServices = setOf(MtServiceType.AWS), + ), + ), + ), ).andIsOk } @@ -228,7 +236,7 @@ class MachineTranslationSettingsControllerTest : ProjectAuthControllerTest() { @ProjectJWTAuthTestMethod fun `it returns the configuration`() { performAuthGet( - "/v2/projects/${project.id}/machine-translation-service-settings" + "/v2/projects/${project.id}/machine-translation-service-settings", ).andPrettyPrint.andAssertThatJson { node("_embedded.languageConfigs") { node("[0]") { @@ -251,7 +259,7 @@ class MachineTranslationSettingsControllerTest : ProjectAuthControllerTest() { @ProjectJWTAuthTestMethod fun `it returns the info`() { performAuthGet( - "/v2/projects/${project.id}/machine-translation-language-info" + "/v2/projects/${project.id}/machine-translation-language-info", ).andPrettyPrint.andAssertThatJson { node("_embedded.languageInfos") { isArray diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/NamespaceControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/NamespaceControllerTest.kt index f351ce08e8..fd6ca921e2 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/NamespaceControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/NamespaceControllerTest.kt @@ -16,7 +16,6 @@ import org.springframework.boot.test.context.SpringBootTest @SpringBootTest @AutoConfigureMockMvc class NamespaceControllerTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: NamespacesTestData @BeforeEach @@ -67,7 +66,7 @@ class NamespaceControllerTest : ProjectAuthControllerTest("/v2/projects/") { fun `updates namespace name`() { performProjectAuthPut( "namespaces/${testData.namespaces[getNs1Def()]?.id}", - mapOf("name" to "ns-new") + mapOf("name" to "ns-new"), ).andIsOk.andAssertThatJson { node("name").isEqualTo("ns-new") } @@ -78,7 +77,7 @@ class NamespaceControllerTest : ProjectAuthControllerTest("/v2/projects/") { fun `cannot rename to existing`() { performProjectAuthPut( "namespaces/${testData.namespaces[getNs1Def()]?.id}", - mapOf("name" to "ns-2") + mapOf("name" to "ns-2"), ).andAssertError.hasCode("namespace_exists") } @@ -88,15 +87,15 @@ class NamespaceControllerTest : ProjectAuthControllerTest("/v2/projects/") { val nsId = testData.namespaces[getNs1Def()]?.id performProjectAuthPut( "namespaces/$nsId", - mapOf("name" to "") + mapOf("name" to ""), ).andAssertError.isStandardValidation.onField("name") performProjectAuthPut( "namespaces/$nsId", - mapOf("name" to null) + mapOf("name" to null), ).andAssertError.isStandardValidation.onField("name") performProjectAuthPut( "namespaces/$nsId", - mapOf("name" to " ") + mapOf("name" to " "), ).andAssertError.isStandardValidation.onField("name") } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/PatControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/PatControllerTest.kt index 9bc2892839..9292ddc5a7 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/PatControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/PatControllerTest.kt @@ -22,7 +22,6 @@ import java.util.* @SpringBootTest @AutoConfigureMockMvc class PatControllerTest : AuthorizedControllerTest() { - lateinit var testData: PatTestData @BeforeEach @@ -64,8 +63,8 @@ class PatControllerTest : AuthorizedControllerTest() { "/v2/pats", mapOf( "description" to description, - "expiresAt" to expiresAt - ) + "expiresAt" to expiresAt, + ), ).andIsCreated.andAssertThatJson { node("description").isEqualTo(description) node("expiresAt").isEqualTo(expiresAt) @@ -77,7 +76,7 @@ class PatControllerTest : AuthorizedControllerTest() { @Test fun `delete works`() { performAuthDelete( - "/v2/pats/${testData.expiredPat.id}" + "/v2/pats/${testData.expiredPat.id}", ).andIsOk assertThat(patService.find(testData.expiredPat.id)).isNull() @@ -90,8 +89,8 @@ class PatControllerTest : AuthorizedControllerTest() { performAuthPut( "/v2/pats/${testData.expiredPat.id}/regenerate", mapOf( - "expiresAt" to expiresAt - ) + "expiresAt" to expiresAt, + ), ).andIsOk.andAssertThatJson { node("token").isString.startsWith("tgpat_") node("expiresAt").isEqualTo(expiresAt) @@ -106,8 +105,8 @@ class PatControllerTest : AuthorizedControllerTest() { performAuthPut( "/v2/pats/${testData.expiredPat.id}/regenerate", mapOf( - "expiresAt" to null - ) + "expiresAt" to null, + ), ).andIsOk.andAssertThatJson { node("token").isString.startsWith("tgpat_") node("expiresAt").isEqualTo(null) @@ -123,7 +122,7 @@ class PatControllerTest : AuthorizedControllerTest() { "/v2/pats/${testData.expiredPat.id}", mapOf( "description" to description, - ) + ), ).andIsOk.andAssertThatJson { node("description").isString.isEqualTo(description) } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/PreferredOrganizationControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/PreferredOrganizationControllerTest.kt index 85ff16d0ab..39fa721ded 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/PreferredOrganizationControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/PreferredOrganizationControllerTest.kt @@ -10,7 +10,6 @@ import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test class PreferredOrganizationControllerTest : AuthorizedControllerTest() { - lateinit var testData: OrganizationTestData @BeforeEach diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/ProjectStatsControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/ProjectStatsControllerTest.kt index 8c6aa70498..d35bbff263 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/ProjectStatsControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/ProjectStatsControllerTest.kt @@ -16,7 +16,6 @@ import java.math.BigDecimal import java.text.SimpleDateFormat class ProjectStatsControllerTest : ProjectAuthControllerTest("/v2/projects/") { - private lateinit var testData: TranslationsTestData private var activityCounter = 0 @@ -108,7 +107,7 @@ class ProjectStatsControllerTest : ProjectAuthControllerTest("/v2/projects/") { "2022-04-05" : 5, "2022-04-20" : 2 } - """ + """, ) } } @@ -121,7 +120,7 @@ class ProjectStatsControllerTest : ProjectAuthControllerTest("/v2/projects/") { repeat(times) { performProjectAuthPut( "translations", - mapOf("key" to "A key", "translations" to mapOf(testData.englishLanguage.tag to "A key ${activityCounter++}")) + mapOf("key" to "A key", "translations" to mapOf(testData.englishLanguage.tag to "A key ${activityCounter++}")), ).andIsOk } } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/SlugControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/SlugControllerTest.kt index a9a3a234a3..d9dd776e32 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/SlugControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/SlugControllerTest.kt @@ -9,7 +9,6 @@ import io.tolgee.testing.AuthorizedControllerTest import org.junit.jupiter.api.Test class SlugControllerTest : AuthorizedControllerTest() { - @Test fun testValidateOrganizationSlug() { performAuthGet("/v2/slug/validate-organization/hello-1").andIsOk.andAssertThatJson { @@ -18,8 +17,8 @@ class SlugControllerTest : AuthorizedControllerTest() { organizationRepository.save( Organization( name = "aaa", - slug = "hello-1" - ) + slug = "hello-1", + ), ) performAuthGet("/v2/slug/validate-organization/hello-1").andIsOk.andAssertThatJson { isEqualTo(false) @@ -34,8 +33,8 @@ class SlugControllerTest : AuthorizedControllerTest() { projectRepository.save( Project( name = "aaa", - slug = "hello-1" - ).also { it.organizationOwner = dbPopulator.createBase("proj").organization } + slug = "hello-1", + ).also { it.organizationOwner = dbPopulator.createBase("proj").organization }, ) performAuthGet("/v2/slug/validate-project/hello-1").andIsOk.andAssertThatJson { isEqualTo(false) @@ -52,8 +51,8 @@ class SlugControllerTest : AuthorizedControllerTest() { organizationRepository.save( Organization( name = "aaa", - slug = "hello-world" - ) + slug = "hello-world", + ), ) performAuthPost("/v2/slug/generate-organization", GenerateSlugDto("Hello world")) @@ -67,8 +66,8 @@ class SlugControllerTest : AuthorizedControllerTest() { organizationRepository.save( Organization( name = "aaa", - slug = "hello-world" - ) + slug = "hello-world", + ), ) performAuthPost("/v2/slug/generate-organization", GenerateSlugDto("Hello world", "hello-world")) @@ -82,8 +81,8 @@ class SlugControllerTest : AuthorizedControllerTest() { projectRepository.save( Project( name = "aaa", - slug = "hello-world" - ).also { it.organizationOwner = dbPopulator.createBase("proj").organization } + slug = "hello-world", + ).also { it.organizationOwner = dbPopulator.createBase("proj").organization }, ) performAuthPost("/v2/slug/generate-project", GenerateSlugDto("Hello world")) .andIsOk.andAssertThatJson { diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/TagsControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/TagsControllerTest.kt index 000c24de29..7cd68945a8 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/TagsControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/TagsControllerTest.kt @@ -18,7 +18,6 @@ import java.math.BigDecimal @Transactional class TagsControllerTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: TagsTestData @BeforeEach diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/UserMfaControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/UserMfaControllerTest.kt index a9d03f2294..91683a0a11 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/UserMfaControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/UserMfaControllerTest.kt @@ -30,11 +30,12 @@ class UserMfaControllerTest : AuthorizedControllerTest() { @Test fun `it enables MFA`() { retry { - val requestDto = UserTotpEnableRequestDto( - totpKey = TOTP_KEY, - otp = mfaService.generateStringCode(encodedKey), - password = initialPassword - ) + val requestDto = + UserTotpEnableRequestDto( + totpKey = TOTP_KEY, + otp = mfaService.generateStringCode(encodedKey), + password = initialPassword, + ) performAuthPut("/v2/user/mfa/totp", requestDto).andIsOk val fromDb = userAccountService.findActive(initialUsername) @@ -45,9 +46,10 @@ class UserMfaControllerTest : AuthorizedControllerTest() { @Test fun `it disables MFA`() { enableMfa() - val requestDto = UserTotpDisableRequestDto( - password = initialPassword - ) + val requestDto = + UserTotpDisableRequestDto( + password = initialPassword, + ) performAuthDelete("/v2/user/mfa/totp", requestDto).andIsOk val fromDb = userAccountService.findActive(initialUsername) Assertions.assertThat(fromDb!!.totpKey).isNull() @@ -56,9 +58,10 @@ class UserMfaControllerTest : AuthorizedControllerTest() { @Test fun `it regenerates MFA recovery codes`() { enableMfa() - val requestDto = UserMfaRecoveryRequestDto( - password = initialPassword - ) + val requestDto = + UserMfaRecoveryRequestDto( + password = initialPassword, + ) var fromDb = userAccountService.findActive(initialUsername) Assertions.assertThat(fromDb!!.mfaRecoveryCodes).isEmpty() @@ -71,15 +74,17 @@ class UserMfaControllerTest : AuthorizedControllerTest() { @Test fun `it requires valid TOTP code for activation`() { retry { - val requestDto = UserTotpEnableRequestDto( - totpKey = TOTP_KEY, - otp = (mfaService.generateCode(encodedKey) + 1).toString().padStart(6, '0'), - password = initialPassword - ) - - val res = performAuthPut("/v2/user/mfa/totp", requestDto) - .andIsBadRequest - .andReturn() + val requestDto = + UserTotpEnableRequestDto( + totpKey = TOTP_KEY, + otp = (mfaService.generateCode(encodedKey) + 1).toString().padStart(6, '0'), + password = initialPassword, + ) + + val res = + performAuthPut("/v2/user/mfa/totp", requestDto) + .andIsBadRequest + .andReturn() assertThat(res).error().isCustomValidation.hasMessage("invalid_otp_code") val fromDb = userAccountService.findActive(initialUsername) @@ -89,19 +94,22 @@ class UserMfaControllerTest : AuthorizedControllerTest() { @Test fun `it requires valid password`() { - val enableRequestDto = UserTotpEnableRequestDto( - totpKey = TOTP_KEY, - otp = mfaService.generateStringCode(encodedKey), - password = "pwease let me innn!!!! >:(" - ) + val enableRequestDto = + UserTotpEnableRequestDto( + totpKey = TOTP_KEY, + otp = mfaService.generateStringCode(encodedKey), + password = "pwease let me innn!!!! >:(", + ) - val disableRequestDto = UserTotpEnableRequestDto( - password = "pwease let me innn!!!! >:(" - ) + val disableRequestDto = + UserTotpEnableRequestDto( + password = "pwease let me innn!!!! >:(", + ) - val recoveryRequestDto = UserMfaRecoveryRequestDto( - password = "pwease let me innn!!!! >:(" - ) + val recoveryRequestDto = + UserMfaRecoveryRequestDto( + password = "pwease let me innn!!!! >:(", + ) performAuthPut("/v2/user/mfa/totp", enableRequestDto).andIsForbidden var fromDb = userAccountService.findActive(initialUsername) @@ -126,11 +134,12 @@ class UserMfaControllerTest : AuthorizedControllerTest() { loginAsAdminIfNotLogged() Thread.sleep(1000) - val enableRequestDto = UserTotpEnableRequestDto( - totpKey = TOTP_KEY, - otp = mfaService.generateStringCode(encodedKey), - password = initialPassword - ) + val enableRequestDto = + UserTotpEnableRequestDto( + totpKey = TOTP_KEY, + otp = mfaService.generateStringCode(encodedKey), + password = initialPassword, + ) performAuthPut("/v2/user/mfa/totp", enableRequestDto).andIsOk refreshUser() @@ -140,9 +149,10 @@ class UserMfaControllerTest : AuthorizedControllerTest() { loginAsAdminIfNotLogged() Thread.sleep(1000) - val disableRequestDto = UserTotpDisableRequestDto( - password = initialPassword - ) + val disableRequestDto = + UserTotpDisableRequestDto( + password = initialPassword, + ) performAuthDelete("/v2/user/mfa/totp", disableRequestDto).andIsOk refreshUser() performAuthGet("/v2/user").andExpect(MockMvcResultMatchers.status().isUnauthorized) diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/UserPreferencesControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/UserPreferencesControllerTest.kt index 7b3eb0a6d7..3680a47249 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/UserPreferencesControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/UserPreferencesControllerTest.kt @@ -9,7 +9,6 @@ import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test class UserPreferencesControllerTest : AuthorizedControllerTest() { - lateinit var testData: OrganizationTestData @BeforeEach diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/V2ExportControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/V2ExportControllerTest.kt index 8fc08b180f..2da74f7874 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/V2ExportControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/V2ExportControllerTest.kt @@ -41,8 +41,8 @@ import kotlin.system.measureTimeMillis @ContextRecreatingTest @SpringBootTest( properties = [ - "tolgee.cache.enabled=true" - ] + "tolgee.cache.enabled=true", + ], ) class V2ExportControllerTest : ProjectAuthControllerTest("/v2/projects/") { lateinit var testData: TranslationsTestData @@ -109,8 +109,9 @@ class V2ExportControllerTest : ProjectAuthControllerTest("/v2/projects/") { executeInNewTransaction { initBaseData() } - val response = performProjectAuthGet("export?languages=en&zip=false") - .andDo { obj: MvcResult -> obj.asyncResult } + val response = + performProjectAuthGet("export?languages=en&zip=false") + .andDo { obj: MvcResult -> obj.asyncResult } response.andPrettyPrint.andAssertThatJson { node("Z key").isEqualTo("A translation") } @@ -129,8 +130,9 @@ class V2ExportControllerTest : ProjectAuthControllerTest("/v2/projects/") { executeInNewTransaction { initBaseData() } - val response = performProjectAuthGet("export?languages=en&zip=false&format=XLIFF") - .andDo { obj: MvcResult -> obj.getAsyncResult(30000) } + val response = + performProjectAuthGet("export?languages=en&zip=false&format=XLIFF") + .andDo { obj: MvcResult -> obj.getAsyncResult(30000) } assertThat(response.andReturn().response.getHeaderValue("content-type")) .isEqualTo("application/x-xliff+xml") @@ -150,17 +152,20 @@ class V2ExportControllerTest : ProjectAuthControllerTest("/v2/projects/") { prepareUserAndProject(testData) commitTransaction() - val time = measureTimeMillis { - val selectAllResult = performProjectAuthGet("translations/select-all") - .andIsOk - .andGetContentAsString - val keyIds = jacksonObjectMapper() - .readValue>>(selectAllResult)["ids"]?.take(500) - val parsed = performExportPost(mapOf("filterKeyId" to keyIds)) - assertThatJson(parsed["en.json"]!!) { - isObject.hasSize(499) + val time = + measureTimeMillis { + val selectAllResult = + performProjectAuthGet("translations/select-all") + .andIsOk + .andGetContentAsString + val keyIds = + jacksonObjectMapper() + .readValue>>(selectAllResult)["ids"]?.take(500) + val parsed = performExportPost(mapOf("filterKeyId" to keyIds)) + assertThatJson(parsed["en.json"]!!) { + isObject.hasSize(499) + } } - } assertThat(time).isLessThan(2000) } @@ -196,16 +201,18 @@ class V2ExportControllerTest : ProjectAuthControllerTest("/v2/projects/") { } private fun performExport(query: String = ""): Map { - val mvcResult = performProjectAuthGet("export?$query") - .andIsOk - .andDo { obj: MvcResult -> obj.asyncResult }.andReturn() + val mvcResult = + performProjectAuthGet("export?$query") + .andIsOk + .andDo { obj: MvcResult -> obj.asyncResult }.andReturn() return parseZip(mvcResult.response.contentAsByteArray) } private fun performExportPost(body: Any): Map { - val mvcResult = performProjectAuthPost("export", body) - .andIsOk - .andDo { obj: MvcResult -> obj.asyncResult }.andReturn() + val mvcResult = + performProjectAuthPost("export", body) + .andIsOk + .andDo { obj: MvcResult -> obj.asyncResult }.andReturn() return parseZip(mvcResult.response.contentAsByteArray) } @@ -264,20 +271,23 @@ class V2ExportControllerTest : ProjectAuthControllerTest("/v2/projects/") { fun `it exports all languages by default`() { retryingOnCommonIssues { val testData = TestDataBuilder() - val user = testData.addUserAccount { - username = "user" - } - val projectBuilder = testData.addProject { - name = "Oh my project" - organizationOwner = user.defaultOrganizationBuilder.self - } + val user = + testData.addUserAccount { + username = "user" + } + val projectBuilder = + testData.addProject { + name = "Oh my project" + organizationOwner = user.defaultOrganizationBuilder.self + } - val langs = arrayOf( - projectBuilder.addEnglish(), - projectBuilder.addCzech(), - projectBuilder.addGerman(), - projectBuilder.addFrench() - ) + val langs = + arrayOf( + projectBuilder.addEnglish(), + projectBuilder.addCzech(), + projectBuilder.addGerman(), + projectBuilder.addFrench(), + ) val key = projectBuilder.addKey { name = "key" }.self langs.forEach { lang -> @@ -313,7 +323,7 @@ class V2ExportControllerTest : ProjectAuthControllerTest("/v2/projects/") { private fun retryingOnCommonIssues(fn: () -> Unit) { retry( retries = 10, - exceptionMatcher = { it is ConcurrentModificationException || it is DataIntegrityViolationException } + exceptionMatcher = { it is ConcurrentModificationException || it is DataIntegrityViolationException }, ) { fn() } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/V2InvitationControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/V2InvitationControllerTest.kt index 5829df38c9..4466bfc3d5 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/V2InvitationControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/V2InvitationControllerTest.kt @@ -20,7 +20,6 @@ import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired class V2InvitationControllerTest : AuthorizedControllerTest() { - @BeforeEach fun setup() { loginAsUser(initialUsername) @@ -55,12 +54,13 @@ class V2InvitationControllerTest : AuthorizedControllerTest() { val base = dbPopulator.createBase(generateUniqueString()) val project = base.project - val invitation = invitationService.create( - CreateProjectInvitationParams( - project, - ProjectPermissionType.EDIT + val invitation = + invitationService.create( + CreateProjectInvitationParams( + project, + ProjectPermissionType.EDIT, + ), ) - ) performAuthDelete("/v2/invitations/${invitation.id}").andIsOk assertThatThrownBy { invitationService.getInvitation(invitation.code) } @@ -70,12 +70,13 @@ class V2InvitationControllerTest : AuthorizedControllerTest() { fun `accepts invitation`() { val base = dbPopulator.createBase(generateUniqueString()) val project = base.project - val code = invitationService.create( - CreateProjectInvitationParams( - project, - ProjectPermissionType.EDIT - ) - ).code + val code = + invitationService.create( + CreateProjectInvitationParams( + project, + ProjectPermissionType.EDIT, + ), + ).code val newUser = dbPopulator.createUserIfNotExists(generateUniqueString(), "pwd") loginAsUser(newUser.username) @@ -88,13 +89,15 @@ class V2InvitationControllerTest : AuthorizedControllerTest() { fun `accepts translate invitation with languages`() { val base = dbPopulator.createBase(generateUniqueString()) val project = base.project - val code = invitationService.create( - CreateProjectInvitationParams( - project, - ProjectPermissionType.TRANSLATE, - LanguagePermissions(translate = project.languages, null, null), null - ) - ).code + val code = + invitationService.create( + CreateProjectInvitationParams( + project, + ProjectPermissionType.TRANSLATE, + LanguagePermissions(translate = project.languages, null, null), + null, + ), + ).code val newUser = dbPopulator.createUserIfNotExists(generateUniqueString(), "pwd") loginAsUser(newUser.username) @@ -105,7 +108,7 @@ class V2InvitationControllerTest : AuthorizedControllerTest() { private fun assertInvitationAccepted( project: Project, newUser: UserAccount, - expectedType: ProjectPermissionType + expectedType: ProjectPermissionType, ) { assertThat(invitationService.getForProject(project)).hasSize(0) assertThat(permissionService.getProjectPermissionScopes(project.id, newUser)).isNotNull @@ -121,8 +124,8 @@ class V2InvitationControllerTest : AuthorizedControllerTest() { languagePermissions = LanguagePermissions(translate = project.languages, view = null, stateChange = null), name = "Franta", email = "a@a.a", - scopes = null - ) + scopes = null, + ), ) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/V2LanguageControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/V2LanguageControllerTest.kt index 033ef25669..9cfc2cb543 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/V2LanguageControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/V2LanguageControllerTest.kt @@ -39,10 +39,13 @@ class V2LanguageControllerTest : ProjectAuthControllerTest("/v2/projects/") { val base = dbPopulator.createBase(generateUniqueString()) val project = base.project val en = project.findLanguageOptional("en").orElseThrow { NotFoundException() } - val languageDTO = LanguageDto( - name = "newEnglish", tag = "newEn", originalName = "newOriginalEnglish", - flagEmoji = "\uD83C\uDDEC\uD83C\uDDE7" - ) + val languageDTO = + LanguageDto( + name = "newEnglish", + tag = "newEn", + originalName = "newOriginalEnglish", + flagEmoji = "\uD83C\uDDEC\uD83C\uDDE7", + ) performEdit(project.id, en.id, languageDTO).andIsOk.andAssertThatJson { node("name").isEqualTo(languageDTO.name) node("originalName").isEqualTo(languageDTO.originalName) @@ -140,7 +143,7 @@ class V2LanguageControllerTest : ProjectAuthControllerTest("/v2/projects/") { val project = base.project performCreate( project.id, - LanguageDto(originalName = "Original name", name = "Name", tag = "aa,aa") + LanguageDto(originalName = "Original name", name = "Name", tag = "aa,aa"), ).andIsBadRequest.andAssertThatJson { node("STANDARD_VALIDATION.tag").isEqualTo("can not contain coma") } @@ -157,8 +160,9 @@ class V2LanguageControllerTest : ProjectAuthControllerTest("/v2/projects/") { } fun createLanguageTestValidation(repoId: Long) { - val mvcResult = performCreate(repoId, languageDTO) - .andExpect(MockMvcResultMatchers.status().isBadRequest).andReturn() + val mvcResult = + performCreate(repoId, languageDTO) + .andExpect(MockMvcResultMatchers.status().isBadRequest).andReturn() Assertions.assertThat(mvcResult.response.contentAsString).contains("language_tag_exists") Assertions.assertThat(mvcResult.response.contentAsString).contains("language_name_exists") performCreate(repoId, languageDTOBlank).andIsBadRequest.andAssertThatJson { @@ -178,15 +182,25 @@ class V2LanguageControllerTest : ProjectAuthControllerTest("/v2/projects/") { } } - private fun performCreate(projectId: Long, content: LanguageDto): ResultActions { + private fun performCreate( + projectId: Long, + content: LanguageDto, + ): ResultActions { return performAuthPost("/v2/projects/$projectId/languages", content) } - private fun performEdit(projectId: Long, languageId: Long, content: LanguageDto): ResultActions { + private fun performEdit( + projectId: Long, + languageId: Long, + content: LanguageDto, + ): ResultActions { return performAuthPut("/v2/projects/$projectId/languages/$languageId", content) } - private fun performDelete(projectId: Long, languageId: Long): ResultActions { + private fun performDelete( + projectId: Long, + languageId: Long, + ): ResultActions { return performAuthDelete("/v2/projects/$projectId/languages/$languageId", null) } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/V2UserControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/V2UserControllerTest.kt index 25f1af2680..2011eef4bd 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/V2UserControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/V2UserControllerTest.kt @@ -28,11 +28,10 @@ import java.util.* @ContextRecreatingTest @SpringBootTest( properties = [ - "tolgee.front-end-url=https://fake.frontend.url" - ] + "tolgee.front-end-url=https://fake.frontend.url", + ], ) class V2UserControllerTest : AuthorizedControllerTest() { - @Autowired override lateinit var tolgeeProperties: TolgeeProperties @@ -49,11 +48,12 @@ class V2UserControllerTest : AuthorizedControllerTest() { @Test fun `it updates the user profile`() { - val requestDTO = UserUpdateRequestDto( - email = "ben@ben.aa", - name = "Ben's new name", - currentPassword = initialPassword - ) + val requestDTO = + UserUpdateRequestDto( + email = "ben@ben.aa", + name = "Ben's new name", + currentPassword = initialPassword, + ) performAuthPut("/v2/user", requestDTO).andExpect(MockMvcResultMatchers.status().isOk) val fromDb = userAccountService.findActive(requestDTO.email) Assertions.assertThat(fromDb!!.name).isEqualTo(requestDTO.name) @@ -61,10 +61,11 @@ class V2UserControllerTest : AuthorizedControllerTest() { @Test fun `it updates the user password`() { - val requestDTO = UserUpdatePasswordRequestDto( - password = "super new password", - currentPassword = initialPassword - ) + val requestDTO = + UserUpdatePasswordRequestDto( + password = "super new password", + currentPassword = initialPassword, + ) performAuthPut("/v2/user/password", requestDTO).andExpect(MockMvcResultMatchers.status().isOk) val fromDb = userAccountService.findActive(initialUsername) Assertions.assertThat(passwordEncoder.matches(requestDTO.password, fromDb!!.password)) @@ -73,36 +74,42 @@ class V2UserControllerTest : AuthorizedControllerTest() { @Test fun `it validates the user update request data`() { - var requestDTO = UserUpdateRequestDto( - email = "ben@ben.aa", - name = "", - currentPassword = initialPassword - ) - var mvcResult = performAuthPut("/v2/user", requestDTO) - .andIsBadRequest.andReturn() + var requestDTO = + UserUpdateRequestDto( + email = "ben@ben.aa", + name = "", + currentPassword = initialPassword, + ) + var mvcResult = + performAuthPut("/v2/user", requestDTO) + .andIsBadRequest.andReturn() val standardValidation = assertThat(mvcResult).error().isStandardValidation standardValidation.onField("name") - requestDTO = UserUpdateRequestDto( - email = "ben@ben.aa", - name = "a", - currentPassword = initialPassword - ) + requestDTO = + UserUpdateRequestDto( + email = "ben@ben.aa", + name = "a", + currentPassword = initialPassword, + ) dbPopulator.createUserIfNotExists(requestDTO.email) - mvcResult = performAuthPut("/v2/user", requestDTO) - .andIsBadRequest.andReturn() + mvcResult = + performAuthPut("/v2/user", requestDTO) + .andIsBadRequest.andReturn() assertThat(mvcResult) .error().isCustomValidation.hasMessage("username_already_exists") } @Test fun `it validates the password change request data`() { - val requestDto = UserUpdatePasswordRequestDto( - password = "", - currentPassword = initialPassword - ) - val mvcResult = performAuthPut("/v2/user/password", requestDto) - .andIsBadRequest.andReturn() + val requestDto = + UserUpdatePasswordRequestDto( + password = "", + currentPassword = initialPassword, + ) + val mvcResult = + performAuthPut("/v2/user/password", requestDto) + .andIsBadRequest.andReturn() val standardValidation = assertThat(mvcResult).error().isStandardValidation standardValidation.onField("password") } @@ -112,11 +119,12 @@ class V2UserControllerTest : AuthorizedControllerTest() { val oldNeedsVerification = tolgeeProperties.authentication.needsEmailVerification tolgeeProperties.authentication.needsEmailVerification = true - val requestDTO = UserUpdateRequestDto( - email = "ben@ben.aaa", - name = "Ben Ben", - currentPassword = initialPassword - ) + val requestDTO = + UserUpdateRequestDto( + email = "ben@ben.aaa", + name = "Ben Ben", + currentPassword = initialPassword, + ) performAuthPut("/v2/user", requestDTO).andIsOk emailTestUtil.verifyEmailSent() @@ -163,10 +171,11 @@ class V2UserControllerTest : AuthorizedControllerTest() { @Test fun `it invalidates tokens generated prior a password change`() { - val requestDTO = UserUpdatePasswordRequestDto( - password = "super new password", - currentPassword = initialPassword - ) + val requestDTO = + UserUpdatePasswordRequestDto( + password = "super new password", + currentPassword = initialPassword, + ) loginAsAdminIfNotLogged() Thread.sleep(2000) @@ -203,9 +212,10 @@ class V2UserControllerTest : AuthorizedControllerTest() { testDataService.saveTestData(testData.root) assertSingleOwned(testData.franta, listOf("Franta")) assertSingleOwned(testData.olga, listOf("Olga")) - val roles = executeInNewTransaction { - userAccountService.get(testData.pepa.id).organizationRoles - } + val roles = + executeInNewTransaction { + userAccountService.get(testData.pepa.id).organizationRoles + } executeInNewTransaction { userAccountService.delete(userAccountService.get(testData.franta.id)) } @@ -227,8 +237,8 @@ class V2UserControllerTest : AuthorizedControllerTest() { performAuthPost( "/v2/user/generate-super-token", mapOf( - "password" to initialPassword - ) + "password" to initialPassword, + ), ).andIsOk.andAssertThatJson { node("accessToken").isString.satisfies { token: String -> val authentication = jwtService.validateToken(token) @@ -245,8 +255,8 @@ class V2UserControllerTest : AuthorizedControllerTest() { performAuthPost( "/v2/user/generate-super-token", mapOf( - "otp" to mfaService.generateStringCode(SensitiveOperationProtectionTestData.TOTP_KEY) - ) + "otp" to mfaService.generateStringCode(SensitiveOperationProtectionTestData.TOTP_KEY), + ), ).andIsOk.andAssertThatJson { node("accessToken").isString.satisfies { token: String -> val authentication = jwtService.validateToken(token) @@ -255,7 +265,10 @@ class V2UserControllerTest : AuthorizedControllerTest() { } } - private fun assertSingleOwned(user: UserAccount, names: List) { + private fun assertSingleOwned( + user: UserAccount, + names: List, + ) { userAccount = user performAuthGet("/v2/user/single-owned-organizations").andIsOk.andAssertThatJson { node("_embedded.organizations") { diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/batch/BatchJobManagementControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/batch/BatchJobManagementControllerTest.kt index 285e4b4ae9..2bd9d7f501 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/batch/BatchJobManagementControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/batch/BatchJobManagementControllerTest.kt @@ -49,7 +49,6 @@ import java.util.concurrent.atomic.AtomicInteger import kotlin.coroutines.CoroutineContext class BatchJobManagementControllerTest : ProjectAuthControllerTest("/v2/projects/"), Logging { - lateinit var testData: BatchJobsTestData @Autowired @@ -101,7 +100,7 @@ class BatchJobManagementControllerTest : ProjectAuthControllerTest("/v2/projects autoTranslationService, machineTranslationChunkProcessor, preTranslationByTmChunkProcessor, - batchJobActivityFinalizer + batchJobActivityFinalizer, ) } @@ -136,10 +135,11 @@ class BatchJobManagementControllerTest : ProjectAuthControllerTest("/v2/projects "start-batch-job/machine-translate", mapOf( "keyIds" to keyIds, - "targetLanguageIds" to listOf( - testData.projectBuilder.getLanguageByTag("cs")!!.self.id - ) - ) + "targetLanguageIds" to + listOf( + testData.projectBuilder.getLanguageByTag("cs")!!.self.id, + ), + ), ).andIsOk Thread.sleep(500) @@ -179,10 +179,11 @@ class BatchJobManagementControllerTest : ProjectAuthControllerTest("/v2/projects "start-batch-job/machine-translate", mapOf( "keyIds" to keyIds, - "targetLanguageIds" to listOf( - testData.projectBuilder.getLanguageByTag("cs")!!.self.id - ) - ) + "targetLanguageIds" to + listOf( + testData.projectBuilder.getLanguageByTag("cs")!!.self.id, + ), + ), ).andIsOk waitForNotThrowing(pollTime = 100) { @@ -253,7 +254,7 @@ class BatchJobManagementControllerTest : ProjectAuthControllerTest("/v2/projects dtos.forEach { val state = batchJobStateProvider.getCached(it.id) println( - "Job ${it.id} status ${it.status} progress: ${state?.values?.sumOf { it.successTargets.size }}" + "Job ${it.id} status ${it.status} progress: ${state?.values?.sumOf { it.successTargets.size }}", ) } dtos.count { it.status == BatchJobStatus.SUCCESS }.assert.isEqualTo(2) @@ -422,16 +423,20 @@ class BatchJobManagementControllerTest : ProjectAuthControllerTest("/v2/projects this.projectSupplier = { testData.projectBuilder.self } } - protected fun runChunkedJob(keyCount: Int, author: UserAccount = testData.user): BatchJob { + protected fun runChunkedJob( + keyCount: Int, + author: UserAccount = testData.user, + ): BatchJob { return executeInNewTransaction { batchJobService.startJob( - request = PreTranslationByTmRequest().apply { - keyIds = (1L..keyCount).map { it } - }, + request = + PreTranslationByTmRequest().apply { + keyIds = (1L..keyCount).map { it } + }, project = testData.projectBuilder.self, author = author, type = BatchJobType.PRE_TRANSLATE_BT_TM, - isHidden = false + isHidden = false, ) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/batch/StartBatchJobControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/batch/StartBatchJobControllerTest.kt index b69d0301d1..09e2fe6d3a 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/batch/StartBatchJobControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/batch/StartBatchJobControllerTest.kt @@ -76,11 +76,12 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { "start-batch-job/pre-translate-by-tm", mapOf( "keyIds" to keyIds, - "targetLanguageIds" to listOf( - testData.projectBuilder.getLanguageByTag("cs")!!.self.id, - testData.projectBuilder.getLanguageByTag("de")!!.self.id - ) - ) + "targetLanguageIds" to + listOf( + testData.projectBuilder.getLanguageByTag("cs")!!.self.id, + testData.projectBuilder.getLanguageByTag("de")!!.self.id, + ), + ), ) .andIsOk .andAssertThatJson { @@ -89,8 +90,9 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { waitForAllTranslated(keyIds, keyCount, "cs") executeInNewTransaction { - val jobs = entityManager.createQuery("""from BatchJob""", BatchJob::class.java) - .resultList + val jobs = + entityManager.createQuery("""from BatchJob""", BatchJob::class.java) + .resultList jobs.assert.hasSize(1) val job = jobs[0] job.status.assert.isEqualTo(BatchJobStatus.SUCCESS) @@ -112,11 +114,12 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { "start-batch-job/machine-translate", mapOf( "keyIds" to keyIds, - "targetLanguageIds" to listOf( - testData.projectBuilder.getLanguageByTag("cs")!!.self.id, - testData.projectBuilder.getLanguageByTag("de")!!.self.id - ) - ) + "targetLanguageIds" to + listOf( + testData.projectBuilder.getLanguageByTag("cs")!!.self.id, + testData.projectBuilder.getLanguageByTag("de")!!.self.id, + ), + ), ) .andIsOk .andAssertThatJson { @@ -125,8 +128,9 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { waitForAllTranslated(keyIds, keyCount) executeInNewTransaction { - val jobs = entityManager.createQuery("""from BatchJob""", BatchJob::class.java) - .resultList + val jobs = + entityManager.createQuery("""from BatchJob""", BatchJob::class.java) + .resultList jobs.assert.hasSize(1) val job = jobs[0] job.status.assert.isEqualTo(BatchJobStatus.SUCCESS) @@ -138,14 +142,16 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { private fun waitForAllTranslated( keyIds: List, keyCount: Int, - expectedCsValue: String = "translated with GOOGLE from en to cs" + expectedCsValue: String = "translated with GOOGLE from en to cs", ) { waitForNotThrowing(pollTime = 1000, timeout = 60000) { - @Suppress("UNCHECKED_CAST") val czechTranslations = entityManager.createQuery( - """ - from Translation t where t.key.id in :keyIds and t.language.tag = 'cs' - """.trimIndent() - ).setParameter("keyIds", keyIds).resultList as List + @Suppress("UNCHECKED_CAST") + val czechTranslations = + entityManager.createQuery( + """ + from Translation t where t.key.id in :keyIds and t.language.tag = 'cs' + """.trimIndent(), + ).setParameter("keyIds", keyIds).resultList as List czechTranslations.assert.hasSize(keyCount) czechTranslations.forEach { it.text.assert.contains(expectedCsValue) @@ -166,7 +172,7 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { "start-batch-job/delete-keys", mapOf( "keyIds" to keyIds, - ) + ), ).andIsOk.waitForJobCompleted() waitForNotThrowing(pollTime = 1000, timeout = 10000) { @@ -176,9 +182,10 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { waitForNotThrowing(pollTime = 1000, timeout = 10000) { executeInNewTransaction { - val data = entityManager - .createQuery("""from BatchJob""", BatchJob::class.java) - .resultList + val data = + entityManager + .createQuery("""from BatchJob""", BatchJob::class.java) + .resultList data.assert.hasSize(1) data[0].activityRevision.assert.isNotNull @@ -203,14 +210,16 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { mapOf( "keyIds" to keyIds, "languageIds" to languagesToChangeStateIds, - "state" to "REVIEWED" - ) + "state" to "REVIEWED", + ), ).andIsOk waitForNotThrowing(pollTime = 1000, timeout = 10000) { - val all = translationService.getTranslations( - keys.map { it.id }, allLanguageIds - ) + val all = + translationService.getTranslations( + keys.map { it.id }, + allLanguageIds, + ) all.count { it.state == TranslationState.REVIEWED }.assert.isEqualTo(keyIds.size * 2) } } @@ -232,13 +241,15 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { mapOf( "keyIds" to keyIds, "languageIds" to languagesToClearIds, - ) + ), ).andIsOk waitForNotThrowing(pollTime = 1000, timeout = 10000) { - val all = translationService.getTranslations( - keys.map { it.id }, allLanguageIds - ) + val all = + translationService.getTranslations( + keys.map { it.id }, + allLanguageIds, + ) all.count { it.state == TranslationState.UNTRANSLATED && it.text == null }.assert.isEqualTo(keyIds.size * 2) } } @@ -261,13 +272,15 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { "keyIds" to keyIds, "sourceLanguageId" to testData.englishLanguage.id, "targetLanguageIds" to languagesToChangeStateIds, - ) + ), ).andIsOk waitForNotThrowing(pollTime = 1000, timeout = 10000) { - val all = translationService.getTranslations( - keys.map { it.id }, allLanguageIds - ) + val all = + translationService.getTranslations( + keys.map { it.id }, + allLanguageIds, + ) all.count { it.text?.startsWith("en") == true }.assert.isEqualTo(allKeyIds.size + keyIds.size * 2) } } @@ -280,7 +293,7 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { mapOf( "keyIds" to listOf(1), "tags" to listOf("a".repeat(101)), - ) + ), ).andIsBadRequest.andPrettyPrint } @@ -300,7 +313,7 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { mapOf( "keyIds" to keyIds, "tags" to newTags, - ) + ), ).andIsOk waitForNotThrowing(pollTime = 1000, timeout = 10000) { @@ -327,8 +340,8 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { "start-batch-job/untag-keys", mapOf( "keyIds" to keyIds, - "tags" to tagsToRemove - ) + "tags" to tagsToRemove, + ), ).andIsOk waitForNotThrowing(pollTime = 1000, timeout = 10000) { @@ -345,8 +358,8 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { "start-batch-job/untag-keys", mapOf( "keyIds" to keyIds, - "tags" to listOf("a-tag") - ) + "tags" to listOf("a-tag"), + ), ).andIsOk } @@ -362,8 +375,8 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { "start-batch-job/untag-keys", mapOf( "keyIds" to listOf(aKeyId), - "tags" to listOf("a-tag") - ) + "tags" to listOf("a-tag"), + ), ).andIsOk waitForNotThrowing { tagService.find(testData.projectBuilder.self, "a-tag").assert.isNull() } } @@ -381,8 +394,8 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { "start-batch-job/set-keys-namespace", mapOf( "keyIds" to keyIds, - "namespace" to "other-namespace" - ) + "namespace" to "other-namespace", + ), ).andIsOk.waitForJobCompleted() val all = keyService.find(keyIds) @@ -397,27 +410,29 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { val key = testData.projectBuilder.addKey(keyName = "key").self saveAndPrepare() - val jobId = performProjectAuthPost( - "start-batch-job/set-keys-namespace", - mapOf( - "keyIds" to listOf(key.id), - "namespace" to "namespace" - ) - ).andIsOk.waitForJobCompleted().jobId + val jobId = + performProjectAuthPost( + "start-batch-job/set-keys-namespace", + mapOf( + "keyIds" to listOf(key.id), + "namespace" to "namespace", + ), + ).andIsOk.waitForJobCompleted().jobId keyService.get(key.id).namespace.assert.isNull() batchJobService.findJobDto(jobId)?.status.assert.isEqualTo(BatchJobStatus.FAILED) } - fun ResultActions.waitForJobCompleted() = andAssertThatJson { - node("id").isNumber.satisfies( - Consumer { - waitFor(pollTime = 2000) { - val job = batchJobService.findJobDto(it.toLong()) - job?.status?.completed == true - } - } - ) - } + fun ResultActions.waitForJobCompleted() = + andAssertThatJson { + node("id").isNumber.satisfies( + Consumer { + waitFor(pollTime = 2000) { + val job = batchJobService.findJobDto(it.toLong()) + job?.status?.completed == true + } + }, + ) + } val ResultActions.jobId: Long get() { @@ -426,7 +441,7 @@ class StartBatchJobControllerTest : ProjectAuthControllerTest("/v2/projects/") { node("id").isNumber.satisfies( Consumer { jobId = it.toLong() - } + }, ) } return jobId!! diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/contentDelivery/ContentDeliveryConfigControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/contentDelivery/ContentDeliveryConfigControllerTest.kt index 3d98f154ad..c03721f241 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/contentDelivery/ContentDeliveryConfigControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/contentDelivery/ContentDeliveryConfigControllerTest.kt @@ -33,7 +33,6 @@ import org.springframework.test.web.servlet.ResultActions @ContextRecreatingTest class ContentDeliveryConfigControllerTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: ContentDeliveryConfigTestData @Autowired @@ -60,9 +59,11 @@ class ContentDeliveryConfigControllerTest : ProjectAuthControllerTest("/v2/proje projectSupplier = { testData.projectBuilder.self } testDataService.saveTestData(testData.root) userAccount = testData.user - enabledFeaturesProvider.forceEnabled = setOf( - Feature.PROJECT_LEVEL_CONTENT_STORAGES, Feature.MULTIPLE_CONTENT_DELIVERY_CONFIGS - ) + enabledFeaturesProvider.forceEnabled = + setOf( + Feature.PROJECT_LEVEL_CONTENT_STORAGES, + Feature.MULTIPLE_CONTENT_DELIVERY_CONFIGS, + ) Mockito.reset(s3FileStorageFactory) Mockito.reset(azureFileStorageFactory) } @@ -102,7 +103,7 @@ class ContentDeliveryConfigControllerTest : ProjectAuthControllerTest("/v2/proje private fun createAzureConfig(): ResultActions { return performProjectAuthPost( "content-delivery-configs", - mapOf("name" to "Azure 2", "contentStorageId" to testData.azureContentStorage.self.id) + mapOf("name" to "Azure 2", "contentStorageId" to testData.azureContentStorage.self.id), ) } @@ -113,7 +114,7 @@ class ContentDeliveryConfigControllerTest : ProjectAuthControllerTest("/v2/proje var id: Long? = null performProjectAuthPost( "content-delivery-configs", - mapOf("name" to "Azure 2", "contentStorageId" to testData.azureContentStorage.self.id, "autoPublish" to true) + mapOf("name" to "Azure 2", "contentStorageId" to testData.azureContentStorage.self.id, "autoPublish" to true), ).andAssertThatJson { node("id").isNumber.satisfies { id = it.toLong() @@ -133,7 +134,7 @@ class ContentDeliveryConfigControllerTest : ProjectAuthControllerTest("/v2/proje fun `removes the automation on update`() { performProjectAuthPut( "content-delivery-configs/${testData.defaultServerContentDeliveryConfig.self.id}", - mapOf("name" to "DS", "autoPublish" to false) + mapOf("name" to "DS", "autoPublish" to false), ) executeInNewTransaction { contentDeliveryConfigService @@ -147,7 +148,7 @@ class ContentDeliveryConfigControllerTest : ProjectAuthControllerTest("/v2/proje fun `updates content delivery config`() { performProjectAuthPut( "content-delivery-configs/${testData.s3ContentDeliveryConfig.self.id}", - mapOf("name" to "S3 2", "contentStorageId" to testData.s3ContentStorage.self.id) + mapOf("name" to "S3 2", "contentStorageId" to testData.s3ContentStorage.self.id), ).andAssertThatJson { node("name").isEqualTo("S3 2") node("storage") { @@ -179,7 +180,7 @@ class ContentDeliveryConfigControllerTest : ProjectAuthControllerTest("/v2/proje @ProjectJWTAuthTestMethod fun `deletes content delivery config`() { performProjectAuthDelete( - "content-delivery-configs/${testData.defaultServerContentDeliveryConfig.self.id}" + "content-delivery-configs/${testData.defaultServerContentDeliveryConfig.self.id}", ).andIsOk contentDeliveryConfigService.find(testData.defaultServerContentDeliveryConfig.self.id).assert.isNull() } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/BaseOrganizationControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/BaseOrganizationControllerTest.kt index 91d1e2c76a..4f3ff4c78e 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/BaseOrganizationControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/BaseOrganizationControllerTest.kt @@ -18,21 +18,23 @@ class BaseOrganizationControllerTest : AuthorizedControllerTest() { } private fun resetDto() { - dummyDto = OrganizationDto( - "Test org", - "This is description", - "test-org", - ) + dummyDto = + OrganizationDto( + "Test org", + "This is description", + "test-org", + ) - dummyDto2 = OrganizationDto( - "Test org 2", - "This is description 2", - "test-org-2", - ) + dummyDto2 = + OrganizationDto( + "Test org 2", + "This is description 2", + "test-org-2", + ) } protected fun withOwnerInOrganization( - fn: (organization: Organization, owner: UserAccount, ownerRole: OrganizationRole) -> Unit + fn: (organization: Organization, owner: UserAccount, ownerRole: OrganizationRole) -> Unit, ) { executeInNewTransaction { this.organizationService.create(dummyDto, userAccount!!) } .let { organization -> @@ -40,7 +42,7 @@ class BaseOrganizationControllerTest : AuthorizedControllerTest() { OrganizationRole( user = createdUser, organization = organization, - type = OrganizationRoleType.OWNER + type = OrganizationRoleType.OWNER, ).let { createdOwnerRole -> organizationRoleRepository.save(createdOwnerRole) fn(organization, createdUser, createdOwnerRole) diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerInvitingTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerInvitingTest.kt index 9e79354bc3..d188069a90 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerInvitingTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerInvitingTest.kt @@ -26,7 +26,6 @@ import org.springframework.boot.test.context.SpringBootTest @SpringBootTest @AutoConfigureMockMvc class OrganizationControllerInvitingTest : AuthorizedControllerTest() { - companion object { private const val INVITED_EMAIL = "jon@doe.com" private const val INVITED_NAME = "Franta" @@ -40,11 +39,12 @@ class OrganizationControllerInvitingTest : AuthorizedControllerTest() { @BeforeEach fun setup() { - dummyDto = OrganizationDto( - "Test org", - "This is description", - "test-org", - ) + dummyDto = + OrganizationDto( + "Test org", + "This is description", + "test-org", + ) tolgeeProperties.frontEndUrl = null emailTestUtil.initMocks() } @@ -54,12 +54,13 @@ class OrganizationControllerInvitingTest : AuthorizedControllerTest() { val helloUser = dbPopulator.createUserIfNotExists("hellouser") this.organizationService.create(dummyDto, helloUser).let { organization -> - val invitation = invitationService.create( - CreateOrganizationInvitationParams( - organization = organization, - type = OrganizationRoleType.MEMBER + val invitation = + invitationService.create( + CreateOrganizationInvitationParams( + organization = organization, + type = OrganizationRoleType.MEMBER, + ), ) - ) loginAsUser("hellouser") performAuthGet("/v2/organizations/${organization.id}/invitations") .andIsOk.andAssertThatJson { @@ -92,12 +93,13 @@ class OrganizationControllerInvitingTest : AuthorizedControllerTest() { val helloUser = dbPopulator.createUserIfNotExists("hellouser") this.organizationService.create(dummyDto, helloUser).let { organization -> - val invitation = invitationService.create( - CreateOrganizationInvitationParams( - organization = organization, - type = OrganizationRoleType.OWNER + val invitation = + invitationService.create( + CreateOrganizationInvitationParams( + organization = organization, + type = OrganizationRoleType.OWNER, + ), ) - ) val invitedUser = dbPopulator.createUserIfNotExists("invitedUser") loginAsUser(invitedUser.username) performAuthGet("/v2/invitations/${invitation.code}/accept").andIsOk @@ -114,12 +116,13 @@ class OrganizationControllerInvitingTest : AuthorizedControllerTest() { val helloUser = dbPopulator.createUserIfNotExists("hellouser") this.organizationService.create(dummyDto, helloUser).let { organization -> - val invitation = invitationService.create( - CreateOrganizationInvitationParams( - organization = organization, - type = OrganizationRoleType.MEMBER + val invitation = + invitationService.create( + CreateOrganizationInvitationParams( + organization = organization, + type = OrganizationRoleType.MEMBER, + ), ) - ) val invitedUser = dbPopulator.createUserIfNotExists("invitedUser") this.organizationRoleService.grantMemberRoleToUser(invitedUser, organization) loginAsUser(invitedUser.username) @@ -131,12 +134,13 @@ class OrganizationControllerInvitingTest : AuthorizedControllerTest() { fun testDeleteInvitation() { val organization = prepareTestOrganization() - val invitation = invitationService.create( - CreateOrganizationInvitationParams( - organization = organization, - type = OrganizationRoleType.MEMBER + val invitation = + invitationService.create( + CreateOrganizationInvitationParams( + organization = organization, + type = OrganizationRoleType.MEMBER, + ), ) - ) performAuthDelete("/v2/invitations/${invitation.id!!}", null).andIsOk assertThatThrownBy { invitationService.getInvitation(invitation.code) } .isInstanceOf(BadRequestException::class.java) @@ -200,8 +204,8 @@ class OrganizationControllerInvitingTest : AuthorizedControllerTest() { OrganizationInviteUserDto( roleType = OrganizationRoleType.MEMBER, email = TEST_USERNAME, - name = INVITED_NAME - ) + name = INVITED_NAME, + ), ).andIsBadRequest } @@ -211,12 +215,13 @@ class OrganizationControllerInvitingTest : AuthorizedControllerTest() { return jacksonObjectMapper().readValue>(invitationJson)["code"] as String } - private fun performCreateInvitation(organizationId: Long) = performAuthPut( - "/v2/organizations/$organizationId/invite", - OrganizationInviteUserDto( - roleType = OrganizationRoleType.MEMBER, - email = INVITED_EMAIL, - name = INVITED_NAME + private fun performCreateInvitation(organizationId: Long) = + performAuthPut( + "/v2/organizations/$organizationId/invite", + OrganizationInviteUserDto( + roleType = OrganizationRoleType.MEMBER, + email = INVITED_EMAIL, + name = INVITED_NAME, + ), ) - ) } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerLeavingTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerLeavingTest.kt index ba9bf3985c..9d9f5b1e18 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerLeavingTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerLeavingTest.kt @@ -16,7 +16,6 @@ import org.springframework.data.domain.PageRequest @SpringBootTest @AutoConfigureMockMvc class OrganizationControllerLeavingTest : BaseOrganizationControllerTest() { - @Test fun testLeaveOrganization() { val testOrg = executeInNewTransaction { this.organizationService.create(dummyDto, userAccount!!) } @@ -53,14 +52,14 @@ class OrganizationControllerLeavingTest : BaseOrganizationControllerTest() { permissionService.getProjectPermissionData( testData.projectBuilder.self.id, - me.id + me.id, ).directPermissions.assert.isNotNull performAuthPut("/v2/organizations/${testData.organizationBuilder.self.id}/leave", null).andIsOk permissionService.getProjectPermissionData( testData.projectBuilder.self.id, - me.id + me.id, ).directPermissions.assert.isNull() } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerMembersTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerMembersTest.kt index 73bf064d71..943504f89d 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerMembersTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerMembersTest.kt @@ -98,7 +98,7 @@ class OrganizationControllerMembersTest : BaseOrganizationControllerTest() { loginAsUser(owner) performAuthPut( "/v2/organizations/${organization.id}/users/${owner.id}/set-role", - SetOrganizationRoleDto(OrganizationRoleType.MEMBER) + SetOrganizationRoleDto(OrganizationRoleType.MEMBER), ).andIsBadRequest.andHasErrorMessage(Message.CANNOT_SET_YOUR_OWN_ROLE) } } @@ -127,7 +127,7 @@ class OrganizationControllerMembersTest : BaseOrganizationControllerTest() { userAccount = testData.admin.self permissionService.getProjectPermissionData( testData.projectBuilder.self.id, - me.id + me.id, ).directPermissions.assert.isNotNull performAuthDelete("/v2/organizations/${testData.organizationBuilder.self.id}/users/${me.id}", null) .andIsOk @@ -163,7 +163,7 @@ class OrganizationControllerMembersTest : BaseOrganizationControllerTest() { performAuthPut( "/v2/projects/${testData.projectBuilder.self.id}/users/${testData.franta.id}/revoke-access", - null + null, ).andIsOk assertThat(userPreferencesService.find(testData.franta.id)!!.preferredOrganization) diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerTest.kt index 3d305f1906..7ae6542fe2 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerTest.kt @@ -67,9 +67,10 @@ class OrganizationControllerTest : BaseOrganizationControllerTest() { testDataService.saveTestData(testData.root) userAccount = testData.franta - val organization = testData.root.data.organizations.map { it.self } - .filter { it.name == "test_username" } - .single() + val organization = + testData.root.data.organizations.map { it.self } + .filter { it.name == "test_username" } + .single() performAuthGet("/v2/organizations/${organization.slug}/projects?size=100") .andPrettyPrint.andAssertThatJson.let { @@ -165,7 +166,7 @@ class OrganizationControllerTest : BaseOrganizationControllerTest() { fun testCreate() { performAuthPost( "/v2/organizations", - dummyDto + dummyDto, ).andIsCreated.andPrettyPrint.andAssertThatJson { node("name").isEqualTo("Test org") node("slug").isEqualTo("test-org") @@ -182,7 +183,7 @@ class OrganizationControllerTest : BaseOrganizationControllerTest() { performAuthPost( "/v2/organizations", - dummyDto.also { it.slug = "hello-1" } + dummyDto.also { it.slug = "hello-1" }, ).andIsBadRequest.andAssertError.isCustomValidation.hasMessage("address_part_not_unique") } @@ -192,7 +193,7 @@ class OrganizationControllerTest : BaseOrganizationControllerTest() { loginAsUserIfNotLogged() performAuthPost( "/v2/organizations", - dummyDto + dummyDto, ).andIsForbidden this.tolgeeProperties.authentication.userCanCreateOrganizations = true } @@ -201,27 +202,27 @@ class OrganizationControllerTest : BaseOrganizationControllerTest() { fun testCreateValidation() { performAuthPost( "/v2/organizations", - dummyDto.also { it.slug = "" } + dummyDto.also { it.slug = "" }, ).andIsBadRequest.let { assertThat(it.andReturn()).error().isStandardValidation.onField("slug") } performAuthPost( "/v2/organizations", - dummyDto.also { it.name = "" } + dummyDto.also { it.name = "" }, ).andIsBadRequest.let { assertThat(it.andReturn()).error().isStandardValidation.onField("name") } performAuthPost( "/v2/organizations", - dummyDto.also { it.slug = "sahsaldlasfhl " } + dummyDto.also { it.slug = "sahsaldlasfhl " }, ).andIsBadRequest.let { assertThat(it.andReturn()).error().isStandardValidation.onField("slug") } performAuthPost( "/v2/organizations", - dummyDto.also { it.slug = "a" } + dummyDto.also { it.slug = "a" }, ).andIsBadRequest.let { assertThat(it.andReturn()).error().isStandardValidation.onField("slug") } @@ -231,7 +232,7 @@ class OrganizationControllerTest : BaseOrganizationControllerTest() { fun testCreateGeneratesSlug() { performAuthPost( "/v2/organizations", - dummyDto.also { it.slug = null } + dummyDto.also { it.slug = null }, ).andIsCreated.andAssertThatJson { node("slug").isEqualTo("test-org") } } @@ -245,7 +246,7 @@ class OrganizationControllerTest : BaseOrganizationControllerTest() { organization.name = "Hello" organization.slug = "hello-1" organization.description = "This is changed description" - } + }, ).andIsOk.andPrettyPrint.andAssertThatJson { node("name").isEqualTo("Hello") node("slug").isEqualTo("hello-1") @@ -267,7 +268,7 @@ class OrganizationControllerTest : BaseOrganizationControllerTest() { "/v2/organizations/${organization.id}", dummyDto.also { organizationDto -> organizationDto.slug = "hello-1" - } + }, ).andIsBadRequest.andAssertError.isCustomValidation.hasMessage("address_part_not_unique") } @@ -281,11 +282,13 @@ class OrganizationControllerTest : BaseOrganizationControllerTest() { } } - private fun createOrganization(organizationDto: OrganizationDto) = executeInNewTransaction { - organizationService.create( - organizationDto, userAccount!! - ) - } + private fun createOrganization(organizationDto: OrganizationDto) = + executeInNewTransaction { + organizationService.create( + organizationDto, + userAccount!!, + ) + } @Test @Transactional @@ -293,7 +296,7 @@ class OrganizationControllerTest : BaseOrganizationControllerTest() { withOwnerInOrganization { organization, owner, role -> performAuthPut( "/v2/organizations/${organization.id}/users/${owner.id}/set-role", - SetOrganizationRoleDto(OrganizationRoleType.MEMBER) + SetOrganizationRoleDto(OrganizationRoleType.MEMBER), ).andIsOk role.let { assertThat(it.type).isEqualTo(OrganizationRoleType.MEMBER) } } @@ -306,7 +309,7 @@ class OrganizationControllerTest : BaseOrganizationControllerTest() { loginAsUser(owner) performAuthPut( "/v2/organizations/${organization.id}/set-base-permissions/REVIEW", - SetOrganizationRoleDto(OrganizationRoleType.MEMBER) + SetOrganizationRoleDto(OrganizationRoleType.MEMBER), ).andIsOk organizationService.get(organization.id).basePermission.type.assert.isEqualTo(ProjectPermissionType.REVIEW) diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationProjectsControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationProjectsControllerTest.kt index 01a1eb53be..e5476ac6b1 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationProjectsControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationProjectsControllerTest.kt @@ -16,7 +16,6 @@ import org.springframework.boot.test.context.SpringBootTest @SpringBootTest @AutoConfigureMockMvc class OrganizationProjectsControllerTest : AuthorizedControllerTest() { - @Test fun `get all projects with slug`() { val users = dbPopulator.createUsersAndOrganizations() @@ -96,9 +95,10 @@ class OrganizationProjectsControllerTest : AuthorizedControllerTest() { @Test fun `user with no direct permission cannot see the the project in organization with none base permissions`() { val testData = PermissionsTestData() - val user = testData.root.addUserAccount { - username = "pavek@stb.cz" - }.self + val user = + testData.root.addUserAccount { + username = "pavek@stb.cz" + }.self testData.organizationBuilder.self.basePermission.type = ProjectPermissionType.NONE testData.organizationBuilder.build { addRole { diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translationSuggestionController/TranslationSuggestionControllerStreamingTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translationSuggestionController/TranslationSuggestionControllerStreamingTest.kt index ff819b3245..bbfefdc4af 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translationSuggestionController/TranslationSuggestionControllerStreamingTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translationSuggestionController/TranslationSuggestionControllerStreamingTest.kt @@ -17,7 +17,6 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.mock.mockito.SpyBean class TranslationSuggestionControllerStreamingTest : ProjectAuthControllerTest("/v2/projects/") { - @Suppress("LateinitVarOverridesLateinitVar") @SpyBean @Autowired @@ -32,15 +31,16 @@ class TranslationSuggestionControllerStreamingTest : ProjectAuthControllerTest(" fun setup() { initMachineTranslationProperties( freeCreditsAmount = -1, - enabledServices = setOf(MtServiceType.GOOGLE, MtServiceType.TOLGEE, MtServiceType.DEEPL) + enabledServices = setOf(MtServiceType.GOOGLE, MtServiceType.TOLGEE, MtServiceType.DEEPL), ) Mockito.clearInvocations(mtService) internalProperties.fakeMtProviders = true - testData = BaseTestData().apply { - czechLanguage = projectBuilder.addCzech().self - hindiLanguage = projectBuilder.addHindi().self - } + testData = + BaseTestData().apply { + czechLanguage = projectBuilder.addCzech().self + hindiLanguage = projectBuilder.addHindi().self + } testDataService.saveTestData(testData.root) userAccount = testData.user @@ -50,15 +50,16 @@ class TranslationSuggestionControllerStreamingTest : ProjectAuthControllerTest(" @Test @ProjectJWTAuthTestMethod fun `it works`() { - val response = performProjectAuthPost( - "suggest/machine-translations-streaming", - mapOf( - "targetLanguageId" to czechLanguage.id, - "baseText" to "text" - ) - ).andDo { - it.asyncResult - }.andReturn().response.contentAsString + val response = + performProjectAuthPost( + "suggest/machine-translations-streaming", + mapOf( + "targetLanguageId" to czechLanguage.id, + "baseText" to "text", + ), + ).andDo { + it.asyncResult + }.andReturn().response.contentAsString response.split("\n").filter { it.isNotBlank() }.map { jacksonObjectMapper().readValue(it, Any::class.java) @@ -68,34 +69,36 @@ class TranslationSuggestionControllerStreamingTest : ProjectAuthControllerTest(" @Test @ProjectJWTAuthTestMethod fun `it returns json error on 400`() { - val response = performProjectAuthPost( - "suggest/machine-translations-streaming", - mapOf( - "targetLanguageId" to czechLanguage.id, - "keyId" to -1 + val response = + performProjectAuthPost( + "suggest/machine-translations-streaming", + mapOf( + "targetLanguageId" to czechLanguage.id, + "keyId" to -1, + ), + ).andPrettyPrint.andAssertThatJson.isEqualTo( + """ + { + "code" : "key_not_found", + "params" : null + } + """.trimIndent(), ) - ).andPrettyPrint.andAssertThatJson.isEqualTo( - """ - { - "code" : "key_not_found", - "params" : null - } - """.trimIndent() - ) } @Test @ProjectJWTAuthTestMethod fun `it does not return unsupporting services`() { - val response = performProjectAuthPost( - "suggest/machine-translations-streaming", - mapOf( - "targetLanguageId" to hindiLanguage.id, - "baseText" to "text" - ) - ).andDo { - it.asyncResult - }.andReturn().response.contentAsString + val response = + performProjectAuthPost( + "suggest/machine-translations-streaming", + mapOf( + "targetLanguageId" to hindiLanguage.id, + "baseText" to "text", + ), + ).andDo { + it.asyncResult + }.andReturn().response.contentAsString response.split("\n").filter { it.isNotBlank() }.map { jacksonObjectMapper().readValue(it, Any::class.java) diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translationSuggestionController/TranslationSuggestionControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translationSuggestionController/TranslationSuggestionControllerTest.kt index 0a4c162bd8..22521b34a6 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translationSuggestionController/TranslationSuggestionControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translationSuggestionController/TranslationSuggestionControllerTest.kt @@ -118,18 +118,19 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje private fun initMachineTranslationMocks() { val googleTranslationMock = mock() as Translation - val awsTranslateTextResult = TranslateTextResponse - .builder() - .translatedText("Translated with Amazon") - .build() + val awsTranslateTextResult = + TranslateTextResponse + .builder() + .translatedText("Translated with Amazon") + .build() whenever( googleTranslate.translate( any(), any(), any(), - any() - ) + any(), + ), ).thenReturn(googleTranslationMock) whenever(googleTranslationMock.translatedText).thenReturn("Translated with Google") @@ -141,8 +142,8 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje any(), any(), any(), - any() - ) + any(), + ), ).thenReturn("Translated with DeepL") whenever( @@ -150,7 +151,7 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje any(), any(), any(), - ) + ), ).thenReturn("Translated with Azure Cognitive") whenever( @@ -158,7 +159,7 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje any(), any(), any(), - ) + ), ).thenReturn("Translated with Baidu") tolgeeTranslateParamsCaptor = argumentCaptor() @@ -166,11 +167,11 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje whenever( tolgeeTranslateApiService.translate( tolgeeTranslateParamsCaptor.capture(), - ) + ), ).thenAnswer { MtValueProvider.MtResult( "Translated with Tolgee Translator", - ((it.arguments[0] as? TolgeeTranslateApiService.Companion.TolgeeTranslateParams)?.text?.length ?: 0) * 100 + ((it.arguments[0] as? TolgeeTranslateApiService.Companion.TolgeeTranslateParams)?.text?.length ?: 0) * 100, ) } } @@ -186,7 +187,7 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje saveTestData() performAuthPost( "/v2/projects/${project.id}/suggest/translation-memory", - SuggestRequestDto(keyId = testData.thisIsBeautifulKey.id, targetLanguageId = testData.germanLanguage.id) + SuggestRequestDto(keyId = testData.thisIsBeautifulKey.id, targetLanguageId = testData.germanLanguage.id), ).andIsOk.andPrettyPrint.andAssertThatJson { node("_embedded.translationMemoryItems") { node("[0]") { @@ -206,7 +207,7 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje saveTestData() performAuthPost( "/v2/projects/${project.id}/suggest/translation-memory", - SuggestRequestDto(baseText = "This is beautiful", targetLanguageId = testData.germanLanguage.id) + SuggestRequestDto(baseText = "This is beautiful", targetLanguageId = testData.germanLanguage.id), ).andIsOk.andPrettyPrint.andAssertThatJson { node("_embedded.translationMemoryItems") { node("[0]") { @@ -225,12 +226,13 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje fun `it suggests from TM fast enough`() { testData.generateLotOfData() saveTestData() - val time = measureTimeMillis { - performAuthPost( - "/v2/projects/${project.id}/suggest/translation-memory", - SuggestRequestDto(keyId = testData.beautifulKey.id, targetLanguageId = testData.germanLanguage.id) - ).andIsOk - } + val time = + measureTimeMillis { + performAuthPost( + "/v2/projects/${project.id}/suggest/translation-memory", + SuggestRequestDto(keyId = testData.beautifulKey.id, targetLanguageId = testData.germanLanguage.id), + ).andIsOk + } assertThat(time).isLessThan(1500) } @@ -240,7 +242,7 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje saveTestData() performAuthPost( "/v2/projects/${project.id}/suggest/machine-translations", - SuggestRequestDto(keyId = testData.beautifulKey.id, targetLanguageId = testData.germanLanguage.id) + SuggestRequestDto(keyId = testData.beautifulKey.id, targetLanguageId = testData.germanLanguage.id), ).andIsOk.andPrettyPrint.andAssertThatJson { node("machineTranslations") { node("GOOGLE").isEqualTo("Translated with Google") @@ -256,7 +258,7 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje saveTestData() performAuthPost( "/v2/projects/${project.id}/suggest/machine-translations", - SuggestRequestDto(baseText = "Yupee", targetLanguageId = testData.germanLanguage.id) + SuggestRequestDto(baseText = "Yupee", targetLanguageId = testData.germanLanguage.id), ).andIsOk.andPrettyPrint.andAssertThatJson { node("machineTranslations") { node("GOOGLE").isEqualTo("Translated with Google") @@ -276,7 +278,7 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje { "AWS": "Translated with Amazon" } - """ + """, ) } } @@ -344,7 +346,7 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje { "AWS": "Translated with Amazon" } - """ + """, ) } } @@ -408,7 +410,7 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje saveTestData() performAuthPost( "/v2/projects/${project.id}/suggest/machine-translations", - SuggestRequestDto(keyId = testData.beautifulKey.id, targetLanguageId = testData.germanLanguage.id) + SuggestRequestDto(keyId = testData.beautifulKey.id, targetLanguageId = testData.germanLanguage.id), ).andIsOk.andPrettyPrint.andAssertThatJson { node("machineTranslations") { node("GOOGLE").isEqualTo("Translated with Google") @@ -416,7 +418,7 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje } performAuthPost( "/v2/projects/${project.id}/suggest/machine-translations", - SuggestRequestDto(keyId = testData.beautifulKey.id, targetLanguageId = testData.germanLanguage.id) + SuggestRequestDto(keyId = testData.beautifulKey.id, targetLanguageId = testData.germanLanguage.id), ).andIsBadRequest } @@ -432,8 +434,8 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje contextDescription = "context", actualPrice = 100, usedService = MtServiceType.GOOGLE, - baseBlank = false - ) + baseBlank = false, + ), ) performMtRequestAndExpectAfterBalance(10) } @@ -487,8 +489,9 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje testData.enableAWS(Formality.FORMAL) saveTestData() performMtRequest() - val request = Mockito.mockingDetails(amazonTranslate).invocations.first().arguments[0] - as TranslateTextRequest + val request = + Mockito.mockingDetails(amazonTranslate).invocations.first().arguments[0] + as TranslateTextRequest request.settings().formality().assert.isEqualTo(AwsFormality.FORMAL) } @@ -498,7 +501,10 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje performMtRequestAndExpectBadRequest() } - private fun performMtRequestAndExpectAfterBalance(creditBalance: Long, extraCreditBalance: Long = 0) { + private fun performMtRequestAndExpectAfterBalance( + creditBalance: Long, + extraCreditBalance: Long = 0, + ) { performMtRequest().andIsOk mtCreditBucketService.getCreditBalances(testData.projectBuilder.self).creditBalance .assert.isEqualTo(creditBalance * 100) @@ -516,8 +522,8 @@ class TranslationSuggestionControllerTest : ProjectAuthControllerTest("/v2/proje SuggestRequestDto( keyId = testData.beautifulKey.id, targetLanguageId = testData.germanLanguage.id, - services = services?.toSet() - ) + services = services?.toSet(), + ), ) } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/TranslationCommentControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/TranslationCommentControllerTest.kt index 52f9402b2c..90107d2eeb 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/TranslationCommentControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/TranslationCommentControllerTest.kt @@ -24,7 +24,6 @@ import java.math.BigDecimal @SpringBootTest @AutoConfigureMockMvc class TranslationCommentControllerTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: TranslationCommentsTestData @BeforeEach @@ -72,8 +71,8 @@ class TranslationCommentControllerTest : ProjectAuthControllerTest("/v2/projects "translations/${testData.translation.id}/comments", TranslationCommentDto( text = "Test", - state = TranslationCommentState.RESOLUTION_NOT_NEEDED - ) + state = TranslationCommentState.RESOLUTION_NOT_NEEDED, + ), ).andIsCreated.andAssertThatJson { node("id").isValidId node("text").isEqualTo("Test") @@ -94,8 +93,8 @@ class TranslationCommentControllerTest : ProjectAuthControllerTest("/v2/projects keyId = testData.bKey.id, testData.englishLanguage.id, text = "Test", - state = TranslationCommentState.RESOLUTION_NOT_NEEDED - ) + state = TranslationCommentState.RESOLUTION_NOT_NEEDED, + ), ).andIsCreated.andAssertThatJson { node("comment") { node("id").isValidId @@ -120,8 +119,8 @@ class TranslationCommentControllerTest : ProjectAuthControllerTest("/v2/projects "translations/${testData.translation.id}/comments", mapOf( "text" to "", - "state" to "DUMMY" - ) + "state" to "DUMMY", + ), ).andIsBadRequest.andPrettyPrint.andAssertThatJson { node("params[0]").isString.startsWith("Cannot deserialize value of type") } @@ -134,8 +133,8 @@ class TranslationCommentControllerTest : ProjectAuthControllerTest("/v2/projects "translations/${testData.translation.id}/comments", mapOf( "text" to "", - "state" to "RESOLVED" - ) + "state" to "RESOLVED", + ), ).andIsBadRequest.andPrettyPrint.andAssertThatJson { node("STANDARD_VALIDATION").isObject } @@ -148,8 +147,8 @@ class TranslationCommentControllerTest : ProjectAuthControllerTest("/v2/projects "translations/${testData.translation.id}/comments/${testData.firstComment.id}", mapOf( "text" to "", - "state" to "RESOLVED" - ) + "state" to "RESOLVED", + ), ).andIsBadRequest.andPrettyPrint.andAssertThatJson { node("STANDARD_VALIDATION").isObject } @@ -162,8 +161,8 @@ class TranslationCommentControllerTest : ProjectAuthControllerTest("/v2/projects "translations/${testData.translation.id}/comments/${testData.firstComment.id}", TranslationCommentDto( text = "Updated", - state = TranslationCommentState.RESOLVED - ) + state = TranslationCommentState.RESOLVED, + ), ).andIsOk.andAssertThatJson { node("id").isValidId node("text").isEqualTo("Updated") @@ -182,8 +181,8 @@ class TranslationCommentControllerTest : ProjectAuthControllerTest("/v2/projects "translations/${testData.translation.id}/comments/${testData.firstComment.id}", TranslationCommentDto( text = "Updated", - state = TranslationCommentState.RESOLVED - ) + state = TranslationCommentState.RESOLVED, + ), ).andIsBadRequest.andPrettyPrint } @@ -192,7 +191,7 @@ class TranslationCommentControllerTest : ProjectAuthControllerTest("/v2/projects fun `updates comment state`() { performProjectAuthPut( "translations/${testData.translation.id}/comments/${testData.firstComment.id}/set-state/RESOLVED", - null + null, ).andIsOk.andAssertThatJson { node("text").isEqualTo("First comment") node("state").isEqualTo("RESOLVED") @@ -204,7 +203,7 @@ class TranslationCommentControllerTest : ProjectAuthControllerTest("/v2/projects fun `deletes comment`() { performProjectAuthDelete( "translations/${testData.translation.id}/comments/${testData.firstComment.id}", - null + null, ).andIsOk assertThat(translationCommentService.find(testData.firstComment.id)).isNull() @@ -217,7 +216,7 @@ class TranslationCommentControllerTest : ProjectAuthControllerTest("/v2/projects userAccount = testData.pepa performProjectAuthDelete( "translations/${testData.translation.id}/comments/${testData.firstComment.id}", - null + null, ).andIsBadRequest.andPrettyPrint } } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerCachingTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerCachingTest.kt index 2a3e8db7ea..a45c94f8d2 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerCachingTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerCachingTest.kt @@ -21,7 +21,6 @@ import java.util.* @SpringBootTest @AutoConfigureMockMvc class TranslationsControllerCachingTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: TranslationsTestData @BeforeEach @@ -84,12 +83,16 @@ class TranslationsControllerCachingTest : ProjectAuthControllerTest("/v2/project return performGet("/v2/projects/translations/en,de", headers) } - private fun performAndGetLastModified(): String? = performProjectAuthGet("/translations/en,de") - .andIsOk.lastModified() + private fun performAndGetLastModified(): String? = + performProjectAuthGet("/translations/en,de") + .andIsOk.lastModified() private fun ResultActions.lastModified() = this.andReturn().response.getHeader("Last-Modified") - private fun assertEqualsDate(lastModified: String?, now: Date) { + private fun assertEqualsDate( + lastModified: String?, + now: Date, + ) { val zdt: ZonedDateTime = ZonedDateTime.parse(lastModified, DateTimeFormatter.RFC_1123_DATE_TIME) (zdt.toInstant().toEpochMilli() / 1000).assert.isEqualTo(now.time / 1000) } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerCursorTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerCursorTest.kt index 8a2e0e5078..ecfb0b8dab 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerCursorTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerCursorTest.kt @@ -16,7 +16,6 @@ import org.springframework.boot.test.context.SpringBootTest @SpringBootTest @AutoConfigureMockMvc class TranslationsControllerCursorTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: TranslationsTestData @BeforeEach @@ -145,7 +144,10 @@ class TranslationsControllerCursorTest : ProjectAuthControllerTest("/v2/projects assertWithCursorReturnsAll("sort=keyNamespace,DESC&sort=keyName", 5) } - private fun assertWithCursorReturnsAll(sortQuery: String, expectedSize: Int) { + private fun assertWithCursorReturnsAll( + sortQuery: String, + expectedSize: Int, + ) { var pageCount = 0 var cursor: String? = null do { diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerFilterTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerFilterTest.kt index 2b58dc8865..c0420b8ced 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerFilterTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerFilterTest.kt @@ -20,7 +20,6 @@ import java.math.BigDecimal @SpringBootTest @AutoConfigureMockMvc class TranslationsControllerFilterTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: TranslationsTestData @BeforeEach diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerHistoryTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerHistoryTest.kt index 15f787b660..9274020808 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerHistoryTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerHistoryTest.kt @@ -22,7 +22,6 @@ import java.util.* @SpringBootTest @AutoConfigureMockMvc class TranslationsControllerHistoryTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var translation: Translation lateinit var testUser: UserAccount @@ -49,10 +48,11 @@ class TranslationsControllerHistoryTest : ProjectAuthControllerTest("/v2/project type = ProjectPermissionType.TRANSLATE project = testProject } - lang = addLanguage { - name = "Deutsch" - tag = "de" - }.self + lang = + addLanguage { + name = "Deutsch" + tag = "de" + }.self addKey { name = "yey" @@ -111,24 +111,30 @@ class TranslationsControllerHistoryTest : ProjectAuthControllerTest("/v2/project fun `does not return comment added events`() { performProjectAuthPost( "/translations/create-comment", - mapOf("keyId" to emptyKey.id, "languageId" to lang.id, "text" to "Yey!") + mapOf("keyId" to emptyKey.id, "languageId" to lang.id, "text" to "Yey!"), ) - val translation = transactionTemplate.execute { - translationService.find(emptyKey, lang).get() - } + val translation = + transactionTemplate.execute { + translationService.find(emptyKey, lang).get() + } performProjectAuthGet("/translations/${translation.id}/history").andPrettyPrint.andAssertThatJson { node("page.totalElements").isEqualTo(0) } } - private fun updateTranslation(testTranslation: Translation, newText: String) { + private fun updateTranslation( + testTranslation: Translation, + newText: String, + ) { performProjectAuthPut( "/translations", SetTranslationsWithKeyDto( - testTranslation.key.name, null, mutableMapOf(testTranslation.language.tag to newText) - ) + testTranslation.key.name, + null, + mutableMapOf(testTranslation.language.tag to newText), + ), ).andIsOk } } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerLanguagePermissionTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerLanguagePermissionTest.kt index 23fa9e6d0e..d1b45ebba4 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerLanguagePermissionTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerLanguagePermissionTest.kt @@ -15,7 +15,6 @@ import org.springframework.boot.test.context.SpringBootTest @SpringBootTest @AutoConfigureMockMvc class TranslationsControllerLanguagePermissionTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: LanguagePermissionsTestData @BeforeEach @@ -101,14 +100,18 @@ class TranslationsControllerLanguagePermissionTest : ProjectAuthControllerTest(" }.andIsOk } - private fun performUpdate(lang: String) = performProjectAuthPut( - "/translations", - SetTranslationsWithKeyDto( - "key", null, mutableMapOf(lang to lang) + private fun performUpdate(lang: String) = + performProjectAuthPut( + "/translations", + SetTranslationsWithKeyDto( + "key", + null, + mutableMapOf(lang to lang), + ), ) - ) - private fun performSetState(translationId: Long) = performProjectAuthPut( - "/translations/$translationId/set-state/REVIEWED" - ) + private fun performSetState(translationId: Long) = + performProjectAuthPut( + "/translations/$translationId/set-state/REVIEWED", + ) } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerModificationTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerModificationTest.kt index c10c2154d3..3f5cb2e079 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerModificationTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerModificationTest.kt @@ -24,7 +24,6 @@ import org.springframework.http.HttpHeaders @SpringBootTest @AutoConfigureMockMvc class TranslationsControllerModificationTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: TranslationsTestData @BeforeEach @@ -39,8 +38,10 @@ class TranslationsControllerModificationTest : ProjectAuthControllerTest("/v2/pr performProjectAuthPut( "/translations", SetTranslationsWithKeyDto( - "A key", null, mutableMapOf("en" to "English") - ) + "A key", + null, + mutableMapOf("en" to "English"), + ), ).andIsOk .andAssertThatJson { node("translations.en.text").isEqualTo("English") @@ -57,8 +58,11 @@ class TranslationsControllerModificationTest : ProjectAuthControllerTest("/v2/pr performProjectAuthPut( "/translations", SetTranslationsWithKeyDto( - "A key", null, mutableMapOf("en" to "English"), setOf("en", "de") - ) + "A key", + null, + mutableMapOf("en" to "English"), + setOf("en", "de"), + ), ).andIsOk .andAssertThatJson { node("translations.en.text").isEqualTo("English") @@ -74,8 +78,10 @@ class TranslationsControllerModificationTest : ProjectAuthControllerTest("/v2/pr performProjectAuthPut( "/translations", SetTranslationsWithKeyDto( - "A key", null, mutableMapOf("en" to text) - ) + "A key", + null, + mutableMapOf("en" to text), + ), ).andIsBadRequest } @@ -110,7 +116,7 @@ class TranslationsControllerModificationTest : ProjectAuthControllerTest("/v2/pr saveTestData() performProjectAuthPut( "/translations", - SetTranslationsWithKeyDto("A key", null, mutableMapOf("en" to "English")) + SetTranslationsWithKeyDto("A key", null, mutableMapOf("en" to "English")), ).andIsForbidden } @@ -120,7 +126,7 @@ class TranslationsControllerModificationTest : ProjectAuthControllerTest("/v2/pr saveTestData() performProjectAuthPost( "/translations", - SetTranslationsWithKeyDto("A key", null, mutableMapOf("en" to "English")) + SetTranslationsWithKeyDto("A key", null, mutableMapOf("en" to "English")), ).andIsOk } @@ -133,7 +139,7 @@ class TranslationsControllerModificationTest : ProjectAuthControllerTest("/v2/pr SetTranslationsWithKeyDto("A key", null, mutableMapOf("en" to "English")), HttpHeaders().apply { add("X-API-Key", "tgpat_${pat.token}") - } + }, ).andIsOk } @@ -143,7 +149,7 @@ class TranslationsControllerModificationTest : ProjectAuthControllerTest("/v2/pr saveTestData() performProjectAuthPost( "/translations", - SetTranslationsWithKeyDto("A key not existings", null, mutableMapOf("en" to "English")) + SetTranslationsWithKeyDto("A key not existings", null, mutableMapOf("en" to "English")), ).andIsForbidden } @@ -155,8 +161,10 @@ class TranslationsControllerModificationTest : ProjectAuthControllerTest("/v2/pr performProjectAuthPut( "/translations", SetTranslationsWithKeyDto( - "A key", null, mutableMapOf("en" to "English", "de" to null) - ) + "A key", + null, + mutableMapOf("en" to "English", "de" to null), + ), ).andIsOk .andAssertThatJson { node("translations.en.text").isEqualTo("English") @@ -178,8 +186,10 @@ class TranslationsControllerModificationTest : ProjectAuthControllerTest("/v2/pr performProjectAuthPost( "/translations", SetTranslationsWithKeyDto( - "Super ultra cool new key", null, mutableMapOf("en" to "English") - ) + "Super ultra cool new key", + null, + mutableMapOf("en" to "English"), + ), ).andIsOk.andAssertThatJson { node("translations.en.text").isEqualTo("English") node("translations.en.id").isValidId @@ -196,8 +206,10 @@ class TranslationsControllerModificationTest : ProjectAuthControllerTest("/v2/pr performProjectAuthPut( "/translations", SetTranslationsWithKeyDto( - "lala", null, mutableMapOf("en" to "English") - ) + "lala", + null, + mutableMapOf("en" to "English"), + ), ).andIsOk.andAssertThatJson { node("translations.en.text").isEqualTo("English") node("translations.en.id").isValidId @@ -216,8 +228,8 @@ class TranslationsControllerModificationTest : ProjectAuthControllerTest("/v2/pr key = "state test key", namespace = null, translations = mutableMapOf("en" to "b"), - languagesToReturn = setOf("en", "de") - ) + languagesToReturn = setOf("en", "de"), + ), ).andAssertThatJson { node("translations.en.outdated").isEqualTo(false) node("translations.de.outdated").isEqualTo(true) @@ -235,8 +247,8 @@ class TranslationsControllerModificationTest : ProjectAuthControllerTest("/v2/pr key = "state test key", namespace = null, translations = mutableMapOf("de" to "new"), - languagesToReturn = setOf("en", "de") - ) + languagesToReturn = setOf("en", "de"), + ), ).andAssertThatJson { node("translations.en.outdated").isEqualTo(false) node("translations.de.outdated").isEqualTo(false) @@ -250,7 +262,7 @@ class TranslationsControllerModificationTest : ProjectAuthControllerTest("/v2/pr val translation = testData.aKeyGermanTranslation performProjectAuthPut( "/translations/${translation.id}/dismiss-auto-translated-state", - null + null, ).andIsOk val updatedTranslation = translationService.get(translation.id) assertThat(updatedTranslation.auto).isEqualTo(false) @@ -266,10 +278,13 @@ class TranslationsControllerModificationTest : ProjectAuthControllerTest("/v2/pr testOutdated(translation, true) } - private fun testOutdated(translation: Translation, state: Boolean) { + private fun testOutdated( + translation: Translation, + state: Boolean, + ) { performProjectAuthPut( "/translations/${translation.id}/set-outdated-flag/$state", - null + null, ).andIsOk val updatedTranslation = translationService.get(translation.id) assertThat(updatedTranslation.outdated).isEqualTo(state) diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerNamespacesTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerNamespacesTest.kt index e8f2c8d5cc..edd45f9fab 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerNamespacesTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerNamespacesTest.kt @@ -18,7 +18,6 @@ import java.math.BigDecimal @SpringBootTest @AutoConfigureMockMvc class TranslationsControllerNamespacesTest : ProjectAuthControllerTest("/v2/projects/") { - @Test @ProjectJWTAuthTestMethod fun `it returns namespaces`() { @@ -52,8 +51,8 @@ class TranslationsControllerNamespacesTest : ProjectAuthControllerTest("/v2/proj SetTranslationsWithKeyDto( key = "new_key_in_ns", namespace = "heloo", - translations = mapOf("en" to "eeeen") - ) + translations = mapOf("en" to "eeeen"), + ), ).andPrettyPrint.andIsOk.andAssertThatJson { node("keyNamespace").isEqualTo("heloo") } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerViewTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerViewTest.kt index fc1b97238e..860b3466a6 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerViewTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/translations/v2TranslationsController/TranslationsControllerViewTest.kt @@ -24,7 +24,6 @@ import kotlin.system.measureTimeMillis @SpringBootTest @AutoConfigureMockMvc class TranslationsControllerViewTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: TranslationsTestData @BeforeEach @@ -337,11 +336,12 @@ class TranslationsControllerViewTest : ProjectAuthControllerTest("/v2/projects/" testData.generateLotOfData(2000) testDataService.saveTestData(testData.root) userAccount = testData.user - val time = measureTimeMillis { - performProjectAuthGet("/translations/select-all").andAssertThatJson { - node("ids").isArray.hasSize(2002) + val time = + measureTimeMillis { + performProjectAuthGet("/translations/select-all").andAssertThatJson { + node("ids").isArray.hasSize(2002) + } } - } assertThat(time).isLessThan(3000) } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImageUploadController/AbstractV2ImageUploadControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImageUploadController/AbstractV2ImageUploadControllerTest.kt index 011b65d219..443b3297ce 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImageUploadController/AbstractV2ImageUploadControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImageUploadController/AbstractV2ImageUploadControllerTest.kt @@ -25,12 +25,15 @@ abstract class AbstractV2ImageUploadControllerTest : AuthorizedControllerTest() protected fun performStoreImage(): ResultActions { return performAuthMultipart( url = "/v2/image-upload", - files = listOf( - MockMultipartFile( - "image", "originalShot.png", "image/png", - screenshotFile.inputStream - ) - ) + files = + listOf( + MockMultipartFile( + "image", + "originalShot.png", + "image/png", + screenshotFile.inputStream, + ), + ), ) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImageUploadController/SecuredV2ImageUploadControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImageUploadController/SecuredV2ImageUploadControllerTest.kt index fcb9aae653..e7f3203513 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImageUploadController/SecuredV2ImageUploadControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImageUploadController/SecuredV2ImageUploadControllerTest.kt @@ -23,8 +23,8 @@ import java.util.* @SpringBootTest( properties = [ "tolgee.authentication.secured-image-retrieval=true", - "tolgee.authentication.secured-image-timestamp-max-age=10000" - ] + "tolgee.authentication.secured-image-timestamp-max-age=10000", + ], ) class SecuredV2ImageUploadControllerTest : AbstractV2ImageUploadControllerTest() { @AfterEach @@ -42,12 +42,13 @@ class SecuredV2ImageUploadControllerTest : AbstractV2ImageUploadControllerTest() fun getScreenshotFileInvalidTimestamp() { val image = imageUploadService.store(screenshotFile, userAccount!!, null) - val token = jwtService.emitTicket( - userAccount!!.id, - JwtService.TicketType.IMG_ACCESS, - 5000, - mapOf("fileName" to image.filenameWithExtension) - ) + val token = + jwtService.emitTicket( + userAccount!!.id, + JwtService.TicketType.IMG_ACCESS, + 5000, + mapOf("fileName" to image.filenameWithExtension), + ) moveCurrentDate(Duration.ofSeconds(10)) performAuthGet("/uploaded-images/${image.filename}.jpg?token=$token").andIsUnauthorized @@ -57,15 +58,17 @@ class SecuredV2ImageUploadControllerTest : AbstractV2ImageUploadControllerTest() fun getFile() { val image = imageUploadService.store(screenshotFile, userAccount!!, null) - val token = jwtService.emitTicket( - userAccount!!.id, - JwtService.TicketType.IMG_ACCESS, - 5000, - mapOf("fileName" to image.filenameWithExtension) - ) + val token = + jwtService.emitTicket( + userAccount!!.id, + JwtService.TicketType.IMG_ACCESS, + 5000, + mapOf("fileName" to image.filenameWithExtension), + ) - val storedImage = performAuthGet("/uploaded-images/${image.filename}.png?token=$token") - .andIsOk.andReturn().response.contentAsByteArray + val storedImage = + performAuthGet("/uploaded-images/${image.filename}.png?token=$token") + .andIsOk.andReturn().response.contentAsByteArray val file = File(tolgeeProperties.fileStorage.fsDataPath + "/uploadedImages/" + image.filename + ".png") assertThat(storedImage).isEqualTo(file.readBytes()) diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImageUploadController/V2ImageUploadControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImageUploadController/V2ImageUploadControllerTest.kt index 69b3d7e6f4..4970fac2fa 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImageUploadController/V2ImageUploadControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImageUploadController/V2ImageUploadControllerTest.kt @@ -27,7 +27,6 @@ import java.util.stream.Collectors @TestInstance(TestInstance.Lifecycle.PER_CLASS) class V2ImageUploadControllerTest : AbstractV2ImageUploadControllerTest() { - lateinit var initialFileStorageUrl: String @BeforeAll @@ -81,26 +80,28 @@ class V2ImageUploadControllerTest : AbstractV2ImageUploadControllerTest() { val image = imageUploadService.store(screenshotFile, userAccount!!, null) val file = File("""${tolgeeProperties.fileStorage.fsDataPath}/uploadedImages/${image.filenameWithExtension}""") - val result = performAuthGet("/uploaded-images/${image.filenameWithExtension}").andIsOk - .andExpect( - header().string("Cache-Control", "max-age=365, must-revalidate, no-transform") - ) - .andReturn() + val result = + performAuthGet("/uploaded-images/${image.filenameWithExtension}").andIsOk + .andExpect( + header().string("Cache-Control", "max-age=365, must-revalidate, no-transform"), + ) + .andReturn() assertThat(result.response.contentAsByteArray).isEqualTo(file.readBytes()) } @Test fun delete() { whenever(maxUploadedFilesByUserProvider.invoke()).thenAnswer { 30L } - val list = (1..20).map { - imageUploadService.store(screenshotFile, userAccount!!, null) - }.toCollection(mutableListOf()) + val list = + (1..20).map { + imageUploadService.store(screenshotFile, userAccount!!, null) + }.toCollection(mutableListOf()) val idsToDelete = list.take(10).map { it.id }.joinToString(",") list.asSequence().take(10).forEach { assertThat( - File("""${tolgeeProperties.fileStorage.fsDataPath}/uploadedImages/${it.filenameWithExtension}""") + File("""${tolgeeProperties.fileStorage.fsDataPath}/uploadedImages/${it.filenameWithExtension}"""), ).exists() } @@ -110,7 +111,7 @@ class V2ImageUploadControllerTest : AbstractV2ImageUploadControllerTest() { list.asSequence().take(10).forEach { assertThat( - File("""${tolgeeProperties.fileStorage.fsDataPath}/uploadedImages/${it.filenameWithExtension}""") + File("""${tolgeeProperties.fileStorage.fsDataPath}/uploadedImages/${it.filenameWithExtension}"""), ).doesNotExist() } } @@ -123,15 +124,18 @@ class V2ImageUploadControllerTest : AbstractV2ImageUploadControllerTest() { @Test fun uploadValidationNoImage() { - val response = performAuthMultipart( - "/v2/image-upload", - listOf( - MockMultipartFile( - "image", "originalShot.png", "not_valid", - "test".toByteArray() - ) - ), - ).andIsBadRequest.andReturn() + val response = + performAuthMultipart( + "/v2/image-upload", + listOf( + MockMultipartFile( + "image", + "originalShot.png", + "not_valid", + "test".toByteArray(), + ), + ), + ).andIsBadRequest.andReturn() assertThat(response).error().isCustomValidation.hasMessage("file_not_image") } } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImportController/V2ImportControllerAddFilesTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImportController/V2ImportControllerAddFilesTest.kt index f79885bf01..1d87a12a4f 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImportController/V2ImportControllerAddFilesTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImportController/V2ImportControllerAddFilesTest.kt @@ -179,7 +179,7 @@ class V2ImportControllerAddFilesTest : AuthorizedControllerTest() { executeInNewTransaction { performImport( projectId = base.project.id, - mapOf(Pair("tooLongTranslation.json", tooLongTranslation)) + mapOf(Pair("tooLongTranslation.json", tooLongTranslation)), ).andIsOk } @@ -201,7 +201,7 @@ class V2ImportControllerAddFilesTest : AuthorizedControllerTest() { executeInNewTransaction { performImport( projectId = base.project.id, - null + null, ).andIsBadRequest.andAssertThatJson { node("STANDARD_VALIDATION") { node("files").isEqualTo("Required part 'files' is not present.") @@ -219,7 +219,7 @@ class V2ImportControllerAddFilesTest : AuthorizedControllerTest() { executeInNewTransaction { performImport( projectId = base.project.id, - mapOf(Pair("namespaces.zip", namespacesZip)) + mapOf(Pair("namespaces.zip", namespacesZip)), ).andIsOk } @@ -243,7 +243,7 @@ class V2ImportControllerAddFilesTest : AuthorizedControllerTest() { executeInNewTransaction { performImport( projectId = base.project.id, - mapOf(Pair("namespaces.zip", namespacesMacZip)) + mapOf(Pair("namespaces.zip", namespacesMacZip)), ).andIsOk } @@ -262,7 +262,7 @@ class V2ImportControllerAddFilesTest : AuthorizedControllerTest() { executeInNewTransaction { performImport( projectId = base.project.id, - mapOf(Pair("tooLongErrorParamValue.json", tooLongErrorParamValue)) + mapOf(Pair("tooLongErrorParamValue.json", tooLongErrorParamValue)), ).andIsOk } @@ -272,7 +272,7 @@ class V2ImportControllerAddFilesTest : AuthorizedControllerTest() { assertThat(it.files[0].issues[0].params[2].value).isEqualTo( "[Lorem ipsum dolor sit amet," + " consectetur adipiscing elit. Suspendisse" + - " ac ultricies tortor. Integer ac..." + " ac ultricies tortor. Integer ac...", ) } } @@ -287,7 +287,7 @@ class V2ImportControllerAddFilesTest : AuthorizedControllerTest() { executeInNewTransaction { performImport( projectId = testData.project.id, - mapOf(Pair("importWithConflicts.zip", importWithConflicts)) + mapOf(Pair("importWithConflicts.zip", importWithConflicts)), ).andIsOk.andAssertThatJson { node("result.page.totalElements").isEqualTo(2) node("result._embedded.languages[0].conflictCount").isEqualTo(1) @@ -296,7 +296,10 @@ class V2ImportControllerAddFilesTest : AuthorizedControllerTest() { } } - private fun validateSavedJsonImportData(project: Project, userAccount: UserAccount) { + private fun validateSavedJsonImportData( + project: Project, + userAccount: UserAccount, + ) { importService.find(project.id, userAccount.id)!!.let { importEntity -> entityManager.refresh(importEntity) assertThat(importEntity.files.size).isEqualTo(3) @@ -318,17 +321,20 @@ class V2ImportControllerAddFilesTest : AuthorizedControllerTest() { private fun performImport( projectId: Long, files: Map?, - params: Map = mapOf() + params: Map = mapOf(), ): ResultActions { - val builder = MockMvcRequestBuilders - .multipart("/v2/projects/$projectId/import?${mapToQueryString(params)}") + val builder = + MockMvcRequestBuilders + .multipart("/v2/projects/$projectId/import?${mapToQueryString(params)}") files?.forEach { builder.file( MockMultipartFile( - "files", it.key, "application/zip", - it.value.file.readBytes() - ) + "files", + it.key, + "application/zip", + it.value.file.readBytes(), + ), ) } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImportController/V2ImportControllerApplicationTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImportController/V2ImportControllerApplicationTest.kt index c6293b29be..ad38f96bfc 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImportController/V2ImportControllerApplicationTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImportController/V2ImportControllerApplicationTest.kt @@ -157,8 +157,9 @@ class V2ImportControllerApplicationTest : ProjectAuthControllerTest("/v2/project performAuthPut(path, null).andIsOk executeInNewTransaction { - val key = projectService.get(testData.project.id) - .keys.find { it.name == "what a nice key" }!! + val key = + projectService.get(testData.project.id) + .keys.find { it.name == "what a nice key" }!! val untouched = key.translations.find { it.language == testData.french }!! untouched.outdated.assert.isEqualTo(true) diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImportController/V2ImportControllerManipulationTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImportController/V2ImportControllerManipulationTest.kt index 8723543068..73f6ddc555 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImportController/V2ImportControllerManipulationTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImportController/V2ImportControllerManipulationTest.kt @@ -44,8 +44,9 @@ class V2ImportControllerManipulationTest : ProjectAuthControllerTest("/v2/projec val user = testData.root.data.userAccounts[0].self val projectId = testData.project.id loginAsUser(user.username) - val path = "/v2/projects/$projectId/import/result/languages/${testData.importEnglish.id}" + - "/translations/${testData.translationWithConflict.id}/resolve/set-override" + val path = + "/v2/projects/$projectId/import/result/languages/${testData.importEnglish.id}" + + "/translations/${testData.translationWithConflict.id}/resolve/set-override" performAuthPut(path, null).andIsOk val translation = importService.findTranslation(testData.translationWithConflict.id) assertThat(translation?.resolved).isTrue @@ -59,8 +60,9 @@ class V2ImportControllerManipulationTest : ProjectAuthControllerTest("/v2/projec val user = testData.root.data.userAccounts[0].self val projectId = testData.project.id loginAsUser(user.username) - val path = "/v2/projects/$projectId/import/result/languages/${testData.importEnglish.id}" + - "/translations/${testData.translationWithConflict.id}/resolve/set-keep-existing" + val path = + "/v2/projects/$projectId/import/result/languages/${testData.importEnglish.id}" + + "/translations/${testData.translationWithConflict.id}/resolve/set-keep-existing" performAuthPut(path, null).andIsOk val translation = importService.findTranslation(testData.translationWithConflict.id) assertThat(translation?.resolved).isTrue @@ -88,8 +90,9 @@ class V2ImportControllerManipulationTest : ProjectAuthControllerTest("/v2/projec val user = testData.root.data.userAccounts[0].self val projectId = testData.project.id loginAsUser(user.username) - val path = "/v2/projects/$projectId/import/result/languages/" + - "${testData.importEnglish.id}/resolve-all/set-keep-existing" + val path = + "/v2/projects/$projectId/import/result/languages/" + + "${testData.importEnglish.id}/resolve-all/set-keep-existing" performAuthPut(path, null).andIsOk val translation = importService.findTranslation(testData.translationWithConflict.id) assertThat(translation?.resolved).isTrue @@ -105,8 +108,9 @@ class V2ImportControllerManipulationTest : ProjectAuthControllerTest("/v2/projec val user = testData.root.data.userAccounts[0].self val projectId = testData.project.id loginAsUser(user.username) - val path = "/v2/projects/$projectId/import/result/languages/${testData.importFrench.id}/" + - "select-existing/${testData.french.id}" + val path = + "/v2/projects/$projectId/import/result/languages/${testData.importFrench.id}/" + + "select-existing/${testData.french.id}" performAuthPut(path, null).andIsOk assertThat(importService.findLanguage(testData.importFrench.id)?.existingLanguage) .isEqualTo(testData.french) @@ -126,8 +130,9 @@ class V2ImportControllerManipulationTest : ProjectAuthControllerTest("/v2/projec val file = importService.findFile(testData.defaultNsFile.id)!! assertThat(file.namespace) .isEqualTo("new-ns") - val importLanguage = file.languages - .find { it.name == "de" }!! + val importLanguage = + file.languages + .find { it.name == "de" }!! importLanguage.translations .any { it.conflict != null } .assert.isEqualTo(false) @@ -174,8 +179,9 @@ class V2ImportControllerManipulationTest : ProjectAuthControllerTest("/v2/projec val projectId = testData.project.id loginAsUser(user.username) // try to assign with another french but in different namespace - val path = "/v2/projects/$projectId/import/result/languages/${nsData.importFrenchInNs.id}/" + - "select-existing/${testData.french.id}" + val path = + "/v2/projects/$projectId/import/result/languages/${nsData.importFrenchInNs.id}/" + + "select-existing/${testData.french.id}" performAuthPut(path, null).andIsOk assertThat(importService.findLanguage(testData.importFrench.id)?.existingLanguage) .isEqualTo(testData.french) @@ -192,8 +198,9 @@ class V2ImportControllerManipulationTest : ProjectAuthControllerTest("/v2/projec val projectId = testData.project.id loginAsUser(user.username) // try to assign with another french but in different namespace - val path = "/v2/projects/$projectId/import/result/languages/${nsData.importFrenchInNs.id}/" + - "select-existing/${testData.french.id}" + val path = + "/v2/projects/$projectId/import/result/languages/${nsData.importFrenchInNs.id}/" + + "select-existing/${testData.french.id}" performAuthPut(path, null).andIsOk assertThat(importService.findLanguage(testData.importFrench.id)?.existingLanguage) .isEqualTo(testData.french) diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImportController/V2ImportControllerResultTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImportController/V2ImportControllerResultTest.kt index a9b674403d..ac4b45f809 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImportController/V2ImportControllerResultTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ImportController/V2ImportControllerResultTest.kt @@ -72,7 +72,7 @@ class V2ImportControllerResultTest : AuthorizedControllerTest() { performAuthGet( "/v2/projects/${testData.project.id}" + - "/import/result/languages/${testData.importEnglish.id}" + "/import/result/languages/${testData.importEnglish.id}", ) .andPrettyPrint.andAssertThatJson { node("name").isEqualTo("en") @@ -103,7 +103,7 @@ class V2ImportControllerResultTest : AuthorizedControllerTest() { performAuthGet( "/v2/projects/${testData.project.id}" + - "/import/result/languages/${testData.importEnglish.id}/translations?onlyConflicts=true" + "/import/result/languages/${testData.importEnglish.id}/translations?onlyConflicts=true", ).andIsOk .andPrettyPrint.andAssertThatJson { node("_embedded.translations") { @@ -131,7 +131,7 @@ class V2ImportControllerResultTest : AuthorizedControllerTest() { performAuthGet( "/v2/projects/${testData.project.id}" + "/import/result/languages/${testData.importEnglish.id}" + - "/translations?search=extraordinary" + "/translations?search=extraordinary", ).andIsOk .andPrettyPrint.andAssertThatJson { node("_embedded.translations") { @@ -145,7 +145,7 @@ class V2ImportControllerResultTest : AuthorizedControllerTest() { performAuthGet( "/v2/projects/${testData.project.id}" + "/import/result/languages/${testData.importEnglish.id}" + - "/translations?search=Imported" + "/translations?search=Imported", ).andIsOk .andPrettyPrint.andAssertThatJson { node("_embedded.translations") { @@ -166,7 +166,7 @@ class V2ImportControllerResultTest : AuthorizedControllerTest() { performAuthGet( "/v2/projects/${testData.project.id}" + - "/import/result/languages/${testData.importEnglish.id}/translations?size=2" + "/import/result/languages/${testData.importEnglish.id}/translations?size=2", ).andIsOk .andPrettyPrint.andAssertThatJson { node("_embedded.translations").isArray.hasSize(2) } } @@ -180,13 +180,13 @@ class V2ImportControllerResultTest : AuthorizedControllerTest() { performAuthGet( "/v2/projects/${testData.project.id}" + - "/import/result/languages/${testData.importEnglish.id}/translations?onlyConflicts=false" + "/import/result/languages/${testData.importEnglish.id}/translations?onlyConflicts=false", ).andIsOk .andPrettyPrint.andAssertThatJson { node("_embedded.translations").isArray.hasSize(5) } performAuthGet( "/v2/projects/${testData.project.id}" + - "/import/result/languages/${testData.importEnglish.id}/translations?onlyConflicts=true" + "/import/result/languages/${testData.importEnglish.id}/translations?onlyConflicts=true", ).andIsOk .andPrettyPrint.andAssertThatJson { node("_embedded.translations").isArray.hasSize(3) } } @@ -201,13 +201,13 @@ class V2ImportControllerResultTest : AuthorizedControllerTest() { performAuthGet( "/v2/projects/${testData.project.id}" + "/import/result/languages/${testData.importEnglish.id}/" + - "translations?onlyConflicts=true" + "translations?onlyConflicts=true", ).andIsOk .andPrettyPrint.andAssertThatJson { node("_embedded.translations").isArray.hasSize(3) } performAuthGet( "/v2/projects/${testData.project.id}" + - "/import/result/languages/${testData.importEnglish.id}/translations?onlyUnresolved=true" + "/import/result/languages/${testData.importEnglish.id}/translations?onlyUnresolved=true", ).andIsOk .andPrettyPrint.andAssertThatJson { node("_embedded.translations").isArray.hasSize(2) } } @@ -263,11 +263,11 @@ class V2ImportControllerResultTest : AuthorizedControllerTest() { node("page.size").isEqualTo(20) node("_embedded.importFileIssues[0].params").isEqualTo( """ - [{ - "value" : "1", - "type" : "KEY_INDEX" - }] - """.trimIndent() + [{ + "value" : "1", + "type" : "KEY_INDEX" + }] + """.trimIndent(), ) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerComplexUpdateTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerComplexUpdateTest.kt index f9be5959bc..b910c8efc0 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerComplexUpdateTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerComplexUpdateTest.kt @@ -34,7 +34,6 @@ import java.math.BigDecimal @SpringBootTest @AutoConfigureMockMvc class KeyControllerComplexUpdateTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: KeysTestData @Autowired @@ -55,8 +54,8 @@ class KeyControllerComplexUpdateTest : ProjectAuthControllerTest("/v2/projects/" @ProjectApiKeyAuthTestMethod( scopes = [ - Scope.TRANSLATIONS_EDIT - ] + Scope.TRANSLATIONS_EDIT, + ], ) @Test fun `complex edit validates change state permissions`() { @@ -68,7 +67,7 @@ class KeyControllerComplexUpdateTest : ProjectAuthControllerTest("/v2/projects/" name = keyName, translations = mapOf("en" to "EN", "de" to "DE"), states = mapOf("en" to AssignableTranslationState.REVIEWED), - ) + ), ).andIsForbidden } @@ -76,8 +75,8 @@ class KeyControllerComplexUpdateTest : ProjectAuthControllerTest("/v2/projects/" scopes = [ Scope.KEYS_CREATE, Scope.TRANSLATIONS_EDIT, - Scope.TRANSLATIONS_STATE_EDIT - ] + Scope.TRANSLATIONS_STATE_EDIT, + ], ) @Test fun `complex edit modifies state`() { @@ -85,35 +84,37 @@ class KeyControllerComplexUpdateTest : ProjectAuthControllerTest("/v2/projects/" doUpdateAndVerifyStates( translations = mapOf("en" to "EN", "de" to "DE"), states = mapOf("en" to AssignableTranslationState.REVIEWED), - statesToVerify = mapOf("en" to TranslationState.REVIEWED, "de" to TranslationState.TRANSLATED) + statesToVerify = mapOf("en" to TranslationState.REVIEWED, "de" to TranslationState.TRANSLATED), ) // existing translation doUpdateAndVerifyStates( translations = mapOf("en" to "EN", "de" to "DE"), states = mapOf("de" to AssignableTranslationState.REVIEWED), - statesToVerify = mapOf("en" to TranslationState.REVIEWED, "de" to TranslationState.REVIEWED) + statesToVerify = mapOf("en" to TranslationState.REVIEWED, "de" to TranslationState.REVIEWED), ) doUpdateAndVerifyStates( translations = mapOf("cs" to "CS"), states = mapOf(), - statesToVerify = mapOf( - "cs" to TranslationState.TRANSLATED, - "en" to TranslationState.REVIEWED, - "de" to TranslationState.REVIEWED - ) + statesToVerify = + mapOf( + "cs" to TranslationState.TRANSLATED, + "en" to TranslationState.REVIEWED, + "de" to TranslationState.REVIEWED, + ), ) doUpdateAndVerifyStates( translations = mapOf("en" to "Test", "cs" to "Test"), states = mapOf("en" to AssignableTranslationState.REVIEWED, "cs" to AssignableTranslationState.REVIEWED), - statesToVerify = mapOf( - "cs" to TranslationState.REVIEWED, - "en" to TranslationState.REVIEWED, - // we modified the base, so it resets the state for the value, which is not modified - "de" to TranslationState.TRANSLATED - ) + statesToVerify = + mapOf( + "cs" to TranslationState.REVIEWED, + "en" to TranslationState.REVIEWED, + // we modified the base, so it resets the state for the value, which is not modified + "de" to TranslationState.TRANSLATED, + ), ) } @@ -121,39 +122,42 @@ class KeyControllerComplexUpdateTest : ProjectAuthControllerTest("/v2/projects/" scopes = [ Scope.KEYS_CREATE, Scope.TRANSLATIONS_EDIT, - Scope.TRANSLATIONS_STATE_EDIT - ] + Scope.TRANSLATIONS_STATE_EDIT, + ], ) @Test fun `complex edit modifies state correctly when new translation created`() { doUpdateAndVerifyStates( translations = mapOf("en" to "Test", "cs" to "Test"), states = mapOf("en" to AssignableTranslationState.REVIEWED, "cs" to AssignableTranslationState.REVIEWED), - statesToVerify = mapOf( - "cs" to TranslationState.REVIEWED, - "en" to TranslationState.REVIEWED, - ) + statesToVerify = + mapOf( + "cs" to TranslationState.REVIEWED, + "en" to TranslationState.REVIEWED, + ), ) doUpdateAndVerifyStates( translations = mapOf("en" to "Test", "cs" to "Test", "de" to "Hello"), - states = mapOf( - "en" to AssignableTranslationState.REVIEWED, - "cs" to AssignableTranslationState.REVIEWED, - "de" to AssignableTranslationState.REVIEWED - ), - statesToVerify = mapOf( - "cs" to TranslationState.REVIEWED, - "en" to TranslationState.REVIEWED, - "de" to TranslationState.REVIEWED - ) + states = + mapOf( + "en" to AssignableTranslationState.REVIEWED, + "cs" to AssignableTranslationState.REVIEWED, + "de" to AssignableTranslationState.REVIEWED, + ), + statesToVerify = + mapOf( + "cs" to TranslationState.REVIEWED, + "en" to TranslationState.REVIEWED, + "de" to TranslationState.REVIEWED, + ), ) } private fun doUpdateAndVerifyStates( translations: Map, states: Map, - statesToVerify: Map + statesToVerify: Map, ) { doUpdate(translations, states) verifyStates(statesToVerify) @@ -174,7 +178,7 @@ class KeyControllerComplexUpdateTest : ProjectAuthControllerTest("/v2/projects/" private fun doUpdate( translations: Map, - states: Map + states: Map, ) { performProjectAuthPut( "keys/${testData.keyWithReferences.id}/complex-update", @@ -182,7 +186,7 @@ class KeyControllerComplexUpdateTest : ProjectAuthControllerTest("/v2/projects/" name = "key_with_referecnces", translations = translations, states = states, - ) + ), ).andIsOk } @@ -191,8 +195,8 @@ class KeyControllerComplexUpdateTest : ProjectAuthControllerTest("/v2/projects/" Scope.KEYS_EDIT, Scope.TRANSLATIONS_EDIT, Scope.SCREENSHOTS_UPLOAD, - Scope.SCREENSHOTS_DELETE - ] + Scope.SCREENSHOTS_DELETE, + ], ) @Test fun `updates key with translations and tags and screenshots`() { @@ -207,8 +211,8 @@ class KeyControllerComplexUpdateTest : ProjectAuthControllerTest("/v2/projects/" translations = mapOf("en" to "EN", "de" to "DE"), tags = listOf("tag", "tag2"), screenshotUploadedImageIds = screenshotImageIds, - screenshotIdsToDelete = listOf(testData.screenshot.id) - ) + screenshotIdsToDelete = listOf(testData.screenshot.id), + ), ).andIsOk.andAssertThatJson { node("id").isValidId node("name").isEqualTo(keyName) @@ -261,7 +265,7 @@ class KeyControllerComplexUpdateTest : ProjectAuthControllerTest("/v2/projects/" assertThrows { screenshotImages.forEach { fileStorage.readFile( - "${ImageUploadService.UPLOADED_IMAGES_STORAGE_FOLDER_NAME}/${it.filenameWithExtension}" + "${ImageUploadService.UPLOADED_IMAGES_STORAGE_FOLDER_NAME}/${it.filenameWithExtension}", ) } } @@ -270,7 +274,7 @@ class KeyControllerComplexUpdateTest : ProjectAuthControllerTest("/v2/projects/" @ProjectApiKeyAuthTestMethod( scopes = [ Scope.TRANSLATIONS_EDIT, - ] + ], ) @Test fun `can modify permitted language translations`() { @@ -280,15 +284,15 @@ class KeyControllerComplexUpdateTest : ProjectAuthControllerTest("/v2/projects/" ComplexEditKeyDto( name = testData.firstKey.name, translations = mapOf("en" to "Oh yes!"), - tags = listOf() - ) + tags = listOf(), + ), ).andIsOk } @ProjectApiKeyAuthTestMethod( scopes = [ Scope.TRANSLATIONS_EDIT, - ] + ], ) @Test fun `stores big meta`() { @@ -297,11 +301,12 @@ class KeyControllerComplexUpdateTest : ProjectAuthControllerTest("/v2/projects/" "keys/${testData.firstKey.id}/complex-update", ComplexEditKeyDto( name = testData.firstKey.name, - relatedKeysInOrder = mutableListOf( - RelatedKeyDto(null, "first_key"), - RelatedKeyDto(null, testData.firstKey.name) - ) - ) + relatedKeysInOrder = + mutableListOf( + RelatedKeyDto(null, "first_key"), + RelatedKeyDto(null, testData.firstKey.name), + ), + ), ).andIsOk bigMetaService.getCloseKeyIds(testData.firstKey.id).assert.hasSize(1) @@ -313,8 +318,8 @@ class KeyControllerComplexUpdateTest : ProjectAuthControllerTest("/v2/projects/" Scope.KEYS_EDIT, Scope.TRANSLATIONS_EDIT, Scope.SCREENSHOTS_UPLOAD, - Scope.SCREENSHOTS_DELETE - ] + Scope.SCREENSHOTS_DELETE, + ], ) fun `updates key screenshots with meta`() { val keyName = "super_key" @@ -327,21 +332,23 @@ class KeyControllerComplexUpdateTest : ProjectAuthControllerTest("/v2/projects/" translations = mapOf("en" to "EN", "de" to "DE"), tags = listOf("tag", "tag2"), screenshotIdsToDelete = listOf(testData.screenshot.id), - screenshotsToAdd = screenshotImages.map { - KeyScreenshotDto().apply { - text = "text" - uploadedImageId = it.id - positions = listOf( - KeyInScreenshotPositionDto().apply { - x = 100 - y = 120 - width = 200 - height = 300 - } - ) - } - } - ) + screenshotsToAdd = + screenshotImages.map { + KeyScreenshotDto().apply { + text = "text" + uploadedImageId = it.id + positions = + listOf( + KeyInScreenshotPositionDto().apply { + x = 100 + y = 120 + width = 200 + height = 300 + }, + ) + } + }, + ), ).andIsOk.andPrettyPrint.andAssertThatJson { node("screenshots") { isArray.hasSize(3) @@ -375,7 +382,7 @@ class KeyControllerComplexUpdateTest : ProjectAuthControllerTest("/v2/projects/" } assertThat(screenshots).hasSize(3) assertThat( - imageUploadService.find(screenshotImages.map { it.id }) + imageUploadService.find(screenshotImages.map { it.id }), ).hasSize(0) screenshots.forEach { val position = it.keyScreenshotReferences[0].positions!![0] diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerCreationTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerCreationTest.kt index 848a750a15..f376cc19af 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerCreationTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerCreationTest.kt @@ -36,7 +36,6 @@ import java.math.BigDecimal @SpringBootTest @AutoConfigureMockMvc class KeyControllerCreationTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: KeysTestData @Autowired @@ -89,7 +88,7 @@ class KeyControllerCreationTest : ProjectAuthControllerTest("/v2/projects/") { fun `create key with translations require translate permissions`() { performProjectAuthPost( "keys", - CreateKeyDto(name = "super_key", translations = mapOf("en" to "hello", "de" to "hello")) + CreateKeyDto(name = "super_key", translations = mapOf("en" to "hello", "de" to "hello")), ).andIsForbidden } @@ -106,8 +105,8 @@ class KeyControllerCreationTest : ProjectAuthControllerTest("/v2/projects/") { name = keyName, translations = mapOf("en" to "EN", "de" to "DE"), tags = listOf("tag", "tag2"), - screenshotUploadedImageIds = screenshotImageIds - ) + screenshotUploadedImageIds = screenshotImageIds, + ), ).andIsCreated.andPrettyPrint.andAssertThatJson { node("id").isValidId node("name").isEqualTo(keyName) @@ -162,7 +161,7 @@ class KeyControllerCreationTest : ProjectAuthControllerTest("/v2/projects/") { assertThrows { screenshotImages.forEach { fileStorage.readFile( - "${ImageUploadService.UPLOADED_IMAGES_STORAGE_FOLDER_NAME}/${it.filenameWithExtension}" + "${ImageUploadService.UPLOADED_IMAGES_STORAGE_FOLDER_NAME}/${it.filenameWithExtension}", ) } } @@ -180,21 +179,23 @@ class KeyControllerCreationTest : ProjectAuthControllerTest("/v2/projects/") { name = keyName, translations = mapOf("en" to "EN", "de" to "DE"), tags = listOf("tag", "tag2"), - screenshots = screenshotImages.map { - KeyScreenshotDto().apply { - text = "text" - uploadedImageId = it.id - positions = listOf( - KeyInScreenshotPositionDto().apply { - x = 100 - y = 120 - width = 200 - height = 300 - } - ) - } - } - ) + screenshots = + screenshotImages.map { + KeyScreenshotDto().apply { + text = "text" + uploadedImageId = it.id + positions = + listOf( + KeyInScreenshotPositionDto().apply { + x = 100 + y = 120 + width = 200 + height = 300 + }, + ) + } + }, + ), ).andIsCreated.andPrettyPrint.andAssertThatJson { node("screenshots") { isArray.hasSize(3) @@ -228,7 +229,7 @@ class KeyControllerCreationTest : ProjectAuthControllerTest("/v2/projects/") { } assertThat(screenshots).hasSize(3) assertThat( - imageUploadService.find(screenshotImages.map { it.id }) + imageUploadService.find(screenshotImages.map { it.id }), ).hasSize(0) screenshots.forEach { val position = it.keyScreenshotReferences[0].positions!![0] @@ -250,11 +251,12 @@ class KeyControllerCreationTest : ProjectAuthControllerTest("/v2/projects/") { CreateKeyDto( name = keyName, translations = mapOf("en" to "EN", "de" to "DE"), - relatedKeysInOrder = mutableListOf( - RelatedKeyDto(null, "first_key"), - RelatedKeyDto(null, "super_key") - ) - ) + relatedKeysInOrder = + mutableListOf( + RelatedKeyDto(null, "first_key"), + RelatedKeyDto(null, "super_key"), + ), + ), ).andIsCreated.andAssertThatJson { node("id").isNumber.satisfies { it -> bigMetaService.getCloseKeyIds(it.toLong()).assert.hasSize(1) @@ -270,8 +272,8 @@ class KeyControllerCreationTest : ProjectAuthControllerTest("/v2/projects/") { CreateKeyDto( name = "super_key", translations = mapOf("en" to "EN"), - states = mapOf("en" to AssignableTranslationState.REVIEWED) - ) + states = mapOf("en" to AssignableTranslationState.REVIEWED), + ), ).andIsCreated.andAssertThatJson { node("id").isNumber.satisfies { id -> executeInNewTransaction { @@ -287,7 +289,7 @@ class KeyControllerCreationTest : ProjectAuthControllerTest("/v2/projects/") { fun `checks state change language permissions`() { prepareTestData( scopes = listOf(Scope.KEYS_CREATE, Scope.TRANSLATIONS_EDIT, Scope.TRANSLATIONS_STATE_EDIT), - stateChangeTags = listOf("cs") + stateChangeTags = listOf("cs"), ) performProjectAuthPost( @@ -295,8 +297,8 @@ class KeyControllerCreationTest : ProjectAuthControllerTest("/v2/projects/") { CreateKeyDto( name = "super_key", translations = mapOf("en" to "EN"), - states = mapOf("en" to AssignableTranslationState.REVIEWED) - ) + states = mapOf("en" to AssignableTranslationState.REVIEWED), + ), ).andIsForbidden performProjectAuthPost( @@ -304,8 +306,8 @@ class KeyControllerCreationTest : ProjectAuthControllerTest("/v2/projects/") { CreateKeyDto( name = "super_key", translations = mapOf("cs" to "CS"), - states = mapOf("cs" to AssignableTranslationState.REVIEWED) - ) + states = mapOf("cs" to AssignableTranslationState.REVIEWED), + ), ).andIsCreated } @@ -314,7 +316,7 @@ class KeyControllerCreationTest : ProjectAuthControllerTest("/v2/projects/") { fun `checks state change permissions (missing scope)`() { prepareTestData( scopes = listOf(Scope.KEYS_CREATE, Scope.TRANSLATIONS_EDIT), - stateChangeTags = null + stateChangeTags = null, ) performProjectAuthPost( @@ -322,8 +324,8 @@ class KeyControllerCreationTest : ProjectAuthControllerTest("/v2/projects/") { CreateKeyDto( name = "super_key", translations = mapOf("cs" to "CS"), - states = mapOf("cs" to AssignableTranslationState.REVIEWED) - ) + states = mapOf("cs" to AssignableTranslationState.REVIEWED), + ), ).andIsForbidden // this works, because TRANSLATED is the initial state, so we are not changing anytning @@ -332,19 +334,23 @@ class KeyControllerCreationTest : ProjectAuthControllerTest("/v2/projects/") { CreateKeyDto( name = "super_key", translations = mapOf("cs" to "CS"), - states = mapOf("cs" to AssignableTranslationState.TRANSLATED) - ) + states = mapOf("cs" to AssignableTranslationState.TRANSLATED), + ), ).andIsCreated } - private fun prepareTestData(scopes: List, stateChangeTags: List?) { + private fun prepareTestData( + scopes: List, + stateChangeTags: List?, + ) { val testData = PermissionsTestData() - val user = testData.addUserWithPermissions( - scopes = scopes, - type = null, - stateChangeLanguageTags = stateChangeTags, - translateLanguageTags = listOf("en", "cs") - ) + val user = + testData.addUserWithPermissions( + scopes = scopes, + type = null, + stateChangeLanguageTags = stateChangeTags, + translateLanguageTags = listOf("en", "cs"), + ) testDataService.saveTestData(testData.root) userAccount = user this.projectSupplier = { testData.projectBuilder.self } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerDeleteManyKeysTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerDeleteManyKeysTest.kt index 9ed1a53042..9f9ff1fa16 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerDeleteManyKeysTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerDeleteManyKeysTest.kt @@ -34,11 +34,13 @@ class KeyControllerDeleteManyKeysTest : ProjectAuthControllerTest("/v2/projects/ @Test fun `deletes multiple keys via post fast enough`() { projectSupplier = { testData.project } - val time = measureTimeMillis { - performProjectAuthDelete( - "keys", mapOf("ids" to testData.root.data.projects[0].data.keys.map { it.self.id }) - ).andIsOk - } + val time = + measureTimeMillis { + performProjectAuthDelete( + "keys", + mapOf("ids" to testData.root.data.projects[0].data.keys.map { it.self.id }), + ).andIsOk + } assertThat(time).isLessThan(2000) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerInfoTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerInfoTest.kt index bd2f48e745..62cc46b874 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerInfoTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerInfoTest.kt @@ -17,7 +17,6 @@ import kotlin.properties.Delegates @SpringBootTest @AutoConfigureMockMvc class KeyControllerInfoTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: KeysInfoTestData var uploadedImageId by Delegates.notNull() @@ -36,19 +35,20 @@ class KeyControllerInfoTest : ProjectAuthControllerTest("/v2/projects/") { @ProjectJWTAuthTestMethod fun `returns the data`() { executeInNewTransaction { - val keys = (1..20) - .map { - mapOf("name" to "key-$it") - } + - listOf( - mapOf("name" to "key-22", "namespace" to "ns"), - mapOf("name" to "key-1", "namespace" to "namespace-1"), - mapOf("name" to "key-300") - ) + val keys = + (1..20) + .map { + mapOf("name" to "key-$it") + } + + listOf( + mapOf("name" to "key-22", "namespace" to "ns"), + mapOf("name" to "key-1", "namespace" to "namespace-1"), + mapOf("name" to "key-300"), + ) performProjectAuthPost( "keys/info", - mapOf("keys" to keys, "languageTags" to listOf("de")) + mapOf("keys" to keys, "languageTags" to listOf("de")), ).andIsOk.andAssertThatJson { node("_embedded.keys") { isArray.hasSize(22) diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerKeySearchTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerKeySearchTest.kt index 5a961a6f6a..b3a120ca48 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerKeySearchTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerKeySearchTest.kt @@ -73,22 +73,24 @@ class KeyControllerKeySearchTest : ProjectAuthControllerTest("/v2/projects/"), L } executeInNewTransaction { - val time = measureTimeMillis { - performProjectAuthGet("keys/search?search=Hello&languageTag=de").andAssertThatJson { - node("page.totalElements").isEqualTo(1) - }.andPrettyPrint - } + val time = + measureTimeMillis { + performProjectAuthGet("keys/search?search=Hello&languageTag=de").andAssertThatJson { + node("page.totalElements").isEqualTo(1) + }.andPrettyPrint + } logger.info("Completed in: $time ms") time.assert.isLessThan(4000) } executeInNewTransaction { - val time = measureTimeMillis { - performProjectAuthGet("keys/search?search=dol&languageTag=de").andAssertThatJson { - node("page.totalElements").isNumber.isGreaterThan(4000.toBigDecimal()) - }.andPrettyPrint - } + val time = + measureTimeMillis { + performProjectAuthGet("keys/search?search=dol&languageTag=de").andAssertThatJson { + node("page.totalElements").isNumber.isGreaterThan(4000.toBigDecimal()) + }.andPrettyPrint + } logger.info("Completed in: $time ms") time.assert.isLessThan(4000) @@ -101,14 +103,15 @@ class KeyControllerKeySearchTest : ProjectAuthControllerTest("/v2/projects/"), L saveAndPrepare() executeInNewTransaction { - val time = measureTimeMillis { - performProjectAuthGet("keys/search?search=krasa&languageTag=de").andAssertThatJson { - node("_embedded.keys") { - isArray.hasSize(1) - node("[0].name").isEqualTo("beauty") - } - }.andPrettyPrint - } + val time = + measureTimeMillis { + performProjectAuthGet("keys/search?search=krasa&languageTag=de").andAssertThatJson { + node("_embedded.keys") { + isArray.hasSize(1) + node("[0].name").isEqualTo("beauty") + } + }.andPrettyPrint + } logger.info("Completed in: $time ms") time.assert.isLessThan(4000) diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerLanguageDisablingTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerLanguageDisablingTest.kt index 10700ff294..ba6a3465cc 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerLanguageDisablingTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerLanguageDisablingTest.kt @@ -19,7 +19,6 @@ import org.springframework.boot.test.context.SpringBootTest @SpringBootTest @AutoConfigureMockMvc class KeyControllerLanguageDisablingTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: KeyLanguageDisablingTestData @BeforeEach @@ -47,8 +46,8 @@ class KeyControllerLanguageDisablingTest : ProjectAuthControllerTest("/v2/projec "keys/${testData.key.self.id}/disabled-languages", mapOf( "languageIds" to - listOf(testData.french.self.id, testData.czech.self.id) - ) + listOf(testData.french.self.id, testData.czech.self.id), + ), ).andIsOk.andAssertThatJson { node("_embedded.languages[0].id").isEqualTo(testData.french.self.id) node("_embedded.languages[1].id").isEqualTo(testData.czech.self.id) @@ -70,8 +69,8 @@ class KeyControllerLanguageDisablingTest : ProjectAuthControllerTest("/v2/projec SetTranslationsWithKeyDto( testData.key.self.name, null, - translations = mapOf("de" to "bla") - ) + translations = mapOf("de" to "bla"), + ), ).andIsBadRequest.andHasErrorMessage(Message.CANNOT_MODIFY_DISABLED_TRANSLATION) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerLanguagePermissionTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerLanguagePermissionTest.kt index 7d5523ef98..cef6e8dc7d 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerLanguagePermissionTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerLanguagePermissionTest.kt @@ -15,7 +15,6 @@ import org.springframework.test.web.servlet.ResultActions @SpringBootTest @AutoConfigureMockMvc class KeyControllerLanguagePermissionTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: LanguagePermissionsTestData @BeforeEach @@ -74,8 +73,8 @@ class KeyControllerLanguagePermissionTest : ProjectAuthControllerTest("/v2/proje "keys/$keyId/complex-update", mapOf( "name" to key.name, - "translations" to mapOf(langTag to langTag) - ) + "translations" to mapOf(langTag to langTag), + ), ) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerResolvableImportTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerResolvableImportTest.kt index c8413bd7b2..944981275b 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerResolvableImportTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerResolvableImportTest.kt @@ -23,7 +23,6 @@ import kotlin.properties.Delegates @SpringBootTest @AutoConfigureMockMvc class KeyControllerResolvableImportTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: ResolvableImportTestData var uploadedImageId by Delegates.notNull() var uploadedImageId2 by Delegates.notNull() @@ -37,16 +36,18 @@ class KeyControllerResolvableImportTest : ProjectAuthControllerTest("/v2/project testDataService.saveTestData(testData.root) projectSupplier = { testData.projectBuilder.self } userAccount = testData.user - uploadedImageId = imageUploadService.store( - generateImage(), - userAccount!!, - ImageUploadInfoDto(location = "My cool frame") - ).id - uploadedImageId2 = imageUploadService.store( - generateImage(), - testData.viewOnlyUser, - ImageUploadInfoDto(location = "My cool frame") - ).id + uploadedImageId = + imageUploadService.store( + generateImage(), + userAccount!!, + ImageUploadInfoDto(location = "My cool frame"), + ).id + uploadedImageId2 = + imageUploadService.store( + generateImage(), + testData.viewOnlyUser, + ImageUploadInfoDto(location = "My cool frame"), + ).id } @Test @@ -55,67 +56,77 @@ class KeyControllerResolvableImportTest : ProjectAuthControllerTest("/v2/project performProjectAuthPost( "keys/import-resolvable", mapOf( - "keys" to listOf( - mapOf( - "name" to "key-1", - "namespace" to "namespace-1", - "translations" to mapOf( - "de" to mapOf( - "text" to "changed", - "resolution" to "OVERRIDE" - ), - "en" to mapOf( - "text" to "new", - "resolution" to "NEW" - ) - ), - "screenshots" to listOf( - mapOf( - "text" to "Oh oh Oh", - "uploadedImageId" to uploadedImageId, - "positions" to listOf( + "keys" to + listOf( + mapOf( + "name" to "key-1", + "namespace" to "namespace-1", + "translations" to + mapOf( + "de" to + mapOf( + "text" to "changed", + "resolution" to "OVERRIDE", + ), + "en" to + mapOf( + "text" to "new", + "resolution" to "NEW", + ), + ), + "screenshots" to + listOf( mapOf( - "x" to 100, - "y" to 150, - "width" to 80, - "height" to 100 + "text" to "Oh oh Oh", + "uploadedImageId" to uploadedImageId, + "positions" to + listOf( + mapOf( + "x" to 100, + "y" to 150, + "width" to 80, + "height" to 100, + ), + mapOf( + "x" to 500, + "y" to 200, + "width" to 30, + "height" to 20, + ), + ), ), - mapOf( - "x" to 500, - "y" to 200, - "width" to 30, - "height" to 20 - ) - ) - ) - ) - ), - mapOf( - "name" to "key-2", - "namespace" to "namespace-1", - "translations" to mapOf( - "en" to mapOf( - "text" to "new", - "resolution" to "KEEP" - ) + ), ), - "screenshots" to listOf( - mapOf( - "text" to "Oh oh Oh", - "uploadedImageId" to uploadedImageId, - "positions" to listOf( + mapOf( + "name" to "key-2", + "namespace" to "namespace-1", + "translations" to + mapOf( + "en" to + mapOf( + "text" to "new", + "resolution" to "KEEP", + ), + ), + "screenshots" to + listOf( mapOf( - "x" to 100, - "y" to 150, - "width" to 80, - "height" to 100 - ) - ) - ) - ) + "text" to "Oh oh Oh", + "uploadedImageId" to uploadedImageId, + "positions" to + listOf( + mapOf( + "x" to 100, + "y" to 150, + "width" to 80, + "height" to 100, + ), + ), + ), + ), + ), ), - ) - ) + ), ).andIsOk.andAssertThatJson { node("keys").isArray.hasSize(2) node("screenshots") { @@ -142,22 +153,26 @@ class KeyControllerResolvableImportTest : ProjectAuthControllerTest("/v2/project performProjectAuthPost( "keys/import-resolvable", mapOf( - "keys" to listOf( - mapOf( - "name" to "key-1", - "namespace" to "namespace-1", - "translations" to mapOf( - "de" to mapOf( - "text" to "changed", - ), - "en" to mapOf( - "text" to "new", - "resolution" to "KEEP" - ) + "keys" to + listOf( + mapOf( + "name" to "key-1", + "namespace" to "namespace-1", + "translations" to + mapOf( + "de" to + mapOf( + "text" to "changed", + ), + "en" to + mapOf( + "text" to "new", + "resolution" to "KEEP", + ), + ), ), ), - ) - ) + ), ).andIsBadRequest.andAssertThatJson { node("code").isEqualTo("import_keys_error") node("params") { @@ -184,7 +199,7 @@ class KeyControllerResolvableImportTest : ProjectAuthControllerTest("/v2/project val data: Map<*, *> = jacksonObjectMapper().readValue(realData.inputStream, Map::class.java) performProjectAuthPost( "keys/import-resolvable", - data + data, ).andIsOk } @@ -195,18 +210,21 @@ class KeyControllerResolvableImportTest : ProjectAuthControllerTest("/v2/project performProjectAuthPost( "keys/import-resolvable", mapOf( - "keys" to listOf( - mapOf( - "name" to "key-1", - "namespace" to "namespace-1", - "translations" to mapOf( - "de" to mapOf( - "text" to "changed", - ), + "keys" to + listOf( + mapOf( + "name" to "key-1", + "namespace" to "namespace-1", + "translations" to + mapOf( + "de" to + mapOf( + "text" to "changed", + ), + ), ), ), - ) - ) + ), ).andIsForbidden } @@ -217,13 +235,14 @@ class KeyControllerResolvableImportTest : ProjectAuthControllerTest("/v2/project performProjectAuthPost( "keys/import-resolvable", mapOf( - "keys" to listOf( - mapOf( - "name" to "key-1", - "namespace" to "namespace-10", + "keys" to + listOf( + mapOf( + "name" to "key-1", + "namespace" to "namespace-10", + ), ), - ) - ) + ), ).andIsForbidden } @@ -234,33 +253,36 @@ class KeyControllerResolvableImportTest : ProjectAuthControllerTest("/v2/project performProjectAuthPost( "keys/import-resolvable", mapOf( - "keys" to listOf( - mapOf( - "name" to "key-1", - "namespace" to "namespace-1", - "screenshots" to listOf( - mapOf( - "text" to "Oh oh Oh", - "uploadedImageId" to uploadedImageId, - "positions" to listOf( + "keys" to + listOf( + mapOf( + "name" to "key-1", + "namespace" to "namespace-1", + "screenshots" to + listOf( mapOf( - "x" to 100, - "y" to 150, - "width" to 80, - "height" to 100 + "text" to "Oh oh Oh", + "uploadedImageId" to uploadedImageId, + "positions" to + listOf( + mapOf( + "x" to 100, + "y" to 150, + "width" to 80, + "height" to 100, + ), + mapOf( + "x" to 500, + "y" to 200, + "width" to 30, + "height" to 20, + ), + ), ), - mapOf( - "x" to 500, - "y" to 200, - "width" to 30, - "height" to 20 - ) - ) - ) - ) + ), + ), ), - ) - ) + ), ).andIsForbidden } @@ -271,13 +293,14 @@ class KeyControllerResolvableImportTest : ProjectAuthControllerTest("/v2/project performProjectAuthPost( "keys/import-resolvable", mapOf( - "keys" to listOf( - mapOf( - "name" to "key-1", - "namespace" to "namespace-8", - ) - ), - ) + "keys" to + listOf( + mapOf( + "name" to "key-1", + "namespace" to "namespace-8", + ), + ), + ), ).andIsOk } @@ -288,22 +311,30 @@ class KeyControllerResolvableImportTest : ProjectAuthControllerTest("/v2/project performProjectAuthPost( "keys/import-resolvable", mapOf( - "keys" to listOf( - mapOf( - "name" to "key-1", - "namespace" to "namespace-1", - "translations" to mapOf( - "en" to mapOf( - "text" to "changed", - ), + "keys" to + listOf( + mapOf( + "name" to "key-1", + "namespace" to "namespace-1", + "translations" to + mapOf( + "en" to + mapOf( + "text" to "changed", + ), + ), ), - ) - ), - ) + ), + ), ).andIsOk } - fun assertTranslationText(namespace: String?, keyName: String, languageTag: String, expectedText: String) { + fun assertTranslationText( + namespace: String?, + keyName: String, + languageTag: String, + expectedText: String, + ) { projectService.get(testData.projectBuilder.self.id) .keys .find { it.name == keyName && it.namespace?.name == namespace }!! @@ -311,7 +342,7 @@ class KeyControllerResolvableImportTest : ProjectAuthControllerTest("/v2/project .find { it.language.tag == languageTag }!! .text .assert.isEqualTo( - expectedText + expectedText, ) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerTest.kt index f359bd07ca..68e8aff904 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2KeyController/KeyControllerTest.kt @@ -195,7 +195,8 @@ class KeyControllerTest : ProjectAuthControllerTest("/v2/projects/") { projectSupplier = { testData.project } performProjectAuthDelete( - "keys", mapOf("ids" to listOf(testData.firstKey.id, testData.secondKey.id)) + "keys", + mapOf("ids" to listOf(testData.firstKey.id, testData.secondKey.id)), ).andIsOk assertThat(keyService.findOptional(testData.firstKey.id)).isEmpty assertThat(keyService.findOptional(testData.secondKey.id)).isEmpty @@ -228,13 +229,13 @@ class KeyControllerTest : ProjectAuthControllerTest("/v2/projects/") { "name" to "first_key", "translations" to mapOf("en" to "hello"), - "tags" to listOf("tag1", "tag2") + "tags" to listOf("tag1", "tag2"), ), mapOf( "name" to "new_key", "translations" to mapOf("en" to "hello"), - "tags" to listOf("tag1", "tag2", "test") + "tags" to listOf("tag1", "tag2", "test"), ), mapOf( "name" to "key_without_tags", @@ -245,17 +246,18 @@ class KeyControllerTest : ProjectAuthControllerTest("/v2/projects/") { "name" to "key_with_empty_tags", "translations" to mapOf("en" to "hello"), - "tags" to listOf() + "tags" to listOf(), ), - ) - ) + ), + ), ).andIsOk executeInNewTransaction { keyService.get(testData.firstKey.id).translations.find { it.language.tag == "en" }.assert.isNull() - val key = projectService.get(testData.project.id).keys.find { - it.name == "new_key" - } + val key = + projectService.get(testData.project.id).keys.find { + it.name == "new_key" + } key.assert.isNotNull() key!!.keyMeta!!.tags.assert.hasSize(3) key.translations.find { it.language.tag == "en" }!!.text.assert.isEqualTo("hello") @@ -278,8 +280,8 @@ class KeyControllerTest : ProjectAuthControllerTest("/v2/projects/") { "translations" to mapOf("en" to "hello"), ), - ) - ) + ), + ), ).andIsOk } @@ -321,8 +323,8 @@ class KeyControllerTest : ProjectAuthControllerTest("/v2/projects/") { } ] } - """.trimIndent() - ) + """.trimIndent(), + ), ).andIsOk } @@ -332,7 +334,7 @@ class KeyControllerTest : ProjectAuthControllerTest("/v2/projects/") { saveTestDataAndPrepare() performProjectAuthPost( "keys", - CreateKeyDto(name = "super_key", translations = mapOf("en" to "Hello", "de" to "Hallo")) + CreateKeyDto(name = "super_key", translations = mapOf("en" to "Hello", "de" to "Hallo")), ).andIsCreated executeInNewTransaction { @@ -358,10 +360,10 @@ class KeyControllerTest : ProjectAuthControllerTest("/v2/projects/") { mapOf( "name" to "first_key", "translations" to - mapOf("de" to "hello") + mapOf("de" to "hello"), ), - ) - ) + ), + ), ).andIsForbidden } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerCreateTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerCreateTest.kt index 6aee2a922e..14b420cb0b 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerCreateTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerCreateTest.kt @@ -23,10 +23,13 @@ import org.springframework.transaction.annotation.Transactional @AutoConfigureMockMvc @Transactional class V2ProjectsControllerCreateTest : AuthorizedControllerTest() { - private val languageDTO = LanguageDto( - "English", - "Original English", "en", "\uD83C\uDDEC\uD83C\uDDE7" - ) + private val languageDTO = + LanguageDto( + "English", + "Original English", + "en", + "\uD83C\uDDEC\uD83C\uDDE7", + ) lateinit var createForLanguagesDto: CreateProjectDTO @@ -34,25 +37,27 @@ class V2ProjectsControllerCreateTest : AuthorizedControllerTest() { fun setup() { val base = dbPopulator.createBase("SomeProject", "user") userAccount = base.userAccount - createForLanguagesDto = CreateProjectDTO( - name = "What a project", - organizationId = base.organization.id, - languages = listOf( - LanguageDto( - name = "English", - originalName = "English", - tag = "en", - flagEmoji = "a" - ), - LanguageDto( - name = "Czech", - originalName = "česky", - tag = "cs", - flagEmoji = "b" - ) - ), - baseLanguageTag = "cs" - ) + createForLanguagesDto = + CreateProjectDTO( + name = "What a project", + organizationId = base.organization.id, + languages = + listOf( + LanguageDto( + name = "English", + originalName = "English", + tag = "en", + flagEmoji = "a", + ), + LanguageDto( + name = "Czech", + originalName = "česky", + tag = "cs", + flagEmoji = "b", + ), + ), + baseLanguageTag = "cs", + ) } @Test @@ -80,26 +85,28 @@ class V2ProjectsControllerCreateTest : AuthorizedControllerTest() { @Test fun testCreateValidationEmptyLanguages() { - val request = CreateProjectDTO( - "A name", - listOf() - ) + val request = + CreateProjectDTO( + "A name", + listOf(), + ) performAuthPost("/v2/projects", request).andIsBadRequest } @Test fun `validates languages`() { - val request = CreateProjectDTO( - "A name", - listOf( - LanguageDto( - name = "English", - originalName = "English", - tag = "en,aa", - flagEmoji = "a" - ) + val request = + CreateProjectDTO( + "A name", + listOf( + LanguageDto( + name = "English", + originalName = "English", + tag = "en,aa", + flagEmoji = "a", + ), + ), ) - ) performAuthPost("/v2/projects", request) .andPrettyPrint .andIsBadRequest @@ -112,8 +119,8 @@ class V2ProjectsControllerCreateTest : AuthorizedControllerTest() { mvc.perform( AuthorizedRequestFactory.loggedPost("/v2/projects") .contentType(MediaType.APPLICATION_JSON).content( - jacksonObjectMapper().writeValueAsString(request) - ) + jacksonObjectMapper().writeValueAsString(request), + ), ) .andExpect(MockMvcResultMatchers.status().isOk) .andReturn() @@ -136,10 +143,11 @@ class V2ProjectsControllerCreateTest : AuthorizedControllerTest() { } private fun testCreateValidationSizeLong() { - val request = CreateProjectDTO( - "Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...", - listOf(languageDTO) - ) + val request = + CreateProjectDTO( + "Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...", + listOf(languageDTO), + ) val mvcResult = performAuthPost("/v2/projects", request).andIsBadRequest.andReturn() assertThat(mvcResult).error().isStandardValidation } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerEditTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerEditTest.kt index 4791eefeba..389c82ecde 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerEditTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerEditTest.kt @@ -16,11 +16,12 @@ class V2ProjectsControllerEditTest : AuthorizedControllerTest() { @Test fun `edits project`() { val base = dbPopulator.createBase("What a project") - val content = EditProjectDTO( - name = "new name", - baseLanguageId = base.project.languages.toList()[1].id, - slug = "new-slug" - ) + val content = + EditProjectDTO( + name = "new name", + baseLanguageId = base.project.languages.toList()[1].id, + slug = "new-slug", + ) performAuthPut("/v2/projects/${base.project.id}", content).andPrettyPrint.andIsOk.andAssertThatJson { node("name").isEqualTo(content.name) node("slug").isEqualTo(content.slug) @@ -31,10 +32,11 @@ class V2ProjectsControllerEditTest : AuthorizedControllerTest() { @Test fun `validates project on edit`() { val base = dbPopulator.createBase("What a project") - val content = EditProjectDTO( - name = "", - baseLanguageId = base.project.languages.toList()[0].id, - ) + val content = + EditProjectDTO( + name = "", + baseLanguageId = base.project.languages.toList()[0].id, + ) performAuthPut("/v2/projects/${base.project.id}", content).andIsBadRequest.andAssertThatJson { node("STANDARD_VALIDATION.name").isNotNull } @@ -43,9 +45,10 @@ class V2ProjectsControllerEditTest : AuthorizedControllerTest() { @Test fun `automatically chooses base language`() { val base = dbPopulator.createBase("What a project") - val content = EditProjectDTO( - name = "test", - ) + val content = + EditProjectDTO( + name = "test", + ) performAuthPut("/v2/projects/${base.project.id}", content).andPrettyPrint.andIsOk.andAssertThatJson { node("name").isEqualTo(content.name) node("baseLanguage.id").isEqualTo(base.project.languages.toList()[0].id) diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerInvitationTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerInvitationTest.kt index 880e075ffd..4eddf66cb7 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerInvitationTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerInvitationTest.kt @@ -34,7 +34,6 @@ import org.springframework.boot.test.context.SpringBootTest @SpringBootTest @AutoConfigureMockMvc class V2ProjectsControllerInvitationTest : ProjectAuthControllerTest("/v2/projects/") { - companion object { private const val INVITED_EMAIL = "jon@doe.com" private const val INVITED_NAME = "Franta" @@ -79,10 +78,11 @@ class V2ProjectsControllerInvitationTest : ProjectAuthControllerTest("/v2/projec @Test @ProjectJWTAuthTestMethod fun `invites user to project with languages (translate)`() { - val result = invitationTestUtil.perform { getLang -> - type = ProjectPermissionType.TRANSLATE - languages = setOf(getLang("en")) - }.andIsOk + val result = + invitationTestUtil.perform { getLang -> + type = ProjectPermissionType.TRANSLATE + languages = setOf(getLang("en")) + }.andIsOk val invitation = invitationTestUtil.getInvitation(result) invitation.permission?.translateLanguages!!.map { it.tag }.assert.contains("en") // stores invitation.permission?.viewLanguages!!.map { it.tag }.assert.contains() // ads also to view @@ -91,11 +91,12 @@ class V2ProjectsControllerInvitationTest : ProjectAuthControllerTest("/v2/projec @Test @ProjectJWTAuthTestMethod fun `invites user to project with languages (review)`() { - val result = invitationTestUtil.perform { getLang -> - type = ProjectPermissionType.REVIEW - translateLanguages = setOf(getLang("en")) - stateChangeLanguages = setOf(getLang("en")) - }.andIsOk + val result = + invitationTestUtil.perform { getLang -> + type = ProjectPermissionType.REVIEW + translateLanguages = setOf(getLang("en")) + stateChangeLanguages = setOf(getLang("en")) + }.andIsOk val invitation = invitationTestUtil.getInvitation(result) invitation.permission?.stateChangeLanguages!!.map { it.tag }.assert.contains("en") // stores invitation.permission?.viewLanguages!!.map { it.tag }.assert.contains() // ads also to view @@ -104,13 +105,16 @@ class V2ProjectsControllerInvitationTest : ProjectAuthControllerTest("/v2/projec @Test @ProjectJWTAuthTestMethod fun `cannot set different languages (review)`() { - val result = invitationTestUtil.perform { getLang -> - type = ProjectPermissionType.REVIEW - translateLanguages = setOf(getLang("en")) - stateChangeLanguages = setOf() - } - .andIsBadRequest - .andHasErrorMessage(Message.CANNOT_SET_DIFFERENT_TRANSLATE_AND_STATE_CHANGE_LANGUAGES_FOR_LEVEL_BASED_PERMISSIONS) + val result = + invitationTestUtil.perform { getLang -> + type = ProjectPermissionType.REVIEW + translateLanguages = setOf(getLang("en")) + stateChangeLanguages = setOf() + } + .andIsBadRequest + .andHasErrorMessage( + Message.CANNOT_SET_DIFFERENT_TRANSLATE_AND_STATE_CHANGE_LANGUAGES_FOR_LEVEL_BASED_PERMISSIONS, + ) } @Test @@ -189,8 +193,8 @@ class V2ProjectsControllerInvitationTest : ProjectAuthControllerTest("/v2/projec Permission( user = user2, project = project, - type = ProjectPermissionType.MANAGE - ) + type = ProjectPermissionType.MANAGE, + ), ) userAccount = user projectSupplier = { project } @@ -201,14 +205,15 @@ class V2ProjectsControllerInvitationTest : ProjectAuthControllerTest("/v2/projec ProjectInviteUserDto( type = ProjectPermissionType.VIEW, email = "hello@hello2.com", - name = "Franta" - ) + name = "Franta", + ), ).andIsBadRequest } private fun inviteWithManagePermissions(): String { - val invitationJson = performProjectAuthPut("/invite", ProjectInviteUserDto(ProjectPermissionType.MANAGE)) - .andIsOk.andGetContentAsString + val invitationJson = + performProjectAuthPut("/invite", ProjectInviteUserDto(ProjectPermissionType.MANAGE)) + .andIsOk.andGetContentAsString return parseCode(invitationJson) } @@ -220,14 +225,15 @@ class V2ProjectsControllerInvitationTest : ProjectAuthControllerTest("/v2/projec private fun parseCode(invitationJson: String) = jacksonObjectMapper().readValue>(invitationJson)["code"] as String - private fun performInviteWithNameAndEmail() = performProjectAuthPut( - "/invite", - ProjectInviteUserDto( - type = ProjectPermissionType.MANAGE, - email = INVITED_EMAIL, - name = INVITED_NAME + private fun performInviteWithNameAndEmail() = + performProjectAuthPut( + "/invite", + ProjectInviteUserDto( + type = ProjectPermissionType.MANAGE, + email = INVITED_EMAIL, + name = INVITED_NAME, + ), ) - ) private fun prepareTestData(): BaseTestData { val testData = BaseTestData() @@ -245,8 +251,8 @@ class V2ProjectsControllerInvitationTest : ProjectAuthControllerTest("/v2/projec languagePermissions = LanguagePermissions(translate = project.languages, view = null, stateChange = null), name = "Franta", email = "a@a.a", - scopes = null - ) + scopes = null, + ), ) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerLeavingTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerLeavingTest.kt index efd6e74a64..a609b422e6 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerLeavingTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerLeavingTest.kt @@ -16,7 +16,6 @@ import org.springframework.boot.test.context.SpringBootTest @SpringBootTest @AutoConfigureMockMvc class V2ProjectsControllerLeavingTest : ProjectAuthControllerTest("/v2/projects/") { - @Test @ProjectJWTAuthTestMethod fun `user can leave project`() { diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerPermissionsTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerPermissionsTest.kt index 0b8f907650..87ee5d5bb2 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerPermissionsTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerPermissionsTest.kt @@ -20,7 +20,6 @@ import org.springframework.boot.test.context.SpringBootTest @SpringBootTest @AutoConfigureMockMvc class V2ProjectsControllerPermissionsTest : ProjectAuthControllerTest("/v2/projects/") { - private val permissionTestUtil: PermissionTestUtil by lazy { PermissionTestUtil(this, applicationContext) } @Test @@ -48,9 +47,10 @@ class V2ProjectsControllerPermissionsTest : ProjectAuthControllerTest("/v2/proje @ProjectJWTAuthTestMethod fun `cannot set permission to user outside of project or organization`() { val testData = PermissionsTestData() - val user = testData.root.addUserAccount { - username = "pepa@seznam.cz" - }.self + val user = + testData.root.addUserAccount { + username = "pepa@seznam.cz" + }.self testDataService.saveTestData(testData.root) userAccount = testData.admin.self projectSupplier = { testData.projectBuilder.self } @@ -62,17 +62,18 @@ class V2ProjectsControllerPermissionsTest : ProjectAuthControllerTest("/v2/proje @ProjectJWTAuthTestMethod fun `sets user permissions to organization base`() { val testData = PermissionsTestData() - val me = testData.addUserWithPermissions( - type = ProjectPermissionType.EDIT, - organizationBaseScopes = listOf(Scope.KEYS_VIEW) - ) + val me = + testData.addUserWithPermissions( + type = ProjectPermissionType.EDIT, + organizationBaseScopes = listOf(Scope.KEYS_VIEW), + ) testDataService.saveTestData(testData.root) userAccount = testData.admin.self this.projectSupplier = { testData.projectBuilder.self } permissionService.getProjectPermissionData( testData.projectBuilder.self.id, - me.id + me.id, ).directPermissions.assert.isNotNull performProjectAuthPut("users/${me.id}/set-by-organization").andIsOk val permissionData = permissionService.getProjectPermissionData(testData.projectBuilder.self.id, me.id) diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerTest.kt index 85e8b36892..8b059e1ad4 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerTest.kt @@ -89,7 +89,7 @@ open class V2ProjectsControllerTest : ProjectAuthControllerTest("/v2/projects/") "TRANSLATED": 0, "REVIEWED": 0 } - """ + """, ) node("[1].stats.translationStatePercentages").isEqualTo( """ @@ -98,7 +98,7 @@ open class V2ProjectsControllerTest : ProjectAuthControllerTest("/v2/projects/") "TRANSLATED": 75.0, "REVIEWED": 0.0 } - """ + """, ) } } @@ -117,8 +117,8 @@ open class V2ProjectsControllerTest : ProjectAuthControllerTest("/v2/projects/") it.node("[0].computedPermission.permittedLanguageIds").isArray.hasSize(2).containsAll( mutableListOf( testData.project2English.id, - testData.project2Deutsch.id - ) + testData.project2Deutsch.id, + ), ) } } @@ -132,7 +132,7 @@ open class V2ProjectsControllerTest : ProjectAuthControllerTest("/v2/projects/") project = base.project, user = userAccount, type = ProjectPermissionType.TRANSLATE, - ).apply { translateLanguages = mutableSetOf(base.project.languages.first()) } + ).apply { translateLanguages = mutableSetOf(base.project.languages.first()) }, ) performAuthGet("/v2/projects/${base.project.id}").andPrettyPrint.andAssertThatJson.let { @@ -164,7 +164,7 @@ open class V2ProjectsControllerTest : ProjectAuthControllerTest("/v2/projects/") project = directPermissionProject type = ProjectPermissionType.TRANSLATE translateLanguages = project!!.languages.toMutableSet() - } + }, ) loginAsUser(usersAndOrganizations[1].name) @@ -215,10 +215,11 @@ open class V2ProjectsControllerTest : ProjectAuthControllerTest("/v2/projects/") @Test fun setUsersPermissionsOwn() { val usersAndOrganizations = dbPopulator.createUsersAndOrganizations() - val repo = usersAndOrganizations[1] - .organizationRoles[0] - .organization!! - .projects[0] + val repo = + usersAndOrganizations[1] + .organizationRoles[0] + .organization!! + .projects[0] loginAsUser(usersAndOrganizations[1].name) diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerWithCacheTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerWithCacheTest.kt index f03fd55a6e..bdece3efdf 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerWithCacheTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/V2ProjectsControllerWithCacheTest.kt @@ -8,7 +8,7 @@ import org.springframework.boot.test.context.SpringBootTest @SpringBootTest( properties = [ "tolgee.cache.enabled=true", - ] + ], ) @AutoConfigureMockMvc class V2ProjectsControllerWithCacheTest : V2ProjectsControllerTest() diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ScreenshotController/AbstractV2ScreenshotControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ScreenshotController/AbstractV2ScreenshotControllerTest.kt index b9192a1934..2ad1c52391 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ScreenshotController/AbstractV2ScreenshotControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ScreenshotController/AbstractV2ScreenshotControllerTest.kt @@ -28,21 +28,28 @@ abstract class AbstractV2ScreenshotControllerTest : ProjectAuthControllerTest("/ File("${tolgeeProperties.fileStorage.fsDataPath}/screenshots").deleteRecursively() } - protected fun performStoreScreenshot(project: Project, key: Key, info: Any? = null): ResultActions { + protected fun performStoreScreenshot( + project: Project, + key: Key, + info: Any? = null, + ): ResultActions { return performProjectAuthMultipart( url = "keys/${key.id}/screenshots", - files = listOf( - MockMultipartFile( - "screenshot", "originalShot.png", "image/png", - screenshotFile.inputStream.readAllBytes() + files = + listOf( + MockMultipartFile( + "screenshot", + "originalShot.png", + "image/png", + screenshotFile.inputStream.readAllBytes(), + ), + MockMultipartFile( + "info", + "info", + MediaType.APPLICATION_JSON_VALUE, + jacksonObjectMapper().writeValueAsBytes(info), + ), ), - MockMultipartFile( - "info", - "info", - MediaType.APPLICATION_JSON_VALUE, - jacksonObjectMapper().writeValueAsBytes(info) - ) - ) ) } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ScreenshotController/KeyScreenshotControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ScreenshotController/KeyScreenshotControllerTest.kt index 566a362d72..d3a9f87f4c 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ScreenshotController/KeyScreenshotControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ScreenshotController/KeyScreenshotControllerTest.kt @@ -45,14 +45,19 @@ class KeyScreenshotControllerTest : AbstractV2ScreenshotControllerTest() { performStoreScreenshot( project, key, - info = mapOf( - "positions" to listOf( - mapOf( - "x" to 200, "y" to 100, "width" to 40, "height" to 40 - ) + info = + mapOf( + "positions" to + listOf( + mapOf( + "x" to 200, + "y" to 100, + "width" to 40, + "height" to 40, + ), + ), + "text" to text, ), - "text" to text - ) ).andPrettyPrint.andIsCreated.andAssertThatJson { executeInNewTransaction { val screenshots = screenshotService.findAll(key = key) @@ -78,7 +83,7 @@ class KeyScreenshotControllerTest : AbstractV2ScreenshotControllerTest() { performStoreScreenshot( project, key, - info = null + info = null, ).andIsCreated } @@ -96,16 +101,17 @@ class KeyScreenshotControllerTest : AbstractV2ScreenshotControllerTest() { @Test @ProjectJWTAuthTestMethod fun findAll() { - val (key, key2) = executeInNewTransaction { - val key = keyService.create(project, CreateKeyDto("test")) - val key2 = keyService.create(project, CreateKeyDto("test_2")) + val (key, key2) = + executeInNewTransaction { + val key = keyService.create(project, CreateKeyDto("test")) + val key2 = keyService.create(project, CreateKeyDto("test_2")) - screenshotService.store(screenshotFile, key, null) - screenshotService.store(screenshotFile, key, null) - screenshotService.store(screenshotFile, key2, null) + screenshotService.store(screenshotFile, key, null) + screenshotService.store(screenshotFile, key, null) + screenshotService.store(screenshotFile, key2, null) - key to key2 - } + key to key2 + } performProjectAuthGet("keys/${key.id}/screenshots").andIsOk.andPrettyPrint.andAssertThatJson { node("_embedded.screenshots").isArray.hasSize(2) @@ -125,11 +131,12 @@ class KeyScreenshotControllerTest : AbstractV2ScreenshotControllerTest() { fun `returns correct fileUrl when absolute url is set`() { tolgeeProperties.fileStorageUrl = "http://hello.com" - val key = executeInNewTransaction { - val key = keyService.create(project, CreateKeyDto("test")) - screenshotService.store(screenshotFile, key, null) - key - } + val key = + executeInNewTransaction { + val key = keyService.create(project, CreateKeyDto("test")) + screenshotService.store(screenshotFile, key, null) + key + } performProjectAuthGet("keys/${key.id}/screenshots").andIsOk.andPrettyPrint.andAssertThatJson { node("_embedded.screenshots[0].fileUrl").isString.startsWith("http://hello.com/screenshots") @@ -139,16 +146,18 @@ class KeyScreenshotControllerTest : AbstractV2ScreenshotControllerTest() { @Test @ProjectJWTAuthTestMethod fun getScreenshotFile() { - val screenshot = executeInNewTransaction { - val key = keyService.create(project, CreateKeyDto("test")) - screenshotService.store(screenshotFile, key, null) - } + val screenshot = + executeInNewTransaction { + val key = keyService.create(project, CreateKeyDto("test")) + screenshotService.store(screenshotFile, key, null) + } val file = File(tolgeeProperties.fileStorage.fsDataPath + "/screenshots/" + screenshot.filename) - val result = performAuthGet("/screenshots/${screenshot.filename}").andIsOk - .andExpect( - header().string("Cache-Control", "max-age=365, must-revalidate, no-transform") - ) - .andReturn() + val result = + performAuthGet("/screenshots/${screenshot.filename}").andIsOk + .andExpect( + header().string("Cache-Control", "max-age=365, must-revalidate, no-transform"), + ) + .andReturn() performAuthGet("/screenshots/${screenshot.thumbnailFilename}").andIsOk assertThat(result.response.contentAsByteArray).isEqualTo(file.readBytes()) } @@ -156,14 +165,16 @@ class KeyScreenshotControllerTest : AbstractV2ScreenshotControllerTest() { @Test @ProjectJWTAuthTestMethod fun delete() { - val (key, list) = executeInNewTransaction { - val key = keyService.create(project, CreateKeyDto("test")) + val (key, list) = + executeInNewTransaction { + val key = keyService.create(project, CreateKeyDto("test")) - val list = (1..20).map { - screenshotService.store(screenshotFile, key, null) - }.toCollection(mutableListOf()) - key to list - } + val list = + (1..20).map { + screenshotService.store(screenshotFile, key, null) + }.toCollection(mutableListOf()) + key to list + } val chunked = list.chunked(10) val toDelete = chunked[0] val notToDelete = chunked[1] @@ -180,15 +191,18 @@ class KeyScreenshotControllerTest : AbstractV2ScreenshotControllerTest() { @ProjectJWTAuthTestMethod fun uploadValidationNoImage() { val key = keyService.create(project, CreateKeyDto("test")) - val response = performProjectAuthMultipart( - "keys/${key.id}/screenshots", - listOf( - MockMultipartFile( - "screenshot", "originalShot.png", "not_valid", - "test".toByteArray() - ) - ), - ).andIsBadRequest.andReturn() + val response = + performProjectAuthMultipart( + "keys/${key.id}/screenshots", + listOf( + MockMultipartFile( + "screenshot", + "originalShot.png", + "not_valid", + "test".toByteArray(), + ), + ), + ).andIsBadRequest.andReturn() assertThat(response).error().isCustomValidation.hasMessage("file_not_image") } } diff --git a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ScreenshotController/SecuredKeyScreenshotControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ScreenshotController/SecuredKeyScreenshotControllerTest.kt index 17551e5c92..a7ec67fb54 100644 --- a/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ScreenshotController/SecuredKeyScreenshotControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ScreenshotController/SecuredKeyScreenshotControllerTest.kt @@ -25,8 +25,8 @@ import java.util.* @SpringBootTest( properties = [ "tolgee.authentication.secured-image-retrieval=true", - "tolgee.authentication.secured-image-timestamp-max-age=10000" - ] + "tolgee.authentication.secured-image-timestamp-max-age=10000", + ], ) @TestInstance(TestInstance.Lifecycle.PER_CLASS) class SecuredKeyScreenshotControllerTest : AbstractV2ScreenshotControllerTest() { @@ -55,15 +55,16 @@ class SecuredKeyScreenshotControllerTest : AbstractV2ScreenshotControllerTest() val key = keyService.create(project, CreateKeyDto("test")) val screenshot = screenshotService.store(screenshotFile, key, null) - val token = jwtService.emitTicket( - userAccount!!.id, - JwtService.TicketType.IMG_ACCESS, - 5000, - mapOf( - "fileName" to screenshot.filename, - "projectId" to project.id.toString(), + val token = + jwtService.emitTicket( + userAccount!!.id, + JwtService.TicketType.IMG_ACCESS, + 5000, + mapOf( + "fileName" to screenshot.filename, + "projectId" to project.id.toString(), + ), ) - ) moveCurrentDate(Duration.ofSeconds(10)) performAuthGet("/screenshots/${screenshot.filename}?token=$token").andIsUnauthorized @@ -78,15 +79,16 @@ class SecuredKeyScreenshotControllerTest : AbstractV2ScreenshotControllerTest() val key = keyService.create(project, CreateKeyDto("test")) val screenshot = screenshotService.store(screenshotFile, key, null) - val token = jwtService.emitTicket( - userAccount!!.id, - JwtService.TicketType.IMG_ACCESS, - 5000, - mapOf( - "fileName" to screenshot.filename, - "projectId" to project.id.toString(), + val token = + jwtService.emitTicket( + userAccount!!.id, + JwtService.TicketType.IMG_ACCESS, + 5000, + mapOf( + "fileName" to screenshot.filename, + "projectId" to project.id.toString(), + ), ) - ) performAuthGet("/screenshots/${screenshot.filename}?token=$token").andIsOk } @@ -136,27 +138,29 @@ class SecuredKeyScreenshotControllerTest : AbstractV2ScreenshotControllerTest() val newUser = dbPopulator.createUserIfNotExists("screenshot-test-user-1") val newUserRandom = dbPopulator.createUserIfNotExists("screenshot-test-user-2") - val userPermission = permissionService.create( - Permission( - type = null, - user = newUser, - project = project, - scopes = Scope.expand(Scope.SCREENSHOTS_UPLOAD) + val userPermission = + permissionService.create( + Permission( + type = null, + user = newUser, + project = project, + scopes = Scope.expand(Scope.SCREENSHOTS_UPLOAD), + ), ) - ) val key = keyService.create(project, CreateKeyDto("test")) val screenshot = screenshotService.store(screenshotFile, key, null) - val token = jwtService.emitTicket( - newUser.id, - JwtService.TicketType.IMG_ACCESS, - 5000, - mapOf( - "fileName" to screenshot.filename, - "projectId" to project.id.toString(), + val token = + jwtService.emitTicket( + newUser.id, + JwtService.TicketType.IMG_ACCESS, + 5000, + mapOf( + "fileName" to screenshot.filename, + "projectId" to project.id.toString(), + ), ) - ) // Login as someone who has 0 access to the project and see if it works loginAsUser(newUserRandom) diff --git a/backend/app/src/test/kotlin/io/tolgee/autoTranslating/AutoTranslatingTest.kt b/backend/app/src/test/kotlin/io/tolgee/autoTranslating/AutoTranslatingTest.kt index 4e91ce411b..1a9c718693 100644 --- a/backend/app/src/test/kotlin/io/tolgee/autoTranslating/AutoTranslatingTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/autoTranslating/AutoTranslatingTest.kt @@ -144,7 +144,7 @@ class AutoTranslatingTest : MachineTranslationTest() { keyService .get(testData.project.id, CREATE_KEY_NAME, null) .translations - .find { it.language == testData.spanishLanguage } + .find { it.language == testData.spanishLanguage }, ) .isNull() } @@ -161,10 +161,11 @@ class AutoTranslatingTest : MachineTranslationTest() { performCreateKey( keyName = "jaj", - translations = mapOf( - "en" to "Hello2", - "de" to "Hallo2" - ) + translations = + mapOf( + "en" to "Hello2", + "de" to "Hallo2", + ), ) waitForSpanishTranslationSet("jaj") @@ -177,13 +178,15 @@ class AutoTranslatingTest : MachineTranslationTest() { private fun waitForSpanishTranslationSet(keyName: String) { waitForNotThrowing(pollTime = 200) { transactionTemplate.execute { - val translations = keyService - .get(testData.project.id, keyName, null) - .translations - val spanishTranslation = translations - .find { - it.language == testData.spanishLanguage - } + val translations = + keyService + .get(testData.project.id, keyName, null) + .translations + val spanishTranslation = + translations + .find { + it.language == testData.spanishLanguage + } spanishTranslation?.text.isNullOrBlank().assert.isFalse() } } @@ -218,19 +221,19 @@ class AutoTranslatingTest : MachineTranslationTest() { mapOf( "languageId" to null, "usingTranslationMemory" to false, - "usingMachineTranslation" to false + "usingMachineTranslation" to false, ), mapOf( "languageId" to testData.germanLanguage.id, "usingTranslationMemory" to false, - "usingMachineTranslation" to false + "usingMachineTranslation" to false, ), mapOf( "languageId" to testData.spanishLanguage.id, "usingTranslationMemory" to false, - "usingMachineTranslation" to false - ) - ) + "usingMachineTranslation" to false, + ), + ), ).andIsOk.andAssertThatJson { node("_embedded.configs").isArray.hasSize(3) } @@ -256,24 +259,27 @@ class AutoTranslatingTest : MachineTranslationTest() { performCreateHalloKeyWithEnAndDeTranslations() Thread.sleep(2000) transactionTemplate.execute { - val esTranslation = keyService.get(testData.project.id, CREATE_KEY_NAME, null) - .translations - .find { it.language == testData.spanishLanguage } + val esTranslation = + keyService.get(testData.project.id, CREATE_KEY_NAME, null) + .translations + .find { it.language == testData.spanishLanguage } assertThat(esTranslation).isNull() } } - private fun getCreatedEsTranslation() = keyService.get(testData.project.id, CREATE_KEY_NAME, null) - .getLangTranslation(testData.spanishLanguage).text + private fun getCreatedEsTranslation() = + keyService.get(testData.project.id, CREATE_KEY_NAME, null) + .getLangTranslation(testData.spanishLanguage).text private fun performCreateHalloKeyWithEnAndDeTranslations(keyName: String = CREATE_KEY_NAME) { performCreateKey( keyName = keyName, - translations = mapOf( - "en" to "Hello", - "de" to "Hallo" - ) + translations = + mapOf( + "en" to "Hello", + "de" to "Hallo", + ), ) } @@ -294,10 +300,16 @@ class AutoTranslatingTest : MachineTranslationTest() { } } - private fun getCreatedDeTranslation() = keyService.get(testData.project.id, CREATE_KEY_NAME, null) - .getLangTranslation(testData.germanLanguage).text + private fun getCreatedDeTranslation() = + keyService.get(testData.project.id, CREATE_KEY_NAME, null) + .getLangTranslation(testData.germanLanguage).text - private fun performSetConfig(usingTm: Boolean, usingMt: Boolean, enableForImport: Boolean, languageId: Long? = null) { + private fun performSetConfig( + usingTm: Boolean, + usingMt: Boolean, + enableForImport: Boolean, + languageId: Long? = null, + ) { performProjectAuthPut( "per-language-auto-translation-settings", listOf( @@ -305,9 +317,9 @@ class AutoTranslatingTest : MachineTranslationTest() { "languageId" to languageId, "usingTranslationMemory" to usingTm, "usingMachineTranslation" to usingMt, - "enableForImport" to enableForImport - ) - ) + "enableForImport" to enableForImport, + ), + ), ).andIsOk } @@ -316,8 +328,8 @@ class AutoTranslatingTest : MachineTranslationTest() { "translations", SetTranslationsWithKeyDto( key = key, - translations = mapOf("en" to "Hello") - ) + translations = mapOf("en" to "Hello"), + ), ) } diff --git a/backend/app/src/test/kotlin/io/tolgee/automation/AutomationCachingTest.kt b/backend/app/src/test/kotlin/io/tolgee/automation/AutomationCachingTest.kt index 3df1f316e4..05d65963dc 100644 --- a/backend/app/src/test/kotlin/io/tolgee/automation/AutomationCachingTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/automation/AutomationCachingTest.kt @@ -23,10 +23,9 @@ import org.springframework.cache.Cache @SpringBootTest( properties = [ "tolgee.cache.enabled=true", - ] + ], ) class AutomationCachingTest : ProjectAuthControllerTest("/v2/projects/") { - private lateinit var testData: ContentDeliveryConfigTestData @Autowired @@ -68,8 +67,8 @@ class AutomationCachingTest : ProjectAuthControllerTest("/v2/projects/") { listOf( testData.projectBuilder.self.id, AutomationTriggerType.TRANSLATION_DATA_MODIFICATION, - null - ) + null, + ), ) @Test @@ -92,16 +91,17 @@ class AutomationCachingTest : ProjectAuthControllerTest("/v2/projects/") { getFromCache().assert.isNull() } - private fun getEntityManagerInvocationsCount() = Mockito.mockingDetails(entityManager) - .invocations.count { - it.method.name == "createQuery" && (it.arguments[0] as? String)?.contains("Automation") == true - } + private fun getEntityManagerInvocationsCount() = + Mockito.mockingDetails(entityManager) + .invocations.count { + it.method.name == "createQuery" && (it.arguments[0] as? String)?.contains("Automation") == true + } private fun doGetAutomations() { automationService.getProjectAutomations( testData.projectBuilder.self.id, AutomationTriggerType.TRANSLATION_DATA_MODIFICATION, - null + null, ) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/automation/AutomationIntegrationTest.kt b/backend/app/src/test/kotlin/io/tolgee/automation/AutomationIntegrationTest.kt index 944b002564..0132e05cd0 100644 --- a/backend/app/src/test/kotlin/io/tolgee/automation/AutomationIntegrationTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/automation/AutomationIntegrationTest.kt @@ -44,7 +44,6 @@ import java.util.* @SpringBootTest @AutoConfigureMockMvc class AutomationIntegrationTest : ProjectAuthControllerTest("/v2/projects/") { - @MockBean @Autowired lateinit var contentDeliveryFileStorageProvider: ContentDeliveryFileStorageProvider @@ -164,11 +163,14 @@ class AutomationIntegrationTest : ProjectAuthControllerTest("/v2/projects/") { any(), any(), any>(), - any>() + any>(), ) } - private fun verifyWebhookExecuted(testData: WebhooksTestData, webhookTriggeringCallback: () -> Unit) { + private fun verifyWebhookExecuted( + testData: WebhooksTestData, + webhookTriggeringCallback: () -> Unit, + ) { val invocations = getWebhookRestTemplateInvocationCount() webhookTriggeringCallback() waitForNotThrowing { @@ -194,7 +196,10 @@ class AutomationIntegrationTest : ProjectAuthControllerTest("/v2/projects/") { private fun getWebhookRestTemplateInvocationCount() = Mockito.mockingDetails(webhookRestTemplate).invocations.count() - private fun verifyWebhookSignature(httpEntity: HttpEntity, secret: String) { + private fun verifyWebhookSignature( + httpEntity: HttpEntity, + secret: String, + ) { val signature = httpEntity.headers["Tolgee-Signature"] signature.assert.isNotNull verifyWebhookSignatureHeader( @@ -202,7 +207,7 @@ class AutomationIntegrationTest : ProjectAuthControllerTest("/v2/projects/") { signature!!.single(), secret, 300000, - currentDateProvider.date.time + currentDateProvider.date.time, ) } @@ -221,8 +226,8 @@ class AutomationIntegrationTest : ProjectAuthControllerTest("/v2/projects/") { "/translations", mapOf( "key" to "key", - "translations" to mapOf("en" to UUID.randomUUID().toString()) - ) + "translations" to mapOf("en" to UUID.randomUUID().toString()), + ), ).andIsOk } } diff --git a/backend/app/src/test/kotlin/io/tolgee/batch/AbstractBatchJobsGeneralTest.kt b/backend/app/src/test/kotlin/io/tolgee/batch/AbstractBatchJobsGeneralTest.kt index bbfccec892..70fcc5c74c 100644 --- a/backend/app/src/test/kotlin/io/tolgee/batch/AbstractBatchJobsGeneralTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/batch/AbstractBatchJobsGeneralTest.kt @@ -22,7 +22,6 @@ import kotlin.math.ceil @WebsocketTest abstract class AbstractBatchJobsGeneralTest : AbstractSpringTest(), Logging { - private lateinit var testData: BatchJobsTestData @Autowired diff --git a/backend/app/src/test/kotlin/io/tolgee/batch/BatchJobTestUtil.kt b/backend/app/src/test/kotlin/io/tolgee/batch/BatchJobTestUtil.kt index cfa6d901b0..a656dcd957 100644 --- a/backend/app/src/test/kotlin/io/tolgee/batch/BatchJobTestUtil.kt +++ b/backend/app/src/test/kotlin/io/tolgee/batch/BatchJobTestUtil.kt @@ -46,16 +46,15 @@ import kotlin.coroutines.CoroutineContext class BatchJobTestUtil( private val applicationContext: ApplicationContext, - private val testData: BatchJobsTestData + private val testData: BatchJobsTestData, ) : Logging { - lateinit var websocketHelper: WebsocketTestHelper fun assertPreTranslationProcessExecutedTimes(times: Int) { waitForNotThrowing(pollTime = 1000) { verify( preTranslationByTmChunkProcessor, - times(times) + times(times), ).process(any(), any(), any(), any()) } } @@ -112,7 +111,10 @@ class BatchJobTestUtil( } } - fun assertJobFailedWithMessage(job: BatchJob, message: Message) { + fun assertJobFailedWithMessage( + job: BatchJob, + message: Message, + ) { waitForNotThrowing { executeInNewTransaction(transactionManager) { batchJobService.getView(job.id).errorMessage.assert.isEqualTo(message) @@ -127,7 +129,7 @@ class BatchJobTestUtil( any(), argThat { this.containsAll((1L..10).toList()) }, any(), - any() + any(), ) } @@ -137,7 +139,10 @@ class BatchJobTestUtil( .process(any(), any(), any(), any()) } - fun verifyConstantRepeats(repeats: Int, timeout: Long = 2000) { + fun verifyConstantRepeats( + repeats: Int, + timeout: Long = 2000, + ) { repeat(repeats) { waitForNotThrowing { batchJobChunkExecutionQueue.find { it.executeAfter == currentDateProvider.date.time + timeout }.assert.isNotNull @@ -147,14 +152,15 @@ class BatchJobTestUtil( } fun makeDeleteKeysProcessorThrowDifferentGenericExceptions() { - val exceptions = (0..100).flatMap { - listOf( - IllegalStateException("a"), - NotFoundException(Message.THIRD_PARTY_AUTH_ERROR_MESSAGE), - RuntimeException("c"), - RuntimeException(IllegalStateException("d")), - ) - } + val exceptions = + (0..100).flatMap { + listOf( + IllegalStateException("a"), + NotFoundException(Message.THIRD_PARTY_AUTH_ERROR_MESSAGE), + RuntimeException("c"), + RuntimeException(IllegalStateException("d")), + ) + } doThrow(*exceptions.toTypedArray()) .whenever(deleteKeysChunkProcessor).process(any(), any(), any(), any()) @@ -179,7 +185,10 @@ class BatchJobTestUtil( } } - fun assertTotalExecutionsCount(job: BatchJob, count: Int) { + fun assertTotalExecutionsCount( + job: BatchJob, + count: Int, + ) { waitForNotThrowing(pollTime = 100, timeout = 2000) { entityManager.createQuery("""from BatchJobChunkExecution b where b.batchJob.id = :id""") .setParameter("id", job.id).resultList.assert.hasSize(count) @@ -201,7 +210,7 @@ class BatchJobTestUtil( any(), any(), any(), - any() + any(), ) } @@ -237,22 +246,23 @@ class BatchJobTestUtil( cause = OutOfCreditsException(OutOfCreditsException.Reason.OUT_OF_CREDITS), delayInMs = 100, increaseFactor = 10, - maxRetries = 3 - ) + maxRetries = 3, + ), ).whenever(preTranslationByTmChunkProcessor).process( any(), argThat { this.containsAll(throwingChunk) }, any(), - any() + any(), ) } fun initWebsocketHelper() { - websocketHelper = WebsocketTestHelper( - port, - jwtService.emitToken(testData.user.id), - testData.projectBuilder.self.id - ) + websocketHelper = + WebsocketTestHelper( + port, + jwtService.emitToken(testData.user.id), + testData.projectBuilder.self.id, + ) websocketHelper.listenForBatchJobProgress() } @@ -265,13 +275,14 @@ class BatchJobTestUtil( } fun makePreTranslateProcessorThrowOutOfCreditsTimes(times: Int) { - val exceptions = (1..times).map { _ -> - FailedDontRequeueException( - Message.OUT_OF_CREDITS, - cause = OutOfCreditsException(OutOfCreditsException.Reason.OUT_OF_CREDITS), - successfulTargets = listOf() - ) - } + val exceptions = + (1..times).map { _ -> + FailedDontRequeueException( + Message.OUT_OF_CREDITS, + cause = OutOfCreditsException(OutOfCreditsException.Reason.OUT_OF_CREDITS), + successfulTargets = listOf(), + ) + } doThrow(*exceptions.toTypedArray()).doAnswer { } .whenever(preTranslationByTmChunkProcessor) @@ -295,21 +306,20 @@ class BatchJobTestUtil( batchJobProjectLockingManager.getLockedForProject(testData.projectBuilder.self.id).assert.isEqualTo(0L) } - fun getExecutions( - jobIds: List, - ): Map> = + fun getExecutions(jobIds: List): Map> = entityManager.createQuery( """from BatchJobChunkExecution b left join fetch b.batchJob where b.batchJob.id in :ids""", - BatchJobChunkExecution::class.java + BatchJobChunkExecution::class.java, ) .setParameter("ids", jobIds).resultList.groupBy { it.batchJob.id } fun runChunkedJob(keyCount: Int): BatchJob { return executeInNewTransaction(transactionManager) { batchJobService.startJob( - request = PreTranslationByTmRequest().apply { - keyIds = (1L..keyCount).map { it } - }, + request = + PreTranslationByTmRequest().apply { + keyIds = (1L..keyCount).map { it } + }, project = testData.projectBuilder.self, author = testData.user, type = BatchJobType.PRE_TRANSLATE_BT_TM, @@ -320,9 +330,10 @@ class BatchJobTestUtil( fun runSingleChunkJob(keyCount: Int): BatchJob { return executeInNewTransaction(transactionManager) { batchJobService.startJob( - request = DeleteKeysRequest().apply { - keyIds = (1L..keyCount).map { it } - }, + request = + DeleteKeysRequest().apply { + keyIds = (1L..keyCount).map { it } + }, project = testData.projectBuilder.self, author = testData.user, type = BatchJobType.DELETE_KEYS, @@ -345,7 +356,7 @@ class BatchJobTestUtil( project = testData.projectBuilder.self, author = testData.user, type = BatchJobType.AUTOMATION, - debounceDuration = duration + debounceDuration = duration, ) } } @@ -389,7 +400,7 @@ class BatchJobTestUtil( // the project was unlocked before job2 acquired the job verify(batchJobProjectLockingManager, times(1)).unlockJobForProject( ArgumentMatchers.eq(job.project.id), - ArgumentMatchers.eq(job.id) + ArgumentMatchers.eq(job.id), ) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/batch/BatchJobsGeneralWithRedisTest.kt b/backend/app/src/test/kotlin/io/tolgee/batch/BatchJobsGeneralWithRedisTest.kt index ae0be7ca07..3b99968c7f 100644 --- a/backend/app/src/test/kotlin/io/tolgee/batch/BatchJobsGeneralWithRedisTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/batch/BatchJobsGeneralWithRedisTest.kt @@ -30,7 +30,7 @@ import org.springframework.test.context.ContextConfiguration "tolgee.websocket.use-redis=true", "spring.redis.port=56379", ], - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, ) @ContextConfiguration(initializers = [BatchJobsGeneralWithRedisTest.Companion.Initializer::class]) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) @@ -85,9 +85,9 @@ class BatchJobsGeneralWithRedisTest : AbstractBatchJobsGeneralTest() { eq(JOB_QUEUE_TOPIC), eq( jacksonObjectMapper().writeValueAsString( - JobQueueItemsEvent(listOf(peek), QueueEventType.REMOVE) - ) - ) + JobQueueItemsEvent(listOf(peek), QueueEventType.REMOVE), + ), + ), ) waitForNotThrowing(timeout = 2000) { batchJobChunkExecutionQueue.contains(peek).assert.isFalse() diff --git a/backend/app/src/test/kotlin/io/tolgee/batch/BatchJobsGeneralWithoutRedisTest.kt b/backend/app/src/test/kotlin/io/tolgee/batch/BatchJobsGeneralWithoutRedisTest.kt index f926debf45..b8988a5c9e 100644 --- a/backend/app/src/test/kotlin/io/tolgee/batch/BatchJobsGeneralWithoutRedisTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/batch/BatchJobsGeneralWithoutRedisTest.kt @@ -6,6 +6,6 @@ import org.springframework.boot.test.context.SpringBootTest properties = [ "tolgee.cache.enabled=true", ], - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, ) class BatchJobsGeneralWithoutRedisTest : AbstractBatchJobsGeneralTest() diff --git a/backend/app/src/test/kotlin/io/tolgee/batch/TolgeeTranslatorWithBatchTest.kt b/backend/app/src/test/kotlin/io/tolgee/batch/TolgeeTranslatorWithBatchTest.kt index 101972fdc9..d18f9e8463 100644 --- a/backend/app/src/test/kotlin/io/tolgee/batch/TolgeeTranslatorWithBatchTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/batch/TolgeeTranslatorWithBatchTest.kt @@ -58,12 +58,12 @@ class TolgeeTranslatorWithBatchTest { @Test fun `it correctly handles Too Many Requests`() { doThrow(getMockedTooManyRequestsError()).whenever( - restTemplate + restTemplate, ).exchange( argThat { this.contains("/api/openai/translate") }, argThat { this == HttpMethod.POST }, any>(), - any>() + any>(), ) assertThrows { @@ -75,8 +75,8 @@ class TolgeeTranslatorWithBatchTest { "cs", null, null, - true - ) + true, + ), ) }.retryAt.assert.isEqualTo(currentDateProvider.date.time + 100 * 1000) @@ -96,8 +96,8 @@ class TolgeeTranslatorWithBatchTest { "cs", null, null, - true - ) + true, + ), ) }.retryAt.assert.isEqualTo(currentDateProvider.date.time + 100 * 1000) @@ -115,10 +115,10 @@ class TolgeeTranslatorWithBatchTest { jacksonObjectMapper().writeValueAsBytes( mapOf( "error" to "Too Many Requests", - "retryAfter" to 100 - ) + "retryAfter" to 100, + ), ), - Charsets.UTF_8 + Charsets.UTF_8, ) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/cache/AbstractCacheTest.kt b/backend/app/src/test/kotlin/io/tolgee/cache/AbstractCacheTest.kt index d3d8dadef5..13019d129e 100644 --- a/backend/app/src/test/kotlin/io/tolgee/cache/AbstractCacheTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/cache/AbstractCacheTest.kt @@ -63,10 +63,11 @@ abstract class AbstractCacheTest : AbstractSpringTest() { lateinit var awsTranslationProvider: AwsMtValueProvider val unwrappedCacheManager - get() = TransactionAwareCacheManagerProxy::class.java.getDeclaredField("targetCacheManager").run { - this.isAccessible = true - this.get(cacheManager) as CacheManager - } + get() = + TransactionAwareCacheManagerProxy::class.java.getDeclaredField("targetCacheManager").run { + this.isAccessible = true + this.get(cacheManager) as CacheManager + } private final val paramsEnGoogle by lazy { mtServiceManager.getParams( @@ -76,7 +77,7 @@ abstract class AbstractCacheTest : AbstractSpringTest() { sourceLanguageTag = "en", targetLanguageTag = "de", serviceInfo = MtServiceInfo(MtServiceType.GOOGLE, null), - isBatch = false + isBatch = false, ) } @@ -92,10 +93,11 @@ abstract class AbstractCacheTest : AbstractSpringTest() { @Test fun `caches user account`() { - val user = UserAccount().apply { - name = "Account" - id = 10 - } + val user = + UserAccount().apply { + name = "Account" + id = 10 + } whenever(userAccountRepository.findActive(user.id)).then { user } userAccountService.findDto(user.id) Mockito.verify(userAccountRepository, times(1)).findActive(user.id) @@ -132,7 +134,7 @@ abstract class AbstractCacheTest : AbstractSpringTest() { val permission = Permission(id = 1) whenever( permissionRepository - .findOneByProjectIdAndUserIdAndOrganizationId(null, null, organizationId = 1) + .findOneByProjectIdAndUserIdAndOrganizationId(null, null, organizationId = 1), ).then { permission } permissionService.find(organizationId = 1) @@ -140,14 +142,14 @@ abstract class AbstractCacheTest : AbstractSpringTest() { .findOneByProjectIdAndUserIdAndOrganizationId( null, null, - organizationId = 1 + organizationId = 1, ) permissionService.find(organizationId = 1) Mockito.verify(permissionRepository, times(1)) .findOneByProjectIdAndUserIdAndOrganizationId( null, null, - 1 + 1, ) } diff --git a/backend/app/src/test/kotlin/io/tolgee/cache/CacheWithRedisTest.kt b/backend/app/src/test/kotlin/io/tolgee/cache/CacheWithRedisTest.kt index c0dfa30e8f..ec673709a1 100644 --- a/backend/app/src/test/kotlin/io/tolgee/cache/CacheWithRedisTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/cache/CacheWithRedisTest.kt @@ -19,8 +19,8 @@ import org.springframework.test.context.ContextConfiguration "tolgee.cache.use-redis=true", "tolgee.cache.enabled=true", "tolgee.internal.fake-mt-providers=false", - "tolgee.machine-translation.free-credits-amount=10000000" - ] + "tolgee.machine-translation.free-credits-amount=10000000", + ], ) @ContextConfiguration(initializers = [CacheWithRedisTest.Companion.Initializer::class]) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) diff --git a/backend/app/src/test/kotlin/io/tolgee/cache/CacheWithoutRedisTest.kt b/backend/app/src/test/kotlin/io/tolgee/cache/CacheWithoutRedisTest.kt index 8556d076ad..e83dcc1ee2 100644 --- a/backend/app/src/test/kotlin/io/tolgee/cache/CacheWithoutRedisTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/cache/CacheWithoutRedisTest.kt @@ -12,7 +12,7 @@ import org.springframework.test.annotation.DirtiesContext properties = [ "tolgee.cache.enabled=true", "tolgee.internal.fake-mt-providers=false", - ] + ], ) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) class CacheWithoutRedisTest : AbstractCacheTest() { diff --git a/backend/app/src/test/kotlin/io/tolgee/component/AesTest.kt b/backend/app/src/test/kotlin/io/tolgee/component/AesTest.kt index e6714e63cd..a19bb65ac0 100644 --- a/backend/app/src/test/kotlin/io/tolgee/component/AesTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/component/AesTest.kt @@ -9,32 +9,24 @@ import io.tolgee.testing.assertions.Assertions.assertThat import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest -import java.util.* @ContextRecreatingTest @SpringBootTest( properties = [ - "tolgee.authentication.jwtSecret=this_is_dummy_jwt_secret_azeazezaezaezaezaezzaezaezaeazeazezaeazezeaeazeazezaezaea" - ] + "tolgee.authentication.jwtSecret=this_is_dummy_jwt_secret_azeazezaezaezaezaezzaezaezaeazeazezaeazezeaeazea", + ], ) class AesTest { - @set:Autowired lateinit var aes: Aes @Test - fun encrypt() { - assertThat( - Base64.getEncoder() - .encode(aes.encrypt("hello".toByteArray(charset("UTF-8")))) - .toString(charset("UTF-8")) - ) - .isEqualTo("6E2puGrGLgbMG+V26rdnMA==") - } - - @Test - fun decrypt() { - val base64 = Base64.getDecoder().decode("6E2puGrGLgbMG+V26rdnMA==") - assertThat(aes.decrypt(base64).toString(charset("UTF-8"))).isEqualTo("hello") + fun `it works`() { + val encrypted1 = aes.encrypt("hello".toByteArray(charset("UTF-8"))) + val encrypted2 = aes.encrypt("hello hello".toByteArray(charset("UTF-8"))) + val decrypted2 = aes.decrypt(encrypted2).toString(charset("UTF-8")) + val decrypted1 = aes.decrypt(encrypted1).toString(charset("UTF-8")) + assertThat(decrypted1).isEqualTo("hello") + assertThat(decrypted2).isEqualTo("hello hello") } } diff --git a/backend/app/src/test/kotlin/io/tolgee/component/LanguageStatsListenerTest.kt b/backend/app/src/test/kotlin/io/tolgee/component/LanguageStatsListenerTest.kt index 6890b9a63e..ebfcca995f 100644 --- a/backend/app/src/test/kotlin/io/tolgee/component/LanguageStatsListenerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/component/LanguageStatsListenerTest.kt @@ -35,16 +35,17 @@ class LanguageStatsListenerTest : AbstractControllerTest() { testData.project, CreateKeyDto( name = "ho ho ho new key", - translations = mapOf("en" to "hello") - ) + translations = mapOf("en" to "hello"), + ), ) } // it's async so lets wait until it passes waitForNotThrowing(AssertionFailedError::class) { executeInNewTransaction(platformTransactionManager) { - val newDeutschStats = languageStatsService.getLanguageStats(projectId = testData.project.id) - .find { it.language.tag == "de" } + val newDeutschStats = + languageStatsService.getLanguageStats(projectId = testData.project.id) + .find { it.language.tag == "de" } assertThat(newDeutschStats!!.untranslatedWords - 1).isEqualTo(deutschStats?.untranslatedWords) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/component/bucket/AbstractTokenBucketManagerTest.kt b/backend/app/src/test/kotlin/io/tolgee/component/bucket/AbstractTokenBucketManagerTest.kt index 9a3292f40a..d20909bebd 100644 --- a/backend/app/src/test/kotlin/io/tolgee/component/bucket/AbstractTokenBucketManagerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/component/bucket/AbstractTokenBucketManagerTest.kt @@ -179,10 +179,14 @@ abstract class AbstractTokenBucketManagerTest { } } - private fun assertThrowsRetry(expectedRetryTime: Duration = Duration.ofMinutes(1), fn: () -> Unit) { - val refillAt = assertThrows { - fn() - }.refillAt + private fun assertThrowsRetry( + expectedRetryTime: Duration = Duration.ofMinutes(1), + fn: () -> Unit, + ) { + val refillAt = + assertThrows { + fn() + }.refillAt val expectedRefillAt = currentDateProvider.date.time + expectedRetryTime.toMillis() diff --git a/backend/app/src/test/kotlin/io/tolgee/component/bucket/TokenBucketManagerTestWithRedis.kt b/backend/app/src/test/kotlin/io/tolgee/component/bucket/TokenBucketManagerTestWithRedis.kt index bd8ecf0ceb..61b76cc512 100644 --- a/backend/app/src/test/kotlin/io/tolgee/component/bucket/TokenBucketManagerTestWithRedis.kt +++ b/backend/app/src/test/kotlin/io/tolgee/component/bucket/TokenBucketManagerTestWithRedis.kt @@ -14,7 +14,7 @@ import org.springframework.test.context.ContextConfiguration "tolgee.websocket.use-redis=true", "spring.redis.port=56379", ], - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, ) @ContextConfiguration(initializers = [TokenBucketManagerTestWithRedis.Companion.Initializer::class]) class TokenBucketManagerTestWithRedis : AbstractTokenBucketManagerTest() { diff --git a/backend/app/src/test/kotlin/io/tolgee/component/fileStorage/AbstractFileStorageServiceTest.kt b/backend/app/src/test/kotlin/io/tolgee/component/fileStorage/AbstractFileStorageServiceTest.kt index db94cea147..345b69c3cf 100644 --- a/backend/app/src/test/kotlin/io/tolgee/component/fileStorage/AbstractFileStorageServiceTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/component/fileStorage/AbstractFileStorageServiceTest.kt @@ -8,7 +8,6 @@ import io.tolgee.configuration.tolgee.TolgeeProperties import org.springframework.beans.factory.annotation.Autowired abstract class AbstractFileStorageServiceTest { - @set:Autowired lateinit var fileStorage: FileStorage diff --git a/backend/app/src/test/kotlin/io/tolgee/component/fileStorage/FileStorageFsTest.kt b/backend/app/src/test/kotlin/io/tolgee/component/fileStorage/FileStorageFsTest.kt index aac7e4a1b8..82363367f5 100644 --- a/backend/app/src/test/kotlin/io/tolgee/component/fileStorage/FileStorageFsTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/component/fileStorage/FileStorageFsTest.kt @@ -12,7 +12,6 @@ import java.io.File @SpringBootTest class FileStorageFsTest : AbstractFileStorageServiceTest() { - lateinit var file: File @BeforeEach diff --git a/backend/app/src/test/kotlin/io/tolgee/component/fileStorage/FileStorageS3Test.kt b/backend/app/src/test/kotlin/io/tolgee/component/fileStorage/FileStorageS3Test.kt index 8a170bbfdd..9c7f970e3a 100644 --- a/backend/app/src/test/kotlin/io/tolgee/component/fileStorage/FileStorageS3Test.kt +++ b/backend/app/src/test/kotlin/io/tolgee/component/fileStorage/FileStorageS3Test.kt @@ -29,7 +29,7 @@ import software.amazon.awssdk.services.s3.model.S3Exception "tolgee.file-storage.s3.signing-region=dummy_signing_region", "tolgee.file-storage.s3.bucket-name=$BUCKET_NAME", "tolgee.authentication.initial-password=hey password manager, please don't use the filesystem :3", - ] + ], ) @TestInstance(TestInstance.Lifecycle.PER_CLASS) class FileStorageS3Test : AbstractFileStorageServiceTest() { @@ -78,7 +78,7 @@ class FileStorageS3Test : AbstractFileStorageServiceTest() { fun testStoreFile() { fileStorage.storeFile(testFilePath, testFileContent.toByteArray(charset("UTF-8"))) assertThat( - s3.getObject { req -> req.bucket(BUCKET_NAME).key(testFilePath) }.readAllBytes() + s3.getObject { req -> req.bucket(BUCKET_NAME).key(testFilePath) }.readAllBytes(), ).isEqualTo(testFileContent.toByteArray()) } diff --git a/backend/app/src/test/kotlin/io/tolgee/controllers/AbstractApiKeyTest.kt b/backend/app/src/test/kotlin/io/tolgee/controllers/AbstractApiKeyTest.kt index 3631804777..34efe3130f 100644 --- a/backend/app/src/test/kotlin/io/tolgee/controllers/AbstractApiKeyTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/controllers/AbstractApiKeyTest.kt @@ -1,6 +1,6 @@ package io.tolgee.controllers -import io.tolgee.dtos.response.ApiKeyDTO.ApiKeyDTO +import io.tolgee.dtos.response.ApiKeyDTO import io.tolgee.fixtures.generateUniqueString import io.tolgee.model.enums.Scope import io.tolgee.testing.AbstractControllerTest @@ -28,6 +28,6 @@ abstract class AbstractApiKeyTest : AbstractControllerTest() { scopesSet = Scope.values().toSet() } val base = dbPopulator.createBase(generateUniqueString()) - return ApiKeyDTO.fromEntity(apiKeyService.create(base.userAccount, scopesSet, base.project)) + return io.tolgee.dtos.response.ApiKeyDTO.fromEntity(apiKeyService.create(base.userAccount, scopesSet, base.project)) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/controllers/DemoProjectTest.kt b/backend/app/src/test/kotlin/io/tolgee/controllers/DemoProjectTest.kt index e1acd446f1..86f74dadbd 100644 --- a/backend/app/src/test/kotlin/io/tolgee/controllers/DemoProjectTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/controllers/DemoProjectTest.kt @@ -13,30 +13,31 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock @AutoConfigureMockMvc class DemoProjectTest : AbstractControllerTest() { - @Test fun `creates demo project`() { val demoOrganization = "Oh my organization" - val dto = SignUpDto( - name = "Pavel Novak", - password = "aaaaaaaaa", - email = "aaaa@aaaa.com", - organizationName = demoOrganization - ) + val dto = + SignUpDto( + name = "Pavel Novak", + password = "aaaaaaaaa", + email = "aaaa@aaaa.com", + organizationName = demoOrganization, + ) performPost("/api/public/sign_up", dto).andIsOk - val project = executeInNewTransaction { - val organization = organizationRepository.findAllByName(demoOrganization).single() - val project = organization.projects.single() - assertThat(project.name).isEqualTo("Demo project") - val keyCount = DemoProjectData.translations["en"]!!.size - project.keys.assert.hasSize(keyCount) - val key = project.keys.find { it.name == "add-item-add-button" }!! - key.keyScreenshotReferences.assert.hasSize(1) - val screenshot = key.keyScreenshotReferences.single().screenshot - screenshot.keyScreenshotReferences.assert.hasSize(keyCount) - key.translations.assert.hasSize(3) - project - } + val project = + executeInNewTransaction { + val organization = organizationRepository.findAllByName(demoOrganization).single() + val project = organization.projects.single() + assertThat(project.name).isEqualTo("Demo project") + val keyCount = DemoProjectData.translations["en"]!!.size + project.keys.assert.hasSize(keyCount) + val key = project.keys.find { it.name == "add-item-add-button" }!! + key.keyScreenshotReferences.assert.hasSize(1) + val screenshot = key.keyScreenshotReferences.single().screenshot + screenshot.keyScreenshotReferences.assert.hasSize(keyCount) + key.translations.assert.hasSize(3) + project + } waitForNotThrowing { executeInNewTransaction { diff --git a/backend/app/src/test/kotlin/io/tolgee/controllers/ExportControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/controllers/ExportControllerTest.kt index 5a065948d2..7efd338fc9 100644 --- a/backend/app/src/test/kotlin/io/tolgee/controllers/ExportControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/controllers/ExportControllerTest.kt @@ -28,15 +28,16 @@ class ExportControllerTest : ProjectAuthControllerTest() { commitTransaction() projectSupplier = { base.project } userAccount = base.userAccount - val mvcResult = performProjectAuthGet("export/jsonZip") - .andIsOk.andDo { obj: MvcResult -> obj.getAsyncResult(60000) }.andReturn() + val mvcResult = + performProjectAuthGet("export/jsonZip") + .andIsOk.andDo { obj: MvcResult -> obj.getAsyncResult(60000) }.andReturn() mvcResult.response val fileSizes = parseZip(mvcResult.response.contentAsByteArray) project.languages.forEach( Consumer { l: Language -> val name = l.tag + ".json" Assertions.assertThat(fileSizes).containsKey(name) - } + }, ) } @@ -47,14 +48,15 @@ class ExportControllerTest : ProjectAuthControllerTest() { val base = dbPopulator.populate(generateUniqueString()) commitTransaction() projectSupplier = { base.project } - val mvcResult = performProjectAuthGet("export/jsonZip") - .andExpect(MockMvcResultMatchers.status().isOk).andDo { obj: MvcResult -> obj.asyncResult }.andReturn() + val mvcResult = + performProjectAuthGet("export/jsonZip") + .andExpect(MockMvcResultMatchers.status().isOk).andDo { obj: MvcResult -> obj.asyncResult }.andReturn() val fileSizes = parseZip(mvcResult.response.contentAsByteArray) project.languages.forEach( Consumer { l: Language -> val name = l.tag + ".json" Assertions.assertThat(fileSizes).containsKey(name) - } + }, ) } @@ -71,9 +73,10 @@ class ExportControllerTest : ProjectAuthControllerTest() { testDataService.saveTestData(testData.root) userAccount = testData.viewEnOnlyUser projectSupplier = { testData.project } - val result = performProjectAuthGet("export/jsonZip") - .andDo { obj: MvcResult -> obj.asyncResult } - .andReturn() + val result = + performProjectAuthGet("export/jsonZip") + .andDo { obj: MvcResult -> obj.asyncResult } + .andReturn() val fileSizes = parseZip(result.response.contentAsByteArray) Assertions.assertThat(fileSizes).containsOnlyKeys("en.json") } @@ -84,8 +87,8 @@ class ExportControllerTest : ProjectAuthControllerTest() { val result = HashMap() var nextEntry: ZipEntry? while (zipInputStream.nextEntry.also { - nextEntry = it - } != null + nextEntry = it + } != null ) { result[nextEntry!!.name] = nextEntry!!.size } diff --git a/backend/app/src/test/kotlin/io/tolgee/controllers/MarketingEmailingTest.kt b/backend/app/src/test/kotlin/io/tolgee/controllers/MarketingEmailingTest.kt index 4c9670d861..f251928dd9 100644 --- a/backend/app/src/test/kotlin/io/tolgee/controllers/MarketingEmailingTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/controllers/MarketingEmailingTest.kt @@ -34,7 +34,6 @@ import sibModel.UpdateContact @SpringBootTest @AutoConfigureMockMvc class MarketingEmailingTest : AuthorizedControllerTest() { - @Autowired lateinit var sendInBlueProperties: SendInBlueProperties @@ -61,11 +60,12 @@ class MarketingEmailingTest : AuthorizedControllerTest() { @BeforeAll fun initDto() { - updateRequestDto = UserUpdateRequestDto( - name = "New Name", - email = "newemail@test.com", - currentPassword = initialPassword - ) + updateRequestDto = + UserUpdateRequestDto( + name = "New Name", + email = "newemail@test.com", + currentPassword = initialPassword, + ) } @BeforeEach @@ -126,11 +126,12 @@ class MarketingEmailingTest : AuthorizedControllerTest() { fun `updates contact email when verified`() { tolgeeProperties.authentication.needsEmailVerification = true val user = dbPopulator.createUserIfNotExists(username = testMail, name = testName) - val updatedUser = executeInNewTransaction { - val updatedUser = userAccountService.get(user.id) - userAccountService.update(userAccountService.get(user.id), updateRequestDto) - updatedUser - } + val updatedUser = + executeInNewTransaction { + val updatedUser = userAccountService.get(user.id) + userAccountService.update(userAccountService.get(user.id), updateRequestDto) + updatedUser + } Thread.sleep(100) verify(contactsApi).updateContact(eq(testMail), any()) Mockito.clearInvocations(contactsApi) @@ -161,7 +162,10 @@ class MarketingEmailingTest : AuthorizedControllerTest() { Mockito.clearInvocations(contactsApi) } - private fun verifyCreateContactCalled(email: String = testMail, name: String = testName) { + private fun verifyCreateContactCalled( + email: String = testMail, + name: String = testName, + ) { Thread.sleep(100) verify(contactsApi).createContact(createContactArgumentCaptor.capture()) assertThat(createContactArgumentCaptor.value.email).isEqualTo(email) diff --git a/backend/app/src/test/kotlin/io/tolgee/controllers/PublicControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/controllers/PublicControllerTest.kt index cc8f1e56b4..b28bc94348 100644 --- a/backend/app/src/test/kotlin/io/tolgee/controllers/PublicControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/controllers/PublicControllerTest.kt @@ -30,7 +30,6 @@ import kotlin.properties.Delegates @AutoConfigureMockMvc class PublicControllerTest : AbstractControllerTest() { - private var canCreateOrganizations by Delegates.notNull() @BeforeEach @@ -50,12 +49,13 @@ class PublicControllerTest : @Test fun `creates organization`() { - val dto = SignUpDto( - name = "Pavel Novak", - password = "aaaaaaaaa", - email = "aaaa@aaaa.com", - organizationName = "Hello" - ) + val dto = + SignUpDto( + name = "Pavel Novak", + password = "aaaaaaaaa", + email = "aaaa@aaaa.com", + organizationName = "Hello", + ) performPost("/api/public/sign_up", dto).andIsOk assertThat(organizationRepository.findAllByName("Hello")).hasSize(1) } @@ -78,17 +78,18 @@ class PublicControllerTest : // hypothetically every endpoint might be triggered from SDK it["X-Tolgee-SDK-Type"] = "Unreal" it["X-Tolgee-SDK-Version"] = "1.0.0" - } + }, ).andIsOk var params: Map? = null waitForNotThrowing(timeout = 10000) { verify(postHog, times(1)).capture( - any(), eq("SIGN_UP"), + any(), + eq("SIGN_UP"), argThat { params = this true - } + }, ) } params!!["utm_hello"].assert.isEqualTo("hello") @@ -100,15 +101,17 @@ class PublicControllerTest : fun `doesn't create organization when invitation provided`() { val base = dbPopulator.createBase(generateUniqueString()) val project = base.project - val invitation = invitationService.create( - CreateProjectInvitationParams(project, ProjectPermissionType.EDIT) - ) - val dto = SignUpDto( - name = "Pavel Novak", - password = "aaaaaaaaa", - email = "aaaa@aaaa.com", - invitationCode = invitation.code - ) + val invitation = + invitationService.create( + CreateProjectInvitationParams(project, ProjectPermissionType.EDIT), + ) + val dto = + SignUpDto( + name = "Pavel Novak", + password = "aaaaaaaaa", + email = "aaaa@aaaa.com", + invitationCode = invitation.code, + ) performPost("/api/public/sign_up", dto).andIsOk assertThat(organizationRepository.findAllByName("Pavel Novak")).hasSize(0) } @@ -116,12 +119,13 @@ class PublicControllerTest : @Test fun `doesn't create orgs when disabled`() { tolgeeProperties.authentication.userCanCreateOrganizations = false - val dto = SignUpDto( - name = "Pavel Novak", - password = "aaaaaaaaa", - email = "aaaa@aaaa.com", - organizationName = "Jejda", - ) + val dto = + SignUpDto( + name = "Pavel Novak", + password = "aaaaaaaaa", + email = "aaaa@aaaa.com", + organizationName = "Jejda", + ) performPost("/api/public/sign_up", dto).andIsOk assertThat(organizationRepository.findAllByName("Jejda")).hasSize(0) } diff --git a/backend/app/src/test/kotlin/io/tolgee/controllers/internal/SqlControllerTest.kt b/backend/app/src/test/kotlin/io/tolgee/controllers/internal/SqlControllerTest.kt index b2596871ae..89f9746664 100644 --- a/backend/app/src/test/kotlin/io/tolgee/controllers/internal/SqlControllerTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/controllers/internal/SqlControllerTest.kt @@ -28,15 +28,17 @@ class SqlControllerTest : AbstractControllerTest(), Logging { @Test fun listEndpoints() { - val requestMappingHandlerMapping: RequestMappingHandlerMapping = applicationContext - .getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping::class.java) - val map: Map = requestMappingHandlerMapping - .handlerMethods + val requestMappingHandlerMapping: RequestMappingHandlerMapping = + applicationContext + .getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping::class.java) + val map: Map = + requestMappingHandlerMapping + .handlerMethods map.forEach { (key: RequestMappingInfo?, value: HandlerMethod?) -> logger.info( "{} {}", key, - value + value, ) } } @@ -45,11 +47,12 @@ class SqlControllerTest : AbstractControllerTest(), Logging { fun getList() { logger.info("Internal controller enabled: ${tolgeeProperties.internal.controllerEnabled}") dbPopulator.createBase("Test") - val parseResponseTo: List = mvc.perform( - post("/internal/sql/list") - .content("select * from user_account") - ) - .andExpect(status().isOk).andReturn().parseResponseTo() + val parseResponseTo: List = + mvc.perform( + post("/internal/sql/list") + .content("select * from user_account"), + ) + .andExpect(status().isOk).andReturn().parseResponseTo() assertThat(parseResponseTo).isNotEmpty } @@ -60,7 +63,7 @@ class SqlControllerTest : AbstractControllerTest(), Logging { val project = dbPopulator.createBase("Test").project mvc.perform( post("/internal/sql/execute") - .content("delete from permission") + .content("delete from permission"), ) .andExpect(status().isOk).andReturn() diff --git a/backend/app/src/test/kotlin/io/tolgee/dialects/postgres/CustomPostgreSQLDialectTest.kt b/backend/app/src/test/kotlin/io/tolgee/dialects/postgres/CustomPostgreSQLDialectTest.kt index e21846cb29..50e2bcba49 100644 --- a/backend/app/src/test/kotlin/io/tolgee/dialects/postgres/CustomPostgreSQLDialectTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/dialects/postgres/CustomPostgreSQLDialectTest.kt @@ -13,7 +13,6 @@ import org.springframework.transaction.annotation.Transactional @TestInstance(TestInstance.Lifecycle.PER_CLASS) @Transactional class CustomPostgreSQLDialectTest { - @Autowired lateinit var entityManager: EntityManager @@ -22,9 +21,10 @@ class CustomPostgreSQLDialectTest { // Hibernate queries doesn't work without FROM clause, so we have // to create a dummy entity to select from entityManager.persist(UserAccount(username = "aaa", password = "aaaa", name = "aaaaa")) - val query = entityManager.createQuery( - "select similarity('I am so funny!', 'You are so funny!') from UserAccount" - ) + val query = + entityManager.createQuery( + "select similarity('I am so funny!', 'You are so funny!') from UserAccount", + ) assertThat(query.resultList).first().isEqualTo(0.47619048f) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/initial_user_creation/CreateEnabledTest.kt b/backend/app/src/test/kotlin/io/tolgee/initialUserCreation/CreateEnabledTest.kt similarity index 97% rename from backend/app/src/test/kotlin/io/tolgee/initial_user_creation/CreateEnabledTest.kt rename to backend/app/src/test/kotlin/io/tolgee/initialUserCreation/CreateEnabledTest.kt index c79a2cfea1..a32380d481 100644 --- a/backend/app/src/test/kotlin/io/tolgee/initial_user_creation/CreateEnabledTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/initialUserCreation/CreateEnabledTest.kt @@ -2,7 +2,7 @@ * Copyright (c) 2020. Tolgee */ -package io.tolgee.initial_user_creation +package io.tolgee.initialUserCreation import io.tolgee.Application import io.tolgee.CleanDbBeforeClass @@ -30,8 +30,8 @@ import java.io.File properties = [ "tolgee.file-storage.fs-data-path=./build/create-enabled-test-data/", "tolgee.authentication.initial-username=johny", - "tolgee.internal.disable-initial-user-creation=false" - ] + "tolgee.internal.disable-initial-user-creation=false", + ], ) @TestInstance(TestInstance.Lifecycle.PER_CLASS) @Transactional diff --git a/backend/app/src/test/kotlin/io/tolgee/initial_user_creation/LegacyMigrationTest.kt b/backend/app/src/test/kotlin/io/tolgee/initialUserCreation/LegacyMigrationTest.kt similarity index 93% rename from backend/app/src/test/kotlin/io/tolgee/initial_user_creation/LegacyMigrationTest.kt rename to backend/app/src/test/kotlin/io/tolgee/initialUserCreation/LegacyMigrationTest.kt index d3df61a01d..25480726cf 100644 --- a/backend/app/src/test/kotlin/io/tolgee/initial_user_creation/LegacyMigrationTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/initialUserCreation/LegacyMigrationTest.kt @@ -2,7 +2,7 @@ * Copyright (c) 2020. Tolgee */ -package io.tolgee.initial_user_creation +package io.tolgee.initialUserCreation import io.tolgee.AbstractSpringTest import io.tolgee.Application @@ -16,7 +16,9 @@ import io.tolgee.repository.UserAccountRepository import io.tolgee.service.security.SecurityService import io.tolgee.testing.ContextRecreatingTest import io.tolgee.testing.assertions.Assertions.assertThat -import org.junit.jupiter.api.* +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.junit.jupiter.api.assertDoesNotThrow import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.transaction.annotation.Transactional @@ -26,8 +28,8 @@ import org.springframework.transaction.annotation.Transactional classes = [Application::class], properties = [ "tolgee.authentication.initial-username=johny", - "tolgee.internal.disable-initial-user-creation=false" - ] + "tolgee.internal.disable-initial-user-creation=false", + ], ) @TestInstance(TestInstance.Lifecycle.PER_CLASS) @Transactional diff --git a/backend/app/src/test/kotlin/io/tolgee/jobs/migration/allOrganizationOwner/AllOrganizationOwnerJobTest.kt b/backend/app/src/test/kotlin/io/tolgee/jobs/migration/allOrganizationOwner/AllOrganizationOwnerJobTest.kt index ba47fff5de..76edaa98b7 100644 --- a/backend/app/src/test/kotlin/io/tolgee/jobs/migration/allOrganizationOwner/AllOrganizationOwnerJobTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/jobs/migration/allOrganizationOwner/AllOrganizationOwnerJobTest.kt @@ -17,7 +17,6 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Qualifier class AllOrganizationOwnerJobTest : AbstractSpringTest() { - @Autowired @Qualifier("translationStatsJob") lateinit var translationStatsJob: Job @@ -40,20 +39,21 @@ class AllOrganizationOwnerJobTest : AbstractSpringTest() { @BeforeEach fun setup() { - val user = userAccountRepository.save( - UserAccount( - name = "User with 2 projects", - username = "user", - password = "pass" + val user = + userAccountRepository.save( + UserAccount( + name = "User with 2 projects", + username = "user", + password = "pass", + ), ) - ) project1 = projectRepository.save(Project(name = "Project").also { it.userOwner = user }) permissionRepository.save( Permission( user = user, project = project1, - type = ProjectPermissionType.MANAGE - ) + type = ProjectPermissionType.MANAGE, + ), ) val project2 = projectRepository.save(Project(name = "Project 2").also { it.userOwner = user }) @@ -61,17 +61,18 @@ class AllOrganizationOwnerJobTest : AbstractSpringTest() { Permission( user = user, project = project2, - type = ProjectPermissionType.MANAGE - ) + type = ProjectPermissionType.MANAGE, + ), ) - val user2 = userAccountRepository.save( - UserAccount( - name = "User with no role", - username = "user2", - password = "pass" + val user2 = + userAccountRepository.save( + UserAccount( + name = "User with no role", + username = "user2", + password = "pass", + ), ) - ) permissionService.grantFullAccessToProject(user2, project2) } @@ -112,8 +113,9 @@ class AllOrganizationOwnerJobTest : AbstractSpringTest() { fun `creates the organization for user with no organization membership`() { allOrganizationOwnerJobRunner.run() transactionTemplate.execute { - val createdOrganization = userAccountRepository.findByUsername("user2").get() - .organizationRoles.single().organization + val createdOrganization = + userAccountRepository.findByUsername("user2").get() + .organizationRoles.single().organization assertThat(createdOrganization?.name).isEqualTo("User with no role") } } diff --git a/backend/app/src/test/kotlin/io/tolgee/jobs/migration/translationStats/TranslationStatsJobTest.kt b/backend/app/src/test/kotlin/io/tolgee/jobs/migration/translationStats/TranslationStatsJobTest.kt index 3f7843926b..bd471211e3 100644 --- a/backend/app/src/test/kotlin/io/tolgee/jobs/migration/translationStats/TranslationStatsJobTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/jobs/migration/translationStats/TranslationStatsJobTest.kt @@ -1,96 +1,86 @@ -// package io.tolgee.jobs.migration.translationStats -// -// import io.tolgee.AbstractSpringTest -// import io.tolgee.development.testDataBuilder.data.TranslationsTestData -// import io.tolgee.repository.TranslationRepository -// import io.tolgee.testing.assertions.Assertions.assertThat -// import org.junit.jupiter.api.Test -// import org.springframework.batch.core.BatchStatus -// import org.springframework.beans.factory.annotation.Autowired -// import org.springframework.boot.test.context.SpringBootTest -// import org.springframework.test.context.transaction.TestTransaction -// import org.springframework.transaction.annotation.Transactional -// -// @SpringBootTest -// class TranslationStatsJobTest : AbstractSpringTest() { -// -// @Autowired -// lateinit var translationsStatsUpdateJobRunner: TranslationsStatsUpdateJobRunner -// -// @Autowired -// lateinit var translationRepository: TranslationRepository -// -// @Test -// @Transactional -// fun `it adds the stats`() { -// prepareData(10) -// -// val instance = translationsStatsUpdateJobRunner.run() -// -// assertStatsAdded() -// assertThat(instance?.status).isEqualTo(BatchStatus.COMPLETED) -// } -// -// @Test -// @Transactional -// fun `it does not run multiple times for same params`() { -// prepareData() -// -// // first - it really runs -// val instance = translationsStatsUpdateJobRunner.run() -// // nothing to migrate, no run -// val instance2 = translationsStatsUpdateJobRunner.run() -// -// assertThat(instance).isNotNull -// assertThat(instance2).isNull() -// } -// -// @Test -// @Transactional -// fun `it runs again when new translation without stats is created`() { -// val testData = prepareData() -// -// val instance = translationsStatsUpdateJobRunner.run() -// -// TestTransaction.start() -// val newTranslationId = translationService.setForKey(testData.aKey, mapOf("en" to "Hellooooo!"))["en"]!!.id -// entityManager -// .createNativeQuery( -// "update translation set word_count = null, character_count = null where id = $newTranslationId" -// ).executeUpdate() -// TestTransaction.flagForCommit() -// TestTransaction.end() -// -// val instance2 = translationsStatsUpdateJobRunner.run() -// assertThat(instance2?.id).isNotEqualTo(instance?.id) -// } -// -// private fun assertStatsAdded() { -// val translations = translationRepository.findAll().toMutableList() -// translations.sortBy { it.id } -// -// assertThat(translations) -// .allMatch { it.wordCount != null } -// .allMatch { it.characterCount != null } -// } -// -// private fun prepareData(keysToCreateCount: Long = 10): TranslationsTestData { -// val testData = TranslationsTestData() -// testData.generateLotOfData(keysToCreateCount) -// testDataService.saveTestData(testData.root) -// -// commitTransaction() -// -// entityManager -// .createNativeQuery("update translation set word_count = null, character_count = null") -// .executeUpdate() -// -// commitTransaction() -// -// val translations = translationRepository.findAll() -// assertThat(translations).allMatch { it.wordCount == null }.allMatch { it.characterCount == null } -// -// TestTransaction.end() -// return testData -// } -// } +package io.tolgee.jobs.migration.translationStats + +import io.tolgee.AbstractSpringTest +import io.tolgee.development.testDataBuilder.data.TranslationsTestData +import io.tolgee.repository.TranslationRepository +import io.tolgee.testing.assertions.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest + +@SpringBootTest +class TranslationStatsJobTest : AbstractSpringTest() { + @Autowired + lateinit var translationsStatsUpdateJobRunner: TranslationsStatsUpdateJobRunner + + @Autowired + lateinit var translationRepository: TranslationRepository + + @Test + fun `it adds the stats`() { + prepareData(10) + val instance = translationsStatsUpdateJobRunner.run() + assertStatsAdded() + assertThat(instance?.status).isEqualTo(BatchStatus.COMPLETED) + } + + @Test + fun `it does not run multiple times for same params`() { + prepareData() + + // first - it really runs + val instance = translationsStatsUpdateJobRunner.run() + // nothing to migrate, no run + val instance2 = translationsStatsUpdateJobRunner.run() + + assertThat(instance).isNotNull + assertThat(instance2).isNull() + } + + @Test + fun `it runs again when new translation without stats is created`() { + val testData = prepareData() + + val instance = translationsStatsUpdateJobRunner.run() + + executeInNewTransaction { + val newTranslationId = translationService.setForKey(testData.aKey, mapOf("en" to "Hellooooo!"))["en"]!!.id + entityManager + .createNativeQuery( + "update translation set word_count = null, character_count = null where id = $newTranslationId", + ).executeUpdate() + } + + val instance2 = translationsStatsUpdateJobRunner.run() + assertThat(instance2?.id).isNotEqualTo(instance?.id) + } + + private fun assertStatsAdded() { + val translations = translationRepository.findAll().toMutableList() + translations.sortBy { it.id } + + assertThat(translations) + .allMatch { it.wordCount != null } + .allMatch { it.characterCount != null } + } + + private fun prepareData(keysToCreateCount: Long = 10): TranslationsTestData { + return executeInNewTransaction { + val testData = TranslationsTestData() + testData.generateLotOfData(keysToCreateCount) + testDataService.saveTestData(testData.root) + + entityManager.flush() + entityManager.clear() + + entityManager + .createNativeQuery("update translation set word_count = null, character_count = null") + .executeUpdate() + + val translations = translationRepository.findAll() + assertThat(translations).allMatch { it.wordCount == null }.allMatch { it.characterCount == null } + testData + } + } +} diff --git a/backend/app/src/test/kotlin/io/tolgee/openapi/OpenApiTest.kt b/backend/app/src/test/kotlin/io/tolgee/openapi/OpenApiTest.kt index 3925f18e8f..f0ef5c4870 100644 --- a/backend/app/src/test/kotlin/io/tolgee/openapi/OpenApiTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/openapi/OpenApiTest.kt @@ -11,7 +11,6 @@ import org.springframework.boot.test.context.SpringBootTest @SpringBootTest @AutoConfigureMockMvc class OpenApiTest : AbstractControllerTest() { - @Test fun `accessible with api key is generated`() { performGet("/v3/api-docs/Accessible with API key").andIsOk.andAssertThatJson { diff --git a/backend/app/src/test/kotlin/io/tolgee/repository/ProjectRepositoryTest.kt b/backend/app/src/test/kotlin/io/tolgee/repository/ProjectRepositoryTest.kt index 6b7882e2e3..1d9ce53b4d 100644 --- a/backend/app/src/test/kotlin/io/tolgee/repository/ProjectRepositoryTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/repository/ProjectRepositoryTest.kt @@ -15,7 +15,6 @@ import org.springframework.transaction.annotation.Transactional @SpringBootTest @Transactional class ProjectRepositoryTest { - @Autowired lateinit var projectRepository: ProjectRepository diff --git a/backend/app/src/test/kotlin/io/tolgee/repository/UserAccountRepositoryTest.kt b/backend/app/src/test/kotlin/io/tolgee/repository/UserAccountRepositoryTest.kt index a16287a964..9848fe0031 100644 --- a/backend/app/src/test/kotlin/io/tolgee/repository/UserAccountRepositoryTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/repository/UserAccountRepositoryTest.kt @@ -13,7 +13,6 @@ import org.springframework.transaction.annotation.Transactional @SpringBootTest @Transactional class UserAccountRepositoryTest : AbstractSpringTest() { - @Autowired lateinit var userAccountRepository: UserAccountRepository diff --git a/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportFileIssueRepositoryTest.kt b/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportFileIssueRepositoryTest.kt index ef2ec3e7a4..e3239ff7db 100644 --- a/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportFileIssueRepositoryTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportFileIssueRepositoryTest.kt @@ -15,7 +15,6 @@ import org.springframework.transaction.annotation.Transactional @SpringBootTest(classes = [Application::class]) @Transactional class ImportFileIssueRepositoryTest : AbstractSpringTest() { - @Autowired lateinit var importFileIssueRepository: ImportFileIssueRepository @@ -24,9 +23,11 @@ class ImportFileIssueRepositoryTest : AbstractSpringTest() { val testData = ImportTestData() testData.addFileIssues() testDataService.saveTestData(testData.root) - val result = importFileIssueRepository.findAllByFileIdView( - testData.importBuilder.data.importFiles[0].self.id, PageRequest.of(0, 10) - ).content + val result = + importFileIssueRepository.findAllByFileIdView( + testData.importBuilder.data.importFiles[0].self.id, + PageRequest.of(0, 10), + ).content assertThat(result).hasSize(4) assertThat(result[0].params).hasSize(1) diff --git a/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportFileRepositoryTest.kt b/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportFileRepositoryTest.kt index 68b6f22ab9..b519f8160f 100644 --- a/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportFileRepositoryTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportFileRepositoryTest.kt @@ -14,7 +14,6 @@ import org.springframework.transaction.annotation.Transactional @Transactional @SpringBootTest class ImportFileRepositoryTest : AbstractSpringTest() { - @Autowired lateinit var importFileRepository: ImportFileRepository @@ -37,12 +36,13 @@ class ImportFileRepositoryTest : AbstractSpringTest() { fun `validates ImportFile entity`() { val import = createBaseImport() - val longName = StringBuilder().let { builder -> - repeat((1..2010).count()) { - builder.append("a") + val longName = + StringBuilder().let { builder -> + repeat((1..2010).count()) { + builder.append("a") + } + builder.toString() } - builder.toString() - } ImportFile(import = import, name = longName).let { assertThatExceptionOfType(ConstraintViolationException::class.java) diff --git a/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportLanguageRepositoryTest.kt b/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportLanguageRepositoryTest.kt index 8398c9fdae..3360386d61 100644 --- a/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportLanguageRepositoryTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportLanguageRepositoryTest.kt @@ -10,7 +10,6 @@ import org.springframework.data.domain.PageRequest @SpringBootTest class ImportLanguageRepositoryTest : AbstractSpringTest() { - @Autowired lateinit var importLanguageRepository: ImportLanguageRepository @@ -19,8 +18,9 @@ class ImportLanguageRepositoryTest : AbstractSpringTest() { val testData = ImportTestData() testData.addFileIssues() testDataService.saveTestData(testData.root) - val result = importLanguageRepository - .findImportLanguagesView(testData.import.id, PageRequest.of(0, 10)).content + val result = + importLanguageRepository + .findImportLanguagesView(testData.import.id, PageRequest.of(0, 10)).content assertThat(result).hasSize(3) assertThat(result[0].existingLanguageName).isEqualTo("English") diff --git a/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportRepositoryTest.kt b/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportRepositoryTest.kt index 188edb9daf..43133450f0 100644 --- a/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportRepositoryTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportRepositoryTest.kt @@ -11,7 +11,6 @@ import org.springframework.transaction.annotation.Transactional @SpringBootTest @Transactional class ImportRepositoryTest : AbstractSpringTest() { - @Autowired lateinit var importRepository: ImportRepository diff --git a/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportTranslationRepositoryTest.kt b/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportTranslationRepositoryTest.kt index e34eac756c..33b1f10778 100644 --- a/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportTranslationRepositoryTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/repository/dataImport/ImportTranslationRepositoryTest.kt @@ -10,7 +10,6 @@ import org.springframework.data.domain.PageRequest @SpringBootTest class ImportTranslationRepositoryTest : AbstractSpringTest() { - @Autowired lateinit var importTranslationRepository: ImportTranslationRepository @@ -19,8 +18,9 @@ class ImportTranslationRepositoryTest : AbstractSpringTest() { val importTestData = ImportTestData() testDataService.saveTestData(importTestData.root) - val result = importTranslationRepository - .findImportTranslationsView(importTestData.importEnglish.id, PageRequest.of(0, 10)) + val result = + importTranslationRepository + .findImportTranslationsView(importTestData.importEnglish.id, PageRequest.of(0, 10)) assertThat(result.content).hasSize(5) result.content[0].let { @@ -39,8 +39,9 @@ class ImportTranslationRepositoryTest : AbstractSpringTest() { val importTestData = ImportTestData() testDataService.saveTestData(importTestData.root) - val result = importTranslationRepository - .findImportTranslationsView(importTestData.importEnglish.id, PageRequest.of(0, 10), true) + val result = + importTranslationRepository + .findImportTranslationsView(importTestData.importEnglish.id, PageRequest.of(0, 10), true) assertThat(result.content).hasSize(3) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/security/DenyInternalTest.kt b/backend/app/src/test/kotlin/io/tolgee/security/DenyInternalTest.kt index 4eb3b8817a..f3a79d1cf7 100644 --- a/backend/app/src/test/kotlin/io/tolgee/security/DenyInternalTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/security/DenyInternalTest.kt @@ -13,20 +13,22 @@ class DenyInternalTest : AbstractControllerTest() { @Test fun getListFail() { dbPopulator.createBase("Test") - val response = mvc.perform( - MockMvcRequestBuilders.post("/internal/sql/list") - .content("select * from user_account") - ) - .andExpect(MockMvcResultMatchers.status().isForbidden) + val response = + mvc.perform( + MockMvcRequestBuilders.post("/internal/sql/list") + .content("select * from user_account"), + ) + .andExpect(MockMvcResultMatchers.status().isForbidden) } @Test fun setPropertyFail() { dbPopulator.createBase("Test") - val response = mvc.perform( - MockMvcRequestBuilders.post("/internal/properties") - .content("select * from user_account") - ) - .andExpect(MockMvcResultMatchers.status().isForbidden) + val response = + mvc.perform( + MockMvcRequestBuilders.post("/internal/properties") + .content("select * from user_account"), + ) + .andExpect(MockMvcResultMatchers.status().isForbidden) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/security/EmailVerificationTest.kt b/backend/app/src/test/kotlin/io/tolgee/security/EmailVerificationTest.kt index 7a801fc415..887ea06167 100644 --- a/backend/app/src/test/kotlin/io/tolgee/security/EmailVerificationTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/security/EmailVerificationTest.kt @@ -18,7 +18,6 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status import org.springframework.transaction.annotation.Transactional class EmailVerificationTest : AbstractControllerTest() { - @Autowired private lateinit var emailTestUtil: EmailTestUtil @@ -108,7 +107,7 @@ class EmailVerificationTest : AbstractControllerTest() { post("/api/public/sign_up") .content(mapper.writeValueAsString(signUpDto)) .accept(MediaType.ALL) - .contentType(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON), ) .andReturn() } diff --git a/backend/app/src/test/kotlin/io/tolgee/security/ProjectApiKeyAuthenticationTest.kt b/backend/app/src/test/kotlin/io/tolgee/security/ProjectApiKeyAuthenticationTest.kt index 5f16548a3a..30c7bc671b 100644 --- a/backend/app/src/test/kotlin/io/tolgee/security/ProjectApiKeyAuthenticationTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/security/ProjectApiKeyAuthenticationTest.kt @@ -34,8 +34,9 @@ class ProjectApiKeyAuthenticationTest : AbstractApiKeyTest() { @Test fun accessWithApiKey_failure() { - val mvcResult = mvc.perform(MockMvcRequestBuilders.get("/v2/projects/translations")) - .andExpect(MockMvcResultMatchers.status().isUnauthorized).andReturn() + val mvcResult = + mvc.perform(MockMvcRequestBuilders.get("/v2/projects/translations")) + .andExpect(MockMvcResultMatchers.status().isUnauthorized).andReturn() Assertions.assertThat(mvcResult).error() } @@ -60,8 +61,8 @@ class ProjectApiKeyAuthenticationTest : AbstractApiKeyTest() { PakAction( apiKey = apiKey.key, url = "/v2/projects", - expectedStatus = HttpStatus.FORBIDDEN - ) + expectedStatus = HttpStatus.FORBIDDEN, + ), ) mvc.perform(MockMvcRequestBuilders.get("/v2/projects")) .andIsUnauthorized @@ -78,7 +79,7 @@ class ProjectApiKeyAuthenticationTest : AbstractApiKeyTest() { "/v2/api-keys/current", HttpHeaders().apply { add(API_KEY_HEADER_NAME, "tgpak_" + testData.frantasKey.encodedKey) - } + }, ).andIsOk.andAssertThatJson { node("description").isNotNull } @@ -100,7 +101,7 @@ class ProjectApiKeyAuthenticationTest : AbstractApiKeyTest() { "/v2/api-keys/current", HttpHeaders().apply { add(API_KEY_HEADER_NAME, "tgpak_" + testData.expiredKey.encodedKey) - } + }, ).andIsUnauthorized } @@ -113,7 +114,7 @@ class ProjectApiKeyAuthenticationTest : AbstractApiKeyTest() { "/v2/projects/${testData.frantasProject.id}", HttpHeaders().apply { add(API_KEY_HEADER_NAME, "tgpak_" + testData.usersKey.encodedKey) - } + }, ).andIsForbidden } @@ -126,7 +127,7 @@ class ProjectApiKeyAuthenticationTest : AbstractApiKeyTest() { "/v2/projects/${testData.projectBuilder.self.id}", HttpHeaders().apply { add(API_KEY_HEADER_NAME, "tgpak_" + testData.usersKey.encodedKey) - } + }, ).andIsOk } @@ -139,7 +140,7 @@ class ProjectApiKeyAuthenticationTest : AbstractApiKeyTest() { "/v2/projects/${testData.frantasProject.id}", HttpHeaders().apply { add(API_KEY_HEADER_NAME, "tgpak_---aaajsjs") - } + }, ).andIsUnauthorized } @@ -153,7 +154,7 @@ class ProjectApiKeyAuthenticationTest : AbstractApiKeyTest() { null, HttpHeaders().apply { add(API_KEY_HEADER_NAME, "tgpak_" + testData.usersKeyFrantasProject.encodedKey) - } + }, ).andIsOk // Revoke user permissions @@ -163,7 +164,7 @@ class ProjectApiKeyAuthenticationTest : AbstractApiKeyTest() { null, HttpHeaders().apply { add("Authorization", "Bearer $tokenFrantisek") - } + }, ).andIsOk // Test if PAK is no longer able to set state @@ -172,7 +173,7 @@ class ProjectApiKeyAuthenticationTest : AbstractApiKeyTest() { null, HttpHeaders().apply { add(API_KEY_HEADER_NAME, "tgpak_" + testData.usersKeyFrantasProject.encodedKey) - } + }, ).andIsForbidden } } diff --git a/backend/app/src/test/kotlin/io/tolgee/security/ServerAdminFilterTest.kt b/backend/app/src/test/kotlin/io/tolgee/security/ServerAdminFilterTest.kt index bcac95fce8..9683be0eb7 100644 --- a/backend/app/src/test/kotlin/io/tolgee/security/ServerAdminFilterTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/security/ServerAdminFilterTest.kt @@ -17,13 +17,14 @@ class ServerAdminFilterTest : AuthorizedControllerTest() { @Test fun allowsAccessToServerAdmin() { - val serverAdmin = userAccountService.createUser( - UserAccount( - username = "serverAdmin", - password = "admin", - role = UserAccount.Role.ADMIN + val serverAdmin = + userAccountService.createUser( + UserAccount( + username = "serverAdmin", + password = "admin", + role = UserAccount.Role.ADMIN, + ), ) - ) loginAsUser(serverAdmin) performAuthGet("/v2/administration/organizations").andIsOk } diff --git a/backend/app/src/test/kotlin/io/tolgee/security/rateLimits/RateLimitsTest.kt b/backend/app/src/test/kotlin/io/tolgee/security/rateLimits/RateLimitsTest.kt index aa6e22d12b..459570b090 100644 --- a/backend/app/src/test/kotlin/io/tolgee/security/rateLimits/RateLimitsTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/security/rateLimits/RateLimitsTest.kt @@ -20,7 +20,7 @@ import org.springframework.boot.test.context.SpringBootTest "tolgee.rate-limits.ip-request-window=10000", "tolgee.rate-limits.user-request-limit=15", "tolgee.rate-limits.user-request-window=10000", - ] + ], ) class RateLimitsTest : AuthorizedControllerTest() { @BeforeEach diff --git a/backend/app/src/test/kotlin/io/tolgee/security/rateLimits/RedisRateLimitsTest.kt b/backend/app/src/test/kotlin/io/tolgee/security/rateLimits/RedisRateLimitsTest.kt index 41010086fe..4c0517bc5d 100644 --- a/backend/app/src/test/kotlin/io/tolgee/security/rateLimits/RedisRateLimitsTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/security/rateLimits/RedisRateLimitsTest.kt @@ -25,7 +25,7 @@ import org.springframework.test.context.ContextConfiguration "spring.redis.port=56379", "tolgee.rate-limits.ip-request-limit=2", "tolgee.rate-limits.ip-request-window=10000", - ] + ], ) @ContextConfiguration(initializers = [RedisRateLimitsTest.Companion.Initializer::class]) @TestInstance(TestInstance.Lifecycle.PER_CLASS) diff --git a/backend/app/src/test/kotlin/io/tolgee/service/BigMetaServiceTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/BigMetaServiceTest.kt index f10ac63daf..b0cdc4d757 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/BigMetaServiceTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/BigMetaServiceTest.kt @@ -12,7 +12,6 @@ import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired class BigMetaServiceTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: BigMetaTestData @Autowired @@ -36,16 +35,17 @@ class BigMetaServiceTest : ProjectAuthControllerTest("/v2/projects/") { performProjectAuthPost( "big-meta", mapOf( - "relatedKeysInOrder" to listOf( - mapOf( - "keyName" to "key" - ), - mapOf( - "namespace" to "yep", - "keyName" to "key" + "relatedKeysInOrder" to + listOf( + mapOf( + "keyName" to "key", + ), + mapOf( + "namespace" to "yep", + "keyName" to "key", + ), ), - ) - ) + ), ).andIsOk bigMetaService.findExistingKeysDistancesDtosByIds(listOf(testData.yepKey.id)).assert.hasSize(1) diff --git a/backend/app/src/test/kotlin/io/tolgee/service/DbPopulatorTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/DbPopulatorTest.kt index a7392318aa..934ab3e012 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/DbPopulatorTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/DbPopulatorTest.kt @@ -17,7 +17,6 @@ import org.springframework.transaction.annotation.Transactional @SpringBootTest class DbPopulatorTest : AbstractTransactionalTest() { - @Autowired lateinit var populator: DbPopulatorReal @@ -38,8 +37,9 @@ class DbPopulatorTest : AbstractTransactionalTest() { @BeforeEach fun setup() { populator.autoPopulate() - userAccount = userAccountRepository.findByUsername(tolgeeProperties.authentication.initialUsername) - .orElseThrow { NotFoundException() } + userAccount = + userAccountRepository.findByUsername(tolgeeProperties.authentication.initialUsername) + .orElseThrow { NotFoundException() } } @Test diff --git a/backend/app/src/test/kotlin/io/tolgee/service/ExportServiceTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/ExportServiceTest.kt index 9c4e091822..1d2c81277f 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/ExportServiceTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/ExportServiceTest.kt @@ -124,6 +124,7 @@ class ExportServiceTest : AbstractSpringTest() { assertThat(result).hasSize(5) assertThat(result.map { it.state }).allMatch { it == TranslationState.REVIEWED } } + @Test fun `filters export data by namespace`() { val testData = NamespacesTestData() diff --git a/backend/app/src/test/kotlin/io/tolgee/service/ImageUploadServiceTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/ImageUploadServiceTest.kt index fe645d9dda..48deed53df 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/ImageUploadServiceTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/ImageUploadServiceTest.kt @@ -41,15 +41,15 @@ class ImageUploadServiceTest : AbstractSpringTest() { Date.from( Instant.now() .plus(2, ChronoUnit.HOURS) - .minus(500, ChronoUnit.MILLIS) - ) + .minus(500, ChronoUnit.MILLIS), + ), ) imageUploadService.cleanOldImages() val after = imageUploadService.find(listOf(storedNewer.id, storedOlder.id)) assertThat(after).hasSize(1) assertThrows { fileStorage.readFile( - UPLOADED_IMAGES_STORAGE_FOLDER_NAME + "/" + storedOlder.filenameWithExtension + UPLOADED_IMAGES_STORAGE_FOLDER_NAME + "/" + storedOlder.filenameWithExtension, ) } assertThat(after[0].id).isEqualTo(storedNewer.id) diff --git a/backend/app/src/test/kotlin/io/tolgee/service/LanguageDeletePermissionTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/LanguageDeletePermissionTest.kt index b769c6b4df..b0d969426b 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/LanguageDeletePermissionTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/LanguageDeletePermissionTest.kt @@ -19,7 +19,6 @@ import org.springframework.transaction.annotation.Transactional @SpringBootTest class LanguageDeletePermissionTest : AbstractSpringTest() { - lateinit var testData: LanguagePermissionsTestData @BeforeEach @@ -110,7 +109,10 @@ class LanguageDeletePermissionTest : AbstractSpringTest() { } } - private fun checkUser(userAccount: UserAccount, checkFn: ProjectPermissionData.() -> Unit) { + private fun checkUser( + userAccount: UserAccount, + checkFn: ProjectPermissionData.() -> Unit, + ) { val data = permissionService.getProjectPermissionData(testData.project.id, userAccount.id) checkFn(data) } diff --git a/backend/app/src/test/kotlin/io/tolgee/service/OrganizationServiceTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/OrganizationServiceTest.kt index 725dce50a9..1da8448329 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/OrganizationServiceTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/OrganizationServiceTest.kt @@ -8,7 +8,6 @@ import org.springframework.transaction.annotation.Transactional @Transactional class OrganizationServiceTest : AbstractSpringTest() { - @Test fun `deletes organization with preferences`() { val testData = OrganizationTestData() diff --git a/backend/app/src/test/kotlin/io/tolgee/service/ProjectStatsServiceTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/ProjectStatsServiceTest.kt index 2c3cae6eab..b0e7ae4a67 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/ProjectStatsServiceTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/ProjectStatsServiceTest.kt @@ -8,7 +8,6 @@ import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired internal class ProjectStatsServiceTest : AbstractSpringTest() { - @Autowired lateinit var projectStatsService: ProjectStatsService diff --git a/backend/app/src/test/kotlin/io/tolgee/service/SoftDeleteTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/SoftDeleteTest.kt index c8c2368ec9..6d5fb84cce 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/SoftDeleteTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/SoftDeleteTest.kt @@ -7,7 +7,6 @@ import org.junit.jupiter.api.Test import org.springframework.data.domain.Pageable class SoftDeleteTest : AbstractSpringTest() { - @Test fun `project is soft deleted`() { val testData = BaseTestData() @@ -17,9 +16,10 @@ class SoftDeleteTest : AbstractSpringTest() { executeInNewTransaction { projectService.deleteProject(testData.projectBuilder.self.id) } - val result = entityManager.createNativeQuery("select deleted_at from project where id = :id") - .setParameter("id", testData.projectBuilder.self.id) - .singleResult + val result = + entityManager.createNativeQuery("select deleted_at from project where id = :id") + .setParameter("id", testData.projectBuilder.self.id) + .singleResult result.assert.isNotNull } @@ -41,7 +41,7 @@ class SoftDeleteTest : AbstractSpringTest() { pageable = Pageable.ofSize(100), search = null, organizationId = testData.projectBuilder.self.organizationOwner.id, - userAccountId = testData.user.id + userAccountId = testData.user.id, ).assert.isEmpty() } } diff --git a/backend/app/src/test/kotlin/io/tolgee/service/TelemetryServiceTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/TelemetryServiceTest.kt index e88d755fb0..ba4b2dab34 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/TelemetryServiceTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/TelemetryServiceTest.kt @@ -25,11 +25,10 @@ import org.springframework.web.client.RestTemplate @SpringBootTest( properties = [ "tolgee.telemetry.report-period-ms=200", - "tolgee.telemetry.enabled=false" - ] + "tolgee.telemetry.enabled=false", + ], ) class TelemetryServiceTest : AbstractSpringTest() { - @MockBean @Autowired lateinit var restTemplate: RestTemplate @@ -62,17 +61,18 @@ class TelemetryServiceTest : AbstractSpringTest() { @Test fun `reports when enabled`() { telemetryProperties.enabled = true - val testData = BaseTestData().apply { - this.root.addProject { name = "bbbb" }.build { - val en = addEnglish() - addKey("a") { - addTranslation { - language = en.self - text = "Hello" + val testData = + BaseTestData().apply { + this.root.addProject { name = "bbbb" }.build { + val en = addEnglish() + addKey("a") { + addTranslation { + language = en.self + text = "Hello" + } } } } - } testDataService.saveTestData(testData.root) mockHttpRequest(restTemplate) { whenReq { diff --git a/backend/app/src/test/kotlin/io/tolgee/service/TranslationServiceTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/TranslationServiceTest.kt index ba77bdc99a..03bb64f652 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/TranslationServiceTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/TranslationServiceTest.kt @@ -12,17 +12,17 @@ import java.util.* @SpringBootTest @Transactional class TranslationServiceTest : AbstractSpringTest() { - @Transactional @Test fun getTranslations() { val id = dbPopulator.populate("App").project.id - val data = translationService.getTranslations( - languageTags = HashSet(Arrays.asList("en", "de")), - namespace = null, - projectId = id, - structureDelimiter = '.' - ) + val data = + translationService.getTranslations( + languageTags = HashSet(Arrays.asList("en", "de")), + namespace = null, + projectId = id, + structureDelimiter = '.', + ) assertThat(data["en"]).isInstanceOf(MutableMap::class.java) } @@ -33,26 +33,28 @@ class TranslationServiceTest : AbstractSpringTest() { keyService.create(project, CreateKeyDto("folder.folder", null, mapOf("en" to "Ha"))) keyService.create(project, CreateKeyDto("folder.folder.translation", null, mapOf("en" to "Ha"))) - val viewData = translationService.getTranslations( - languageTags = HashSet(Arrays.asList("en", "de")), - namespace = null, - projectId = project.id, - structureDelimiter = '.' - ) + val viewData = + translationService.getTranslations( + languageTags = HashSet(Arrays.asList("en", "de")), + namespace = null, + projectId = project.id, + structureDelimiter = '.', + ) @Suppress("UNCHECKED_CAST") assertThat(viewData["en"] as Map).containsKey("folder.folder.translation") } @Test fun `adds stats on translation save and update`() { - val testData = executeInNewTransaction { - val testData = TranslationsTestData() - testDataService.saveTestData(testData.root) - val translation = testData.aKeyGermanTranslation - assertThat(translation.wordCount).isEqualTo(2) - assertThat(translation.characterCount).isEqualTo(translation.text!!.length) - testData - } + val testData = + executeInNewTransaction { + val testData = TranslationsTestData() + testDataService.saveTestData(testData.root) + val translation = testData.aKeyGermanTranslation + assertThat(translation.wordCount).isEqualTo(2) + assertThat(translation.characterCount).isEqualTo(translation.text!!.length) + testData + } executeInNewTransaction { val translation = translationService.get(testData.aKeyGermanTranslation.id) translation.text = "My dog is cool!" diff --git a/backend/app/src/test/kotlin/io/tolgee/service/dataImport/ImportServiceTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/dataImport/ImportServiceTest.kt index 8fd91800cc..59f9e8cc0c 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/dataImport/ImportServiceTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/dataImport/ImportServiceTest.kt @@ -49,12 +49,13 @@ class ImportServiceTest : AbstractSpringTest() { @Test fun `deletes import language`() { - val testData = executeInNewTransaction { - val testData = ImportTestData() - testDataService.saveTestData(testData.root) - assertThat(importService.findLanguage(testData.importEnglish.id)).isNotNull - testData - } + val testData = + executeInNewTransaction { + val testData = ImportTestData() + testDataService.saveTestData(testData.root) + assertThat(importService.findLanguage(testData.importEnglish.id)).isNotNull + testData + } executeInNewTransaction { importService.findLanguage(testData.importEnglish.id)?.let { importService.deleteLanguage(it) @@ -115,16 +116,18 @@ class ImportServiceTest : AbstractSpringTest() { @Test fun `imports namespaces and merges same keys from multiple files`() { - val testData = executeInNewTransaction { - val testData = ImportNamespacesTestData() - testDataService.saveTestData(testData.root) - SecurityContextHolder.getContext().authentication = TolgeeAuthentication( - null, - UserAccountDto.fromEntity(testData.userAccount), - TolgeeAuthenticationDetails(false) - ) - testData - } + val testData = + executeInNewTransaction { + val testData = ImportNamespacesTestData() + testDataService.saveTestData(testData.root) + SecurityContextHolder.getContext().authentication = + TolgeeAuthentication( + null, + UserAccountDto.fromEntity(testData.userAccount), + TolgeeAuthenticationDetails(false), + ) + testData + } executeInNewTransaction { permissionService.find(testData.project.id, testData.userAccount.id) val import = importService.get(testData.import.id) diff --git a/backend/app/src/test/kotlin/io/tolgee/service/dataImport/StoredDataImporterTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/dataImport/StoredDataImporterTest.kt index e398543dce..e7318f42d2 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/dataImport/StoredDataImporterTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/dataImport/StoredDataImporterTest.kt @@ -23,18 +23,20 @@ class StoredDataImporterTest : AbstractSpringTest() { @BeforeEach fun setup() { importTestData = ImportTestData() - storedDataImporter = StoredDataImporter( - applicationContext, - importTestData.import, - ) + storedDataImporter = + StoredDataImporter( + applicationContext, + importTestData.import, + ) } fun login() { - SecurityContextHolder.getContext().authentication = TolgeeAuthentication( - null, - UserAccountDto.fromEntity(importTestData.userAccount), - TolgeeAuthenticationDetails(false) - ) + SecurityContextHolder.getContext().authentication = + TolgeeAuthentication( + null, + UserAccountDto.fromEntity(importTestData.userAccount), + TolgeeAuthenticationDetails(false), + ) } @Test @@ -85,11 +87,12 @@ class StoredDataImporterTest : AbstractSpringTest() { @Test fun `it force replaces translations`() { - storedDataImporter = StoredDataImporter( - applicationContext!!, - importTestData.import, - ForceMode.OVERRIDE, - ) + storedDataImporter = + StoredDataImporter( + applicationContext!!, + importTestData.import, + ForceMode.OVERRIDE, + ) testDataService.saveTestData(importTestData.root) login() storedDataImporter.doImport() @@ -104,11 +107,12 @@ class StoredDataImporterTest : AbstractSpringTest() { fun `it imports metadata`() { importTestData.addKeyMetadata() testDataService.saveTestData(importTestData.root) - storedDataImporter = StoredDataImporter( - applicationContext, - importTestData.import, - ForceMode.OVERRIDE, - ) + storedDataImporter = + StoredDataImporter( + applicationContext, + importTestData.import, + ForceMode.OVERRIDE, + ) login() storedDataImporter.doImport() entityManager.flush() @@ -132,11 +136,12 @@ class StoredDataImporterTest : AbstractSpringTest() { fun `it force keeps translations`() { importTestData.translationWithConflict.override = true importTestData.translationWithConflict.resolve() - storedDataImporter = StoredDataImporter( - applicationContext, - importTestData.import, - ForceMode.KEEP, - ) + storedDataImporter = + StoredDataImporter( + applicationContext, + importTestData.import, + ForceMode.KEEP, + ) testDataService.saveTestData(importTestData.root) login() diff --git a/backend/app/src/test/kotlin/io/tolgee/service/export/exporters/JsonFileExporterTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/export/exporters/JsonFileExporterTest.kt index 5a52278dbb..e65f615a48 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/export/exporters/JsonFileExporterTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/export/exporters/JsonFileExporterTest.kt @@ -12,15 +12,15 @@ import org.junit.jupiter.api.Test import java.io.InputStream class JsonFileExporterTest { - @Suppress("UNCHECKED_CAST") @Test fun `it scopes and handles collisions`() { val data = generateTranslationsForKeys(listOf("a.a.a.a", "a.a", "a.a.a", "a.b.b", "a.c.c", "b", "b.b")) val exported = JsonFileExporter(data, ExportParams()).produceFiles() val json = exported.getFileTextContent("en.json") - val parsed = jacksonObjectMapper() - .readValue>(json) + val parsed = + jacksonObjectMapper() + .readValue>(json) val a = (parsed["a"] as Map) val aa = a["a"] @@ -40,8 +40,9 @@ class JsonFileExporterTest { val data = generateTranslationsForKeys(listOf(".a")) val exported = JsonFileExporter(data, ExportParams()).produceFiles() val json = exported.getFileTextContent("en.json") - val parsed = jacksonObjectMapper() - .readValue>(json) + val parsed = + jacksonObjectMapper() + .readValue>(json) val map = (parsed[""] as Map) val a = map["a"] @@ -52,10 +53,11 @@ class JsonFileExporterTest { @Test fun `it scopes by namespaces`() { val data = generateTranslationsForKeys(listOf("a:a.a", "a", "a:a", "a:b.a")) - val exported = JsonFileExporter( - data, - ExportParams().apply {} - ).produceFiles() + val exported = + JsonFileExporter( + data, + ExportParams().apply {}, + ).produceFiles() val ajson = exported.getFileTextContent("en.json") assertThatJson(ajson) { @@ -74,10 +76,11 @@ class JsonFileExporterTest { fun `it returns result in the same order as it comes from DB`() { val keys = listOf("a", "b", "c", "d", "e", "f") val data = generateTranslationsForKeys(keys) - val exported = JsonFileExporter( - data, - ExportParams() - ).produceFiles() + val exported = + JsonFileExporter( + data, + ExportParams(), + ).produceFiles() val parsed: LinkedHashMap = exported.parseFileContent("en.json") assertThat(parsed.keys.toList()).isEqualTo(keys) } @@ -87,10 +90,11 @@ class JsonFileExporterTest { fun `it is formatted`() { val keys = listOf("a", "b") val data = generateTranslationsForKeys(keys) - val exported = JsonFileExporter( - data, - ExportParams() - ).produceFiles() + val exported = + JsonFileExporter( + data, + ExportParams(), + ).produceFiles() assertThat(exported.getFileTextContent("en.json")).contains("\n").contains(" ") } diff --git a/backend/app/src/test/kotlin/io/tolgee/service/export/exporters/XliffFileExporterTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/export/exporters/XliffFileExporterTest.kt index 8f3bf20de6..2942f4061a 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/export/exporters/XliffFileExporterTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/export/exporters/XliffFileExporterTest.kt @@ -27,7 +27,6 @@ import javax.xml.xpath.XPathConstants import javax.xml.xpath.XPathFactory class XliffFileExporterTest { - @Test fun `exports translations`() { val translations = getBaseTranslations() @@ -35,12 +34,13 @@ class XliffFileExporterTest { val params = ExportParams() val baseProvider = { translations.filter { it.languageTag == "en" } } - val files = XliffFileExporter( - translations, - exportParams = params, - baseTranslationsProvider = baseProvider, - baseLanguage = Language().apply { tag = "en" } - ).produceFiles() + val files = + XliffFileExporter( + translations, + exportParams = params, + baseTranslationsProvider = baseProvider, + baseLanguage = Language().apply { tag = "en" }, + ).produceFiles() assertThat(files).hasSize(2) var fileContent = files["de.xlf"]!!.bufferedReader().readText() @@ -75,12 +75,13 @@ class XliffFileExporterTest { val params = ExportParams() val baseProvider = { translations.filter { it.languageTag == "en" } } - val files = XliffFileExporter( - translations, - exportParams = params, - baseTranslationsProvider = baseProvider, - baseLanguage = Language().apply { tag = "en" } - ).produceFiles() + val files = + XliffFileExporter( + translations, + exportParams = params, + baseTranslationsProvider = baseProvider, + baseLanguage = Language().apply { tag = "en" }, + ).produceFiles() assertThat(files).hasSize(2) val fileContent = files["de.xlf"]!!.bufferedReader().readText() @@ -93,27 +94,33 @@ class XliffFileExporterTest { private fun getHtmlTranslations(): List { val key = ExportKeyView(1, "html_key") - val validHtmlTranslation = ExportTranslationView( - 1, - "

Sweat jesus, this is HTML!

", - TranslationState.TRANSLATED, - key, - "en" - ) - val invalidHtmlTranslation = ExportTranslationView( - 1, - "Sweat jesus, this is invalid < HTML!", - TranslationState.TRANSLATED, - key, - "de" - ) + val validHtmlTranslation = + ExportTranslationView( + 1, + "

Sweat jesus, this is HTML!

", + TranslationState.TRANSLATED, + key, + "en", + ) + val invalidHtmlTranslation = + ExportTranslationView( + 1, + "Sweat jesus, this is invalid < HTML!", + TranslationState.TRANSLATED, + key, + "de", + ) key.translations["en"] = validHtmlTranslation key.translations["de"] = invalidHtmlTranslation val translations = listOf(validHtmlTranslation, invalidHtmlTranslation) return translations } - private fun assertHasTransUnitAndReturn(text: String, sourceLanguage: String, targetLanguage: String): Element { + private fun assertHasTransUnitAndReturn( + text: String, + sourceLanguage: String, + targetLanguage: String, + ): Element { val document = text.parseToDocument() val docFiles = document.selectNodes("//file") assertThat(docFiles).hasSize(1) @@ -157,25 +164,27 @@ class XliffFileExporterTest { val params = ExportParams() val baseProvider = { translations.filter { it.languageTag == "en" } } - val files = XliffFileExporter( - translations, - exportParams = params, - baseTranslationsProvider = baseProvider, - baseLanguage = Language().apply { tag = "en" } - ).produceFiles() + val files = + XliffFileExporter( + translations, + exportParams = params, + baseTranslationsProvider = baseProvider, + baseLanguage = Language().apply { tag = "en" }, + ).produceFiles() val validator: Validator javaClass.classLoader.getResourceAsStream("xliff/xliff-core-1.2-transitional.xsd") .use { xsdInputStream -> - validator = try { - val factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI) - val schemaFile: Source = StreamSource(xsdInputStream) - - val schema = factory.newSchema(schemaFile) - schema.newValidator() - } catch (e: Exception) { - throw e - } + validator = + try { + val factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI) + val schemaFile: Source = StreamSource(xsdInputStream) + + val schema = factory.newSchema(schemaFile) + schema.newValidator() + } catch (e: Exception) { + throw e + } } assertThat(files).hasSize(2) diff --git a/backend/app/src/test/kotlin/io/tolgee/service/project/ProjectServiceTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/project/ProjectServiceTest.kt index b385217f7d..744dde8beb 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/project/ProjectServiceTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/project/ProjectServiceTest.kt @@ -33,7 +33,6 @@ import org.springframework.boot.test.context.SpringBootTest @SpringBootTest class ProjectServiceTest : AbstractSpringTest() { - @Autowired private lateinit var batchJobService: BatchJobService @@ -110,15 +109,15 @@ class ProjectServiceTest : AbstractSpringTest() { Permission( user = base.userAccount, project = customPermissionProject, - type = ProjectPermissionType.TRANSLATE - ) + type = ProjectPermissionType.TRANSLATE, + ), ) permissionService.create( Permission( user = base.userAccount, project = customPermissionProject2, - type = ProjectPermissionType.TRANSLATE - ) + type = ProjectPermissionType.TRANSLATE, + ), ) val projects = projectService.findAllPermitted(base.userAccount) @@ -149,11 +148,12 @@ class ProjectServiceTest : AbstractSpringTest() { @Test fun `deletes project with MT Settings`() { - val testData = executeInNewTransaction { - val testData = MtSettingsTestData() - testDataService.saveTestData(testData.root) - return@executeInNewTransaction testData - } + val testData = + executeInNewTransaction { + val testData = MtSettingsTestData() + testDataService.saveTestData(testData.root) + return@executeInNewTransaction testData + } executeInNewTransaction(platformTransactionManager) { projectService.hardDeleteProject(testData.projectBuilder.self.id) } @@ -165,14 +165,16 @@ class ProjectServiceTest : AbstractSpringTest() { val keys = testData.addTranslationOperationData(10) testDataService.saveTestData(testData.root) - val job = batchJobService.startJob( - request = DeleteKeysRequest().apply { - keyIds = keys.map { it.id } - }, - project = testData.projectBuilder.self, - author = testData.user, - type = BatchJobType.DELETE_KEYS, - ) + val job = + batchJobService.startJob( + request = + DeleteKeysRequest().apply { + keyIds = keys.map { it.id } + }, + project = testData.projectBuilder.self, + author = testData.user, + type = BatchJobType.DELETE_KEYS, + ) waitFor { executeInNewTransaction { @@ -200,12 +202,13 @@ class ProjectServiceTest : AbstractSpringTest() { executeInNewTransaction { bigMetaService.store( BigMetaDto().apply { - relatedKeysInOrder = mutableListOf( - RelatedKeyDto(keyName = key1.name), - RelatedKeyDto(keyName = key2.name) - ) + relatedKeysInOrder = + mutableListOf( + RelatedKeyDto(keyName = key1.name), + RelatedKeyDto(keyName = key2.name), + ) }, - testData.projectBuilder.self + testData.projectBuilder.self, ) } executeInNewTransaction(platformTransactionManager) { diff --git a/backend/app/src/test/kotlin/io/tolgee/service/query_builders/CursorUtilUnitTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/queryBuilders/CursorUtilUnitTest.kt similarity index 57% rename from backend/app/src/test/kotlin/io/tolgee/service/query_builders/CursorUtilUnitTest.kt rename to backend/app/src/test/kotlin/io/tolgee/service/queryBuilders/CursorUtilUnitTest.kt index 59c8a16b57..552aaf3560 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/query_builders/CursorUtilUnitTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/queryBuilders/CursorUtilUnitTest.kt @@ -1,4 +1,4 @@ -package io.tolgee.service.query_builders +package io.tolgee.service.queryBuilders import io.tolgee.fixtures.node import io.tolgee.model.enums.TranslationState @@ -12,38 +12,41 @@ import org.springframework.data.domain.Sort import java.util.* class CursorUtilUnitTest { - lateinit var cursor: String @BeforeEach fun setup() { - val item = KeyWithTranslationsView( - keyId = 1, - keyName = "Super key", - keyNamespaceId = null, - keyNamespace = null, - screenshotCount = 1, - translations = mutableMapOf( - "en" to TranslationView( - id = 1, - text = "Super key translated \uD83C\uDF8C", - state = TranslationState.TRANSLATED, - outdated = false, - auto = false, - mtProvider = null, - commentCount = 0, - unresolvedCommentCount = 1 - ) - ), - contextPresent = false - ) - cursor = CursorUtil.getCursor( - item, - Sort.by( - Sort.Order.asc("translations.en.text"), - Sort.Order.desc("keyName") + val item = + KeyWithTranslationsView( + keyId = 1, + keyName = "Super key", + keyNamespaceId = null, + keyNamespace = null, + screenshotCount = 1, + translations = + mutableMapOf( + "en" to + TranslationView( + id = 1, + text = "Super key translated \uD83C\uDF8C", + state = TranslationState.TRANSLATED, + outdated = false, + auto = false, + mtProvider = null, + commentCount = 0, + unresolvedCommentCount = 1, + ), + ), + contextPresent = false, + ) + cursor = + CursorUtil.getCursor( + item, + Sort.by( + Sort.Order.asc("translations.en.text"), + Sort.Order.desc("keyName"), + ), ) - ) } @Test diff --git a/backend/app/src/test/kotlin/io/tolgee/service/query_builders/TranslationViewDataProviderTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/queryBuilders/TranslationViewDataProviderTest.kt similarity index 64% rename from backend/app/src/test/kotlin/io/tolgee/service/query_builders/TranslationViewDataProviderTest.kt rename to backend/app/src/test/kotlin/io/tolgee/service/queryBuilders/TranslationViewDataProviderTest.kt index f073efb8d7..6935ac251b 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/query_builders/TranslationViewDataProviderTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/queryBuilders/TranslationViewDataProviderTest.kt @@ -1,9 +1,9 @@ -package io.tolgee.service.query_builders +package io.tolgee.service.queryBuilders import io.tolgee.AbstractSpringTest import io.tolgee.development.testDataBuilder.data.TranslationsTestData import io.tolgee.dtos.request.translation.GetTranslationsParams -import io.tolgee.service.query_builders.translationViewBuilder.TranslationViewDataProvider +import io.tolgee.service.queryBuilders.translationViewBuilder.TranslationViewDataProvider import io.tolgee.testing.assertions.Assertions.assertThat import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired @@ -14,18 +14,18 @@ import org.springframework.transaction.annotation.Transactional @SpringBootTest @Transactional class TranslationViewDataProviderTest : AbstractSpringTest() { - @Autowired private lateinit var translationViewDataProvider: TranslationViewDataProvider @Test fun `returns correct page size and page meta`() { val testData = prepareLotOfData() - val result = translationViewDataProvider.getData( - projectId = testData.project.id, - languages = setOf(testData.englishLanguage, testData.germanLanguage), - PageRequest.of(0, 10), - ) + val result = + translationViewDataProvider.getData( + projectId = testData.project.id, + languages = setOf(testData.englishLanguage, testData.germanLanguage), + PageRequest.of(0, 10), + ) assertThat(result.content).hasSize(10) assertThat(result.totalElements).isGreaterThan(90) } @@ -33,27 +33,31 @@ class TranslationViewDataProviderTest : AbstractSpringTest() { @Test fun `selects languages`() { val testData = prepareLotOfData() - val result = translationViewDataProvider.getData( - projectId = testData.project.id, - languages = setOf(testData.englishLanguage), - PageRequest.of( - 0, 10, + val result = + translationViewDataProvider.getData( + projectId = testData.project.id, + languages = setOf(testData.englishLanguage), + PageRequest.of( + 0, + 10, + ), ) - ) assertThat(result.content[1].translations).doesNotContainKey("de") } @Test fun `searches in data`() { val testData = prepareLotOfData() - val result = translationViewDataProvider.getData( - projectId = testData.project.id, - languages = setOf(testData.englishLanguage), - PageRequest.of(0, 10), - params = GetTranslationsParams().apply { - search = "A tr" - } - ) + val result = + translationViewDataProvider.getData( + projectId = testData.project.id, + languages = setOf(testData.englishLanguage), + PageRequest.of(0, 10), + params = + GetTranslationsParams().apply { + search = "A tr" + }, + ) assertThat(result.content.first().translations["en"]?.text).isEqualTo("A translation") assertThat(result.totalElements).isEqualTo(1) } @@ -62,12 +66,13 @@ class TranslationViewDataProviderTest : AbstractSpringTest() { fun `returns correct comment counts`() { val testData = generateCommentStatesTestData() - val result = translationViewDataProvider.getData( - projectId = testData.project.id, - languages = setOf(testData.germanLanguage), - PageRequest.of(0, 10), - params = GetTranslationsParams() - ) + val result = + translationViewDataProvider.getData( + projectId = testData.project.id, + languages = setOf(testData.germanLanguage), + PageRequest.of(0, 10), + params = GetTranslationsParams(), + ) val key = result.content.find { it.keyName == "commented_key" }!! assertThat(key.translations["de"]?.commentCount).isEqualTo(4) diff --git a/backend/app/src/test/kotlin/io/tolgee/service/recaptchaValidation/RecaptchaValidationDisabledTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/recaptchaValidation/RecaptchaValidationDisabledTest.kt index 00ccc763c3..552c1e1f9e 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/recaptchaValidation/RecaptchaValidationDisabledTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/recaptchaValidation/RecaptchaValidationDisabledTest.kt @@ -22,7 +22,6 @@ import org.springframework.web.client.RestTemplate import java.util.* class RecaptchaValidationDisabledTest : AbstractSpringTest() { - @Autowired lateinit var reCaptchaValidationService: ReCaptchaValidationService @@ -33,7 +32,7 @@ class RecaptchaValidationDisabledTest : AbstractSpringTest() { @Test fun `does not validate`() { whenever( - restTemplate.postForEntity(any(), any(), any>()) + restTemplate.postForEntity(any(), any(), any>()), ).then { ResponseEntity( Companion.Response().apply { @@ -42,7 +41,7 @@ class RecaptchaValidationDisabledTest : AbstractSpringTest() { hostname = "" errorCodes = null }, - HttpStatus.OK + HttpStatus.OK, ) } @@ -50,7 +49,9 @@ class RecaptchaValidationDisabledTest : AbstractSpringTest() { verify(restTemplate, times(0)) .postForEntity( - eq("https://www.google.com/recaptcha/api/siteverify"), any(), eq(Companion.Response::class.java) + eq("https://www.google.com/recaptcha/api/siteverify"), + any(), + eq(Companion.Response::class.java), ) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/service/recaptchaValidation/RecaptchaValidationTest.kt b/backend/app/src/test/kotlin/io/tolgee/service/recaptchaValidation/RecaptchaValidationTest.kt index 13106a414e..f7914ebac8 100644 --- a/backend/app/src/test/kotlin/io/tolgee/service/recaptchaValidation/RecaptchaValidationTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/service/recaptchaValidation/RecaptchaValidationTest.kt @@ -29,10 +29,9 @@ import java.util.* @SpringBootTest( properties = [ "tolgee.recaptcha.secretKey=dummy_key", - ] + ], ) class RecaptchaValidationTest : AbstractSpringTest() { - @Autowired lateinit var reCaptchaValidationService: ReCaptchaValidationService @@ -44,7 +43,7 @@ class RecaptchaValidationTest : AbstractSpringTest() { fun setup() { Mockito.reset(restTemplate) whenever( - restTemplate.postForEntity(any(), any(), any>()) + restTemplate.postForEntity(any(), any(), any>()), ).then { ResponseEntity( Companion.Response().apply { @@ -53,7 +52,7 @@ class RecaptchaValidationTest : AbstractSpringTest() { hostname = "" errorCodes = null }, - HttpStatus.OK + HttpStatus.OK, ) } } @@ -64,14 +63,16 @@ class RecaptchaValidationTest : AbstractSpringTest() { verify(restTemplate, times(1)) .postForEntity( - eq("https://www.google.com/recaptcha/api/siteverify"), any(), eq(Companion.Response::class.java) + eq("https://www.google.com/recaptcha/api/siteverify"), + any(), + eq(Companion.Response::class.java), ) } @Test fun `returns false when invalid`() { whenever( - restTemplate.postForEntity(any(), any(), any>()) + restTemplate.postForEntity(any(), any(), any>()), ).then { ResponseEntity( Companion.Response().apply { @@ -80,7 +81,7 @@ class RecaptchaValidationTest : AbstractSpringTest() { hostname = "" errorCodes = null }, - HttpStatus.OK + HttpStatus.OK, ) } @@ -88,7 +89,9 @@ class RecaptchaValidationTest : AbstractSpringTest() { verify(restTemplate, times(1)) .postForEntity( - eq("https://www.google.com/recaptcha/api/siteverify"), any(), eq(Companion.Response::class.java) + eq("https://www.google.com/recaptcha/api/siteverify"), + any(), + eq(Companion.Response::class.java), ) } } diff --git a/backend/app/src/test/kotlin/io/tolgee/unit/component/SimpleLockingProviderTest.kt b/backend/app/src/test/kotlin/io/tolgee/unit/component/SimpleLockingProviderTest.kt index 5c23e8d4f5..eab5be3d97 100644 --- a/backend/app/src/test/kotlin/io/tolgee/unit/component/SimpleLockingProviderTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/unit/component/SimpleLockingProviderTest.kt @@ -12,7 +12,6 @@ import java.util.concurrent.TimeUnit import kotlin.system.measureTimeMillis class SimpleLockingProviderTest { - val provider = SimpleLockingProvider() @Test @@ -57,7 +56,11 @@ class SimpleLockingProviderTest { yep2Lock.lock() } - private suspend fun massiveRun(threads: Int, repeats: Int, action: suspend () -> Unit) { + private suspend fun massiveRun( + threads: Int, + repeats: Int, + action: suspend () -> Unit, + ) { measureTimeMillis { coroutineScope { // scope for coroutines repeat(threads) { diff --git a/backend/app/src/test/kotlin/io/tolgee/util/BatchDumper.kt b/backend/app/src/test/kotlin/io/tolgee/util/BatchDumper.kt index 1672bbdcbb..32c97b916a 100644 --- a/backend/app/src/test/kotlin/io/tolgee/util/BatchDumper.kt +++ b/backend/app/src/test/kotlin/io/tolgee/util/BatchDumper.kt @@ -11,7 +11,7 @@ class BatchDumper( private val batchJobService: BatchJobService, private val batchJobStateProvider: BatchJobStateProvider, private val currentDateProvider: CurrentDateProvider, - private val batchJobChunkExecutionQueue: BatchJobChunkExecutionQueue + private val batchJobChunkExecutionQueue: BatchJobChunkExecutionQueue, ) : Logging { fun dump(jobId: Long) { val stringBuilder = StringBuilder() @@ -22,21 +22,31 @@ class BatchDumper( logger.info(stringBuilder.toString()) } - private fun dumpDbExecutions(jobId: Long, stringBuilder: StringBuilder) { + private fun dumpDbExecutions( + jobId: Long, + stringBuilder: StringBuilder, + ) { val dbExecutions = batchJobService.getExecutions(jobId) stringBuilder.append("\n\nDatabase state:") stringBuilder.append(" (${dbExecutions.size} executions)") stringBuilder.append("\n\n${listOf("Execution ID", "Status", "Completed", "ExecuteAfter offset").toTable()}") - val dbExecutionsString = dbExecutions - .joinToString(separator = "\n") { - listOf( - it.id, it.status.name, it.status.completed, it.executeAfter.offset - ).toTable() - } + val dbExecutionsString = + dbExecutions + .joinToString(separator = "\n") { + listOf( + it.id, + it.status.name, + it.status.completed, + it.executeAfter.offset, + ).toTable() + } stringBuilder.append("\n$dbExecutionsString") } - private fun dumpCachedState(stringBuilder: StringBuilder, jobId: Long) { + private fun dumpCachedState( + stringBuilder: StringBuilder, + jobId: Long, + ) { stringBuilder.append("\n\nCached state:") val cachedState = batchJobStateProvider.getCached(jobId)?.entries if (cachedState == null) { @@ -57,7 +67,10 @@ class BatchDumper( } } - private fun dumpQueuedItems(jobId: Long, stringBuilder: StringBuilder) { + private fun dumpQueuedItems( + jobId: Long, + stringBuilder: StringBuilder, + ) { val queuedItems = batchJobChunkExecutionQueue.getQueuedJobItems(jobId) val queuedItemsString = queuedItems.joinToString(", ") stringBuilder.append("\n\nQueued items: (${queuedItems.size} executions) $queuedItemsString") diff --git a/backend/app/src/test/kotlin/io/tolgee/util/GitHubAuthUtil.kt b/backend/app/src/test/kotlin/io/tolgee/util/GitHubAuthUtil.kt index d581528e78..762881f462 100644 --- a/backend/app/src/test/kotlin/io/tolgee/util/GitHubAuthUtil.kt +++ b/backend/app/src/test/kotlin/io/tolgee/util/GitHubAuthUtil.kt @@ -1,7 +1,7 @@ package io.tolgee.util import io.tolgee.configuration.tolgee.TolgeeProperties -import io.tolgee.security.third_party.GithubOAuthDelegate +import io.tolgee.security.thirdParty.GithubOAuthDelegate import org.mockito.kotlin.any import org.mockito.kotlin.eq import org.mockito.kotlin.whenever @@ -17,7 +17,7 @@ import org.springframework.web.client.RestTemplate class GitHubAuthUtil( private val tolgeeProperties: TolgeeProperties, private var authMvc: MockMvc? = null, - private val restTemplate: RestTemplate? = null + private val restTemplate: RestTemplate? = null, ) { private val defaultEmailResponse: GithubOAuthDelegate.GithubEmailResponse get() { @@ -46,14 +46,16 @@ class GitHubAuthUtil( fun authorizeGithubUser( tokenResponse: Map? = this.defaultTokenResponse, - userResponse: ResponseEntity = ResponseEntity( - this.defaultUserResponse, - HttpStatus.OK - ), - emailResponse: ResponseEntity> = ResponseEntity( - arrayOf(this.defaultEmailResponse), - HttpStatus.OK - ) + userResponse: ResponseEntity = + ResponseEntity( + this.defaultUserResponse, + HttpStatus.OK, + ), + emailResponse: ResponseEntity> = + ResponseEntity( + arrayOf(this.defaultEmailResponse), + HttpStatus.OK, + ), ): MvcResult { val receivedCode = "ThiS_Is_Fake_valid_COde" val githubConf = tolgeeProperties.authentication.github @@ -66,8 +68,8 @@ class GitHubAuthUtil( eq(githubConf.userUrl), eq(HttpMethod.GET), any(), - eq(GithubOAuthDelegate.GithubUserResponse::class.java) - ) + eq(GithubOAuthDelegate.GithubUserResponse::class.java), + ), ).thenReturn(userResponse) whenever( @@ -75,15 +77,15 @@ class GitHubAuthUtil( eq(value = githubConf.userUrl + "/emails"), eq(HttpMethod.GET), any(), - eq(Array::class.java) - ) + eq(Array::class.java), + ), ) .thenReturn(emailResponse) return authMvc!!.perform( MockMvcRequestBuilders.get("/api/public/authorize_oauth/github?code=$receivedCode") .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON), ) .andReturn() } diff --git a/backend/app/src/test/kotlin/io/tolgee/util/GoogleAuthUtil.kt b/backend/app/src/test/kotlin/io/tolgee/util/GoogleAuthUtil.kt index ce76c1d9e4..26257e72a3 100644 --- a/backend/app/src/test/kotlin/io/tolgee/util/GoogleAuthUtil.kt +++ b/backend/app/src/test/kotlin/io/tolgee/util/GoogleAuthUtil.kt @@ -1,7 +1,7 @@ package io.tolgee.util import io.tolgee.configuration.tolgee.TolgeeProperties -import io.tolgee.security.third_party.GoogleOAuthDelegate +import io.tolgee.security.thirdParty.GoogleOAuthDelegate import org.mockito.kotlin.any import org.mockito.kotlin.eq import org.mockito.kotlin.whenever @@ -17,9 +17,8 @@ import org.springframework.web.client.RestTemplate class GoogleAuthUtil( private val tolgeeProperties: TolgeeProperties, private var authMvc: MockMvc? = null, - private val restTemplate: RestTemplate? = null + private val restTemplate: RestTemplate? = null, ) { - private val defaultUserResponse: GoogleOAuthDelegate.GoogleUserResponse get() { val fakeGoogleUser = GoogleOAuthDelegate.GoogleUserResponse() @@ -42,10 +41,11 @@ class GoogleAuthUtil( fun authorizeGoogleUser( tokenResponse: Map? = this.defaultTokenResponse, - userResponse: ResponseEntity = ResponseEntity( - this.defaultUserResponse, - HttpStatus.OK - ) + userResponse: ResponseEntity = + ResponseEntity( + this.defaultUserResponse, + HttpStatus.OK, + ), ): MvcResult { val receivedCode = "ThiS_Is_Fake_valid_COde" val googleConf = tolgeeProperties.authentication.google @@ -58,14 +58,14 @@ class GoogleAuthUtil( eq(googleConf.userUrl), eq(HttpMethod.GET), any(), - eq(GoogleOAuthDelegate.GoogleUserResponse::class.java) - ) + eq(GoogleOAuthDelegate.GoogleUserResponse::class.java), + ), ).thenReturn(userResponse) return authMvc!!.perform( MockMvcRequestBuilders.get("/api/public/authorize_oauth/google?code=$receivedCode") .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON), ) .andReturn() } diff --git a/backend/app/src/test/kotlin/io/tolgee/util/OAuth2AuthUtil.kt b/backend/app/src/test/kotlin/io/tolgee/util/OAuth2AuthUtil.kt index 384b72beb4..9eff548b47 100644 --- a/backend/app/src/test/kotlin/io/tolgee/util/OAuth2AuthUtil.kt +++ b/backend/app/src/test/kotlin/io/tolgee/util/OAuth2AuthUtil.kt @@ -1,7 +1,7 @@ package io.tolgee.util import io.tolgee.configuration.tolgee.TolgeeProperties -import io.tolgee.security.third_party.OAuth2Delegate +import io.tolgee.security.thirdParty.OAuth2Delegate import org.mockito.kotlin.any import org.mockito.kotlin.eq import org.mockito.kotlin.whenever @@ -17,9 +17,8 @@ import org.springframework.web.client.RestTemplate class OAuth2AuthUtil( private val tolgeeProperties: TolgeeProperties, private var authMvc: MockMvc? = null, - private val restTemplate: RestTemplate? = null + private val restTemplate: RestTemplate? = null, ) { - private val defaultUserResponse: OAuth2Delegate.GenericUserResponse get() { val fakeGenericOAuth2User = OAuth2Delegate.GenericUserResponse() @@ -40,10 +39,11 @@ class OAuth2AuthUtil( fun authorizeOAuth2User( tokenResponse: Map? = this.defaultTokenResponse, - userResponse: ResponseEntity = ResponseEntity( - this.defaultUserResponse, - HttpStatus.OK - ) + userResponse: ResponseEntity = + ResponseEntity( + this.defaultUserResponse, + HttpStatus.OK, + ), ): MvcResult { val receivedCode = "ThiS_Is_Fake_valid_COde" val oauth2Conf = tolgeeProperties.authentication.oauth2 @@ -59,15 +59,15 @@ class OAuth2AuthUtil( eq(oauth2Conf.userUrl!!), eq(HttpMethod.GET), any(), - eq(OAuth2Delegate.GenericUserResponse::class.java) - ) + eq(OAuth2Delegate.GenericUserResponse::class.java), + ), ).thenReturn(userResponse) } return authMvc!!.perform( MockMvcRequestBuilders.get("/api/public/authorize_oauth/oauth2?code=$receivedCode") .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON), ) .andReturn() } diff --git a/backend/app/src/test/kotlin/io/tolgee/util/generateImage.kt b/backend/app/src/test/kotlin/io/tolgee/util/generateImage.kt index e154d741c2..312b996b32 100644 --- a/backend/app/src/test/kotlin/io/tolgee/util/generateImage.kt +++ b/backend/app/src/test/kotlin/io/tolgee/util/generateImage.kt @@ -5,7 +5,10 @@ import java.awt.image.BufferedImage import java.io.ByteArrayOutputStream import javax.imageio.ImageIO -fun generateImage(width: Int = 2000, height: Int = 3000): InputStreamSource { +fun generateImage( + width: Int = 2000, + height: Int = 3000, +): InputStreamSource { val image = BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY) image.createGraphics().drawString("Hello World", 10, 20) val outputStream = ByteArrayOutputStream() diff --git a/backend/app/src/test/kotlin/io/tolgee/websocket/AbstractWebsocketTest.kt b/backend/app/src/test/kotlin/io/tolgee/websocket/AbstractWebsocketTest.kt index 233125c11c..a284f79b80 100644 --- a/backend/app/src/test/kotlin/io/tolgee/websocket/AbstractWebsocketTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/websocket/AbstractWebsocketTest.kt @@ -33,11 +33,12 @@ abstract class AbstractWebsocketTest : ProjectAuthControllerTest("/v2/projects/" @BeforeEach fun beforeEach() { prepareTestData() - helper = WebsocketTestHelper( - port, - jwtService.emitToken(testData.user.id), - testData.projectBuilder.self.id - ) + helper = + WebsocketTestHelper( + port, + jwtService.emitToken(testData.user.id), + testData.projectBuilder.self.id, + ) helper.listenForTranslationDataModified() } @@ -52,7 +53,7 @@ abstract class AbstractWebsocketTest : ProjectAuthControllerTest("/v2/projects/" helper.assertNotified( { performProjectAuthPut("keys/${key.id}", mapOf("name" to "name edited")) - } + }, ) { assertThatJson(it.poll()).apply { node("actor") { @@ -87,7 +88,7 @@ abstract class AbstractWebsocketTest : ProjectAuthControllerTest("/v2/projects/" helper.assertNotified( { performProjectAuthDelete("keys/${key.id}") - } + }, ) { assertThatJson(it.poll()).apply { node("data") { @@ -115,7 +116,7 @@ abstract class AbstractWebsocketTest : ProjectAuthControllerTest("/v2/projects/" helper.assertNotified( { performProjectAuthPost("keys", mapOf("name" to "new key")) - } + }, ) { assertThatJson(it.poll()).apply { node("data") { @@ -146,10 +147,10 @@ abstract class AbstractWebsocketTest : ProjectAuthControllerTest("/v2/projects/" "translations", mapOf( "key" to key.name, - "translations" to mapOf("en" to "haha") - ) + "translations" to mapOf("en" to "haha"), + ), ).andIsOk - } + }, ) { assertThatJson(it.poll()).apply { node("data") { @@ -190,18 +191,19 @@ abstract class AbstractWebsocketTest : ProjectAuthControllerTest("/v2/projects/" @Test @ProjectJWTAuthTestMethod fun `doesn't subscribe without permissions`() { - val notPermittedSubscriptionHelper = WebsocketTestHelper( - port, - jwtService.emitToken(notPermittedUser.id), - testData.projectBuilder.self.id - ) + val notPermittedSubscriptionHelper = + WebsocketTestHelper( + port, + jwtService.emitToken(notPermittedUser.id), + testData.projectBuilder.self.id, + ) notPermittedSubscriptionHelper.listenForTranslationDataModified() performProjectAuthPut( "translations", mapOf( "key" to key.name, - "translations" to mapOf("en" to "haha") - ) + "translations" to mapOf("en" to "haha"), + ), ).andIsOk Thread.sleep(1000) notPermittedSubscriptionHelper.receivedMessages.assert.isEmpty() diff --git a/backend/app/src/test/kotlin/io/tolgee/websocket/WebsocketTestHelper.kt b/backend/app/src/test/kotlin/io/tolgee/websocket/WebsocketTestHelper.kt index 2d7e99a472..c622bc7e41 100644 --- a/backend/app/src/test/kotlin/io/tolgee/websocket/WebsocketTestHelper.kt +++ b/backend/app/src/test/kotlin/io/tolgee/websocket/WebsocketTestHelper.kt @@ -32,7 +32,7 @@ class WebsocketTestHelper(val port: Int?, val jwtToken: String, val projectId: L private val webSocketStompClient by lazy { WebSocketStompClient( - SockJsClient(listOf(WebSocketTransport(StandardWebSocketClient()))) + SockJsClient(listOf(WebSocketTransport(StandardWebSocketClient()))), ) } @@ -43,11 +43,13 @@ class WebsocketTestHelper(val port: Int?, val jwtToken: String, val projectId: L webSocketStompClient.messageConverter = SimpleMessageConverter() sessionHandler = MySessionHandler(path, receivedMessages) - connection = webSocketStompClient.connectAsync( - "http://localhost:$port/websocket", WebSocketHttpHeaders(), - StompHeaders().apply { add("jwtToken", jwtToken) }, - sessionHandler!! - ).get(10, TimeUnit.SECONDS) + connection = + webSocketStompClient.connectAsync( + "http://localhost:$port/websocket", + WebSocketHttpHeaders(), + StompHeaders().apply { add("jwtToken", jwtToken) }, + sessionHandler!!, + ).get(10, TimeUnit.SECONDS) } fun stop() { @@ -64,12 +66,14 @@ class WebsocketTestHelper(val port: Int?, val jwtToken: String, val projectId: L private class MySessionHandler( val dest: String, - val receivedMessages: LinkedBlockingDeque + val receivedMessages: LinkedBlockingDeque, ) : StompSessionHandlerAdapter(), Logging { - var subscription: StompSession.Subscription? = null - override fun afterConnected(session: StompSession, connectedHeaders: StompHeaders) { + override fun afterConnected( + session: StompSession, + connectedHeaders: StompHeaders, + ) { logger.info("Connected to websocket") logger.info("Subscribing to $dest") subscription = session.subscribe(dest, this) @@ -80,12 +84,15 @@ class WebsocketTestHelper(val port: Int?, val jwtToken: String, val projectId: L @Nullable command: StompCommand?, headers: StompHeaders, payload: ByteArray, - exception: Throwable + exception: Throwable, ) { logger.warn("Stomp Error:", exception) } - override fun handleTransportError(session: StompSession, exception: Throwable) { + override fun handleTransportError( + session: StompSession, + exception: Throwable, + ) { super.handleTransportError(session, exception) logger.warn("Stomp Transport Error:", exception) } @@ -94,7 +101,10 @@ class WebsocketTestHelper(val port: Int?, val jwtToken: String, val projectId: L return ByteArray::class.java } - override fun handleFrame(stompHeaders: StompHeaders, o: Any?) { + override fun handleFrame( + stompHeaders: StompHeaders, + o: Any?, + ) { logger.info("Handle Frame with payload: {}", (o as? ByteArray)?.decodeToString()) try { receivedMessages.add((o as ByteArray).decodeToString()) @@ -109,7 +119,7 @@ class WebsocketTestHelper(val port: Int?, val jwtToken: String, val projectId: L */ fun assertNotified( dispatchCallback: () -> Unit, - assertCallback: ((value: LinkedBlockingDeque) -> Unit) + assertCallback: ((value: LinkedBlockingDeque) -> Unit), ) { Thread.sleep(200) dispatchCallback() diff --git a/backend/app/src/test/kotlin/io/tolgee/websocket/WebsocketWithRedisTest.kt b/backend/app/src/test/kotlin/io/tolgee/websocket/WebsocketWithRedisTest.kt index 97a8fc6e62..e55cdfffa6 100644 --- a/backend/app/src/test/kotlin/io/tolgee/websocket/WebsocketWithRedisTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/websocket/WebsocketWithRedisTest.kt @@ -11,9 +11,9 @@ import org.springframework.test.context.ContextConfiguration @SpringBootTest( properties = [ "spring.redis.port=56379", - "tolgee.websocket.use-redis=true" + "tolgee.websocket.use-redis=true", ], - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, ) @ContextConfiguration(initializers = [WebsocketWithRedisTest.Companion.Initializer::class]) @TestInstance(TestInstance.Lifecycle.PER_CLASS) diff --git a/backend/app/src/test/kotlin/io/tolgee/websocket/WebsocketWithoutRedisTest.kt b/backend/app/src/test/kotlin/io/tolgee/websocket/WebsocketWithoutRedisTest.kt index c4b0573e5f..2400c42934 100644 --- a/backend/app/src/test/kotlin/io/tolgee/websocket/WebsocketWithoutRedisTest.kt +++ b/backend/app/src/test/kotlin/io/tolgee/websocket/WebsocketWithoutRedisTest.kt @@ -7,7 +7,7 @@ import org.springframework.boot.test.context.SpringBootTest properties = [ "tolgee.websocket.use-redis=false", ], - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, ) @TestInstance(TestInstance.Lifecycle.PER_CLASS) class WebsocketWithoutRedisTest : AbstractWebsocketTest() diff --git a/backend/data/build.gradle b/backend/data/build.gradle index ff145a6a4c..750736c5b0 100644 --- a/backend/data/build.gradle +++ b/backend/data/build.gradle @@ -158,7 +158,7 @@ dependencies { * MISC */ implementation libs.commonsCodec - implementation group: 'org.apache.commons', name: 'commons-text', version: '1.9' + implementation group: 'org.apache.commons', name: 'commons-text', version: '1.10.0' implementation libs.icu4j implementation libs.jjwtApi implementation libs.jjwtImpl @@ -227,3 +227,11 @@ jar { tasks.named('compileJava') { inputs.files(tasks.named('processResources')) } + +ktlint { + debug = true + verbose = true + filter { + exclude("**/PluralData.kt") + } +} diff --git a/backend/data/src/main/java/io/tolgee/helpers/TextHelper.kt b/backend/data/src/main/java/io/tolgee/helpers/TextHelper.kt index db0681522a..ebdc92cb61 100644 --- a/backend/data/src/main/java/io/tolgee/helpers/TextHelper.kt +++ b/backend/data/src/main/java/io/tolgee/helpers/TextHelper.kt @@ -5,7 +5,10 @@ import java.util.regex.Pattern object TextHelper { @JvmStatic - fun splitOnNonEscapedDelimiter(string: String, delimiter: Char?): List { + fun splitOnNonEscapedDelimiter( + string: String, + delimiter: Char?, + ): List { if (delimiter == null) { return listOf(string) } @@ -25,7 +28,10 @@ object TextHelper { return result } - private fun isCharEscaped(position: Int, fullString: String): Boolean { + private fun isCharEscaped( + position: Int, + fullString: String, + ): Boolean { if (position == 0) { return false } @@ -111,6 +117,6 @@ object TextHelper { data class ReplaceIcuResult( val text: String, val isComplex: Boolean, - val params: Map + val params: Map, ) } diff --git a/backend/data/src/main/java/io/tolgee/security/InitialPasswordManager.kt b/backend/data/src/main/java/io/tolgee/security/InitialPasswordManager.kt index 4e374c0abb..9a5d3681e9 100644 --- a/backend/data/src/main/java/io/tolgee/security/InitialPasswordManager.kt +++ b/backend/data/src/main/java/io/tolgee/security/InitialPasswordManager.kt @@ -7,7 +7,7 @@ package io.tolgee.security import io.tolgee.component.fileStorage.FileStorage import io.tolgee.configuration.tolgee.TolgeeProperties import org.springframework.stereotype.Component -import kotlin.random.Random +import java.security.SecureRandom @Component class InitialPasswordManager( @@ -40,7 +40,18 @@ class InitialPasswordManager( } private fun generatePassword(): String { - val charPool: List = ('a'..'z') + ('A'..'Z') + ('0'..'9') - return (1..40).map { charPool[Random.nextInt(0, charPool.size)] }.joinToString("") + return (1..40) + .asSequence() + .map { secureRandom.nextInt(charPool.size) } + .map(charPool::get) + .joinToString("") + } + + val charPool by lazy { + ('a'..'z') + ('A'..'Z') + ('0'..'9') + } + + val secureRandom by lazy { + SecureRandom() } } diff --git a/backend/data/src/main/kotlin/io/tolgee/Metrics.kt b/backend/data/src/main/kotlin/io/tolgee/Metrics.kt index 9c4eff66a8..00b9a4fe80 100644 --- a/backend/data/src/main/kotlin/io/tolgee/Metrics.kt +++ b/backend/data/src/main/kotlin/io/tolgee/Metrics.kt @@ -8,7 +8,7 @@ import java.util.concurrent.ConcurrentLinkedQueue @Component class Metrics( - private val meterRegistry: MeterRegistry + private val meterRegistry: MeterRegistry, ) { fun registerJobQueue(queue: ConcurrentLinkedQueue<*>) { Gauge.builder("tolgee.batch.job.execution.queue.size", queue) { it.size.toDouble() } diff --git a/backend/data/src/main/kotlin/io/tolgee/MtServicesConfiguration.kt b/backend/data/src/main/kotlin/io/tolgee/MtServicesConfiguration.kt index e9767ee482..15b9748761 100644 --- a/backend/data/src/main/kotlin/io/tolgee/MtServicesConfiguration.kt +++ b/backend/data/src/main/kotlin/io/tolgee/MtServicesConfiguration.kt @@ -15,7 +15,7 @@ import software.amazon.awssdk.services.translate.TranslateClient @Configuration class MtServicesConfiguration( private val googleMachineTranslationProperties: GoogleMachineTranslationProperties, - private val awsMachineTranslationProperties: AwsMachineTranslationProperties + private val awsMachineTranslationProperties: AwsMachineTranslationProperties, ) { @Bean fun getGoogleTranslationService(): Translate? { @@ -34,17 +34,20 @@ class MtServicesConfiguration( @Bean fun getAwsTranslationService(): TranslateClient? { - val chain = when ( - awsMachineTranslationProperties.accessKey.isNullOrEmpty() || - awsMachineTranslationProperties.secretKey.isNullOrEmpty() - ) { - true -> DefaultCredentialsProvider.create() - false -> StaticCredentialsProvider.create( - AwsBasicCredentials.create( - awsMachineTranslationProperties.accessKey, awsMachineTranslationProperties.secretKey - ) - ) - } + val chain = + when ( + awsMachineTranslationProperties.accessKey.isNullOrEmpty() || + awsMachineTranslationProperties.secretKey.isNullOrEmpty() + ) { + true -> DefaultCredentialsProvider.create() + false -> + StaticCredentialsProvider.create( + AwsBasicCredentials.create( + awsMachineTranslationProperties.accessKey, + awsMachineTranslationProperties.secretKey, + ), + ) + } return TranslateClient.builder() .credentialsProvider(chain) diff --git a/backend/data/src/main/kotlin/io/tolgee/PostgresRunner.kt b/backend/data/src/main/kotlin/io/tolgee/PostgresRunner.kt index 0da1798733..1cc311d857 100644 --- a/backend/data/src/main/kotlin/io/tolgee/PostgresRunner.kt +++ b/backend/data/src/main/kotlin/io/tolgee/PostgresRunner.kt @@ -2,6 +2,7 @@ package io.tolgee interface PostgresRunner { fun run() + fun stop() /** diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/ActivityHandlerInterceptor.kt b/backend/data/src/main/kotlin/io/tolgee/activity/ActivityHandlerInterceptor.kt index f835f783eb..c6856c671f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/ActivityHandlerInterceptor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/ActivityHandlerInterceptor.kt @@ -18,11 +18,15 @@ import java.util.* @Component class ActivityHandlerInterceptor( private val activityHolder: ActivityHolder, - private val sdkInfoProvider: SdkInfoProvider + private val sdkInfoProvider: SdkInfoProvider, ) : HandlerInterceptor { private val logger = LoggerFactory.getLogger(this::class.java) - override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean { + override fun preHandle( + request: HttpServletRequest, + response: HttpServletResponse, + handler: Any, + ): Boolean { if (handler !is HandlerMethod) { return super.preHandle(request, response, handler) } diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/ActivityHolder.kt b/backend/data/src/main/kotlin/io/tolgee/activity/ActivityHolder.kt index 5bdc95a252..499a7ae8f2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/ActivityHolder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/ActivityHolder.kt @@ -56,7 +56,7 @@ open class ActivityHolder(val applicationContext: ApplicationContext) { fun getDescribingRelationFromCache( entityId: Long, entityClass: String, - provider: () -> ActivityDescribingEntity + provider: () -> ActivityDescribingEntity, ): ActivityDescribingEntity { return describingRelationCache.getOrPut(entityId to entityClass, provider) } diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/ActivityService.kt b/backend/data/src/main/kotlin/io/tolgee/activity/ActivityService.kt index e43ad59425..66121aa676 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/ActivityService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/ActivityService.kt @@ -6,7 +6,7 @@ import io.tolgee.activity.data.RevisionType import io.tolgee.activity.projectActivityView.ProjectActivityViewByPageableProvider import io.tolgee.activity.projectActivityView.ProjectActivityViewByRevisionProvider import io.tolgee.component.CurrentDateProvider -import io.tolgee.dtos.query_results.TranslationHistoryView +import io.tolgee.dtos.queryResults.TranslationHistoryView import io.tolgee.events.OnProjectActivityStoredEvent import io.tolgee.model.activity.ActivityModifiedEntity import io.tolgee.model.activity.ActivityRevision @@ -30,10 +30,13 @@ class ActivityService( private val activityModifiedEntityRepository: ActivityModifiedEntityRepository, private val currentDateProvider: CurrentDateProvider, private val objectMapper: ObjectMapper, - private val jdbcTemplate: JdbcTemplate + private val jdbcTemplate: JdbcTemplate, ) : Logging { @Transactional - fun storeActivityData(activityRevision: ActivityRevision, modifiedEntities: ModifiedEntitiesType) { + fun storeActivityData( + activityRevision: ActivityRevision, + modifiedEntities: ModifiedEntitiesType, + ) { // let's keep the persistent context small entityManager.flushAndClear() @@ -52,7 +55,7 @@ class ActivityService( "describing_relations, modifications, revision_type, activity_revision_id) " + "VALUES (?, ?, ?, ?, ?, ?, ?)", list, - 100 + 100, ) { ps, entity -> ps.setString(1, entity.entityClass) ps.setLong(2, entity.entityId) @@ -72,7 +75,7 @@ class ActivityService( "(entity_class, entity_id, data, describing_relations, activity_revision_id) " + "VALUES (?, ?, ?, ?, ?)", activityRevision.describingRelations, - 100 + 100, ) { ps, entity -> ps.setString(1, entity.entityClass) ps.setLong(2, entity.entityId) @@ -100,11 +103,14 @@ class ActivityService( } @Transactional - fun getProjectActivity(projectId: Long, pageable: Pageable): Page { + fun getProjectActivity( + projectId: Long, + pageable: Pageable, + ): Page { return ProjectActivityViewByPageableProvider( applicationContext = applicationContext, projectId = projectId, - pageable = pageable + pageable = pageable, ).get() } @@ -112,16 +118,19 @@ class ActivityService( fun getProjectActivity(revisionId: Long): ProjectActivityView? { return ProjectActivityViewByRevisionProvider( applicationContext = applicationContext, - revisionId + revisionId, ).get() } @Transactional - fun getTranslationHistory(translationId: Long, pageable: Pageable): Page { + fun getTranslationHistory( + translationId: Long, + pageable: Pageable, + ): Page { return activityModifiedEntityRepository.getTranslationHistory( translationId = translationId, pageable = pageable, - ignoredActivityTypes = listOf(ActivityType.TRANSLATION_COMMENT_ADD) + ignoredActivityTypes = listOf(ActivityType.TRANSLATION_COMMENT_ADD), ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/EntityDescriptionProvider.kt b/backend/data/src/main/kotlin/io/tolgee/activity/EntityDescriptionProvider.kt index 40bb5bd80e..337f49c961 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/EntityDescriptionProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/EntityDescriptionProvider.kt @@ -12,12 +12,9 @@ import kotlin.reflect.full.hasAnnotation @Component class EntityDescriptionProvider( - private val entityUtil: EntityUtil + private val entityUtil: EntityUtil, ) { - fun getDescriptionWithRelations( - entity: EntityWithId, - ): EntityDescriptionWithRelations? { - + fun getDescriptionWithRelations(entity: EntityWithId): EntityDescriptionWithRelations? { val description = getDescription(entity) ?: return null val relations = mutableMapOf() @@ -38,19 +35,22 @@ class EntityDescriptionProvider( description.entityClass, description.entityId, description.data, - relations + relations, ) } fun getDescription(entity: EntityWithId): EntityDescription? { val entityClass = entityUtil.getRealEntityClass(entity::class.java) ?: return null - val fieldValues = entityClass.kotlin.members.filter { member -> - member.hasAnnotation() - }.associateTo(HashMap()) { it.name to it.call(entity) } + val fieldValues = + entityClass.kotlin.members.filter { member -> + member.hasAnnotation() + }.associateTo(HashMap()) { it.name to it.call(entity) } return EntityDescription( - entityClass.simpleName, entityId = entity.id, fieldValues + entityClass.simpleName, + entityId = entity.id, + fieldValues, ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/RequestActivity.kt b/backend/data/src/main/kotlin/io/tolgee/activity/RequestActivity.kt index 694f4eec37..05cf12a9f6 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/RequestActivity.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/RequestActivity.kt @@ -3,5 +3,5 @@ package io.tolgee.activity import io.tolgee.activity.data.ActivityType annotation class RequestActivity( - val activity: ActivityType + val activity: ActivityType, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/annotation/ActivityEntityDescribingPaths.kt b/backend/data/src/main/kotlin/io/tolgee/activity/annotation/ActivityEntityDescribingPaths.kt index be4ad66a90..af65ff7ec8 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/annotation/ActivityEntityDescribingPaths.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/annotation/ActivityEntityDescribingPaths.kt @@ -2,5 +2,5 @@ package io.tolgee.activity.annotation @Target(allowedTargets = [AnnotationTarget.CLASS]) annotation class ActivityEntityDescribingPaths( - val paths: Array = [] + val paths: Array = [], ) diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/annotation/ActivityLoggedProp.kt b/backend/data/src/main/kotlin/io/tolgee/activity/annotation/ActivityLoggedProp.kt index a16b47b72a..ad67a3b3a6 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/annotation/ActivityLoggedProp.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/annotation/ActivityLoggedProp.kt @@ -6,5 +6,5 @@ import kotlin.reflect.KClass @Target(allowedTargets = [AnnotationTarget.PROPERTY]) annotation class ActivityLoggedProp( - val modificationProvider: KClass = DefaultPropChangesProvider::class + val modificationProvider: KClass = DefaultPropChangesProvider::class, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/data/ActivityType.kt b/backend/data/src/main/kotlin/io/tolgee/activity/data/ActivityType.kt index 7bf103c183..8fc424980d 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/data/ActivityType.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/data/ActivityType.kt @@ -10,7 +10,7 @@ enum class ActivityType( val onlyCountsInList: Boolean = false, val restrictEntitiesInList: Array>? = null, val paramsProvider: KClass? = null, - val hideInList: Boolean = false + val hideInList: Boolean = false, ) { UNKNOWN, SET_TRANSLATION_STATE, @@ -44,6 +44,5 @@ enum class ActivityType( BATCH_TAG_KEYS(true, paramsProvider = BatchActivityParamsProvider::class), BATCH_UNTAG_KEYS(true, paramsProvider = BatchActivityParamsProvider::class), BATCH_SET_KEYS_NAMESPACE(true, paramsProvider = BatchActivityParamsProvider::class), - AUTOMATION(onlyCountsInList = true, hideInList = true) - ; + AUTOMATION(onlyCountsInList = true, hideInList = true), } diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/data/EntityDescriptionRef.kt b/backend/data/src/main/kotlin/io/tolgee/activity/data/EntityDescriptionRef.kt index c873de26a6..cc48d58bc9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/data/EntityDescriptionRef.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/data/EntityDescriptionRef.kt @@ -2,5 +2,5 @@ package io.tolgee.activity.data data class EntityDescriptionRef( val entityClass: String, - val entityId: Long + val entityId: Long, ) : java.io.Serializable diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/data/EntityDescriptionWithRelations.kt b/backend/data/src/main/kotlin/io/tolgee/activity/data/EntityDescriptionWithRelations.kt index 972b98bb68..9ddac388bc 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/data/EntityDescriptionWithRelations.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/data/EntityDescriptionWithRelations.kt @@ -4,9 +4,9 @@ open class EntityDescriptionWithRelations( entityClass: String, entityId: Long, data: Map, - val relations: Map + val relations: Map, ) : EntityDescription( - entityClass, - entityId, - data -) + entityClass, + entityId, + data, + ) diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/data/ExistenceEntityDescription.kt b/backend/data/src/main/kotlin/io/tolgee/activity/data/ExistenceEntityDescription.kt index 04b36fa6e5..b69177f4ce 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/data/ExistenceEntityDescription.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/data/ExistenceEntityDescription.kt @@ -5,5 +5,5 @@ class ExistenceEntityDescription( entityId: Long, data: Map, relations: Map, - val exists: Boolean? = null + val exists: Boolean? = null, ) : EntityDescriptionWithRelations(entityClass, entityId, data, relations) diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/data/PropertyModification.kt b/backend/data/src/main/kotlin/io/tolgee/activity/data/PropertyModification.kt index 4e5b7ef119..8cb7111ee6 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/data/PropertyModification.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/data/PropertyModification.kt @@ -2,5 +2,5 @@ package io.tolgee.activity.data data class PropertyModification( val old: Any?, - val new: Any? + val new: Any?, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/data/RevisionType.kt b/backend/data/src/main/kotlin/io/tolgee/activity/data/RevisionType.kt index c329d6da5f..9efba7d7af 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/data/RevisionType.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/data/RevisionType.kt @@ -1,7 +1,10 @@ package io.tolgee.activity.data enum class RevisionType { - ADD, MOD, DEL; + ADD, + MOD, + DEL, + ; fun isAdd(): Boolean { return this == ADD diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/iterceptor/ActivityDatabaseInterceptor.kt b/backend/data/src/main/kotlin/io/tolgee/activity/iterceptor/ActivityDatabaseInterceptor.kt index a6df5ebe64..3ee1c35bd7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/iterceptor/ActivityDatabaseInterceptor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/iterceptor/ActivityDatabaseInterceptor.kt @@ -11,7 +11,6 @@ import org.springframework.stereotype.Component @Component class ActivityDatabaseInterceptor : Interceptor, Logging { - @Autowired lateinit var applicationContext: ApplicationContext @@ -24,11 +23,15 @@ class ActivityDatabaseInterceptor : Interceptor, Logging { id: Any?, state: Array?, propertyNames: Array?, - types: Array? + types: Array?, ): Boolean { preCommitEventsPublisher.onPersist(entity) interceptedEventsManager.onFieldModificationsActivity( - entity, state, null, propertyNames, RevisionType.ADD + entity, + state, + null, + propertyNames, + RevisionType.ADD, ) return true } @@ -38,11 +41,15 @@ class ActivityDatabaseInterceptor : Interceptor, Logging { id: Any?, state: Array?, propertyNames: Array?, - types: Array? + types: Array?, ) { preCommitEventsPublisher.onDelete(entity) interceptedEventsManager.onFieldModificationsActivity( - entity, null, state, propertyNames, RevisionType.DEL + entity, + null, + state, + propertyNames, + RevisionType.DEL, ) } @@ -52,7 +59,7 @@ class ActivityDatabaseInterceptor : Interceptor, Logging { currentState: Array?, previousState: Array?, propertyNames: Array?, - types: Array? + types: Array?, ): Boolean { preCommitEventsPublisher.onUpdate(entity) interceptedEventsManager.onFieldModificationsActivity( @@ -60,20 +67,29 @@ class ActivityDatabaseInterceptor : Interceptor, Logging { currentState, previousState, propertyNames, - RevisionType.MOD + RevisionType.MOD, ) return true } - override fun onCollectionRemove(collection: Any?, key: Any?) { + override fun onCollectionRemove( + collection: Any?, + key: Any?, + ) { interceptedEventsManager.onCollectionModification(collection, key) } - override fun onCollectionRecreate(collection: Any?, key: Any?) { + override fun onCollectionRecreate( + collection: Any?, + key: Any?, + ) { interceptedEventsManager.onCollectionModification(collection, key) } - override fun onCollectionUpdate(collection: Any?, key: Any?) { + override fun onCollectionUpdate( + collection: Any?, + key: Any?, + ) { interceptedEventsManager.onCollectionModification(collection, key) } diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/iterceptor/InterceptedEventsManager.kt b/backend/data/src/main/kotlin/io/tolgee/activity/iterceptor/InterceptedEventsManager.kt index 74ec83fc3a..90bd817fb5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/iterceptor/InterceptedEventsManager.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/iterceptor/InterceptedEventsManager.kt @@ -35,7 +35,7 @@ import kotlin.reflect.full.hasAnnotation @Component @Scope(SCOPE_SINGLETON) class InterceptedEventsManager( - private val applicationContext: ApplicationContext + private val applicationContext: ApplicationContext, ) { private val logger = LoggerFactory.getLogger(this::class.java) @@ -43,7 +43,10 @@ class InterceptedEventsManager( activityHolder.transactionRollbackOnly = tx.rollbackOnly } - fun onCollectionModification(collection: Any?, key: Any?) { + fun onCollectionModification( + collection: Any?, + key: Any?, + ) { if (collection !is AbstractPersistentCollection<*> || collection !is Collection<*> || key !is Long) { return } @@ -55,17 +58,19 @@ class InterceptedEventsManager( return } - val ownerField = collectionOwner::class.members.find { - it.parameters.size == 1 && it.call(collectionOwner) === collection - } ?: return + val ownerField = + collectionOwner::class.members.find { + it.parameters.size == 1 && it.call(collectionOwner) === collection + } ?: return val provider = getChangesProvider(collectionOwner, ownerField.name) ?: return val stored = (collection.storedSnapshot as? HashMap<*, *>)?.values?.toList() - val old = activityHolder.modifiedCollections.computeIfAbsent(collectionOwner to ownerField.name) { - stored - } + val old = + activityHolder.modifiedCollections.computeIfAbsent(collectionOwner to ownerField.name) { + stored + } val changes = provider.getChanges(old, collection) ?: return val activityModifiedEntity = getModifiedEntity(collectionOwner, RevisionType.MOD) @@ -81,7 +86,7 @@ class InterceptedEventsManager( currentState: Array?, previousState: Array?, propertyNames: Array?, - revisionType: RevisionType + revisionType: RevisionType, ) { if (!shouldHandleActivity(entity)) { return @@ -99,66 +104,73 @@ class InterceptedEventsManager( activityModifiedEntity.setEntityDescription(entity) } - private fun ActivityModifiedEntity.setEntityDescription( - entity: EntityWithId, - ) { + private fun ActivityModifiedEntity.setEntityDescription(entity: EntityWithId) { val describingData = getChangeEntityDescription(entity, activityRevision) this.describingData = describingData.first?.filter { !this.modifications.keys.contains(it.key) } this.describingRelations = describingData.second } - private fun getModifiedEntity(entity: EntityWithId, revisionType: RevisionType): ActivityModifiedEntity { - val activityModifiedEntity = activityHolder.modifiedEntities - .computeIfAbsent(entity::class) { mutableMapOf() } - .computeIfAbsent( - entity.id - ) { - ActivityModifiedEntity( - activityRevision, - entity::class.simpleName!!, - entity.id - ).also { it.revisionType = revisionType } - } + private fun getModifiedEntity( + entity: EntityWithId, + revisionType: RevisionType, + ): ActivityModifiedEntity { + val activityModifiedEntity = + activityHolder.modifiedEntities + .computeIfAbsent(entity::class) { mutableMapOf() } + .computeIfAbsent( + entity.id, + ) { + ActivityModifiedEntity( + activityRevision, + entity::class.simpleName!!, + entity.id, + ).also { it.revisionType = revisionType } + } return activityModifiedEntity } private fun getChangeEntityDescription( entity: EntityWithId, - activityRevision: ActivityRevision + activityRevision: ActivityRevision, ): Pair?, Map?> { - val rootDescription = applicationContext.getBean(EntityDescriptionProvider::class.java).getDescriptionWithRelations( - entity - ) - val relations = rootDescription?.relations - ?.map { it.key to compressRelation(it.value, activityRevision) } - ?.toMap() + val rootDescription = + applicationContext.getBean(EntityDescriptionProvider::class.java).getDescriptionWithRelations( + entity, + ) + val relations = + rootDescription?.relations + ?.map { it.key to compressRelation(it.value, activityRevision) } + ?.toMap() return (rootDescription?.data to relations) } private fun compressRelation( value: EntityDescriptionWithRelations, - activityRevision: ActivityRevision + activityRevision: ActivityRevision, ): EntityDescriptionRef { - val activityDescribingEntity = activityHolder - .getDescribingRelationFromCache(value.entityId, value.entityClass) { - val compressedRelations = value.relations.map { relation -> - relation.key to compressRelation(relation.value, activityRevision) - }.toMap() - - val activityDescribingEntity = ActivityDescribingEntity( - activityRevision, - value.entityClass, - value.entityId - ) - - activityDescribingEntity.data = value.data - activityDescribingEntity.describingRelations = compressedRelations - activityRevision.describingRelations.add(activityDescribingEntity) - - activityDescribingEntity - } + val activityDescribingEntity = + activityHolder + .getDescribingRelationFromCache(value.entityId, value.entityClass) { + val compressedRelations = + value.relations.map { relation -> + relation.key to compressRelation(relation.value, activityRevision) + }.toMap() + + val activityDescribingEntity = + ActivityDescribingEntity( + activityRevision, + value.entityClass, + value.entityId, + ) + + activityDescribingEntity.data = value.data + activityDescribingEntity.describingRelations = compressedRelations + activityRevision.describingRelations.add(activityDescribingEntity) + + activityDescribingEntity + } return EntityDescriptionRef(activityDescribingEntity.entityClass, activityDescribingEntity.entityId) } @@ -166,7 +178,7 @@ class InterceptedEventsManager( entity: Any, currentState: Array?, previousState: Array?, - propertyNames: Array? + propertyNames: Array?, ): Map { if (propertyNames == null) { return mapOf() @@ -180,11 +192,15 @@ class InterceptedEventsManager( }.toMap() } - fun getChangesProvider(entity: Any, propertyName: String): PropChangesProvider? { - val propertyAnnotation = entity::class.members - .find { it.name == propertyName } - ?.findAnnotation() - ?: return null + fun getChangesProvider( + entity: Any, + propertyName: String, + ): PropChangesProvider? { + val propertyAnnotation = + entity::class.members + .find { it.name == propertyName } + ?.findAnnotation() + ?: return null val providerClass = propertyAnnotation.modificationProvider return applicationContext.getBean(providerClass.java) @@ -229,8 +245,9 @@ class InterceptedEventsManager( return@BeforeTransactionCompletionProcess } val activityRevision = activityHolder.activityRevision - if (!activityRevision.isInitializedByInterceptor) + if (!activityRevision.isInitializedByInterceptor) { return@BeforeTransactionCompletionProcess + } logger.debug("Publishing project activity event") try { publishOnActivityEvent(activityRevision) @@ -243,7 +260,7 @@ class InterceptedEventsManager( throw e } } - } + }, ) } @@ -254,8 +271,8 @@ class InterceptedEventsManager( activityHolder.modifiedEntities, activityHolder.organizationId, activityHolder.utmData, - activityHolder.sdkInfo - ) + activityHolder.sdkInfo, + ), ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/iterceptor/PreCommitEventPublisher.kt b/backend/data/src/main/kotlin/io/tolgee/activity/iterceptor/PreCommitEventPublisher.kt index 5d36d5e5d5..b18f25c064 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/iterceptor/PreCommitEventPublisher.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/iterceptor/PreCommitEventPublisher.kt @@ -8,7 +8,6 @@ import org.springframework.stereotype.Component @Component class PreCommitEventPublisher(private val applicationContext: ApplicationContext) { - fun onPersist(entity: Any?) { applicationContext.publishEvent(OnEntityPrePersist(this, entity)) } diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/projectActivityView/ActivityViewByRevisionsProvider.kt b/backend/data/src/main/kotlin/io/tolgee/activity/projectActivityView/ActivityViewByRevisionsProvider.kt index 5c385e50c5..cd34c35059 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/projectActivityView/ActivityViewByRevisionsProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/projectActivityView/ActivityViewByRevisionsProvider.kt @@ -63,7 +63,7 @@ class ActivityViewByRevisionsProvider( meta = revision.meta, modifications = modifiedEntities[revision.id], counts = counts[revision.id], - params = params[revision.id] + params = params[revision.id], ) } } @@ -109,7 +109,7 @@ class ActivityViewByRevisionsProvider( val counts: MutableMap> = mutableMapOf() activityRevisionRepository.getModifiedEntityTypeCounts( revisionIds = revisionIds, - allowedTypes + allowedTypes, ).forEach { (revisionId, entityClass, count) -> counts .computeIfAbsent(revisionId as Long) { mutableMapOf() } @@ -120,12 +120,12 @@ class ActivityViewByRevisionsProvider( private fun getAuthors(revisions: Collection) = userAccountService.getAllByIdsIncludingDeleted( - revisions.mapNotNull { it.authorId }.toSet() + revisions.mapNotNull { it.authorId }.toSet(), ).associateBy { it.id } private fun getAllowedRevisionRelations( revisionIds: List, - allowedTypes: Collection + allowedTypes: Collection, ): Map> { return activityRevisionRepository.getRelationsForRevisions(revisionIds, allowedTypes) .groupBy { it.activityRevision.id } @@ -133,18 +133,20 @@ class ActivityViewByRevisionsProvider( private fun getModifiedEntities(): Map> { return rawModifiedEntities.map { modifiedEntity -> - val relations = modifiedEntity.describingRelations - ?.mapNotNull relationsOfEntityMap@{ relationEntry -> - relationEntry.key to extractCompressedRef( - relationEntry.value, - allRelationData[modifiedEntity.activityRevision.id] ?: let { - Sentry.captureException( - IllegalStateException("No relation data for revision ${modifiedEntity.activityRevision.id}") + val relations = + modifiedEntity.describingRelations + ?.mapNotNull relationsOfEntityMap@{ relationEntry -> + relationEntry.key to + extractCompressedRef( + relationEntry.value, + allRelationData[modifiedEntity.activityRevision.id] ?: let { + Sentry.captureException( + IllegalStateException("No relation data for revision ${modifiedEntity.activityRevision.id}"), + ) + return@relationsOfEntityMap null + }, ) - return@relationsOfEntityMap null - } - ) - }?.toMap() + }?.toMap() ModifiedEntityView( activityRevision = modifiedEntity.activityRevision, entityClass = modifiedEntity.entityClass, @@ -152,7 +154,7 @@ class ActivityViewByRevisionsProvider( exists = entityExistences[modifiedEntity.entityClass to modifiedEntity.entityId], modifications = modifiedEntity.modifications, description = modifiedEntity.describingData, - describingRelations = relations + describingRelations = relations, ) }.groupBy { it.activityRevision.id } } @@ -198,8 +200,8 @@ class ActivityViewByRevisionsProvider( whereConditions.add( cb.or( cb.notEqual(revision.get(ActivityRevision_.type), it), - root.get(ActivityModifiedEntity_.entityClass).`in`(restrictedEntityNames) - ) + root.get(ActivityModifiedEntity_.entityClass).`in`(restrictedEntityNames), + ), ) } } @@ -210,20 +212,21 @@ class ActivityViewByRevisionsProvider( private fun extractCompressedRef( value: EntityDescriptionRef, - describingEntities: List + describingEntities: List, ): ExistenceEntityDescription { val entity = describingEntities.find { it.entityClass == value.entityClass && it.entityId == value.entityId } - val relations = entity?.describingRelations - ?.map { it.key to extractCompressedRef(it.value, describingEntities) } - ?.toMap() + val relations = + entity?.describingRelations + ?.map { it.key to extractCompressedRef(it.value, describingEntities) } + ?.toMap() return ExistenceEntityDescription( entityClass = value.entityClass, entityId = value.entityId, exists = entityExistences[value.entityClass to value.entityId], data = entity?.data ?: mapOf(), - relations = relations ?: mapOf() + relations = relations ?: mapOf(), ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/projectActivityView/ProjectActivityViewByPageableProvider.kt b/backend/data/src/main/kotlin/io/tolgee/activity/projectActivityView/ProjectActivityViewByPageableProvider.kt index 1b31a1d57f..7eecf61b7b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/projectActivityView/ProjectActivityViewByPageableProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/projectActivityView/ProjectActivityViewByPageableProvider.kt @@ -12,19 +12,22 @@ import org.springframework.data.domain.Pageable class ProjectActivityViewByPageableProvider( private val applicationContext: ApplicationContext, private val projectId: Long, - private val pageable: Pageable + private val pageable: Pageable, ) { - fun get(): Page { val revisions = getProjectActivityRevisions(projectId, pageable) val newContent = ActivityViewByRevisionsProvider(applicationContext, revisions.content).get() return PageImpl(newContent, revisions.pageable, revisions.totalElements) } - private fun getProjectActivityRevisions(projectId: Long, pageable: Pageable): Page { + private fun getProjectActivityRevisions( + projectId: Long, + pageable: Pageable, + ): Page { val types = ActivityType.values().filter { !it.hideInList } return activityRevisionRepository.getForProject(projectId, pageable, types) } + private val activityRevisionRepository: ActivityRevisionRepository = applicationContext.getBean(ActivityRevisionRepository::class.java) } diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/projectActivityView/ProjectActivityViewByRevisionProvider.kt b/backend/data/src/main/kotlin/io/tolgee/activity/projectActivityView/ProjectActivityViewByRevisionProvider.kt index 24a58e7f30..db61322206 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/projectActivityView/ProjectActivityViewByRevisionProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/projectActivityView/ProjectActivityViewByRevisionProvider.kt @@ -7,7 +7,7 @@ import org.springframework.context.ApplicationContext class ProjectActivityViewByRevisionProvider( private val applicationContext: ApplicationContext, - private val revisionId: Long + private val revisionId: Long, ) { fun get(): ProjectActivityView? { val revisions = getProjectActivityRevisions(revisionId) diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/projectActivityView/RelationDescriptionExtractor.kt b/backend/data/src/main/kotlin/io/tolgee/activity/projectActivityView/RelationDescriptionExtractor.kt index c75dd93cf9..0572fdea18 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/projectActivityView/RelationDescriptionExtractor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/projectActivityView/RelationDescriptionExtractor.kt @@ -9,19 +9,20 @@ import org.springframework.stereotype.Component class RelationDescriptionExtractor { fun extract( value: EntityDescriptionRef, - describingEntities: List + describingEntities: List, ): EntityDescriptionWithRelations { val entity = describingEntities.find { it.entityClass == value.entityClass && it.entityId == value.entityId } - val relations = entity?.describingRelations - ?.map { it.key to extract(it.value, describingEntities) } - ?.toMap() + val relations = + entity?.describingRelations + ?.map { it.key to extract(it.value, describingEntities) } + ?.toMap() return EntityDescriptionWithRelations( entityClass = value.entityClass, entityId = value.entityId, data = entity?.data ?: mapOf(), - relations = relations ?: mapOf() + relations = relations ?: mapOf(), ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/propChangesProvider/DefaultPropChangesProvider.kt b/backend/data/src/main/kotlin/io/tolgee/activity/propChangesProvider/DefaultPropChangesProvider.kt index b656066fa3..22caf78ade 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/propChangesProvider/DefaultPropChangesProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/propChangesProvider/DefaultPropChangesProvider.kt @@ -7,9 +7,12 @@ import org.springframework.stereotype.Component @Component class DefaultPropChangesProvider( - val entityDescriptionProvider: EntityDescriptionProvider + val entityDescriptionProvider: EntityDescriptionProvider, ) : PropChangesProvider { - override fun getChanges(old: Any?, new: Any?): PropertyModification? { + override fun getChanges( + old: Any?, + new: Any?, + ): PropertyModification? { if (old != new) { return PropertyModification(old.description, new.description) } diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/propChangesProvider/PropChangesProvider.kt b/backend/data/src/main/kotlin/io/tolgee/activity/propChangesProvider/PropChangesProvider.kt index abf2318207..c8e41e635f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/propChangesProvider/PropChangesProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/propChangesProvider/PropChangesProvider.kt @@ -3,7 +3,10 @@ package io.tolgee.activity.propChangesProvider import io.tolgee.activity.data.PropertyModification interface PropChangesProvider { - fun getChanges(old: Any?, new: Any?): PropertyModification? { + fun getChanges( + old: Any?, + new: Any?, + ): PropertyModification? { return null } } diff --git a/backend/data/src/main/kotlin/io/tolgee/activity/propChangesProvider/TagsPropChangesProvider.kt b/backend/data/src/main/kotlin/io/tolgee/activity/propChangesProvider/TagsPropChangesProvider.kt index 96b921aee4..b5b18c5f32 100644 --- a/backend/data/src/main/kotlin/io/tolgee/activity/propChangesProvider/TagsPropChangesProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/activity/propChangesProvider/TagsPropChangesProvider.kt @@ -6,8 +6,10 @@ import org.springframework.stereotype.Service @Service class TagsPropChangesProvider : PropChangesProvider { - - override fun getChanges(old: Any?, new: Any?): PropertyModification? { + override fun getChanges( + old: Any?, + new: Any?, + ): PropertyModification? { if (old is Collection<*> && new is Collection<*>) { if (old === new) { return null diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/BatchActivityParamsProvider.kt b/backend/data/src/main/kotlin/io/tolgee/batch/BatchActivityParamsProvider.kt index 8b946bfa83..2ebdbfe56c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/BatchActivityParamsProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/BatchActivityParamsProvider.kt @@ -6,14 +6,14 @@ import org.springframework.stereotype.Component @Component class BatchActivityParamsProvider( - private val entityManager: EntityManager + private val entityManager: EntityManager, ) : PublicParamsProvider { override fun provide(revisionIds: List): Map { return entityManager.createQuery( """select bj.activityRevision.id, bj.params from BatchJob bj where bj.activityRevision.id in :revisionIds """, - Array::class.java + Array::class.java, ).setParameter("revisionIds", revisionIds).resultList.associate { (it[0] as Long) to it[1] } } } diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobActionService.kt b/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobActionService.kt index ae70495d7e..168712a90f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobActionService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobActionService.kt @@ -47,7 +47,7 @@ class BatchJobActionService( private val savePointManager: SavePointManager, private val currentDateProvider: CurrentDateProvider, private val activityHolder: ActivityHolder, - private val metrics: Metrics + private val metrics: Metrics, ) : Logging { companion object { const val MIN_TIME_BETWEEN_OPERATIONS = 100 @@ -59,44 +59,46 @@ class BatchJobActionService( concurrentExecutionLauncher.run { executionItem, coroutineContext -> var retryExecution: BatchJobChunkExecution? = null try { - val execution = catchingExceptions(executionItem) { - executeInNewTransaction(transactionManager) { transactionStatus -> - - val lockedExecution = getPendingUnlockedExecutionItem(executionItem) - ?: return@executeInNewTransaction null - - publishRemoveConsuming(executionItem) - - progressManager.handleJobRunning(lockedExecution.batchJob.id) - val batchJobDto = batchJobService.getJobDto(lockedExecution.batchJob.id) - - logger.debug("Job ${batchJobDto.id}: 🟡 Processing chunk ${lockedExecution.id}") - val savepoint = savePointManager.setSavepoint() - val util = ChunkProcessingUtil(lockedExecution, applicationContext, coroutineContext) - util.processChunk() - - if (transactionStatus.isRollbackOnly) { - logger.debug("Job ${batchJobDto.id}: 🛑 Rollbacking chunk ${lockedExecution.id}") - savePointManager.rollbackSavepoint(savepoint) - // we have rolled back the transaction, so no targets were actually successfull - lockedExecution.successTargets = listOf() - entityManager.clear() - rollbackActivity() - } - - progressManager.handleProgress(lockedExecution) - entityManager.persist(entityManager.merge(lockedExecution)) - - if (lockedExecution.retry) { - retryExecution = util.retryExecution - entityManager.persist(util.retryExecution) - entityManager.flush() + val execution = + catchingExceptions(executionItem) { + executeInNewTransaction(transactionManager) { transactionStatus -> + + val lockedExecution = + getPendingUnlockedExecutionItem(executionItem) + ?: return@executeInNewTransaction null + + publishRemoveConsuming(executionItem) + + progressManager.handleJobRunning(lockedExecution.batchJob.id) + val batchJobDto = batchJobService.getJobDto(lockedExecution.batchJob.id) + + logger.debug("Job ${batchJobDto.id}: 🟡 Processing chunk ${lockedExecution.id}") + val savepoint = savePointManager.setSavepoint() + val util = ChunkProcessingUtil(lockedExecution, applicationContext, coroutineContext) + util.processChunk() + + if (transactionStatus.isRollbackOnly) { + logger.debug("Job ${batchJobDto.id}: 🛑 Rollbacking chunk ${lockedExecution.id}") + savePointManager.rollbackSavepoint(savepoint) + // we have rolled back the transaction, so no targets were actually successfull + lockedExecution.successTargets = listOf() + entityManager.clear() + rollbackActivity() + } + + progressManager.handleProgress(lockedExecution) + entityManager.persist(entityManager.merge(lockedExecution)) + + if (lockedExecution.retry) { + retryExecution = util.retryExecution + entityManager.persist(util.retryExecution) + entityManager.flush() + } + + logger.debug("Job ${batchJobDto.id}: ✅ Processed chunk ${lockedExecution.id}") + return@executeInNewTransaction lockedExecution } - - logger.debug("Job ${batchJobDto.id}: ✅ Processed chunk ${lockedExecution.id}") - return@executeInNewTransaction lockedExecution } - } execution?.let { logger.debug("Job: ${it.batchJob.id} - Handling execution committed ${it.id} (standard flow)") progressManager.handleChunkCompletedCommitted(it) @@ -108,7 +110,7 @@ class BatchJobActionService( is UnexpectedRollbackException -> { logger.debug( "Job ${executionItem.jobId}: ⚠️ Chunk ${executionItem.chunkExecutionId}" + - " thrown UnexpectedRollbackException" + " thrown UnexpectedRollbackException", ) } @@ -143,7 +145,10 @@ class BatchJobActionService( return lockedExecution } - private fun addRetryExecutionToQueue(retryExecution: BatchJobChunkExecution?, jobCharacter: JobCharacter) { + private fun addRetryExecutionToQueue( + retryExecution: BatchJobChunkExecution?, + jobCharacter: JobCharacter, + ) { retryExecution?.let { batchJobChunkExecutionQueue.addToQueue(it, jobCharacter) logger.debug("Job ${it.batchJob.id}: Added chunk ${it.id} for re-trial") @@ -152,7 +157,7 @@ class BatchJobActionService( private inline fun catchingExceptions( executionItem: ExecutionQueueItem, - fn: () -> T + fn: () -> T, ): T? { return try { fn() @@ -173,16 +178,20 @@ class BatchJobActionService( } } - private fun failExecution(chunkExecutionId: Long, e: Throwable) { - val execution = executeInNewTransaction(transactionManager) { - val execution = entityManager.find(BatchJobChunkExecution::class.java, chunkExecutionId) - execution.status = BatchJobChunkExecutionStatus.FAILED - execution.errorMessage = Message.EXECUTION_FAILED_ON_MANAGEMENT_ERROR - execution.stackTrace = e.stackTraceToString() - execution.errorKey = "management_error" - entityManager.persist(execution) - execution - } + private fun failExecution( + chunkExecutionId: Long, + e: Throwable, + ) { + val execution = + executeInNewTransaction(transactionManager) { + val execution = entityManager.find(BatchJobChunkExecution::class.java, chunkExecutionId) + execution.status = BatchJobChunkExecutionStatus.FAILED + execution.errorMessage = Message.EXECUTION_FAILED_ON_MANAGEMENT_ERROR + execution.stackTrace = e.stackTraceToString() + execution.errorKey = "management_error" + entityManager.persist(execution) + execution + } executeInNewTransaction(transactionManager) { progressManager.handleProgress(execution, failOnly = true) } @@ -191,8 +200,9 @@ class BatchJobActionService( fun publishRemoveConsuming(item: ExecutionQueueItem) { if (usingRedisProvider.areWeUsingRedis) { - val message = jacksonObjectMapper() - .writeValueAsString(JobQueueItemsEvent(listOf(item), QueueEventType.REMOVE)) + val message = + jacksonObjectMapper() + .writeValueAsString(JobQueueItemsEvent(listOf(item), QueueEventType.REMOVE)) redisTemplate.convertAndSend(RedisPubSubReceiverConfiguration.JOB_QUEUE_TOPIC, message) } } @@ -201,16 +211,16 @@ class BatchJobActionService( entityManager.createNativeQuery("""SET enable_seqscan=off""") return entityManager.createQuery( """ - from BatchJobChunkExecution bjce - where bjce.id = :id + from BatchJobChunkExecution bjce + where bjce.id = :id """.trimIndent(), - BatchJobChunkExecution::class.java + BatchJobChunkExecution::class.java, ) .setParameter("id", id) .setLockMode(LockModeType.PESSIMISTIC_WRITE) .setHint( "jakarta.persistence.lock.timeout", - LockOptions.SKIP_LOCKED + LockOptions.SKIP_LOCKED, ).resultList.singleOrNull() } diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobActivityFinalizer.kt b/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobActivityFinalizer.kt index 669ff6dd81..60f924ccca 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobActivityFinalizer.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobActivityFinalizer.kt @@ -68,17 +68,21 @@ class BatchJobActivityFinalizer( logger.debug("Committed chunks executions in this transaction: $committedInThisTransactions") retryWaitingWithBatchJobResetting(job.id) { - val committedChunks = batchJobStateProvider.get(job.id).values - .count { it.retry == false && it.transactionCommitted && it.status.completed } + val committedChunks = + batchJobStateProvider.get(job.id).values + .count { it.retry == false && it.transactionCommitted && it.status.completed } logger.debug( "Waiting for completed chunks and committed ($committedChunks) to be equal to all other chunks" + - " count (${job.totalChunks - committedInThisTransactions})" + " count (${job.totalChunks - committedInThisTransactions})", ) committedChunks == job.totalChunks - committedInThisTransactions } } - private fun retryWaitingWithBatchJobResetting(jobId: Long, fn: () -> Boolean) { + private fun retryWaitingWithBatchJobResetting( + jobId: Long, + fn: () -> Boolean, + ) { waitForNotThrowing(WaitNotSatisfiedException::class) { try { waitFor(2000) { @@ -91,7 +95,10 @@ class BatchJobActivityFinalizer( } } - private fun setJobIdAndAuthorIdToRevision(activityRevisionIdToMergeInto: Long, job: BatchJobDto) { + private fun setJobIdAndAuthorIdToRevision( + activityRevisionIdToMergeInto: Long, + job: BatchJobDto, + ) { entityManager.createNativeQuery( """ update activity_revision @@ -100,7 +107,7 @@ class BatchJobActivityFinalizer( batch_job_id = :jobId, author_id = :authorId where id = :activityRevisionIdToMergeInto - """ + """, ) .setParameter("activityRevisionIdToMergeInto", activityRevisionIdToMergeInto) .setParameter("jobId", job.id) @@ -112,7 +119,7 @@ class BatchJobActivityFinalizer( entityManager.createNativeQuery( """ delete from activity_revision where id in (:revisionIds) - """ + """, ) .setParameter("revisionIds", revisionIds) .executeUpdate() @@ -120,13 +127,13 @@ class BatchJobActivityFinalizer( private fun mergeModifiedEntities( activityRevisionIdToMergeInto: Long, - revisionIds: MutableList + revisionIds: MutableList, ) { entityManager.createNativeQuery( """ update activity_modified_entity set activity_revision_id = :activityRevisionIdToMergeInto where activity_revision_id in (:revisionIds) - """ + """, ) .setParameter("activityRevisionIdToMergeInto", activityRevisionIdToMergeInto) .setParameter("revisionIds", revisionIds) @@ -135,7 +142,7 @@ class BatchJobActivityFinalizer( private fun mergeDescribingEntities( activityRevisionIdToMergeInto: Long, - revisionIds: MutableList + revisionIds: MutableList, ) { removeDuplicityDescribingEntities(activityRevisionIdToMergeInto, revisionIds) @@ -143,7 +150,7 @@ class BatchJobActivityFinalizer( """ update activity_describing_entity set activity_revision_id = :activityRevisionIdToMergeInto where activity_revision_id in (:revisionIds) - """ + """, ) .setParameter("activityRevisionIdToMergeInto", activityRevisionIdToMergeInto) .setParameter("revisionIds", revisionIds) @@ -152,42 +159,43 @@ class BatchJobActivityFinalizer( private fun removeDuplicityDescribingEntities( activityRevisionIdToMergeInto: Long, - revisionIds: MutableList + revisionIds: MutableList, ) { entityManager.createNativeQuery( """ - delete from activity_describing_entity - where (entity_class, entity_id) in - (select entity_class, entity_id - from activity_describing_entity - where activity_revision_id in (:revisionIds) + delete from activity_describing_entity + where (entity_class, entity_id) in + (select entity_class, entity_id + from activity_describing_entity + where activity_revision_id in (:revisionIds) + or activity_revision_id = :activityRevisionIdToMergeInto + group by entity_class, entity_id + having count(*) > 1) + and + (activity_revision_id, entity_class, entity_id) not in ( + select min(activity_revision_id), entity_class, entity_id + from activity_describing_entity + where activity_revision_id in (:revisionIds) or activity_revision_id = :activityRevisionIdToMergeInto - group by entity_class, entity_id - having count(*) > 1) - and - (activity_revision_id, entity_class, entity_id) not in ( - select min(activity_revision_id), entity_class, entity_id - from activity_describing_entity - where activity_revision_id in (:revisionIds) - or activity_revision_id = :activityRevisionIdToMergeInto - group by entity_class, entity_id - having count(*) > 1) - """.trimIndent() + group by entity_class, entity_id + having count(*) > 1) + """.trimIndent(), ) .setParameter("activityRevisionIdToMergeInto", activityRevisionIdToMergeInto) .setParameter("revisionIds", revisionIds) .executeUpdate() } - private fun getRevisionIds(jobId: Long): MutableList = entityManager.createQuery( - """ + private fun getRevisionIds(jobId: Long): MutableList = + entityManager.createQuery( + """ select ar.id from ActivityRevision ar join ar.batchJobChunkExecution b where b.batchJob.id = :jobId """, - Long::class.javaObjectType - ) - .setParameter("jobId", jobId) - .resultList + Long::class.javaObjectType, + ) + .setParameter("jobId", jobId) + .resultList } diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobCancellationManager.kt b/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobCancellationManager.kt index f40dd10c4d..75a8eb7a47 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobCancellationManager.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobCancellationManager.kt @@ -29,7 +29,7 @@ class BatchJobCancellationManager( private val transactionManager: PlatformTransactionManager, private val batchJobActionService: BatchJobActionService, private val progressManager: ProgressManager, - private val activityHolder: ActivityHolder + private val activityHolder: ActivityHolder, ) : Logging { @Transactional fun cancel(id: Long) { @@ -47,7 +47,7 @@ class BatchJobCancellationManager( if (usingRedisProvider.areWeUsingRedis) { redisTemplate.convertAndSend( RedisPubSubReceiverConfiguration.JOB_CANCEL_TOPIC, - jacksonObjectMapper().writeValueAsString(id) + jacksonObjectMapper().writeValueAsString(id), ) return } @@ -60,36 +60,38 @@ class BatchJobCancellationManager( } fun cancelJob(jobId: Long) { - val executions = executeInNewTransaction(transactionManager) { - entityManager.createNativeQuery("""SET enable_seqscan=off""") - val executions = entityManager.createQuery( - """ + val executions = + executeInNewTransaction(transactionManager) { + entityManager.createNativeQuery("""SET enable_seqscan=off""") + val executions = + entityManager.createQuery( + """ from BatchJobChunkExecution bjce where bjce.batchJob.id = :id and status = :status """, - BatchJobChunkExecution::class.java - ) - .setLockMode(LockModeType.PESSIMISTIC_WRITE) - .setHint( - "jakarta.persistence.lock.timeout", - LockOptions.SKIP_LOCKED - ) - .setParameter("id", jobId) - .setParameter("status", BatchJobChunkExecutionStatus.PENDING) - .resultList + BatchJobChunkExecution::class.java, + ) + .setLockMode(LockModeType.PESSIMISTIC_WRITE) + .setHint( + "jakarta.persistence.lock.timeout", + LockOptions.SKIP_LOCKED, + ) + .setParameter("id", jobId) + .setParameter("status", BatchJobChunkExecutionStatus.PENDING) + .resultList - executions.forEach { execution -> - cancelExecution(execution) - } + executions.forEach { execution -> + cancelExecution(execution) + } - logger.debug( - "Cancelling job $jobId, cancelling locked execution ids: ${ - executions.map { it.id }.joinToString(", ") - }" - ) - executions - } + logger.debug( + "Cancelling job $jobId, cancelling locked execution ids: ${ + executions.map { it.id }.joinToString(", ") + }", + ) + executions + } logger.debug("""Job $jobId cancellation committed. setting transaction committed for the executions.""") executions.forEach { progressManager.handleChunkCompletedCommitted(it, false) diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobChunkExecutionQueue.kt b/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobChunkExecutionQueue.kt index 5b9ae11c65..6a53cede35 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobChunkExecutionQueue.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobChunkExecutionQueue.kt @@ -29,7 +29,7 @@ class BatchJobChunkExecutionQueue( private val usingRedisProvider: UsingRedisProvider, @Lazy private val redisTemplate: StringRedisTemplate, - private val metrics: Metrics + private val metrics: Metrics, ) : Logging, InitializingBean { companion object { /** @@ -54,20 +54,21 @@ class BatchJobChunkExecutionQueue( @Scheduled(fixedDelay = 60000) fun populateQueue() { logger.debug("Running scheduled populate queue") - val data = entityManager.createQuery( - """ - select new io.tolgee.batch.data.BatchJobChunkExecutionDto(bjce.id, bk.id, bjce.executeAfter, bk.jobCharacter) - from BatchJobChunkExecution bjce - join bjce.batchJob bk - where bjce.status = :executionStatus - order by bjce.createdAt asc, bjce.executeAfter asc, bjce.id asc - """.trimIndent(), - BatchJobChunkExecutionDto::class.java - ).setParameter("executionStatus", BatchJobChunkExecutionStatus.PENDING) - .setHint( - "jakarta.persistence.lock.timeout", - LockOptions.SKIP_LOCKED - ).resultList + val data = + entityManager.createQuery( + """ + select new io.tolgee.batch.data.BatchJobChunkExecutionDto(bjce.id, bk.id, bjce.executeAfter, bk.jobCharacter) + from BatchJobChunkExecution bjce + join bjce.batchJob bk + where bjce.status = :executionStatus + order by bjce.createdAt asc, bjce.executeAfter asc, bjce.id asc + """.trimIndent(), + BatchJobChunkExecutionDto::class.java, + ).setParameter("executionStatus", BatchJobChunkExecutionStatus.PENDING) + .setHint( + "jakarta.persistence.lock.timeout", + LockOptions.SKIP_LOCKED, + ).resultList if (data.size > 0) { logger.debug("Attempt to add ${data.size} items to queue ${System.identityHashCode(this)}") @@ -96,7 +97,10 @@ class BatchJobChunkExecutionQueue( } } - fun addToQueue(execution: BatchJobChunkExecution, jobCharacter: JobCharacter) { + fun addToQueue( + execution: BatchJobChunkExecution, + jobCharacter: JobCharacter, + ) { val item = execution.toItem(jobCharacter) addItemsToQueue(listOf(item)) } @@ -111,7 +115,7 @@ class BatchJobChunkExecutionQueue( val event = JobQueueItemsEvent(items, QueueEventType.ADD) redisTemplate.convertAndSend( RedisPubSubReceiverConfiguration.JOB_QUEUE_TOPIC, - jacksonObjectMapper().writeValueAsString(event) + jacksonObjectMapper().writeValueAsString(event), ) return } @@ -129,7 +133,7 @@ class BatchJobChunkExecutionQueue( // Yes. jobCharacter is part of the batchJob entity. // However, we don't want to fetch it here, because it would be a waste of resources. // So we can provide the jobCharacter here. - jobCharacter: JobCharacter? = null + jobCharacter: JobCharacter? = null, ) = ExecutionQueueItem(id, batchJob.id, executeAfter?.time, jobCharacter ?: batchJob.jobCharacter) @@ -138,8 +142,10 @@ class BatchJobChunkExecutionQueue( val size get() = queue.size - fun joinToString(separator: String = ", ", transform: (item: ExecutionQueueItem) -> String) = - queue.joinToString(separator, transform = transform) + fun joinToString( + separator: String = ", ", + transform: (item: ExecutionQueueItem) -> String, + ) = queue.joinToString(separator, transform = transform) fun poll(): ExecutionQueueItem? { return queue.poll() @@ -154,9 +160,11 @@ class BatchJobChunkExecutionQueue( } fun peek(): ExecutionQueueItem = queue.peek() + fun contains(item: ExecutionQueueItem?): Boolean = queue.contains(item) fun isEmpty(): Boolean = queue.isEmpty() + fun getJobCharacterCounts(): Map { return queue.groupBy { it.jobCharacter }.map { it.key to it.value.size }.toMap() } diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobConcurrentLauncher.kt b/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobConcurrentLauncher.kt index b6cb79524d..7516fa1ef0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobConcurrentLauncher.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobConcurrentLauncher.kt @@ -91,7 +91,10 @@ class BatchJobConcurrentLauncher( } } - private fun getSleepTime(startTime: Long, somethingHandled: Boolean): Long { + private fun getSleepTime( + startTime: Long, + somethingHandled: Boolean, + ): Long { if (!batchJobChunkExecutionQueue.isEmpty() && jobsToLaunch > 0 && somethingHandled) { return 0 } @@ -100,41 +103,43 @@ class BatchJobConcurrentLauncher( fun run(processExecution: (executionItem: ExecutionQueueItem, coroutineContext: CoroutineContext) -> Unit) { @Suppress("OPT_IN_USAGE") - masterRunJob = GlobalScope.launch(Dispatchers.IO) { - repeatForever { - if (pause) { - return@repeatForever false - } + masterRunJob = + GlobalScope.launch(Dispatchers.IO) { + repeatForever { + if (pause) { + return@repeatForever false + } - val jobsToLaunch = jobsToLaunch - if (jobsToLaunch <= 0) { - return@repeatForever false - } + val jobsToLaunch = jobsToLaunch + if (jobsToLaunch <= 0) { + return@repeatForever false + } - logger.trace("Jobs to launch: $jobsToLaunch") - val items = (1..jobsToLaunch) - .mapNotNull { batchJobChunkExecutionQueue.poll() } + logger.trace("Jobs to launch: $jobsToLaunch") + val items = + (1..jobsToLaunch) + .mapNotNull { batchJobChunkExecutionQueue.poll() } - logItemsPulled(items) + logItemsPulled(items) - // when something handled, return true - items.map { executionItem -> - handleItem(executionItem, processExecution) - }.any() + // when something handled, return true + items.map { executionItem -> + handleItem(executionItem, processExecution) + }.any() + } } - } } private fun logItemsPulled(items: List) { if (items.isNotEmpty()) { logger.trace( "Pulled ${items.size} items from queue: " + - items.joinToString(", ") { it.chunkExecutionId.toString() } + items.joinToString(", ") { it.chunkExecutionId.toString() }, ) logger.trace( "${batchJobChunkExecutionQueue.size} is left in the queue " + "(${System.identityHashCode(batchJobChunkExecutionQueue)}): " + - batchJobChunkExecutionQueue.joinToString(", ") { it.chunkExecutionId.toString() } + batchJobChunkExecutionQueue.joinToString(", ") { it.chunkExecutionId.toString() }, ) } } @@ -144,7 +149,7 @@ class BatchJobConcurrentLauncher( */ private fun CoroutineScope.handleItem( executionItem: ExecutionQueueItem, - processExecution: (executionItem: ExecutionQueueItem, coroutineContext: CoroutineContext) -> Unit + processExecution: (executionItem: ExecutionQueueItem, coroutineContext: CoroutineContext) -> Unit, ): Boolean { logger.trace("Trying to run execution ${executionItem.chunkExecutionId}") if (!executionItem.isTimeToExecute()) { @@ -157,7 +162,7 @@ class BatchJobConcurrentLauncher( } if (!executionItem.shouldNotBeDebounced()) { logger.trace( - """Execution ${executionItem.chunkExecutionId} not ready to execute (debouncing), adding back to queue""" + """Execution ${executionItem.chunkExecutionId} not ready to execute (debouncing), adding back to queue""", ) addBackToQueue(executionItem) return false @@ -165,7 +170,8 @@ class BatchJobConcurrentLauncher( if (!canRunJobWithCharacter(executionItem.jobCharacter)) { logger.trace( """Execution ${executionItem.chunkExecutionId} cannot run concurrent job - |(there are already max coroutines working on this specific job)""".trimMargin() + |(there are already max coroutines working on this specific job) + """.trimMargin(), ) addBackToQueue(executionItem) return false @@ -174,7 +180,8 @@ class BatchJobConcurrentLauncher( if (!executionItem.trySetRunningState()) { logger.trace( """Execution ${executionItem.chunkExecutionId} cannot run concurrent job - |(there are already max concurrent executions running of this specific job)""".trimMargin() + |(there are already max concurrent executions running of this specific job) + """.trimMargin(), ) addBackToQueue(executionItem) return false @@ -186,7 +193,7 @@ class BatchJobConcurrentLauncher( if (!batchJobProjectLockingManager.canLockJobForProject(executionItem.jobId)) { logger.debug( "⚠️ Cannot run execution ${executionItem.chunkExecutionId}. " + - "Other job from the project is currently running, skipping" + "Other job from the project is currently running, skipping", ) // we haven't publish consuming, so we can add it only to the local queue @@ -194,15 +201,16 @@ class BatchJobConcurrentLauncher( listOf( executionItem.also { it.executeAfter = currentDateProvider.date.time + 1000 - } - ) + }, + ), ) return false } - val job = launch { - processExecution(executionItem, this.coroutineContext) - } + val job = + launch { + processExecution(executionItem, this.coroutineContext) + } val batchJobDto = batchJobService.getJobDto(executionItem.jobId) runningJobs[executionItem.chunkExecutionId] = batchJobDto to job @@ -241,7 +249,7 @@ class BatchJobConcurrentLauncher( logger.debug( "Debouncing duration reached for job ${dto.id}, " + "execute after $executeAfter, " + - "now ${currentDateProvider.date.time}" + "now ${currentDateProvider.date.time}", ) return true } diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobProjectLockingManager.kt b/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobProjectLockingManager.kt index c9d6f0be0c..271e777388 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobProjectLockingManager.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobProjectLockingManager.kt @@ -46,7 +46,10 @@ class BatchJobProjectLockingManager( } } - fun unlockJobForProject(projectId: Long, jobId: Long) { + fun unlockJobForProject( + projectId: Long, + jobId: Long, + ) { getMap().compute(projectId) { _, lockedJobId -> logger.debug("Unlocking job: $jobId for project $projectId") if (lockedJobId == jobId) { @@ -66,9 +69,10 @@ class BatchJobProjectLockingManager( } private fun tryLockWithRedisson(batchJobDto: BatchJobDto): Boolean { - val computed = getRedissonProjectLocks().compute(batchJobDto.projectId) { _, value -> - computeFnBody(batchJobDto, value) - } + val computed = + getRedissonProjectLocks().compute(batchJobDto.projectId) { _, value -> + computeFnBody(batchJobDto, value) + } return computed == batchJobDto.id } @@ -80,15 +84,19 @@ class BatchJobProjectLockingManager( } private fun tryLockLocal(toLock: BatchJobDto): Boolean { - val computed = localProjectLocks.compute(toLock.projectId) { _, value -> - val newLocked = computeFnBody(toLock, value) - logger.debug("While trying to lock ${toLock.id} for project ${toLock.projectId} new lock value is $newLocked") - newLocked - } + val computed = + localProjectLocks.compute(toLock.projectId) { _, value -> + val newLocked = computeFnBody(toLock, value) + logger.debug("While trying to lock ${toLock.id} for project ${toLock.projectId} new lock value is $newLocked") + newLocked + } return computed == toLock.id } - private fun computeFnBody(toLock: BatchJobDto, currentValue: Long?): Long { + private fun computeFnBody( + toLock: BatchJobDto, + currentValue: Long?, + ): Long { // nothing is locked if (currentValue == 0L) { logger.debug("Locking job ${toLock.id} for project ${toLock.projectId}, nothing is locked") @@ -117,9 +125,10 @@ class BatchJobProjectLockingManager( private fun getInitialJobId(projectId: Long): Long? { val jobs = batchJobService.getAllIncompleteJobIds(projectId) - val unlockedChunkCounts = batchJobService - .getAllUnlockedChunksForJobs(jobs.map { it.jobId }) - .groupBy { it.batchJobId }.map { it.key to it.value.count() }.toMap() + val unlockedChunkCounts = + batchJobService + .getAllUnlockedChunksForJobs(jobs.map { it.jobId }) + .groupBy { it.batchJobId }.map { it.key to it.value.count() }.toMap() // we are looking for a job that has already started and preferably for a locked one return jobs.find { it.totalChunks != unlockedChunkCounts[it.jobId] }?.jobId ?: jobs.firstOrNull()?.jobId } diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobService.kt b/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobService.kt index 0f643188c5..c96e6bdf6f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/BatchJobService.kt @@ -59,9 +59,8 @@ class BatchJobService( private val securityService: SecurityService, private val authenticationFacade: AuthenticationFacade, private val objectMapper: ObjectMapper, - private val jdbcTemplate: JdbcTemplate + private val jdbcTemplate: JdbcTemplate, ) : Logging { - companion object { private const val DEBOUNCE_MAX_WAITING_TIME_MULTIPLIER = 4 } @@ -73,7 +72,7 @@ class BatchJobService( author: UserAccount?, type: BatchJobType, isHidden: Boolean = false, - debounceDuration: Duration? = null + debounceDuration: Duration? = null, ): BatchJob { val processor = getProcessor(type) val target = processor.getTarget(request) @@ -86,20 +85,21 @@ class BatchJobService( } } - val job = BatchJob().apply { - this.project = project - this.author = author - this.target = target - this.totalItems = target.size - this.chunkSize = processor.getChunkSize(projectId = project.id, request = request) - this.jobCharacter = processor.getJobCharacter() - this.maxPerJobConcurrency = processor.getMaxPerJobConcurrency() - this.type = type - this.hidden = isHidden - this.debounceDurationInMs = debounceDuration?.toMillis() - this.debounceMaxWaitTimeInMs = debounceDuration?.let { it.toMillis() * DEBOUNCE_MAX_WAITING_TIME_MULTIPLIER } - this.debouncingKey = debouncingKey - } + val job = + BatchJob().apply { + this.project = project + this.author = author + this.target = target + this.totalItems = target.size + this.chunkSize = processor.getChunkSize(projectId = project.id, request = request) + this.jobCharacter = processor.getJobCharacter() + this.maxPerJobConcurrency = processor.getMaxPerJobConcurrency() + this.type = type + this.hidden = isHidden + this.debounceDurationInMs = debounceDuration?.toMillis() + this.debounceMaxWaitTimeInMs = debounceDuration?.let { it.toMillis() * DEBOUNCE_MAX_WAITING_TIME_MULTIPLIER } + this.debouncingKey = debouncingKey + } val chunked = job.chunkedTarget job.totalChunks = chunked.size @@ -118,14 +118,15 @@ class BatchJobService( private fun storeExecutions( chunked: List>, - job: BatchJob + job: BatchJob, ): List { - val executions = List(chunked.size) { chunkNumber -> - BatchJobChunkExecution().apply { - batchJob = job - this.chunkNumber = chunkNumber + val executions = + List(chunked.size) { chunkNumber -> + BatchJobChunkExecution().apply { + batchJob = job + this.chunkNumber = chunkNumber + } } - } insertExecutionsViaBatchStatement(executions) @@ -143,7 +144,7 @@ class BatchJobService( values (?, ?, ?, ?, ?, ?, ?) """, executions, - 100 + 100, ) { ps, execution -> val id = sequenceIdProvider.next(ps.connection) execution.id = id @@ -158,14 +159,14 @@ class BatchJobService( PGobject().apply { type = "jsonb" value = objectMapper.writeValueAsString(execution.successTargets) - } + }, ) } } private fun tryDebounceJob( debouncingKey: String?, - debounceDuration: Duration? + debounceDuration: Duration?, ): BatchJob? { debouncingKey ?: return null val job = batchJobRepository.findBatchJobByDebouncingKey(debouncingKey) ?: return null @@ -179,7 +180,7 @@ class BatchJobService( type: BatchJobType, project: Project, target: List, - request: Any + request: Any, ): String? { val debouncingKeyJson = jacksonObjectMapper().writeValueAsString(listOf(type, project.id, target, request)) return sha256Hex(debouncingKeyJson) @@ -193,10 +194,10 @@ class BatchJobService( executions.let { batchJobChunkExecutionQueue.addToQueue(it) } logger.debug( "Starting job ${job.id}, aadded ${executions.size} executions to queue ${ - System.identityHashCode( - batchJobChunkExecutionQueue - ) - }" + System.identityHashCode( + batchJobChunkExecutionQueue, + ) + }", ) } @@ -216,7 +217,11 @@ class BatchJobService( return this.findJobDto(id) ?: throw NotFoundException(Message.BATCH_JOB_NOT_FOUND) } - fun getViews(projectId: Long, userAccount: UserAccountDto?, pageable: Pageable): Page { + fun getViews( + projectId: Long, + userAccount: UserAccountDto?, + pageable: Pageable, + ): Page { val jobs = batchJobRepository.getJobs(projectId, userAccount?.id, pageable) val progresses = getProgresses(jobs) @@ -228,12 +233,13 @@ class BatchJobService( } fun getCurrentJobViews(projectId: Long): List { - val jobs: List = batchJobRepository.getCurrentJobs( - projectId, - userAccountId = getUserAccountIdForCurrentJobView(projectId), - oneHourAgo = currentDateProvider.date.addMinutes(-60), - completedStatuses = BatchJobStatus.entries.filter { it.completed } - ) + val jobs: List = + batchJobRepository.getCurrentJobs( + projectId, + userAccountId = getUserAccountIdForCurrentJobView(projectId), + oneHourAgo = currentDateProvider.date.addMinutes(-60), + completedStatuses = BatchJobStatus.entries.filter { it.completed }, + ) val progresses = getProgresses(jobs) val errorMessages = getErrorMessages(jobs) @@ -247,7 +253,6 @@ class BatchJobService( * Returns user account id if user has no permission to view all jobs. */ private fun getUserAccountIdForCurrentJobView(projectId: Long): Long? { - return try { securityService.checkProjectPermission(projectId, Scope.BATCH_JOBS_VIEW) null @@ -271,14 +276,16 @@ class BatchJobService( val cachedProgresses = jobs.associate { it.id to - if (it.status == BatchJobStatus.RUNNING) + if (it.status == BatchJobStatus.RUNNING) { progressManager.getJobCachedProgress(jobId = it.id) - else + } else { null + } } val needsProgress = cachedProgresses.filter { it.value == null }.map { it.key }.toList() - val progresses = batchJobRepository.getProgresses(needsProgress) - .associate { it[0] as Long to it[1] as Long } + val progresses = + batchJobRepository.getProgresses(needsProgress) + .associate { it[0] as Long to it[1] as Long } return jobs.associate { it.id to (cachedProgresses[it.id] ?: progresses[it.id] ?: 0).toInt() } } @@ -301,12 +308,12 @@ class BatchJobService( from BatchJobChunkExecution bjce where bjce.batchJob.id in :jobIds """, - JobUnlockedChunk::class.java + JobUnlockedChunk::class.java, ) .setParameter("jobIds", jobIds) .setHint( "jakarta.persistence.lock.timeout", - LockOptions.SKIP_LOCKED + LockOptions.SKIP_LOCKED, ).resultList } @@ -327,17 +334,20 @@ class BatchJobService( entityManager.createQuery( """ delete from BatchJobChunkExecution e where e.id in :executionIds - """.trimIndent() + """.trimIndent(), ).setParameter("executionIds", executions.map { it.id }) .executeUpdate() } - private fun setActivityRevisionFieldsToNull(batchJobIds: List, executionIds: List) { + private fun setActivityRevisionFieldsToNull( + batchJobIds: List, + executionIds: List, + ) { entityManager.createQuery( """ update ActivityRevision ar set ar.batchJob = null, ar.batchJobChunkExecution = null where ar.batchJob.id in :batchJobIds or ar.batchJobChunkExecution.id in :executionIds - """.trimIndent() + """.trimIndent(), ).setParameter("batchJobIds", batchJobIds) .setParameter("executionIds", executionIds) .executeUpdate() @@ -349,7 +359,7 @@ class BatchJobService( from BatchJobChunkExecution e where e.batchJob.id in :jobIds """.trimIndent(), - BatchJobChunkExecution::class.java + BatchJobChunkExecution::class.java, ) .setParameter("jobIds", jobIds) .resultList @@ -365,7 +375,7 @@ class BatchJobService( from BatchJobChunkExecution e where e.batchJob.id = :id """.trimIndent(), - BatchJobChunkExecution::class.java + BatchJobChunkExecution::class.java, ) .setParameter("id", batchJobId) .resultList @@ -377,7 +387,7 @@ class BatchJobService( where j.project.id = :projectId and j.status not in :completedStatuses """, - AllIncompleteJobsResult::class.java + AllIncompleteJobsResult::class.java, ) .setParameter("projectId", projectId) .setParameter("completedStatuses", BatchJobStatus.entries.filter { it.completed }) @@ -390,14 +400,16 @@ class BatchJobService( join fetch bjce.batchJob bk where bjce.id = :id """, - BatchJobChunkExecution::class.java + BatchJobChunkExecution::class.java, ) .setParameter("id", id) .singleResult ?: throw NotFoundException() } - fun getJobsCompletedBefore(lockedJobIds: Iterable, before: Date): List = - batchJobRepository.getCompletedJobs(lockedJobIds, before) + fun getJobsCompletedBefore( + lockedJobIds: Iterable, + before: Date, + ): List = batchJobRepository.getCompletedJobs(lockedJobIds, before) fun getStuckJobIds(jobIds: MutableSet): List { return batchJobRepository.getStuckJobIds(jobIds, currentDateProvider.date.addMinutes(-2)) diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/CachingBatchJobService.kt b/backend/data/src/main/kotlin/io/tolgee/batch/CachingBatchJobService.kt index 588832759f..b00abb1d7f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/CachingBatchJobService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/CachingBatchJobService.kt @@ -19,13 +19,12 @@ class CachingBatchJobService( private val batchJobRepository: BatchJobRepository, @Lazy private val batchJobService: BatchJobService, - private val entityManager: EntityManager + private val entityManager: EntityManager, ) : Logging { - @Transactional @CacheEvict( cacheNames = [Caches.BATCH_JOBS], - key = "#result.id" + key = "#result.id", ) fun saveJob(batchJob: BatchJob): BatchJob { logger.debug("Saving job ${batchJob.id}, status: ${batchJob.status}") @@ -35,7 +34,7 @@ class CachingBatchJobService( @Transactional @CacheEvict( cacheNames = [Caches.BATCH_JOBS], - key = "#jobId" + key = "#jobId", ) fun setRunningState(jobId: Long) { logger.debug("Setting running state for job $jobId") @@ -48,7 +47,7 @@ class CachingBatchJobService( @Cacheable( cacheNames = [Caches.BATCH_JOBS], - key = "#id" + key = "#id", ) fun findJobDto(id: Long): BatchJobDto? { val entity = batchJobService.findJobEntity(id) ?: return null @@ -58,7 +57,7 @@ class CachingBatchJobService( @CacheEvict( cacheNames = [Caches.BATCH_JOBS], - key = "#jobId" + key = "#jobId", ) fun evictJobCache(jobId: Long) { } diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/ChunkProcessingUtil.kt b/backend/data/src/main/kotlin/io/tolgee/batch/ChunkProcessingUtil.kt index 916851c7fe..5346568876 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/ChunkProcessingUtil.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/ChunkProcessingUtil.kt @@ -27,24 +27,25 @@ open class ChunkProcessingUtil( private val coroutineContext: CoroutineContext, ) : Logging { open fun processChunk() { - val time = measureTimeMillis { - handleActivity() - try { - processor.process(job, toProcess, coroutineContext) { - if (it != toProcess.size) { - progressManager.publishSingleChunkProgress(job.id, it) + val time = + measureTimeMillis { + handleActivity() + try { + processor.process(job, toProcess, coroutineContext) { + if (it != toProcess.size) { + progressManager.publishSingleChunkProgress(job.id, it) + } + } + successfulTargets = toProcess + execution.status = BatchJobChunkExecutionStatus.SUCCESS + } catch (e: Throwable) { + handleException(e) + } finally { + successfulTargets?.let { + execution.successTargets = it } - } - successfulTargets = toProcess - execution.status = BatchJobChunkExecutionStatus.SUCCESS - } catch (e: Throwable) { - handleException(e) - } finally { - successfulTargets?.let { - execution.successTargets = it } } - } logger.debug("Chunk ${execution.id} executed in ${time}ms") } @@ -83,9 +84,11 @@ open class ChunkProcessingUtil( } private fun logException(exception: Throwable) { - val knownCauses = listOf( - OutOfCreditsException::class.java, TranslationApiRateLimitException::class.java - ) + val knownCauses = + listOf( + OutOfCreditsException::class.java, + TranslationApiRateLimitException::class.java, + ) val isKnownCause = knownCauses.any { ExceptionUtils.indexOfType(exception, it) > -1 } if (!isKnownCause) { @@ -105,7 +108,7 @@ open class ChunkProcessingUtil( logger.debug( "Total retries ${retries.values.sum()}, " + - "retries for error key: $errorKeyRetries, max retries $maxRetries" + "retries for error key: $errorKeyRetries, max retries $maxRetries", ) if (errorKeyRetries >= maxRetries && maxRetries != -1) { logger.debug("Max retries reached for job execution ${execution.id}") @@ -206,14 +209,14 @@ open class ChunkProcessingUtil( where chunkNumber = :chunkNumber and batchJob.id = :batchJobId and status = :status - """.trimIndent() + """.trimIndent(), ) .setParameter("chunkNumber", execution.chunkNumber) .setParameter("batchJobId", job.id) .setParameter("status", BatchJobChunkExecutionStatus.FAILED) .setHint( "jakarta.persistence.lock.timeout", - LockOptions.NO_WAIT + LockOptions.NO_WAIT, ) .resultList as List } diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/ChunkProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/batch/ChunkProcessor.kt index b951278019..97a7fd3629 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/ChunkProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/ChunkProcessor.kt @@ -9,10 +9,11 @@ interface ChunkProcessor { job: BatchJobDto, chunk: List, coroutineContext: CoroutineContext, - onProgress: ((Int) -> Unit) + onProgress: ((Int) -> Unit), ) fun getTarget(data: RequestType): List + fun getParams(data: RequestType): ParamsType fun getParams(job: BatchJobDto): ParamsType { @@ -27,7 +28,10 @@ interface ChunkProcessor { return JobCharacter.FAST } - fun getChunkSize(request: RequestType, projectId: Long): Int { + fun getChunkSize( + request: RequestType, + projectId: Long, + ): Int { return 0 } diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/JobCharacter.kt b/backend/data/src/main/kotlin/io/tolgee/batch/JobCharacter.kt index f6cbe32cb7..5523321949 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/JobCharacter.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/JobCharacter.kt @@ -8,5 +8,5 @@ enum class JobCharacter( val maxConcurrencyRatio: Double, ) { SLOW(0.2), - FAST(0.8) + FAST(0.8), } diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/ProgressManager.kt b/backend/data/src/main/kotlin/io/tolgee/batch/ProgressManager.kt index 3bb71e5cfa..b21f746433 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/ProgressManager.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/ProgressManager.kt @@ -29,9 +29,8 @@ class ProgressManager( private val batchJobStateProvider: BatchJobStateProvider, private val cachingBatchJobService: CachingBatchJobService, private val batchJobProjectLockingManager: BatchJobProjectLockingManager, - private val queue: BatchJobChunkExecutionQueue + private val queue: BatchJobChunkExecutionQueue, ) : Logging { - /** * This method tries to set execution running in the state * @param canRunFn function that returns true if execution can be run @@ -39,7 +38,7 @@ class ProgressManager( fun trySetExecutionRunning( executionId: Long, batchJobId: Long, - canRunFn: (Map) -> Boolean + canRunFn: (Map) -> Boolean, ): Boolean { return batchJobStateProvider.updateState(batchJobId) { if (canRunFn(it)) { @@ -52,7 +51,7 @@ class ProgressManager( status = BatchJobChunkExecutionStatus.RUNNING, chunkNumber = null, retry = null, - transactionCommitted = false + transactionCommitted = false, ) return@updateState true } @@ -75,13 +74,17 @@ class ProgressManager( } } - fun handleProgress(execution: BatchJobChunkExecution, failOnly: Boolean = false) { + fun handleProgress( + execution: BatchJobChunkExecution, + failOnly: Boolean = false, + ) { val job = batchJobService.getJobDto(execution.batchJob.id) - val info = batchJobStateProvider.updateState(job.id) { - it[execution.id] = batchJobStateProvider.getStateForExecution(execution) - it.getInfoForJobResult() - } + val info = + batchJobStateProvider.updateState(job.id) { + it[execution.id] = batchJobStateProvider.getStateForExecution(execution) + it.getInfoForJobResult() + } if (execution.successTargets.isNotEmpty()) { eventPublisher.publishEvent(OnBatchJobProgress(job, info.progress, job.totalItems.toLong())) @@ -93,20 +96,24 @@ class ProgressManager( isAnyCancelled = info.isAnyCancelled, completedChunks = info.completedChunks, errorMessage = execution.errorMessage, - failOnly = failOnly + failOnly = failOnly, ) } - fun handleChunkCompletedCommitted(execution: BatchJobChunkExecution, triggerJobCompleted: Boolean = true) { - val state = batchJobStateProvider.updateState(execution.batchJob.id) { - logger.debug("Setting transaction committed for chunk execution ${execution.id} to true") - it.compute(execution.id) { _, v -> - val state = batchJobStateProvider.getStateForExecution(execution) - state.transactionCommitted = true - state + fun handleChunkCompletedCommitted( + execution: BatchJobChunkExecution, + triggerJobCompleted: Boolean = true, + ) { + val state = + batchJobStateProvider.updateState(execution.batchJob.id) { + logger.debug("Setting transaction committed for chunk execution ${execution.id} to true") + it.compute(execution.id) { _, v -> + val state = batchJobStateProvider.getStateForExecution(execution) + state.transactionCommitted = true + state + } + it } - it - } val isJobCompleted = state.all { it.value.transactionCommitted && it.value.status.completed } logger.debug { val incompleteExecutions = @@ -141,7 +148,7 @@ class ProgressManager( completedChunks: Long, isAnyCancelled: Boolean, errorMessage: Message? = null, - failOnly: Boolean = false + failOnly: Boolean = false, ) { logger.debug { "Job ${job.id} completed chunks: $completedChunks of ${job.totalChunks}" } logger.debug { "Job ${job.id} progress: $progress of ${job.totalItems}" } @@ -189,7 +196,10 @@ class ProgressManager( return batchJobStateProvider.getCached(jobId)?.getInfoForJobResult()?.progress } - fun publishSingleChunkProgress(jobId: Long, progress: Int) { + fun publishSingleChunkProgress( + jobId: Long, + progress: Int, + ) { val job = batchJobService.getJobDto(jobId) eventPublisher.publishEvent(OnBatchJobProgress(job, progress.toLong(), job.totalItems.toLong())) } diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/ScheduledJobCleaner.kt b/backend/data/src/main/kotlin/io/tolgee/batch/ScheduledJobCleaner.kt index 3b0b862e2c..da8ede9518 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/ScheduledJobCleaner.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/ScheduledJobCleaner.kt @@ -14,9 +14,8 @@ class ScheduledJobCleaner( private val batchJobService: BatchJobService, private val lockingManager: BatchJobProjectLockingManager, private val currentDateProvider: CurrentDateProvider, - private val batchJobStateProvider: BatchJobStateProvider + private val batchJobStateProvider: BatchJobStateProvider, ) : Logging { - /** * Sometimes it doesn't unlock the job for project (for some reason) * For that reason, we have this scheduled task that unlocks all completed jobs diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/data/AllIncompleteJobsResult.kt b/backend/data/src/main/kotlin/io/tolgee/batch/data/AllIncompleteJobsResult.kt index ec0159b119..96c0c62fce 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/data/AllIncompleteJobsResult.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/data/AllIncompleteJobsResult.kt @@ -2,5 +2,5 @@ package io.tolgee.batch.data data class AllIncompleteJobsResult( val jobId: Long, - val totalChunks: Int + val totalChunks: Int, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/data/BatchJobType.kt b/backend/data/src/main/kotlin/io/tolgee/batch/data/BatchJobType.kt index d00a5453b4..dc590158bd 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/data/BatchJobType.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/data/BatchJobType.kt @@ -79,7 +79,6 @@ enum class BatchJobType( activityType = ActivityType.AUTOMATION, maxRetries = 3, processor = AutomationChunkProcessor::class, - exclusive = false - ) - ; + exclusive = false, + ), } diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/data/JobUnlockedChunk.kt b/backend/data/src/main/kotlin/io/tolgee/batch/data/JobUnlockedChunk.kt index e4c38eac92..c50e5c457a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/data/JobUnlockedChunk.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/data/JobUnlockedChunk.kt @@ -2,5 +2,5 @@ package io.tolgee.batch.data data class JobUnlockedChunk( val batchJobId: Long, - val batchJobChunkExecutionId: Long + val batchJobChunkExecutionId: Long, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/data/QueueEventType.kt b/backend/data/src/main/kotlin/io/tolgee/batch/data/QueueEventType.kt index f407ec927a..5464add8b2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/data/QueueEventType.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/data/QueueEventType.kt @@ -1,5 +1,6 @@ package io.tolgee.batch.data enum class QueueEventType { - ADD, REMOVE + ADD, + REMOVE, } diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/events/JobCancelEvent.kt b/backend/data/src/main/kotlin/io/tolgee/batch/events/JobCancelEvent.kt index 4cdaccaf73..4aae482c75 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/events/JobCancelEvent.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/events/JobCancelEvent.kt @@ -1,5 +1,5 @@ package io.tolgee.batch.events class JobCancelEvent( - val jobId: Long + val jobId: Long, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/events/JobQueueItemsEvent.kt b/backend/data/src/main/kotlin/io/tolgee/batch/events/JobQueueItemsEvent.kt index 8d5bed7441..37e34f6ad3 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/events/JobQueueItemsEvent.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/events/JobQueueItemsEvent.kt @@ -5,5 +5,5 @@ import io.tolgee.batch.data.QueueEventType data class JobQueueItemsEvent( val items: List, - val type: QueueEventType + val type: QueueEventType, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/events/OnBatchJobStatusUpdated.kt b/backend/data/src/main/kotlin/io/tolgee/batch/events/OnBatchJobStatusUpdated.kt index ec309c0fb6..1ff05fde54 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/events/OnBatchJobStatusUpdated.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/events/OnBatchJobStatusUpdated.kt @@ -5,5 +5,5 @@ import io.tolgee.model.batch.BatchJobStatus class OnBatchJobStatusUpdated( val jobId: Long, val projectId: Long, - val status: BatchJobStatus + val status: BatchJobStatus, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/exceptions.kt b/backend/data/src/main/kotlin/io/tolgee/batch/exceptions.kt index 508dbcd7ba..9fa2bc52b0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/exceptions.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/exceptions.kt @@ -6,14 +6,14 @@ import io.tolgee.exceptions.ExceptionWithMessage open class ChunkFailedException( message: Message, val successfulTargets: List, - override val cause: Throwable + override val cause: Throwable, ) : ExceptionWithMessage(message) open class FailedDontRequeueException( message: Message, successfulTargets: List, - cause: Throwable + cause: Throwable, ) : ChunkFailedException(message, successfulTargets, cause) open class RequeueWithDelayException( @@ -22,7 +22,7 @@ open class RequeueWithDelayException( cause: Throwable, val delayInMs: Int = 100, val increaseFactor: Int = 10, - val maxRetries: Int = 3 + val maxRetries: Int = 3, ) : ChunkFailedException(message, successfulTargets, cause) open class CannotFinalizeActivityException(cause: Throwable) : diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/processors/AutoTranslateChunkProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/batch/processors/AutoTranslateChunkProcessor.kt index e73cc6de3b..8d502ee9ce 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/processors/AutoTranslateChunkProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/processors/AutoTranslateChunkProcessor.kt @@ -19,13 +19,13 @@ class AutoTranslateChunkProcessor( private val genericAutoTranslationChunkProcessor: GenericAutoTranslationChunkProcessor, private val mtServiceConfigService: MtServiceConfigService, private val entityManager: EntityManager, - private val autoTranslationService: AutoTranslationService + private val autoTranslationService: AutoTranslationService, ) : ChunkProcessor { override fun process( job: BatchJobDto, chunk: List, coroutineContext: CoroutineContext, - onProgress: (Int) -> Unit + onProgress: (Int) -> Unit, ) { genericAutoTranslationChunkProcessor.iterateCatching(chunk, coroutineContext) { item -> val (keyId, languageId) = item @@ -49,7 +49,10 @@ class AutoTranslateChunkProcessor( return JobCharacter.SLOW } - override fun getChunkSize(request: AutoTranslationRequest, projectId: Long): Int { + override fun getChunkSize( + request: AutoTranslationRequest, + projectId: Long, + ): Int { val languageIds = request.target.map { it.languageId }.distinct() val project = entityManager.getReference(Project::class.java, projectId) val services = mtServiceConfigService.getPrimaryServices(languageIds, project).values.toSet() diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/processors/AutomationChunkProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/batch/processors/AutomationChunkProcessor.kt index 45bf254bb5..a30ffb0b4d 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/processors/AutomationChunkProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/processors/AutomationChunkProcessor.kt @@ -11,13 +11,13 @@ import kotlin.coroutines.CoroutineContext @Component class AutomationChunkProcessor( - private val automationRunner: AutomationRunner + private val automationRunner: AutomationRunner, ) : ChunkProcessor { override fun process( job: BatchJobDto, chunk: List, coroutineContext: CoroutineContext, - onProgress: (Int) -> Unit + onProgress: (Int) -> Unit, ) { chunk.forEach { automationRunner.run(it.actionId, it.activityRevisionId) diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/processors/ClearTranslationsChunkProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/batch/processors/ClearTranslationsChunkProcessor.kt index 7cf3bfa1d3..3d6fdf3763 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/processors/ClearTranslationsChunkProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/processors/ClearTranslationsChunkProcessor.kt @@ -13,13 +13,13 @@ import kotlin.coroutines.CoroutineContext @Component class ClearTranslationsChunkProcessor( private val translationService: TranslationService, - private val entityManager: EntityManager + private val entityManager: EntityManager, ) : ChunkProcessor { override fun process( job: BatchJobDto, chunk: List, coroutineContext: CoroutineContext, - onProgress: ((Int) -> Unit) + onProgress: ((Int) -> Unit), ) { val subChunked = chunk.chunked(100) var progress: Int = 0 diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/processors/CopyTranslationsChunkProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/batch/processors/CopyTranslationsChunkProcessor.kt index 51e88dfe4f..d76961a113 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/processors/CopyTranslationsChunkProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/processors/CopyTranslationsChunkProcessor.kt @@ -13,13 +13,13 @@ import kotlin.coroutines.CoroutineContext @Component class CopyTranslationsChunkProcessor( private val translationService: TranslationService, - private val entityManager: EntityManager + private val entityManager: EntityManager, ) : ChunkProcessor { override fun process( job: BatchJobDto, chunk: List, coroutineContext: CoroutineContext, - onProgress: ((Int) -> Unit) + onProgress: ((Int) -> Unit), ) { val subChunked = chunk.chunked(1000) var progress: Int = 0 diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/processors/DeleteKeysChunkProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/batch/processors/DeleteKeysChunkProcessor.kt index eb5cb7e3c2..1403041a94 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/processors/DeleteKeysChunkProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/processors/DeleteKeysChunkProcessor.kt @@ -12,13 +12,13 @@ import kotlin.coroutines.CoroutineContext @Component class DeleteKeysChunkProcessor( private val keyService: KeyService, - private val entityManager: EntityManager + private val entityManager: EntityManager, ) : ChunkProcessor { override fun process( job: BatchJobDto, chunk: List, coroutineContext: CoroutineContext, - onProgress: ((Int) -> Unit) + onProgress: ((Int) -> Unit), ) { coroutineContext.ensureActive() val subChunked = chunk.chunked(100) diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/processors/GenericAutoTranslationChunkProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/batch/processors/GenericAutoTranslationChunkProcessor.kt index e04bd70d25..76866d2275 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/processors/GenericAutoTranslationChunkProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/processors/GenericAutoTranslationChunkProcessor.kt @@ -24,7 +24,7 @@ class GenericAutoTranslationChunkProcessor( private val autoTranslationService: AutoTranslationService, private val keyService: KeyService, private val currentDateProvider: CurrentDateProvider, - private val languageService: LanguageService + private val languageService: LanguageService, ) { fun process( job: BatchJobDto, @@ -46,7 +46,7 @@ class GenericAutoTranslationChunkProcessor( forcedLanguageTags = listOf(languageTag), useTranslationMemory = useTranslationMemory, useMachineTranslation = useMachineTranslation, - isBatch = true + isBatch = true, ) } } @@ -54,7 +54,7 @@ class GenericAutoTranslationChunkProcessor( fun iterateCatching( chunk: List, coroutineContext: CoroutineContext, - fn: (item: BatchTranslationTargetItem) -> Unit + fn: (item: BatchTranslationTargetItem) -> Unit, ) { val successfulTargets = mutableListOf() chunk.forEach { item -> @@ -71,7 +71,7 @@ class GenericAutoTranslationChunkProcessor( e, (e.retryAt - currentDateProvider.date.time).toInt(), increaseFactor = 1, - maxRetries = -1 + maxRetries = -1, ) } catch (e: PlanTranslationLimitExceeded) { throw FailedDontRequeueException(Message.PLAN_TRANSLATION_LIMIT_EXCEEDED, successfulTargets, e) diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/processors/MachineTranslationChunkProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/batch/processors/MachineTranslationChunkProcessor.kt index 50e5ab8dc5..b672b5f093 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/processors/MachineTranslationChunkProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/processors/MachineTranslationChunkProcessor.kt @@ -17,13 +17,13 @@ import kotlin.coroutines.CoroutineContext class MachineTranslationChunkProcessor( private val genericAutoTranslationChunkProcessor: GenericAutoTranslationChunkProcessor, private val mtServiceConfigService: MtServiceConfigService, - private val entityManager: EntityManager + private val entityManager: EntityManager, ) : ChunkProcessor { override fun process( job: BatchJobDto, chunk: List, coroutineContext: CoroutineContext, - onProgress: (Int) -> Unit + onProgress: (Int) -> Unit, ) { @Suppress("UNCHECKED_CAST") genericAutoTranslationChunkProcessor.process( @@ -32,7 +32,7 @@ class MachineTranslationChunkProcessor( coroutineContext, onProgress, useMachineTranslation = true, - useTranslationMemory = false + useTranslationMemory = false, ) } @@ -56,7 +56,10 @@ class MachineTranslationChunkProcessor( return JobCharacter.SLOW } - override fun getChunkSize(request: MachineTranslationRequest, projectId: Long): Int { + override fun getChunkSize( + request: MachineTranslationRequest, + projectId: Long, + ): Int { val languageIds = request.targetLanguageIds val project = entityManager.getReference(Project::class.java, projectId) val services = mtServiceConfigService.getPrimaryServices(languageIds, project).values.toSet() diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/processors/PreTranslationByTmChunkProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/batch/processors/PreTranslationByTmChunkProcessor.kt index 65cc597086..51fe607018 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/processors/PreTranslationByTmChunkProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/processors/PreTranslationByTmChunkProcessor.kt @@ -12,22 +12,23 @@ import kotlin.coroutines.CoroutineContext @Component class PreTranslationByTmChunkProcessor( private val languageService: LanguageService, - private val genericAutoTranslationChunkProcessor: GenericAutoTranslationChunkProcessor + private val genericAutoTranslationChunkProcessor: GenericAutoTranslationChunkProcessor, ) : ChunkProcessor { override fun process( job: BatchJobDto, chunk: List, coroutineContext: CoroutineContext, - onProgress: (Int) -> Unit + onProgress: (Int) -> Unit, ) { val parameters = getParams(job) val languages = languageService.findByIdIn(parameters.targetLanguageIds) - val preparedChunk = chunk.map { keyId -> - languages.map { language -> - BatchTranslationTargetItem(keyId, language.id) - } - }.flatten() + val preparedChunk = + chunk.map { keyId -> + languages.map { language -> + BatchTranslationTargetItem(keyId, language.id) + } + }.flatten() genericAutoTranslationChunkProcessor.process( job, @@ -35,7 +36,7 @@ class PreTranslationByTmChunkProcessor( coroutineContext, onProgress, useTranslationMemory = true, - useMachineTranslation = false + useMachineTranslation = false, ) } @@ -51,7 +52,10 @@ class PreTranslationByTmChunkProcessor( return PreTranslationByTmJobParams::class.java } - override fun getChunkSize(request: PreTranslationByTmRequest, projectId: Long): Int { + override fun getChunkSize( + request: PreTranslationByTmRequest, + projectId: Long, + ): Int { return 10 } diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/processors/SetKeysNamespaceChunkProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/batch/processors/SetKeysNamespaceChunkProcessor.kt index d90951b27d..12ffb58897 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/processors/SetKeysNamespaceChunkProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/processors/SetKeysNamespaceChunkProcessor.kt @@ -17,13 +17,13 @@ import kotlin.coroutines.CoroutineContext @Component class SetKeysNamespaceChunkProcessor( private val entityManager: EntityManager, - private val keyService: KeyService + private val keyService: KeyService, ) : ChunkProcessor { override fun process( job: BatchJobDto, chunk: List, coroutineContext: CoroutineContext, - onProgress: (Int) -> Unit + onProgress: (Int) -> Unit, ) { val subChunked = chunk.chunked(100) var progress = 0 diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/processors/SetTranslationsStateChunkProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/batch/processors/SetTranslationsStateChunkProcessor.kt index 65ee90bc27..7ae8c3add7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/processors/SetTranslationsStateChunkProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/processors/SetTranslationsStateChunkProcessor.kt @@ -13,13 +13,13 @@ import kotlin.coroutines.CoroutineContext @Component class SetTranslationsStateChunkProcessor( private val translationService: TranslationService, - private val entityManager: EntityManager + private val entityManager: EntityManager, ) : ChunkProcessor { override fun process( job: BatchJobDto, chunk: List, coroutineContext: CoroutineContext, - onProgress: (Int) -> Unit + onProgress: (Int) -> Unit, ) { val subChunked = chunk.chunked(1000) var progress: Int = 0 diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/processors/TagKeysChunkProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/batch/processors/TagKeysChunkProcessor.kt index 70a73cddac..b40b819389 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/processors/TagKeysChunkProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/processors/TagKeysChunkProcessor.kt @@ -13,13 +13,13 @@ import kotlin.coroutines.CoroutineContext @Component class TagKeysChunkProcessor( private val entityManager: EntityManager, - private val tagService: TagService + private val tagService: TagService, ) : ChunkProcessor { override fun process( job: BatchJobDto, chunk: List, coroutineContext: CoroutineContext, - onProgress: (Int) -> Unit + onProgress: (Int) -> Unit, ) { val subChunked = chunk.chunked(100) as List> var progress: Int = 0 diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/processors/UntagKeysChunkProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/batch/processors/UntagKeysChunkProcessor.kt index c293717434..ba318afd2a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/processors/UntagKeysChunkProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/processors/UntagKeysChunkProcessor.kt @@ -13,13 +13,13 @@ import kotlin.coroutines.CoroutineContext @Component class UntagKeysChunkProcessor( private val entityManager: EntityManager, - private val tagService: TagService + private val tagService: TagService, ) : ChunkProcessor { override fun process( job: BatchJobDto, chunk: List, coroutineContext: CoroutineContext, - onProgress: (Int) -> Unit + onProgress: (Int) -> Unit, ) { @Suppress("UNCHECKED_CAST") val subChunked = chunk.chunked(100) as List> diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/request/AutomationBjRequest.kt b/backend/data/src/main/kotlin/io/tolgee/batch/request/AutomationBjRequest.kt index afe32be91d..8efec81bf6 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/request/AutomationBjRequest.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/request/AutomationBjRequest.kt @@ -3,5 +3,5 @@ package io.tolgee.batch.request data class AutomationBjRequest( var triggerId: Long, var actionId: Long, - var activityRevisionId: Long? + var activityRevisionId: Long?, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/batch/state/BatchJobStateProvider.kt b/backend/data/src/main/kotlin/io/tolgee/batch/state/BatchJobStateProvider.kt index 1f3b5fec8f..3168e78860 100644 --- a/backend/data/src/main/kotlin/io/tolgee/batch/state/BatchJobStateProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/batch/state/BatchJobStateProvider.kt @@ -24,7 +24,7 @@ class BatchJobStateProvider( val redissonClient: RedissonClient, val entityManager: EntityManager, val lockingProvider: LockingProvider, - val platformTransactionManager: PlatformTransactionManager + val platformTransactionManager: PlatformTransactionManager, ) : Logging { companion object { private val localJobStatesMap by lazy { @@ -32,7 +32,10 @@ class BatchJobStateProvider( } } - fun updateState(jobId: Long, block: (MutableMap) -> T): T { + fun updateState( + jobId: Long, + block: (MutableMap) -> T, + ): T { return lockingProvider.withLocking("batch_job_state_lock_$jobId") { val map = get(jobId) val result = block(map) @@ -47,7 +50,7 @@ class BatchJobStateProvider( status = execution.status, chunkNumber = execution.chunkNumber, retry = execution.retry, - transactionCommitted = false + transactionCommitted = false, ) } @@ -87,28 +90,30 @@ class BatchJobStateProvider( fun getInitialState(jobId: Long): MutableMap { logger.debug("Initializing batch job state for job $jobId") // we want to get state which is not affected by current transaction - val executions = executeInNewTransaction( - platformTransactionManager, - isolationLevel = TransactionDefinition.ISOLATION_READ_COMMITTED - ) { - entityManager.createQuery( - """ + val executions = + executeInNewTransaction( + platformTransactionManager, + isolationLevel = TransactionDefinition.ISOLATION_READ_COMMITTED, + ) { + entityManager.createQuery( + """ from BatchJobChunkExecution bjce where bjce.batchJob.id = :jobId """, - BatchJobChunkExecution::class.java - ) - .setParameter("jobId", jobId).resultList - } + BatchJobChunkExecution::class.java, + ) + .setParameter("jobId", jobId).resultList + } return executions.associate { - it.id to ExecutionState( - it.successTargets, - it.status, - it.chunkNumber, - it.retry, - true - ) + it.id to + ExecutionState( + it.successTargets, + it.status, + it.chunkNumber, + it.retry, + true, + ) }.toMutableMap() } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/ActivityHolderProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/ActivityHolderProvider.kt index 0372d35d95..72536e7bb5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/ActivityHolderProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/ActivityHolderProvider.kt @@ -60,6 +60,7 @@ class ActivityHolderProvider(private val applicationContext: ApplicationContext) } enum class Scope { - REQUEST, TRANSACTION + REQUEST, + TRANSACTION, } } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/Aes.kt b/backend/data/src/main/kotlin/io/tolgee/component/Aes.kt index c4a187b61c..b45dc3e022 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/Aes.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/Aes.kt @@ -6,28 +6,52 @@ package io.tolgee.component import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Component +import java.nio.ByteBuffer import java.security.MessageDigest -import java.util.* +import java.security.SecureRandom import javax.crypto.Cipher +import javax.crypto.spec.GCMParameterSpec import javax.crypto.spec.SecretKeySpec @Component -class Aes(@Qualifier("jwt_signing_secret") bytes: ByteArray) { - private val secretKey: SecretKeySpec? by lazy { - val sha = MessageDigest.getInstance("SHA-1") - val key = Arrays.copyOf(sha.digest(bytes), 16) - SecretKeySpec(key, "AES") +class Aes( + @Qualifier("jwt_signing_secret") bytes: ByteArray, +) { + private val secretKey: SecretKeySpec by lazy { + val sha = MessageDigest.getInstance("SHA-256") + val key = sha.digest(bytes) + SecretKeySpec(key.sliceArray(0 until 16), "AES") + } + + private val secureRandom = SecureRandom() + + private fun getGcmParameterSpec(): GCMParameterSpec { + val iv = ByteArray(16) + secureRandom.nextBytes(iv) + return GCMParameterSpec(128, iv) } fun encrypt(toEncrypt: ByteArray): ByteArray { - val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding") - cipher.init(Cipher.ENCRYPT_MODE, secretKey) - return cipher.doFinal(toEncrypt) + val cipher = Cipher.getInstance("AES/GCM/NoPadding") + val cipherInitVector = getGcmParameterSpec() + cipher.init(Cipher.ENCRYPT_MODE, secretKey, cipherInitVector) + val encryptedData = cipher.doFinal(toEncrypt) + return ByteBuffer.allocate(4 + cipherInitVector.iv.size + encryptedData.size) + .putInt(cipherInitVector.iv.size) + .put(cipherInitVector.iv) + .put(encryptedData) + .array() } fun decrypt(toDecrypt: ByteArray): ByteArray { - val cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING") - cipher.init(Cipher.DECRYPT_MODE, secretKey) - return cipher.doFinal(toDecrypt) + val cipher = Cipher.getInstance("AES/GCM/NoPadding") + val byteBuffer = ByteBuffer.wrap(toDecrypt) + val ivLength = byteBuffer.int + val iv = ByteArray(ivLength) + byteBuffer.get(iv) + val cipherText = ByteArray(byteBuffer.remaining()) + byteBuffer.get(cipherText) + cipher.init(Cipher.DECRYPT_MODE, secretKey, GCMParameterSpec(128, iv)) + return cipher.doFinal(cipherText) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/ContentStorageProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/ContentStorageProvider.kt index 5784c127b5..525ca56a11 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/ContentStorageProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/ContentStorageProvider.kt @@ -3,5 +3,8 @@ package io.tolgee.component import io.tolgee.model.contentDelivery.ContentStorage interface ContentStorageProvider { - fun getStorage(projectId: Long, contentStorageId: Long): ContentStorage + fun getStorage( + projectId: Long, + contentStorageId: Long, + ): ContentStorage } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/CurrentDateProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/CurrentDateProvider.kt index 4df1fe681c..b7fd11c41f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/CurrentDateProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/CurrentDateProvider.kt @@ -28,7 +28,7 @@ class CurrentDateProvider( auditingHandler: AuditingHandler, private val entityManager: EntityManager, private val applicationEventPublisher: ApplicationEventPublisher, - private val transactionManager: PlatformTransactionManager + private val transactionManager: PlatformTransactionManager, ) : Logging, DateTimeProvider { var forcedDate: Date? = null set(value) { @@ -54,7 +54,7 @@ class CurrentDateProvider( entityManager.persist( ForcedServerDateTime().apply { time = date - } + }, ) } } @@ -66,7 +66,10 @@ class CurrentDateProvider( auditingHandler.setDateTimeProvider(this) } - fun forceDateString(dateString: String, pattern: String = "yyyy-MM-dd HH:mm:ss z") { + fun forceDateString( + dateString: String, + pattern: String = "yyyy-MM-dd HH:mm:ss z", + ) { val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern(pattern) val parsed = ZonedDateTime.parse(dateString, formatter).toInstant().toEpochMilli() forcedDate = Date(parsed) @@ -88,12 +91,12 @@ class CurrentDateProvider( private fun getServerTimeEntity(): ForcedServerDateTime? = entityManager.createQuery( "select st from ForcedServerDateTime st where st.id = 1", - ForcedServerDateTime::class.java + ForcedServerDateTime::class.java, ).resultList.singleOrNull() private fun getForcedTime(): Timestamp? = entityManager.createNativeQuery( "select st.time from public.forced_server_date_time st where st.id = 1", - Timestamp::class.java + Timestamp::class.java, ).resultList.singleOrNull() as Timestamp? } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/FrontendUrlProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/FrontendUrlProvider.kt index 278e461ce0..ad142a557f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/FrontendUrlProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/FrontendUrlProvider.kt @@ -6,7 +6,7 @@ import org.springframework.web.servlet.support.ServletUriComponentsBuilder @Component class FrontendUrlProvider( - private val tolgeeProperties: TolgeeProperties + private val tolgeeProperties: TolgeeProperties, ) { val url: String get() { diff --git a/backend/data/src/main/kotlin/io/tolgee/component/HttpClient.kt b/backend/data/src/main/kotlin/io/tolgee/component/HttpClient.kt index bfcc268ebe..7a62a3d5d9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/HttpClient.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/HttpClient.kt @@ -13,18 +13,25 @@ import org.springframework.web.client.RestTemplate class HttpClient( private val restTemplate: RestTemplate, ) { - fun requestForJson(url: String, body: Any, method: HttpMethod, result: Class): T? { + fun requestForJson( + url: String, + body: Any, + method: HttpMethod, + result: Class, + ): T? { val bodyJson = jacksonObjectMapper().writeValueAsString(body) - val headers = HttpHeaders().apply { - contentType = MediaType.APPLICATION_JSON - } + val headers = + HttpHeaders().apply { + contentType = MediaType.APPLICATION_JSON + } - val response = restTemplate.exchange( - url, - method, - HttpEntity(bodyJson, headers), - String::class.java - ) + val response = + restTemplate.exchange( + url, + method, + HttpEntity(bodyJson, headers), + String::class.java, + ) @Suppress("UNNECESSARY_SAFE_CALL") return response?.body?.let { stringResponseBody -> diff --git a/backend/data/src/main/kotlin/io/tolgee/component/KeyGenerator.kt b/backend/data/src/main/kotlin/io/tolgee/component/KeyGenerator.kt index 891821d345..719ee82ce3 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/KeyGenerator.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/KeyGenerator.kt @@ -8,7 +8,7 @@ import java.security.SecureRandom @Component class KeyGenerator( - private val random: SecureRandom + private val random: SecureRandom, ) { fun generate(bits: Int = 256): String { return BigInteger(bits, random).toString(32) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/LockingProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/LockingProvider.kt index 0e41c48484..66579d35f7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/LockingProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/LockingProvider.kt @@ -5,5 +5,8 @@ import java.util.concurrent.locks.Lock interface LockingProvider { fun getLock(name: String): Lock - fun withLocking(name: String, fn: () -> T): T + fun withLocking( + name: String, + fn: () -> T, + ): T } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/MarketingEmailServiceManager.kt b/backend/data/src/main/kotlin/io/tolgee/component/MarketingEmailServiceManager.kt index 6ef4515469..732317fe15 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/MarketingEmailServiceManager.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/MarketingEmailServiceManager.kt @@ -12,10 +12,13 @@ import sibModel.UpdateContact @Component class MarketingEmailServiceManager( private val sendInBlueProperties: SendInBlueProperties, - private val contactsApi: ContactsApi? + private val contactsApi: ContactsApi?, ) { @Async - fun submitNewContact(name: String, email: String) { + fun submitNewContact( + name: String, + email: String, + ) { runSentryCatching { if (contactsApi == null) { return @@ -26,7 +29,11 @@ class MarketingEmailServiceManager( } @Async - fun updateContact(oldEmail: String, newEmail: String, newName: String) { + fun updateContact( + oldEmail: String, + newEmail: String, + newName: String, + ) { try { if (contactsApi == null) { return @@ -39,13 +46,19 @@ class MarketingEmailServiceManager( } } - private fun getUpdateContactDto(newEmail: String, newName: String): UpdateContact { + private fun getUpdateContactDto( + newEmail: String, + newName: String, + ): UpdateContact { val updateContact = UpdateContact() updateContact.attributes = mapOf("EMAIL" to newEmail, "NAME" to newName) return updateContact } - private fun getCreateContactDto(email: String, name: String): CreateContact { + private fun getCreateContactDto( + email: String, + name: String, + ): CreateContact { val createContact = CreateContact() createContact.email = email createContact.attributes = mapOf("NAME" to name) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/OutdatedFlagListener.kt b/backend/data/src/main/kotlin/io/tolgee/component/OutdatedFlagListener.kt index e98ef7faef..f362b2b6e7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/OutdatedFlagListener.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/OutdatedFlagListener.kt @@ -11,7 +11,7 @@ import org.springframework.stereotype.Component @Component @Scope(TransactionScopeConfig.SCOPE_TRANSACTION) class OutdatedFlagListener( - private val translationService: TranslationService + private val translationService: TranslationService, ) { @EventListener @Order(1) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/SavePointManager.kt b/backend/data/src/main/kotlin/io/tolgee/component/SavePointManager.kt index 2711496814..f388e841d7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/SavePointManager.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/SavePointManager.kt @@ -9,7 +9,7 @@ import java.util.* @Component class SavePointManager( - private val entityManager: EntityManager + private val entityManager: EntityManager, ) { fun setSavepoint(): Savepoint? { var savepoint: Savepoint? = null @@ -25,8 +25,9 @@ class SavePointManager( val session = getSession() val coordinatorGetter = session::class.java.getMethod("getTransactionCoordinator") coordinatorGetter.isAccessible = true - val coordinator = coordinatorGetter.invoke(session) as? JdbcResourceLocalTransactionCoordinatorImpl - ?: throw IllegalStateException("Transaction coordinator is not JdbcResourceLocalTransactionCoordinatorImpl") + val coordinator = + coordinatorGetter.invoke(session) as? JdbcResourceLocalTransactionCoordinatorImpl + ?: throw IllegalStateException("Transaction coordinator is not JdbcResourceLocalTransactionCoordinatorImpl") val delegateField = coordinator::class.java.getDeclaredField("physicalTransactionDelegate") delegateField.isAccessible = true val delegate = diff --git a/backend/data/src/main/kotlin/io/tolgee/component/SentryBeforeSendCallback.kt b/backend/data/src/main/kotlin/io/tolgee/component/SentryBeforeSendCallback.kt index 914445d883..0e6fe5caa9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/SentryBeforeSendCallback.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/SentryBeforeSendCallback.kt @@ -7,7 +7,10 @@ import org.springframework.stereotype.Component @Component class SentryBeforeSendCallback : SentryOptions.BeforeSendCallback { - override fun execute(event: SentryEvent, hint: Hint): SentryEvent? { + override fun execute( + event: SentryEvent, + hint: Hint, + ): SentryEvent? { if (event.containsMessage("Failed to send message to MessageChannel")) { return null } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/UsingRedisProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/UsingRedisProvider.kt index d0c7c7b594..ac17019b0a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/UsingRedisProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/UsingRedisProvider.kt @@ -7,7 +7,7 @@ import org.springframework.stereotype.Component @Component class UsingRedisProvider( - private val applicationContext: ApplicationContext + private val applicationContext: ApplicationContext, ) { val areWeUsingRedis: Boolean by lazy { try { diff --git a/backend/data/src/main/kotlin/io/tolgee/component/atomicLong/AtomicLongProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/atomicLong/AtomicLongProvider.kt index 3f45cf2180..8b903ea3b6 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/atomicLong/AtomicLongProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/atomicLong/AtomicLongProvider.kt @@ -12,9 +12,12 @@ import java.util.concurrent.TimeUnit @Component class AtomicLongProvider( val isUsingRedisProvider: UsingRedisProvider, - val applicationContext: ApplicationContext + val applicationContext: ApplicationContext, ) : Logging { - fun get(name: String, defaultProvider: () -> Long): TolgeeAtomicLong { + fun get( + name: String, + defaultProvider: () -> Long, + ): TolgeeAtomicLong { return if (isUsingRedisProvider.areWeUsingRedis) { // we need to lock it, because we don't want to set the default multiple times val lock = redissonClient.getLock("lock_$name") diff --git a/backend/data/src/main/kotlin/io/tolgee/component/atomicLong/MemoryTolgeeAtomicLong.kt b/backend/data/src/main/kotlin/io/tolgee/component/atomicLong/MemoryTolgeeAtomicLong.kt index 23c5759197..fe0c60dece 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/atomicLong/MemoryTolgeeAtomicLong.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/atomicLong/MemoryTolgeeAtomicLong.kt @@ -6,7 +6,7 @@ import java.util.concurrent.atomic.AtomicLong class MemoryTolgeeAtomicLong( private val name: String, - private val defaultProvider: () -> Long + private val defaultProvider: () -> Long, ) : TolgeeAtomicLong { companion object { private val map = ConcurrentHashMap() diff --git a/backend/data/src/main/kotlin/io/tolgee/component/atomicLong/RedisTolgeeAtomicLong.kt b/backend/data/src/main/kotlin/io/tolgee/component/atomicLong/RedisTolgeeAtomicLong.kt index f2512dd88a..9500850dce 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/atomicLong/RedisTolgeeAtomicLong.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/atomicLong/RedisTolgeeAtomicLong.kt @@ -4,7 +4,7 @@ import io.tolgee.util.TolgeeAtomicLong import org.redisson.api.RAtomicLong class RedisTolgeeAtomicLong( - private val it: RAtomicLong + private val it: RAtomicLong, ) : TolgeeAtomicLong { override fun addAndGet(delta: Long): Long { return it.addAndGet(delta) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/autoTranslation/AutoTranslationEventHandler.kt b/backend/data/src/main/kotlin/io/tolgee/component/autoTranslation/AutoTranslationEventHandler.kt index b27310d3c9..b94899a109 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/autoTranslation/AutoTranslationEventHandler.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/autoTranslation/AutoTranslationEventHandler.kt @@ -21,7 +21,7 @@ import kotlin.properties.Delegates */ class AutoTranslationEventHandler( private val event: OnProjectActivityStoredEvent, - private val applicationContext: ApplicationContext + private val applicationContext: ApplicationContext, ) { var projectId by Delegates.notNull() @@ -44,15 +44,16 @@ class AutoTranslationEventHandler( keyIds = keyIds, isBatch = true, baseLanguageId = baseLanguageId ?: return, - isHiddenJob = event.isLowVolumeActivity() + isHiddenJob = event.isLowVolumeActivity(), ) } } private fun shouldRunTheOperation(): Boolean { - val configs = autoTranslationService.getConfigs( - entityManager.getReference(Project::class.java, projectId) - ) + val configs = + autoTranslationService.getConfigs( + entityManager.getReference(Project::class.java, projectId), + ) val usingPrimaryMtService = configs.any { it.usingPrimaryMtService } val usingTm = configs.any { it.usingTm } @@ -70,8 +71,7 @@ class AutoTranslationEventHandler( return hasEnabledForImport && event.activityRevision.type in IMPORT_ACTIVITIES } - private fun OnProjectActivityStoredEvent.isLowVolumeActivity() = - activityRevision.type in LOW_VOLUME_ACTIVITIES + private fun OnProjectActivityStoredEvent.isLowVolumeActivity() = activityRevision.type in LOW_VOLUME_ACTIVITIES private fun getKeyIdsToAutoTranslate(): List { return event.activityRevision.modifiedEntities.mapNotNull { modifiedEntity -> @@ -96,8 +96,7 @@ class AutoTranslationEventHandler( modification.old != modification.new } - private fun ActivityModifiedEntity.isTranslation() = - entityClass == Translation::class.simpleName + private fun ActivityModifiedEntity.isTranslation() = entityClass == Translation::class.simpleName private fun ActivityModifiedEntity.isBaseTranslation(): Boolean { return describingRelations?.values diff --git a/backend/data/src/main/kotlin/io/tolgee/component/autoTranslation/AutoTranslationListener.kt b/backend/data/src/main/kotlin/io/tolgee/component/autoTranslation/AutoTranslationListener.kt index 5f36506ca3..2016626dd2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/autoTranslation/AutoTranslationListener.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/autoTranslation/AutoTranslationListener.kt @@ -9,9 +9,8 @@ import org.springframework.stereotype.Component @Component class AutoTranslationListener( - private val applicationContext: ApplicationContext + private val applicationContext: ApplicationContext, ) : Logging { - @Order(2) @EventListener fun onApplicationEvent(event: OnProjectActivityStoredEvent) { diff --git a/backend/data/src/main/kotlin/io/tolgee/component/automations/AutomationActivityListener.kt b/backend/data/src/main/kotlin/io/tolgee/component/automations/AutomationActivityListener.kt index edd86c4104..27c1a65a26 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/automations/AutomationActivityListener.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/automations/AutomationActivityListener.kt @@ -11,7 +11,7 @@ import org.springframework.stereotype.Component @Component class AutomationActivityListener( - private val automationsBatchJobCreator: AutomationsBatchJobCreator + private val automationsBatchJobCreator: AutomationsBatchJobCreator, ) { @EventListener @Async @@ -42,7 +42,7 @@ class AutomationActivityListener( Translation::class, Key::class, Language::class, - Project::class + Project::class, ).any { allowedClass -> allowedClass.simpleName == modifiedEntity.entityClass } } } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/automations/AutomationProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/component/automations/AutomationProcessor.kt index 598d6912f5..ef2b512f16 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/automations/AutomationProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/automations/AutomationProcessor.kt @@ -3,5 +3,8 @@ package io.tolgee.component.automations import io.tolgee.model.automations.AutomationAction interface AutomationProcessor { - fun process(action: AutomationAction, activityRevisionId: Long?) + fun process( + action: AutomationAction, + activityRevisionId: Long?, + ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/automations/AutomationRunner.kt b/backend/data/src/main/kotlin/io/tolgee/component/automations/AutomationRunner.kt index 4f74d92f41..7c24658682 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/automations/AutomationRunner.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/automations/AutomationRunner.kt @@ -7,9 +7,12 @@ import org.springframework.stereotype.Component @Component class AutomationRunner( private val automationService: AutomationService, - private val applicationContext: ApplicationContext + private val applicationContext: ApplicationContext, ) { - fun run(actionId: Long, activityRevisionId: Long?) { + fun run( + actionId: Long, + activityRevisionId: Long?, + ) { val action = automationService.getAction(actionId) applicationContext.getBean(action.type.processor.java).process(action, activityRevisionId) } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/automations/AutomationsBatchJobCreator.kt b/backend/data/src/main/kotlin/io/tolgee/component/automations/AutomationsBatchJobCreator.kt index 85e3f2190d..8f877f72be 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/automations/AutomationsBatchJobCreator.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/automations/AutomationsBatchJobCreator.kt @@ -18,18 +18,25 @@ import java.time.Duration class AutomationsBatchJobCreator( val batchJobService: BatchJobService, val automationService: AutomationService, - val entityManager: EntityManager + val entityManager: EntityManager, ) { - fun executeActivityAutomation(projectId: Long, type: ActivityType, activityRevisionId: Long) { + fun executeActivityAutomation( + projectId: Long, + type: ActivityType, + activityRevisionId: Long, + ) { startBatchJobForAutomations(projectId, AutomationTriggerType.ACTIVITY, type, activityRevisionId) } - fun executeTranslationDataModificationAutomation(projectId: Long, activityRevisionId: Long) { + fun executeTranslationDataModificationAutomation( + projectId: Long, + activityRevisionId: Long, + ) { startBatchJobForAutomations( projectId, AutomationTriggerType.TRANSLATION_DATA_MODIFICATION, null, - activityRevisionId + activityRevisionId, ) } @@ -37,7 +44,7 @@ class AutomationsBatchJobCreator( projectId: Long, triggerType: AutomationTriggerType, activityType: ActivityType? = null, - activityRevisionId: Long + activityRevisionId: Long, ) { val automations = automationService.getProjectAutomations(projectId, triggerType, activityType) @@ -59,7 +66,7 @@ class AutomationsBatchJobCreator( trigger: AutomationTriggerDto, action: AutomationActionDto, projectId: Long, - activityRevisionId: Long + activityRevisionId: Long, ) { batchJobService.startJob( AutomationBjRequest(trigger.id, action.id, activityRevisionId), @@ -67,7 +74,7 @@ class AutomationsBatchJobCreator( author = null, type = BatchJobType.AUTOMATION, isHidden = true, - debounceDuration = trigger.debounceDurationInMs?.let { Duration.ofMillis(it) } + debounceDuration = trigger.debounceDurationInMs?.let { Duration.ofMillis(it) }, ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/ContentDeliveryPublishProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/ContentDeliveryPublishProcessor.kt index ff9c6fc49a..68e234e6db 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/ContentDeliveryPublishProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/ContentDeliveryPublishProcessor.kt @@ -16,7 +16,10 @@ class ContentDeliveryPublishProcessor( val securityService: SecurityService, val projectHolder: ProjectHolder, ) : AutomationProcessor { - override fun process(action: AutomationAction, activityRevisionId: Long?) { + override fun process( + action: AutomationAction, + activityRevisionId: Long?, + ) { try { val config = action.contentDeliveryConfig @@ -30,7 +33,8 @@ class ContentDeliveryPublishProcessor( ) else -> throw RequeueWithDelayException( - Message.UNEXPECTED_ERROR_WHILE_PUBLISHING_TO_CONTENT_STORAGE, cause = e + Message.UNEXPECTED_ERROR_WHILE_PUBLISHING_TO_CONTENT_STORAGE, + cause = e, ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/WebhookEventType.kt b/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/WebhookEventType.kt index c1d8652cd6..8b9353bfe9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/WebhookEventType.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/WebhookEventType.kt @@ -1,5 +1,6 @@ package io.tolgee.component.automations.processors enum class WebhookEventType { - TEST, PROJECT_ACTIVITY + TEST, + PROJECT_ACTIVITY, } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/WebhookExecutor.kt b/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/WebhookExecutor.kt index 2b0550c4c0..aaa76c7a29 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/WebhookExecutor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/WebhookExecutor.kt @@ -17,9 +17,12 @@ import org.springframework.web.client.RestTemplate class WebhookExecutor( @Qualifier("webhookRestTemplate") private val restTemplate: RestTemplate, - private val currentDateProvider: CurrentDateProvider + private val currentDateProvider: CurrentDateProvider, ) { - fun signAndExecute(config: WebhookConfig, data: WebhookRequest) { + fun signAndExecute( + config: WebhookConfig, + data: WebhookRequest, + ) { val stringData = jacksonObjectMapper().writeValueAsString(data) val headers = HttpHeaders() @Suppress("UastIncorrectHttpHeaderInspection") @@ -39,7 +42,10 @@ class WebhookExecutor( } } - private fun generateSigHeader(payload: String, key: String): String { + private fun generateSigHeader( + payload: String, + key: String, + ): String { val timestamp = currentDateProvider.date.time val signature = computeHmacSha256(key, "$timestamp.$payload") return String.format("""{"timestamp": $timestamp, "signature": "$signature"}""") diff --git a/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/WebhookProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/WebhookProcessor.kt index 496df046b9..9123e499a8 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/WebhookProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/WebhookProcessor.kt @@ -19,19 +19,23 @@ class WebhookProcessor( val activityService: ActivityService, val currentDateProvider: CurrentDateProvider, val webhookExecutor: WebhookExecutor, - val entityManager: EntityManager + val entityManager: EntityManager, ) : AutomationProcessor { - override fun process(action: AutomationAction, activityRevisionId: Long?) { + override fun process( + action: AutomationAction, + activityRevisionId: Long?, + ) { activityRevisionId ?: return val view = activityService.getProjectActivity(activityRevisionId) ?: return val activityModel = activityModelAssembler.toModel(view) val config = action.webhookConfig ?: return - val data = WebhookRequest( - webhookConfigId = config.id, - eventType = WebhookEventType.PROJECT_ACTIVITY, - activityData = activityModel - ) + val data = + WebhookRequest( + webhookConfigId = config.id, + eventType = WebhookEventType.PROJECT_ACTIVITY, + activityData = activityModel, + ) try { webhookExecutor.signAndExecute(config, data) @@ -54,7 +58,10 @@ class WebhookProcessor( } } - fun updateEntity(webhookConfig: WebhookConfig, failing: Boolean) { + fun updateEntity( + webhookConfig: WebhookConfig, + failing: Boolean, + ) { webhookConfig.firstFailed = if (failing) currentDateProvider.date else null webhookConfig.lastExecuted = currentDateProvider.date entityManager.persist(webhookConfig) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/WebhookRequest.kt b/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/WebhookRequest.kt index e663c9e9de..6a6af96973 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/WebhookRequest.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/WebhookRequest.kt @@ -5,5 +5,5 @@ import io.tolgee.api.IProjectActivityModel data class WebhookRequest( val webhookConfigId: Long?, val eventType: WebhookEventType, - val activityData: IProjectActivityModel? + val activityData: IProjectActivityModel?, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/webhookExceptions.kt b/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/webhookExceptions.kt index 019beb0305..49830e6721 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/webhookExceptions.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/automations/processors/webhookExceptions.kt @@ -3,6 +3,7 @@ package io.tolgee.component.automations.processors import org.springframework.http.HttpStatusCode class WebhookRespondedWithNon200Status(statusCode: HttpStatusCode, body: Any?) : WebhookException() + class WebhookExecutionFailed(e: Throwable) : WebhookException(e) open class WebhookException(cause: Throwable? = null) : RuntimeException("Webhook execution failed", cause) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/bucket/TokenBucket.kt b/backend/data/src/main/kotlin/io/tolgee/component/bucket/TokenBucket.kt index 3c1c6412f0..2bb7a24994 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/bucket/TokenBucket.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/bucket/TokenBucket.kt @@ -6,7 +6,7 @@ class TokenBucket( currentTimestamp: Long, var size: Long, var tokens: Long, - var period: Duration + var period: Duration, ) { var refillAt: Long @@ -14,7 +14,11 @@ class TokenBucket( refillAt = currentTimestamp + period.toMillis() } - fun refillIfItsTime(currentTimestamp: Long, newTokens: Long, renewPeriod: Duration): TokenBucket { + fun refillIfItsTime( + currentTimestamp: Long, + newTokens: Long, + renewPeriod: Duration, + ): TokenBucket { if (isTimeToRefill(currentTimestamp)) { this.tokens = newTokens this.size = newTokens diff --git a/backend/data/src/main/kotlin/io/tolgee/component/bucket/TokenBucketManager.kt b/backend/data/src/main/kotlin/io/tolgee/component/bucket/TokenBucketManager.kt index 50ebb4d5ff..c8a4872613 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/bucket/TokenBucketManager.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/bucket/TokenBucketManager.kt @@ -17,19 +17,24 @@ class TokenBucketManager( val currentDateProvider: CurrentDateProvider, val lockingProvider: LockingProvider, @Lazy - var redissonClient: RedissonClient + var redissonClient: RedissonClient, ) : Logging { companion object { val localTokenBucketStorage = ConcurrentHashMap() } - fun consume(bucketId: String, tokensToConsume: Long, bucketSize: Long, renewPeriod: Duration) { + fun consume( + bucketId: String, + tokensToConsume: Long, + bucketSize: Long, + renewPeriod: Duration, + ) { updateBucket(bucketId) { consumeMappingFn( tokenBucket = it, tokensToConsume = tokensToConsume, bucketSize = bucketSize, - renewPeriod = renewPeriod + renewPeriod = renewPeriod, ) } } @@ -42,19 +47,28 @@ class TokenBucketManager( } } - fun addTokens(bucketId: String, tokensToAdd: Long) { + fun addTokens( + bucketId: String, + tokensToAdd: Long, + ) { updateTokens(bucketId) { oldTokens, bucketSize -> min(oldTokens + tokensToAdd, bucketSize) } } - fun updateTokens(bucketId: String, updateFn: ((oldTokens: Long, bucketSize: Long) -> Long)) { + fun updateTokens( + bucketId: String, + updateFn: ((oldTokens: Long, bucketSize: Long) -> Long), + ) { updateBucket(bucketId) { updateMappingFn(it, updateFn) } } - fun setEmptyUntil(bucketId: String, refillAt: Long) { + fun setEmptyUntil( + bucketId: String, + refillAt: Long, + ) { updateBucket(bucketId) { setEmptyUntilMappingFn(it, refillAt) } } @@ -64,7 +78,7 @@ class TokenBucketManager( tokenBucket: TokenBucket?, tokensToConsume: Long, bucketSize: Long, - renewPeriod: Duration + renewPeriod: Duration, ): TokenBucket { val currentTokenBucket = getCurrentOrNewBucket(tokenBucket, bucketSize, renewPeriod) @@ -75,9 +89,7 @@ class TokenBucketManager( return currentTokenBucket.apply { tokens = currentTokenBucket.tokens - tokensToConsume } } - private fun checkPositiveMappingFn( - tokenBucket: TokenBucket?, - ): TokenBucket? { + private fun checkPositiveMappingFn(tokenBucket: TokenBucket?): TokenBucket? { tokenBucket ?: return null if (tokenBucket.isTimeToRefill(currentDateProvider.date.time)) { return tokenBucket @@ -102,19 +114,22 @@ class TokenBucketManager( private fun getCurrentOrNewBucket( tokenBucket: TokenBucket?, bucketSize: Long, - renewPeriod: Duration + renewPeriod: Duration, ) = tokenBucket ?: TokenBucket(currentDateProvider.date.time, bucketSize, bucketSize, renewPeriod) private fun updateMappingFn( tokenBucket: TokenBucket?, - updateFn: ((oldTokens: Long, bucketSize: Long) -> Long) + updateFn: ((oldTokens: Long, bucketSize: Long) -> Long), ): TokenBucket? { tokenBucket ?: return null val newTokens = updateFn(tokenBucket.tokens, tokenBucket.size) return tokenBucket.apply { tokens = newTokens } } - private fun updateBucket(bucketId: String, mappingFn: (bucket: TokenBucket?) -> TokenBucket?): TokenBucket? { + private fun updateBucket( + bucketId: String, + mappingFn: (bucket: TokenBucket?) -> TokenBucket?, + ): TokenBucket? { if (!usingRedisProvider.areWeUsingRedis) { return localTokenBucketStorage.compute(bucketId) { _, bucket -> mappingFn(bucket) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/cacheWithExpiration/CacheWithExpiration.kt b/backend/data/src/main/kotlin/io/tolgee/component/cacheWithExpiration/CacheWithExpiration.kt index 0c6e77386b..3f9dbdf1f5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/cacheWithExpiration/CacheWithExpiration.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/cacheWithExpiration/CacheWithExpiration.kt @@ -6,9 +6,12 @@ import java.time.Duration class CacheWithExpiration( private val cache: Cache, - private val currentDateProvider: CurrentDateProvider + private val currentDateProvider: CurrentDateProvider, ) { - fun get(key: Any, type: Class?): T? { + fun get( + key: Any, + type: Class?, + ): T? { this.cache.get(key, CachedWithExpiration::class.java)?.let { if (it.expiresAt > currentDateProvider.date.time) { try { @@ -24,7 +27,11 @@ class CacheWithExpiration( return null } - fun put(key: Any, value: Any?, expiration: Duration) { + fun put( + key: Any, + value: Any?, + expiration: Duration, + ) { this.cache.put(key, CachedWithExpiration(currentDateProvider.date.time + expiration.toMillis(), value)) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/cacheWithExpiration/CacheWithExpirationManager.kt b/backend/data/src/main/kotlin/io/tolgee/component/cacheWithExpiration/CacheWithExpirationManager.kt index f9bf0086b1..74617aa5cb 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/cacheWithExpiration/CacheWithExpirationManager.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/cacheWithExpiration/CacheWithExpirationManager.kt @@ -7,7 +7,7 @@ import org.springframework.stereotype.Component @Component class CacheWithExpirationManager( private val cacheManager: CacheManager, - private val currentDateProvider: CurrentDateProvider + private val currentDateProvider: CurrentDateProvider, ) { fun getCache(name: String): CacheWithExpiration? { return cacheManager.getCache(name)?.let { CacheWithExpiration(it, currentDateProvider) } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/cacheWithExpiration/CachedWithExpiration.kt b/backend/data/src/main/kotlin/io/tolgee/component/cacheWithExpiration/CachedWithExpiration.kt index 1c1833fd95..927530a157 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/cacheWithExpiration/CachedWithExpiration.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/cacheWithExpiration/CachedWithExpiration.kt @@ -2,5 +2,5 @@ package io.tolgee.component.cacheWithExpiration data class CachedWithExpiration( val expiresAt: Long, - val data: Any? + val data: Any?, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/ContentDeliveryFileStorageProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/ContentDeliveryFileStorageProvider.kt index ce5b794661..f34ea9f08e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/ContentDeliveryFileStorageProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/ContentDeliveryFileStorageProvider.kt @@ -16,7 +16,7 @@ import org.springframework.stereotype.Component class ContentDeliveryFileStorageProvider( private val tolgeeProperties: TolgeeProperties, private val s3FileStorageFactory: S3FileStorageFactory, - private val azureFileStorageFactory: AzureFileStorageFactory + private val azureFileStorageFactory: AzureFileStorageFactory, ) { fun getContentStorageWithDefaultClient(): FileStorage { return bypassForTesting() ?: defaultStorage diff --git a/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/ContentDeliveryUploader.kt b/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/ContentDeliveryUploader.kt index a6c4e3d93b..a6156e03b5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/ContentDeliveryUploader.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/ContentDeliveryUploader.kt @@ -15,7 +15,7 @@ class ContentDeliveryUploader( private val exportService: ExportService, private val contentDeliveryConfigService: ContentDeliveryConfigService, private val contentDeliveryCachePurgingProvider: ContentDeliveryCachePurgingProvider, - private val currentDateProvider: CurrentDateProvider + private val currentDateProvider: CurrentDateProvider, ) { fun upload(contentDeliveryConfigId: Long) { val config = contentDeliveryConfigService.get(contentDeliveryConfigId) @@ -31,7 +31,7 @@ class ContentDeliveryUploader( private fun purgeCacheIfConfigured( contentDeliveryConfig: ContentDeliveryConfig, - paths: Set + paths: Set, ) { val isDefaultStorage = contentDeliveryConfig.contentStorage == null if (isDefaultStorage) { @@ -41,21 +41,22 @@ class ContentDeliveryUploader( private fun storeToStorage( withFullPaths: Map, - storage: FileStorage + storage: FileStorage, ) { withFullPaths.forEach { storage.storeFile( storageFilePath = it.key, - bytes = it.value.readBytes() + bytes = it.value.readBytes(), ) } } - private fun getStorage(contentDeliveryConfig: ContentDeliveryConfig) = contentDeliveryConfig.contentStorage - ?.let { - contentDeliveryFileStorageProvider.getStorage( - config = it.storageConfig ?: throw IllegalStateException("No storage config stored") - ) - } - ?: contentDeliveryFileStorageProvider.getContentStorageWithDefaultClient() + private fun getStorage(contentDeliveryConfig: ContentDeliveryConfig) = + contentDeliveryConfig.contentStorage + ?.let { + contentDeliveryFileStorageProvider.getStorage( + config = it.storageConfig ?: throw IllegalStateException("No storage config stored"), + ) + } + ?: contentDeliveryFileStorageProvider.getContentStorageWithDefaultClient() } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/cachePurging/AzureContentDeliveryCachePurging.kt b/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/cachePurging/AzureContentDeliveryCachePurging.kt index d36f9c8bc6..4180ab38b1 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/cachePurging/AzureContentDeliveryCachePurging.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/cachePurging/AzureContentDeliveryCachePurging.kt @@ -13,16 +13,19 @@ import org.springframework.web.client.RestTemplate class AzureContentDeliveryCachePurging( private val config: AzureFrontDoorConfig, private val restTemplate: RestTemplate, - private val azureCredentialProvider: AzureCredentialProvider + private val azureCredentialProvider: AzureCredentialProvider, ) : ContentDeliveryCachePurging { - override fun purgeForPaths(contentDeliveryConfig: ContentDeliveryConfig, paths: Set) { + override fun purgeForPaths( + contentDeliveryConfig: ContentDeliveryConfig, + paths: Set, + ) { val token = getAccessToken() purgeWithToken(contentDeliveryConfig, token) } private fun purgeWithToken( contentDeliveryConfig: ContentDeliveryConfig, - token: String + token: String, ) { val contentRoot = config.contentRoot?.removeSuffix("/") ?: "" val body = mapOf("contentPaths" to listOf("$contentRoot/${contentDeliveryConfig.slug}/*")) @@ -32,7 +35,7 @@ class AzureContentDeliveryCachePurging( private fun executePurgeRequest( token: String, body: Map>, - config: AzureFrontDoorConfig + config: AzureFrontDoorConfig, ) { val entity: HttpEntity = getHttpEntity(token, body) @@ -43,10 +46,13 @@ class AzureContentDeliveryCachePurging( "/afdEndpoints/${config.endpointName}" + "/purge?api-version=2023-05-01" - val response = restTemplate.exchange( - url, HttpMethod.POST, entity, - String::class.java - ) + val response = + restTemplate.exchange( + url, + HttpMethod.POST, + entity, + String::class.java, + ) if (!response.statusCode.is2xxSuccessful) { throw IllegalStateException("Purging failed with status code ${response.statusCode}") @@ -55,7 +61,7 @@ class AzureContentDeliveryCachePurging( private fun getHttpEntity( token: String, - body: Map> + body: Map>, ): HttpEntity { val headers = getHeaders(token) val jsonBody = jacksonObjectMapper().writeValueAsString(body) @@ -72,8 +78,9 @@ class AzureContentDeliveryCachePurging( private fun getAccessToken(): String { val credential = azureCredentialProvider.get(config) - val context = TokenRequestContext() - .addScopes("https://management.azure.com/.default") + val context = + TokenRequestContext() + .addScopes("https://management.azure.com/.default") return credential.getToken(context).block()?.token ?: throw IllegalStateException("No token") } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/cachePurging/AzureContentDeliveryCachePurgingFactory.kt b/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/cachePurging/AzureContentDeliveryCachePurgingFactory.kt index 0aad24fb61..ef383f4fbc 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/cachePurging/AzureContentDeliveryCachePurgingFactory.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/cachePurging/AzureContentDeliveryCachePurgingFactory.kt @@ -6,7 +6,7 @@ import org.springframework.web.client.RestTemplate @Component class AzureContentDeliveryCachePurgingFactory( - private val restTemplate: RestTemplate + private val restTemplate: RestTemplate, ) : ContentDeliveryCachePurgingFactory { override fun create(config: Any): AzureContentDeliveryCachePurging { return AzureContentDeliveryCachePurging(config as AzureFrontDoorConfig, restTemplate, AzureCredentialProvider()) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/cachePurging/ContentDeliveryCachePurging.kt b/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/cachePurging/ContentDeliveryCachePurging.kt index f649815431..7959db9b79 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/cachePurging/ContentDeliveryCachePurging.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/cachePurging/ContentDeliveryCachePurging.kt @@ -3,5 +3,8 @@ package io.tolgee.component.contentDelivery.cachePurging import io.tolgee.model.contentDelivery.ContentDeliveryConfig interface ContentDeliveryCachePurging { - fun purgeForPaths(contentDeliveryConfig: ContentDeliveryConfig, paths: Set) + fun purgeForPaths( + contentDeliveryConfig: ContentDeliveryConfig, + paths: Set, + ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/cachePurging/ContentDeliveryCachePurgingProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/cachePurging/ContentDeliveryCachePurgingProvider.kt index 2625e2c2f6..e2d888dce0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/cachePurging/ContentDeliveryCachePurgingProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/contentDelivery/cachePurging/ContentDeliveryCachePurgingProvider.kt @@ -14,12 +14,13 @@ class ContentDeliveryCachePurgingProvider( } private fun getDefaultFactory(): ContentDeliveryCachePurging? { - val purgings = configs.mapNotNull { - if (!it.enabled) { - return@mapNotNull null + val purgings = + configs.mapNotNull { + if (!it.enabled) { + return@mapNotNull null + } + applicationContext.getBean(it.contentDeliveryCachePurgingType.factory.java).create(it) } - applicationContext.getBean(it.contentDeliveryCachePurgingType.factory.java).create(it) - } if (purgings.size > 1) { throw RuntimeException("Exactly one content delivery purging must be set") } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/demoProject/DemoProjectCreator.kt b/backend/data/src/main/kotlin/io/tolgee/component/demoProject/DemoProjectCreator.kt index 7669522f80..fdef9c0745 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/demoProject/DemoProjectCreator.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/demoProject/DemoProjectCreator.kt @@ -42,11 +42,12 @@ class DemoProjectCreator( } val project: Project by lazy { - val project = Project().apply { - name = "Demo project" - this@apply.organizationOwner = organization - this.description = "This is a demo project of a packing list app" - } + val project = + Project().apply { + name = "Demo project" + this@apply.organizationOwner = organization + this.description = "This is a demo project of a packing list app" + } projectService.save(project) setAvatar(project) project @@ -66,7 +67,7 @@ class DemoProjectCreator( relatedKeysInOrder.add( RelatedKeyDto().apply { this.keyName = keyName - } + }, ) } bigMetaService.store(relatedKeysInOrder, project) @@ -78,7 +79,11 @@ class DemoProjectCreator( } } - private fun setTranslation(keyName: String, languageTag: String, translation: String): Translation { + private fun setTranslation( + keyName: String, + languageTag: String, + translation: String, + ): Translation { val language = languages[languageTag]!! return translationService.setTranslation(getOrCreateKey(keyName), language, translation).also { it.state = TranslationState.REVIEWED @@ -91,13 +96,18 @@ class DemoProjectCreator( DemoProjectData.screenshots.forEach { demoScreenshot -> val key = getOrCreateKey(demoScreenshot.keyName) - val positions = demoScreenshot.positions.map { - KeyInScreenshotPositionDto(it.x, it.y, it.width, it.height) - } + val positions = + demoScreenshot.positions.map { + KeyInScreenshotPositionDto(it.x, it.y, it.width, it.height) + } val dimension = Dimension(SCREENSHOT_WIDTH, SCREENSHOT_HEIGHT) screenshotService.addReference( - key, screenshot, ScreenshotInfoDto(text = null, positions, null), dimension, dimension + key, + screenshot, + ScreenshotInfoDto(text = null, positions, null), + dimension, + dimension, ) } } @@ -111,7 +121,7 @@ class DemoProjectCreator( screenshotImage.readAllBytes(), screenshotThumbnail.readAllBytes(), null, - Dimension(SCREENSHOT_WIDTH, SCREENSHOT_HEIGHT) + Dimension(SCREENSHOT_WIDTH, SCREENSHOT_HEIGHT), ) } } @@ -121,10 +131,11 @@ class DemoProjectCreator( private fun getOrCreateKey(keyName: String): Key { return keys.computeIfAbsent(keyName) { - val key = Key().apply { - name = keyName - this@apply.project = this@DemoProjectCreator.project - } + val key = + Key().apply { + name = keyName + this@apply.project = this@DemoProjectCreator.project + } keyService.save(key) key } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/demoProject/DemoProjectData.kt b/backend/data/src/main/kotlin/io/tolgee/component/demoProject/DemoProjectData.kt index 17c6dfcb5e..ad01619967 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/demoProject/DemoProjectData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/demoProject/DemoProjectData.kt @@ -3,104 +3,111 @@ package io.tolgee.component.demoProject import io.tolgee.model.Language object DemoProjectData { - val translations = mapOf( - "en" to mapOf( - "add-item-add-button" to "Add", - "add-item-input-placeholder" to "New list item", - "delete-item-button" to "Delete", - "menu-item-translation-methods" to "Translation methods", - "send-via-email" to "Send via e-mail", - "share-button" to "Share", - "app-title" to "What to pack", - ), - "de" to mapOf( - "add-item-add-button" to "Einfügen", - "add-item-input-placeholder" to "Neuer Eintrag", - "delete-item-button" to "Löschen", - "menu-item-translation-methods" to "Übersetzungsmethoden", - "send-via-email" to "Per Email abschicken", - "share-button" to "Teilen", - "app-title" to "Was mitnehmen" - ), - "fr" to mapOf( - "add-item-add-button" to "Ajouter", - "add-item-input-placeholder" to "Nouvel élément de la liste", - "delete-item-button" to "Supprimer", - "menu-item-translation-methods" to "Méthodes de traduction", - "send-via-email" to "Envoyer par courriel", - "share-button" to "Partager", - "app-title" to "Quoi emballer" - ), - ) + val translations = + mapOf( + "en" to + mapOf( + "add-item-add-button" to "Add", + "add-item-input-placeholder" to "New list item", + "delete-item-button" to "Delete", + "menu-item-translation-methods" to "Translation methods", + "send-via-email" to "Send via e-mail", + "share-button" to "Share", + "app-title" to "What to pack", + ), + "de" to + mapOf( + "add-item-add-button" to "Einfügen", + "add-item-input-placeholder" to "Neuer Eintrag", + "delete-item-button" to "Löschen", + "menu-item-translation-methods" to "Übersetzungsmethoden", + "send-via-email" to "Per Email abschicken", + "share-button" to "Teilen", + "app-title" to "Was mitnehmen", + ), + "fr" to + mapOf( + "add-item-add-button" to "Ajouter", + "add-item-input-placeholder" to "Nouvel élément de la liste", + "delete-item-button" to "Supprimer", + "menu-item-translation-methods" to "Méthodes de traduction", + "send-via-email" to "Envoyer par courriel", + "share-button" to "Partager", + "app-title" to "Quoi emballer", + ), + ) - val screenshots = listOf( - DemoProjectScreenshotReference( - keyName = "add-item-add-button", - positions = listOf(DemoProjectScreenshotReferencePosition(1601, 359, 168, 86)) - ), - DemoProjectScreenshotReference( - keyName = "add-item-input-placeholder", - positions = listOf(DemoProjectScreenshotReferencePosition(617, 359, 951, 86)) - ), - DemoProjectScreenshotReference( - keyName = "delete-item-button", - positions = listOf( - DemoProjectScreenshotReferencePosition(1637, 568, 116, 35), - DemoProjectScreenshotReferencePosition(1637, 637, 116, 35), - DemoProjectScreenshotReferencePosition(1637, 707, 116, 35) - ) - ), - DemoProjectScreenshotReference( - keyName = "menu-item-translation-methods", - positions = listOf(DemoProjectScreenshotReferencePosition(564, 27, 290, 60)) - ), - DemoProjectScreenshotReference( - keyName = "send-via-email", - positions = listOf(DemoProjectScreenshotReferencePosition(1439, 995, 331, 86)) - ), - DemoProjectScreenshotReference( - keyName = "share-button", - positions = listOf(DemoProjectScreenshotReferencePosition(1202, 995, 204, 86)) - ), - DemoProjectScreenshotReference( - keyName = "app-title", - positions = listOf(DemoProjectScreenshotReferencePosition(956, 181, 475, 91)) - ), - ) + val screenshots = + listOf( + DemoProjectScreenshotReference( + keyName = "add-item-add-button", + positions = listOf(DemoProjectScreenshotReferencePosition(1601, 359, 168, 86)), + ), + DemoProjectScreenshotReference( + keyName = "add-item-input-placeholder", + positions = listOf(DemoProjectScreenshotReferencePosition(617, 359, 951, 86)), + ), + DemoProjectScreenshotReference( + keyName = "delete-item-button", + positions = + listOf( + DemoProjectScreenshotReferencePosition(1637, 568, 116, 35), + DemoProjectScreenshotReferencePosition(1637, 637, 116, 35), + DemoProjectScreenshotReferencePosition(1637, 707, 116, 35), + ), + ), + DemoProjectScreenshotReference( + keyName = "menu-item-translation-methods", + positions = listOf(DemoProjectScreenshotReferencePosition(564, 27, 290, 60)), + ), + DemoProjectScreenshotReference( + keyName = "send-via-email", + positions = listOf(DemoProjectScreenshotReferencePosition(1439, 995, 331, 86)), + ), + DemoProjectScreenshotReference( + keyName = "share-button", + positions = listOf(DemoProjectScreenshotReferencePosition(1202, 995, 204, 86)), + ), + DemoProjectScreenshotReference( + keyName = "app-title", + positions = listOf(DemoProjectScreenshotReferencePosition(956, 181, 475, 91)), + ), + ) val inTranslatedState = mapOf("fr" to "add-item-add-button") val languages - get() = listOf( - Language().apply { - name = "English" - tag = "en" - originalName = "English" - flagEmoji = "🇬🇧" - }, - Language().apply { - name = "German" - tag = "de" - originalName = "Deutsch" - flagEmoji = "🇩🇪" - }, - Language().apply { - name = "French" - tag = "fr" - originalName = "Français" - flagEmoji = "🇫🇷" - }, - ) + get() = + listOf( + Language().apply { + name = "English" + tag = "en" + originalName = "English" + flagEmoji = "🇬🇧" + }, + Language().apply { + name = "German" + tag = "de" + originalName = "Deutsch" + flagEmoji = "🇩🇪" + }, + Language().apply { + name = "French" + tag = "fr" + originalName = "Français" + flagEmoji = "🇫🇷" + }, + ) data class DemoProjectScreenshotReference( val keyName: String, - val positions: List + val positions: List, ) data class DemoProjectScreenshotReferencePosition( val x: Int, val y: Int, val width: Int, - val height: Int + val height: Int, ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/email/EmailVerificationSender.kt b/backend/data/src/main/kotlin/io/tolgee/component/email/EmailVerificationSender.kt index ea21c5b63c..015def8bd5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/email/EmailVerificationSender.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/email/EmailVerificationSender.kt @@ -5,30 +5,32 @@ import org.springframework.stereotype.Component @Component class EmailVerificationSender( - private val tolgeeEmailSender: TolgeeEmailSender + private val tolgeeEmailSender: TolgeeEmailSender, ) { fun sendEmailVerification( userId: Long, email: String, resultCallbackUrl: String?, code: String, - isSignUp: Boolean = true + isSignUp: Boolean = true, ) { val url = "$resultCallbackUrl/$userId/$code" - val params = EmailParams( - to = email, - subject = "Tolgee e-mail verification", - text = """ - Hello! 👋

- ${if (isSignUp) "Welcome to Tolgee. Thanks for signing up. \uD83C\uDF89

" else ""} - - To verify your e-mail, follow this link:
- $url

- - Regards,
- Tolgee

- """.trimIndent() - ) + val params = + EmailParams( + to = email, + subject = "Tolgee e-mail verification", + text = + """ + Hello! 👋

+ ${if (isSignUp) "Welcome to Tolgee. Thanks for signing up. \uD83C\uDF89

" else ""} + + To verify your e-mail, follow this link:
+ $url

+ + Regards,
+ Tolgee

+ """.trimIndent(), + ) tolgeeEmailSender.sendEmail(params) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/email/InvitationEmailSender.kt b/backend/data/src/main/kotlin/io/tolgee/component/email/InvitationEmailSender.kt index cdf976783f..7d4c103b7c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/email/InvitationEmailSender.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/email/InvitationEmailSender.kt @@ -9,44 +9,46 @@ import org.springframework.web.util.HtmlUtils @Component class InvitationEmailSender( private val tolgeeEmailSender: TolgeeEmailSender, - private val frontendUrlProvider: FrontendUrlProvider + private val frontendUrlProvider: FrontendUrlProvider, ) { - fun sendInvitation( - invitation: Invitation, - ) { + fun sendInvitation(invitation: Invitation) { val email = invitation.email if (email.isNullOrBlank()) { return } val url = getInvitationAcceptUrl(invitation.code) - val params = EmailParams( - to = email, - subject = "Invitation to Tolgee", - text = """ - Hello! 👋

- Good news. ${getInvitationSentence(invitation)}

- - To accept the invitation, follow this link:
- $url

- - Regards,
- Tolgee

- """.trimIndent() - ) + val params = + EmailParams( + to = email, + subject = "Invitation to Tolgee", + text = + """ + Hello! 👋

+ Good news. ${getInvitationSentence(invitation)}

+ + To accept the invitation, follow this link:
+ $url

+ + Regards,
+ Tolgee

+ """.trimIndent(), + ) tolgeeEmailSender.sendEmail(params) } private fun getInvitationSentence(invitation: Invitation): Any { val projectNameOrNull = invitation.permission?.project?.name val organizationNameOrNull = invitation.organizationRole?.organization?.name - val toWhat = when { - projectNameOrNull != null -> "project" - organizationNameOrNull != null -> "organization" - else -> throw IllegalStateException("No organization or project!") - } + val toWhat = + when { + projectNameOrNull != null -> "project" + organizationNameOrNull != null -> "organization" + else -> throw IllegalStateException("No organization or project!") + } - val name = projectNameOrNull ?: organizationNameOrNull - ?: throw IllegalStateException("Both the organization and the project are null??") + val name = + projectNameOrNull ?: organizationNameOrNull + ?: throw IllegalStateException("Both the organization and the project are null??") val escapedName = HtmlUtils.htmlEscape(name) return "You have been invited to $toWhat $escapedName in Tolgee." diff --git a/backend/data/src/main/kotlin/io/tolgee/component/email/MimeMessageHelperFactory.kt b/backend/data/src/main/kotlin/io/tolgee/component/email/MimeMessageHelperFactory.kt index ec29c18783..c6f8f2f954 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/email/MimeMessageHelperFactory.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/email/MimeMessageHelperFactory.kt @@ -14,7 +14,7 @@ class MimeMessageHelperFactory( return MimeMessageHelper( message, MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED, - StandardCharsets.UTF_8.name() + StandardCharsets.UTF_8.name(), ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/email/TolgeeEmailSender.kt b/backend/data/src/main/kotlin/io/tolgee/component/email/TolgeeEmailSender.kt index 6c3e6c38ff..38931dde4b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/email/TolgeeEmailSender.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/email/TolgeeEmailSender.kt @@ -10,7 +10,7 @@ import org.springframework.stereotype.Component class TolgeeEmailSender( private val tolgeeProperties: TolgeeProperties, private val mailSender: JavaMailSender, - private val mimeMessageHelperFactory: MimeMessageHelperFactory + private val mimeMessageHelperFactory: MimeMessageHelperFactory, ) { fun sendEmail(params: EmailParams) { validateProps() @@ -18,14 +18,15 @@ class TolgeeEmailSender( helper.setFrom(tolgeeProperties.smtp.from!!) helper.setTo(params.to) helper.setSubject(params.subject) - val content = """ + val content = + """ ${params.text} - """.trimIndent() + """.trimIndent() helper.setText(content, true) params.attachments.forEach { @@ -35,7 +36,7 @@ class TolgeeEmailSender( helper.addInline( "logo.png", { ClassPathResource("tolgee-logo.png").inputStream }, - "image/png" + "image/png", ) mailSender.send(helper.mimeMessage) @@ -45,7 +46,8 @@ class TolgeeEmailSender( if (tolgeeProperties.smtp.from.isNullOrEmpty()) { throw IllegalStateException( """tolgee.smtp.from property not provided. - |You have to configure smtp properties to send an e-mail.""".trimMargin() + |You have to configure smtp properties to send an e-mail. + """.trimMargin(), ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/enabledFeaturesProvider/EnabledFeaturesProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/enabledFeaturesProvider/EnabledFeaturesProvider.kt index 98f2095ccb..4b6c591d0b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/enabledFeaturesProvider/EnabledFeaturesProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/enabledFeaturesProvider/EnabledFeaturesProvider.kt @@ -7,11 +7,17 @@ import io.tolgee.exceptions.BadRequestException interface EnabledFeaturesProvider { fun get(organizationId: Long): Array - fun isFeatureEnabled(organizationId: Long, feature: Feature): Boolean { + fun isFeatureEnabled( + organizationId: Long, + feature: Feature, + ): Boolean { return this.get(organizationId).contains(feature) } - fun checkFeatureEnabled(organizationId: Long, feature: Feature) { + fun checkFeatureEnabled( + organizationId: Long, + feature: Feature, + ) { if (!this.isFeatureEnabled(organizationId, feature)) { throw BadRequestException(Message.FEATURE_NOT_ENABLED, listOf(feature)) } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/eventListeners/LanguageStatsListener.kt b/backend/data/src/main/kotlin/io/tolgee/component/eventListeners/LanguageStatsListener.kt index ebd8188e57..625bbd6bb4 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/eventListeners/LanguageStatsListener.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/eventListeners/LanguageStatsListener.kt @@ -13,9 +13,8 @@ import org.springframework.transaction.event.TransactionalEventListener @Component class LanguageStatsListener( - private var languageStatsService: LanguageStatsService + private var languageStatsService: LanguageStatsService, ) { - var bypass = false @TransactionalEventListener @@ -26,10 +25,11 @@ class LanguageStatsListener( val projectId = event.activityRevision.projectId ?: return val modifiedEntityClasses = event.modifiedEntities.keys.toSet() - val isStatsModified = modifiedEntityClasses.contains(Language::class) || - modifiedEntityClasses.contains(Translation::class) || - modifiedEntityClasses.contains(Key::class) || - modifiedEntityClasses.contains(Project::class) + val isStatsModified = + modifiedEntityClasses.contains(Language::class) || + modifiedEntityClasses.contains(Translation::class) || + modifiedEntityClasses.contains(Key::class) || + modifiedEntityClasses.contains(Project::class) if (isStatsModified) { languageStatsService.refreshLanguageStats(projectId) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/eventListeners/MailServiceUserListener.kt b/backend/data/src/main/kotlin/io/tolgee/component/eventListeners/MailServiceUserListener.kt index edb7583cdb..6a0847a10a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/eventListeners/MailServiceUserListener.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/eventListeners/MailServiceUserListener.kt @@ -11,15 +11,14 @@ import org.springframework.transaction.event.TransactionalEventListener @Component class MailServiceUserListener( private val tolgeeProperties: TolgeeProperties, - private val marketingEmailServiceManager: MarketingEmailServiceManager + private val marketingEmailServiceManager: MarketingEmailServiceManager, ) { - @TransactionalEventListener(OnUserCreated::class) fun onUserCreated(event: OnUserCreated) { if (!tolgeeProperties.authentication.needsEmailVerification || event.userAccount.emailVerification == null) { marketingEmailServiceManager.submitNewContact( name = event.userAccount.name, - email = event.userAccount.username + email = event.userAccount.username, ) } } @@ -28,7 +27,7 @@ class MailServiceUserListener( fun onUserEmailVerifiedFirst(event: OnUserEmailVerifiedFirst) { marketingEmailServiceManager.submitNewContact( name = event.userAccount.name, - email = event.userAccount.username + email = event.userAccount.username, ) } @@ -41,7 +40,7 @@ class MailServiceUserListener( marketingEmailServiceManager.updateContact( oldEmail = event.oldUserAccount.username, newEmail = event.newUserAccount.username, - newName = event.newUserAccount.name + newName = event.newUserAccount.name, ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/AzureBlobFileStorage.kt b/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/AzureBlobFileStorage.kt index cdbac34729..d16f41a5fa 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/AzureBlobFileStorage.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/AzureBlobFileStorage.kt @@ -32,7 +32,10 @@ open class AzureBlobFileStorage( } } - override fun storeFile(storageFilePath: String, bytes: ByteArray) { + override fun storeFile( + storageFilePath: String, + bytes: ByteArray, + ) { try { val client = getBlobClient(storageFilePath) client.upload(BinaryData.fromBytes(bytes), true) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/AzureFileStorageFactory.kt b/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/AzureFileStorageFactory.kt index 38ec98a6e2..f48a97c8c9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/AzureFileStorageFactory.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/AzureFileStorageFactory.kt @@ -12,9 +12,10 @@ open class AzureFileStorageFactory { fun create(config: AzureBlobConfig): AzureBlobFileStorage { try { val connectionString = config.connectionString - val blobServiceClient = BlobServiceClientBuilder() - .connectionString(connectionString) - .buildClient() + val blobServiceClient = + BlobServiceClientBuilder() + .connectionString(connectionString) + .buildClient() val containerClient = blobServiceClient.getBlobContainerClient(config.containerName) return AzureBlobFileStorage(containerClient) } catch (e: Exception) { diff --git a/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/FileStorage.kt b/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/FileStorage.kt index 95abd71a18..c2ed185d95 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/FileStorage.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/FileStorage.kt @@ -4,9 +4,16 @@ import io.tolgee.exceptions.FileStoreException interface FileStorage { fun readFile(storageFilePath: String): ByteArray + fun deleteFile(storageFilePath: String) - fun storeFile(storageFilePath: String, bytes: ByteArray) + + fun storeFile( + storageFilePath: String, + bytes: ByteArray, + ) + fun fileExists(storageFilePath: String): Boolean + fun test() { try { this.storeFile("test", "test".toByteArray()) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/LocalFileStorage.kt b/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/LocalFileStorage.kt index 72ade34ec4..ff5cac0108 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/LocalFileStorage.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/LocalFileStorage.kt @@ -11,7 +11,6 @@ import java.io.File class LocalFileStorage( tolgeeProperties: TolgeeProperties, ) : FileStorage { - private val localDataPath = tolgeeProperties.fileStorage.fsDataPath override fun readFile(storageFilePath: String): ByteArray { @@ -30,7 +29,10 @@ class LocalFileStorage( } } - override fun storeFile(storageFilePath: String, bytes: ByteArray) { + override fun storeFile( + storageFilePath: String, + bytes: ByteArray, + ) { val file = getLocalFile(storageFilePath) try { file.parentFile.mkdirs() diff --git a/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/S3ClientProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/S3ClientProvider.kt index 057dd673ff..41c23042de 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/S3ClientProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/S3ClientProvider.kt @@ -15,9 +15,10 @@ class S3ClientProvider(private val s3config: S3Config) { fun provide(): S3Client { val credentialsProvider = getCredentialsProvider() - val builder = S3Client.builder().credentialsProvider(credentialsProvider).serviceConfiguration( - S3Configuration.builder().pathStyleAccessEnabled(true).build() - ) + val builder = + S3Client.builder().credentialsProvider(credentialsProvider).serviceConfiguration( + S3Configuration.builder().pathStyleAccessEnabled(true).build(), + ) if (!s3config.endpoint.isNullOrEmpty()) { builder.setEndpoint() } @@ -27,17 +28,20 @@ class S3ClientProvider(private val s3config: S3Config) { return builder.build() } - private fun getCredentialsProvider(): AwsCredentialsProvider? = when ( - s3config.accessKey.isNullOrEmpty() || - s3config.secretKey.isNullOrEmpty() - ) { - true -> DefaultCredentialsProvider.create() - false -> StaticCredentialsProvider.create( - AwsBasicCredentials.create( - s3config.accessKey, s3config.secretKey - ) - ) - } + private fun getCredentialsProvider(): AwsCredentialsProvider? = + when ( + s3config.accessKey.isNullOrEmpty() || + s3config.secretKey.isNullOrEmpty() + ) { + true -> DefaultCredentialsProvider.create() + false -> + StaticCredentialsProvider.create( + AwsBasicCredentials.create( + s3config.accessKey, + s3config.secretKey, + ), + ) + } private fun S3ClientBuilder.setEndpoint() { try { diff --git a/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/S3FileStorage.kt b/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/S3FileStorage.kt index 522e147110..2ed7a86b6e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/S3FileStorage.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/S3FileStorage.kt @@ -31,12 +31,15 @@ open class S3FileStorage( } } - override fun storeFile(storageFilePath: String, bytes: ByteArray) { + override fun storeFile( + storageFilePath: String, + bytes: ByteArray, + ) { val byteArrayInputStream = ByteArrayInputStream(bytes) try { s3.putObject( { b -> b.bucket(bucketName).key(storageFilePath) }, - RequestBody.fromInputStream(byteArrayInputStream, bytes.size.toLong()) + RequestBody.fromInputStream(byteArrayInputStream, bytes.size.toLong()), ) } catch (e: Exception) { throw FileStoreException("Can not store file using s3 bucket!", storageFilePath, e) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/TolgeeBlobClient.kt b/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/TolgeeBlobClient.kt index 63979a9b15..7a60af88ee 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/TolgeeBlobClient.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/fileStorage/TolgeeBlobClient.kt @@ -31,11 +31,12 @@ class TolgeeBlobClient(val client: BlobAsyncClient) : BlobClient(client) { override fun uploadWithResponse( options: BlobParallelUploadOptions, timeout: Duration?, - context: Context? + context: Context?, ): Response { Objects.requireNonNull(options) - val upload: Mono> = client.uploadWithResponse(options) - .contextWrite(FluxUtil.toReactorContext(context)) + val upload: Mono> = + client.uploadWithResponse(options) + .contextWrite(FluxUtil.toReactorContext(context)) try { return StorageImplUtils.blockWithOptionalTimeout(upload, timeout) @@ -48,7 +49,7 @@ class TolgeeBlobClient(val client: BlobAsyncClient) : BlobClient(client) { override fun uploadFromFileWithResponse( options: BlobUploadFromFileOptions?, timeout: Duration?, - context: Context? + context: Context?, ): Response { val upload: Mono> = this.client.uploadFromFileWithResponse(options) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/LanguageTagConvertor.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/LanguageTagConvertor.kt index e1718fcca9..9b483de1ef 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/LanguageTagConvertor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/LanguageTagConvertor.kt @@ -1,7 +1,10 @@ package io.tolgee.component.machineTranslation object LanguageTagConvertor { - fun findSuitableTag(suitableTags: Array, desiredLanguage: String): String? { + fun findSuitableTag( + suitableTags: Array, + desiredLanguage: String, + ): String? { if (suitableTags.contains(desiredLanguage)) { return desiredLanguage } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/MtEventListener.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/MtEventListener.kt index f278857186..485398f786 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/MtEventListener.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/MtEventListener.kt @@ -16,7 +16,7 @@ class MtEventListener( private val mtCreditBucketService: MtCreditBucketService, private val machineTranslationProperties: MachineTranslationProperties, private val publicBillingConfProvider: PublicBillingConfProvider, - private val entityManager: EntityManager + private val entityManager: EntityManager, ) { @EventListener(OnBeforeMachineTranslationEvent::class) @ExperimentalTime diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/MtServiceManager.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/MtServiceManager.kt index 001450fe49..4f26514538 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/MtServiceManager.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/MtServiceManager.kt @@ -31,9 +31,8 @@ import org.springframework.stereotype.Component class MtServiceManager( private val applicationContext: ApplicationContext, private val internalProperties: InternalProperties, - private val cacheManager: CacheManager + private val cacheManager: CacheManager, ) { - private val logger = LoggerFactory.getLogger(this::class.java) /** @@ -47,36 +46,35 @@ class MtServiceManager( targetLanguageTag: String, serviceInfos: Collection, metadata: Metadata?, - isBatch: Boolean + isBatch: Boolean, ): Map { return runBlocking(Dispatchers.IO) { serviceInfos.map { service -> async { - service to translate( - text = text, - textRaw = textRaw, - keyName = keyName, - sourceLanguageTag = sourceLanguageTag, - targetLanguageTag = targetLanguageTag, - serviceInfo = service, - metadata = metadata, - isBatch = isBatch - ) + service to + translate( + text = text, + textRaw = textRaw, + keyName = keyName, + sourceLanguageTag = sourceLanguageTag, + targetLanguageTag = targetLanguageTag, + serviceInfo = service, + metadata = metadata, + isBatch = isBatch, + ) } }.awaitAll().toMap() } } - private fun findInCache( - params: TranslationParams - ): TranslateResult? { + private fun findInCache(params: TranslationParams): TranslateResult? { return params.findInCacheByParams()?.let { TranslateResult( translatedText = it.translatedText, contextDescription = it.contextDescription, actualPrice = 0, usedService = params.serviceInfo.serviceType, - params.textRaw.isEmpty() + params.textRaw.isEmpty(), ) } } @@ -106,26 +104,28 @@ class MtServiceManager( } return try { - val translated = provider.translate( - ProviderTranslateParams( - params.text, - params.textRaw, - params.keyName, - params.sourceLanguageTag, - params.targetLanguageTag, - params.metadata, - params.serviceInfo.formality, - params.isBatch + val translated = + provider.translate( + ProviderTranslateParams( + params.text, + params.textRaw, + params.keyName, + params.sourceLanguageTag, + params.targetLanguageTag, + params.metadata, + params.serviceInfo.formality, + params.isBatch, + ), ) - ) - val translateResult = TranslateResult( - translated.translated, - translated.contextDescription, - translated.price, - params.serviceInfo.serviceType, - params.textRaw.isBlank() - ) + val translateResult = + TranslateResult( + translated.translated, + translated.contextDescription, + translated.price, + params.serviceInfo.serviceType, + params.textRaw.isBlank(), + ) params.cacheResult(translateResult) @@ -144,22 +144,26 @@ class MtServiceManager( private fun validate( provider: MtValueProvider, - params: TranslationParams + params: TranslationParams, ) { if (!provider.isLanguageSupported(params.targetLanguageTag)) { throw LanguageNotSupportedException(params.targetLanguageTag, params.serviceInfo.serviceType) } val formality = params.serviceInfo.formality - val requiresFormality = formality != null && - formality != Formality.DEFAULT + val requiresFormality = + formality != null && + formality != Formality.DEFAULT if (!provider.isLanguageFormalitySupported(params.targetLanguageTag) && requiresFormality) { throw FormalityNotSupportedException(params.targetLanguageTag, params.serviceInfo.serviceType) } } - private fun handleSilentFail(params: TranslationParams, e: Exception) { + private fun handleSilentFail( + params: TranslationParams, + e: Exception, + ) { val silentFail = !params.isBatch if (!silentFail) { throw e @@ -169,7 +173,7 @@ class MtServiceManager( |text "${params.text}" |from ${params.sourceLanguageTag} |to ${params.targetLanguageTag}" - """.trimMargin() + """.trimMargin(), ) logger.error(e.stackTraceToString()) Sentry.captureException(e) @@ -184,7 +188,7 @@ class MtServiceManager( targetLanguageTag: String, serviceInfo: MtServiceInfo, metadata: Metadata? = null, - isBatch: Boolean + isBatch: Boolean, ) = TranslationParams( text = text, textRaw = textRaw, @@ -193,14 +197,13 @@ class MtServiceManager( serviceInfo = serviceInfo, metadata = metadata, keyName = keyName, - isBatch = isBatch + isBatch = isBatch, ) - private fun getFaked( - params: TranslationParams - ): TranslateResult { - var fakedText = "${params.text} translated with ${params.serviceInfo.serviceType.name} " + - "from ${params.sourceLanguageTag} to ${params.targetLanguageTag}" + private fun getFaked(params: TranslationParams): TranslateResult { + var fakedText = + "${params.text} translated with ${params.serviceInfo.serviceType.name} " + + "from ${params.sourceLanguageTag} to ${params.targetLanguageTag}" if ((params.serviceInfo.formality ?: Formality.DEFAULT) !== Formality.DEFAULT) { fakedText += " ${params.serviceInfo.formality}" } @@ -209,7 +212,7 @@ class MtServiceManager( contextDescription = null, actualPrice = params.text.length * 100, usedService = params.serviceInfo.serviceType, - baseBlank = params.textRaw.isEmpty() + baseBlank = params.textRaw.isEmpty(), ) } @@ -235,7 +238,7 @@ class MtServiceManager( targetLanguageTag: String, serviceInfo: MtServiceInfo, metadata: Metadata? = null, - isBatch: Boolean = false + isBatch: Boolean = false, ): TranslateResult { val params = getParams(text, textRaw, keyName, sourceLanguageTag, targetLanguageTag, serviceInfo, metadata, isBatch) @@ -253,7 +256,7 @@ class MtServiceManager( targetLanguageTags: List, service: MtServiceInfo, metadata: Map? = null, - isBatch: Boolean + isBatch: Boolean, ): List { return translateToMultipleTargets( serviceInfo = service, @@ -263,7 +266,7 @@ class MtServiceManager( sourceLanguageTag = sourceLanguageTag, targetLanguageTags = targetLanguageTags, metadata = metadata, - isBatch = isBatch + isBatch = isBatch, ) } @@ -275,7 +278,7 @@ class MtServiceManager( sourceLanguageTag: String, targetLanguageTags: List, metadata: Map? = null, - isBatch: Boolean + isBatch: Boolean, ): List { return runBlocking(Dispatchers.IO) { targetLanguageTags.map { targetLanguageTag -> @@ -288,7 +291,7 @@ class MtServiceManager( targetLanguageTag, serviceInfo, metadata?.get(targetLanguageTag), - isBatch + isBatch, ) } }.awaitAll() diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/MtValueProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/MtValueProvider.kt index d4ecf9d0ec..e11662bfae 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/MtValueProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/MtValueProvider.kt @@ -25,7 +25,7 @@ interface MtValueProvider { data class MtResult( var translated: String?, val price: Int, - val contextDescription: String? = null + val contextDescription: String? = null, ) val formalitySupportingLanguages: Array? diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/TranslateResult.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/TranslateResult.kt index 7ccd4a2db6..4f2f7fe1b4 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/TranslateResult.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/TranslateResult.kt @@ -8,5 +8,5 @@ data class TranslateResult( var contextDescription: String?, var actualPrice: Int = 0, val usedService: MtServiceType? = null, - val baseBlank: Boolean + val baseBlank: Boolean, ) : Serializable diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/TranslationParams.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/TranslationParams.kt index a38fdb5836..74e4939572 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/TranslationParams.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/TranslationParams.kt @@ -12,10 +12,10 @@ data class TranslationParams( val targetLanguageTag: String, val serviceInfo: MtServiceInfo, val metadata: Metadata?, - val isBatch: Boolean + val isBatch: Boolean, ) { - val cacheKey: String - get() = jacksonObjectMapper() - .writeValueAsString(listOf(text, sourceLanguageTag, targetLanguageTag, serviceInfo, metadata)) + get() = + jacksonObjectMapper() + .writeValueAsString(listOf(text, sourceLanguageTag, targetLanguageTag, serviceInfo, metadata)) } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/metadata/ExampleItem.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/metadata/ExampleItem.kt index 5356e239fb..3d0652a00d 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/metadata/ExampleItem.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/metadata/ExampleItem.kt @@ -3,5 +3,5 @@ package io.tolgee.component.machineTranslation.metadata data class ExampleItem( val source: String, val target: String, - val key: String + val key: String, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/AbstractMtValueProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/AbstractMtValueProvider.kt index e5e1c63cec..c85ea3df17 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/AbstractMtValueProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/AbstractMtValueProvider.kt @@ -3,7 +3,6 @@ package io.tolgee.component.machineTranslation.providers import io.tolgee.component.machineTranslation.MtValueProvider abstract class AbstractMtValueProvider : MtValueProvider { - private val String.toSuitableTag: String? get() = getSuitableTag(this) @@ -19,14 +18,14 @@ abstract class AbstractMtValueProvider : MtValueProvider { if (suitableSourceTag.isNullOrEmpty() || suitableTargetTag.isNullOrEmpty()) { return MtValueProvider.MtResult( null, - 0 + 0, ) } if (suitableSourceTag == suitableTargetTag) { return MtValueProvider.MtResult( params.text, - 0 + 0, ) } @@ -34,7 +33,7 @@ abstract class AbstractMtValueProvider : MtValueProvider { params.apply { sourceLanguageTag = suitableSourceTag targetLanguageTag = suitableTargetTag - } + }, ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/AwsMtValueProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/AwsMtValueProvider.kt index 7ce0762803..64a8855946 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/AwsMtValueProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/AwsMtValueProvider.kt @@ -15,25 +15,27 @@ import software.amazon.awssdk.services.translate.model.Formality as AwsFormality @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON) class AwsMtValueProvider( private val awsMachineTranslationProperties: AwsMachineTranslationProperties, - private val amazonTranslate: TranslateClient? + private val amazonTranslate: TranslateClient?, ) : AbstractMtValueProvider() { override val isEnabled: Boolean - get() = awsMachineTranslationProperties.enabled - ?: (awsMachineTranslationProperties.accessKey != null && awsMachineTranslationProperties.secretKey != null) + get() = + awsMachineTranslationProperties.enabled + ?: (awsMachineTranslationProperties.accessKey != null && awsMachineTranslationProperties.secretKey != null) override fun translateViaProvider(params: ProviderTranslateParams): MtValueProvider.MtResult { - val result = translateService.translateText( - TranslateTextRequest.builder() - .sourceLanguageCode(params.sourceLanguageTag) - .targetLanguageCode(params.targetLanguageTag) - .settings(getSettings(params)) - .text(params.text) - .build() - ) + val result = + translateService.translateText( + TranslateTextRequest.builder() + .sourceLanguageCode(params.sourceLanguageTag) + .targetLanguageCode(params.targetLanguageTag) + .settings(getSettings(params)) + .text(params.text) + .build(), + ) return MtValueProvider.MtResult( result.translatedText(), - params.text.length * 100 + params.text.length * 100, ) } @@ -59,95 +61,97 @@ class AwsMtValueProvider( .build() } - override val formalitySupportingLanguages = arrayOf( - "nl", - "fr", - "fr-CA", - "de", - "hi", - "it", - "ja", - "ko", - "pt-PT", - "es", - "es-MX" - ) + override val formalitySupportingLanguages = + arrayOf( + "nl", + "fr", + "fr-CA", + "de", + "hi", + "it", + "ja", + "ko", + "pt-PT", + "es", + "es-MX", + ) - override val supportedLanguages = arrayOf( - "af", - "sq", - "am", - "ar", - "hy", - "az", - "bn", - "bs", - "bg", - "ca", - "zh", - "zh-TW", - "hr", - "cs", - "da ", - "fa-AF", - "nl ", - "en", - "et", - "fa", - "tl", - "fi", - "fr", - "fr-CA", - "ka", - "de", - "el", - "gu", - "ht", - "ha", - "he ", - "hi", - "hu", - "is", - "id ", - "ga", - "it", - "ja", - "kn", - "kk", - "ko", - "lv", - "lt", - "mk", - "ms", - "ml", - "mt", - "mr", - "mn", - "no", - "ps", - "pl", - "pt", - "pt-PT", - "pa", - "ro", - "ru", - "sr", - "si", - "sk", - "sl", - "so", - "es", - "es-MX", - "sw", - "sv", - "ta", - "te", - "th", - "tr", - "uk", - "ur", - "uz", - "vi", - "cy" - ) + override val supportedLanguages = + arrayOf( + "af", + "sq", + "am", + "ar", + "hy", + "az", + "bn", + "bs", + "bg", + "ca", + "zh", + "zh-TW", + "hr", + "cs", + "da ", + "fa-AF", + "nl ", + "en", + "et", + "fa", + "tl", + "fi", + "fr", + "fr-CA", + "ka", + "de", + "el", + "gu", + "ht", + "ha", + "he ", + "hi", + "hu", + "is", + "id ", + "ga", + "it", + "ja", + "kn", + "kk", + "ko", + "lv", + "lt", + "mk", + "ms", + "ml", + "mt", + "mr", + "mn", + "no", + "ps", + "pl", + "pt", + "pt-PT", + "pa", + "ro", + "ru", + "sr", + "si", + "sk", + "sl", + "so", + "es", + "es-MX", + "sw", + "sv", + "ta", + "te", + "th", + "tr", + "uk", + "ur", + "uz", + "vi", + "cy", + ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/AzureCognitiveApiService.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/AzureCognitiveApiService.kt index 4ee73ee762..7cc2e82e26 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/AzureCognitiveApiService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/AzureCognitiveApiService.kt @@ -20,23 +20,28 @@ class AzureCognitiveApiService( private val azureCognitiveTranslationProperties: AzureCognitiveTranslationProperties, private val restTemplate: RestTemplate, ) { - - fun translate(text: String, sourceTag: String, targetTag: String): String? { + fun translate( + text: String, + sourceTag: String, + targetTag: String, + ): String? { val headers = HttpHeaders() headers.add("Ocp-Apim-Subscription-Key", azureCognitiveTranslationProperties.authKey) // Optional when using a single-service Translator Resource - if (azureCognitiveTranslationProperties.region != null) + if (azureCognitiveTranslationProperties.region != null) { headers.add("Ocp-Apim-Subscription-Region", azureCognitiveTranslationProperties.region) + } headers.contentType = MediaType.APPLICATION_JSON val requestBody: List = listOf(AzureCognitiveRequest(text)) val request = HttpEntity(requestBody, headers) - val response: ResponseEntity> = restTemplate.exchange( - "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&from=$sourceTag&to=$targetTag", - HttpMethod.POST, - request - ) + val response: ResponseEntity> = + restTemplate.exchange( + "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&from=$sourceTag&to=$targetTag", + HttpMethod.POST, + request, + ) return response.body?.first?.translations?.first()?.text ?: throw RuntimeException(response.toString()) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/AzureCognitiveTranslationProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/AzureCognitiveTranslationProvider.kt index 93b9aea9f5..2ae2a05c4d 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/AzureCognitiveTranslationProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/AzureCognitiveTranslationProvider.kt @@ -10,32 +10,34 @@ import org.springframework.stereotype.Component @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON) class AzureCognitiveTranslationProvider( private val azureCognitiveTranslationProperties: AzureCognitiveTranslationProperties, - private val azureCognitiveApiService: AzureCognitiveApiService + private val azureCognitiveApiService: AzureCognitiveApiService, ) : AbstractMtValueProvider() { - override val isEnabled: Boolean get() = !azureCognitiveTranslationProperties.authKey.isNullOrEmpty() override fun translateViaProvider(params: ProviderTranslateParams): MtValueProvider.MtResult { - val result = azureCognitiveApiService.translate( - params.text, - params.sourceLanguageTag.uppercase(), - params.targetLanguageTag.uppercase() - ) + val result = + azureCognitiveApiService.translate( + params.text, + params.sourceLanguageTag.uppercase(), + params.targetLanguageTag.uppercase(), + ) return MtValueProvider.MtResult( result, - params.text.length * 100 + params.text.length * 100, ) } - override val supportedLanguages = arrayOf( - "af", "am", "ar", "as", "az", "ba", "bg", "bn", "bo", "bs", "ca", "cs", "cy", "da", "de", "dv", "el", "en", "es", - "et", "eu", "fa", "fi", "fil", "fj", "fo", "fr", "fr-CA", "ga", "gl", "gu", "he", "hi", "hr", "hsb", "ht", "hu", - "hy", "id", "ikt", "is", "it", "iu", "iu-Latn", "ja", "ka", "kk", "km", "kmr", "kn", "ko", "ku", "ky", "lo", "lt", - "lv", "lzh", "mg", "mi", "mk", "ml", "mn-Cyrl", "mn-Mong", "mr", "ms", "mt", "mww", "my", "nb", "ne", "nl", "or", - "otq", "pa", "pl", "prs", "ps", "pt", "pt-PT", "ro", "ru", "sk", "sl", "sm", "so", "sq", "sr-Cyrl", "sr-Latn", "sv", - "sw", "ta", "te", "th", "ti", "tk", "tlh-Latn", "tlh-Piqd", "to", "tr", "tt", "ty", "ug", "uk", "ur", "uz", "vi", - "yua", "yue", "zh-Hans", "zh-Hant", "zu" - ) + override val supportedLanguages = + arrayOf( + "af", "am", "ar", "as", "az", "ba", "bg", "bn", "bo", "bs", "ca", "cs", "cy", "da", "de", "dv", "el", "en", "es", + "et", "eu", "fa", "fi", "fil", "fj", "fo", "fr", "fr-CA", "ga", "gl", "gu", "he", "hi", "hr", "hsb", "ht", "hu", + "hy", "id", "ikt", "is", "it", "iu", "iu-Latn", "ja", "ka", "kk", "km", "kmr", "kn", "ko", "ku", "ky", "lo", "lt", + "lv", "lzh", "mg", "mi", "mk", "ml", "mn-Cyrl", "mn-Mong", "mr", "ms", "mt", "mww", "my", "nb", "ne", "nl", "or", + "otq", "pa", "pl", "prs", "ps", "pt", "pt-PT", "ro", "ru", "sk", "sl", "sm", "so", "sq", "sr-Cyrl", "sr-Latn", + "sv", + "sw", "ta", "te", "th", "ti", "tk", "tlh-Latn", "tlh-Piqd", "to", "tr", "tt", "ty", "ug", "uk", "ur", "uz", "vi", + "yua", "yue", "zh-Hans", "zh-Hant", "zu", + ) override val formalitySupportingLanguages: Array? = null } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/BaiduApiService.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/BaiduApiService.kt index 6f36e465af..03c5345c20 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/BaiduApiService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/BaiduApiService.kt @@ -19,8 +19,11 @@ class BaiduApiService( private val baiduMachineTranslationProperties: BaiduMachineTranslationProperties, private val restTemplate: RestTemplate, ) { - - fun translate(text: String, sourceTag: String, targetTag: String): String? { + fun translate( + text: String, + sourceTag: String, + targetTag: String, + ): String? { val headers = HttpHeaders() headers.contentType = MediaType.APPLICATION_FORM_URLENCODED @@ -40,10 +43,11 @@ class BaiduApiService( requestBody.add("action", action) requestBody.add("sign", signature.lowercase()) - val response = restTemplate.postForEntity( - "https://fanyi-api.baidu.com/api/trans/vip/translate", - requestBody - ) + val response = + restTemplate.postForEntity( + "https://fanyi-api.baidu.com/api/trans/vip/translate", + requestBody, + ) return response.body?.transResult?.first()?.dst ?: throw RuntimeException(response.toString()) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/BaiduTranslationProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/BaiduTranslationProvider.kt index 81308688b7..c903e77b77 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/BaiduTranslationProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/BaiduTranslationProvider.kt @@ -10,22 +10,23 @@ import org.springframework.stereotype.Component @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON) class BaiduTranslationProvider( private val baiduMachineTranslationProperties: BaiduMachineTranslationProperties, - private val baiduApiService: BaiduApiService + private val baiduApiService: BaiduApiService, ) : AbstractMtValueProvider() { - override val isEnabled: Boolean - get() = !baiduMachineTranslationProperties.appId.isNullOrEmpty() && - !baiduMachineTranslationProperties.appSecret.isNullOrEmpty() + get() = + !baiduMachineTranslationProperties.appId.isNullOrEmpty() && + !baiduMachineTranslationProperties.appSecret.isNullOrEmpty() override fun translateViaProvider(params: ProviderTranslateParams): MtValueProvider.MtResult { - val result = baiduApiService.translate( - params.text, - getLanguageTag(params.sourceLanguageTag), - getLanguageTag(params.targetLanguageTag) - ) + val result = + baiduApiService.translate( + params.text, + getLanguageTag(params.sourceLanguageTag), + getLanguageTag(params.targetLanguageTag), + ) return MtValueProvider.MtResult( result, - params.text.length * 100 + params.text.length * 100, ) } @@ -33,139 +34,141 @@ class BaiduTranslationProvider( return languageTagMap[tag.lowercase()] ?: tag.lowercase() } - override val supportedLanguages = arrayOf( - "yue", - "yue-hans", - "yue-hans-cn", - "kor", - "ko", - "ko-kr", - "th", - "th-th", - "pt", - "pt-pt", - "pt-br", - "el", - "el-gr", - "bul", - "bg", - "bg-bg", - "fin", - "fi", - "fi-fi", - "slo", - "sk", - "sk-sk", - "cht", - "zh-hant", - "zh-hant-hk", - "zh-hant-mo", - "zh-hant-tw", - "zh-tw", - "zh", - "zh-hans", - "zh-hans-cn", - "zh-hans-sg", - "zh-hans-hk", - "zh-hans-mo", - "wyw", - "fra", - "fr", - "fr-fr", - "ara", - "ar", - "de", - "de-de", - "nl", - "nl", - "nl-nl", - "est", - "et", - "et-ee", - "cs", - "cs-cz", - "swe", - "sl", - "sl-si", - "sv", - "sv-se", - "vie", - "vi", - "vi-vn", - "en", - "en-us", - "en-gb", - "jp", - "ja", - "ja-jp", - "spa", - "es", - "es-es", - "ru", - "ru-ru", - "it", - "it-it", - "pl", - "pl-pl", - "dan", - "da", - "da-dk", - "rom", - "ro", - "ro-ro", - "hu", - "hu-hu", - ) + override val supportedLanguages = + arrayOf( + "yue", + "yue-hans", + "yue-hans-cn", + "kor", + "ko", + "ko-kr", + "th", + "th-th", + "pt", + "pt-pt", + "pt-br", + "el", + "el-gr", + "bul", + "bg", + "bg-bg", + "fin", + "fi", + "fi-fi", + "slo", + "sk", + "sk-sk", + "cht", + "zh-hant", + "zh-hant-hk", + "zh-hant-mo", + "zh-hant-tw", + "zh-tw", + "zh", + "zh-hans", + "zh-hans-cn", + "zh-hans-sg", + "zh-hans-hk", + "zh-hans-mo", + "wyw", + "fra", + "fr", + "fr-fr", + "ara", + "ar", + "de", + "de-de", + "nl", + "nl", + "nl-nl", + "est", + "et", + "et-ee", + "cs", + "cs-cz", + "swe", + "sl", + "sl-si", + "sv", + "sv-se", + "vie", + "vi", + "vi-vn", + "en", + "en-us", + "en-gb", + "jp", + "ja", + "ja-jp", + "spa", + "es", + "es-es", + "ru", + "ru-ru", + "it", + "it-it", + "pl", + "pl-pl", + "dan", + "da", + "da-dk", + "rom", + "ro", + "ro-ro", + "hu", + "hu-hu", + ) override val formalitySupportingLanguages: Array? = null // https://fanyi-api.baidu.com/doc/21 // extracted commonly used only - val languageTagMap = mapOf( - // "yue" - // "kor" - "ko" to "kor", - // "th" - // "pt" - // "el" - // "bul" - "bg" to "bul", - // "fin" - "fi" to "fin", - // "slo" - "sl" to "slo", - // "sk" - // "cht" - "zh-hant" to "cht", - "zh-tw" to "cht", - // "zh" - "zh-hans" to "zh", - // "wyw" - // "fra" - "fr" to "fra", - // "ara" - "ar" to "ara", - // "de" - // "nl" - // "est" - "et" to "est", - // "cs" - // "swe" - "sv" to "swe", - // "vie" - "vi" to "vie", - // "en" - // "jp" - "ja" to "jp", - // "spa" - "es" to "spa", - // "ru" - // "it" - // "pl" - // "dan" - "da" to "dan", - // "rom" - "ro" to "rom", - // "hu" - ) + val languageTagMap = + mapOf( + // "yue" + // "kor" + "ko" to "kor", + // "th" + // "pt" + // "el" + // "bul" + "bg" to "bul", + // "fin" + "fi" to "fin", + // "slo" + "sl" to "slo", + // "sk" + // "cht" + "zh-hant" to "cht", + "zh-tw" to "cht", + // "zh" + "zh-hans" to "zh", + // "wyw" + // "fra" + "fr" to "fra", + // "ara" + "ar" to "ara", + // "de" + // "nl" + // "est" + "et" to "est", + // "cs" + // "swe" + "sv" to "swe", + // "vie" + "vi" to "vie", + // "en" + // "jp" + "ja" to "jp", + // "spa" + "es" to "spa", + // "ru" + // "it" + // "pl" + // "dan" + "da" to "dan", + // "rom" + "ro" to "rom", + // "hu" + ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/DeeplApiService.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/DeeplApiService.kt index 63cd40053f..7382f0a92b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/DeeplApiService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/DeeplApiService.kt @@ -19,8 +19,12 @@ class DeeplApiService( private val deeplMachineTranslationProperties: DeeplMachineTranslationProperties, private val restTemplate: RestTemplate, ) { - - fun translate(text: String, sourceTag: String, targetTag: String, formality: Formality): String? { + fun translate( + text: String, + sourceTag: String, + targetTag: String, + formality: Formality, + ): String? { val headers = HttpHeaders() headers.contentType = MediaType.APPLICATION_FORM_URLENCODED @@ -33,21 +37,26 @@ class DeeplApiService( addFormality(requestBody, formality) - val response = restTemplate.postForEntity( - apiEndpointFromKey(), - requestBody - ) + val response = + restTemplate.postForEntity( + apiEndpointFromKey(), + requestBody, + ) return response.body?.translations?.first()?.text ?: throw RuntimeException(response.toString()) } - private fun addFormality(requestBody: MultiValueMap, formality: Formality) { - val deeplFormality = when (formality) { - Formality.FORMAL -> "prefer_more" - Formality.INFORMAL -> "prefer_less" - else -> "default" - } + private fun addFormality( + requestBody: MultiValueMap, + formality: Formality, + ) { + val deeplFormality = + when (formality) { + Formality.FORMAL -> "prefer_more" + Formality.INFORMAL -> "prefer_less" + else -> "default" + } return requestBody.add("formality", deeplFormality) } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/DeeplTranslationProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/DeeplTranslationProvider.kt index b86f4a0dad..d93f13847c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/DeeplTranslationProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/DeeplTranslationProvider.kt @@ -11,23 +11,23 @@ import org.springframework.stereotype.Component @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON) class DeeplTranslationProvider( private val deeplMachineTranslationProperties: DeeplMachineTranslationProperties, - private val deeplApiService: DeeplApiService + private val deeplApiService: DeeplApiService, ) : AbstractMtValueProvider() { - override val isEnabled: Boolean get() = !deeplMachineTranslationProperties.authKey.isNullOrEmpty() override fun translateViaProvider(params: ProviderTranslateParams): MtValueProvider.MtResult { - val result = deeplApiService.translate( - params.text, - params.sourceLanguageTag.uppercase(), - params.targetLanguageTag.uppercase(), - getFormality(params) - ) + val result = + deeplApiService.translate( + params.text, + params.sourceLanguageTag.uppercase(), + params.targetLanguageTag.uppercase(), + getFormality(params), + ) return MtValueProvider.MtResult( result, - params.text.length * 100 + params.text.length * 100, ) } @@ -38,52 +38,54 @@ class DeeplTranslationProvider( return params.formality ?: Formality.DEFAULT } - override val formalitySupportingLanguages = arrayOf( - "de", - "es", - "fr", - "it", - "ja", - "nl", - "pl", - "pt-pt", - "pt-br", - "ru", - ) + override val formalitySupportingLanguages = + arrayOf( + "de", + "es", + "fr", + "it", + "ja", + "nl", + "pl", + "pt-pt", + "pt-br", + "ru", + ) - override val supportedLanguages = arrayOf( - "bg", - "cs", - "da", - "de", - "el", - "en", - "en-gb", - "en-us", - "es", - "et", - "fi", - "fr", - "hu", - "it", - "id", - "ja", - "ko", - "lt", - "lv", - "nb", - "nl", - "pl", - "pt", - "pt-pt", - "pt-br", - "ro", - "ru", - "sk", - "sl", - "sv", - "tr", - "uk", - "zh" - ) + override val supportedLanguages = + arrayOf( + "bg", + "cs", + "da", + "de", + "el", + "en", + "en-gb", + "en-us", + "es", + "et", + "fi", + "fr", + "hu", + "it", + "id", + "ja", + "ko", + "lt", + "lv", + "nb", + "nl", + "pl", + "pt", + "pt-pt", + "pt-br", + "ro", + "ru", + "sk", + "sl", + "sv", + "tr", + "uk", + "zh", + ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/GoogleTranslationProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/GoogleTranslationProvider.kt index 27be746cd4..f91eeb11d6 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/GoogleTranslationProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/GoogleTranslationProvider.kt @@ -11,21 +11,22 @@ import org.springframework.stereotype.Component @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON) class GoogleTranslationProvider( private val googleMachineTranslationProperties: GoogleMachineTranslationProperties, - private val translate: Translate? + private val translate: Translate?, ) : AbstractMtValueProvider() { override val isEnabled: Boolean get() = !googleMachineTranslationProperties.apiKey.isNullOrEmpty() override fun translateViaProvider(params: ProviderTranslateParams): MtValueProvider.MtResult { - val result = translateService.translate( - params.text, - Translate.TranslateOption.sourceLanguage(params.sourceLanguageTag), - Translate.TranslateOption.targetLanguage(params.targetLanguageTag), - Translate.TranslateOption.format("text") - ).translatedText + val result = + translateService.translate( + params.text, + Translate.TranslateOption.sourceLanguage(params.sourceLanguageTag), + Translate.TranslateOption.targetLanguage(params.targetLanguageTag), + Translate.TranslateOption.format("text"), + ).translatedText return MtValueProvider.MtResult( result, - params.text.length * 100 + params.text.length * 100, ) } @@ -33,118 +34,119 @@ class GoogleTranslationProvider( translate ?: throw IllegalStateException("Google Translate is not injected") } - override val supportedLanguages = arrayOf( - "af", - "sq", - "am", - "ar", - "hy", - "az", - "eu", - "be", - "bn", - "bs", - "bg", - "ca", - "ceb", - "ny", - "zh-CN", - "zh-TW", - "co", - "hr", - "cs", - "da", - "nl", - "en", - "eo", - "et", - "tl", - "fi", - "fr", - "fy", - "gl", - "ka", - "de", - "el", - "gu", - "ht", - "ha", - "haw", - "iw", - "hi", - "hmn", - "hu", - "is", - "ig", - "id", - "ga", - "it", - "ja", - "jw", - "kn", - "kk", - "km", - "rw", - "ko", - "ku", - "ky", - "lo", - "la", - "lv", - "lt", - "lb", - "mk", - "mg", - "ms", - "ml", - "mt", - "mi", - "mr", - "mn", - "my", - "ne", - "no", - "or", - "ps", - "fa", - "pl", - "pt", - "pa", - "ro", - "ru", - "sm", - "gd", - "sr", - "st", - "sn", - "sd", - "si", - "sk", - "sl", - "so", - "es", - "su", - "sw", - "sv", - "tg", - "ta", - "tt", - "te", - "th", - "tr", - "tk", - "uk", - "ur", - "ug", - "uz", - "vi", - "cy", - "xh", - "yi", - "yo", - "zu", - "he", - "zh" - ) + override val supportedLanguages = + arrayOf( + "af", + "sq", + "am", + "ar", + "hy", + "az", + "eu", + "be", + "bn", + "bs", + "bg", + "ca", + "ceb", + "ny", + "zh-CN", + "zh-TW", + "co", + "hr", + "cs", + "da", + "nl", + "en", + "eo", + "et", + "tl", + "fi", + "fr", + "fy", + "gl", + "ka", + "de", + "el", + "gu", + "ht", + "ha", + "haw", + "iw", + "hi", + "hmn", + "hu", + "is", + "ig", + "id", + "ga", + "it", + "ja", + "jw", + "kn", + "kk", + "km", + "rw", + "ko", + "ku", + "ky", + "lo", + "la", + "lv", + "lt", + "lb", + "mk", + "mg", + "ms", + "ml", + "mt", + "mi", + "mr", + "mn", + "my", + "ne", + "no", + "or", + "ps", + "fa", + "pl", + "pt", + "pa", + "ro", + "ru", + "sm", + "gd", + "sr", + "st", + "sn", + "sd", + "si", + "sk", + "sl", + "so", + "es", + "su", + "sw", + "sv", + "tg", + "ta", + "tt", + "te", + "th", + "tr", + "tk", + "uk", + "ur", + "ug", + "uz", + "vi", + "cy", + "xh", + "yi", + "yo", + "zu", + "he", + "zh", + ) override val formalitySupportingLanguages: Array? = null } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/ProviderTranslateParams.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/ProviderTranslateParams.kt index 752aa9d3ce..72351c9457 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/ProviderTranslateParams.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/ProviderTranslateParams.kt @@ -11,7 +11,6 @@ data class ProviderTranslateParams( var targetLanguageTag: String, val metadata: Metadata? = null, val formality: Formality? = null, - /** * Whether translation is executed as a part of batch translation task */ diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/TolgeeTranslateApiService.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/TolgeeTranslateApiService.kt index 93e98a3a2b..bf30c62042 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/TolgeeTranslateApiService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/TolgeeTranslateApiService.kt @@ -33,9 +33,8 @@ class TolgeeTranslateApiService( private val tolgeeMachineTranslationProperties: TolgeeMachineTranslationProperties, private val restTemplate: RestTemplate, private val tokenBucketManager: TokenBucketManager, - private val currentDateProvider: CurrentDateProvider + private val currentDateProvider: CurrentDateProvider, ) : Logging { - @OptIn(ExperimentalTime::class) fun translate(params: TolgeeTranslateParams): MtValueProvider.MtResult { val headers = HttpHeaders() @@ -44,40 +43,44 @@ class TolgeeTranslateApiService( params.metadata?.closeItems?.map { item -> TolgeeTranslateExample(item.key, item.source, item.target) } val examples = params.metadata?.examples?.map { item -> TolgeeTranslateExample(item.key, item.source, item.target) } - val requestBody = TolgeeTranslateRequest( - params.text, - params.keyName, - params.sourceTag, - params.targetTag, - examples, - closeItems, - priority = if (params.isBatch) "low" else "high", - params.formality - ) + val requestBody = + TolgeeTranslateRequest( + params.text, + params.keyName, + params.sourceTag, + params.targetTag, + examples, + closeItems, + priority = if (params.isBatch) "low" else "high", + params.formality, + ) val request = HttpEntity(requestBody, headers) checkPositiveRateLimitTokens(params) - val response: ResponseEntity = try { - val (value, time) = measureTimedValue { - restTemplate.exchange( - "${tolgeeMachineTranslationProperties.url}/api/openai/translate", - HttpMethod.POST, - request - ) + val response: ResponseEntity = + try { + val (value, time) = + measureTimedValue { + restTemplate.exchange( + "${tolgeeMachineTranslationProperties.url}/api/openai/translate", + HttpMethod.POST, + request, + ) + } + logger.debug("Translator request took ${time.inWholeMilliseconds} ms") + value + } catch (e: HttpClientErrorException.TooManyRequests) { + val data = e.parse() + emptyBucket(data) + val waitTime = data.retryAfter ?: 0 + logger.debug("Translator thrown TooManyRequests exception. Waiting for ${waitTime}s") + throw TranslationApiRateLimitException(currentDateProvider.date.time + (waitTime * 1000), e) } - logger.debug("Translator request took ${time.inWholeMilliseconds} ms") - value - } catch (e: HttpClientErrorException.TooManyRequests) { - val data = e.parse() - emptyBucket(data) - val waitTime = data.retryAfter ?: 0 - logger.debug("Translator thrown TooManyRequests exception. Waiting for ${waitTime}s") - throw TranslationApiRateLimitException(currentDateProvider.date.time + (waitTime * 1000), e) - } - val costString = response.headers.get("Mt-Credits-Cost")?.singleOrNull() - ?: throw IllegalStateException("No valid Credits-Cost header in response") + val costString = + response.headers.get("Mt-Credits-Cost")?.singleOrNull() + ?: throw IllegalStateException("No valid Credits-Cost header in response") val cost = costString.toInt() return MtValueProvider.MtResult( @@ -124,7 +127,7 @@ class TolgeeTranslateApiService( val examples: List?, val closeItems: List?, val priority: String = "low", - val formality: Formality? = null + val formality: Formality? = null, ) class TolgeeTranslateParams( @@ -134,13 +137,13 @@ class TolgeeTranslateApiService( val targetTag: String, val metadata: Metadata?, val formality: Formality?, - val isBatch: Boolean + val isBatch: Boolean, ) class TolgeeTranslateExample( var keyName: String, var source: String, - var target: String + var target: String, ) class TolgeeTranslateResponse(val output: String, val contextDescription: String?) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/TolgeeTranslationProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/TolgeeTranslationProvider.kt index 440d66e66a..37da6cdf98 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/TolgeeTranslationProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/machineTranslation/providers/TolgeeTranslationProvider.kt @@ -13,7 +13,6 @@ class TolgeeTranslationProvider( private val tolgeeMachineTranslationProperties: TolgeeMachineTranslationProperties, private val tolgeeTranslateApiService: TolgeeTranslateApiService, ) : AbstractMtValueProvider() { - override val isEnabled: Boolean get() = !tolgeeMachineTranslationProperties.url.isNullOrBlank() @@ -26,8 +25,8 @@ class TolgeeTranslationProvider( params.targetLanguageTag, params.metadataOrThrow(), params.formality, - params.isBatch - ) + params.isBatch, + ), ) } @@ -42,5 +41,6 @@ class TolgeeTranslationProvider( override val formalitySupportingLanguages = null override fun isLanguageSupported(tag: String): Boolean = true + override fun isLanguageFormalitySupported(tag: String): Boolean = true } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/mtBucketSizeProvider/FreeMtBucketSizeProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/mtBucketSizeProvider/FreeMtBucketSizeProvider.kt index d76ecf4ad8..c95dac7f85 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/mtBucketSizeProvider/FreeMtBucketSizeProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/mtBucketSizeProvider/FreeMtBucketSizeProvider.kt @@ -6,12 +6,15 @@ import org.springframework.stereotype.Component @Component class FreeMtBucketSizeProvider( - private val machineTranslationProperties: MachineTranslationProperties + private val machineTranslationProperties: MachineTranslationProperties, ) : MtBucketSizeProvider { override fun getSize(organization: Organization?): Long = machineTranslationProperties.freeCreditsAmount + override fun getPayAsYouGoAvailableCredits(organization: Organization?): Long = 0 + override fun isPayAsYouGo(organization: Organization?): Boolean { return false } + override fun getUsedPayAsYouGoCredits(organization: Organization?): Long = 0 } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/mtBucketSizeProvider/MtBucketSizeProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/mtBucketSizeProvider/MtBucketSizeProvider.kt index ffa6043c5d..a8f32f8882 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/mtBucketSizeProvider/MtBucketSizeProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/mtBucketSizeProvider/MtBucketSizeProvider.kt @@ -6,6 +6,8 @@ interface MtBucketSizeProvider { fun getSize(organization: Organization?): Long fun getPayAsYouGoAvailableCredits(organization: Organization?): Long + fun isPayAsYouGo(organization: Organization?): Boolean + fun getUsedPayAsYouGoCredits(organization: Organization?): Long } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/reporting/BusinessEventPublisher.kt b/backend/data/src/main/kotlin/io/tolgee/component/reporting/BusinessEventPublisher.kt index 4e352bd613..c606a694ce 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/reporting/BusinessEventPublisher.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/reporting/BusinessEventPublisher.kt @@ -24,9 +24,8 @@ class BusinessEventPublisher( private val authenticationFacade: AuthenticationFacade, private val cacheManager: CacheManager, private val currentDateProvider: CurrentDateProvider, - private val sdkInfoProvider: SdkInfoProvider + private val sdkInfoProvider: SdkInfoProvider, ) : Logging { - fun publish(request: BusinessEventReportRequest) { publish( OnBusinessEventToCaptureEvent( @@ -35,8 +34,8 @@ class BusinessEventPublisher( organizationId = request.organizationId, utmData = getUtmData(), data = request.data, - anonymousUserId = request.anonymousUserId - ) + anonymousUserId = request.anonymousUserId, + ), ) } @@ -44,12 +43,13 @@ class BusinessEventPublisher( applicationEventPublisher.publishEvent( event.copy( utmData = event.utmData ?: getUtmData(), - userAccountId = event.userAccountId - ?: event.userAccountDto?.id - ?: authenticationFacade.authenticatedUserOrNull?.id, + userAccountId = + event.userAccountId + ?: event.userAccountDto?.id + ?: authenticationFacade.authenticatedUserOrNull?.id, userAccountDto = event.userAccountDto ?: authenticationFacade.authenticatedUserOrNull, - data = getDataWithSdkInfo(event.data) - ) + data = getDataWithSdkInfo(event.data), + ), ) } @@ -58,8 +58,8 @@ class BusinessEventPublisher( applicationEventPublisher.publishEvent( OnIdentifyEvent( userAccountId = userId, - anonymousUserId = event.anonymousUserId - ) + anonymousUserId = event.anonymousUserId, + ), ) } } @@ -67,7 +67,7 @@ class BusinessEventPublisher( fun publishOnceInTime( event: OnBusinessEventToCaptureEvent, onceIn: Duration, - keyProvider: (e: OnBusinessEventToCaptureEvent) -> String = { it.eventName + "_" + it.userAccountId } + keyProvider: (e: OnBusinessEventToCaptureEvent) -> String = { it.eventName + "_" + it.userAccountId }, ) { val key = keyProvider(event) if (shouldPublishOnceInTime(key, onceIn)) { @@ -82,7 +82,7 @@ class BusinessEventPublisher( private fun shouldPublishOnceInTime( key: String, - onceIn: Duration + onceIn: Duration, ): Boolean { val cache = getEventThrottlingCache() val cached = @@ -116,7 +116,7 @@ class BusinessEventPublisher( fun getDataWithSdkInfo( sdkInfoMap: Map, - data: Map? + data: Map?, ): Map? { if (sdkInfoMap.values.all { it == null }) { return data diff --git a/backend/data/src/main/kotlin/io/tolgee/component/reporting/BusinessEventReporter.kt b/backend/data/src/main/kotlin/io/tolgee/component/reporting/BusinessEventReporter.kt index cf366cc65a..681a487bbd 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/reporting/BusinessEventReporter.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/reporting/BusinessEventReporter.kt @@ -18,7 +18,6 @@ class BusinessEventReporter( private val organizationService: OrganizationService, private val userAccountService: UserAccountService, ) { - @Lazy @Autowired private lateinit var selfProxied: BusinessEventReporter @@ -43,7 +42,7 @@ class BusinessEventReporter( "${'$'}identify", mapOf( "${'$'}anon_distinct_id" to data.anonymousUserId, - ) + getSetMapOfUserData(dto) + ) + getSetMapOfUserData(dto), ) } @@ -52,11 +51,12 @@ class BusinessEventReporter( val setEntry = getIdentificationMapForPostHog(data) postHog?.capture( - id.toString(), data.eventName, + id.toString(), + data.eventName, mapOf( "organizationId" to data.organizationId, "organizationName" to data.organizationName, - ) + (data.utmData ?: emptyMap()) + (data.data ?: emptyMap()) + setEntry + ) + (data.utmData ?: emptyMap()) + (data.data ?: emptyMap()) + setEntry, ) } @@ -67,24 +67,28 @@ class BusinessEventReporter( * or if instanceId is sent by self-hosted instance. */ private fun getIdentificationMapForPostHog(data: OnBusinessEventToCaptureEvent): Map { - val setEntry = data.userAccountDto?.let { userAccountDto -> - getSetMapOfUserData(userAccountDto) - } ?: data.instanceId?.let { - mapOf( - "${'$'}set" to mapOf( - "instanceId" to it + val setEntry = + data.userAccountDto?.let { userAccountDto -> + getSetMapOfUserData(userAccountDto) + } ?: data.instanceId?.let { + mapOf( + "${'$'}set" to + mapOf( + "instanceId" to it, + ), ) - ) - } ?: emptyMap() + } ?: emptyMap() return setEntry + getAnonIdMap(data) } - private fun getSetMapOfUserData(userAccountDto: UserAccountDto) = mapOf( - "${'$'}set" to mapOf( - "email" to userAccountDto.username, - "name" to userAccountDto.name, - ), - ) + private fun getSetMapOfUserData(userAccountDto: UserAccountDto) = + mapOf( + "${'$'}set" to + mapOf( + "email" to userAccountDto.username, + "name" to userAccountDto.name, + ), + ) fun getAnonIdMap(data: OnBusinessEventToCaptureEvent): Map { return ( @@ -93,7 +97,7 @@ class BusinessEventReporter( "${'$'}anon_distinct_id" to data.anonymousUserId, ) } - ) ?: emptyMap() + ) ?: emptyMap() } private fun fillOtherData(data: OnBusinessEventToCaptureEvent): OnBusinessEventToCaptureEvent { @@ -105,7 +109,7 @@ class BusinessEventReporter( projectDto = projectDto, organizationId = organizationId, organizationName = organizationName, - userAccountDto = userAccountDto + userAccountDto = userAccountDto, ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/reporting/BusinessEventReportingActivityListener.kt b/backend/data/src/main/kotlin/io/tolgee/component/reporting/BusinessEventReportingActivityListener.kt index dab0ac00c6..7652ae7d57 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/reporting/BusinessEventReportingActivityListener.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/reporting/BusinessEventReportingActivityListener.kt @@ -21,8 +21,8 @@ class BusinessEventReportingActivityListener( userAccountId = userId, projectId = projectId, utmData = event.utmData, - data = event.sdkInfo - ) + data = event.sdkInfo, + ), ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/reporting/OnIdentifyEvent.kt b/backend/data/src/main/kotlin/io/tolgee/component/reporting/OnIdentifyEvent.kt index e3f13ddac5..bb374fda48 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/reporting/OnIdentifyEvent.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/reporting/OnIdentifyEvent.kt @@ -2,5 +2,5 @@ package io.tolgee.component.reporting data class OnIdentifyEvent( val userAccountId: Long, - val anonymousUserId: String + val anonymousUserId: String, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/component/reporting/SdkInfoProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/reporting/SdkInfoProvider.kt index 930b50a056..5579089149 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/reporting/SdkInfoProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/reporting/SdkInfoProvider.kt @@ -11,7 +11,7 @@ class SdkInfoProvider() { val safeRequest = request ?: getRequest() ?: return null return mapOf( "sdkType" to safeRequest.getHeader("X-Tolgee-SDK-Type"), - "sdkVersion" to safeRequest.getHeader("X-Tolgee-SDK-Version") + "sdkVersion" to safeRequest.getHeader("X-Tolgee-SDK-Version"), ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/reporting/SignUpListener.kt b/backend/data/src/main/kotlin/io/tolgee/component/reporting/SignUpListener.kt index 8ff13a20e7..7a34f3e7f0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/reporting/SignUpListener.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/reporting/SignUpListener.kt @@ -10,7 +10,7 @@ import org.springframework.transaction.event.TransactionalEventListener @Component class SignUpListener( private val businessEventPublisher: BusinessEventPublisher, - private val organizationService: OrganizationService + private val organizationService: OrganizationService, ) { @TransactionalEventListener(OnUserCreated::class) fun listen(onUserCreated: OnUserCreated) { @@ -25,8 +25,8 @@ class SignUpListener( organizationId = organization?.id, organizationName = organization?.name, userAccountId = user.id, - userAccountDto = UserAccountDto.fromEntity(user) - ) + userAccountDto = UserAccountDto.fromEntity(user), + ), ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/translationsLimitProvider/BaseTranslationsLimitProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/translationsLimitProvider/BaseTranslationsLimitProvider.kt index 8e5de506dc..83bb3bfc73 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/translationsLimitProvider/BaseTranslationsLimitProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/translationsLimitProvider/BaseTranslationsLimitProvider.kt @@ -6,7 +6,10 @@ import org.springframework.stereotype.Component @Component class BaseTranslationsLimitProvider : TranslationsLimitProvider { override fun getTranslationSlotsLimit(organization: Organization?): Long = -1 + override fun getTranslationLimit(organization: Organization?): Long = -1 + override fun getPlanTranslations(organization: Organization?): Long = -1 + override fun getPlanTranslationSlots(organization: Organization?): Long = -1 } diff --git a/backend/data/src/main/kotlin/io/tolgee/component/translationsLimitProvider/TranslationsLimitProvider.kt b/backend/data/src/main/kotlin/io/tolgee/component/translationsLimitProvider/TranslationsLimitProvider.kt index 55f490daf6..cb2309fe2f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/component/translationsLimitProvider/TranslationsLimitProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/component/translationsLimitProvider/TranslationsLimitProvider.kt @@ -16,5 +16,6 @@ interface TranslationsLimitProvider { fun getTranslationLimit(organization: Organization?): Long fun getPlanTranslations(organization: Organization?): Long + fun getPlanTranslationSlots(organization: Organization?): Long } diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/LiquibaseConfiguration.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/LiquibaseConfiguration.kt index afb90ef102..e413a51a79 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/LiquibaseConfiguration.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/LiquibaseConfiguration.kt @@ -11,7 +11,10 @@ import javax.sql.DataSource class LiquibaseConfiguration { @Bean @Primary - fun liquibase(dataSource: DataSource, postgresRunner: PostgresRunner?): SpringLiquibase { + fun liquibase( + dataSource: DataSource, + postgresRunner: PostgresRunner?, + ): SpringLiquibase { val liquibase = SpringLiquibase() liquibase.setShouldRun(postgresRunner?.shouldRunMigrations != false) liquibase.dataSource = dataSource diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/PostHogConfiguration.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/PostHogConfiguration.kt index 42437ef787..c5de561cca 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/PostHogConfiguration.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/PostHogConfiguration.kt @@ -7,9 +7,8 @@ import org.springframework.context.annotation.Configuration @Configuration class PostHogConfiguration( - private val properties: PostHogProperties + private val properties: PostHogProperties, ) { - @Bean(destroyMethod = "shutdown") fun postHog(): PostHog? { return properties.apiKey?.let { postHogApiKey -> diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/SendInBlueConfiguration.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/SendInBlueConfiguration.kt index 07bec9e25b..c60ac2fc43 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/SendInBlueConfiguration.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/SendInBlueConfiguration.kt @@ -9,9 +9,8 @@ import sibApi.ContactsApi @Configuration class SendInBlueConfiguration( - private val sendInBlueProperties: SendInBlueProperties + private val sendInBlueProperties: SendInBlueProperties, ) { - @Bean fun sendInBlueContactsApi(): ContactsApi? { if (sendInBlueProperties.apiKey != null) { diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/annotations/DocProperty.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/annotations/DocProperty.kt index 7f29f04fdc..82426ab700 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/annotations/DocProperty.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/annotations/DocProperty.kt @@ -11,5 +11,5 @@ annotation class DocProperty( val prefix: String = "", val removedIn: String = "", val removalReason: String = "", - val hidden: Boolean = false + val hidden: Boolean = false, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/AuthenticationProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/AuthenticationProperties.kt index 0cfa212f4d..59ded4749e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/AuthenticationProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/AuthenticationProperties.kt @@ -15,17 +15,19 @@ import org.springframework.boot.context.properties.ConfigurationProperties properties = [ DocProperty( name = "userCanCreateProjects", - description = "Whether regular users are allowed to create projects. " + - "When disabled, only administrators can create projects", + description = + "Whether regular users are allowed to create projects. " + + "When disabled, only administrators can create projects", removedIn = "2.33.0", - defaultValue = "true" + defaultValue = "true", ), DocProperty( name = "createInitialUser", description = "If true, Tolgee creates initial user on first start-up.", removedIn = "3.31.0", - removalReason = "Presence of this initial account is now expected for Tolgee to operate as expected.\n" + - "For instance, when authentication is disabled, users are automatically logged in as this admin user.", + removalReason = + "Presence of this initial account is now expected for Tolgee to operate as expected.\n" + + "For instance, when authentication is disabled, users are automatically logged in as this admin user.", defaultValue = "true", ), DocProperty( @@ -40,99 +42,99 @@ import org.springframework.boot.context.properties.ConfigurationProperties class AuthenticationProperties( @E2eRuntimeMutable @DocProperty( - description = "Whether authentication is enabled. " + - "When authentication is disabled, there are no login screen and no permission control. " + - "Users get automatically logged in as the administrator account of the Tolgee instance. " + - "This is very useful, when you want to use Tolgee on your local machine, or you just want to test it. ", - defaultExplanation = "when running with Java directly, `false` when running via Docker." + description = + "Whether authentication is enabled. " + + "When authentication is disabled, there are no login screen and no permission control. " + + "Users get automatically logged in as the administrator account of the Tolgee instance. " + + "This is very useful, when you want to use Tolgee on your local machine, or you just want to test it. ", + defaultExplanation = "when running with Java directly, `false` when running via Docker.", ) var enabled: Boolean = true, - @DocProperty( - description = "Secret used to sign JWT authentication tokens with. It will be generated " + - "automatically, if not provided. You will be fine with 64 characters long random string.\n\n" + - ":::warning\n" + - "When running multiple replicas, it is required to set it, or you will be constantly logged out otherwise.\n" + - ":::\n\n" + description = + "Secret used to sign JWT authentication tokens with. It will be generated " + + "automatically, if not provided. You will be fine with 64 characters long random string.\n\n" + + ":::warning\n" + + "When running multiple replicas, it is required to set it, or you will be constantly logged out otherwise.\n" + + ":::\n\n", ) @Size(min = 32) var jwtSecret: String? = null, - @DocProperty( description = "Expiration time of generated JWT tokens in milliseconds.", - defaultExplanation = "= 7 days" + defaultExplanation = "= 7 days", ) var jwtExpiration: Long = 7 * 24 * 60 * 60 * 1000, - @DocProperty( description = "Expiration time of generated JWT tokens for superuser in milliseconds.", - defaultExplanation = "= 1 hour" + defaultExplanation = "= 1 hour", ) var jwtSuperExpiration: Long = 60 * 60 * 1000, - @DocProperty( - description = "Whether to enable Tolgee-native authentication and registration.\n" + - "When set to `false`, users will only be able to register and login via third-party SSO options (e.g. OAuth)." + description = + "Whether to enable Tolgee-native authentication and registration.\n" + + "When set to `false`, users will only be able to register and login via third-party SSO options (e.g. OAuth).", ) var nativeEnabled: Boolean = true, - @E2eRuntimeMutable @DocProperty( - description = "Whether users are allowed to register on Tolgee.\n" + - "When set to `false`, existing users must send invites to projects to new users for them to be able to register." + description = + "Whether users are allowed to register on Tolgee.\n" + + "When set to `false`, existing users must send invites " + + "to projects to new users for them to be able to register.", ) var registrationsAllowed: Boolean = false, - @E2eRuntimeMutable @DocProperty( - description = "Whether users need to verify their email addresses when creating their account. " + - "Requires a valid [SMTP configuration](#SMTP)." + description = + "Whether users need to verify their email addresses when creating their account. " + + "Requires a valid [SMTP configuration](#SMTP).", ) var needsEmailVerification: Boolean = false, - @DocProperty( - description = "Username of initial user.\n\n" + - ":::tip\n" + - "Tolgee will ask for an email instead of a username - don't worry, just give it the username specified here.\n" + - ":::\n\n" + description = + "Username of initial user.\n\n" + + ":::tip\n" + + "Tolgee will ask for an email instead of a username - don't worry, " + + "just give it the username specified here.\n" + + ":::\n\n", ) var initialUsername: String = "admin", - @DocProperty( - description = "Password of initial user. If unspecified, a random password will be generated " + - "and stored in the `initial.pwd` file, located at the root of Tolgee's data path.\n\n" + - ":::tip\n" + - "Once set, you don't need to set this property anymore, and it is recommended you unset it so the password is " + - "not stored in plaintext in config files.\n\n" + - "If you set this field to something else, the initial user's password will be updated **unless the password " + - "was updated once via the Tolgee web UI**.\n" + - ":::\n\n" + description = + "Password of initial user. If unspecified, a random password will be generated " + + "and stored in the `initial.pwd` file, located at the root of Tolgee's data path.\n\n" + + ":::tip\n" + + "Once set, you don't need to set this property anymore, " + + "and it is recommended you unset it so the password is " + + "not stored in plaintext in config files.\n\n" + + "If you set this field to something else, the initial user's password will be updated **unless the password " + + "was updated once via the Tolgee web UI**.\n" + + ":::\n\n", ) var initialPassword: String? = null, - @DocProperty( - description = "Whether image assets should be protected by Tolgee. " + - "When enabled, all images are served with an access token valid for\n" + - "a set period of time to prevent unauthorized access to images." + description = + "Whether image assets should be protected by Tolgee. " + + "When enabled, all images are served with an access token valid for\n" + + "a set period of time to prevent unauthorized access to images.", ) var securedImageRetrieval: Boolean = false, - @DocProperty( description = "Expiration time of a generated image access token in milliseconds.", - defaultExplanation = "= 10 minutes" + defaultExplanation = "= 10 minutes", ) var securedImageTimestampMaxAge: Long = 10 * 60 * 1000, - @E2eRuntimeMutable @DocProperty( - description = "Whether regular users are allowed to create organizations. " + - "When `false`, only administrators can create organizations.\n" + - "By default, when the user has no organization, one is created for them; " + - "this doesn't apply when this setting is set to `false`. " + - "In that case, the user without organization has no permissions on the server.", + description = + "Whether regular users are allowed to create organizations. " + + "When `false`, only administrators can create organizations.\n" + + "By default, when the user has no organization, one is created for them; " + + "this doesn't apply when this setting is set to `false`. " + + "In that case, the user without organization has no permissions on the server.", ) var userCanCreateOrganizations: Boolean = true, - var github: GithubAuthenticationProperties = GithubAuthenticationProperties(), var google: GoogleAuthenticationProperties = GoogleAuthenticationProperties(), var oauth2: OAuth2AuthenticationProperties = OAuth2AuthenticationProperties(), diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/CacheProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/CacheProperties.kt index 49c144f315..327393f0b6 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/CacheProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/CacheProperties.kt @@ -5,41 +5,41 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.cache") @DocProperty( - description = "At the expense of higher memory footprint, " + - "Tolgee can use a cache to reduce the stress on the database and fetch the\n" + - "data it needs faster. Cache is also used to track certain states, such as rate limits.", - displayName = "Cache" + description = + "At the expense of higher memory footprint, " + + "Tolgee can use a cache to reduce the stress on the database and fetch the\n" + + "data it needs faster. Cache is also used to track certain states, such as rate limits.", + displayName = "Cache", ) class CacheProperties( @DocProperty(description = "Whether Tolgee should use a cache.") var enabled: Boolean = false, - @DocProperty( - description = "Whether Tolgee should use Redis to store cache data instead of storing it in-memory.\n" + - ":::info\n" + - "In a distributed environment, you **should** use a Redis server " + - "to ensure consistent enforcement of rate limits, as\n" + - "they heavily rely on cache. For a simple single-node deployment, in-memory cache is sufficient.\n" + - ":::\n" + - "\n" + - ":::info\n" + - "Tolgee uses [Redisson](https://github.com/redisson/redisson) to interface with the Redis server. " + - "You can find the properties Redisson expects [here]" + - "(https://github.com/redisson/redisson/tree/56ea7f5/redisson-spring-boot-starter" + - "#2-add-settings-into-applicationsettings-file).\n" + - ":::\n\n" + description = + "Whether Tolgee should use Redis to store cache data instead of storing it in-memory.\n" + + ":::info\n" + + "In a distributed environment, you **should** use a Redis server " + + "to ensure consistent enforcement of rate limits, as\n" + + "they heavily rely on cache. For a simple single-node deployment, in-memory cache is sufficient.\n" + + ":::\n" + + "\n" + + ":::info\n" + + "Tolgee uses [Redisson](https://github.com/redisson/redisson) to interface with the Redis server. " + + "You can find the properties Redisson expects [here]" + + "(https://github.com/redisson/redisson/tree/56ea7f5/redisson-spring-boot-starter" + + "#2-add-settings-into-applicationsettings-file).\n" + + ":::\n\n", ) var useRedis: Boolean = false, - @DocProperty(description = "TTL of cache data, in milliseconds.", defaultExplanation = "≈ 2 hours") var defaultTtl: Long = 120 * 60 * 1000, - @DocProperty( - description = "Maximum size of the Caffeine cache. " + - "When exceeded, some entries will be purged from cache. Set to -1 to disable size limitation.\n" + - "This has no effect when Redis cache is used. See\n" + - "[Caffeine's documentation about size-based eviction]" + - "(https://github.com/ben-manes/caffeine/wiki/Eviction#size-based)" + description = + "Maximum size of the Caffeine cache. " + + "When exceeded, some entries will be purged from cache. Set to -1 to disable size limitation.\n" + + "This has no effect when Redis cache is used. See\n" + + "[Caffeine's documentation about size-based eviction]" + + "(https://github.com/ben-manes/caffeine/wiki/Eviction#size-based)", ) var caffeineMaxSize: Long = -1, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/ContentDeliveryProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/ContentDeliveryProperties.kt index bd10478c36..5671949e1d 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/ContentDeliveryProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/ContentDeliveryProperties.kt @@ -6,13 +6,15 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.content-delivery") @DocProperty( displayName = "Content Delivery", - description = "These properties are used to configure " + - "default server content delivery storage." + description = + "These properties are used to configure " + + "default server content delivery storage.", ) class ContentDeliveryProperties { @DocProperty( - description = "The root path where the content is accessible by the public. If this property is not null. " + - "Content delivery will be enabled on your server." + description = + "The root path where the content is accessible by the public. If this property is not null. " + + "Content delivery will be enabled on your server.", ) var publicUrlPrefix: String? = null diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/FileStorageProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/FileStorageProperties.kt index c3fc9e8228..c68a5b77dc 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/FileStorageProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/FileStorageProperties.kt @@ -11,11 +11,10 @@ import org.springframework.boot.context.properties.ConfigurationProperties @DocProperty(description = "Configuration of Tolgee file storage.", displayName = "File storage") class FileStorageProperties( var s3: S3Settings = S3Settings(), - @DocProperty( description = "Path to directory where Tolgee will store its files.", defaultExplanation = ", with docker `/data/`", - defaultValue = "~/.tolgee/" + defaultValue = "~/.tolgee/", ) var fsDataPath: String = """${System.getProperty("user.home")}/.tolgee""", ) diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/GithubAuthenticationProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/GithubAuthenticationProperties.kt index 21da46af00..f177137dab 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/GithubAuthenticationProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/GithubAuthenticationProperties.kt @@ -5,10 +5,11 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.authentication.github") @DocProperty( - description = ":::info\n" + - "GitHub authentication can be used in combination with native authentication.\n" + - ":::\n\n", - displayName = "GitHub" + description = + ":::info\n" + + "GitHub authentication can be used in combination with native authentication.\n" + + ":::\n\n", + displayName = "GitHub", ) class GithubAuthenticationProperties { @DocProperty(description = "OAuth Client ID, obtained in GitHub administration.") @@ -18,14 +19,16 @@ class GithubAuthenticationProperties { var clientSecret: String? = null @DocProperty( - description = "URL to the OAuth authorization screen. " + - "Useful if you want to authenticate against a self-hosted GitHub Enterprise Server." + description = + "URL to the OAuth authorization screen. " + + "Useful if you want to authenticate against a self-hosted GitHub Enterprise Server.", ) var authorizationUrl: String = "https://github.com/login/oauth/access_token" @DocProperty( - description = "URL to GitHub's `/user` API endpoint. " + - "Useful if you want to authenticate against a self-hosted GitHub Enterprise Server." + description = + "URL to GitHub's `/user` API endpoint. " + + "Useful if you want to authenticate against a self-hosted GitHub Enterprise Server.", ) var userUrl: String = "https://api.github.com/user" } diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/GoogleAuthenticationProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/GoogleAuthenticationProperties.kt index 9363cbdc8d..0ecbd98610 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/GoogleAuthenticationProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/GoogleAuthenticationProperties.kt @@ -5,9 +5,10 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.authentication.google") @DocProperty( - description = "The following instructions explain how to set up Google OAuth. " + - "[Setting up OAuth 2.0](https://support.google.com/cloud/answer/6158849).", - displayName = "Google" + description = + "The following instructions explain how to set up Google OAuth. " + + "[Setting up OAuth 2.0](https://support.google.com/cloud/answer/6158849).", + displayName = "Google", ) class GoogleAuthenticationProperties { @DocProperty(description = "OAuth Client ID, obtained in Google Cloud Console.") @@ -17,8 +18,9 @@ class GoogleAuthenticationProperties { var clientSecret: String? = null @DocProperty( - description = "The registration can be limited to users of a Google Workspace domain. " + - "If nothing is set, anyone can log in with their Google account." + description = + "The registration can be limited to users of a Google Workspace domain. " + + "If nothing is set, anyone can log in with their Google account.", ) var workspaceDomain: String? = null diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/HibernateConfiguration.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/HibernateConfiguration.kt index 78f8c3e708..7cf14c5ba0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/HibernateConfiguration.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/HibernateConfiguration.kt @@ -7,7 +7,6 @@ import org.springframework.context.annotation.Configuration @Configuration class HibernateConfiguration : HibernatePropertiesCustomizer { - @Autowired lateinit var activityInterceptor: ActivityDatabaseInterceptor diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/ImportProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/ImportProperties.kt index a0eae6b76e..6c19c01b66 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/ImportProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/ImportProperties.kt @@ -5,36 +5,39 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.import") @DocProperty( - description = "Bulk-imports exported json files in the database during startup. " + - "Useful to quickly provision a development server, and used for testing.", - displayName = "Import" + description = + "Bulk-imports exported json files in the database during startup. " + + "Useful to quickly provision a development server, and used for testing.", + displayName = "Import", ) class ImportProperties { @DocProperty( - description = "File path of the directory where the files to import are located.\n" + - "\n" + - ":::info\n" + - "Your folder structure should look like:\n" + - "importDir\n" + - "└─Project # the foler name is the project name\n" + - " └─validation # the foler name is namespace\n" + - " ├─ en.json # the file name is the target language\n" + - " └─ de.json # second project language\n" + - ":::\n\n" + description = + "File path of the directory where the files to import are located.\n" + + "\n" + + ":::info\n" + + "Your folder structure should look like:\n" + + "importDir\n" + + "└─Project # the foler name is the project name\n" + + " └─validation # the foler name is namespace\n" + + " ├─ en.json # the file name is the target language\n" + + " └─ de.json # second project language\n" + + ":::\n\n", ) var dir: String? = null @DocProperty( - description = "Whether an implicit API key should be created.\n" + - "\n" + - "The key is built with a predictable format: " + - "`\${lowercase filename (without extension)}-\${initial username}-imported-project-implicit`\n" + - "\n" + - ":::danger\n" + - "While this is useful for tests, make sure to keep this **disabled** " + - "if you're importing projects on a production server as trying this predictable key " + - "may be the first thing an attacker will attempt to gain unauthorized access!\n" + - ":::\n\n" + description = + "Whether an implicit API key should be created.\n" + + "\n" + + "The key is built with a predictable format: " + + "`\${lowercase filename (without extension)}-\${initial username}-imported-project-implicit`\n" + + "\n" + + ":::danger\n" + + "While this is useful for tests, make sure to keep this **disabled** " + + "if you're importing projects on a production server as trying this predictable key " + + "may be the first thing an attacker will attempt to gain unauthorized access!\n" + + ":::\n\n", ) var createImplicitApiKey: Boolean = false diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/OAuth2AuthenticationProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/OAuth2AuthenticationProperties.kt index 6cb6203c54..7d5b0b1678 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/OAuth2AuthenticationProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/OAuth2AuthenticationProperties.kt @@ -5,10 +5,11 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.authentication.oauth2") @DocProperty( - description = "OAuth 2.0 is the industry-standard protocol for authorization.\n" + - "This enables the integration of a wide range of authorization providers into tolgee, " + - "such as Auth0, KeyCloak, Okta and others.", - displayName = "OAuth2" + description = + "OAuth 2.0 is the industry-standard protocol for authorization.\n" + + "This enables the integration of a wide range of authorization providers into tolgee, " + + "such as Auth0, KeyCloak, Okta and others.", + displayName = "OAuth2", ) class OAuth2AuthenticationProperties { @DocProperty(description = "OAuth2 Client ID") @@ -18,10 +19,11 @@ class OAuth2AuthenticationProperties { var clientSecret: String? = null @DocProperty( - description = "Oauth2 scopes (as list)\n" + - "Tolgee absolutely requires rights to view the email and user information (also known as openid data).\n" + - "In most cases the scopes `openid email profile` is used for this. " + - "(But can also be different depending on the provider)" + description = + "Oauth2 scopes (as list)\n" + + "Tolgee absolutely requires rights to view the email and user information (also known as openid data).\n" + + "In most cases the scopes `openid email profile` is used for this. " + + "(But can also be different depending on the provider)", ) val scopes: MutableList = mutableListOf() diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/PostgresAutostartProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/PostgresAutostartProperties.kt index 832bd499f6..2579de5ae8 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/PostgresAutostartProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/PostgresAutostartProperties.kt @@ -6,21 +6,22 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.postgres-autostart") @DocProperty( description = "Defines whether and how is PostgreSQL started on Tolgee startup.", - displayName = "Postgres autostart" + displayName = "Postgres autostart", ) class PostgresAutostartProperties { @DocProperty(description = "Whether to start PostgreSQL on Tolgee startup.") var enabled: Boolean = true @DocProperty( - description = "How is Tolgee running PostgreSQL.\n" + - "\n" + - "Options:\n" + - "- `DOCKER` - Tolgee tries to run Postgres Docker container in your machine. " + - "This is default option when running Tolgee using Java. " + - "See [Running with Java](/self_hosting/running_with_java.mdx).\n" + - "- `EMBEDDED` - Tolgee tries to run it's embedded PostgreSQL " + - "which is bundled in the `tolgee/tolgee` Docker image." + description = + "How is Tolgee running PostgreSQL.\n" + + "\n" + + "Options:\n" + + "- `DOCKER` - Tolgee tries to run Postgres Docker container in your machine. " + + "This is default option when running Tolgee using Java. " + + "See [Running with Java](/self_hosting/running_with_java.mdx).\n" + + "- `EMBEDDED` - Tolgee tries to run it's embedded PostgreSQL " + + "which is bundled in the `tolgee/tolgee` Docker image.", ) var mode: PostgresAutostartMode = PostgresAutostartMode.DOCKER @@ -34,14 +35,16 @@ class PostgresAutostartProperties { var databaseName: String = "postgres" @DocProperty( - description = "The port of Postgres to listen on host machine.\n" + - "This setting is applicable only for `DOCKER` mode." + description = + "The port of Postgres to listen on host machine.\n" + + "This setting is applicable only for `DOCKER` mode.", ) var port: String = "25432" @DocProperty( - description = "The container name of the Postgres container.\n" + - "This setting is applicable only for `DOCKER` mode." + description = + "The container name of the Postgres container.\n" + + "This setting is applicable only for `DOCKER` mode.", ) var containerName: String = "tolgee_postgres" @@ -55,12 +58,13 @@ class PostgresAutostartProperties { * Expects that postgres is installed in the same container. * So the Postgres is started with Tolgee. */ - EMBEDDED + EMBEDDED, } @DocProperty( - description = "When true, Tolgee will stop the Postgres container on Tolgee shutdown." + - "This setting is applicable only for `DOCKER` mode." + description = + "When true, Tolgee will stop the Postgres container on Tolgee shutdown." + + "This setting is applicable only for `DOCKER` mode.", ) var stop: Boolean = true } diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/RabbitmqAutostartProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/RabbitmqAutostartProperties.kt index 6c296559f4..3d8a410faa 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/RabbitmqAutostartProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/RabbitmqAutostartProperties.kt @@ -22,6 +22,6 @@ class RabbitmqAutostartProperties { * Expects that postgres is installed in the same container. * So the Postgres is started with Tolgee. */ - EMBEDDED + EMBEDDED, } } diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/RateLimitProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/RateLimitProperties.kt index 8dadab541a..2ee2ded573 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/RateLimitProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/RateLimitProperties.kt @@ -6,57 +6,54 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.rate-limits") @DocProperty( displayName = "Rate limits", - description = "Configuration of the rate limit behavior of the server.\n" + - "Rate limits are used to protect against server overload and/or abuse, and are enabled by default.\n\n" + - // TODO: dedicated documentation section somewhere about rate limits & link it here - "You can disable global, per-endpoint and auth-related rate limits, or configure global rate limits.\n" + - "Per-endpoint and auth-related rate limits are fixed and cannot be configured.\n\n" + description = + "Configuration of the rate limit behavior of the server.\n" + + "Rate limits are used to protect against server overload and/or abuse, and are enabled by default.\n\n" + + // TODO: dedicated documentation section somewhere about rate limits & link it here + "You can disable global, per-endpoint and auth-related rate limits, or configure global rate limits.\n" + + "Per-endpoint and auth-related rate limits are fixed and cannot be configured.\n\n", ) class RateLimitProperties( @DocProperty( - description = "To turn all rate limits off, set this value to `false`.\n\n" + - ":::danger\n" + - "This field is **deprecated** and will be removed with Tolgee 4. If set to `false`, it will take priority\n" + - "over the more granular `global-limits`, `endpoint-limits` and `authentication-limits` and all limits\n" + - "will be disabled.\n" + - ":::\n\n", + description = + "To turn all rate limits off, set this value to `false`.\n\n" + + ":::danger\n" + + "This field is **deprecated** and will be removed with Tolgee 4. If set to `false`, it will take priority\n" + + "over the more granular `global-limits`, `endpoint-limits` and `authentication-limits` and all limits\n" + + "will be disabled.\n" + + ":::\n\n", ) @Deprecated(message = "Use `global-limits`, `endpoint-limits` and `authentication-limits` individually instead.") var enabled: Boolean = true, - @DocProperty(description = "Control whether global limits on the API are enabled or not.") var globalLimits: Boolean = true, - @DocProperty( - description = "Control whether per-endpoint limits on the API are enabled or not.\n" + - "Does not affect authentication-related endpoints, these are controlled by `authentication-limits`." + description = + "Control whether per-endpoint limits on the API are enabled or not.\n" + + "Does not affect authentication-related endpoints, these are controlled by `authentication-limits`.", ) var endpointLimits: Boolean = true, - @DocProperty( - description = "Control whether per-endpoint limits on authentication-related endpoints are enabled or not.\n" + - ":::warning\n" + - "It is **strongly** recommended to keep these limits enabled. They act as a protection layer against\n" + - "brute-force attacks on the login (and register) prompt.\n" + - ":::\n\n" + description = + "Control whether per-endpoint limits on authentication-related endpoints are enabled or not.\n" + + ":::warning\n" + + "It is **strongly** recommended to keep these limits enabled. They act as a protection layer against\n" + + "brute-force attacks on the login (and register) prompt.\n" + + ":::\n\n", ) var authenticationLimits: Boolean = true, - @DocProperty(description = "Amount of requests an IP address can do in a single time window.") var ipRequestLimit: Int = 20_000, - @DocProperty( description = "Size, in milliseconds, of the time window for IP-based limiting.", - defaultExplanation = "= 5 minutes" + defaultExplanation = "= 5 minutes", ) var ipRequestWindow: Long = 5 * 60 * 1000, - @DocProperty(description = "Amount of requests a user can do in a single time window.") var userRequestLimit: Int = 400, - @DocProperty( description = "Size, in milliseconds, of the time window for user-based limiting.", - defaultExplanation = "= 1 minute" + defaultExplanation = "= 1 minute", ) var userRequestWindow: Long = 1 * 60 * 1000, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/ReCaptchaProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/ReCaptchaProperties.kt index b4857c2b3e..dbb90370e7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/ReCaptchaProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/ReCaptchaProperties.kt @@ -5,12 +5,13 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.recaptcha") @DocProperty( - description = "When configured, reCAPTCHA v3 is used to protect the sign up page against bots. " + - "By default, reCAPTCHA is disabled.\n" + - "\n" + - "To enable it, you first need to [register a new site on reCAPTCHA](https://www.google.com/recaptcha/admin). " + - "Make sure to select reCAPTCHA v3 when registering your site.", - displayName = "reCAPTCHA" + description = + "When configured, reCAPTCHA v3 is used to protect the sign up page against bots. " + + "By default, reCAPTCHA is disabled.\n" + + "\n" + + "To enable it, you first need to [register a new site on reCAPTCHA](https://www.google.com/recaptcha/admin). " + + "Make sure to select reCAPTCHA v3 when registering your site.", + displayName = "reCAPTCHA", ) class ReCaptchaProperties { @E2eRuntimeMutable diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/S3Settings.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/S3Settings.kt index cd38455bed..d64a3c5c4e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/S3Settings.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/S3Settings.kt @@ -10,35 +10,34 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.file-storage.s3") @DocProperty( - description = "Tolgee supports storing its files on an S3-compatible storage server. " + - "When enabled, Tolgee will store all its files on the S3 server rather than in filesystem.", - displayName = "S3" + description = + "Tolgee supports storing its files on an S3-compatible storage server. " + + "When enabled, Tolgee will store all its files on the S3 server rather than in filesystem.", + displayName = "S3", ) class S3Settings( @DocProperty(description = "Whether S3 is enabled. If enabled, you need to set all remaining properties below.") override var enabled: Boolean = false, - @DocProperty( - description = "Access key for the S3 server. (optional if you are authenticating " + - "with a different method, like STS Web Identity)" + description = + "Access key for the S3 server. (optional if you are authenticating " + + "with a different method, like STS Web Identity)", ) override var accessKey: String? = null, - @DocProperty( - description = "Secret key for the access key. (optional if you are authenticating " + - "with a different method, like STS Web Identity)" + description = + "Secret key for the access key. (optional if you are authenticating " + + "with a different method, like STS Web Identity)", ) override var secretKey: String? = null, - @DocProperty( - description = "Has to be set to a service endpoint: " + - "https://docs.aws.amazon.com/general/latest/gr/s3.html" + description = + "Has to be set to a service endpoint: " + + "https://docs.aws.amazon.com/general/latest/gr/s3.html", ) override var endpoint: String? = null, - @DocProperty(description = "Has to be set to a signing region: https://docs.aws.amazon.com/general/latest/gr/s3.html") override var signingRegion: String? = null, - @DocProperty(description = "Name of the bucket where Tolgee will store its files.") override var bucketName: String? = null, ) : S3Config diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/SentryProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/SentryProperties.kt index 76bbb243d8..d857f50e52 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/SentryProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/SentryProperties.kt @@ -6,7 +6,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.sentry") @DocProperty( description = "Tolgee uses [Sentry](https://sentry.io/) for error reporting.", - displayName = "Sentry" + displayName = "Sentry", ) class SentryProperties { @DocProperty(description = "Server DSN. If unset, error reporting is disabled on the server.") diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/SmtpProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/SmtpProperties.kt index be6a8c3522..940a9dc250 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/SmtpProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/SmtpProperties.kt @@ -5,20 +5,21 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.smtp") @DocProperty( - description = "Configuration of SMTP server used to send emails to your users " + - "like password reset links or notifications.\n" + - "\n" + - "For AWS SES it would look like this:\n" + - "```\n" + - "tolgee.smtp.host=email-smtp.eu-central-1.amazonaws.com\n" + - "tolgee.smtp.username=*****************\n" + - "tolgee.smtp.password=*****************\n" + - "tolgee.smtp.port=465\n" + - "tolgee.smtp.auth=true\n" + - "tolgee.smtp.ssl-enabled=true\n" + - "tolgee.smtp.from=Tolgee \n" + - "```", - displayName = "SMTP" + description = + "Configuration of SMTP server used to send emails to your users " + + "like password reset links or notifications.\n" + + "\n" + + "For AWS SES it would look like this:\n" + + "```\n" + + "tolgee.smtp.host=email-smtp.eu-central-1.amazonaws.com\n" + + "tolgee.smtp.username=*****************\n" + + "tolgee.smtp.password=*****************\n" + + "tolgee.smtp.port=465\n" + + "tolgee.smtp.auth=true\n" + + "tolgee.smtp.ssl-enabled=true\n" + + "tolgee.smtp.from=Tolgee \n" + + "```", + displayName = "SMTP", ) class SmtpProperties { @DocProperty(description = "SMTP server host") diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/TelemetryProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/TelemetryProperties.kt index b73de35119..14f6a201a9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/TelemetryProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/TelemetryProperties.kt @@ -18,7 +18,7 @@ Once a day we collect following data - number of users We don't collect any other data. Please leave telemetry enabled to help us improve Tolgee.""", - displayName = "Telemetry" + displayName = "Telemetry", ) class TelemetryProperties { @DocProperty(description = "Whether telemetry is enabled") diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/TolgeeProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/TolgeeProperties.kt index 44911475f0..ed4f2bbdbc 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/TolgeeProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/TolgeeProperties.kt @@ -20,9 +20,9 @@ import org.springframework.boot.context.properties.ConfigurationProperties DocProperty( name = "port", description = "Port on which Tolgee exposes itself.", - defaultValue = "8080" - ) - ] + defaultValue = "8080", + ), + ], ), DocProperty( name = "spring", @@ -34,32 +34,34 @@ import org.springframework.boot.context.properties.ConfigurationProperties name = "datasource", prefix = "spring.datasource", displayName = "Data source settings", - description = "Since Tolgee is built on Spring framework, you have to edit following configuration props\n" + - "to configure its database connection. These properties can be omitted when using\n" + - "[Postgres autostart](#postgres-autostart), which is enabled by default.", + description = + "Since Tolgee is built on Spring framework, you have to edit following configuration props\n" + + "to configure its database connection. These properties can be omitted when using\n" + + "[Postgres autostart](#postgres-autostart), which is enabled by default.", children = [ DocProperty( name = "url", - description = "The url of the datasource in format `jdbc:postgresql://:/`. " + - "e.g. `jdbc:postgresql://db:5432/postgres`", - defaultValue = "" + description = + "The url of the datasource in format `jdbc:postgresql://:/`. " + + "e.g. `jdbc:postgresql://db:5432/postgres`", + defaultValue = "", ), DocProperty( name = "username", description = "Database username. e.g. `postgres`", - defaultValue = "" + defaultValue = "", ), DocProperty( name = "password", description = "Database password. e.g. `postgres`", - defaultValue = "" + defaultValue = "", ), - ] - ) - ] - ) + ], + ), + ], + ), ], - global = true + global = true, ) @ConfigurationProperties(prefix = "tolgee") @DocProperty(description = "Configuration specific to Tolgee.", displayName = "Tolgee") @@ -67,67 +69,50 @@ open class TolgeeProperties( var authentication: AuthenticationProperties = AuthenticationProperties(), var smtp: SmtpProperties = SmtpProperties(), var sentry: SentryProperties = SentryProperties(), - @DocProperty(hidden = true) var chatwootToken: String? = null, - @DocProperty(hidden = true) var capterraTracker: String? = null, - @DocProperty(hidden = true) var ga4Tag: String? = null, - @DocProperty(hidden = true) var internal: InternalProperties = InternalProperties(), - @DocProperty( description = "Public base path where files are accessible. Used by the user interface.", - defaultExplanation = "The root of the same origin." + defaultExplanation = "The root of the same origin.", ) var fileStorageUrl: String = "", - @DocProperty(description = "Maximum size of uploaded files (in kilobytes).", defaultExplanation = "≈ 50MB") var maxUploadFileSize: Int = 51200, - @DocProperty(description = "Maximum amount of screenshots which can be uploaded per API key.") val maxScreenshotsPerKey: Int = 20, - var fileStorage: FileStorageProperties = FileStorageProperties(), - @DocProperty( - description = "Public URL where Tolgee is accessible. " + - "Used to generate links to Tolgee (e.g. email confirmation link)." + description = + "Public URL where Tolgee is accessible. " + + "Used to generate links to Tolgee (e.g. email confirmation link).", ) var frontEndUrl: String? = null, - var websocket: WebsocketProperties = WebsocketProperties(), - @DocProperty(description = "Name of the application.", hidden = true) var appName: String = "Tolgee", - @DocProperty(description = "Maximum length of translations.") open var maxTranslationTextLength: Long = 10000, - @DocProperty( description = "Properties related to batch jobs", - displayName = "Batch jobs" + displayName = "Batch jobs", ) open var batch: BatchProperties = BatchProperties(), - var cache: CacheProperties = CacheProperties(), var recaptcha: ReCaptchaProperties = ReCaptchaProperties(), var machineTranslation: MachineTranslationProperties = MachineTranslationProperties(), var postgresAutostart: PostgresAutostartProperties = PostgresAutostartProperties(), - @DocProperty(hidden = true) var sendInBlue: SendInBlueProperties = SendInBlueProperties(), - open var import: ImportProperties = ImportProperties(), var rateLimit: RateLimitProperties = RateLimitProperties(), @DocProperty(hidden = true) var postHog: PostHogProperties = PostHogProperties(), - var telemetry: TelemetryProperties = TelemetryProperties(), - var contentDelivery: ContentDeliveryProperties = ContentDeliveryProperties(), ) diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/AwsMachineTranslationProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/AwsMachineTranslationProperties.kt index 79c775556a..f94a4b0cfb 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/AwsMachineTranslationProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/AwsMachineTranslationProperties.kt @@ -5,36 +5,35 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.machine-translation.aws") @DocProperty( - description = "See [AWS's Amazon Translate](https://aws.amazon.com/translate) page " + - "for more information and applicable pricing.", - displayName = "AWS Amazon Translate" + description = + "See [AWS's Amazon Translate](https://aws.amazon.com/translate) page " + + "for more information and applicable pricing.", + displayName = "AWS Amazon Translate", ) open class AwsMachineTranslationProperties( @DocProperty(description = "Whether AWS-powered machine translation is enabled.") override var defaultEnabled: Boolean = true, - @DocProperty(description = "Whether to use AWS Amazon Translate as a primary translation engine.") override var defaultPrimary: Boolean = false, - @DocProperty( - description = "If you are authenticating using a different method than " + - "explicit access key and secret key, which implicitly enable AWS Translate, " + - "you should enable AWS Translate using this option." + description = + "If you are authenticating using a different method than " + + "explicit access key and secret key, which implicitly enable AWS Translate, " + + "you should enable AWS Translate using this option.", ) var enabled: Boolean? = null, - @DocProperty( - description = "AWS access key. (optional if you are authenticating " + - "with a different method, like STS Web Identity)" + description = + "AWS access key. (optional if you are authenticating " + + "with a different method, like STS Web Identity)", ) var accessKey: String? = null, - @DocProperty( - description = "AWS secret key. (optional if you are authenticating " + - "with a different method, like STS Web Identity)" + description = + "AWS secret key. (optional if you are authenticating " + + "with a different method, like STS Web Identity)", ) var secretKey: String? = null, - @DocProperty(description = "AWS region.") - var region: String? = "eu-central-1" + var region: String? = "eu-central-1", ) : MachineTranslationServiceProperties diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/AzureCognitiveTranslationProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/AzureCognitiveTranslationProperties.kt index 07087ffd02..06bc39816c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/AzureCognitiveTranslationProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/AzureCognitiveTranslationProperties.kt @@ -5,22 +5,20 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.machine-translation.azurecognitive") @DocProperty( - description = "See " + - "[Azure Cognitive Translation]" + - "(https://azure.microsoft.com/en-us/services/cognitive-services/translator-text-api/)" + - " page for more information and applicable pricing.", - displayName = "Azure Cognitive Translation" + description = + "See " + + "[Azure Cognitive Translation]" + + "(https://azure.microsoft.com/en-us/services/cognitive-services/translator-text-api/)" + + " page for more information and applicable pricing.", + displayName = "Azure Cognitive Translation", ) open class AzureCognitiveTranslationProperties( @DocProperty(description = "Whether Azure Cognitive Translation is enabled.") override var defaultEnabled: Boolean = true, - @DocProperty(description = "Whether to use Azure Cognitive Translation as a primary translation engine.") override var defaultPrimary: Boolean = false, - @DocProperty(description = "Azure Cognitive Translation auth key.") var authKey: String? = null, - @DocProperty(description = "Azure Cognitive Translation region.") - var region: String? = null + var region: String? = null, ) : MachineTranslationServiceProperties diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/BaiduMachineTranslationProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/BaiduMachineTranslationProperties.kt index c4d8ad6bd5..40a17d575d 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/BaiduMachineTranslationProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/BaiduMachineTranslationProperties.kt @@ -5,26 +5,25 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.machine-translation.baidu") @DocProperty( - description = "See [Baidu's](https://fanyi-api.baidu.com/product/11) page (in Chinese) " + - "for more information and applicable pricing.", - displayName = "Baidu Translate" + description = + "See [Baidu's](https://fanyi-api.baidu.com/product/11) page (in Chinese) " + + "for more information and applicable pricing.", + displayName = "Baidu Translate", ) open class BaiduMachineTranslationProperties( @DocProperty(description = "Whether Baidu-powered machine translation is enabled.") override var defaultEnabled: Boolean = true, - @DocProperty(description = "Whether to use Baidu Translate as a primary translation engine.") override var defaultPrimary: Boolean = false, - @DocProperty(description = "Baidu Translate App ID.") var appId: String? = null, - @DocProperty(description = "Baidu Translate Secret key.") var appSecret: String? = null, - @DocProperty( - description = "Whether the resulting translation should be changed according to the user-defined dictionary.\n" + - "The dictionary used can be modified at [Manage Terms](https://fanyi-api.baidu.com/manage/term) (login required)." + description = + "Whether the resulting translation should be changed according to the user-defined dictionary.\n" + + "The dictionary used can be modified at " + + "[Manage Terms](https://fanyi-api.baidu.com/manage/term) (login required).", ) var action: Boolean = false, ) : MachineTranslationServiceProperties diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/DeeplMachineTranslationProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/DeeplMachineTranslationProperties.kt index 072f984d95..1ba611ae6e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/DeeplMachineTranslationProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/DeeplMachineTranslationProperties.kt @@ -6,15 +6,13 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.machine-translation.deepl") @DocProperty( description = "See [DeepL's](https://www.deepl.com/) page for more information and applicable pricing.", - displayName = "DeepL" + displayName = "DeepL", ) open class DeeplMachineTranslationProperties( @DocProperty(description = "Whether DeepL-powered machine translation is enabled.") override var defaultEnabled: Boolean = true, - @DocProperty(description = "Whether to use DeepL as a primary translation engine.") override var defaultPrimary: Boolean = false, - @DocProperty(description = "DeepL auth key. Both key types (commercial and free) are supported.") var authKey: String? = null, ) : MachineTranslationServiceProperties diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/GoogleMachineTranslationProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/GoogleMachineTranslationProperties.kt index 80e1128fa7..22cc3a793b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/GoogleMachineTranslationProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/GoogleMachineTranslationProperties.kt @@ -5,17 +5,16 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.machine-translation.google") @DocProperty( - description = "See [Google Cloud Translation](https://cloud.google.com/translate) page " + - "for more information and applicable pricing.", - displayName = "Google Cloud Translation" + description = + "See [Google Cloud Translation](https://cloud.google.com/translate) page " + + "for more information and applicable pricing.", + displayName = "Google Cloud Translation", ) open class GoogleMachineTranslationProperties( @DocProperty(description = "Whether Google-powered machine translation is enabled.") override var defaultEnabled: Boolean = true, - @DocProperty(description = "Whether to use Google Cloud Translation as a primary translation engine.") override var defaultPrimary: Boolean = true, - @DocProperty(description = "Google Cloud Translation API key.") - var apiKey: String? = null + var apiKey: String? = null, ) : MachineTranslationServiceProperties diff --git a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/MachineTranslationProperties.kt b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/MachineTranslationProperties.kt index 788e4d8908..e54a256437 100644 --- a/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/MachineTranslationProperties.kt +++ b/backend/data/src/main/kotlin/io/tolgee/configuration/tolgee/machineTranslation/MachineTranslationProperties.kt @@ -6,7 +6,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties(prefix = "tolgee.machine-translation") @DocProperty( description = "Configuration of Machine Translation services.", - displayName = "Machine Translation" + displayName = "Machine Translation", ) open class MachineTranslationProperties( var google: GoogleMachineTranslationProperties = GoogleMachineTranslationProperties(), @@ -14,10 +14,10 @@ open class MachineTranslationProperties( var deepl: DeeplMachineTranslationProperties = DeeplMachineTranslationProperties(), var azure: AzureCognitiveTranslationProperties = AzureCognitiveTranslationProperties(), var baidu: BaiduMachineTranslationProperties = BaiduMachineTranslationProperties(), - @DocProperty( - description = "Amount of machine translations users of the Free tier can request per month. " + - "Used by Tolgee Cloud, see [pricing](/pricing). Set to `-1` to disable credit-based limitation." + description = + "Amount of machine translations users of the Free tier can request per month. " + + "Used by Tolgee Cloud, see [pricing](/pricing). Set to `-1` to disable credit-based limitation.", ) var freeCreditsAmount: Long = -1, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/constants/BillingPeriod.kt b/backend/data/src/main/kotlin/io/tolgee/constants/BillingPeriod.kt index cd0e3bf4f7..e11a448df0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/constants/BillingPeriod.kt +++ b/backend/data/src/main/kotlin/io/tolgee/constants/BillingPeriod.kt @@ -1,5 +1,6 @@ package io.tolgee.constants enum class BillingPeriod { - MONTHLY, YEARLY + MONTHLY, + YEARLY, } diff --git a/backend/data/src/main/kotlin/io/tolgee/constants/Caches.kt b/backend/data/src/main/kotlin/io/tolgee/constants/Caches.kt index 82ffe193af..d051824fc6 100644 --- a/backend/data/src/main/kotlin/io/tolgee/constants/Caches.kt +++ b/backend/data/src/main/kotlin/io/tolgee/constants/Caches.kt @@ -17,19 +17,20 @@ interface Caches { const val DISMISSED_ANNOUNCEMENT = "dismissedAnnouncement" const val AUTOMATIONS = "automations" - val caches = listOf( - USER_ACCOUNTS, - PROJECT_API_KEYS, - PERSONAL_ACCESS_TOKENS, - ORGANIZATIONS, - PROJECTS, - PERMISSIONS, - MACHINE_TRANSLATIONS, - PROJECT_TRANSLATIONS_MODIFIED, - BUSINESS_EVENT_THROTTLING, - USAGE, - DISMISSED_ANNOUNCEMENT, - AUTOMATIONS - ) + val caches = + listOf( + USER_ACCOUNTS, + PROJECT_API_KEYS, + PERSONAL_ACCESS_TOKENS, + ORGANIZATIONS, + PROJECTS, + PERMISSIONS, + MACHINE_TRANSLATIONS, + PROJECT_TRANSLATIONS_MODIFIED, + BUSINESS_EVENT_THROTTLING, + USAGE, + DISMISSED_ANNOUNCEMENT, + AUTOMATIONS, + ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/constants/ComputedPermissionOrigin.kt b/backend/data/src/main/kotlin/io/tolgee/constants/ComputedPermissionOrigin.kt index b57d74244f..2ba4ef86ee 100644 --- a/backend/data/src/main/kotlin/io/tolgee/constants/ComputedPermissionOrigin.kt +++ b/backend/data/src/main/kotlin/io/tolgee/constants/ComputedPermissionOrigin.kt @@ -1,5 +1,9 @@ package io.tolgee.constants enum class ComputedPermissionOrigin { - ORGANIZATION_BASE, DIRECT, ORGANIZATION_OWNER, NONE, SERVER_ADMIN + ORGANIZATION_BASE, + DIRECT, + ORGANIZATION_OWNER, + NONE, + SERVER_ADMIN, } diff --git a/backend/data/src/main/kotlin/io/tolgee/constants/Message.kt b/backend/data/src/main/kotlin/io/tolgee/constants/Message.kt index 1c2bc302d4..de182ff0d7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/constants/Message.kt +++ b/backend/data/src/main/kotlin/io/tolgee/constants/Message.kt @@ -186,7 +186,7 @@ enum class Message { UNEXPECTED_ERROR_WHILE_EXECUTING_WEBHOOK, CONTENT_STORAGE_IS_IN_USE, CANNOT_SET_STATE_FOR_MISSING_TRANSLATION, - NO_PROJECT_ID_PROVIDED + NO_PROJECT_ID_PROVIDED, ; val code: String diff --git a/backend/data/src/main/kotlin/io/tolgee/constants/MtServiceType.kt b/backend/data/src/main/kotlin/io/tolgee/constants/MtServiceType.kt index 061b334af7..7038fa6a99 100644 --- a/backend/data/src/main/kotlin/io/tolgee/constants/MtServiceType.kt +++ b/backend/data/src/main/kotlin/io/tolgee/constants/MtServiceType.kt @@ -19,12 +19,12 @@ enum class MtServiceType( val propertyClass: Class, val providerClass: Class, val usesMetadata: Boolean = false, - val order: Int = 0 + val order: Int = 0, ) { GOOGLE(GoogleMachineTranslationProperties::class.java, GoogleTranslationProvider::class.java), AWS(AwsMachineTranslationProperties::class.java, AwsMtValueProvider::class.java), DEEPL(DeeplMachineTranslationProperties::class.java, DeeplTranslationProvider::class.java), AZURE(AzureCognitiveTranslationProperties::class.java, AzureCognitiveTranslationProvider::class.java), BAIDU(BaiduMachineTranslationProperties::class.java, BaiduTranslationProvider::class.java), - TOLGEE(TolgeeMachineTranslationProperties::class.java, TolgeeTranslationProvider::class.java, true, order = -1); + TOLGEE(TolgeeMachineTranslationProperties::class.java, TolgeeTranslationProvider::class.java, true, order = -1), } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/Base.kt b/backend/data/src/main/kotlin/io/tolgee/development/Base.kt index eecde684bb..d43b7da929 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/Base.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/Base.kt @@ -7,5 +7,5 @@ import io.tolgee.model.UserAccount data class Base( val project: Project, var organization: Organization, - val userAccount: UserAccount + val userAccount: UserAccount, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/development/DbPopulatorReal.kt b/backend/data/src/main/kotlin/io/tolgee/development/DbPopulatorReal.kt index 63898666c8..fe7b78a7f9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/DbPopulatorReal.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/DbPopulatorReal.kt @@ -45,7 +45,7 @@ class DbPopulatorReal( private val apiKeyService: ApiKeyService, private val languageStatsService: LanguageStatsService, private val platformTransactionManager: PlatformTransactionManager, - private val passwordEncoder: PasswordEncoder + private val passwordEncoder: PasswordEncoder, ) { private lateinit var de: Language private lateinit var en: Language @@ -58,33 +58,44 @@ class DbPopulatorReal( } } - fun createUserIfNotExists(username: String, password: String? = null, name: String? = null): UserAccount { + fun createUserIfNotExists( + username: String, + password: String? = null, + name: String? = null, + ): UserAccount { return userAccountService.findActive(username) ?: let { - - val rawPassword = password - ?: initialPasswordManager.initialPassword + val rawPassword = + password + ?: initialPasswordManager.initialPassword userAccountService.createUser( UserAccount( name = name ?: username, username = username, - password = passwordEncoder.encode(rawPassword) - ) + password = passwordEncoder.encode(rawPassword), + ), ) } } - fun createOrganization(name: String, userAccount: UserAccount): Organization { + fun createOrganization( + name: String, + userAccount: UserAccount, + ): Organization { val slug = slugGenerator.generate(name, 3, 100) { true } return organizationService.create(OrganizationDto(name, slug), userAccount) } @Transactional @Deprecated("Use create PermissionTestData or other permission classes") - fun createUsersAndOrganizations(username: String = "user", userCount: Int = 4): List { - val users = (1..userCount).map { - createUserIfNotExists("$username-$it") - } + fun createUsersAndOrganizations( + username: String = "user", + userCount: Int = 4, + ): List { + val users = + (1..userCount).map { + createUserIfNotExists("$username-$it") + } users.mapIndexed { listUserIdx, user -> (1..listUserIdx).forEach { organizationNum -> @@ -103,7 +114,10 @@ class DbPopulatorReal( } @Transactional - fun createProjectWithOrganization(projectName: String, organization: Organization): Project { + fun createProjectWithOrganization( + projectName: String, + organization: Organization, + ): Project { val project = Project() project.name = projectName project.organizationOwner = organization @@ -117,7 +131,11 @@ class DbPopulatorReal( } @Transactional - fun createBase(projectName: String, username: String, password: String? = null): Base { + fun createBase( + projectName: String, + username: String, + password: String? = null, + ): Base { val userAccount = createUserIfNotExists(username, password) val organization = createOrganizationIfNotExist(username, username, userAccount) val project = createProject(projectName, organization) @@ -141,14 +159,21 @@ class DbPopulatorReal( return project } - fun createOrganizationIfNotExist(name: String, slug: String = name, userAccount: UserAccount): Organization { + fun createOrganizationIfNotExist( + name: String, + slug: String = name, + userAccount: UserAccount, + ): Organization { return organizationService.find(name) ?: let { organizationService.create(OrganizationDto(name, slug = slug), userAccount) } } @Transactional - fun createBase(projectName: String, username: String): Base { + fun createBase( + projectName: String, + username: String, + ): Base { return createBase(projectName, username, null) } @@ -166,51 +191,84 @@ class DbPopulatorReal( } @Transactional - fun populate(projectName: String, userName: String): Base { + fun populate( + projectName: String, + userName: String, + ): Base { val base = createBase(projectName, userName) val project = projectService.get(base.project.id) createApiKey(project) createTranslation(project, "Hello world!", "Hallo Welt!", en, de) createTranslation(project, "English text one.", "Deutsch text einz.", en, de) createTranslation( - project, "This is translation in home folder", - "Das ist die Übersetzung im Home-Ordner", en, de + project, + "This is translation in home folder", + "Das ist die Übersetzung im Home-Ordner", + en, + de, ) createTranslation( - project, "This is translation in news folder", - "Das ist die Übersetzung im News-Ordner", en, de + project, + "This is translation in news folder", + "Das ist die Übersetzung im News-Ordner", + en, + de, ) createTranslation( - project, "This is another translation in news folder", - "Das ist eine weitere Übersetzung im Nachrichtenordner", en, de + project, + "This is another translation in news folder", + "Das ist eine weitere Übersetzung im Nachrichtenordner", + en, + de, ) createTranslation( - project, "This is standard text somewhere in DOM.", - "Das ist Standardtext irgendwo im DOM.", en, de + project, + "This is standard text somewhere in DOM.", + "Das ist Standardtext irgendwo im DOM.", + en, + de, ) createTranslation( - project, "This is another standard text somewhere in DOM.", - "Das ist ein weiterer Standardtext irgendwo in DOM.", en, de + project, + "This is another standard text somewhere in DOM.", + "Das ist ein weiterer Standardtext irgendwo in DOM.", + en, + de, ) createTranslation( - project, "This is translation retrieved by service.", - "Dase Übersetzung wird vom Service abgerufen.", en, de + project, + "This is translation retrieved by service.", + "Dase Übersetzung wird vom Service abgerufen.", + en, + de, ) createTranslation( - project, "This is textarea with placeholder and value.", - "Das ist ein Textarea mit Placeholder und Value.", en, de + project, + "This is textarea with placeholder and value.", + "Das ist ein Textarea mit Placeholder und Value.", + en, + de, ) createTranslation( - project, "This is textarea with placeholder.", - "Das ist ein Textarea mit Placeholder.", en, de + project, + "This is textarea with placeholder.", + "Das ist ein Textarea mit Placeholder.", + en, + de, ) createTranslation( - project, "This is input with value.", - "Das ist ein Input mit value.", en, de + project, + "This is input with value.", + "Das ist ein Input mit value.", + en, + de, ) createTranslation( - project, "This is input with placeholder.", - "Das ist ein Input mit Placeholder.", en, de + project, + "This is input with placeholder.", + "Das ist ein Input mit Placeholder.", + en, + de, ) return base } @@ -218,18 +276,22 @@ class DbPopulatorReal( private fun createApiKey(project: Project) { val user = project.organizationOwner.memberRoles[0].user if (apiKeyService.findOptional(apiKeyService.hashKey(API_KEY)).isEmpty) { - val apiKey = ApiKey( - project = project, - key = API_KEY, - userAccount = user!!, - scopesEnum = Scope.values().toSet() - ) + val apiKey = + ApiKey( + project = project, + key = API_KEY, + userAccount = user!!, + scopesEnum = Scope.values().toSet(), + ) project.apiKeys.add(apiKey) apiKeyService.save(apiKey) } } - private fun createLanguage(name: String, project: Project): Language { + private fun createLanguage( + name: String, + project: Project, + ): Language { return languageService.createLanguage(LanguageDto(name, name, name), project) } @@ -238,11 +300,12 @@ class DbPopulatorReal( english: String, deutsch: String, en: Language, - de: Language + de: Language, ) { val key = Key() - key.name = "sampleApp." + english.replace(" ", "_") - .lowercase(Locale.getDefault()).replace("\\.+$".toRegex(), "") + key.name = "sampleApp." + + english.replace(" ", "_") + .lowercase(Locale.getDefault()).replace("\\.+$".toRegex(), "") key.project = project val translation = Translation() translation.language = en diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/AdditionalTestDataSaver.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/AdditionalTestDataSaver.kt index 3e8d2126c5..671e9269fd 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/AdditionalTestDataSaver.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/AdditionalTestDataSaver.kt @@ -4,5 +4,6 @@ import io.tolgee.development.testDataBuilder.builders.TestDataBuilder interface AdditionalTestDataSaver { fun save(builder: TestDataBuilder) + fun clean(builder: TestDataBuilder) } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/TestDataService.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/TestDataService.kt index a8bb59f0f1..6d92330fb4 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/TestDataService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/TestDataService.kt @@ -76,9 +76,8 @@ class TestDataService( private val activityHolder: ActivityHolder, private val automationService: AutomationService, private val contentDeliveryConfigService: ContentDeliveryConfigService, - private val languageStatsListener: LanguageStatsListener + private val languageStatsListener: LanguageStatsListener, ) : Logging { - @Transactional fun saveTestData(ft: TestDataBuilder.() -> Unit): TestDataBuilder { val builder = TestDataBuilder() @@ -322,15 +321,16 @@ class TestDataService( private fun saveMtServiceConfigs(builder: ProjectBuilder) { mtServiceConfigService.saveAll( - builder.data.translationServiceConfigs.map { it.self } + builder.data.translationServiceConfigs.map { it.self }, ) } private fun saveLanguages(builder: ProjectBuilder) { - val languages = builder.data.languages.map { - // refresh entity if updating to get new stats - if (it.self.id != 0L) languageService.get(it.self.id) else it.self - } + val languages = + builder.data.languages.map { + // refresh entity if updating to get new stats + if (it.self.id != 0L) languageService.get(it.self.id) else it.self + } languageService.saveAll(languages) } @@ -380,14 +380,15 @@ class TestDataService( } private fun saveAllOrganizations(builder: TestDataBuilder) { - val organizationsToSave = builder.data.organizations.map { - it.self.apply { - val slug = this.slug - if (slug.isEmpty()) { - this.slug = organizationService.generateSlug(this.name) + val organizationsToSave = + builder.data.organizations.map { + it.self.apply { + val slug = this.slug + if (slug.isEmpty()) { + this.slug = organizationService.generateSlug(this.name) + } } } - } organizationsToSave.forEach { org -> permissionService.save(org.basePermission) @@ -401,7 +402,7 @@ class TestDataService( userAccountBuilders.map { it.self.password = passwordEncoder.encode(it.rawPassword) it.self - } + }, ) saveUserAvatars(userAccountBuilders) saveUserPreferences(userAccountBuilders.mapNotNull { it.data.userPreferences }) diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ApiKeyBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ApiKeyBuilder.kt index 4a770aaf83..a48faee2c8 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ApiKeyBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ApiKeyBuilder.kt @@ -4,14 +4,16 @@ import io.tolgee.development.testDataBuilder.EntityDataBuilder import io.tolgee.model.ApiKey class ApiKeyBuilder( - val projectBuilder: ProjectBuilder + val projectBuilder: ProjectBuilder, ) : EntityDataBuilder { - override var self: ApiKey = ApiKey( - "test_api_key", mutableSetOf() - ).apply { - project = projectBuilder.self - projectBuilder.onlyUser?.let { - this.userAccount = it + override var self: ApiKey = + ApiKey( + "test_api_key", + mutableSetOf(), + ).apply { + project = projectBuilder.self + projectBuilder.onlyUser?.let { + this.userAccount = it + } } - } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/AutoTranslationConfigBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/AutoTranslationConfigBuilder.kt index 94382b3070..2eddaf0741 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/AutoTranslationConfigBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/AutoTranslationConfigBuilder.kt @@ -3,7 +3,7 @@ package io.tolgee.development.testDataBuilder.builders import io.tolgee.model.AutoTranslationConfig class AutoTranslationConfigBuilder( - val projectBuilder: ProjectBuilder + val projectBuilder: ProjectBuilder, ) : BaseEntityDataBuilder() { override var self: AutoTranslationConfig = AutoTranslationConfig().apply { project = projectBuilder.self } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/AutomationBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/AutomationBuilder.kt index 34b16adff1..caff1d5583 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/AutomationBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/AutomationBuilder.kt @@ -6,6 +6,5 @@ import io.tolgee.model.automations.Automation class AutomationBuilder( val projectBuilder: ProjectBuilder, ) : EntityDataBuilder { - override var self = Automation(projectBuilder.self) } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/BaseEntityDataBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/BaseEntityDataBuilder.kt index 0c76db3f73..da5f34d304 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/BaseEntityDataBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/BaseEntityDataBuilder.kt @@ -7,7 +7,7 @@ abstract class BaseEntityDataBuilder : EntityDataBuilder> addOperation( collection: MutableCollection, instance: Builder, - ft: AddedEntity.() -> Unit + ft: AddedEntity.() -> Unit, ): Builder { ft(instance.self) collection.add(instance) @@ -16,7 +16,7 @@ abstract class BaseEntityDataBuilder : EntityDataBuilder> addOperation( collection: MutableCollection, - ft: AddedEntity.() -> Unit + ft: AddedEntity.() -> Unit, ): Builder { val instance = Builder::class.constructors.find { it.parameters[0].type == this::class.createType() }!!.call(this) addOperation(collection, instance, ft) diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportBuilder.kt index 66063babf4..a921a623d8 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportBuilder.kt @@ -13,11 +13,12 @@ class ImportBuilder( val data = DATA() - override var self: Import = Import(projectBuilder.self).apply { - projectBuilder.onlyUser?.let { - author = it + override var self: Import = + Import(projectBuilder.self).apply { + projectBuilder.onlyUser?.let { + author = it + } } - } fun addImportFile(ft: FT) = addOperation(data.importFiles, ft) } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportFileBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportFileBuilder.kt index 7690a76982..54fa07e8c9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportFileBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportFileBuilder.kt @@ -17,16 +17,18 @@ class ImportFileBuilder(importBuilder: ImportBuilder) : BaseEntityDataBuilder) = addOperation(data.importKeys, ft).also { - it.self { - this@ImportFileBuilder.self.keys.add(this) - this.file = this@ImportFileBuilder.self + fun addImportKey(ft: FT) = + addOperation(data.importKeys, ft).also { + it.self { + this@ImportFileBuilder.self.keys.add(this) + this.file = this@ImportFileBuilder.self + } } - } - fun addImportLanguage(ft: FT) = addOperation(data.importLanguages, ft).also { - it.self { this.file = this@ImportFileBuilder.self } - } + fun addImportLanguage(ft: FT) = + addOperation(data.importLanguages, ft).also { + it.self { this.file = this@ImportFileBuilder.self } + } fun addImportTranslation(ft: FT) = addOperation(data.importTranslations, ft) } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportKeyBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportKeyBuilder.kt index 5480c62ea0..ed52012da0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportKeyBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportKeyBuilder.kt @@ -6,9 +6,8 @@ import io.tolgee.model.dataImport.ImportKey import io.tolgee.model.key.KeyMeta class ImportKeyBuilder( - importFileBuilder: ImportFileBuilder + importFileBuilder: ImportFileBuilder, ) : EntityDataBuilder { - class DATA { var meta: KeyMetaBuilder? = null val screenshots = mutableListOf() @@ -19,8 +18,9 @@ class ImportKeyBuilder( override var self: ImportKey = ImportKey("testKey", importFileBuilder.self) fun addMeta(ft: FT) { - data.meta = KeyMetaBuilder(this).apply { - ft(this.self) - } + data.meta = + KeyMetaBuilder(this).apply { + ft(this.self) + } } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportLanguageBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportLanguageBuilder.kt index 04abed9540..5985a65976 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportLanguageBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportLanguageBuilder.kt @@ -4,7 +4,7 @@ import io.tolgee.development.testDataBuilder.EntityDataBuilder import io.tolgee.model.dataImport.ImportLanguage class ImportLanguageBuilder( - importFileBuilder: ImportFileBuilder + importFileBuilder: ImportFileBuilder, ) : EntityDataBuilder { override var self: ImportLanguage = ImportLanguage("en", importFileBuilder.self) } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportTranslationBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportTranslationBuilder.kt index c16197f476..74302b4db5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportTranslationBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ImportTranslationBuilder.kt @@ -4,7 +4,7 @@ import io.tolgee.development.testDataBuilder.EntityDataBuilder import io.tolgee.model.dataImport.ImportTranslation class ImportTranslationBuilder( - importFileBuilder: ImportFileBuilder + importFileBuilder: ImportFileBuilder, ) : EntityDataBuilder { override var self: ImportTranslation = ImportTranslation("test translation", importFileBuilder.data.importLanguages[0].self).apply { diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/KeyBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/KeyBuilder.kt index 768f998972..7d63eb7e63 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/KeyBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/KeyBuilder.kt @@ -11,23 +11,24 @@ import io.tolgee.util.ImageConverter import org.springframework.core.io.Resource class KeyBuilder( - val projectBuilder: ProjectBuilder + val projectBuilder: ProjectBuilder, ) : BaseEntityDataBuilder() { - class DATA { var meta: KeyMetaBuilder? = null } val data = DATA() - override var self: Key = Key().also { - it.project = projectBuilder.self - } + override var self: Key = + Key().also { + it.project = projectBuilder.self + } fun addTranslation(ft: FT): TranslationBuilder { - val builder = TranslationBuilder(projectBuilder).apply { - self.key = this@KeyBuilder.self - } + val builder = + TranslationBuilder(projectBuilder).apply { + self.key = this@KeyBuilder.self + } return addOperation(projectBuilder.data.translations, builder, ft) } @@ -41,39 +42,44 @@ class KeyBuilder( this.self.namespace = null return null } - val nsBuilder = projectBuilder.data.namespaces.singleOrNull { it.self.name === name } - ?: projectBuilder.addNamespace { this.name = name } + val nsBuilder = + projectBuilder.data.namespaces.singleOrNull { it.self.name === name } + ?: projectBuilder.addNamespace { this.name = name } this.self.namespace = nsBuilder.self return nsBuilder } fun addScreenshot( file: Resource? = null, - ft: Screenshot.(reference: KeyScreenshotReference) -> Unit + ft: Screenshot.(reference: KeyScreenshotReference) -> Unit, ): ScreenshotBuilder { - val converter = file?.let { ImageConverter(file.inputStream) } val image = converter?.getImage() val thumbnail = converter?.getThumbnail() - val screenshotBuilder = projectBuilder.addScreenshot { - width = converter?.targetDimension?.width ?: 0 - height = converter?.targetDimension?.height ?: 0 - } + val screenshotBuilder = + projectBuilder.addScreenshot { + width = converter?.targetDimension?.width ?: 0 + height = converter?.targetDimension?.height ?: 0 + } screenshotBuilder.image = image screenshotBuilder.thumbnail = thumbnail - val reference = projectBuilder.addScreenshotReference { - key = this@KeyBuilder.self - screenshot = screenshotBuilder.self - } + val reference = + projectBuilder.addScreenshotReference { + key = this@KeyBuilder.self + screenshot = screenshotBuilder.self + } ft(screenshotBuilder.self, reference.self) return screenshotBuilder } - fun addTranslation(languageTag: String, text: String?) { + fun addTranslation( + languageTag: String, + text: String?, + ) { addTranslation { this.language = projectBuilder.getLanguageByTag(languageTag)!!.self this.text = text @@ -83,17 +89,19 @@ class KeyBuilder( fun addTag(name: String): Tag { val meta = this.data.meta ?: addMeta { } - val tags = projectBuilder.data.keys - .mapNotNull { it.data.meta?.self?.tags }.flatten().filter { it.name == name }.distinct() + val tags = + projectBuilder.data.keys + .mapNotNull { it.data.meta?.self?.tags }.flatten().filter { it.name == name }.distinct() if (tags.size > 1) { throw IllegalStateException("More than one tag with name $name in the project") } - val tag = tags.firstOrNull() ?: Tag().apply { - this.name = name - this.project = projectBuilder.self - } + val tag = + tags.firstOrNull() ?: Tag().apply { + this.name = name + this.project = projectBuilder.self + } meta.self.tags.add(tag) return tag diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/KeyMetaBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/KeyMetaBuilder.kt index 536371da9b..f4fa3aaebb 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/KeyMetaBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/KeyMetaBuilder.kt @@ -5,17 +5,18 @@ import io.tolgee.model.key.KeyMeta class KeyMetaBuilder( importKeyBuilder: ImportKeyBuilder? = null, - keyBuilder: KeyBuilder? = null + keyBuilder: KeyBuilder? = null, ) : EntityDataBuilder { - override var self: KeyMeta = KeyMeta( - key = keyBuilder?.self, - importKey = importKeyBuilder?.self - ).also { - keyBuilder?.self { - keyMeta = it + override var self: KeyMeta = + KeyMeta( + key = keyBuilder?.self, + importKey = importKeyBuilder?.self, + ).also { + keyBuilder?.self { + keyMeta = it + } + importKeyBuilder?.self { + keyMeta = it + } } - importKeyBuilder?.self { - keyMeta = it - } - } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/KeysDistanceBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/KeysDistanceBuilder.kt index 83fab1212b..c686c7722e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/KeysDistanceBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/KeysDistanceBuilder.kt @@ -7,10 +7,11 @@ import io.tolgee.model.keyBigMeta.KeysDistance class KeysDistanceBuilder( val projectBuilder: ProjectBuilder, val key1: Key, - val key2: Key + val key2: Key, ) : EntityDataBuilder { - override var self: KeysDistance = KeysDistance().apply { - project = projectBuilder.self - new = true - } + override var self: KeysDistance = + KeysDistance().apply { + project = projectBuilder.self + new = true + } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/LanguageBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/LanguageBuilder.kt index bfdb92be6d..83f79d5243 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/LanguageBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/LanguageBuilder.kt @@ -4,9 +4,10 @@ import io.tolgee.development.testDataBuilder.EntityDataBuilder import io.tolgee.model.Language class LanguageBuilder( - val projectBuilder: ProjectBuilder + val projectBuilder: ProjectBuilder, ) : EntityDataBuilder { - override var self: Language = Language().apply { - project = projectBuilder.self - } + override var self: Language = + Language().apply { + project = projectBuilder.self + } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/MtServiceConfigBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/MtServiceConfigBuilder.kt index f6f6f27cc3..f2fabb78aa 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/MtServiceConfigBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/MtServiceConfigBuilder.kt @@ -3,10 +3,11 @@ package io.tolgee.development.testDataBuilder.builders import io.tolgee.model.mtServiceConfig.MtServiceConfig class MtServiceConfigBuilder( - val projectBuilder: ProjectBuilder + val projectBuilder: ProjectBuilder, ) : BaseEntityDataBuilder() { - override var self: MtServiceConfig = MtServiceConfig() - .apply { - project = projectBuilder.self - } + override var self: MtServiceConfig = + MtServiceConfig() + .apply { + project = projectBuilder.self + } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/NamespaceBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/NamespaceBuilder.kt index dc83c8f8c9..7dca49e8ce 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/NamespaceBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/NamespaceBuilder.kt @@ -3,7 +3,7 @@ package io.tolgee.development.testDataBuilder.builders import io.tolgee.model.key.Namespace class NamespaceBuilder( - val projectBuilder: ProjectBuilder + val projectBuilder: ProjectBuilder, ) : BaseEntityDataBuilder() { override var self: Namespace = Namespace("homepage", projectBuilder.self) } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/OrganizationBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/OrganizationBuilder.kt index 216bfa4c0b..9de12ce07e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/OrganizationBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/OrganizationBuilder.kt @@ -10,7 +10,7 @@ import io.tolgee.model.enums.ProjectPermissionType.VIEW import org.springframework.core.io.ClassPathResource class OrganizationBuilder( - val testDataBuilder: TestDataBuilder + val testDataBuilder: TestDataBuilder, ) : BaseEntityDataBuilder() { class DATA { var roles: MutableList = mutableListOf() @@ -31,12 +31,14 @@ class OrganizationBuilder( return builder } - override var self: Organization = Organization().also { - it.basePermission = Permission( - organization = it, - type = VIEW - ) - } + override var self: Organization = + Organization().also { + it.basePermission = + Permission( + organization = it, + type = VIEW, + ) + } fun setAvatar(filePath: String) { data.avatarFile = ClassPathResource(filePath, this.javaClass.classLoader) diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/OrganizationRoleBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/OrganizationRoleBuilder.kt index 18b3ebc7f7..333b94bbfb 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/OrganizationRoleBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/OrganizationRoleBuilder.kt @@ -4,11 +4,11 @@ import io.tolgee.development.testDataBuilder.EntityDataBuilder import io.tolgee.model.OrganizationRole class OrganizationRoleBuilder( - val organizationBuilder: OrganizationBuilder + val organizationBuilder: OrganizationBuilder, ) : EntityDataBuilder { - - override var self: OrganizationRole = OrganizationRole().apply { - organization = organizationBuilder.self - organizationBuilder.self.memberRoles.add(this) - } + override var self: OrganizationRole = + OrganizationRole().apply { + organization = organizationBuilder.self + organizationBuilder.self.memberRoles.add(this) + } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/PatBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/PatBuilder.kt index 4ec9cb1a8b..78d376e5aa 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/PatBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/PatBuilder.kt @@ -4,7 +4,7 @@ import io.tolgee.development.testDataBuilder.EntityDataBuilder import io.tolgee.model.Pat class PatBuilder( - val userAccountBuilder: UserAccountBuilder + val userAccountBuilder: UserAccountBuilder, ) : EntityDataBuilder { override var self: Pat = Pat().apply { userAccount = userAccountBuilder.self } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/PermissionBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/PermissionBuilder.kt index 2ae41f6071..bceb3c49f5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/PermissionBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/PermissionBuilder.kt @@ -5,9 +5,10 @@ import io.tolgee.model.Permission import io.tolgee.model.UserAccount class PermissionBuilder( - val projectBuilder: ProjectBuilder + val projectBuilder: ProjectBuilder, ) : EntityDataBuilder { - override var self: Permission = Permission(user = projectBuilder.onlyUser ?: UserAccount()).apply { - project = projectBuilder.self - } + override var self: Permission = + Permission(user = projectBuilder.onlyUser ?: UserAccount()).apply { + project = projectBuilder.self + } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ProjectBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ProjectBuilder.kt index f35d4d7be9..55b67b1f76 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ProjectBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/ProjectBuilder.kt @@ -23,17 +23,18 @@ import org.springframework.core.io.ClassPathResource class ProjectBuilder( organizationOwner: Organization? = null, - val testDataBuilder: TestDataBuilder + val testDataBuilder: TestDataBuilder, ) : BaseEntityDataBuilder() { - override var self: Project = Project().apply { - if (organizationOwner == null) { - if (testDataBuilder.data.organizations.size > 0) { - this.organizationOwner = testDataBuilder.data.organizations.first().self + override var self: Project = + Project().apply { + if (organizationOwner == null) { + if (testDataBuilder.data.organizations.size > 0) { + this.organizationOwner = testDataBuilder.data.organizations.first().self + } + return@apply } - return@apply + this.organizationOwner = organizationOwner } - this.organizationOwner = organizationOwner - } class DATA { val permissions = mutableListOf() @@ -61,15 +62,17 @@ class ProjectBuilder( fun addApiKey(ft: FT) = addOperation(data.apiKeys, ft) - fun addImport(ft: FT = {}) = - addOperation(data.imports, ImportBuilder(this), ft) + fun addImport(ft: FT = {}) = addOperation(data.imports, ImportBuilder(this), ft) - fun addLanguage(ft: FT) = - addOperation(data.languages, ft) + fun addLanguage(ft: FT) = addOperation(data.languages, ft) fun addKey(ft: FT) = addOperation(data.keys, ft) - fun addKey(namespace: String? = null, keyName: String, ft: (KeyBuilder.() -> Unit)? = null): KeyBuilder { + fun addKey( + namespace: String? = null, + keyName: String, + ft: (KeyBuilder.() -> Unit)? = null, + ): KeyBuilder { return addKey(keyName, ft).build { setNamespace(namespace) } } @@ -77,7 +80,10 @@ class ProjectBuilder( return addKey(keyName, null) } - fun addKey(keyName: String, ft: (KeyBuilder.() -> Unit)?): KeyBuilder { + fun addKey( + keyName: String, + ft: (KeyBuilder.() -> Unit)?, + ): KeyBuilder { return addKey { name = keyName }.apply { @@ -89,8 +95,7 @@ class ProjectBuilder( fun addTranslation(ft: FT) = addOperation(data.translations, ft) - fun addMtServiceConfig(ft: FT) = - addOperation(data.translationServiceConfigs, ft) + fun addMtServiceConfig(ft: FT) = addOperation(data.translationServiceConfigs, ft) fun setAvatar(filePath: String) { data.avatarFile = ClassPathResource(filePath, this.javaClass.classLoader) @@ -149,7 +154,11 @@ class ProjectBuilder( return data.languages.find { it.self.tag == tag } } - fun addKeysDistance(key1: Key, key2: Key, ft: FT): KeysDistanceBuilder { + fun addKeysDistance( + key1: Key, + key2: Key, + ft: FT, + ): KeysDistanceBuilder { val builder = KeysDistanceBuilder(this, key1, key2) ft(builder.self) data.keyDistances.add(builder) @@ -157,8 +166,11 @@ class ProjectBuilder( } fun addAutomation(ft: FT) = addOperation(data.automations, ft) + fun addContentStorage(ft: FT) = addOperation(data.contentStorages, ft) + fun addContentDeliveryConfig(ft: FT) = addOperation(data.contentDeliveryConfigs, ft) + fun addWebhookConfig(ft: FT) = addOperation(data.webhookConfigs, ft) val onlyUser get() = this.self.organizationOwner.memberRoles.singleOrNull()?.user diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/TestDataBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/TestDataBuilder.kt index b7e8afcecc..f5f07b21ad 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/TestDataBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/TestDataBuilder.kt @@ -6,7 +6,6 @@ import io.tolgee.model.UserAccount import io.tolgee.model.enums.OrganizationRoleType class TestDataBuilder(fn: (TestDataBuilder.() -> Unit) = {}) { - companion object { operator fun invoke(fn: (TestDataBuilder.() -> Unit) = {}) = TestDataBuilder(fn) } @@ -37,21 +36,22 @@ class TestDataBuilder(fn: (TestDataBuilder.() -> Unit) = {}) { val builder = UserAccountBuilder(this) data.userAccounts.add(builder) ft(builder.self) - val organizationBuilder = addOrganization { - name = if (builder.self.name.isNotBlank()) builder.self.name else builder.self.username - }.build { - addRole { - user = builder.self - type = OrganizationRoleType.OWNER + val organizationBuilder = + addOrganization { + name = if (builder.self.name.isNotBlank()) builder.self.name else builder.self.username + }.build { + addRole { + user = builder.self + type = OrganizationRoleType.OWNER + } } - } builder.defaultOrganizationBuilder = organizationBuilder return builder } fun addProject( organizationOwner: Organization? = null, - ft: Project.() -> Unit + ft: Project.() -> Unit, ): ProjectBuilder { val projectBuilder = ProjectBuilder(organizationOwner, testDataBuilder = this) data.projects.add(projectBuilder) diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/TranslationBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/TranslationBuilder.kt index 89cecaefcd..5fb28ec16a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/TranslationBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/TranslationBuilder.kt @@ -5,9 +5,8 @@ import io.tolgee.model.translation.Translation import io.tolgee.model.translation.TranslationComment class TranslationBuilder( - val projectBuilder: ProjectBuilder + val projectBuilder: ProjectBuilder, ) : BaseEntityDataBuilder() { - class DATA { var comments = mutableListOf() } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/TranslationCommentBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/TranslationCommentBuilder.kt index 89dfb7729c..4cab68b722 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/TranslationCommentBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/TranslationCommentBuilder.kt @@ -3,13 +3,14 @@ package io.tolgee.development.testDataBuilder.builders import io.tolgee.model.translation.TranslationComment class TranslationCommentBuilder( - private val translationBuilder: TranslationBuilder + private val translationBuilder: TranslationBuilder, ) : BaseEntityDataBuilder() { - override var self: TranslationComment = TranslationComment( - translation = translationBuilder.self, - ).also { comment -> - translationBuilder.projectBuilder.onlyUser?.let { - comment.author = it + override var self: TranslationComment = + TranslationComment( + translation = translationBuilder.self, + ).also { comment -> + translationBuilder.projectBuilder.onlyUser?.let { + comment.author = it + } } - } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/UserAccountBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/UserAccountBuilder.kt index ebf87e7aef..6adf059fc7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/UserAccountBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/UserAccountBuilder.kt @@ -7,7 +7,7 @@ import io.tolgee.model.UserPreferences import org.springframework.core.io.ClassPathResource class UserAccountBuilder( - val testDataBuilder: TestDataBuilder + val testDataBuilder: TestDataBuilder, ) : BaseEntityDataBuilder() { var rawPassword = "admin" override var self: UserAccount = UserAccount() @@ -26,8 +26,9 @@ class UserAccountBuilder( } fun setUserPreferences(ft: UserPreferences.() -> Unit) { - data.userPreferences = UserPreferencesBuilder(this) - .also { ft(it.self) } + data.userPreferences = + UserPreferencesBuilder(this) + .also { ft(it.self) } } fun addPat(ft: FT) = addOperation(data.pats, ft) diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/UserPreferencesBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/UserPreferencesBuilder.kt index 19bd3915d2..172f656d7a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/UserPreferencesBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/builders/UserPreferencesBuilder.kt @@ -4,7 +4,7 @@ import io.tolgee.development.testDataBuilder.EntityDataBuilder import io.tolgee.model.UserPreferences class UserPreferencesBuilder( - val userAccountBuilder: UserAccountBuilder + val userAccountBuilder: UserAccountBuilder, ) : EntityDataBuilder { override var self: UserPreferences = UserPreferences(userAccount = userAccountBuilder.self) lateinit var defaultOrganizationBuilder: OrganizationBuilder diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/AdministrationTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/AdministrationTestData.kt index b3e4743009..f93b5852b5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/AdministrationTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/AdministrationTestData.kt @@ -7,19 +7,20 @@ class AdministrationTestData { lateinit var admin: UserAccount lateinit var user: UserAccount - val root = TestDataBuilder().apply { - addUserAccount { - username = "admin@admin.com" - name = "Peter Administrator" - role = UserAccount.Role.ADMIN - admin = this - } + val root = + TestDataBuilder().apply { + addUserAccount { + username = "admin@admin.com" + name = "Peter Administrator" + role = UserAccount.Role.ADMIN + admin = this + } - addUserAccount { - username = "user@user.com" - name = "John User" - role = UserAccount.Role.USER - user = this + addUserAccount { + username = "user@user.com" + name = "John User" + role = UserAccount.Role.USER + user = this + } } - } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/AllOrganizationOwnerMigrationTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/AllOrganizationOwnerMigrationTestData.kt index dd5f795633..e860ff8a69 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/AllOrganizationOwnerMigrationTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/AllOrganizationOwnerMigrationTestData.kt @@ -4,31 +4,32 @@ import io.tolgee.development.testDataBuilder.builders.TestDataBuilder import io.tolgee.model.enums.ProjectPermissionType class AllOrganizationOwnerMigrationTestData { - val root = TestDataBuilder().apply { - addUserAccount { - name = "User with 2 projects" - username = "to.si@proladite.krkovicku" - }.build userAccount@{ - addProject { - name = "A project" - userOwner = this@userAccount.self - }.build project@{ - addPermission { - user = this@userAccount.self - project = this@project.self - type = ProjectPermissionType.MANAGE + val root = + TestDataBuilder().apply { + addUserAccount { + name = "User with 2 projects" + username = "to.si@proladite.krkovicku" + }.build userAccount@{ + addProject { + name = "A project" + userOwner = this@userAccount.self + }.build project@{ + addPermission { + user = this@userAccount.self + project = this@project.self + type = ProjectPermissionType.MANAGE + } } - } - addProject { - name = "A project 2" - userOwner = this@userAccount.self - }.build project@{ - addPermission { - user = this@userAccount.self - project = this@project.self - type = ProjectPermissionType.MANAGE + addProject { + name = "A project 2" + userOwner = this@userAccount.self + }.build project@{ + addPermission { + user = this@userAccount.self + project = this@project.self + type = ProjectPermissionType.MANAGE + } } } } - } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ApiKeysTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ApiKeysTestData.kt index 0f88dc8c1e..d4a6bf3bdd 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ApiKeysTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ApiKeysTestData.kt @@ -24,16 +24,17 @@ class ApiKeysTestData : BaseTestData() { init { this.root.apply { - val userAccountBuilder = addUserAccount { - name = "Franta Dobrota" - username = "franta" - frantisekDobrota = this - }.build { - addPat { - description = "cool pat" - frantasPat = this + val userAccountBuilder = + addUserAccount { + name = "Franta Dobrota" + username = "franta" + frantisekDobrota = this + }.build { + addPat { + description = "cool pat" + frantasPat = this + } } - } addProject { organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/AutoTranslateTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/AutoTranslateTestData.kt index c0bb50b4d3..158c773247 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/AutoTranslateTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/AutoTranslateTestData.kt @@ -20,11 +20,12 @@ class AutoTranslateTestData : BaseTestData() { tag = "de" germanLanguage = this } - val spanish = addLanguage { - name = "Spanish" - tag = "es" - spanishLanguage = this - }.self + val spanish = + addLanguage { + name = "Spanish" + tag = "es" + spanishLanguage = this + }.self addAutoTranslationConfig { usingTm = true usingPrimaryMtService = true diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/BaseTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/BaseTestData.kt index f85b402a1e..9495cd943f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/BaseTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/BaseTestData.kt @@ -9,42 +9,45 @@ import io.tolgee.model.enums.ProjectPermissionType open class BaseTestData( userName: String = "test_username", - projectName: String = "test_project" + projectName: String = "test_project", ) { var projectBuilder: ProjectBuilder lateinit var englishLanguage: Language var user: UserAccount var userAccountBuilder: UserAccountBuilder - val root: TestDataBuilder = TestDataBuilder().apply { - userAccountBuilder = addUserAccount { - username = userName + val root: TestDataBuilder = + TestDataBuilder().apply { + userAccountBuilder = + addUserAccount { + username = userName + } + + user = userAccountBuilder.self + + projectBuilder = + addProject { + name = projectName + organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self + }.build buildProject@{ + + addPermission { + project = this@buildProject.self + user = this@BaseTestData.user + type = ProjectPermissionType.MANAGE + } + + addLanguage { + name = "English" + tag = "en" + originalName = "English" + englishLanguage = this + this@buildProject.self.baseLanguage = this + } + + this.self { + baseLanguage = englishLanguage + } + } } - - user = userAccountBuilder.self - - projectBuilder = addProject { - name = projectName - organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self - }.build buildProject@{ - - addPermission { - project = this@buildProject.self - user = this@BaseTestData.user - type = ProjectPermissionType.MANAGE - } - - addLanguage { - name = "English" - tag = "en" - originalName = "English" - englishLanguage = this - this@buildProject.self.baseLanguage = this - } - - this.self { - baseLanguage = englishLanguage - } - } - } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/BatchJobsTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/BatchJobsTestData.kt index 722dc21567..12d33ba050 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/BatchJobsTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/BatchJobsTestData.kt @@ -4,7 +4,6 @@ import io.tolgee.model.enums.Scope import io.tolgee.model.key.Key class BatchJobsTestData : BaseTestData() { - val anotherUser = root.addUserAccount { username = "anotherUser" }.self val germanLanguage = projectBuilder.addGerman().self val czechLanguage = projectBuilder.addCzech().self diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/BigMetaTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/BigMetaTestData.kt index 6bc5ec4a32..8e7778fbf2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/BigMetaTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/BigMetaTestData.kt @@ -15,24 +15,27 @@ class BigMetaTestData { lateinit var noNsKey: Key lateinit var yepKey: Key - val root = TestDataBuilder().apply { - addUserAccount { - username = "hehe@hehe" - userAccount = this - } - projectBuilder = addProject { - name = "Project" - this@BigMetaTestData.project = this - }.build { - noNsKey = addKey(null, "key").self - yepKey = addKey("yep", "key").self + val root = + TestDataBuilder().apply { + addUserAccount { + username = "hehe@hehe" + userAccount = this + } + projectBuilder = + addProject { + name = "Project" + this@BigMetaTestData.project = this + }.build { + noNsKey = addKey(null, "key").self + yepKey = addKey("yep", "key").self + } } - } fun addLotOfData(): List { - val keys = (0..5000).map { - projectBuilder.addKey(null, "key$it").self - } + val keys = + (0..5000).map { + projectBuilder.addKey(null, "key$it").self + } keys.forEachIndexed forEach1@{ idx1, key1 -> keys.forEachIndexed forEach2@{ idx2, key2 -> diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ContentDeliveryConfigTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ContentDeliveryConfigTestData.kt index 5c88972a8a..717d6ae947 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ContentDeliveryConfigTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ContentDeliveryConfigTestData.kt @@ -7,47 +7,58 @@ import io.tolgee.model.contentDelivery.AzureContentStorageConfig import io.tolgee.model.contentDelivery.S3ContentStorageConfig class ContentDeliveryConfigTestData : BaseTestData() { - val azureContentStorage = projectBuilder.addContentStorage { - this.azureContentStorageConfig = AzureContentStorageConfig(this).apply { - connectionString = "fake" - containerName = "fake" + val azureContentStorage = + projectBuilder.addContentStorage { + this.azureContentStorageConfig = + AzureContentStorageConfig(this).apply { + connectionString = "fake" + containerName = "fake" + } } - } - - val s3ContentStorage = projectBuilder.addContentStorage { - name = "S3" - this.s3ContentStorageConfig = S3ContentStorageConfig(this).apply { - bucketName = "fake" - accessKey = "fake" - secretKey = "fake" - endpoint = "fake" - signingRegion = "fake" + + val s3ContentStorage = + projectBuilder.addContentStorage { + name = "S3" + this.s3ContentStorageConfig = + S3ContentStorageConfig(this).apply { + bucketName = "fake" + accessKey = "fake" + secretKey = "fake" + endpoint = "fake" + signingRegion = "fake" + } + } + + val defaultServerContentDeliveryConfig = + projectBuilder.addContentDeliveryConfig { + name = "Default server" + } + + val azureContentDeliveryConfig = + projectBuilder.addContentDeliveryConfig { + contentStorage = azureContentStorage.self + name = "Azure" + } + + val s3ContentDeliveryConfig = + projectBuilder.addContentDeliveryConfig { + contentStorage = s3ContentStorage.self + name = "S3" + } + + val automation = + projectBuilder.addAutomation { + this.triggers.add( + AutomationTrigger(this) + .also { it.type = AutomationTriggerType.TRANSLATION_DATA_MODIFICATION }, + ) + this.actions.add( + AutomationAction(this).also { it.contentDeliveryConfig = defaultServerContentDeliveryConfig.self }, + ) + } + + val keyWithTranslation = + this.projectBuilder.addKey("key") { + addTranslation("en", "Hello") } - } - - val defaultServerContentDeliveryConfig = projectBuilder.addContentDeliveryConfig { - name = "Default server" - } - - val azureContentDeliveryConfig = projectBuilder.addContentDeliveryConfig { - contentStorage = azureContentStorage.self - name = "Azure" - } - - val s3ContentDeliveryConfig = projectBuilder.addContentDeliveryConfig { - contentStorage = s3ContentStorage.self - name = "S3" - } - - val automation = projectBuilder.addAutomation { - this.triggers.add( - AutomationTrigger(this) - .also { it.type = AutomationTriggerType.TRANSLATION_DATA_MODIFICATION } - ) - this.actions.add(AutomationAction(this).also { it.contentDeliveryConfig = defaultServerContentDeliveryConfig.self }) - } - - val keyWithTranslation = this.projectBuilder.addKey("key") { - addTranslation("en", "Hello") - } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/FormerUserTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/FormerUserTestData.kt index 87696c0a31..8079cffcb9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/FormerUserTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/FormerUserTestData.kt @@ -14,50 +14,52 @@ class FormerUserTestData { lateinit var translation: Translation lateinit var project: Project - val root = TestDataBuilder().apply { - addUserAccount { - username = "admin@admin.com" - name = "Peter Administrator" - role = UserAccount.Role.ADMIN - activeUser = this - }.build { - organizationBuilder = defaultOrganizationBuilder - } - - addUserAccountWithoutOrganization { - username = "will@be.removed" - name = "Will Be Removed" - role = UserAccount.Role.USER - formerUser = this - } + val root = + TestDataBuilder().apply { + addUserAccount { + username = "admin@admin.com" + name = "Peter Administrator" + role = UserAccount.Role.ADMIN + activeUser = this + }.build { + organizationBuilder = defaultOrganizationBuilder + } - organizationBuilder.build { - addRole { - user = formerUser - type = OrganizationRoleType.OWNER + addUserAccountWithoutOrganization { + username = "will@be.removed" + name = "Will Be Removed" + role = UserAccount.Role.USER + formerUser = this } - } - addProject { - organizationOwner = organizationBuilder.self - name = "project" - project = this - }.build { - val key = addKey { - name = "key" + organizationBuilder.build { + addRole { + user = formerUser + type = OrganizationRoleType.OWNER + } } - val en = addEnglish() - addTranslation { - text = "helloo" - language = en.self - this.key = key.self - translation = this + + addProject { + organizationOwner = organizationBuilder.self + name = "project" + project = this }.build { - addComment { - text = "Hellooo!" - author = formerUser + val key = + addKey { + name = "key" + } + val en = addEnglish() + addTranslation { + text = "helloo" + language = en.self + this.key = key.self + translation = this + }.build { + addComment { + text = "Hellooo!" + author = formerUser + } } } } - } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/KeyLanguageDisablingTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/KeyLanguageDisablingTestData.kt index dd0ebb8c7c..7de6b2bff5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/KeyLanguageDisablingTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/KeyLanguageDisablingTestData.kt @@ -4,12 +4,12 @@ import io.tolgee.development.testDataBuilder.builders.TestDataBuilder import io.tolgee.model.enums.TranslationState class KeyLanguageDisablingTestData { - val root: TestDataBuilder = TestDataBuilder() - val user = root.addUserAccount { - username = "user" - }.self + val user = + root.addUserAccount { + username = "user" + }.self val project = root.addProject { name = "project" } @@ -20,19 +20,22 @@ class KeyLanguageDisablingTestData { val key = project.addKey("key") - val enTranslation = key.addTranslation { - language = english.self - } - - val deTranslation = key.addTranslation { - language = german.self - text = null - state = TranslationState.DISABLED - } - - val csTranslation = key.addTranslation { - language = czech.self - text = null - state = TranslationState.DISABLED - } + val enTranslation = + key.addTranslation { + language = english.self + } + + val deTranslation = + key.addTranslation { + language = german.self + text = null + state = TranslationState.DISABLED + } + + val csTranslation = + key.addTranslation { + language = czech.self + text = null + state = TranslationState.DISABLED + } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/KeySearchTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/KeySearchTestData.kt index 5331bce5e3..df4624e527 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/KeySearchTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/KeySearchTestData.kt @@ -5,7 +5,6 @@ import net.datafaker.Faker import java.util.* class KeySearchTestData : BaseTestData() { - init { projectBuilder.addGerman() @@ -24,7 +23,11 @@ class KeySearchTestData : BaseTestData() { } } - fun ProjectBuilder.addKeyWithTranslations(keyName: String, translation: String?, baseTranslation: String) { + fun ProjectBuilder.addKeyWithTranslations( + keyName: String, + translation: String?, + baseTranslation: String, + ) { addKey { name = keyName addTranslation { @@ -44,7 +47,7 @@ class KeySearchTestData : BaseTestData() { this.projectBuilder.addKeyWithTranslations( getRandomWords(), getRandomWords(), - getRandomWords() + getRandomWords(), ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/KeysInfoTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/KeysInfoTestData.kt index de541aa683..60a718f5bf 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/KeysInfoTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/KeysInfoTestData.kt @@ -3,7 +3,6 @@ package io.tolgee.development.testDataBuilder.data import io.tolgee.model.Screenshot class KeysInfoTestData : BaseTestData() { - lateinit var key1and2Screenshot: Screenshot lateinit var key2Screenshot: Screenshot @@ -17,9 +16,10 @@ class KeysInfoTestData : BaseTestData() { key1and2Screenshot = addScreenshot { }.self } - val key2 = addKey("namespace-1", "key-2") { - addTranslation("de", "existing translation") - } + val key2 = + addKey("namespace-1", "key-2") { + addTranslation("de", "existing translation") + } addScreenshotReference { screenshot = key1and2Screenshot diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/KeysTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/KeysTestData.kt index 4119bcf906..2ffa214ea0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/KeysTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/KeysTestData.kt @@ -24,88 +24,96 @@ class KeysTestData { var projectBuilder: ProjectBuilder - val root: TestDataBuilder = TestDataBuilder().apply { - val userAccountBuilder = addUserAccount { - username = "Peter" - user = this - } + val root: TestDataBuilder = + TestDataBuilder().apply { + val userAccountBuilder = + addUserAccount { + username = "Peter" + user = this + } - project2 = addProject { - name = "Other project" - organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self - }.build { - addPermission { - user = this@KeysTestData.user - type = ProjectPermissionType.MANAGE - } - }.self + project2 = + addProject { + name = "Other project" + organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self + }.build { + addPermission { + user = this@KeysTestData.user + type = ProjectPermissionType.MANAGE + } + }.self - projectBuilder = addProject { - name = "Peter's project" - organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self - project = this - }.build { - english = addLanguage { - name = "English" - tag = "en" - }.self + projectBuilder = + addProject { + name = "Peter's project" + organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self + project = this + }.build { + english = + addLanguage { + name = "English" + tag = "en" + }.self - german = addLanguage { - name = "German" - tag = "de" - }.self + german = + addLanguage { + name = "German" + tag = "de" + }.self - addPermission { - user = this@KeysTestData.user - type = ProjectPermissionType.MANAGE - } + addPermission { + user = this@KeysTestData.user + type = ProjectPermissionType.MANAGE + } - firstKey = addKey { - name = "first_key" - }.self + firstKey = + addKey { + name = "first_key" + }.self - secondKey = addKey { - name = "second_key" - }.build { - screenshot = addScreenshot { }.self - }.self + secondKey = + addKey { + name = "second_key" + }.build { + screenshot = addScreenshot { }.self + }.self - addKey { - name = "key_with_referecnces" - this@KeysTestData.keyWithReferences = this - }.build { - addScreenshotReference { - screenshot = this@KeysTestData.screenshot - key = this@build.self - } - addMeta { - tags.add( - Tag().apply { - project = projectBuilder.self - name = "test" + addKey { + name = "key_with_referecnces" + this@KeysTestData.keyWithReferences = this + }.build { + addScreenshotReference { + screenshot = this@KeysTestData.screenshot + key = this@build.self + } + addMeta { + tags.add( + Tag().apply { + project = projectBuilder.self + name = "test" + }, + ) + addComment { + text = "What a text comment" + } + addCodeReference { + line = 20 + path = "./code/exist.extension" + } } - ) - addComment { - text = "What a text comment" - } - addCodeReference { - line = 20 - path = "./code/exist.extension" } } - } - } - addUserAccountWithoutOrganization { - username = "enOnly" - projectBuilder.addPermission { - user = this@addUserAccountWithoutOrganization - type = ProjectPermissionType.TRANSLATE - translateLanguages = mutableSetOf(english) + addUserAccountWithoutOrganization { + username = "enOnly" + projectBuilder.addPermission { + user = this@addUserAccountWithoutOrganization + type = ProjectPermissionType.TRANSLATE + translateLanguages = mutableSetOf(english) + } + enOnlyUserAccount = this } - enOnlyUserAccount = this } - } fun addNKeys(n: Int) { (1..n).forEach { diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/LanguagePermissionsTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/LanguagePermissionsTestData.kt index b81dab1a97..9b547b9f46 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/LanguagePermissionsTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/LanguagePermissionsTestData.kt @@ -23,81 +23,94 @@ class LanguagePermissionsTestData { lateinit var germanTranslation: Translation lateinit var projectBuilder: ProjectBuilder - val root: TestDataBuilder = TestDataBuilder().apply { - addProject() - } + val root: TestDataBuilder = + TestDataBuilder().apply { + addProject() + } - val reviewEnOnlyUser = addUserAccountWithPermissions { - translateLanguages = mutableSetOf(englishLanguage) - type = ProjectPermissionType.REVIEW - } + val reviewEnOnlyUser = + addUserAccountWithPermissions { + translateLanguages = mutableSetOf(englishLanguage) + type = ProjectPermissionType.REVIEW + } - val translateEnOnlyUser = addUserAccountWithPermissions { - translateLanguages = mutableSetOf(englishLanguage) - type = ProjectPermissionType.TRANSLATE - } + val translateEnOnlyUser = + addUserAccountWithPermissions { + translateLanguages = mutableSetOf(englishLanguage) + type = ProjectPermissionType.TRANSLATE + } - val translateAllUser = addUserAccountWithPermissions { - type = ProjectPermissionType.TRANSLATE - } + val translateAllUser = + addUserAccountWithPermissions { + type = ProjectPermissionType.TRANSLATE + } - val reviewAllUser = addUserAccountWithPermissions { - type = ProjectPermissionType.REVIEW - } + val reviewAllUser = + addUserAccountWithPermissions { + type = ProjectPermissionType.REVIEW + } - val translateAllExplicitUser = addUserAccountWithPermissions { - type = ProjectPermissionType.TRANSLATE - translateLanguages = mutableSetOf(englishLanguage, germanLanguage) - } + val translateAllExplicitUser = + addUserAccountWithPermissions { + type = ProjectPermissionType.TRANSLATE + translateLanguages = mutableSetOf(englishLanguage, germanLanguage) + } - val reviewUser = addUserAccountWithPermissions { - type = ProjectPermissionType.REVIEW - translateLanguages = mutableSetOf(englishLanguage) - viewLanguages = mutableSetOf(englishLanguage) - stateChangeLanguages = mutableSetOf(englishLanguage) - } + val reviewUser = + addUserAccountWithPermissions { + type = ProjectPermissionType.REVIEW + translateLanguages = mutableSetOf(englishLanguage) + viewLanguages = mutableSetOf(englishLanguage) + stateChangeLanguages = mutableSetOf(englishLanguage) + } - val translateUser = addUserAccountWithPermissions { - type = ProjectPermissionType.TRANSLATE - translateLanguages = mutableSetOf(englishLanguage) - viewLanguages = mutableSetOf(englishLanguage) - stateChangeLanguages = mutableSetOf() - } + val translateUser = + addUserAccountWithPermissions { + type = ProjectPermissionType.TRANSLATE + translateLanguages = mutableSetOf(englishLanguage) + viewLanguages = mutableSetOf(englishLanguage) + stateChangeLanguages = mutableSetOf() + } - val viewEnOnlyUser = addUserAccountWithPermissions { - type = ProjectPermissionType.VIEW - translateLanguages = mutableSetOf() - viewLanguages = mutableSetOf(englishLanguage) - stateChangeLanguages = mutableSetOf() - } + val viewEnOnlyUser = + addUserAccountWithPermissions { + type = ProjectPermissionType.VIEW + translateLanguages = mutableSetOf() + viewLanguages = mutableSetOf(englishLanguage) + stateChangeLanguages = mutableSetOf() + } - val viewScopeUser = addUserAccountWithPermissions { - scopes = arrayOf(Scope.TRANSLATIONS_VIEW) - type = null - translateLanguages = mutableSetOf() - viewLanguages = mutableSetOf(englishLanguage) - stateChangeLanguages = mutableSetOf() - } + val viewScopeUser = + addUserAccountWithPermissions { + scopes = arrayOf(Scope.TRANSLATIONS_VIEW) + type = null + translateLanguages = mutableSetOf() + viewLanguages = mutableSetOf(englishLanguage) + stateChangeLanguages = mutableSetOf() + } - val editScopeUser = addUserAccountWithPermissions { - scopes = arrayOf(Scope.TRANSLATIONS_EDIT) - type = null - translateLanguages = mutableSetOf(englishLanguage) - } + val editScopeUser = + addUserAccountWithPermissions { + scopes = arrayOf(Scope.TRANSLATIONS_EDIT) + type = null + translateLanguages = mutableSetOf(englishLanguage) + } - val stateChangeScopeUser = addUserAccountWithPermissions { - scopes = arrayOf(Scope.TRANSLATIONS_STATE_EDIT, Scope.TRANSLATIONS_EDIT) - type = null - stateChangeLanguages = mutableSetOf(englishLanguage) - } + val stateChangeScopeUser = + addUserAccountWithPermissions { + scopes = arrayOf(Scope.TRANSLATIONS_STATE_EDIT, Scope.TRANSLATIONS_EDIT) + type = null + stateChangeLanguages = mutableSetOf(englishLanguage) + } - val stateChangeScopeUserEnForAll = addUserAccountWithPermissions { - scopes = arrayOf(Scope.TRANSLATIONS_STATE_EDIT, Scope.TRANSLATIONS_EDIT) - type = null - translateLanguages = mutableSetOf(englishLanguage) - viewLanguages = mutableSetOf(englishLanguage) - stateChangeLanguages = mutableSetOf(englishLanguage) - } + val stateChangeScopeUserEnForAll = + addUserAccountWithPermissions { + scopes = arrayOf(Scope.TRANSLATIONS_STATE_EDIT, Scope.TRANSLATIONS_EDIT) + type = null + translateLanguages = mutableSetOf(englishLanguage) + viewLanguages = mutableSetOf(englishLanguage) + stateChangeLanguages = mutableSetOf(englishLanguage) + } init { projectBuilder.apply { @@ -110,9 +123,10 @@ class LanguagePermissionsTestData { } private fun TestDataBuilder.addProject() { - val organization = addOrganization { - name = "Org" - } + val organization = + addOrganization { + name = "Org" + } addProject { project = this @@ -146,9 +160,10 @@ class LanguagePermissionsTestData { } private fun addUserAccountWithPermissions(setPerms: Permission.() -> Unit): UserAccount { - val userBuilder = this.root.addUserAccount { - this@addUserAccount.username = UUID.randomUUID().toString() - } + val userBuilder = + this.root.addUserAccount { + this@addUserAccount.username = UUID.randomUUID().toString() + } projectBuilder.addPermission { user = userBuilder.self diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/MtSettingsTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/MtSettingsTestData.kt index 51494fa275..a7e27415c2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/MtSettingsTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/MtSettingsTestData.kt @@ -9,16 +9,18 @@ class MtSettingsTestData : BaseTestData() { init { projectBuilder.apply { - germanLanguage = addLanguage { - name = "German" - tag = "de" - originalName = "Deutsch" - }.self - spanishLanguage = addLanguage { - name = "Sp" - tag = "es" - originalName = "Spanish" - }.self + germanLanguage = + addLanguage { + name = "German" + tag = "de" + originalName = "Deutsch" + }.self + spanishLanguage = + addLanguage { + name = "Sp" + tag = "es" + originalName = "Spanish" + }.self addFrench() } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/NamespacesTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/NamespacesTestData.kt index c55b5fc30e..513a2ebc45 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/NamespacesTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/NamespacesTestData.kt @@ -61,18 +61,22 @@ class NamespacesTestData : BaseTestData() { } } - private fun ProjectBuilder.addKeyWithTranslation(keyName: String, namespace: String?): Key { - val keyBuilder = this.addKey { - name = keyName - }.build { - setNamespace(namespace)?.self?.let { - namespaces[it.project to it.name] = it - } - addTranslation { - language = englishLanguage - text = "hello" + private fun ProjectBuilder.addKeyWithTranslation( + keyName: String, + namespace: String?, + ): Key { + val keyBuilder = + this.addKey { + name = keyName + }.build { + setNamespace(namespace)?.self?.let { + namespaces[it.project to it.name] = it + } + addTranslation { + language = englishLanguage + text = "hello" + } } - } return keyBuilder.self } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/OrganizationTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/OrganizationTestData.kt index 454ca4eb4a..021b18b7c0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/OrganizationTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/OrganizationTestData.kt @@ -25,11 +25,12 @@ class OrganizationTestData : BaseTestData() { user = franta } - val pepaBuilder = addUserAccountWithoutOrganization { - username = "pepa" - name = "Josef Tyl" - pepa = this - } + val pepaBuilder = + addUserAccountWithoutOrganization { + username = "pepa" + name = "Josef Tyl" + pepa = this + } projectBuilder.addPermission { user = pepa @@ -53,17 +54,19 @@ class OrganizationTestData : BaseTestData() { } } - val jirinaBuilder = addUserAccountWithoutOrganization { - username = "jirina" - name = "Jirina Svetla" - jirina = this - } + val jirinaBuilder = + addUserAccountWithoutOrganization { + username = "jirina" + name = "Jirina Svetla" + jirina = this + } - val kvetoslavBuilder = addUserAccountWithoutOrganization { - username = "kvetoslav" - name = "Kvetoslav Barta" - kvetoslav = this - } + val kvetoslavBuilder = + addUserAccountWithoutOrganization { + username = "kvetoslav" + name = "Kvetoslav Barta" + kvetoslav = this + } projectBuilder.build { addPermission { diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PatTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PatTestData.kt index b61277f779..508d309962 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PatTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PatTestData.kt @@ -11,33 +11,34 @@ class PatTestData { lateinit var pat: Pat lateinit var expiredPat: Pat - val root = TestDataBuilder().apply { - addUserAccount { - username = "peter@peter.com" - name = "Peter Peter" - role = UserAccount.Role.ADMIN - user2 = this - } - - addUserAccount { - username = "user@user.com" - name = "John User" - role = UserAccount.Role.USER - user = this - }.build { - addPat { - description = "Expired PAT" - expiresAt = Date(1661342685000) - lastUsedAt = Date(1661342385000) - expiredPat = this + val root = + TestDataBuilder().apply { + addUserAccount { + username = "peter@peter.com" + name = "Peter Peter" + role = UserAccount.Role.ADMIN + user2 = this } - addPat { - description = "Yee2" - pat = this - } - addPat { - description = "Yeey3" + + addUserAccount { + username = "user@user.com" + name = "John User" + role = UserAccount.Role.USER + user = this + }.build { + addPat { + description = "Expired PAT" + expiresAt = Date(1661342685000) + lastUsedAt = Date(1661342385000) + expiredPat = this + } + addPat { + description = "Yee2" + pat = this + } + addPat { + description = "Yeey3" + } } } - } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PermissionsTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PermissionsTestData.kt index 6d141270c7..6df0f699d5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PermissionsTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/PermissionsTestData.kt @@ -17,55 +17,59 @@ class PermissionsTestData { var organizationBuilder: OrganizationBuilder var admin: UserAccountBuilder - val root: TestDataBuilder = TestDataBuilder().apply { - admin = addUserAccount { username = "admin@admin.com" } - organizationBuilder = admin.defaultOrganizationBuilder + val root: TestDataBuilder = + TestDataBuilder().apply { + admin = addUserAccount { username = "admin@admin.com" } + organizationBuilder = admin.defaultOrganizationBuilder - val member = addUserAccount { username = "member@member.com" } - addUserAccount { username = "no@no.no" } + val member = addUserAccount { username = "member@member.com" } + addUserAccount { username = "no@no.no" } - val orgOnly = addUserAccount { username = "org@org.org" } + val orgOnly = addUserAccount { username = "org@org.org" } - organizationBuilder.build { - addRole { - user = orgOnly.self - type = OrganizationRoleType.MEMBER + organizationBuilder.build { + addRole { + user = orgOnly.self + type = OrganizationRoleType.MEMBER + } } - } - projectBuilder = addProject { name = "Project" }.build { - val en = addEnglish() - val de = addGerman() - val cs = addCzech() + projectBuilder = + addProject { name = "Project" }.build { + val en = addEnglish() + val de = addGerman() + val cs = addCzech() - addPermission { - this.user = member.self - this.type = ProjectPermissionType.VIEW - } + addPermission { + this.user = member.self + this.type = ProjectPermissionType.VIEW + } - val keyBuilders = (1..10).map { i -> - addKey { name = "key-$i" }.build { - - listOf(en, de, cs).forEach { - addTranslation { - text = "${it.self.name} text $i" - language = it.self - }.build { - addComment { - text = "comment $i" - author = admin.self + val keyBuilders = + (1..10).map { i -> + addKey { name = "key-$i" }.build { + + listOf(en, de, cs).forEach { + addTranslation { + text = "${it.self.name} text $i" + language = it.self + }.build { + addComment { + text = "comment $i" + author = admin.self + } + } + } } } + + keyBuilders[0].apply { + val screenshotResource = + ClassPathResource("development/testScreenshot.png", this::class.java.getClassLoader()) + addScreenshot(screenshotResource) {} } } - } - - keyBuilders[0].apply { - val screenshotResource = ClassPathResource("development/testScreenshot.png", this::class.java.getClassLoader()) - addScreenshot(screenshotResource) {} - } } - } fun addUserWithPermissions( scopes: List? = null, @@ -75,9 +79,10 @@ class PermissionsTestData { stateChangeLanguageTags: List? = null, organizationBaseScopes: List? = null, ): UserAccount { - val me = root.addUserAccount { - username = "me@me.me" - } + val me = + root.addUserAccount { + username = "me@me.me" + } projectBuilder.build { addPermission { @@ -104,9 +109,10 @@ class PermissionsTestData { } fun addUnrelatedUsers() { - val user = root.addUserAccount { - username = "unrelated@ur.com" - } + val user = + root.addUserAccount { + username = "unrelated@ur.com" + } root.addUserAccount { username = "another@an.com" } @@ -121,9 +127,10 @@ class PermissionsTestData { } } - private fun getLanguagesByTags(tags: List?) = tags?.map { tag -> - projectBuilder.data.languages.find { it.self.tag == tag }?.self ?: throw NotFoundException( - Message.LANGUAGE_NOT_FOUND - ) - }?.toMutableSet() ?: mutableSetOf() + private fun getLanguagesByTags(tags: List?) = + tags?.map { tag -> + projectBuilder.data.languages.find { it.self.tag == tag }?.self ?: throw NotFoundException( + Message.LANGUAGE_NOT_FOUND, + ) + }?.toMutableSet() ?: mutableSetOf() } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectStatsTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectStatsTestData.kt index ccb5aa379b..b3af72a4b9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectStatsTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectStatsTestData.kt @@ -17,15 +17,17 @@ class ProjectStatsTestData : BaseTestData() { addLanguages() addKeys() - val organizationOwner = root.addUserAccount { - name = "franta" - username = "franta" - }.self - - val organizationMember = root.addUserAccount { - name = "jindra" - username = "jindra" - }.self + val organizationOwner = + root.addUserAccount { + name = "franta" + username = "franta" + }.self + + val organizationMember = + root.addUserAccount { + name = "jindra" + username = "jindra" + }.self root.addOrganization { name = "org" @@ -56,20 +58,23 @@ class ProjectStatsTestData : BaseTestData() { } private fun ProjectBuilder.addKeys() { - val tag1 = Tag().apply { - name = "Tag1" - project = this@addKeys.self - } + val tag1 = + Tag().apply { + name = "Tag1" + project = this@addKeys.self + } - val tag2 = Tag().apply { - name = "Tag2" - project = this@addKeys.self - } + val tag2 = + Tag().apply { + name = "Tag2" + project = this@addKeys.self + } - val tag3 = Tag().apply { - name = "Tag3" - project = this@addKeys.self - } + val tag3 = + Tag().apply { + name = "Tag3" + project = this@addKeys.self + } addKey { name = "Super key" diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsTestData.kt index 8bc6edecff..bd6813e37f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ProjectsTestData.kt @@ -33,16 +33,18 @@ class ProjectsTestData : BaseTestData() { type = ProjectPermissionType.MANAGE } - project2English = addLanguage { - name = "English" - tag = "en" - this@buildProject.self.baseLanguage = this - }.self + project2English = + addLanguage { + name = "English" + tag = "en" + this@buildProject.self.baseLanguage = this + }.self - project2Deutsch = addLanguage { - name = "Deutsch" - tag = "de" - }.self + project2Deutsch = + addLanguage { + name = "Deutsch" + tag = "de" + }.self addPermission { user = userWithTranslatePermission diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ResolvableImportTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ResolvableImportTestData.kt index 63d5e128e7..b7ce25bf69 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ResolvableImportTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/ResolvableImportTestData.kt @@ -5,7 +5,6 @@ import io.tolgee.model.UserAccount import io.tolgee.model.enums.Scope class ResolvableImportTestData : BaseTestData() { - lateinit var key1and2Screenshot: Screenshot lateinit var key2Screenshot: Screenshot lateinit var enOnlyUser: UserAccount @@ -19,9 +18,10 @@ class ResolvableImportTestData : BaseTestData() { addKey("namespace-1", "key-1") { addTranslation("de", "existing translation") - key1and2Screenshot = addScreenshot { - location = "My cool frame" - }.self + key1and2Screenshot = + addScreenshot { + location = "My cool frame" + }.self } addKey("namespace-1", "key-2") { diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/SensitiveOperationProtectionTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/SensitiveOperationProtectionTestData.kt index 9f71f408fc..7bfd34d699 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/SensitiveOperationProtectionTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/SensitiveOperationProtectionTestData.kt @@ -14,29 +14,30 @@ class SensitiveOperationProtectionTestData { lateinit var frantasProject: Project lateinit var pepasProject: Project - val root = TestDataBuilder { - addUserAccount { - username = "franta" - name = "Franta" - franta = this - }.build { - addProject { - name = "Project" - organizationOwner = this@build.defaultOrganizationBuilder.self - frantasProject = this + val root = + TestDataBuilder { + addUserAccount { + username = "franta" + name = "Franta" + franta = this + }.build { + addProject { + name = "Project" + organizationOwner = this@build.defaultOrganizationBuilder.self + frantasProject = this + } } - } - addUserAccount { - username = "pepa" - name = "Pepa" - totpKey = TOTP_KEY - pepa = this - }.build { - addProject { - name = "Project" - organizationOwner = this@build.defaultOrganizationBuilder.self - pepasProject = this + addUserAccount { + username = "pepa" + name = "Pepa" + totpKey = TOTP_KEY + pepa = this + }.build { + addProject { + name = "Project" + organizationOwner = this@build.defaultOrganizationBuilder.self + pepasProject = this + } } } - } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/SuggestionTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/SuggestionTestData.kt index 2656e7166a..9bee56d33a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/SuggestionTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/SuggestionTestData.kt @@ -17,11 +17,12 @@ class SuggestionTestData : BaseTestData() { init { projectBuilder.apply { - germanLanguage = addLanguage { - name = "German" - tag = "de" - originalName = "Deutsch" - }.self + germanLanguage = + addLanguage { + name = "German" + tag = "de" + originalName = "Deutsch" + }.self addKeys() addKeyDistances() } @@ -162,8 +163,12 @@ class SuggestionTestData : BaseTestData() { this.targetLanguage = germanLanguage this.enabledServices = mutableSetOf( - MtServiceType.GOOGLE, MtServiceType.AWS, MtServiceType.DEEPL, MtServiceType.AZURE, - MtServiceType.BAIDU, MtServiceType.TOLGEE + MtServiceType.GOOGLE, + MtServiceType.AWS, + MtServiceType.DEEPL, + MtServiceType.AZURE, + MtServiceType.BAIDU, + MtServiceType.TOLGEE, ) this.primaryService = MtServiceType.AWS } @@ -174,8 +179,11 @@ class SuggestionTestData : BaseTestData() { this.targetLanguage = germanLanguage this.enabledServices = mutableSetOf( - MtServiceType.GOOGLE, MtServiceType.AWS, MtServiceType.DEEPL, MtServiceType.AZURE, - MtServiceType.BAIDU + MtServiceType.GOOGLE, + MtServiceType.AWS, + MtServiceType.DEEPL, + MtServiceType.AZURE, + MtServiceType.BAIDU, ) this.primaryService = MtServiceType.GOOGLE } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/TranslationCommentsTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/TranslationCommentsTestData.kt index b5c9422717..6a6cc82e2d 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/TranslationCommentsTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/TranslationCommentsTestData.kt @@ -25,95 +25,105 @@ class TranslationCommentsTestData { lateinit var projectBuilder: ProjectBuilder lateinit var translation: Translation - val root: TestDataBuilder = TestDataBuilder().apply { - var userAccountBuilder = addUserAccount { - username = "franta" - user = this - } - pepa = addUserAccount { - username = "pepa" - }.self - - project = addProject { - name = "Franta's project" - organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self - }.build { - addPermission { - user = this@TranslationCommentsTestData.user - type = ProjectPermissionType.MANAGE - } - - addPermission { - user = this@TranslationCommentsTestData.pepa - type = null - scopes = arrayOf(Scope.TRANSLATIONS_VIEW) - } + val root: TestDataBuilder = + TestDataBuilder().apply { + var userAccountBuilder = + addUserAccount { + username = "franta" + user = this + } + pepa = + addUserAccount { + username = "pepa" + }.self - englishLanguage = addLanguage { - name = "English" - tag = "en" - originalName = "English" - }.self + project = + addProject { + name = "Franta's project" + organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self + }.build { + addPermission { + user = this@TranslationCommentsTestData.user + type = ProjectPermissionType.MANAGE + } + + addPermission { + user = this@TranslationCommentsTestData.pepa + type = null + scopes = arrayOf(Scope.TRANSLATIONS_VIEW) + } + + englishLanguage = + addLanguage { + name = "English" + tag = "en" + originalName = "English" + }.self - czechLanguage = addLanguage { - name = "Czech" - tag = "cs" - originalName = "Čeština" - }.self + czechLanguage = + addLanguage { + name = "Czech" + tag = "cs" + originalName = "Čeština" + }.self - self.baseLanguage = czechLanguage + self.baseLanguage = czechLanguage - addKey { - name = "A key" - this@TranslationCommentsTestData.aKey = this - }.build { - addTranslation { - language = englishLanguage - text = "Z translation" - state = TranslationState.REVIEWED - this@TranslationCommentsTestData.translation = this - }.build { - firstComment = addComment { - text = "First comment" - }.self - secondComment = addComment { - text = "Second comment" - }.self - } + addKey { + name = "A key" + this@TranslationCommentsTestData.aKey = this + }.build { + addTranslation { + language = englishLanguage + text = "Z translation" + state = TranslationState.REVIEWED + this@TranslationCommentsTestData.translation = this + }.build { + firstComment = + addComment { + text = "First comment" + }.self + secondComment = + addComment { + text = "Second comment" + }.self + } - addTranslation { - language = czechLanguage - text = "Z překlad" - state = TranslationState.REVIEWED - this@TranslationCommentsTestData.translation = this - }.build { - firstComment = addComment { - text = "First comment" - }.self - secondComment = addComment { - text = "Second comment" - }.self - } - } + addTranslation { + language = czechLanguage + text = "Z překlad" + state = TranslationState.REVIEWED + this@TranslationCommentsTestData.translation = this + }.build { + firstComment = + addComment { + text = "First comment" + }.self + secondComment = + addComment { + text = "Second comment" + }.self + } + } - addKey { - name = "B key" - this@TranslationCommentsTestData.bKey = this - } - projectBuilder = this - }.self - } + addKey { + name = "B key" + this@TranslationCommentsTestData.bKey = this + } + projectBuilder = this + }.self + } fun addE2eTestData() { this.root.apply { - val jindra = addUserAccount { - - username = "jindra" - } - val vojta = addUserAccount { - - username = "vojta" - } + val jindra = + addUserAccount { + username = "jindra" + } + val vojta = + addUserAccount { + username = "vojta" + } projectBuilder.apply { addPermission { project = projectBuilder.self @@ -122,7 +132,6 @@ class TranslationCommentsTestData { translateLanguages = mutableSetOf(englishLanguage) } addPermission { - project = projectBuilder.self user = vojta.self type = ProjectPermissionType.VIEW @@ -135,13 +144,15 @@ class TranslationCommentsTestData { text = "Bla translation" state = TranslationState.REVIEWED }.build { - firstComment = addComment { - text = "First comment" - author = jindra.self - }.self - secondComment = addComment { - text = "Second comment" - }.self + firstComment = + addComment { + text = "First comment" + author = jindra.self + }.self + secondComment = + addComment { + text = "Second comment" + }.self }.self }.self diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/TranslationNsAndTagsData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/TranslationNsAndTagsData.kt index 4c47d0772b..2a1e92c74c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/TranslationNsAndTagsData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/TranslationNsAndTagsData.kt @@ -17,64 +17,68 @@ class TranslationNsAndTagsData { lateinit var translation: Translation lateinit var userAccountBuilder: UserAccountBuilder - val root: TestDataBuilder = TestDataBuilder().apply { - val userAccountBuilder = addUserAccount { - username = "olin" - user = this - } + val root: TestDataBuilder = + TestDataBuilder().apply { + val userAccountBuilder = + addUserAccount { + username = "olin" + user = this + } - addProject { - name = "Test project" - organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self - }.build { + addProject { + name = "Test project" + organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self + }.build { - val newProject = this.self - englishLanguage = addLanguage { - name = "English" - tag = "en" - originalName = "English" - }.self + val newProject = this.self + englishLanguage = + addLanguage { + name = "English" + tag = "en" + originalName = "English" + }.self - czechLanguage = addLanguage { - name = "Czech" - tag = "cs" - originalName = "Čeština" - }.self + czechLanguage = + addLanguage { + name = "Czech" + tag = "cs" + originalName = "Čeština" + }.self - self.baseLanguage = englishLanguage + self.baseLanguage = englishLanguage - for (i in 1..20) { - val paddedNum = i.toString().padStart(2, '0') - addKey { - name = "Key $paddedNum" - }.build { - addTranslation { - language = englishLanguage - text = "Translation $paddedNum" - state = TranslationState.REVIEWED - } + for (i in 1..20) { + val paddedNum = i.toString().padStart(2, '0') + addKey { + name = "Key $paddedNum" + }.build { + addTranslation { + language = englishLanguage + text = "Translation $paddedNum" + state = TranslationState.REVIEWED + } - addTranslation { - language = czechLanguage - text = "Překlad $paddedNum" - state = TranslationState.REVIEWED - } + addTranslation { + language = czechLanguage + text = "Překlad $paddedNum" + state = TranslationState.REVIEWED + } - setNamespace("Namespace $paddedNum") - addMeta { - self { - tags.add( - Tag().apply { - project = newProject - name = "Tag $paddedNum" - } - ) + setNamespace("Namespace $paddedNum") + addMeta { + self { + tags.add( + Tag().apply { + project = newProject + name = "Tag $paddedNum" + }, + ) + } } } } - } - projectBuilder = this - }.self - } + projectBuilder = this + }.self + } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/TranslationSingleTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/TranslationSingleTestData.kt index a79cad5870..ddd5a1f9ee 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/TranslationSingleTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/TranslationSingleTestData.kt @@ -22,85 +22,96 @@ class TranslationSingleTestData { lateinit var projectBuilder: ProjectBuilder lateinit var translation: Translation - val root: TestDataBuilder = TestDataBuilder().apply { - val userAccountBuilder = addUserAccount { - username = "franta" - user = this - } + val root: TestDataBuilder = + TestDataBuilder().apply { + val userAccountBuilder = + addUserAccount { + username = "franta" + user = this + } + + pepa = + addUserAccount { + username = "pepa" + }.self - pepa = addUserAccount { - username = "pepa" - }.self + val jindra = + addUserAccount { - val jindra = addUserAccount { + username = "jindra" + } - username = "jindra" - } + val vojta = + addUserAccount { + username = "vojta" + } - val vojta = addUserAccount { - username = "vojta" - } - - project = addProject { - name = "Franta's project" - organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self - }.build { - addPermission { - user = this@TranslationSingleTestData.user - type = ProjectPermissionType.MANAGE - } - - addPermission { - user = this@TranslationSingleTestData.pepa - type = ProjectPermissionType.EDIT - } - - addPermission { - user = jindra.self - type = ProjectPermissionType.TRANSLATE - } - - addPermission { - user = vojta.self - type = ProjectPermissionType.VIEW - } - - englishLanguage = addLanguage { - name = "English" - tag = "en" - originalName = "English" - }.self - - addLanguage { - name = "Czech" - tag = "cs" - originalName = "Čeština" - } - - val keyBuilder = addKey { - name = "A key" - aKey = this - } - - keyBuilder.apply { - translation = addTranslation { - key = aKey - language = englishLanguage - text = "Z translation" - state = TranslationState.REVIEWED + project = + addProject { + name = "Franta's project" + organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self }.build { - firstComment = addComment { - text = "First comment" - author = this@TranslationSingleTestData.user - }.self - secondComment = addComment { - text = "Second comment" - author = this@TranslationSingleTestData.pepa - }.self + addPermission { + user = this@TranslationSingleTestData.user + type = ProjectPermissionType.MANAGE + } + + addPermission { + user = this@TranslationSingleTestData.pepa + type = ProjectPermissionType.EDIT + } + + addPermission { + user = jindra.self + type = ProjectPermissionType.TRANSLATE + } + + addPermission { + user = vojta.self + type = ProjectPermissionType.VIEW + } + + englishLanguage = + addLanguage { + name = "English" + tag = "en" + originalName = "English" + }.self + + addLanguage { + name = "Czech" + tag = "cs" + originalName = "Čeština" + } + + val keyBuilder = + addKey { + name = "A key" + aKey = this + } + + keyBuilder.apply { + translation = + addTranslation { + key = aKey + language = englishLanguage + text = "Z translation" + state = TranslationState.REVIEWED + }.build { + firstComment = + addComment { + text = "First comment" + author = this@TranslationSingleTestData.user + }.self + secondComment = + addComment { + text = "Second comment" + author = this@TranslationSingleTestData.pepa + }.self + }.self + } + + projectBuilder = this }.self - } - - projectBuilder = this - }.self - } + } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/TranslationsTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/TranslationsTestData.kt index 7dc6c448f7..9ef7dbd610 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/TranslationsTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/TranslationsTestData.kt @@ -26,69 +26,74 @@ class TranslationsTestData { lateinit var aKeyGermanTranslation: Translation lateinit var keysOnlyUser: UserAccount - val root: TestDataBuilder = TestDataBuilder().apply { - val userAccountBuilder = addUserAccount { - username = "franta" - user = this - } - addProject { - name = "Franta's project" - organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self - project = this - }.build project@{ - addPermission { - user = this@TranslationsTestData.user - type = ProjectPermissionType.MANAGE - } - englishLanguage = addLanguage { - name = "English" - tag = "en" - originalName = "English" - this@project.self.baseLanguage = this - }.self - germanLanguage = addLanguage { - name = "German" - tag = "de" - originalName = "Deutsch" - }.self + val root: TestDataBuilder = + TestDataBuilder().apply { + val userAccountBuilder = + addUserAccount { + username = "franta" + user = this + } + addProject { + name = "Franta's project" + organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self + project = this + }.build project@{ + addPermission { + user = this@TranslationsTestData.user + type = ProjectPermissionType.MANAGE + } + englishLanguage = + addLanguage { + name = "English" + tag = "en" + originalName = "English" + this@project.self.baseLanguage = this + }.self + germanLanguage = + addLanguage { + name = "German" + tag = "de" + originalName = "Deutsch" + }.self - addKey { - name = "A key" - aKey = this - }.build { - addTranslation { - language = germanLanguage - text = "Z translation" - state = TranslationState.REVIEWED - auto = true - outdated = true - mtProvider = MtServiceType.GOOGLE - aKeyGermanTranslation = this + addKey { + name = "A key" + aKey = this }.build { - addComment { - author = user - text = "Comment" + addTranslation { + language = germanLanguage + text = "Z translation" + state = TranslationState.REVIEWED + auto = true + outdated = true + mtProvider = MtServiceType.GOOGLE + aKeyGermanTranslation = this + }.build { + addComment { + author = user + text = "Comment" + } } + addTag("Cool tag") } - addTag("Cool tag") - } - val zKeyBuilder = addKey { - name = "Z key" - } - zKeyBuilder.build { - addTranslation { - key = zKeyBuilder.self - language = englishLanguage - text = "A translation" - auto = true - }.build { - addTag("Lame tag") + val zKeyBuilder = + addKey { + name = "Z key" + } + zKeyBuilder.build { + addTranslation { + key = zKeyBuilder.self + language = englishLanguage + text = "A translation" + auto = true + }.build { + addTag("Lame tag") + } } - } - projectBuilder = this - }.self - } + projectBuilder = this + }.self + } fun addKeysViewOnlyUser() { root.apply { diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/UserDeletionTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/UserDeletionTestData.kt index ddbf0ac5ed..9eb32efc87 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/UserDeletionTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/UserDeletionTestData.kt @@ -22,58 +22,59 @@ class UserDeletionTestData { lateinit var frantasRole: OrganizationRole lateinit var pepaFrantaOrganization: Organization - val root = TestDataBuilder { - addUserAccount { - name = "Franta" - username = "franta" - franta = this - }.build { - frantasOrganization = this.defaultOrganizationBuilder.self - addPat { - frantasPat = this - description = "My PAT" + val root = + TestDataBuilder { + addUserAccount { + name = "Franta" + username = "franta" + franta = this + }.build { + frantasOrganization = this.defaultOrganizationBuilder.self + addPat { + frantasPat = this + description = "My PAT" + } + setUserPreferences { + preferredOrganization = this@build.defaultOrganizationBuilder.self + } } - setUserPreferences { - preferredOrganization = this@build.defaultOrganizationBuilder.self + addUserAccountWithoutOrganization { + name = "Pepa" + username = "pepa" + pepa = this } - } - addUserAccountWithoutOrganization { - name = "Pepa" - username = "pepa" - pepa = this - } - addUserAccount { - name = "Olga" - username = "olga" - olga = this - }.build { - this.defaultOrganizationBuilder.apply { - addProject { - organizationOwner = this@apply.self - name = "Olga's project" - }.build { - val en = addEnglish() - val helloKey = addKey { name = "hello" } - addTranslation { - language = en.self - text = "Hello" - key = helloKey.self + addUserAccount { + name = "Olga" + username = "olga" + olga = this + }.build { + this.defaultOrganizationBuilder.apply { + addProject { + organizationOwner = this@apply.self + name = "Olga's project" }.build { - addComment { - author = franta - frantasComment = this - text = "Comment!" + val en = addEnglish() + val helloKey = addKey { name = "hello" } + addTranslation { + language = en.self + text = "Hello" + key = helloKey.self + }.build { + addComment { + author = franta + frantasComment = this + text = "Comment!" + } + } + addPermission { + user = franta + frantasPermissionInOlgasProject = this } - } - addPermission { - user = franta - frantasPermissionInOlgasProject = this } } } + addPepaAndFrantaOrganization() } - addPepaAndFrantaOrganization() - } private fun TestDataBuilder.addPepaAndFrantaOrganization() { addOrganization { diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/WebhooksTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/WebhooksTestData.kt index fb5537e3fa..70d1f95637 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/WebhooksTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/WebhooksTestData.kt @@ -6,25 +6,26 @@ import io.tolgee.model.automations.AutomationTrigger import io.tolgee.model.automations.AutomationTriggerType class WebhooksTestData : BaseTestData() { + val webhookConfig = + projectBuilder.addWebhookConfig { + url = "https://this-will-hopefully-never-exist.com/wh" + webhookSecret = "whsec_hello" + } - val webhookConfig = projectBuilder.addWebhookConfig { - url = "https://this-will-hopefully-never-exist.com/wh" - webhookSecret = "whsec_hello" - } - - val automation = projectBuilder.addAutomation { - this.triggers.add( - AutomationTrigger(this) - .also { - it.type = AutomationTriggerType.ACTIVITY - it.activityType = null - } - ) - this.actions.add( - AutomationAction(this).also { - it.type = AutomationActionType.WEBHOOK - it.webhookConfig = webhookConfig.self - } - ) - } + val automation = + projectBuilder.addAutomation { + this.triggers.add( + AutomationTrigger(this) + .also { + it.type = AutomationTriggerType.ACTIVITY + it.activityType = null + }, + ) + this.actions.add( + AutomationAction(this).also { + it.type = AutomationActionType.WEBHOOK + it.webhookConfig = webhookConfig.self + }, + ) + } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/dataImport/ImportCleanTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/dataImport/ImportCleanTestData.kt index d3a7f2bdb3..2dbb0520c2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/dataImport/ImportCleanTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/dataImport/ImportCleanTestData.kt @@ -10,39 +10,45 @@ class ImportCleanTestData { var userAccount: UserAccount val projectBuilder get() = root.data.projects[0] - val root: TestDataBuilder = TestDataBuilder().apply { - userAccount = addUserAccount { - username = "franta" - name = "Frantisek Dobrota" - }.self - project = addProject { name = "test" }.build project@{ - addPermission { - project = this@project.self - user = this@ImportCleanTestData.userAccount - type = ProjectPermissionType.MANAGE - } + val root: TestDataBuilder = + TestDataBuilder().apply { + userAccount = + addUserAccount { + username = "franta" + name = "Frantisek Dobrota" + }.self + project = + addProject { name = "test" }.build project@{ + addPermission { + project = this@project.self + user = this@ImportCleanTestData.userAccount + type = ProjectPermissionType.MANAGE + } - val key = addKey { - name = "key1" - }.self - val english = addLanguage { - name = "English" - tag = "en" - }.self - val french = addLanguage { - name = "French" - tag = "fr" - }.self - addTranslation { - this.language = english - this.key = key - this.text = "test" - }.self - addTranslation { - this.language = french - this.key = key - this.text = "test" - }.self - }.self - } + val key = + addKey { + name = "key1" + }.self + val english = + addLanguage { + name = "English" + tag = "en" + }.self + val french = + addLanguage { + name = "French" + tag = "fr" + }.self + addTranslation { + this.language = english + this.key = key + this.text = "test" + }.self + addTranslation { + this.language = french + this.key = key + this.text = "test" + }.self + }.self + } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/dataImport/ImportNamespacesTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/dataImport/ImportNamespacesTestData.kt index d975076872..941caf4038 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/dataImport/ImportNamespacesTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/dataImport/ImportNamespacesTestData.kt @@ -28,135 +28,145 @@ class ImportNamespacesTestData { lateinit var homepageNsFile2: ImportFile lateinit var existingTranslation: Translation - val root: TestDataBuilder = TestDataBuilder().apply { - createProject() - projectBuilder.build { - addImport { - author = userAccount - import = this - }.build { - addImportFile { - name = "multilang.json" - defaultNsFile = this + val root: TestDataBuilder = + TestDataBuilder().apply { + createProject() + projectBuilder.build { + addImport { + author = userAccount + import = this }.build { - importEnglish = addImportLanguage { - name = "en" - existingLanguage = english - }.self - importGerman = addImportLanguage { - name = "de" - existingLanguage = german - }.self - addImportKey { - name = "what a key" - }.build key@{ - addMeta { - comments = mutableListOf( - KeyComment(this).apply { - text = "hello1" - author = userAccount - } - ) - } - addImportTranslation { - text = "hello" - language = importGerman - key = this@key.self - conflict = existingTranslation - override = true - resolve() + addImportFile { + name = "multilang.json" + defaultNsFile = this + }.build { + importEnglish = + addImportLanguage { + name = "en" + existingLanguage = english + }.self + importGerman = + addImportLanguage { + name = "de" + existingLanguage = german + }.self + addImportKey { + name = "what a key" + }.build key@{ + addMeta { + comments = + mutableListOf( + KeyComment(this).apply { + text = "hello1" + author = userAccount + }, + ) + } + addImportTranslation { + text = "hello" + language = importGerman + key = this@key.self + conflict = existingTranslation + override = true + resolve() + } } } - } - addImportFile { - name = "multilang2.json" - defaultNsFile2 = this - }.build { - addImportKey { - name = "what a key" - }.build key@{ - addMeta { - comments = mutableListOf( - KeyComment(this).apply { - text = "hello2" - author = userAccount - } - ) + addImportFile { + name = "multilang2.json" + defaultNsFile2 = this + }.build { + addImportKey { + name = "what a key" + }.build key@{ + addMeta { + comments = + mutableListOf( + KeyComment(this).apply { + text = "hello2" + author = userAccount + }, + ) + } } } - } - addImportFile { - name = "another.json" - namespace = "homepage" - homepageNsFile2 = this - }.build { - homepageImportEnglish = addImportLanguage { - name = "en" - existingLanguage = english - }.self - homepageImportGerman = addImportLanguage { - name = "de" - existingLanguage = german - }.self - addImportKey { - name = "what a key" - }.build key@{ - addMeta { - comments = mutableListOf( - KeyComment(this).apply { - text = "hello2" - author = userAccount - } - ) - } - addImportTranslation { - text = "hello" - language = homepageImportGerman - key = this@key.self + addImportFile { + name = "another.json" + namespace = "homepage" + homepageNsFile2 = this + }.build { + homepageImportEnglish = + addImportLanguage { + name = "en" + existingLanguage = english + }.self + homepageImportGerman = + addImportLanguage { + name = "de" + existingLanguage = german + }.self + addImportKey { + name = "what a key" + }.build key@{ + addMeta { + comments = + mutableListOf( + KeyComment(this).apply { + text = "hello2" + author = userAccount + }, + ) + } + addImportTranslation { + text = "hello" + language = homepageImportGerman + key = this@key.self + } } } } - } - }.self - } + }.self + } private fun TestDataBuilder.createProject() { - userAccount = addUserAccount { - username = "franta" - name = "Frantisek Dobrota" - }.self - projectBuilder = addProject { - name = "test" - project = this - }.build project@{ - addPermission { - project = this@project.self - user = this@ImportNamespacesTestData.userAccount - type = ProjectPermissionType.MANAGE - } - english = addEnglish().self - german = addGerman().self - addKey { - name = "what a key" - }.setNamespace("existing-namespace") - addKey { - name = "what a key" - }.setNamespace("existing-namespace2") - addKey { - name = "what a key" - }.build { - addTranslation { - existingTranslation = this - language = german - this.key = this@build.self - text = "some text!" + userAccount = + addUserAccount { + username = "franta" + name = "Frantisek Dobrota" + }.self + projectBuilder = + addProject { + name = "test" + project = this + }.build project@{ + addPermission { + project = this@project.self + user = this@ImportNamespacesTestData.userAccount + type = ProjectPermissionType.MANAGE + } + english = addEnglish().self + german = addGerman().self + addKey { + name = "what a key" + }.setNamespace("existing-namespace") + addKey { + name = "what a key" + }.setNamespace("existing-namespace2") + addKey { + name = "what a key" + }.build { + addTranslation { + existingTranslation = this + language = german + this.key = this@build.self + text = "some text!" + } + } + addKey { + name = "what a nice key" } } - addKey { - name = "what a nice key" - } - } } } diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/dataImport/ImportTestData.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/dataImport/ImportTestData.kt index d1fc5503a0..99557b8052 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/dataImport/ImportTestData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/data/dataImport/ImportTestData.kt @@ -30,156 +30,171 @@ class ImportTestData { var userAccount: UserAccount val projectBuilder get() = root.data.projects[0] - val root: TestDataBuilder = TestDataBuilder().apply { - userAccount = addUserAccount { - username = "franta" - name = "Frantisek Dobrota" - }.self - project = addProject { name = "test" }.build project@{ - addPermission { - project = this@project.self - user = this@ImportTestData.userAccount - type = ProjectPermissionType.MANAGE - } - - val key = addKey { - name = "what a key" - }.self - addKey { - name = "what a nice key" - }.self - addKey { - name = "what a beautiful key" - }.self - addKey { - name = "another nice key" - }.self - addKey { - name = "extraordinary key" - }.self - addKey { - name = "this is another key" - }.self - english = addLanguage { - name = "English" - tag = "en" - }.self - german = addLanguage { - name = "German" - tag = "de" - }.self - czech = addLanguage { - name = "Czech" - tag = "cs" - }.self - french = addLanguage { - name = "French" - tag = "fr" - }.self - conflict = addTranslation { - this.language = english - this.key = key - }.self - addTranslation { - this.language = english - this.key = this@project.data.keys[1].self - }.self - addTranslation { - this.language = english - this.key = this@project.data.keys[2].self - }.self - addTranslation { - this.language = english - this.key = this@project.data.keys[3].self - }.self - addTranslation { - this.auto = true - this.mtProvider = MtServiceType.GOOGLE - this.language = french - this.key = this@project.data.keys[0].self - this.text = "What a french text" - }.self - addTranslation { - this.auto = true - this.mtProvider = MtServiceType.GOOGLE - this.language = french - this.key = this@project.data.keys[1].self - this.text = "What a french text 2" - }.self - importBuilder = addImport { - author = userAccount - }.build { - addImportFile { - name = "multilang.json" - }.build { - importEnglish = addImportLanguage { - name = "en" - existingLanguage = english - }.self - importFrench = addImportLanguage { - name = "fr" - }.self - addImportLanguage { - name = "de" - existingLanguage = german + val root: TestDataBuilder = + TestDataBuilder().apply { + userAccount = + addUserAccount { + username = "franta" + name = "Frantisek Dobrota" + }.self + project = + addProject { name = "test" }.build project@{ + addPermission { + project = this@project.self + user = this@ImportTestData.userAccount + type = ProjectPermissionType.MANAGE } - val addedKey = addImportKey { - name = "what a key" - } - addImportKey { + val key = + addKey { + name = "what a key" + }.self + addKey { name = "what a nice key" - } - addImportKey { + }.self + addKey { name = "what a beautiful key" - } - addImportKey { - name = (1..2000).joinToString("") { "a" } - newLongKey = this - } - addImportKey { + }.self + addKey { + name = "another nice key" + }.self + addKey { name = "extraordinary key" - } - addImportKey { + }.self + addKey { name = "this is another key" - } - - translationWithConflict = addImportTranslation { - this.language = importEnglish - this.key = addedKey.self - this.conflict = this@ImportTestData.conflict - this.text = "Overridden" }.self - addImportTranslation { - this.language = importEnglish - this.key = data.importKeys[1].self - this.conflict = projectBuilder.data.translations[1].self - this.text = "Imported text" - } - addImportTranslation { - this.language = importEnglish - this.key = data.importKeys[2].self - this.conflict = projectBuilder.data.translations[2].self - } - addImportTranslation { - this.language = importEnglish - this.key = data.importKeys[4].self - } - addImportTranslation { - this.language = importEnglish - this.key = data.importKeys[5].self - } - } - } - import = importBuilder.self - }.self - } + english = + addLanguage { + name = "English" + tag = "en" + }.self + german = + addLanguage { + name = "German" + tag = "de" + }.self + czech = + addLanguage { + name = "Czech" + tag = "cs" + }.self + french = + addLanguage { + name = "French" + tag = "fr" + }.self + conflict = + addTranslation { + this.language = english + this.key = key + }.self + addTranslation { + this.language = english + this.key = this@project.data.keys[1].self + }.self + addTranslation { + this.language = english + this.key = this@project.data.keys[2].self + }.self + addTranslation { + this.language = english + this.key = this@project.data.keys[3].self + }.self + addTranslation { + this.auto = true + this.mtProvider = MtServiceType.GOOGLE + this.language = french + this.key = this@project.data.keys[0].self + this.text = "What a french text" + }.self + addTranslation { + this.auto = true + this.mtProvider = MtServiceType.GOOGLE + this.language = french + this.key = this@project.data.keys[1].self + this.text = "What a french text 2" + }.self + importBuilder = + addImport { + author = userAccount + }.build { + addImportFile { + name = "multilang.json" + }.build { + importEnglish = + addImportLanguage { + name = "en" + existingLanguage = english + }.self + importFrench = + addImportLanguage { + name = "fr" + }.self + addImportLanguage { + name = "de" + existingLanguage = german + } - fun useTranslateOnlyUser(): UserAccount { - val user = this.root.addUserAccount { - name = "En only user" - username = "en_only_user" + val addedKey = + addImportKey { + name = "what a key" + } + addImportKey { + name = "what a nice key" + } + addImportKey { + name = "what a beautiful key" + } + addImportKey { + name = (1..2000).joinToString("") { "a" } + newLongKey = this + } + addImportKey { + name = "extraordinary key" + } + addImportKey { + name = "this is another key" + } + + translationWithConflict = + addImportTranslation { + this.language = importEnglish + this.key = addedKey.self + this.conflict = this@ImportTestData.conflict + this.text = "Overridden" + }.self + addImportTranslation { + this.language = importEnglish + this.key = data.importKeys[1].self + this.conflict = projectBuilder.data.translations[1].self + this.text = "Imported text" + } + addImportTranslation { + this.language = importEnglish + this.key = data.importKeys[2].self + this.conflict = projectBuilder.data.translations[2].self + } + addImportTranslation { + this.language = importEnglish + this.key = data.importKeys[4].self + } + addImportTranslation { + this.language = importEnglish + this.key = data.importKeys[5].self + } + } + } + import = importBuilder.self + }.self } + + fun useTranslateOnlyUser(): UserAccount { + val user = + this.root.addUserAccount { + name = "En only user" + username = "en_only_user" + } this.import.author = user.self this.projectBuilder.addPermission { this.user = user.self @@ -192,10 +207,11 @@ class ImportTestData { } fun useViewEnOnlyUser(): UserAccount { - val user = this.root.addUserAccount { - name = "En only user" - username = "en_only_user" - } + val user = + this.root.addUserAccount { + name = "En only user" + username = "en_only_user" + } this.import.author = user.self this.projectBuilder.addPermission { this.user = user.self @@ -283,10 +299,11 @@ class ImportTestData { import.addImportFile { name = "another.json" }.build { - val fr = addImportLanguage { - name = "fr" - existingLanguage = french - }.self + val fr = + addImportLanguage { + name = "fr" + existingLanguage = french + }.self (1..300).forEach { num -> projectBuilder.addKey { name = "this_is_key_$num" @@ -390,6 +407,6 @@ class ImportTestData { } data class AddFilesWithNamespacesResult( - val importFrenchInNs: ImportLanguage + val importFrenchInNs: ImportLanguage, ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/dialects/postgres/CustomPostgreSQLDialect.kt b/backend/data/src/main/kotlin/io/tolgee/dialects/postgres/CustomPostgreSQLDialect.kt index fc8f04b169..8d544683d2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dialects/postgres/CustomPostgreSQLDialect.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dialects/postgres/CustomPostgreSQLDialect.kt @@ -7,13 +7,12 @@ import org.hibernate.type.StandardBasicTypes @Suppress("unused") class CustomPostgreSQLDialect : PostgreSQLDialect(DatabaseVersion.make(13)) { - override fun contributeFunctions(functionContributions: FunctionContributions) { super.contributeFunctions(functionContributions) functionContributions.functionRegistry.registerPattern( "similarity", "similarity(?1, ?2)", - functionContributions.typeConfiguration.basicTypeRegistry.resolve(StandardBasicTypes.FLOAT) + functionContributions.typeConfiguration.basicTypeRegistry.resolve(StandardBasicTypes.FLOAT), ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/Avatar.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/Avatar.kt index 884094f7f5..57f6cfd6c0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/Avatar.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/Avatar.kt @@ -2,5 +2,5 @@ package io.tolgee.dtos data class Avatar( val large: String, - val thumbnail: String + val thumbnail: String, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/ComputedPermissionDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/ComputedPermissionDto.kt index a2c9e88144..8c75654358 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/ComputedPermissionDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/ComputedPermissionDto.kt @@ -9,23 +9,25 @@ import io.tolgee.model.enums.Scope class ComputedPermissionDto( permission: IPermission, - val origin: ComputedPermissionOrigin = ComputedPermissionOrigin.NONE + val origin: ComputedPermissionOrigin = ComputedPermissionOrigin.NONE, ) : IPermission by permission { - val expandedScopes: Array by lazy { Scope.expand(this.scopes) } fun checkViewPermitted(vararg languageIds: Long) = checkLanguagePermitted(languageIds.toList(), viewLanguageIds) - fun checkTranslatePermitted(vararg languageIds: Long) = checkLanguagePermitted( - languageIds.toList(), - translateLanguageIds - ) - fun checkStateChangePermitted(vararg languageIds: Long) = checkLanguagePermitted( - languageIds.toList(), - stateChangeLanguageIds - ) + fun checkTranslatePermitted(vararg languageIds: Long) = + checkLanguagePermitted( + languageIds.toList(), + translateLanguageIds, + ) + + fun checkStateChangePermitted(vararg languageIds: Long) = + checkLanguagePermitted( + languageIds.toList(), + stateChangeLanguageIds, + ) private fun isAllLanguagesPermitted(languageIds: Collection?): Boolean { if (scopes.isEmpty()) { @@ -43,7 +45,10 @@ class ComputedPermissionDto( return false } - private fun checkLanguagePermitted(languageIds: Collection, permittedLanguageIds: Collection?) { + private fun checkLanguagePermitted( + languageIds: Collection, + permittedLanguageIds: Collection?, + ) { if (this.isAllLanguagesPermitted(permittedLanguageIds)) { return } @@ -54,9 +59,7 @@ class ComputedPermissionDto( val isAllPermitted = this.expandedScopes.toSet().containsAll(Scope.values().toList()) - fun getAdminPermissions( - userRole: UserAccount.Role?, - ): ComputedPermissionDto { + fun getAdminPermissions(userRole: UserAccount.Role?): ComputedPermissionDto { if (userRole == UserAccount.Role.ADMIN && !this.isAllPermitted) { return SERVER_ADMIN } @@ -65,14 +68,19 @@ class ComputedPermissionDto( constructor(permission: IPermission) : this( permission, - origin = if (permission.organizationId != null) - ComputedPermissionOrigin.ORGANIZATION_BASE - else - ComputedPermissionOrigin.DIRECT + origin = + if (permission.organizationId != null) { + ComputedPermissionOrigin.ORGANIZATION_BASE + } else { + ComputedPermissionOrigin.DIRECT + }, ) companion object { - private fun getEmptyPermission(scopes: Array, type: ProjectPermissionType): IPermission { + private fun getEmptyPermission( + scopes: Array, + type: ProjectPermissionType, + ): IPermission { return object : IPermission { override val scopes: Array get() = scopes @@ -96,20 +104,22 @@ class ComputedPermissionDto( val NONE get() = ComputedPermissionDto(getEmptyPermission(scopes = arrayOf(), ProjectPermissionType.NONE)) val ORGANIZATION_OWNER - get() = ComputedPermissionDto( - getEmptyPermission( - scopes = arrayOf(Scope.ADMIN), - type = ProjectPermissionType.MANAGE - ), - origin = ComputedPermissionOrigin.ORGANIZATION_OWNER - ) + get() = + ComputedPermissionDto( + getEmptyPermission( + scopes = arrayOf(Scope.ADMIN), + type = ProjectPermissionType.MANAGE, + ), + origin = ComputedPermissionOrigin.ORGANIZATION_OWNER, + ) val SERVER_ADMIN - get() = ComputedPermissionDto( - getEmptyPermission( - scopes = arrayOf(Scope.ADMIN), - type = ProjectPermissionType.MANAGE - ), - origin = ComputedPermissionOrigin.SERVER_ADMIN - ) + get() = + ComputedPermissionDto( + getEmptyPermission( + scopes = arrayOf(Scope.ADMIN), + type = ProjectPermissionType.MANAGE, + ), + origin = ComputedPermissionOrigin.SERVER_ADMIN, + ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/CreateScreenshotResult.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/CreateScreenshotResult.kt index f900ee4342..50d3c10b33 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/CreateScreenshotResult.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/CreateScreenshotResult.kt @@ -6,5 +6,5 @@ import java.awt.Dimension data class CreateScreenshotResult( val screenshot: Screenshot, val originalDimension: Dimension, - val targetDimension: Dimension + val targetDimension: Dimension, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/IExportParams.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/IExportParams.kt index 40a1e6b1e9..b35b26256e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/IExportParams.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/IExportParams.kt @@ -11,7 +11,7 @@ interface IExportParams { description = """Languages to be contained in export. If null, all languages are exported""", - example = "en" + example = "en", ) var languages: Set? @@ -56,7 +56,7 @@ When null, resulting file won't be structured. var filterState: List? @get:Schema( - description = """Select one ore multiple namespaces to export""" + description = """Select one ore multiple namespaces to export""", ) var filterNamespace: List? diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/MtCreditBalanceDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/MtCreditBalanceDto.kt index 66ea9ea52c..974deff523 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/MtCreditBalanceDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/MtCreditBalanceDto.kt @@ -7,5 +7,5 @@ data class MtCreditBalanceDto( val bucketSize: Long, val extraCreditBalance: Long, val refilledAt: Date, - val nextRefillAt: Date + val nextRefillAt: Date, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/PathDTO.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/PathDTO.kt index 7468751a09..65ef25b07d 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/PathDTO.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/PathDTO.kt @@ -10,14 +10,15 @@ class PathDTO private constructor() { val name: String get() = fullPath.last() val fullPathString: String - get() = fullPath.stream().map { i: String -> - i.replace( - ("\\" + DELIMITER).toRegex(), - "\\\\" + DELIMITER + get() = + fullPath.stream().map { i: String -> + i.replace( + ("\\" + DELIMITER).toRegex(), + "\\\\" + DELIMITER, + ) + }.collect( + Collectors.joining("."), ) - }.collect( - Collectors.joining(".") - ) val path: List get() { val path = LinkedList(fullPath) @@ -43,6 +44,7 @@ class PathDTO private constructor() { companion object { const val DELIMITER = '.' + fun fromFullPath(fullPath: String?): PathDTO { val pathDTO = PathDTO() pathDTO.add(splitOnNonEscapedDelimiter(fullPath!!, DELIMITER)) @@ -55,7 +57,10 @@ class PathDTO private constructor() { return pathDTO } - fun fromPathAndName(path: String, name: String): PathDTO { + fun fromPathAndName( + path: String, + name: String, + ): PathDTO { val pathDTO = PathDTO() var items = splitOnNonEscapedDelimiter(path, DELIMITER) if (path.isEmpty()) { @@ -66,7 +71,10 @@ class PathDTO private constructor() { return pathDTO } - fun fromPathAndName(path: List, name: String): PathDTO { + fun fromPathAndName( + path: List, + name: String, + ): PathDTO { val pathDTO = PathDTO() pathDTO.add(path) pathDTO.add(name) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/ProjectPermissionData.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/ProjectPermissionData.kt index f0f4b1aa25..199e200d8e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/ProjectPermissionData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/ProjectPermissionData.kt @@ -7,5 +7,5 @@ data class ProjectPermissionData( val directPermissions: PermissionDto?, val organizationRole: OrganizationRoleType?, val organizationBasePermissions: PermissionDto?, - val computedPermissions: ComputedPermissionDto + val computedPermissions: ComputedPermissionDto, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/RelatedKeyDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/RelatedKeyDto.kt index a4b761e5a4..74093bbde7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/RelatedKeyDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/RelatedKeyDto.kt @@ -4,7 +4,6 @@ import jakarta.validation.constraints.NotEmpty data class RelatedKeyDto( var namespace: String? = null, - @field:NotEmpty - var keyName: String = "" + var keyName: String = "", ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/WithRelatedKeysInOrder.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/WithRelatedKeysInOrder.kt index 34fbd3d60e..ad906dd9a9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/WithRelatedKeysInOrder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/WithRelatedKeysInOrder.kt @@ -4,9 +4,10 @@ import io.swagger.v3.oas.annotations.media.Schema interface WithRelatedKeysInOrder { @get:Schema( - description = "Keys in the document used as a context for machine translation. " + - "Keys in the same order as they appear in the document. " + - "The order is important! We are using it for graph distance calculation. " + description = + "Keys in the document used as a context for machine translation. " + + "Keys in the same order as they appear in the document. " + + "The order is important! We are using it for graph distance calculation. ", ) var relatedKeysInOrder: MutableList? } diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/PermissionDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/PermissionDto.kt index 682b69c90a..d147914dad 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/PermissionDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/PermissionDto.kt @@ -15,7 +15,7 @@ data class PermissionDto( override val type: ProjectPermissionType?, override val granular: Boolean?, override val viewLanguageIds: Set?, - override val stateChangeLanguageIds: Set? + override val stateChangeLanguageIds: Set?, ) : Serializable, IPermission { override fun equals(other: Any?): Boolean { if (this === other) return true diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/ProjectDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/ProjectDto.kt index aca529d443..cef1b16fe5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/ProjectDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/ProjectDto.kt @@ -11,12 +11,13 @@ data class ProjectDto( val organizationOwnerId: Long, ) : Serializable { companion object { - fun fromEntity(entity: Project) = ProjectDto( - name = entity.name, - description = entity.description, - slug = entity.slug, - id = entity.id, - organizationOwnerId = entity.organizationOwner.id, - ) + fun fromEntity(entity: Project) = + ProjectDto( + name = entity.name, + description = entity.description, + slug = entity.slug, + id = entity.id, + organizationOwnerId = entity.organizationOwner.id, + ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/UserAccountDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/UserAccountDto.kt index 3b86d3c73e..bffc807234 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/UserAccountDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/UserAccountDto.kt @@ -15,16 +15,17 @@ data class UserAccountDto( val tokensValidNotBefore: Date?, ) : Serializable { companion object { - fun fromEntity(entity: UserAccount) = UserAccountDto( - name = entity.name, - username = entity.username, - role = entity.role, - id = entity.id, - needsSuperJwt = entity.needsSuperJwt, - avatarHash = entity.avatarHash, - deleted = entity.deletedAt != null, - tokensValidNotBefore = entity.tokensValidNotBefore, - ) + fun fromEntity(entity: UserAccount) = + UserAccountDto( + name = entity.name, + username = entity.username, + role = entity.role, + id = entity.id, + needsSuperJwt = entity.needsSuperJwt, + avatarHash = entity.avatarHash, + deleted = entity.deletedAt != null, + tokensValidNotBefore = entity.tokensValidNotBefore, + ) } override fun toString(): String { diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/automations/AutomationActionDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/automations/AutomationActionDto.kt index 84bcc6a55c..6fd3a035c8 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/automations/AutomationActionDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/automations/AutomationActionDto.kt @@ -4,5 +4,5 @@ import io.tolgee.model.automations.AutomationActionType class AutomationActionDto( var id: Long, - var type: AutomationActionType = AutomationActionType.CONTENT_DELIVERY_PUBLISH + var type: AutomationActionType = AutomationActionType.CONTENT_DELIVERY_PUBLISH, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/automations/AutomationDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/automations/AutomationDto.kt index 2af5c4e543..853c3d7b9e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/automations/AutomationDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/automations/AutomationDto.kt @@ -4,21 +4,21 @@ import io.tolgee.model.automations.Automation data class AutomationDto( val triggers: List, - val actions: List + val actions: List, ) { - companion object { fun fromEntity(entity: Automation): AutomationDto { return AutomationDto( - triggers = entity.triggers.map { - AutomationTriggerDto( - it.id, - it.type, - it.activityType, - it.debounceDurationInMs - ) - }, - actions = entity.actions.map { AutomationActionDto(it.id, it.type) } + triggers = + entity.triggers.map { + AutomationTriggerDto( + it.id, + it.type, + it.activityType, + it.debounceDurationInMs, + ) + }, + actions = entity.actions.map { AutomationActionDto(it.id, it.type) }, ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/automations/AutomationTriggerDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/automations/AutomationTriggerDto.kt index 4b8b004f8a..8e0e60700f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/automations/AutomationTriggerDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/cacheable/automations/AutomationTriggerDto.kt @@ -5,10 +5,7 @@ import io.tolgee.model.automations.AutomationTriggerType class AutomationTriggerDto( var id: Long, - var type: AutomationTriggerType, - var activityType: ActivityType? = null, - - var debounceDurationInMs: Long? = null + var debounceDurationInMs: Long? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/contentDelivery/ContentStorageRequest.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/contentDelivery/ContentStorageRequest.kt index 86f35e9f59..0c794cac18 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/contentDelivery/ContentStorageRequest.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/contentDelivery/ContentStorageRequest.kt @@ -13,5 +13,5 @@ data class ContentStorageRequest( @field:Valid val s3ContentStorageConfig: S3ContentStorageConfigDto?, @field:Size(max = 255) - val publicUrlPrefix: String? = null + val publicUrlPrefix: String? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/dataImport/ImportAddFilesParams.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/dataImport/ImportAddFilesParams.kt index 7278bc422e..d674e57ed8 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/dataImport/ImportAddFilesParams.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/dataImport/ImportAddFilesParams.kt @@ -4,8 +4,9 @@ import io.swagger.v3.oas.annotations.Parameter class ImportAddFilesParams( @field:Parameter( - description = "When importing structured JSONs, you can set " + - "the delimiter which will be used in names of improted keys.", + description = + "When importing structured JSONs, you can set " + + "the delimiter which will be used in names of improted keys.", ) var structureDelimiter: Char? = '.', ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/dataImport/SetFileNamespaceRequest.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/dataImport/SetFileNamespaceRequest.kt index 8eaf508f56..faf2710028 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/dataImport/SetFileNamespaceRequest.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/dataImport/SetFileNamespaceRequest.kt @@ -1,5 +1,5 @@ package io.tolgee.dtos.dataImport data class SetFileNamespaceRequest( - var namespace: String? = null + var namespace: String? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/misc/CreateOrganizationInvitationParams.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/misc/CreateOrganizationInvitationParams.kt index 57ca01434d..b1afb8985c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/misc/CreateOrganizationInvitationParams.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/misc/CreateOrganizationInvitationParams.kt @@ -7,5 +7,5 @@ data class CreateOrganizationInvitationParams( var organization: Organization, var type: OrganizationRoleType, override val email: String? = null, - override val name: String? = null + override val name: String? = null, ) : CreateInvitationParams diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/misc/CreateProjectInvitationParams.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/misc/CreateProjectInvitationParams.kt index 737a52b59d..67a4e18bf1 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/misc/CreateProjectInvitationParams.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/misc/CreateProjectInvitationParams.kt @@ -10,5 +10,5 @@ data class CreateProjectInvitationParams( var languagePermissions: LanguagePermissions = LanguagePermissions(null, null, null), var scopes: Set? = null, override val email: String? = null, - override val name: String? = null + override val name: String? = null, ) : CreateInvitationParams diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/misc/EmailAttachment.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/misc/EmailAttachment.kt index 1756e46754..eb944e9a2b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/misc/EmailAttachment.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/misc/EmailAttachment.kt @@ -4,5 +4,5 @@ import org.springframework.core.io.InputStreamSource class EmailAttachment( var name: String, - var inputStreamSource: InputStreamSource + var inputStreamSource: InputStreamSource, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/misc/EmailParams.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/misc/EmailParams.kt index dd091ce515..1260cab5df 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/misc/EmailParams.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/misc/EmailParams.kt @@ -4,5 +4,5 @@ class EmailParams( var to: String, var text: String, var subject: String, - var attachments: List = listOf() + var attachments: List = listOf(), ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/query_results/KeyIdFindResult.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/KeyIdFindResult.kt similarity index 71% rename from backend/data/src/main/kotlin/io/tolgee/dtos/query_results/KeyIdFindResult.kt rename to backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/KeyIdFindResult.kt index ebc1b9b7ac..84b2d2721b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/query_results/KeyIdFindResult.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/KeyIdFindResult.kt @@ -1,4 +1,4 @@ -package io.tolgee.dtos.query_results +package io.tolgee.dtos.queryResults data class KeyIdFindResult( val id: Long, diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/query_results/KeyWithTranslationsDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/KeyWithTranslationsDto.kt similarity index 95% rename from backend/data/src/main/kotlin/io/tolgee/dtos/query_results/KeyWithTranslationsDto.kt rename to backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/KeyWithTranslationsDto.kt index 8917f0dc8a..b4678e0a3b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/query_results/KeyWithTranslationsDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/KeyWithTranslationsDto.kt @@ -1,4 +1,4 @@ -package io.tolgee.dtos.query_results +package io.tolgee.dtos.queryResults import io.tolgee.dtos.PathDTO import java.util.* @@ -7,6 +7,7 @@ class KeyWithTranslationsDto(queryResult: Array) { val path: PathDTO val id: Long private val translations: MutableMap = LinkedHashMap() + fun getTranslations(): Map { return translations } diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/query_results/ProjectStatistics.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/ProjectStatistics.kt similarity index 85% rename from backend/data/src/main/kotlin/io/tolgee/dtos/query_results/ProjectStatistics.kt rename to backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/ProjectStatistics.kt index 20362555a3..b0f8c3315d 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/query_results/ProjectStatistics.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/ProjectStatistics.kt @@ -1,4 +1,4 @@ -package io.tolgee.dtos.query_results +package io.tolgee.dtos.queryResults import io.tolgee.model.enums.TranslationState import java.math.BigDecimal @@ -7,5 +7,5 @@ data class ProjectStatistics( val projectId: Long, val keyCount: Long, val languageCount: Long, - val translationStatePercentages: Map + val translationStatePercentages: Map, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/query_results/TranslationHistoryView.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/TranslationHistoryView.kt similarity index 91% rename from backend/data/src/main/kotlin/io/tolgee/dtos/query_results/TranslationHistoryView.kt rename to backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/TranslationHistoryView.kt index 4d1c4a9a65..f6722d2ab6 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/query_results/TranslationHistoryView.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/queryResults/TranslationHistoryView.kt @@ -1,4 +1,4 @@ -package io.tolgee.dtos.query_results +package io.tolgee.dtos.queryResults import io.tolgee.activity.data.PropertyModification import io.tolgee.activity.data.RevisionType diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/AutoTranslationSettingsDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/AutoTranslationSettingsDto.kt index 9d90b8b8bd..a9d24c37fe 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/AutoTranslationSettingsDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/AutoTranslationSettingsDto.kt @@ -4,24 +4,25 @@ import io.swagger.v3.oas.annotations.media.Schema data class AutoTranslationSettingsDto( val languageId: Long? = null, - @Schema( - description = "If true, new keys will be automatically translated via batch operation using translation memory" + - " when 100% match is found" + description = + "If true, new keys will be automatically translated via batch operation using translation memory" + + " when 100% match is found", ) var usingTranslationMemory: Boolean = false, @Schema( - description = "If true, new keys will be automatically translated via batch operation" + - "using primary machine translation service." + - "" + - "When \"usingTranslationMemory\" is enabled, it tries to translate it with translation memory first." + description = + "If true, new keys will be automatically translated via batch operation" + + "using primary machine translation service." + + "" + + "When \"usingTranslationMemory\" is enabled, it tries to translate it with translation memory first.", ) var usingMachineTranslation: Boolean = false, - @Schema( - description = "If true, import will trigger batch operation to translate the new new keys." + - "\n" + - "It includes also the data imported via CLI, Figma, or other integrations using batch key import." + description = + "If true, import will trigger batch operation to translate the new new keys." + + "\n" + + "It includes also the data imported via CLI, Figma, or other integrations using batch key import.", ) - var enableForImport: Boolean = false + var enableForImport: Boolean = false, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/BusinessEventReportRequest.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/BusinessEventReportRequest.kt index dc644039bb..8f564ad610 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/BusinessEventReportRequest.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/BusinessEventReportRequest.kt @@ -5,12 +5,8 @@ import jakarta.validation.constraints.NotBlank data class BusinessEventReportRequest( @field:NotBlank var eventName: String = "", - var anonymousUserId: String? = null, - var organizationId: Long? = null, - var projectId: Long? = null, - - val data: Map? = null + val data: Map? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/ContentDeliveryConfigRequest.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/ContentDeliveryConfigRequest.kt index 15753d972f..706133b022 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/ContentDeliveryConfigRequest.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/ContentDeliveryConfigRequest.kt @@ -11,13 +11,14 @@ class ContentDeliveryConfigRequest : IExportParams { var name: String = "" @Schema( - description = "Id of custom storage to use for content delivery. If null, default server storage is used. " + - "Tolgee Cloud provides default Content Storage." + description = + "Id of custom storage to use for content delivery. If null, default server storage is used. " + + "Tolgee Cloud provides default Content Storage.", ) var contentStorageId: Long? = null @Schema( - description = "If true, data are published to the content delivery automatically after each change." + description = "If true, data are published to the content delivery automatically after each change.", ) var autoPublish: Boolean = false @@ -33,10 +34,11 @@ class ContentDeliveryConfigRequest : IExportParams { override var filterKeyPrefix: String? = null - override var filterState: List? = listOf( - TranslationState.TRANSLATED, - TranslationState.REVIEWED, - ) + override var filterState: List? = + listOf( + TranslationState.TRANSLATED, + TranslationState.REVIEWED, + ) override var filterNamespace: List? = null } diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/GenerateSlugDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/GenerateSlugDto.kt index 56e12aeb74..40e28d7427 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/GenerateSlugDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/GenerateSlugDto.kt @@ -5,6 +5,5 @@ import jakarta.validation.constraints.NotBlank data class GenerateSlugDto( @field:NotBlank var name: String? = null, - val oldSlug: String? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/GetKeysRequestDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/GetKeysRequestDto.kt index cb30e8596f..193c8b5880 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/GetKeysRequestDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/GetKeysRequestDto.kt @@ -5,6 +5,7 @@ import jakarta.validation.constraints.NotEmpty class GetKeysRequestDto { var keys: List = listOf() + @get:NotEmpty @Schema(description = "Tags to return language translations in") var languageTags: List = listOf() diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/IdentifyRequest.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/IdentifyRequest.kt index 9977f6c7dd..5a9ef4267e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/IdentifyRequest.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/IdentifyRequest.kt @@ -4,5 +4,5 @@ import jakarta.validation.constraints.NotBlank data class IdentifyRequest( @NotBlank - var anonymousUserId: String = "" + var anonymousUserId: String = "", ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/ImageUploadInfoDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/ImageUploadInfoDto.kt index df4e2c0d3d..bda22380ac 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/ImageUploadInfoDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/ImageUploadInfoDto.kt @@ -1,5 +1,5 @@ package io.tolgee.dtos.request class ImageUploadInfoDto( - var location: String? = null + var location: String? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/KeyInScreenshotPositionDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/KeyInScreenshotPositionDto.kt index 1089954485..fc9c33babb 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/KeyInScreenshotPositionDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/KeyInScreenshotPositionDto.kt @@ -4,5 +4,5 @@ class KeyInScreenshotPositionDto( var x: Int = 0, var y: Int = 0, var width: Int = 0, - var height: Int = 0 + var height: Int = 0, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/LanguageDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/LanguageDto.kt index 8cdf4110e6..9ce0692526 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/LanguageDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/LanguageDto.kt @@ -7,18 +7,19 @@ import jakarta.validation.constraints.Size data class LanguageDto( @Schema(example = "Czech", description = "Language name in english") - @field:NotBlank @field:Size(max = 100) + @field:NotBlank + @field:Size(max = 100) var name: String = "", - @Schema(example = "čeština", description = "Language name in this language") - @field:NotBlank @field:Size(max = 100) + @field:NotBlank + @field:Size(max = 100) var originalName: String? = null, - @Schema(example = "cs-CZ", description = "Language tag according to BCP 47 definition") - @field:NotBlank @field:Size(max = 20) @field:Pattern(regexp = "^[^,]*$", message = "can not contain coma") + @field:NotBlank + @field:Size(max = 20) + @field:Pattern(regexp = "^[^,]*$", message = "can not contain coma") var tag: String = "", - @Schema(example = "\uD83C\uDDE8\uD83C\uDDFF", description = "Language flag emoji as UTF-8 emoji") @field:Size(max = 20) - var flagEmoji: String? = null + var flagEmoji: String? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/MachineTranslationLanguagePropsDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/MachineTranslationLanguagePropsDto.kt index c92e6154df..d6f1aab0f7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/MachineTranslationLanguagePropsDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/MachineTranslationLanguagePropsDto.kt @@ -8,20 +8,15 @@ import io.tolgee.service.machineTranslation.MtServiceInfo data class MachineTranslationLanguagePropsDto( @Schema(description = "The language to apply those rules. If null, then this settings are default.") var targetLanguageId: Long? = null, - @Schema(description = "This service will be used for automated translation", deprecated = true) var primaryService: MtServiceType? = null, - @Schema(description = "This service info will be used for automated translation") var primaryServiceInfo: MtServiceInfo? = null, - @Schema(description = "List of enabled services (deprecated: use enabledServicesInfo)", deprecated = true) var enabledServices: Set? = setOf(), - @Schema(description = "Info about enabled services") - var enabledServicesInfo: Set? = setOf() + var enabledServicesInfo: Set? = setOf(), ) { - /* * The OpenApi generator doesn't support default values and marks property as required when non nullable type is used, * so we need nullable types and add these custom setters diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/ScreenshotInfoDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/ScreenshotInfoDto.kt index d332abcbae..260e402bb9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/ScreenshotInfoDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/ScreenshotInfoDto.kt @@ -3,5 +3,5 @@ package io.tolgee.dtos.request class ScreenshotInfoDto( var text: String? = null, var positions: List? = null, - var location: String? = null + var location: String? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/SetDisabledLanguagesRequest.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/SetDisabledLanguagesRequest.kt index 9bf8b873ef..acf7abdb55 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/SetDisabledLanguagesRequest.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/SetDisabledLanguagesRequest.kt @@ -1,5 +1,5 @@ package io.tolgee.dtos.request class SetDisabledLanguagesRequest( - val languageIds: List + val languageIds: List, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/SetMachineTranslationSettingsDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/SetMachineTranslationSettingsDto.kt index 790bd77cde..be1504b594 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/SetMachineTranslationSettingsDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/SetMachineTranslationSettingsDto.kt @@ -1,5 +1,5 @@ package io.tolgee.dtos.request data class SetMachineTranslationSettingsDto( - var settings: List = listOf() + var settings: List = listOf(), ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/SetPropertyDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/SetPropertyDto.kt index 22233fe2b7..d16acd20ef 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/SetPropertyDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/SetPropertyDto.kt @@ -2,5 +2,5 @@ package io.tolgee.dtos.request data class SetPropertyDto( var name: String = "", - var value: Any? = null + var value: Any? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/SuggestRequestDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/SuggestRequestDto.kt index 967d84f829..bd4b265fe5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/SuggestRequestDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/SuggestRequestDto.kt @@ -10,5 +10,5 @@ data class SuggestRequestDto( @Schema(description = "Text value of base translation. Useful, when base translation is not stored yet.") var baseText: String? = null, @Schema(description = "List of services to use. If null, then all enabled services are used.") - var services: Set? = null + var services: Set? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/SuperTokenRequest.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/SuperTokenRequest.kt index 8e30eb463c..b8d88bcef1 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/SuperTokenRequest.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/SuperTokenRequest.kt @@ -5,7 +5,6 @@ import io.swagger.v3.oas.annotations.media.Schema data class SuperTokenRequest( @Schema(description = "Has to be provided when TOTP enabled") var otp: String? = null, - @Schema(description = "Has to be provided when TOTP not enabled") - var password: String? = null + var password: String? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserMfaRecoveryRequestDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserMfaRecoveryRequestDto.kt index 6d68227100..448974787d 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserMfaRecoveryRequestDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserMfaRecoveryRequestDto.kt @@ -8,5 +8,5 @@ import jakarta.validation.constraints.Size data class UserMfaRecoveryRequestDto( @field:NotBlank @field:Size(max = 50) - var password: String = "" + var password: String = "", ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserTotpDisableRequestDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserTotpDisableRequestDto.kt index fa6c0945e7..664952d017 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserTotpDisableRequestDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserTotpDisableRequestDto.kt @@ -8,5 +8,5 @@ import jakarta.validation.constraints.Size data class UserTotpDisableRequestDto( @field:NotBlank @field:Size(max = 50) - var password: String = "" + var password: String = "", ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserTotpEnableRequestDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserTotpEnableRequestDto.kt index 1488b308d6..699034a47d 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserTotpEnableRequestDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserTotpEnableRequestDto.kt @@ -11,12 +11,10 @@ data class UserTotpEnableRequestDto( @field:Size(min = 16, max = 16) @field:Pattern(regexp = "^(?:[a-z2-7]{8})*$") var totpKey: String = "", - @field:NotBlank @field:Size(min = 6, max = 6) var otp: String = "", - @field:NotBlank @field:Size(max = 50) - var password: String = "" + var password: String = "", ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserUpdatePasswordRequestDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserUpdatePasswordRequestDto.kt index 230a3b2557..50f8adaf79 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserUpdatePasswordRequestDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserUpdatePasswordRequestDto.kt @@ -9,7 +9,6 @@ data class UserUpdatePasswordRequestDto( @field:NotBlank @field:Size(max = 50) var currentPassword: String = "", - @field:Size(min = 8, max = 50) - var password: String = "" + var password: String = "", ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserUpdateRequestDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserUpdateRequestDto.kt index 5acfe02465..80bd8bcf52 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserUpdateRequestDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/UserUpdateRequestDto.kt @@ -9,16 +9,14 @@ import jakarta.validation.constraints.Size data class UserUpdateRequestDto( @field:NotBlank var name: String = "", - @field:NotBlank var email: String = "", - @field:Size(max = 50) var currentPassword: String? = null, - @Schema( - description = "Callback url for link sent in e-mail." + - " This may be omitted, when server has set frontEndUrl in properties." + description = + "Callback url for link sent in e-mail." + + " This may be omitted, when server has set frontEndUrl in properties.", ) - var callbackUrl: String? = null + var callbackUrl: String? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/apiKey/CreateApiKeyDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/apiKey/CreateApiKeyDto.kt index fdfe360c48..6f9d931c3b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/apiKey/CreateApiKeyDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/apiKey/CreateApiKeyDto.kt @@ -15,28 +15,25 @@ data class CreateApiKeyDto( @field:NotNull @field:Min(1) var projectId: Long = 0, - @field:NotEmpty @JsonIgnore @Schema( example = """ ["screenshots.upload", "screenshots.delete", "translations.edit", "screenshots.view", "translations.view", "keys.edit"] - """ + """, ) var scopes: Set = setOf(), - @Schema(description = "Description of the project API key") @field:Length(max = 250, min = 1) var description: String? = null, - @Schema( - description = "Expiration date in epoch format (milliseconds)." + - " When null key never expires.", - example = "1661172869000" + description = + "Expiration date in epoch format (milliseconds)." + + " When null key never expires.", + example = "1661172869000", ) - val expiresAt: Long? = null + val expiresAt: Long? = null, ) { - @Suppress("unused") @JsonSetter("scopes") fun jsonSetScopes(scopes: Set) { diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/apiKey/RegenerateApiKeyDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/apiKey/RegenerateApiKeyDto.kt index 9c9f388e19..c2e36644e9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/apiKey/RegenerateApiKeyDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/apiKey/RegenerateApiKeyDto.kt @@ -4,9 +4,10 @@ import io.swagger.v3.oas.annotations.media.Schema data class RegenerateApiKeyDto( @Schema( - description = "Expiration date in epoch format (milliseconds)." + - " When null key never expires.", - example = "1661172869000" + description = + "Expiration date in epoch format (milliseconds)." + + " When null key never expires.", + example = "1661172869000", ) - val expiresAt: Long? = null + val expiresAt: Long? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/apiKey/V2EditApiKeyDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/apiKey/V2EditApiKeyDto.kt index be9805c7bb..e6b1d77d85 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/apiKey/V2EditApiKeyDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/apiKey/V2EditApiKeyDto.kt @@ -13,12 +13,11 @@ data class V2EditApiKeyDto( @Schema( example = """ ["screenshots.upload", "screenshots.delete", "translations.edit", "screenshots.view", "translations.view", "keys.edit"] - """ + """, ) var scopes: Set = setOf(), - var description: String? = null + var description: String? = null, ) { - @Suppress("unused") @JsonSetter("scopes") fun jsonSetScopes(scopes: Set) { diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/auth/ResetPassword.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/auth/ResetPassword.kt index 4fc877906a..7f2e333ab8 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/auth/ResetPassword.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/auth/ResetPassword.kt @@ -6,10 +6,8 @@ import jakarta.validation.constraints.Size data class ResetPassword( @field:NotBlank var email: String? = null, - @field:NotBlank var code: String? = null, - @field:Size(min = 8, max = 50) var password: String? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/auth/ResetPasswordRequest.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/auth/ResetPasswordRequest.kt index 05f0d24963..668f7f004f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/auth/ResetPasswordRequest.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/auth/ResetPasswordRequest.kt @@ -6,8 +6,7 @@ import jakarta.validation.constraints.NotBlank data class ResetPasswordRequest( @field:NotBlank var callbackUrl: String? = null, - @field:Email @field:NotBlank - var email: String? = null + var email: String? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/auth/SignUpDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/auth/SignUpDto.kt index 68d9a14222..8663983c69 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/auth/SignUpDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/auth/SignUpDto.kt @@ -7,19 +7,14 @@ import jakarta.validation.constraints.Size data class SignUpDto( @field:NotBlank var name: String = "", - @field:Email @field:NotBlank var email: String = "", - @field:Size(min = 3, max = 50) var organizationName: String? = null, - @field:Size(min = 8, max = 50) @field:NotBlank var password: String? = null, - var invitationCode: String? = null, - var callbackUrl: String? = null, ) { var recaptchaToken: String? = null diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/export/ExportParams.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/export/ExportParams.kt index e7cb292705..3d84b4c7d1 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/export/ExportParams.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/export/ExportParams.kt @@ -9,15 +9,13 @@ data class ExportParams( description = """Languages to be contained in export. If null, all languages are exported""", - example = "en" + example = "en", ) override var languages: Set? = null, - @field:Parameter( description = """Format to export to""", ) override var format: ExportFormat = ExportFormat.JSON, - @field:Parameter( description = """Delimiter to structure file content. @@ -27,45 +25,39 @@ When null, resulting file won't be structured. """, ) override var structureDelimiter: Char? = '.', - @field:Parameter( description = """Filter key IDs to be contained in export""", ) override var filterKeyId: List? = null, - @field:Parameter( description = """Filter key IDs not to be contained in export""", ) override var filterKeyIdNot: List? = null, - @field:Parameter( description = """Filter keys tagged by""", ) override var filterTag: String? = null, - @field:Parameter( description = """Filter keys with prefix""", ) override var filterKeyPrefix: String? = null, - @field:Parameter( description = """Filter translations with state. By default, everything except untranslated is exported.""", ) - override var filterState: List? = listOf( - TranslationState.TRANSLATED, - TranslationState.REVIEWED, - ), - + override var filterState: List? = + listOf( + TranslationState.TRANSLATED, + TranslationState.REVIEWED, + ), @field:Parameter( - description = """Select one ore multiple namespaces to export""" + description = """Select one ore multiple namespaces to export""", ) override var filterNamespace: List? = null, - @field:Parameter( description = """If false, it doesn't return zip of files, but it returns single file. This is possible only when single language is exported. Otherwise it returns "400 - Bad Request" response. - """ + """, ) - var zip: Boolean = true + var zip: Boolean = true, ) : IExportParams diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/ComplexEditKeyDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/ComplexEditKeyDto.kt index caa4e4dd52..26812b6ef1 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/ComplexEditKeyDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/ComplexEditKeyDto.kt @@ -17,31 +17,23 @@ data class ComplexEditKeyDto( @field:NotBlank @field:Length(max = 2000, min = 1) val name: String = "", - @field:Length(max = 100) @Schema(description = "The namespace of the key. (When empty or null default namespace will be used)") @JsonProperty(access = JsonProperty.Access.READ_ONLY) var namespace: String? = null, - @Schema(description = "Translations to update") val translations: Map? = null, - @Schema(description = "Translation states to update, if not provided states won't be modified") val states: Map? = null, - @Schema(description = "Tags of the key. If not provided tags won't be modified") val tags: List? = null, - @Schema(description = "IDs of screenshots to delete") val screenshotIdsToDelete: List? = null, - @Schema(description = "Ids of screenshots uploaded with /v2/image-upload endpoint") @Deprecated("Use screenshotsToAdd instead") val screenshotUploadedImageIds: List? = null, - val screenshotsToAdd: List? = null, - - override var relatedKeysInOrder: MutableList? = null + override var relatedKeysInOrder: MutableList? = null, ) : WithRelatedKeysInOrder { @JsonSetter("namespace") fun setJsonNamespace(namespace: String?) { diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/CreateKeyDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/CreateKeyDto.kt index 99087bd97b..931aa84930 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/CreateKeyDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/CreateKeyDto.kt @@ -20,26 +20,19 @@ class CreateKeyDto( @field:NotBlank @field:Length(max = 2000, min = 1) val name: String = "", - @field:Length(max = 100) @Schema(description = "The namespace of the key. (When empty or null default namespace will be used)") @JsonProperty(access = JsonProperty.Access.READ_ONLY) var namespace: String? = null, - val translations: Map? = null, - @Schema(description = "Translation states to update, if not provided states won't be modified") val states: Map? = null, - val tags: List? = null, - @Schema(description = "Ids of screenshots uploaded with /v2/image-upload endpoint") @Deprecated("Use screenshots instead") val screenshotUploadedImageIds: List? = null, - val screenshots: List? = null, - - override var relatedKeysInOrder: MutableList? = null + override var relatedKeysInOrder: MutableList? = null, ) : WithRelatedKeysInOrder { @JsonSetter("namespace") fun setJsonNamespace(namespace: String?) { diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/DeleteKeysDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/DeleteKeysDto.kt index 3952d2f257..df7ae6739e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/DeleteKeysDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/DeleteKeysDto.kt @@ -4,5 +4,5 @@ import io.swagger.v3.oas.annotations.media.Schema data class DeleteKeysDto( @Schema(description = "IDs of keys to delete") - var ids: Set = setOf() + var ids: Set = setOf(), ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/DeprecatedEditKeyDTO.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/DeprecatedEditKeyDTO.kt index 66c2d4906e..7c3e1654c9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/DeprecatedEditKeyDTO.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/DeprecatedEditKeyDTO.kt @@ -10,7 +10,7 @@ data class DeprecatedEditKeyDTO( @field:NotBlank var oldFullPathString: String = "", @field:NotBlank - var newFullPathString: String = "" + var newFullPathString: String = "", ) { @get:Hidden @get:JsonIgnore diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/EditKeyDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/EditKeyDto.kt index 41141a82d5..c70f406385 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/EditKeyDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/EditKeyDto.kt @@ -12,13 +12,11 @@ data class EditKeyDto( @field:NotBlank @field:Length(max = 2000) var name: String = "", - @field:Length(max = ValidationConstants.MAX_NAMESPACE_LENGTH) @Schema(description = "The namespace of the key. (When empty or null default namespace will be used)") @JsonProperty(access = JsonProperty.Access.READ_ONLY) var namespace: String? = null, ) { - @JsonSetter("namespace") fun setJsonNamespace(namespace: String?) { this.namespace = getSafeNamespace(namespace) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/KeyScreenshotDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/KeyScreenshotDto.kt index 81c6fda269..f890f042c5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/KeyScreenshotDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/KeyScreenshotDto.kt @@ -5,6 +5,7 @@ import io.tolgee.dtos.request.KeyInScreenshotPositionDto class KeyScreenshotDto { var text: String? = null + @Schema(description = "Ids of screenshot uploaded with /v2/image-upload endpoint") var uploadedImageId: Long = 0 var positions: List? = null diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/OldEditKeyDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/OldEditKeyDto.kt index 1a1ad45fda..8149d44e31 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/OldEditKeyDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/OldEditKeyDto.kt @@ -11,7 +11,7 @@ data class OldEditKeyDto( var currentName: String = "", @field:NotBlank @field:Length(max = 2000) - var newName: String = "" + var newName: String = "", ) { @get:Hidden @get:JsonIgnore diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/TagKeyDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/TagKeyDto.kt index 71844bf156..c6beaf623a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/TagKeyDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/key/TagKeyDto.kt @@ -7,5 +7,5 @@ import jakarta.validation.constraints.Size data class TagKeyDto( @field:NotBlank @field:Size(max = ValidationConstants.MAX_TAG_LENGTH) - val name: String = "" + val name: String = "", ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/organization/OrganizationDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/organization/OrganizationDto.kt index e72bfca793..1021f71afe 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/organization/OrganizationDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/organization/OrganizationDto.kt @@ -6,13 +6,12 @@ import jakarta.validation.constraints.Pattern import jakarta.validation.constraints.Size data class OrganizationDto( - @field:NotBlank @field:Size(min = 3, max = 50) + @field:NotBlank + @field:Size(min = 3, max = 50) @Schema(example = "Beautiful organization") var name: String = "", - @Schema(example = "This is a beautiful organization full of beautiful and clever people") var description: String? = null, - @field:Size(min = 3, max = 60) @field:Pattern(regexp = "^[a-z0-9-]*[a-z]+[a-z0-9-]*$", message = "invalid_pattern") @Schema(example = "btforg") diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/organization/OrganizationInviteUserDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/organization/OrganizationInviteUserDto.kt index 872337be10..46169b56e4 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/organization/OrganizationInviteUserDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/organization/OrganizationInviteUserDto.kt @@ -9,17 +9,15 @@ import jakarta.validation.constraints.Size data class OrganizationInviteUserDto( @field:NotNull var roleType: OrganizationRoleType = OrganizationRoleType.MEMBER, - @Schema( - description = """Name of invited user""" + description = """Name of invited user""", ) @field:Size(max = 250) var name: String? = null, - @Schema( - description = """Email to send invitation to""" + description = """Email to send invitation to""", ) @field:Size(max = 250) @field:Email - var email: String? = null + var email: String? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/organization/OrganizationRequestParamsDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/organization/OrganizationRequestParamsDto.kt index ef2267790a..1bbba152f4 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/organization/OrganizationRequestParamsDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/organization/OrganizationRequestParamsDto.kt @@ -2,5 +2,5 @@ package io.tolgee.dtos.request.organization data class OrganizationRequestParamsDto( val filterCurrentUserOwner: Boolean = false, - val search: String? = "" + val search: String? = "", ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/organization/SetOrganizationRoleDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/organization/SetOrganizationRoleDto.kt index 85f65f21f8..ed589750f2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/organization/SetOrganizationRoleDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/organization/SetOrganizationRoleDto.kt @@ -5,5 +5,5 @@ import jakarta.validation.constraints.NotBlank data class SetOrganizationRoleDto( @NotBlank - val roleType: OrganizationRoleType = OrganizationRoleType.MEMBER + val roleType: OrganizationRoleType = OrganizationRoleType.MEMBER, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/pat/CreatePatDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/pat/CreatePatDto.kt index 89aa700c11..14ab3f54e7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/pat/CreatePatDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/pat/CreatePatDto.kt @@ -11,11 +11,11 @@ data class CreatePatDto( @field:NotBlank @field:Length(max = 250, min = 1) val description: String = "", - @Schema( - description = "Expiration date in epoch format (milliseconds)." + - " When null, token never expires.", - example = "1661172869000" + description = + "Expiration date in epoch format (milliseconds)." + + " When null, token never expires.", + example = "1661172869000", ) - val expiresAt: Long? = null + val expiresAt: Long? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/pat/RegeneratePatDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/pat/RegeneratePatDto.kt index bbed105b39..3d50dc2db6 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/pat/RegeneratePatDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/pat/RegeneratePatDto.kt @@ -7,7 +7,7 @@ import org.springframework.validation.annotation.Validated data class RegeneratePatDto( @Schema( description = "Expiration date in epoch format (milliseconds). When null key never expires.", - example = "1661172869000" + example = "1661172869000", ) - val expiresAt: Long? = null + val expiresAt: Long? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/project/CreateProjectDTO.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/project/CreateProjectDTO.kt index bb819a2be6..c076c98bd6 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/project/CreateProjectDTO.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/project/CreateProjectDTO.kt @@ -10,28 +10,27 @@ import jakarta.validation.constraints.Pattern import jakarta.validation.constraints.Size data class CreateProjectDTO( - @field:NotBlank @field:Size(min = 3, max = 50) + @field:NotBlank + @field:Size(min = 3, max = 50) var name: String = "", - @field:NotEmpty @field:Valid var languages: List? = null, - @field:Size(min = 3, max = 60) @field:Pattern(regexp = "^[a-z0-9-]*[a-z]+[a-z0-9-]*$", message = "invalid_pattern") @Schema( - description = "Slug of your project used in url e.g. \"/v2/projects/what-a-project\"." + - " If not provided, it will be generated" + description = + "Slug of your project used in url e.g. \"/v2/projects/what-a-project\"." + + " If not provided, it will be generated", ) var slug: String? = null, - - @field: Min(1) + @field:Min(1) @Schema(description = "Organization to create the project in") var organizationId: Long = 0, - @Schema( - description = "Tag of one of created languages, to select it as base language. If not provided, " + - "first language will be selected as base." + description = + "Tag of one of created languages, to select it as base language. If not provided, " + + "first language will be selected as base.", ) - var baseLanguageTag: String? = null + var baseLanguageTag: String? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/project/EditProjectDTO.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/project/EditProjectDTO.kt index 8db7253eb8..4a7fe2e7f6 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/project/EditProjectDTO.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/project/EditProjectDTO.kt @@ -5,15 +5,13 @@ import jakarta.validation.constraints.Pattern import jakarta.validation.constraints.Size data class EditProjectDTO( - @field:NotBlank @field:Size(min = 3, max = 50) + @field:NotBlank + @field:Size(min = 3, max = 50) var name: String = "", - @field:Size(min = 3, max = 60) @field:Pattern(regexp = "^[a-z0-9-]*[a-z]+[a-z0-9-]*$", message = "invalid_pattern") var slug: String? = null, - var baseLanguageId: Long? = null, - @field:Size(min = 3, max = 2000) var description: String? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/project/LanguagePermissions.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/project/LanguagePermissions.kt index d0d71af0e5..03c822b6f0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/project/LanguagePermissions.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/project/LanguagePermissions.kt @@ -4,8 +4,6 @@ import io.tolgee.model.Language class LanguagePermissions( var translate: Set?, - var view: Set?, - - var stateChange: Set? + var stateChange: Set?, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/project/ProjectInviteUserDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/project/ProjectInviteUserDto.kt index 63a9de2545..e975daf57f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/project/ProjectInviteUserDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/project/ProjectInviteUserDto.kt @@ -7,31 +7,24 @@ import jakarta.validation.constraints.Size data class ProjectInviteUserDto( var type: ProjectPermissionType? = null, - @get:Schema( description = "Granted scopes for the invited user", - example = """["translations.view", "translations.edit"]""" + example = """["translations.view", "translations.edit"]""", ) var scopes: Set? = null, - override var languages: Set? = null, - override var translateLanguages: Set? = null, - override var viewLanguages: Set? = null, - override var stateChangeLanguages: Set? = null, - @Schema( - description = """Email to send invitation to""" + description = """Email to send invitation to""", ) @field:Size(max = 250) @field:Email val email: String? = null, - @Schema( - description = """Name of invited user""" + description = """Name of invited user""", ) @field:Size(max = 250) - val name: String? = null + val name: String? = null, ) : RequestWithLanguagePermissions diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/screenshot/GetScreenshotsByKeyDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/screenshot/GetScreenshotsByKeyDto.kt index 3cd5240193..23f8ed9d7b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/screenshot/GetScreenshotsByKeyDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/screenshot/GetScreenshotsByKeyDto.kt @@ -4,5 +4,5 @@ import jakarta.validation.constraints.NotBlank data class GetScreenshotsByKeyDto( @field:NotBlank - var key: String = "" + var key: String = "", ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/screenshot/UploadScreenshotDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/screenshot/UploadScreenshotDto.kt index f64425c9a7..262a21bf9a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/screenshot/UploadScreenshotDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/screenshot/UploadScreenshotDto.kt @@ -6,5 +6,5 @@ import org.springframework.validation.annotation.Validated @Validated data class UploadScreenshotDto( @field:NotBlank - var key: String? = null + var key: String? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/GetTranslationsParams.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/GetTranslationsParams.kt index 42e676cddf..79d563ece3 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/GetTranslationsParams.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/GetTranslationsParams.kt @@ -6,7 +6,6 @@ class GetTranslationsParams( // When filterState has setter, it starts to split it's values on ',' char, // so we need to add it here, to be able to not provide the setter filterState: List? = null, - @field:Parameter(description = "Cursor to get next data") - val cursor: String? = null + val cursor: String? = null, ) : TranslationFilters(filterState) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/ImportKeysDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/ImportKeysDto.kt index 7da91bfe2a..206e4b8179 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/ImportKeysDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/ImportKeysDto.kt @@ -6,5 +6,5 @@ import org.springframework.validation.annotation.Validated @Validated data class ImportKeysDto( @field:Valid - val keys: List = listOf() + val keys: List = listOf(), ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/ImportKeysItemDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/ImportKeysItemDto.kt index 72eb8e2ed2..1a1fffdb7a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/ImportKeysItemDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/ImportKeysItemDto.kt @@ -13,24 +13,21 @@ class ImportKeysItemDto( @field:NotBlank @field:Length(max = 2000) val name: String = "", - @field:Length(max = 100) @Schema(description = "The namespace of the key. (When empty or null default namespace will be used)") val namespace: String? = null, - /** * Map of language tag -> text */ @field:NotNull @Schema( description = "Object mapping language tag to translation", - example = "{\"en\": \"What a translated value!\", \"cs\": \"Jaká to přeložená hodnota!\"}" + example = "{\"en\": \"What a translated value!\", \"cs\": \"Jaká to přeložená hodnota!\"}", ) val translations: Map = mapOf(), - @Schema( description = "Tags of the key", - example = "[\"homepage\", \"user-profile\"]" + example = "[\"homepage\", \"user-profile\"]", ) - val tags: List? = null + val tags: List? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/SelectAllResponse.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/SelectAllResponse.kt index 9cb2c48031..a0aacfe2fc 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/SelectAllResponse.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/SelectAllResponse.kt @@ -1,5 +1,5 @@ package io.tolgee.dtos.request.translation data class SelectAllResponse( - val ids: List + val ids: List, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/SetTranslationsWithKeyDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/SetTranslationsWithKeyDto.kt index 1b136d0ae1..3bdbf1248f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/SetTranslationsWithKeyDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/SetTranslationsWithKeyDto.kt @@ -15,27 +15,24 @@ data class SetTranslationsWithKeyDto( @field:NotBlank @field:Length(max = 2000) val key: String = "", - @field:Length(max = 100) @Schema(description = "The namespace of the key. (When empty or null default namespace will be used)") val namespace: String? = null, - /** * Map of language tag -> text */ @field:NotNull @Schema( description = "Object mapping language tag to translation", - example = "{\"en\": \"What a translated value!\", \"cs\": \"Jaká to přeložená hodnota!\"}" + example = "{\"en\": \"What a translated value!\", \"cs\": \"Jaká to přeložená hodnota!\"}", ) val translations: Map = mapOf(), - @Schema( description = """List of languages to return translations for. If not provided, only modified translation will be provided. """, - example = """["en", "de", "fr"]""" + example = """["en", "de", "fr"]""", ) - val languagesToReturn: Set? = null + val languagesToReturn: Set? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/TranslationFilters.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/TranslationFilters.kt index ba35b4a39d..31f629c45c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/TranslationFilters.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/TranslationFilters.kt @@ -15,15 +15,15 @@ When used with multiple languages, it is applied with logical AND. ExampleObject("en,TRANSLATED"), ExampleObject("en-US,UNTRANSLATED"), ExampleObject("fr,REVIEWED"), - ] + ], ) - open val filterState: List? = null + open val filterState: List? = null, ) { @field:Parameter( description = """Languages to be contained in response. To add multiple languages, repeat this param (eg. ?languages=en&languages=de)""", - example = "en" + example = "en", ) var languages: Set? = null @@ -44,13 +44,13 @@ To add multiple languages, repeat this param (eg. ?languages=en&languages=de)""" @field:Parameter( description = "Selects only keys, where translation is missing in specified language", - example = "en-US" + example = "en-US", ) var filterUntranslatedInLang: String? = null @field:Parameter( description = "Selects only keys, where translation is provided in specified language", - example = "en-US" + example = "en-US", ) var filterTranslatedInLang: String? = null @@ -64,7 +64,7 @@ To add multiple languages, repeat this param (eg. ?languages=en&languages=de)""" description = """Filter namespaces. To filter default namespace, set to empty string. - """ + """, ) var filterNamespace: List? = null @@ -73,13 +73,13 @@ To filter default namespace, set to empty string. @field:Parameter( description = "Selects only keys, where translation in provided langs is in outdated state", - example = "en-US" + example = "en-US", ) var filterOutdatedLanguage: List? = null @field:Parameter( description = "Selects only keys, where translation in provided langs is not in outdated state", - example = "en-US" + example = "en-US", ) var filterNotOutdatedLanguage: List? = null } diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/comment/TranslationCommentDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/comment/TranslationCommentDto.kt index 7817dee9b0..b8ef6a61b5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/comment/TranslationCommentDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/comment/TranslationCommentDto.kt @@ -8,6 +8,5 @@ data class TranslationCommentDto( @field:Length(max = 10000) @field:NotBlank override var text: String = "", - - override var state: TranslationCommentState = TranslationCommentState.RESOLUTION_NOT_NEEDED + override var state: TranslationCommentState = TranslationCommentState.RESOLUTION_NOT_NEEDED, ) : ITranslationCommentDto diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/comment/TranslationCommentWithLangKeyDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/comment/TranslationCommentWithLangKeyDto.kt index cece2b3982..43a40203a2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/comment/TranslationCommentWithLangKeyDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/comment/TranslationCommentWithLangKeyDto.kt @@ -8,13 +8,10 @@ import org.hibernate.validator.constraints.Length data class TranslationCommentWithLangKeyDto( @field:NotNull val keyId: Long = 0, - @field:NotNull val languageId: Long = 0, - @field:Length(max = 10000) @field:NotBlank override var text: String = "", - - override var state: TranslationCommentState = TranslationCommentState.RESOLUTION_NOT_NEEDED + override var state: TranslationCommentState = TranslationCommentState.RESOLUTION_NOT_NEEDED, ) : ITranslationCommentDto diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/importKeysResolvable/ImportKeysResolvableDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/importKeysResolvable/ImportKeysResolvableDto.kt index ec8cb965c5..28687006d1 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/importKeysResolvable/ImportKeysResolvableDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/importKeysResolvable/ImportKeysResolvableDto.kt @@ -4,5 +4,5 @@ import org.springframework.validation.annotation.Validated @Validated data class ImportKeysResolvableDto( - val keys: List = listOf() + val keys: List = listOf(), ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/importKeysResolvable/ImportKeysResolvableItemDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/importKeysResolvable/ImportKeysResolvableItemDto.kt index 89ae3fd735..0ad45ac347 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/importKeysResolvable/ImportKeysResolvableItemDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/importKeysResolvable/ImportKeysResolvableItemDto.kt @@ -14,13 +14,10 @@ class ImportKeysResolvableItemDto( @field:NotBlank @field:Length(max = 2000) val name: String = "", - @field:Length(max = 100) @Schema(description = "The namespace of the key. (When empty or null default namespace will be used)") val namespace: String? = null, - val screenshots: List? = null, - /** * Map of language tag -> text */ diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/importKeysResolvable/ImportTranslationResolution.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/importKeysResolvable/ImportTranslationResolution.kt index 2052c0fa15..d50e08d425 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/importKeysResolvable/ImportTranslationResolution.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/importKeysResolvable/ImportTranslationResolution.kt @@ -3,5 +3,5 @@ package io.tolgee.dtos.request.translation.importKeysResolvable enum class ImportTranslationResolution { KEEP, OVERRIDE, - NEW + NEW, } diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/importKeysResolvable/ImportTranslationResolvableDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/importKeysResolvable/ImportTranslationResolvableDto.kt index 4cb9db040d..6eb826860b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/importKeysResolvable/ImportTranslationResolvableDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/translation/importKeysResolvable/ImportTranslationResolvableDto.kt @@ -8,7 +8,6 @@ class ImportTranslationResolvableDto( */ @Schema(description = "Translation text", example = "Hello! I am a translation!") val text: String = "", - @Schema( description = """Determines, how conflict is resolved. @@ -16,7 +15,7 @@ class ImportTranslationResolvableDto( - OVERRIDE: Translation is overridden - NEW: New translation is created) """, - example = "OVERRIDE" + example = "OVERRIDE", ) val resolution: ImportTranslationResolution = ImportTranslationResolution.NEW, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/request/validators/ValidationErrorType.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/request/validators/ValidationErrorType.kt index 23d28d3e43..bbe0eb14c3 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/request/validators/ValidationErrorType.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/request/validators/ValidationErrorType.kt @@ -1,5 +1,6 @@ package io.tolgee.dtos.request.validators enum class ValidationErrorType { - CUSTOM_VALIDATION, STANDARD_VALIDATION + CUSTOM_VALIDATION, + STANDARD_VALIDATION, } diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/response/ApiKeyDTO/ApiKeyDTO.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/response/ApiKeyDTO.kt similarity index 79% rename from backend/data/src/main/kotlin/io/tolgee/dtos/response/ApiKeyDTO/ApiKeyDTO.kt rename to backend/data/src/main/kotlin/io/tolgee/dtos/response/ApiKeyDTO.kt index 1fe590d789..e5ff40af15 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/response/ApiKeyDTO/ApiKeyDTO.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/response/ApiKeyDTO.kt @@ -1,4 +1,4 @@ -package io.tolgee.dtos.response.ApiKeyDTO +package io.tolgee.dtos.response import io.swagger.v3.oas.annotations.media.Schema import io.tolgee.model.ApiKey @@ -7,17 +7,17 @@ import io.tolgee.security.PROJECT_API_KEY_PREFIX class ApiKeyDTO( var id: Long = 0, @field:Schema( - description = "Resulting user's api key. " + - "Is is hidden when is not response to creation or regeneration." + description = + "Resulting user's api key. " + + "Is is hidden when is not response to creation or regeneration.", ) var key: String? = null, var description: String = "", var userName: String? = null, var projectId: Long = 0, var projectName: String = "", - var scopes: Set = setOf() + var scopes: Set = setOf(), ) { - companion object { fun fromEntity(apiKey: ApiKey): ApiKeyDTO { return ApiKeyDTO( @@ -27,7 +27,7 @@ class ApiKeyDTO( userName = apiKey.userAccount.name, projectId = apiKey.project.id, projectName = apiKey.project.name, - scopes = apiKey.scopesEnum.mapNotNull { it?.value }.toSet() + scopes = apiKey.scopesEnum.mapNotNull { it?.value }.toSet(), ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/response/CursorValue.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/response/CursorValue.kt index 5f91561c2e..7b08e91cfd 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/response/CursorValue.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/response/CursorValue.kt @@ -4,5 +4,5 @@ import org.springframework.data.domain.Sort data class CursorValue( val direction: Sort.Direction, - val value: String? + val value: String?, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/response/DeprecatedKeyDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/response/DeprecatedKeyDto.kt index db8de9d6cd..81d47fe0c0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/response/DeprecatedKeyDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/response/DeprecatedKeyDto.kt @@ -11,7 +11,7 @@ data class DeprecatedKeyDto( @field:NotBlank @field:Size(min = 1, max = 300) @Schema(description = "This means name of key. Will be renamed in v2") - var fullPathString: String = "" + var fullPathString: String = "", ) { @get:JsonIgnore val pathDto: PathDTO diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/response/KeyWithTranslationsResponseDto.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/response/KeyWithTranslationsResponseDto.kt index f9dff2d58f..689e34eb93 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/response/KeyWithTranslationsResponseDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/response/KeyWithTranslationsResponseDto.kt @@ -1,11 +1,11 @@ package io.tolgee.dtos.response -import io.tolgee.dtos.query_results.KeyWithTranslationsDto +import io.tolgee.dtos.queryResults.KeyWithTranslationsDto data class KeyWithTranslationsResponseDto( var id: Long? = null, var name: String? = null, - var translations: Map = LinkedHashMap() + var translations: Map = LinkedHashMap(), ) { companion object { @JvmStatic @@ -13,7 +13,7 @@ data class KeyWithTranslationsResponseDto( return KeyWithTranslationsResponseDto( keyWithTranslationsDTO.id, keyWithTranslationsDTO.path.fullPathString, - keyWithTranslationsDTO.getTranslations() + keyWithTranslationsDTO.getTranslations(), ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/response/ProjectDTO.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/response/ProjectDTO.kt index 913ca91ade..50833d0a27 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/response/ProjectDTO.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/response/ProjectDTO.kt @@ -6,12 +6,14 @@ import io.tolgee.model.enums.Scope open class ProjectDTO( var id: Long? = null, var name: String? = null, - var scopes: Array + var scopes: Array, ) { - companion object { @JvmStatic - fun fromEntityAndPermission(project: Project, scopes: Array): ProjectDTO { + fun fromEntityAndPermission( + project: Project, + scopes: Array, + ): ProjectDTO { return ProjectDTO(project.id, project.name, scopes) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/response/PublicBillingConfigurationDTO.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/response/PublicBillingConfigurationDTO.kt index 4f386796d5..f3722330ed 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/response/PublicBillingConfigurationDTO.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/response/PublicBillingConfigurationDTO.kt @@ -1,5 +1,5 @@ package io.tolgee.dtos.response class PublicBillingConfigurationDTO( - val enabled: Boolean + val enabled: Boolean, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/response/ScreenshotDTO.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/response/ScreenshotDTO.kt index 3d3b697f97..10b27b4d49 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/response/ScreenshotDTO.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/response/ScreenshotDTO.kt @@ -9,5 +9,5 @@ import java.util.* data class ScreenshotDTO( val id: Long, val filename: String, - val createdAt: Date + val createdAt: Date, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/dtos/security/LoginRequest.kt b/backend/data/src/main/kotlin/io/tolgee/dtos/security/LoginRequest.kt index ec0a391213..3883c16f6f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/dtos/security/LoginRequest.kt +++ b/backend/data/src/main/kotlin/io/tolgee/dtos/security/LoginRequest.kt @@ -6,6 +6,7 @@ import jakarta.validation.constraints.NotEmpty class LoginRequest { @field:NotBlank var username: String = "" + @field:NotEmpty var password: String = "" var otp: String? = null diff --git a/backend/data/src/main/kotlin/io/tolgee/events/BeforeOrganizationDeleteEvent.kt b/backend/data/src/main/kotlin/io/tolgee/events/BeforeOrganizationDeleteEvent.kt index d4b7356dfb..5485cb1546 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/BeforeOrganizationDeleteEvent.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/BeforeOrganizationDeleteEvent.kt @@ -3,5 +3,5 @@ package io.tolgee.events import io.tolgee.model.Organization open class BeforeOrganizationDeleteEvent( - val organization: Organization + val organization: Organization, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/events/MachineTranslationEvent.kt b/backend/data/src/main/kotlin/io/tolgee/events/MachineTranslationEvent.kt index 9d60458667..3b2740eddd 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/MachineTranslationEvent.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/MachineTranslationEvent.kt @@ -13,5 +13,4 @@ open class MachineTranslationEvent( * The project containing translation */ val project: Project, - ) : ApplicationEvent(source) diff --git a/backend/data/src/main/kotlin/io/tolgee/events/OnAfterMachineTranslationEvent.kt b/backend/data/src/main/kotlin/io/tolgee/events/OnAfterMachineTranslationEvent.kt index 10b13159de..101073fc49 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/OnAfterMachineTranslationEvent.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/OnAfterMachineTranslationEvent.kt @@ -9,9 +9,8 @@ class OnAfterMachineTranslationEvent( * The project containing translation */ val project: Project, - /** * The actual total price of translation actually consumed */ - val actualSumPrice: Int + val actualSumPrice: Int, ) : ApplicationEvent(source) diff --git a/backend/data/src/main/kotlin/io/tolgee/events/OnConsumePayAsYouGoMtCredits.kt b/backend/data/src/main/kotlin/io/tolgee/events/OnConsumePayAsYouGoMtCredits.kt index 58b47ee891..8b826a40b2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/OnConsumePayAsYouGoMtCredits.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/OnConsumePayAsYouGoMtCredits.kt @@ -6,5 +6,5 @@ import org.springframework.context.ApplicationEvent class OnConsumePayAsYouGoMtCredits( source: MtCreditBucketService, val organizationId: Long, - val credits: Long + val credits: Long, ) : ApplicationEvent(source) diff --git a/backend/data/src/main/kotlin/io/tolgee/events/OnEntityPreDelete.kt b/backend/data/src/main/kotlin/io/tolgee/events/OnEntityPreDelete.kt index aeb88835fd..372d99cd6b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/OnEntityPreDelete.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/OnEntityPreDelete.kt @@ -5,5 +5,5 @@ import org.springframework.context.ApplicationEvent class OnEntityPreDelete( override val source: PreCommitEventPublisher, - override val entity: Any? + override val entity: Any?, ) : ApplicationEvent(source), EntityPreCommitEvent diff --git a/backend/data/src/main/kotlin/io/tolgee/events/OnEntityPrePersist.kt b/backend/data/src/main/kotlin/io/tolgee/events/OnEntityPrePersist.kt index d9387a34a1..ea90e61e45 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/OnEntityPrePersist.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/OnEntityPrePersist.kt @@ -5,5 +5,5 @@ import org.springframework.context.ApplicationEvent class OnEntityPrePersist( override val source: PreCommitEventPublisher, - override val entity: Any? + override val entity: Any?, ) : ApplicationEvent(source), EntityPreCommitEvent diff --git a/backend/data/src/main/kotlin/io/tolgee/events/OnEntityPreUpdate.kt b/backend/data/src/main/kotlin/io/tolgee/events/OnEntityPreUpdate.kt index d7d9a349aa..72b2802384 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/OnEntityPreUpdate.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/OnEntityPreUpdate.kt @@ -5,5 +5,5 @@ import org.springframework.context.ApplicationEvent class OnEntityPreUpdate( override val source: PreCommitEventPublisher, - override val entity: Any? + override val entity: Any?, ) : ApplicationEvent(source), EntityPreCommitEvent diff --git a/backend/data/src/main/kotlin/io/tolgee/events/OnImportSoftDeleted.kt b/backend/data/src/main/kotlin/io/tolgee/events/OnImportSoftDeleted.kt index 4453642383..71af4925bd 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/OnImportSoftDeleted.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/OnImportSoftDeleted.kt @@ -1,5 +1,5 @@ package io.tolgee.events class OnImportSoftDeleted( - val importId: Long + val importId: Long, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/events/OnKeyPrePersist.kt b/backend/data/src/main/kotlin/io/tolgee/events/OnKeyPrePersist.kt index a6e2a853c0..98652146e8 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/OnKeyPrePersist.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/OnKeyPrePersist.kt @@ -5,5 +5,5 @@ import org.springframework.context.ApplicationEvent class OnKeyPrePersist( source: Any, - val key: Key + val key: Key, ) : ApplicationEvent(source) diff --git a/backend/data/src/main/kotlin/io/tolgee/events/OnKeyPreRemove.kt b/backend/data/src/main/kotlin/io/tolgee/events/OnKeyPreRemove.kt index 5185544cd4..243889993c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/OnKeyPreRemove.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/OnKeyPreRemove.kt @@ -5,5 +5,5 @@ import org.springframework.context.ApplicationEvent class OnKeyPreRemove( source: Any, - val key: Key + val key: Key, ) : ApplicationEvent(source) diff --git a/backend/data/src/main/kotlin/io/tolgee/events/OnLanguagePrePersist.kt b/backend/data/src/main/kotlin/io/tolgee/events/OnLanguagePrePersist.kt index f3d8f92320..32af00f36b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/OnLanguagePrePersist.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/OnLanguagePrePersist.kt @@ -5,5 +5,5 @@ import org.springframework.context.ApplicationEvent class OnLanguagePrePersist( source: Any, - val language: Language + val language: Language, ) : ApplicationEvent(source) diff --git a/backend/data/src/main/kotlin/io/tolgee/events/OnLanguagePreRemove.kt b/backend/data/src/main/kotlin/io/tolgee/events/OnLanguagePreRemove.kt index 790a6d183f..a014fc3603 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/OnLanguagePreRemove.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/OnLanguagePreRemove.kt @@ -5,5 +5,5 @@ import org.springframework.context.ApplicationEvent class OnLanguagePreRemove( source: Any, - val language: Language + val language: Language, ) : ApplicationEvent(source) diff --git a/backend/data/src/main/kotlin/io/tolgee/events/OnProjectActivityEvent.kt b/backend/data/src/main/kotlin/io/tolgee/events/OnProjectActivityEvent.kt index 69d6ddfb41..444469b5f2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/OnProjectActivityEvent.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/OnProjectActivityEvent.kt @@ -9,5 +9,5 @@ class OnProjectActivityEvent( val modifiedEntities: ModifiedEntitiesType, val organizationId: Long?, var utmData: UtmData, - var sdkInfo: Map? + var sdkInfo: Map?, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/events/OnProjectActivityStoredEvent.kt b/backend/data/src/main/kotlin/io/tolgee/events/OnProjectActivityStoredEvent.kt index 3d5c1103f3..5340aa9d15 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/OnProjectActivityStoredEvent.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/OnProjectActivityStoredEvent.kt @@ -5,5 +5,5 @@ import org.springframework.context.ApplicationEvent class OnProjectActivityStoredEvent( source: Any, - val activityRevision: ActivityRevision + val activityRevision: ActivityRevision, ) : ApplicationEvent(source) diff --git a/backend/data/src/main/kotlin/io/tolgee/events/OnTranslationsSet.kt b/backend/data/src/main/kotlin/io/tolgee/events/OnTranslationsSet.kt index f7432658f4..2829219a37 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/OnTranslationsSet.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/OnTranslationsSet.kt @@ -10,13 +10,10 @@ import org.springframework.context.ApplicationEvent */ class OnTranslationsSet( source: Any, - val key: Key, - /** * Map of old values languageTag -> String */ val oldValues: Map, - - val translations: List + val translations: List, ) : ApplicationEvent(source) diff --git a/backend/data/src/main/kotlin/io/tolgee/events/OnUserCountChanged.kt b/backend/data/src/main/kotlin/io/tolgee/events/OnUserCountChanged.kt index d9b4fe3e33..a3e4326e6b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/OnUserCountChanged.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/OnUserCountChanged.kt @@ -3,5 +3,5 @@ package io.tolgee.events import org.springframework.context.ApplicationEvent class OnUserCountChanged( - source: Any + source: Any, ) : ApplicationEvent(source) diff --git a/backend/data/src/main/kotlin/io/tolgee/events/user/OnUserCreated.kt b/backend/data/src/main/kotlin/io/tolgee/events/user/OnUserCreated.kt index 2dbc9a81bc..fb4a4e4c71 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/user/OnUserCreated.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/user/OnUserCreated.kt @@ -4,5 +4,5 @@ import io.tolgee.model.UserAccount class OnUserCreated( source: Any, - userAccount: UserAccount + userAccount: UserAccount, ) : UserAccountEvent(source, userAccount) diff --git a/backend/data/src/main/kotlin/io/tolgee/events/user/OnUserEmailVerifiedFirst.kt b/backend/data/src/main/kotlin/io/tolgee/events/user/OnUserEmailVerifiedFirst.kt index be176df1b3..2fa6e42871 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/user/OnUserEmailVerifiedFirst.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/user/OnUserEmailVerifiedFirst.kt @@ -4,5 +4,5 @@ import io.tolgee.model.UserAccount class OnUserEmailVerifiedFirst( source: Any, - userAccount: UserAccount + userAccount: UserAccount, ) : UserAccountEvent(source, userAccount) diff --git a/backend/data/src/main/kotlin/io/tolgee/events/user/OnUserUpdated.kt b/backend/data/src/main/kotlin/io/tolgee/events/user/OnUserUpdated.kt index 3f513ad83d..d201821d86 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/user/OnUserUpdated.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/user/OnUserUpdated.kt @@ -6,5 +6,5 @@ import org.springframework.context.ApplicationEvent class OnUserUpdated( source: Any, val oldUserAccount: UserAccountDto, - val newUserAccount: UserAccountDto + val newUserAccount: UserAccountDto, ) : ApplicationEvent(source) diff --git a/backend/data/src/main/kotlin/io/tolgee/events/user/UserAccountEvent.kt b/backend/data/src/main/kotlin/io/tolgee/events/user/UserAccountEvent.kt index be6f4cebfe..d18291fbb7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/events/user/UserAccountEvent.kt +++ b/backend/data/src/main/kotlin/io/tolgee/events/user/UserAccountEvent.kt @@ -5,5 +5,5 @@ import org.springframework.context.ApplicationEvent abstract class UserAccountEvent( source: Any, - val userAccount: UserAccount + val userAccount: UserAccount, ) : ApplicationEvent(source) diff --git a/backend/data/src/main/kotlin/io/tolgee/exceptions/AuthenticationException.kt b/backend/data/src/main/kotlin/io/tolgee/exceptions/AuthenticationException.kt index 845306f628..43b35601f7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/exceptions/AuthenticationException.kt +++ b/backend/data/src/main/kotlin/io/tolgee/exceptions/AuthenticationException.kt @@ -5,7 +5,6 @@ import org.springframework.web.bind.annotation.ResponseStatus @ResponseStatus(HttpStatus.UNAUTHORIZED) class AuthenticationException(message: io.tolgee.constants.Message) : ErrorException(message) { - override val httpStatus: HttpStatus get() = HttpStatus.UNAUTHORIZED } diff --git a/backend/data/src/main/kotlin/io/tolgee/exceptions/ExceptionWithMessage.kt b/backend/data/src/main/kotlin/io/tolgee/exceptions/ExceptionWithMessage.kt index e841739f03..bdae753c54 100644 --- a/backend/data/src/main/kotlin/io/tolgee/exceptions/ExceptionWithMessage.kt +++ b/backend/data/src/main/kotlin/io/tolgee/exceptions/ExceptionWithMessage.kt @@ -6,9 +6,8 @@ import java.io.Serializable abstract class ExceptionWithMessage( private val _code: String? = null, val params: List? = null, - cause: Throwable? = null + cause: Throwable? = null, ) : RuntimeException("$_code $params", cause) { - var tolgeeMessage: Message? = null val code: String @@ -17,7 +16,7 @@ abstract class ExceptionWithMessage( constructor(message: Message, params: List? = null, cause: Throwable? = null) : this( message.code, params, - cause + cause, ) { this.tolgeeMessage = message } diff --git a/backend/data/src/main/kotlin/io/tolgee/exceptions/FileIssueException.kt b/backend/data/src/main/kotlin/io/tolgee/exceptions/FileIssueException.kt index 85e09f2972..18befde47d 100644 --- a/backend/data/src/main/kotlin/io/tolgee/exceptions/FileIssueException.kt +++ b/backend/data/src/main/kotlin/io/tolgee/exceptions/FileIssueException.kt @@ -4,5 +4,5 @@ import io.tolgee.model.dataImport.issues.issueTypes.FileIssueType class FileIssueException( val type: FileIssueType, - val params: List? = null + val params: List? = null, ) : Throwable() diff --git a/backend/data/src/main/kotlin/io/tolgee/exceptions/FileStoreException.kt b/backend/data/src/main/kotlin/io/tolgee/exceptions/FileStoreException.kt index 6c97515f28..8d9aee66ec 100644 --- a/backend/data/src/main/kotlin/io/tolgee/exceptions/FileStoreException.kt +++ b/backend/data/src/main/kotlin/io/tolgee/exceptions/FileStoreException.kt @@ -7,5 +7,5 @@ package io.tolgee.exceptions class FileStoreException( message: String, val storageFilePath: String, - val e: Exception? = null + val e: Exception? = null, ) : RuntimeException(message, e) diff --git a/backend/data/src/main/kotlin/io/tolgee/exceptions/FormalityNotSupportedException.kt b/backend/data/src/main/kotlin/io/tolgee/exceptions/FormalityNotSupportedException.kt index a027e03951..c8517987ab 100644 --- a/backend/data/src/main/kotlin/io/tolgee/exceptions/FormalityNotSupportedException.kt +++ b/backend/data/src/main/kotlin/io/tolgee/exceptions/FormalityNotSupportedException.kt @@ -5,5 +5,5 @@ import io.tolgee.constants.MtServiceType class FormalityNotSupportedException(val tag: String, val service: MtServiceType) : BadRequestException( Message.FORMALITY_NOT_SUPPORTED_BY_SERVICE, - params = listOf(tag, service) + params = listOf(tag, service), ) diff --git a/backend/data/src/main/kotlin/io/tolgee/exceptions/LanguageNotPermittedException.kt b/backend/data/src/main/kotlin/io/tolgee/exceptions/LanguageNotPermittedException.kt index 9157dda8f3..e457e5c456 100644 --- a/backend/data/src/main/kotlin/io/tolgee/exceptions/LanguageNotPermittedException.kt +++ b/backend/data/src/main/kotlin/io/tolgee/exceptions/LanguageNotPermittedException.kt @@ -6,5 +6,5 @@ import java.io.Serializable @Suppress("UNCHECKED_CAST") class LanguageNotPermittedException( val languageIds: List, - val languageTags: List? = null + val languageTags: List? = null, ) : PermissionException(Message.LANGUAGE_NOT_PERMITTED, listOf(languageIds, languageTags) as List?) diff --git a/backend/data/src/main/kotlin/io/tolgee/exceptions/LanguageNotSupportedException.kt b/backend/data/src/main/kotlin/io/tolgee/exceptions/LanguageNotSupportedException.kt index f2d967db60..fc2eb93fe2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/exceptions/LanguageNotSupportedException.kt +++ b/backend/data/src/main/kotlin/io/tolgee/exceptions/LanguageNotSupportedException.kt @@ -5,5 +5,5 @@ import io.tolgee.constants.MtServiceType class LanguageNotSupportedException(val tag: String, val service: MtServiceType) : BadRequestException( Message.LANGUAGE_NOT_SUPPORTED_BY_SERVICE, - params = listOf(tag, service) + params = listOf(tag, service), ) diff --git a/backend/data/src/main/kotlin/io/tolgee/exceptions/OutOfCreditsException.kt b/backend/data/src/main/kotlin/io/tolgee/exceptions/OutOfCreditsException.kt index 9f98b35a3a..270fd285bf 100644 --- a/backend/data/src/main/kotlin/io/tolgee/exceptions/OutOfCreditsException.kt +++ b/backend/data/src/main/kotlin/io/tolgee/exceptions/OutOfCreditsException.kt @@ -3,6 +3,6 @@ package io.tolgee.exceptions class OutOfCreditsException(val reason: Reason) : RuntimeException() { enum class Reason { OUT_OF_CREDITS, - SPENDING_LIMIT_EXCEEDED + SPENDING_LIMIT_EXCEEDED, } } diff --git a/backend/data/src/main/kotlin/io/tolgee/exceptions/PermissionException.kt b/backend/data/src/main/kotlin/io/tolgee/exceptions/PermissionException.kt index cdb28cc5d7..889c69bb31 100644 --- a/backend/data/src/main/kotlin/io/tolgee/exceptions/PermissionException.kt +++ b/backend/data/src/main/kotlin/io/tolgee/exceptions/PermissionException.kt @@ -7,7 +7,7 @@ import java.io.Serializable @ResponseStatus(HttpStatus.FORBIDDEN) open class PermissionException( message: io.tolgee.constants.Message = io.tolgee.constants.Message.OPERATION_NOT_PERMITTED, - params: List? = null + params: List? = null, ) : ErrorException(message, params) { override val httpStatus: HttpStatus get() = HttpStatus.FORBIDDEN diff --git a/backend/data/src/main/kotlin/io/tolgee/exceptions/PoParserException.kt b/backend/data/src/main/kotlin/io/tolgee/exceptions/PoParserException.kt index d69d7d4dea..98c45c793c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/exceptions/PoParserException.kt +++ b/backend/data/src/main/kotlin/io/tolgee/exceptions/PoParserException.kt @@ -1,6 +1,5 @@ package io.tolgee.exceptions class PoParserException(message: String = "Error", line: Int, position: Int) : Throwable() { - override val message = "$message on line $line, position: $position" } diff --git a/backend/data/src/main/kotlin/io/tolgee/exceptions/TranslationSpendingLimitExceeded.kt b/backend/data/src/main/kotlin/io/tolgee/exceptions/TranslationSpendingLimitExceeded.kt index 59b84f14ef..d03a502673 100644 --- a/backend/data/src/main/kotlin/io/tolgee/exceptions/TranslationSpendingLimitExceeded.kt +++ b/backend/data/src/main/kotlin/io/tolgee/exceptions/TranslationSpendingLimitExceeded.kt @@ -4,5 +4,6 @@ import io.tolgee.constants.Message class TranslationSpendingLimitExceeded(required: Long, limit: Long) : BadRequestException( - Message.TRANSLATION_SPENDING_LIMIT_EXCEEDED, params = listOf(required, limit) + Message.TRANSLATION_SPENDING_LIMIT_EXCEEDED, + params = listOf(required, limit), ) diff --git a/backend/data/src/main/kotlin/io/tolgee/exceptions/UnexpectedGoogleApiResponseException.kt b/backend/data/src/main/kotlin/io/tolgee/exceptions/UnexpectedGoogleApiResponseException.kt index d397d183e8..c2286262ea 100644 --- a/backend/data/src/main/kotlin/io/tolgee/exceptions/UnexpectedGoogleApiResponseException.kt +++ b/backend/data/src/main/kotlin/io/tolgee/exceptions/UnexpectedGoogleApiResponseException.kt @@ -4,5 +4,5 @@ import io.tolgee.service.security.ReCaptchaValidationService import org.springframework.http.ResponseEntity class UnexpectedGoogleApiResponseException( - val response: ResponseEntity + val response: ResponseEntity, ) : Throwable() diff --git a/backend/data/src/main/kotlin/io/tolgee/facade/ProjectPermissionFacade.kt b/backend/data/src/main/kotlin/io/tolgee/facade/ProjectPermissionFacade.kt index 1689ee7aaa..d7ea7fcab9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/facade/ProjectPermissionFacade.kt +++ b/backend/data/src/main/kotlin/io/tolgee/facade/ProjectPermissionFacade.kt @@ -12,9 +12,8 @@ import org.springframework.stereotype.Component @Component class ProjectPermissionFacade( private val authenticationFacade: AuthenticationFacade, - private val languageService: LanguageService + private val languageService: LanguageService, ) { - fun checkNotCurrentUser(userId: Long) { if (userId == authenticationFacade.authenticatedUser.id) { throw BadRequestException(Message.CANNOT_SET_YOUR_OWN_PERMISSIONS) @@ -23,7 +22,7 @@ class ProjectPermissionFacade( fun getLanguagesAndCheckFromProject( languages: Set?, - projectId: Long + projectId: Long, ): Set { languages?.let { val languageEntities = languageService.findByIdIn(languages) @@ -37,16 +36,22 @@ class ProjectPermissionFacade( return setOf() } - fun getLanguages(params: RequestWithLanguagePermissions, projectId: Long): LanguagePermissions { + fun getLanguages( + params: RequestWithLanguagePermissions, + projectId: Long, + ): LanguagePermissions { return LanguagePermissions( view = this.getLanguagesAndCheckFromProject(params.viewLanguages, projectId), - translate = this.getLanguagesAndCheckFromProject( - params.translateLanguages ?: params.languages, - projectId - ), - stateChange = this.getLanguagesAndCheckFromProject( - params.stateChangeLanguages, projectId - ) + translate = + this.getLanguagesAndCheckFromProject( + params.translateLanguages ?: params.languages, + projectId, + ), + stateChange = + this.getLanguagesAndCheckFromProject( + params.stateChangeLanguages, + projectId, + ), ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/jobs/migration/allOrganizationOwner/AllOrganizationOwnerJobConfiguration.kt b/backend/data/src/main/kotlin/io/tolgee/jobs/migration/allOrganizationOwner/AllOrganizationOwnerJobConfiguration.kt index 4c16ec4298..a3e5273a83 100644 --- a/backend/data/src/main/kotlin/io/tolgee/jobs/migration/allOrganizationOwner/AllOrganizationOwnerJobConfiguration.kt +++ b/backend/data/src/main/kotlin/io/tolgee/jobs/migration/allOrganizationOwner/AllOrganizationOwnerJobConfiguration.kt @@ -27,7 +27,6 @@ import org.springframework.transaction.PlatformTransactionManager @Suppress("SpringJavaInjectionPointsAutowiringInspection") @Configuration class AllOrganizationOwnerJobConfiguration { - companion object { const val JOB_NAME = "allOrganizationOwnerJob" const val STEP_SIZE = 100 @@ -67,35 +66,40 @@ class AllOrganizationOwnerJobConfiguration { } val noOrgProjectReader: ItemReader - get() = RepositoryItemReader().apply { - setRepository(projectRepository) - setMethodName(projectRepository::findAllWithUserOwner.name) - setSort(mapOf("id" to Direction.ASC)) - setPageSize(STEP_SIZE) - } - - val noOrgProjectWriter: ItemWriter = ItemWriter { items -> - items.forEach { project -> - val organization = organizationRepository.findUsersDefaultOrganization(project.userOwner!!) - ?: let { - val ownerName = project.userOwner!!.name - val ownerNameSafe = if (ownerName.length >= 3) ownerName else "$ownerName Organization" - organizationService.create( - OrganizationDto(name = ownerNameSafe), project.userOwner!! + get() = + RepositoryItemReader().apply { + setRepository(projectRepository) + setMethodName(projectRepository::findAllWithUserOwner.name) + setSort(mapOf("id" to Direction.ASC)) + setPageSize(STEP_SIZE) + } + + val noOrgProjectWriter: ItemWriter = + ItemWriter { items -> + items.forEach { project -> + val organization = + organizationRepository.findUsersDefaultOrganization(project.userOwner!!) + ?: let { + val ownerName = project.userOwner!!.name + val ownerNameSafe = if (ownerName.length >= 3) ownerName else "$ownerName Organization" + organizationService.create( + OrganizationDto(name = ownerNameSafe), + project.userOwner!!, + ) + } + + val permission = + permissionService.find( + projectId = project.id, + userId = project.userOwner!!.id, ) - } + permission?.let { permissionService.delete(it.id) } - val permission = permissionService.find( - projectId = project.id, - userId = project.userOwner!!.id - ) - permission?.let { permissionService.delete(it.id) } - - project.organizationOwner = organization - project.userOwner = null - projectService.save(project) + project.organizationOwner = organization + project.userOwner = null + projectService.save(project) + } } - } fun getNoOrgProjectsStep(jobRepository: JobRepository): Step { return StepBuilder("noOrProjectStep", jobRepository) @@ -106,22 +110,25 @@ class AllOrganizationOwnerJobConfiguration { } val noRoleUserReader: ItemReader - get() = RepositoryItemReader().apply { - setRepository(userAccountRepository) - setMethodName(userAccountRepository::findAllWithoutAnyOrganization.name) - setSort(mapOf("id" to Direction.ASC)) - setPageSize(STEP_SIZE) + get() = + RepositoryItemReader().apply { + setRepository(userAccountRepository) + setMethodName(userAccountRepository::findAllWithoutAnyOrganization.name) + setSort(mapOf("id" to Direction.ASC)) + setPageSize(STEP_SIZE) + } + + val noRoleUserWriter: ItemWriter = + ItemWriter { items -> + items.forEach { userAccount -> + organizationService.create(OrganizationDto(name = userAccount.name), userAccount) + } } - val noRoleUserWriter: ItemWriter = ItemWriter { items -> - items.forEach { userAccount -> - organizationService.create(OrganizationDto(name = userAccount.name), userAccount) - } - } - - fun getNoRoleUserStep(jobRepository: JobRepository): Step = StepBuilder("noRoleUserStep", jobRepository) - .chunk(STEP_SIZE, platformTransactionManager) - .reader(noRoleUserReader) - .writer(noRoleUserWriter) - .build() + fun getNoRoleUserStep(jobRepository: JobRepository): Step = + StepBuilder("noRoleUserStep", jobRepository) + .chunk(STEP_SIZE, platformTransactionManager) + .reader(noRoleUserReader) + .writer(noRoleUserWriter) + .build() } diff --git a/backend/data/src/main/kotlin/io/tolgee/jobs/migration/allOrganizationOwner/AllOrganizationOwnerJobRunner.kt b/backend/data/src/main/kotlin/io/tolgee/jobs/migration/allOrganizationOwner/AllOrganizationOwnerJobRunner.kt index c2834fb086..0a21b822e8 100644 --- a/backend/data/src/main/kotlin/io/tolgee/jobs/migration/allOrganizationOwner/AllOrganizationOwnerJobRunner.kt +++ b/backend/data/src/main/kotlin/io/tolgee/jobs/migration/allOrganizationOwner/AllOrganizationOwnerJobRunner.kt @@ -25,9 +25,8 @@ class AllOrganizationOwnerJobRunner( val jobLauncher: JobLauncher, val projectRepository: ProjectRepository, val userAccountRepository: UserAccountRepository, - val jobRepository: JobRepository + val jobRepository: JobRepository, ) : MigrationJobRunner { - val log = LoggerFactory.getLogger(this::class.java) override fun run(): JobExecution? { diff --git a/backend/data/src/main/kotlin/io/tolgee/jobs/migration/translationStats/TranslationProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/jobs/migration/translationStats/TranslationProcessor.kt index 42b53a133e..262e9f7c8e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/jobs/migration/translationStats/TranslationProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/jobs/migration/translationStats/TranslationProcessor.kt @@ -6,8 +6,9 @@ import org.springframework.batch.item.ItemProcessor class TranslationProcessor : ItemProcessor { override fun process(item: StatsMigrationTranslationView): TranslationStats { return TranslationStats( - id = item.id, wordCount = TranslationStatsUtil.getWordCount(item.text, item.languageTag), - characterCount = TranslationStatsUtil.getCharacterCount(item.text) + id = item.id, + wordCount = TranslationStatsUtil.getWordCount(item.text, item.languageTag), + characterCount = TranslationStatsUtil.getCharacterCount(item.text), ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/jobs/migration/translationStats/TranslationStats.kt b/backend/data/src/main/kotlin/io/tolgee/jobs/migration/translationStats/TranslationStats.kt index 8973bfb018..335b279794 100644 --- a/backend/data/src/main/kotlin/io/tolgee/jobs/migration/translationStats/TranslationStats.kt +++ b/backend/data/src/main/kotlin/io/tolgee/jobs/migration/translationStats/TranslationStats.kt @@ -3,5 +3,5 @@ package io.tolgee.jobs.migration.translationStats class TranslationStats( val id: Long, val wordCount: Int, - val characterCount: Int + val characterCount: Int, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/jobs/migration/translationStats/TranslationStatsJobConfiguration.kt b/backend/data/src/main/kotlin/io/tolgee/jobs/migration/translationStats/TranslationStatsJobConfiguration.kt index 27a4fa5759..2fe85bcb44 100644 --- a/backend/data/src/main/kotlin/io/tolgee/jobs/migration/translationStats/TranslationStatsJobConfiguration.kt +++ b/backend/data/src/main/kotlin/io/tolgee/jobs/migration/translationStats/TranslationStatsJobConfiguration.kt @@ -20,7 +20,6 @@ import javax.sql.DataSource @Suppress("SpringJavaInjectionPointsAutowiringInspection") @Configuration class TranslationStatsJobConfiguration { - companion object { const val JOB_NAME = "translationStatsJob" } @@ -49,30 +48,34 @@ class TranslationStatsJobConfiguration { } val reader: ItemReader - get() = RepositoryItemReader().apply { - setRepository(translationRepository) - setMethodName(translationRepository::findAllForStatsUpdate.name) - setSort(mapOf("id" to Sort.Direction.ASC)) - setPageSize(100) - } + get() = + RepositoryItemReader().apply { + setRepository(translationRepository) + setMethodName(translationRepository::findAllForStatsUpdate.name) + setSort(mapOf("id" to Sort.Direction.ASC)) + setPageSize(100) + } - val writer: ItemWriter = ItemWriter { items -> - items.forEach { - val query = entityManager.createNativeQuery( - "UPDATE translation set word_count = :wordCount, character_count = :characterCount where id = :id" - ) - query.setParameter("wordCount", it.wordCount) - query.setParameter("characterCount", it.characterCount) - query.setParameter("id", it.id) - query.executeUpdate() + val writer: ItemWriter = + ItemWriter { items -> + items.forEach { + val query = + entityManager.createNativeQuery( + "UPDATE translation set word_count = :wordCount, character_count = :characterCount where id = :id", + ) + query.setParameter("wordCount", it.wordCount) + query.setParameter("characterCount", it.characterCount) + query.setParameter("id", it.id) + query.executeUpdate() + } } - } val step: Step - get() = StepBuilder("step", jobRepository) - .chunk(100, platformTransactionManager) - .reader(reader) - .processor(TranslationProcessor()) - .writer(writer) - .build() + get() = + StepBuilder("step", jobRepository) + .chunk(100, platformTransactionManager) + .reader(reader) + .processor(TranslationProcessor()) + .writer(writer) + .build() } diff --git a/backend/data/src/main/kotlin/io/tolgee/jobs/migration/translationStats/TranslationsStatsUpdateJobRunner.kt b/backend/data/src/main/kotlin/io/tolgee/jobs/migration/translationStats/TranslationsStatsUpdateJobRunner.kt index 2c03d47d93..8d59124793 100644 --- a/backend/data/src/main/kotlin/io/tolgee/jobs/migration/translationStats/TranslationsStatsUpdateJobRunner.kt +++ b/backend/data/src/main/kotlin/io/tolgee/jobs/migration/translationStats/TranslationsStatsUpdateJobRunner.kt @@ -22,9 +22,8 @@ class TranslationsStatsUpdateJobRunner( val translationStatsJob: Job, val jobLauncher: JobLauncher, val translationRepository: TranslationRepository, - val jobRepository: JobRepository + val jobRepository: JobRepository, ) : MigrationJobRunner { - val log = LoggerFactory.getLogger(this::class.java) override fun run(): JobExecution? { diff --git a/backend/data/src/main/kotlin/io/tolgee/model/ApiKey.kt b/backend/data/src/main/kotlin/io/tolgee/model/ApiKey.kt index 41e0b27ff4..28edf4034f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/ApiKey.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/ApiKey.kt @@ -21,24 +21,22 @@ import java.util.* @Table( uniqueConstraints = [ UniqueConstraint(columnNames = ["keyHash"], name = "api_key_hash_unique"), - UniqueConstraint(columnNames = ["key"], name = "api_key_unique") - ] + UniqueConstraint(columnNames = ["key"], name = "api_key_unique"), + ], ) class ApiKey( @Column(updatable = false, insertable = false, nullable = true) var key: String? = null, - - @NotNull - @NotEmpty - @Enumerated(EnumType.STRING) - @field:ElementCollection(targetClass = Scope::class, fetch = FetchType.EAGER) /** * Scope should be never nullable, butthere were entries with null scopes in the production DB, which caused NPEs, * so to be sure, lets meke it nullable */ - var scopesEnum: MutableSet + @NotNull + @NotEmpty + @Enumerated(EnumType.STRING) + @field:ElementCollection(targetClass = Scope::class, fetch = FetchType.EAGER) + var scopesEnum: MutableSet, ) : StandardAuditModel() { - @field:NotBlank var description: String = "" @@ -69,7 +67,7 @@ class ApiKey( key: String, scopesEnum: Set, userAccount: UserAccount, - project: Project + project: Project, ) : this(key, scopesEnum.toMutableSet()) { this.userAccount = userAccount this.project = project diff --git a/backend/data/src/main/kotlin/io/tolgee/model/DismissedAnnouncement.kt b/backend/data/src/main/kotlin/io/tolgee/model/DismissedAnnouncement.kt index 8a7dda5179..1bd524cab5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/DismissedAnnouncement.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/DismissedAnnouncement.kt @@ -1,7 +1,13 @@ package io.tolgee.model import io.tolgee.model.enums.Announcement -import jakarta.persistence.* +import jakarta.persistence.Entity +import jakarta.persistence.EnumType +import jakarta.persistence.Enumerated +import jakarta.persistence.FetchType +import jakarta.persistence.Id +import jakarta.persistence.IdClass +import jakarta.persistence.ManyToOne import java.io.Serializable @Entity @@ -10,8 +16,7 @@ class DismissedAnnouncement( @Id @ManyToOne(fetch = FetchType.LAZY) var user: UserAccount, - @Id @Enumerated(EnumType.STRING) - var announcement: Announcement + var announcement: Announcement, ) : Serializable diff --git a/backend/data/src/main/kotlin/io/tolgee/model/DismissedAnnouncementId.kt b/backend/data/src/main/kotlin/io/tolgee/model/DismissedAnnouncementId.kt index 40177d3a1d..990de1f760 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/DismissedAnnouncementId.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/DismissedAnnouncementId.kt @@ -5,5 +5,5 @@ import java.io.Serializable data class DismissedAnnouncementId( val user: Long? = null, - val announcement: Announcement? = null + val announcement: Announcement? = null, ) : Serializable diff --git a/backend/data/src/main/kotlin/io/tolgee/model/EmailVerification.kt b/backend/data/src/main/kotlin/io/tolgee/model/EmailVerification.kt index f5aaeb7513..3c0cd8b330 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/EmailVerification.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/EmailVerification.kt @@ -15,12 +15,10 @@ data class EmailVerification( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id: Long? = null, - @NotBlank var code: String? = null, - @Email - var newEmail: String? = null + var newEmail: String? = null, ) : AuditModel() { @Suppress("JoinDeclarationAndAssignment") @OneToOne(optional = false) @@ -30,9 +28,9 @@ data class EmailVerification( id: Long? = null, @NotBlank code: String, userAccount: UserAccount, - newEmail: String? = null + newEmail: String? = null, ) : this(id = id, code = code, newEmail = newEmail) { - this.userAccount = userAccount - } + this.userAccount = userAccount + } } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/Invitation.kt b/backend/data/src/main/kotlin/io/tolgee/model/Invitation.kt index f40d51b8bf..b5765a136f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/Invitation.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/Invitation.kt @@ -13,23 +13,26 @@ import jakarta.validation.constraints.NotBlank @Entity @Table( uniqueConstraints = [ - UniqueConstraint(columnNames = ["code"], name = "invitation_code_unique") - ] + UniqueConstraint(columnNames = ["code"], name = "invitation_code_unique"), + ], ) class Invitation( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id: Long? = null, - var code: @NotBlank String + var code: @NotBlank String, ) : AuditModel() { - @OneToOne(mappedBy = "invitation", cascade = [CascadeType.ALL]) var permission: Permission? = null @OneToOne(mappedBy = "invitation", cascade = [CascadeType.ALL]) var organizationRole: OrganizationRole? = null - constructor(id: Long?, @NotBlank code: String, permission: Permission?) : this(id = id, code = code) { + constructor( + id: Long?, + @NotBlank code: String, + permission: Permission?, + ) : this(id = id, code = code) { this.permission = permission } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/Language.kt b/backend/data/src/main/kotlin/io/tolgee/model/Language.kt index b5274f9cd2..44a775cd53 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/Language.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/Language.kt @@ -10,7 +10,18 @@ import io.tolgee.events.OnLanguagePreRemove import io.tolgee.model.mtServiceConfig.MtServiceConfig import io.tolgee.model.translation.Translation import io.tolgee.service.dataImport.ImportService -import jakarta.persistence.* +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.EntityListeners +import jakarta.persistence.FetchType +import jakarta.persistence.Index +import jakarta.persistence.ManyToOne +import jakarta.persistence.OneToMany +import jakarta.persistence.OneToOne +import jakarta.persistence.PrePersist +import jakarta.persistence.PreRemove +import jakarta.persistence.Table +import jakarta.persistence.UniqueConstraint import jakarta.validation.constraints.NotEmpty import jakarta.validation.constraints.Size import org.springframework.beans.factory.ObjectFactory @@ -25,25 +36,24 @@ import org.springframework.transaction.annotation.Transactional uniqueConstraints = [ UniqueConstraint( columnNames = ["project_id", "name"], - name = "language_project_name" + name = "language_project_name", ), UniqueConstraint( columnNames = ["project_id", "tag"], - name = "language_tag_name" - ) + name = "language_tag_name", + ), ], indexes = [ Index( columnList = "tag", - name = "index_tag" + name = "index_tag", ), Index( columnList = "tag, project_id", - name = "index_tag_project" - ) - ] + name = "index_tag_project", + ), + ], ) - @ActivityLoggedEntity @ActivityReturnsExistence class Language : StandardAuditModel() { diff --git a/backend/data/src/main/kotlin/io/tolgee/model/LanguageStats.kt b/backend/data/src/main/kotlin/io/tolgee/model/LanguageStats.kt index 681ee2a215..1355f8136e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/LanguageStats.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/LanguageStats.kt @@ -13,9 +13,8 @@ import jakarta.persistence.UniqueConstraint @Table(uniqueConstraints = [UniqueConstraint(columnNames = ["language_id"], name = "language_stats_language_id_key")]) class LanguageStats( @OneToOne - val language: Language + val language: Language, ) : StandardAuditModel() { - var untranslatedWords: Long = 0 var translatedWords: Long = 0 diff --git a/backend/data/src/main/kotlin/io/tolgee/model/MtCreditBucket.kt b/backend/data/src/main/kotlin/io/tolgee/model/MtCreditBucket.kt index 6e6080f0f6..01e72982ae 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/MtCreditBucket.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/MtCreditBucket.kt @@ -11,17 +11,15 @@ import java.util.* @Table( uniqueConstraints = [ UniqueConstraint(columnNames = ["organization_id"], name = "mt_credit_bucket_organization_unique"), - ] + ], ) class MtCreditBucket( @OneToOne @Deprecated("Only organization can own a credit bucket...") var userAccount: UserAccount? = null, - @OneToOne - var organization: Organization? = null + var organization: Organization? = null, ) : StandardAuditModel() { - var credits: Long = 0 /** diff --git a/backend/data/src/main/kotlin/io/tolgee/model/Organization.kt b/backend/data/src/main/kotlin/io/tolgee/model/Organization.kt index fcccda0b39..5e0eb880d0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/Organization.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/Organization.kt @@ -22,26 +22,24 @@ import java.util.* @Table( uniqueConstraints = [ UniqueConstraint(columnNames = ["address_part"], name = "organization_address_part_unique"), - ] + ], ) class Organization( - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) override var id: Long = 0, - - @field:NotBlank @field:Size(min = 1, max = 50) + @field:NotBlank + @field:Size(min = 1, max = 50) open var name: String = "", - open var description: String? = null, - @Column(name = "address_part") - @field:NotBlank @field:Size(min = 1, max = 60) + @field:NotBlank + @field:Size(min = 1, max = 60) @field:Pattern(regexp = "^[a-z0-9-]*[a-z]+[a-z0-9-_]*$", message = "invalid_pattern") open var slug: String = "", - @OneToOne(mappedBy = "organization", cascade = [CascadeType.REMOVE], fetch = FetchType.LAZY) - var mtCreditBucket: MtCreditBucket? = null + var mtCreditBucket: MtCreditBucket? = null, ) : ModelWithAvatar, AuditModel(), SoftDeletable { - @OneToOne(mappedBy = "organization", optional = false, orphanRemoval = true) lateinit var basePermission: Permission @@ -52,7 +50,7 @@ class Organization( @OneToMany(mappedBy = "organizationOwner") @field:Filter( name = "deletedFilter", - condition = "(deleted_at IS NULL)" + condition = "(deleted_at IS NULL)", ) var projects: MutableList = mutableListOf() diff --git a/backend/data/src/main/kotlin/io/tolgee/model/OrganizationRole.kt b/backend/data/src/main/kotlin/io/tolgee/model/OrganizationRole.kt index 7334de0940..f56aa636a0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/OrganizationRole.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/OrganizationRole.kt @@ -15,23 +15,21 @@ import jakarta.validation.constraints.NotNull uniqueConstraints = [ UniqueConstraint( columnNames = ["user_id", "organization_id"], - name = "organization_member_role_user_organization_unique" - ) - ] + name = "organization_member_role_user_organization_unique", + ), + ], ) class OrganizationRole( @OneToOne var invitation: Invitation? = null, - @Enumerated(EnumType.ORDINAL) - var type: OrganizationRoleType? = null + var type: OrganizationRoleType? = null, ) : StandardAuditModel() { - constructor( user: UserAccount? = null, invitation: Invitation? = null, organization: Organization?, - type: OrganizationRoleType? + type: OrganizationRoleType?, ) : this(invitation, type) { this.organization = organization this.user = user diff --git a/backend/data/src/main/kotlin/io/tolgee/model/Pat.kt b/backend/data/src/main/kotlin/io/tolgee/model/Pat.kt index a925afe43d..b2f54309a0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/Pat.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/Pat.kt @@ -16,21 +16,16 @@ class Pat( @field:NotEmpty @field:NotNull var tokenHash: String = "", - @field:NotEmpty @field:NotNull var description: String = "", - @Temporal(value = TemporalType.TIMESTAMP) var expiresAt: Date? = null, - @Temporal(value = TemporalType.TIMESTAMP) var lastUsedAt: Date? = null, - @Transient - var token: String? = null + var token: String? = null, ) : StandardAuditModel() { - @ManyToOne @NotNull lateinit var userAccount: UserAccount diff --git a/backend/data/src/main/kotlin/io/tolgee/model/Permission.kt b/backend/data/src/main/kotlin/io/tolgee/model/Permission.kt index 1de59a9e96..411b7018b4 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/Permission.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/Permission.kt @@ -31,16 +31,13 @@ class Permission( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id: Long = 0L, - @ManyToOne(fetch = FetchType.LAZY) var user: UserAccount? = null, - /** * When base permission for organization */ @OneToOne(fetch = FetchType.LAZY) var organization: Organization? = null, - @OneToOne(fetch = FetchType.LAZY) var invitation: Invitation? = null, ) : AuditModel(), IPermission { @@ -49,9 +46,9 @@ class Permission( parameters = [ Parameter( name = EnumArrayType.SQL_ARRAY_TYPE, - value = "varchar" - ) - ] + value = "varchar", + ), + ], ) @Column(name = "scopes", columnDefinition = "varchar[]") private var _scopes: Array? = null @@ -108,12 +105,12 @@ class Permission( organization: Organization? = null, type: ProjectPermissionType? = ProjectPermissionType.VIEW, languagePermissions: LanguagePermissions? = null, - scopes: Array? = null + scopes: Array? = null, ) : this( id = id, user = user, organization = null, - invitation = invitation + invitation = invitation, ) { this._scopes = scopes this.project = project @@ -145,7 +142,6 @@ class Permission( get() = this.stateChangeLanguages.map { it.id }.toSet() companion object { - class PermissionListeners { @PrePersist @PreUpdate @@ -157,9 +153,9 @@ class Permission( throw IllegalStateException("Exactly one of scopes or type has to be set") } if (permission.organization != null && ( - permission.viewLanguages.isNotEmpty() || - permission.translateLanguages.isNotEmpty() || - permission.stateChangeLanguages.isNotEmpty() + permission.viewLanguages.isNotEmpty() || + permission.translateLanguages.isNotEmpty() || + permission.stateChangeLanguages.isNotEmpty() ) ) { throw IllegalStateException("Organization base permission cannot have language permissions") diff --git a/backend/data/src/main/kotlin/io/tolgee/model/Project.kt b/backend/data/src/main/kotlin/io/tolgee/model/Project.kt index 01a1fa9d6d..2b595981cb 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/Project.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/Project.kt @@ -37,16 +37,13 @@ class Project( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) override var id: Long = 0L, - @field:NotBlank @field:Size(min = 3, max = 50) @ActivityLoggedProp var name: String = "", - @field:Size(min = 3, max = 2000) @ActivityLoggedProp var description: String? = null, - @Column(name = "address_part") @ActivityLoggedProp @field:Size(min = 3, max = 60) @@ -109,8 +106,8 @@ class Project( constructor(name: String, description: String? = null, slug: String?, organizationOwner: Organization) : this(id = 0L, name, description, slug) { - this.organizationOwner = organizationOwner - } + this.organizationOwner = organizationOwner + } fun findLanguageOptional(tag: String): Optional { return languages.stream().filter { l: Language -> (l.tag == tag) }.findFirst() diff --git a/backend/data/src/main/kotlin/io/tolgee/model/QuickStart.kt b/backend/data/src/main/kotlin/io/tolgee/model/QuickStart.kt index 3d39f31f36..13e41de334 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/QuickStart.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/QuickStart.kt @@ -17,7 +17,6 @@ data class QuickStart( @JoinColumn(name = "user_account_id") var userAccount: UserAccount, ) { - @Id @Column(name = "user_account_id") var userAccountId: Long = 0 diff --git a/backend/data/src/main/kotlin/io/tolgee/model/StandardAuditModel.kt b/backend/data/src/main/kotlin/io/tolgee/model/StandardAuditModel.kt index 4949890de1..8bca59eeca 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/StandardAuditModel.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/StandardAuditModel.kt @@ -17,11 +17,11 @@ abstract class StandardAuditModel : AuditModel(), EntityWithId { name = "sequenceGenerator", sequenceName = SEQUENCE_NAME, initialValue = 1000000000, - allocationSize = ALLOCATION_SIZE + allocationSize = ALLOCATION_SIZE, ) @GeneratedValue( strategy = GenerationType.SEQUENCE, - generator = "sequenceGenerator" + generator = "sequenceGenerator", ) override var id: Long = 0 diff --git a/backend/data/src/main/kotlin/io/tolgee/model/UploadedImage.kt b/backend/data/src/main/kotlin/io/tolgee/model/UploadedImage.kt index 6338e78999..a6a979c5db 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/UploadedImage.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/UploadedImage.kt @@ -15,13 +15,11 @@ import org.hibernate.annotations.ColumnDefault @Table(uniqueConstraints = [UniqueConstraint(columnNames = ["filename"], name = "uploaded_image_filename")]) class UploadedImage( var filename: String, - @ManyToOne(fetch = FetchType.LAZY) - var userAccount: UserAccount + var userAccount: UserAccount, ) : StandardAuditModel() { - - @ColumnDefault("jpg") // legacy is jpg, new is png + @ColumnDefault("jpg") var extension: String? = null get() = field ?: "jpg" diff --git a/backend/data/src/main/kotlin/io/tolgee/model/UserAccount.kt b/backend/data/src/main/kotlin/io/tolgee/model/UserAccount.kt index 1d0211c906..53d995607c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/UserAccount.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/UserAccount.kt @@ -23,17 +23,12 @@ data class UserAccount( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) override var id: Long = 0L, - @field:NotBlank var username: String = "", - var password: String? = null, - var name: String = "", - @Enumerated(EnumType.STRING) var role: Role? = Role.USER, - @Enumerated(EnumType.STRING) @Column(name = "account_type") var accountType: AccountType? = AccountType.LOCAL, @@ -111,7 +106,7 @@ data class UserAccount( accountType: AccountType = AccountType.LOCAL, thirdPartyAuthType: String?, thirdPartyAuthId: String?, - resetPasswordCode: String? + resetPasswordCode: String?, ) : this(id = 0L, username = "", password, name = "") { this.permissions = permissions this.role = role @@ -122,10 +117,13 @@ data class UserAccount( } enum class Role { - USER, ADMIN + USER, + ADMIN, } enum class AccountType { - LOCAL, MANAGED, THIRD_PARTY + LOCAL, + MANAGED, + THIRD_PARTY, } } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/UserPreferences.kt b/backend/data/src/main/kotlin/io/tolgee/model/UserPreferences.kt index ec16c274d3..ee30abc61d 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/UserPreferences.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/UserPreferences.kt @@ -15,7 +15,6 @@ class UserPreferences( @JoinColumn(name = "user_account_id") var userAccount: UserAccount, ) : AuditModel() { - constructor(userAccount: UserAccount, preferredOrganization: Organization?) : this(userAccount) { this.preferredOrganization = preferredOrganization } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityDescribingEntity.kt b/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityDescribingEntity.kt index d00e96f3ec..f2d28ac8f0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityDescribingEntity.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityDescribingEntity.kt @@ -19,14 +19,11 @@ class ActivityDescribingEntity( @Id @NotFound(action = NotFoundAction.IGNORE) val activityRevision: ActivityRevision, - @Id val entityClass: String, - @Id - val entityId: Long + val entityId: Long, ) : Serializable { - @Column(columnDefinition = "jsonb") @Type(JsonBinaryType::class) var data: Map = mutableMapOf() diff --git a/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityDescribingEntityId.kt b/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityDescribingEntityId.kt index 40899ef043..ef20b7e203 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityDescribingEntityId.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityDescribingEntityId.kt @@ -3,5 +3,5 @@ package io.tolgee.model.activity data class ActivityDescribingEntityId( var activityRevision: Long? = null, var entityClass: String? = null, - var entityId: Long? = null + var entityId: Long? = null, ) : java.io.Serializable diff --git a/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityModifiedEntity.kt b/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityModifiedEntity.kt index c35436d43e..93d5a096d5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityModifiedEntity.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityModifiedEntity.kt @@ -22,21 +22,18 @@ class ActivityModifiedEntity( @ManyToOne @Id val activityRevision: ActivityRevision, - /** * Class of the modified entity * e.g. Translation, Key */ @Id val entityClass: String, - /** * ID of the modified entity */ @Id - val entityId: Long + val entityId: Long, ) : Serializable { - /** * Map of field to object containing old and new values */ diff --git a/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityModifiedEntityId.kt b/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityModifiedEntityId.kt index 80946c9fd2..2e7b54e617 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityModifiedEntityId.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityModifiedEntityId.kt @@ -3,5 +3,5 @@ package io.tolgee.model.activity data class ActivityModifiedEntityId( var activityRevision: Long? = null, var entityClass: String? = null, - var entityId: Long? = null + var entityId: Long? = null, ) : java.io.Serializable diff --git a/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityRevision.kt b/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityRevision.kt index 320bdad8d0..ff81687338 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityRevision.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/activity/ActivityRevision.kt @@ -33,22 +33,21 @@ import java.util.* indexes = [ Index(columnList = "projectId"), Index(columnList = "authorId"), - Index(columnList = "type") - ] + Index(columnList = "type"), + ], ) @EntityListeners(ActivityRevision.Companion.ActivityRevisionListener::class) class ActivityRevision : java.io.Serializable { - @Id @SequenceGenerator( name = "activitySequenceGenerator", sequenceName = "activity_sequence", initialValue = 0, - allocationSize = 10 + allocationSize = 10, ) @GeneratedValue( strategy = GenerationType.SEQUENCE, - generator = "activitySequenceGenerator" + generator = "activitySequenceGenerator", ) val id: Long = 0 diff --git a/backend/data/src/main/kotlin/io/tolgee/model/automations/Automation.kt b/backend/data/src/main/kotlin/io/tolgee/model/automations/Automation.kt index 69d6095fbf..40622de437 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/automations/Automation.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/automations/Automation.kt @@ -12,7 +12,6 @@ class Automation( @ManyToOne(fetch = FetchType.LAZY) var project: Project, ) : StandardAuditModel() { - @OneToMany(mappedBy = "automation", orphanRemoval = true) var triggers: MutableList = mutableListOf() diff --git a/backend/data/src/main/kotlin/io/tolgee/model/automations/AutomationActionType.kt b/backend/data/src/main/kotlin/io/tolgee/model/automations/AutomationActionType.kt index a65abedc30..0a1f8a925c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/automations/AutomationActionType.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/automations/AutomationActionType.kt @@ -6,8 +6,8 @@ import io.tolgee.component.automations.processors.WebhookProcessor import kotlin.reflect.KClass enum class AutomationActionType( - val processor: KClass + val processor: KClass, ) { CONTENT_DELIVERY_PUBLISH(ContentDeliveryPublishProcessor::class), - WEBHOOK(WebhookProcessor::class) + WEBHOOK(WebhookProcessor::class), } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/batch/BatchJob.kt b/backend/data/src/main/kotlin/io/tolgee/model/batch/BatchJob.kt index 234e4925a6..64837a701b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/batch/BatchJob.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/batch/BatchJob.kt @@ -71,7 +71,9 @@ class BatchJob : StandardAuditModel(), IBatchJob { var debouncingKey: String? = null companion object { - fun chunkTarget(chunkSize: Int, target: List): List> = - if (chunkSize == 0) listOf(target) else target.chunked(chunkSize) + fun chunkTarget( + chunkSize: Int, + target: List, + ): List> = if (chunkSize == 0) listOf(target) else target.chunked(chunkSize) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/batch/BatchJobChunkExecution.kt b/backend/data/src/main/kotlin/io/tolgee/model/batch/BatchJobChunkExecution.kt index 226e8d58e3..1d189d1d90 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/batch/BatchJobChunkExecution.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/batch/BatchJobChunkExecution.kt @@ -22,7 +22,7 @@ import java.util.* indexes = [ jakarta.persistence.Index(columnList = "chunkNumber"), jakarta.persistence.Index(columnList = "status"), - ] + ], ) class BatchJobChunkExecution : StandardAuditModel() { @ManyToOne(fetch = FetchType.LAZY, optional = false) diff --git a/backend/data/src/main/kotlin/io/tolgee/model/batch/BatchJobChunkExecutionStatus.kt b/backend/data/src/main/kotlin/io/tolgee/model/batch/BatchJobChunkExecutionStatus.kt index 486b6d2522..0d7876e010 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/batch/BatchJobChunkExecutionStatus.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/batch/BatchJobChunkExecutionStatus.kt @@ -1,7 +1,7 @@ package io.tolgee.model.batch enum class BatchJobChunkExecutionStatus( - val completed: Boolean + val completed: Boolean, ) { PENDING(false), RUNNING(false), diff --git a/backend/data/src/main/kotlin/io/tolgee/model/batch/BatchJobStatus.kt b/backend/data/src/main/kotlin/io/tolgee/model/batch/BatchJobStatus.kt index c23289d493..a77881c085 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/batch/BatchJobStatus.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/batch/BatchJobStatus.kt @@ -1,7 +1,7 @@ package io.tolgee.model.batch enum class BatchJobStatus( - val completed: Boolean + val completed: Boolean, ) { PENDING(false), RUNNING(false), diff --git a/backend/data/src/main/kotlin/io/tolgee/model/batch/params/PreTranslationByTmJobParams.kt b/backend/data/src/main/kotlin/io/tolgee/model/batch/params/PreTranslationByTmJobParams.kt index d1a685ec8f..cb505d8128 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/batch/params/PreTranslationByTmJobParams.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/batch/params/PreTranslationByTmJobParams.kt @@ -3,7 +3,6 @@ package io.tolgee.model.batch.params import io.tolgee.constants.MtServiceType class PreTranslationByTmJobParams { - var targetLanguageIds: List = mutableListOf() var service: MtServiceType? = null diff --git a/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/AzureFrontDoorConfig.kt b/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/AzureFrontDoorConfig.kt index 37906b7cde..48c71b4ec1 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/AzureFrontDoorConfig.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/AzureFrontDoorConfig.kt @@ -14,6 +14,7 @@ interface AzureFrontDoorConfig : ContentDeliveryPurgingConfig { get() = ContentDeliveryCachePurgingType.AZURE_FRONT_DOOR override val enabled: Boolean - get() = arrayOf(clientId, clientSecret, tenantId, subscriptionId, profileName, endpointName, resourceGroupName) - .all { it != null } + get() = + arrayOf(clientId, clientSecret, tenantId, subscriptionId, profileName, endpointName, resourceGroupName) + .all { it != null } } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/ContentDeliveryCachePurgingType.kt b/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/ContentDeliveryCachePurgingType.kt index c681b9da99..06350456bb 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/ContentDeliveryCachePurgingType.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/ContentDeliveryCachePurgingType.kt @@ -5,5 +5,5 @@ import io.tolgee.component.contentDelivery.cachePurging.ContentDeliveryCachePurg import kotlin.reflect.KClass enum class ContentDeliveryCachePurgingType(val factory: KClass) { - AZURE_FRONT_DOOR(AzureContentDeliveryCachePurgingFactory::class) + AZURE_FRONT_DOOR(AzureContentDeliveryCachePurgingFactory::class), } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/ContentDeliveryConfig.kt b/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/ContentDeliveryConfig.kt index 7a0658cee5..ea47214002 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/ContentDeliveryConfig.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/ContentDeliveryConfig.kt @@ -19,7 +19,7 @@ import java.util.* @Entity @Table( - uniqueConstraints = [UniqueConstraint(columnNames = ["project_id", "slug"])] + uniqueConstraints = [UniqueConstraint(columnNames = ["project_id", "slug"])], ) class ContentDeliveryConfig( @ManyToOne(fetch = FetchType.LAZY) @@ -56,10 +56,11 @@ class ContentDeliveryConfig( @Type(JsonBinaryType::class) @Column(columnDefinition = "jsonb") - override var filterState: List? = listOf( - TranslationState.TRANSLATED, - TranslationState.REVIEWED, - ) + override var filterState: List? = + listOf( + TranslationState.TRANSLATED, + TranslationState.REVIEWED, + ) @Type(JsonBinaryType::class) @Column(columnDefinition = "jsonb") diff --git a/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/ContentStorage.kt b/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/ContentStorage.kt index b6e475775c..6239158246 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/ContentStorage.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/ContentStorage.kt @@ -12,11 +12,9 @@ import jakarta.validation.constraints.NotBlank class ContentStorage( @ManyToOne(fetch = FetchType.LAZY) var project: Project, - @NotBlank - var name: String + var name: String, ) : StandardAuditModel() { - var publicUrlPrefix: String? = null @OneToOne(mappedBy = "contentStorage", optional = true, orphanRemoval = true) diff --git a/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/ContentStorageType.kt b/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/ContentStorageType.kt index 0ef51d4196..07c0531d51 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/ContentStorageType.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/contentDelivery/ContentStorageType.kt @@ -2,5 +2,5 @@ package io.tolgee.model.contentDelivery enum class ContentStorageType { S3, - AZURE + AZURE, } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/Import.kt b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/Import.kt index 99328ffad3..ee750f8ce2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/Import.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/Import.kt @@ -17,9 +17,8 @@ import java.util.* class Import( @field:NotNull @ManyToOne(optional = false) - val project: Project + val project: Project, ) : StandardAuditModel(), SoftDeletable { - @field:NotNull @ManyToOne(optional = false) lateinit var author: UserAccount diff --git a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/ImportFile.kt b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/ImportFile.kt index 9137eb2034..1f1ce5a9ab 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/ImportFile.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/ImportFile.kt @@ -16,7 +16,6 @@ class ImportFile( @field:Size(max = 2000) @Column(length = 2000) var name: String?, - @ManyToOne(optional = false) val import: Import, ) : StandardAuditModel() { @@ -31,33 +30,45 @@ class ImportFile( var namespace: String? = null - fun addIssue(type: FileIssueType, params: Map) { - val issue = ImportFileIssue(file = this, type = type).apply { - this.params = params.map { - ImportFileIssueParam(this, it.key, it.value.shortenWithEllipsis()) - }.toMutableList() - } + fun addIssue( + type: FileIssueType, + params: Map, + ) { + val issue = + ImportFileIssue(file = this, type = type).apply { + this.params = + params.map { + ImportFileIssueParam(this, it.key, it.value.shortenWithEllipsis()) + }.toMutableList() + } this.issues.add(issue) } - fun addKeyIsNotStringIssue(keyName: Any, keyIndex: Int) { + fun addKeyIsNotStringIssue( + keyName: Any, + keyIndex: Int, + ) { addIssue( FileIssueType.KEY_IS_NOT_STRING, mapOf( FileIssueParamType.KEY_NAME to keyName.toString(), - FileIssueParamType.KEY_INDEX to keyIndex.toString() - ) + FileIssueParamType.KEY_INDEX to keyIndex.toString(), + ), ) } - fun addValueIsNotStringIssue(keyName: String, keyIndex: Int?, value: Any?) { + fun addValueIsNotStringIssue( + keyName: String, + keyIndex: Int?, + value: Any?, + ) { addIssue( FileIssueType.VALUE_IS_NOT_STRING, mapOf( FileIssueParamType.KEY_NAME to keyName, FileIssueParamType.KEY_INDEX to keyIndex.toString(), - FileIssueParamType.VALUE to value.toString() - ) + FileIssueParamType.VALUE to value.toString(), + ), ) } @@ -66,7 +77,7 @@ class ImportFile( FileIssueType.KEY_IS_EMPTY, mapOf( FileIssueParamType.KEY_INDEX to keyIndex.toString(), - ) + ), ) } @@ -75,7 +86,7 @@ class ImportFile( FileIssueType.KEY_IS_BLANK, mapOf( FileIssueParamType.KEY_INDEX to keyIndex.toString(), - ) + ), ) } @@ -84,7 +95,7 @@ class ImportFile( FileIssueType.VALUE_IS_EMPTY, mapOf( FileIssueParamType.KEY_NAME to keyName, - ) + ), ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/ImportKey.kt b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/ImportKey.kt index 29bac88d13..ee1f455649 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/ImportKey.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/ImportKey.kt @@ -16,11 +16,9 @@ class ImportKey( @field:Size(max = 2000) @Column(length = 2000) var name: String, - @ManyToOne - var file: ImportFile + var file: ImportFile, ) : StandardAuditModel(), WithKeyMeta { - @OneToMany(mappedBy = "key", orphanRemoval = true) var translations: MutableList = mutableListOf() diff --git a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/ImportLanguage.kt b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/ImportLanguage.kt index 0d411fd5a6..cb926f5560 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/ImportLanguage.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/ImportLanguage.kt @@ -13,9 +13,8 @@ class ImportLanguage( @Size(max = 2000) @Column(length = 2000) var name: String, - @ManyToOne(optional = false) - var file: ImportFile + var file: ImportFile, ) : StandardAuditModel() { @OneToMany(mappedBy = "language", orphanRemoval = true) var translations: MutableList = mutableListOf() diff --git a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/ImportTranslation.kt b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/ImportTranslation.kt index 5d5b690941..a0012fe160 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/ImportTranslation.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/ImportTranslation.kt @@ -15,7 +15,6 @@ import java.util.* class ImportTranslation( @Column(columnDefinition = "text") var text: String?, - @ManyToOne var language: ImportLanguage, ) : StandardAuditModel() { @@ -52,11 +51,12 @@ class ImportTranslation( if (this == null) { return "__null_value" } - val hash = MurmurHash3.hash128(this.toByteArray()).asSequence().flatMap { - val buffer = ByteBuffer.allocate(java.lang.Long.BYTES) - buffer.putLong(it) - buffer.array().asSequence() - }.toList().toByteArray() + val hash = + MurmurHash3.hash128(this.toByteArray()).asSequence().flatMap { + val buffer = ByteBuffer.allocate(java.lang.Long.BYTES) + buffer.putLong(it) + buffer.array().asSequence() + }.toList().toByteArray() return Base64.getEncoder().encodeToString(hash) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/issues/ImportFileIssue.kt b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/issues/ImportFileIssue.kt index 7049eb2ee8..7bb85c6fc6 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/issues/ImportFileIssue.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/issues/ImportFileIssue.kt @@ -14,10 +14,8 @@ class ImportFileIssue( @ManyToOne(optional = false) @field:NotNull var file: ImportFile, - @Enumerated var type: FileIssueType = FileIssueType.ID_ATTRIBUTE_NOT_PROVIDED, - @OneToMany(mappedBy = "issue", orphanRemoval = true) var params: MutableList = mutableListOf(), ) : StandardAuditModel() diff --git a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/issues/ImportFileIssueParam.kt b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/issues/ImportFileIssueParam.kt index 9643d66c8c..d1262200e9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/issues/ImportFileIssueParam.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/issues/ImportFileIssueParam.kt @@ -11,10 +11,8 @@ import jakarta.validation.constraints.NotBlank class ImportFileIssueParam( @ManyToOne(optional = false) val issue: ImportFileIssue, - @Enumerated val type: FileIssueParamType, - @field:NotBlank - val value: String + val value: String, ) : StandardAuditModel() diff --git a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/issues/issueTypes/FileIssueType.kt b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/issues/issueTypes/FileIssueType.kt index 16c8f3a4eb..9a11a367a0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/issues/issueTypes/FileIssueType.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/issues/issueTypes/FileIssueType.kt @@ -10,5 +10,5 @@ enum class FileIssueType { ID_ATTRIBUTE_NOT_PROVIDED, TARGET_NOT_PROVIDED, TRANSLATION_TOO_LONG, - KEY_IS_BLANK + KEY_IS_BLANK, } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/issues/paramTypes/FileIssueParamType.kt b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/issues/paramTypes/FileIssueParamType.kt index 1fa03be5c6..76f5ed41fc 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/dataImport/issues/paramTypes/FileIssueParamType.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/dataImport/issues/paramTypes/FileIssueParamType.kt @@ -7,5 +7,5 @@ enum class FileIssueParamType { KEY_INDEX, VALUE, LINE, - FILE_NODE_ORIGINAL + FILE_NODE_ORIGINAL, } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/enums/Announcement.kt b/backend/data/src/main/kotlin/io/tolgee/model/enums/Announcement.kt index 60d2d155c4..87b4e6a729 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/enums/Announcement.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/enums/Announcement.kt @@ -7,7 +7,8 @@ import java.time.format.DateTimeFormatter enum class Announcement(val until: Long) { FEATURE_BATCH_OPERATIONS(parseTime("2023-09-10 00:00 UTC")), FEATURE_MT_FORMALITY(parseTime("2023-10-20 00:00 UTC")), - FEATURE_CONTENT_DELIVERY_AND_WEBHOOKS(parseTime("2024-01-05 00:00 UTC")); + FEATURE_CONTENT_DELIVERY_AND_WEBHOOKS(parseTime("2024-01-05 00:00 UTC")), + ; companion object { val last: Announcement diff --git a/backend/data/src/main/kotlin/io/tolgee/model/enums/AssignableTranslationState.kt b/backend/data/src/main/kotlin/io/tolgee/model/enums/AssignableTranslationState.kt index 88ecb346d1..b3040bc1fa 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/enums/AssignableTranslationState.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/enums/AssignableTranslationState.kt @@ -1,7 +1,7 @@ package io.tolgee.model.enums enum class AssignableTranslationState( - val translationState: TranslationState + val translationState: TranslationState, ) { TRANSLATED(TranslationState.TRANSLATED), REVIEWED(TranslationState.REVIEWED), diff --git a/backend/data/src/main/kotlin/io/tolgee/model/enums/OrganizationRoleType.kt b/backend/data/src/main/kotlin/io/tolgee/model/enums/OrganizationRoleType.kt index 3ae4ea4fef..ba54004314 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/enums/OrganizationRoleType.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/enums/OrganizationRoleType.kt @@ -2,5 +2,5 @@ package io.tolgee.model.enums enum class OrganizationRoleType { MEMBER, - OWNER + OWNER, } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/enums/ProjectPermissionType.kt b/backend/data/src/main/kotlin/io/tolgee/model/enums/ProjectPermissionType.kt index b89925f3b1..abb799bf3c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/enums/ProjectPermissionType.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/enums/ProjectPermissionType.kt @@ -7,8 +7,8 @@ enum class ProjectPermissionType(val availableScopes: Array) { Scope.TRANSLATIONS_VIEW, Scope.SCREENSHOTS_VIEW, Scope.ACTIVITY_VIEW, - Scope.KEYS_VIEW - ) + Scope.KEYS_VIEW, + ), ), TRANSLATE( arrayOf( @@ -19,7 +19,7 @@ enum class ProjectPermissionType(val availableScopes: Array) { Scope.ACTIVITY_VIEW, Scope.TRANSLATIONS_COMMENTS_ADD, Scope.TRANSLATIONS_COMMENTS_SET_STATE, - ) + ), ), REVIEW( arrayOf( @@ -30,8 +30,8 @@ enum class ProjectPermissionType(val availableScopes: Array) { Scope.ACTIVITY_VIEW, Scope.TRANSLATIONS_COMMENTS_ADD, Scope.TRANSLATIONS_COMMENTS_SET_STATE, - Scope.TRANSLATIONS_STATE_EDIT - ) + Scope.TRANSLATIONS_STATE_EDIT, + ), ), EDIT( arrayOf( @@ -52,11 +52,12 @@ enum class ProjectPermissionType(val availableScopes: Array) { Scope.BATCH_PRE_TRANSLATE_BY_TM, Scope.BATCH_MACHINE_TRANSLATE, Scope.BATCH_JOBS_VIEW, - ) + ), ), MANAGE( - arrayOf(Scope.ADMIN) - ); + arrayOf(Scope.ADMIN), + ), + ; companion object { fun getRoles(): Map> { diff --git a/backend/data/src/main/kotlin/io/tolgee/model/enums/Scope.kt b/backend/data/src/main/kotlin/io/tolgee/model/enums/Scope.kt index 6fb8860cef..acc7ed18c2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/enums/Scope.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/enums/Scope.kt @@ -7,7 +7,7 @@ import io.tolgee.exceptions.NotFoundException enum class Scope( @get:JsonValue - var value: String + var value: String, ) { TRANSLATIONS_VIEW("translations.view"), TRANSLATIONS_EDIT("translations.edit"), @@ -43,85 +43,91 @@ enum class Scope( private val keysView = HierarchyItem(KEYS_VIEW) private val translationsView = HierarchyItem(TRANSLATIONS_VIEW, listOf(keysView)) private val screenshotsView = HierarchyItem(SCREENSHOTS_VIEW, listOf(keysView)) - private val translationsEdit = HierarchyItem( - TRANSLATIONS_EDIT, - listOf(translationsView) - ) + private val translationsEdit = + HierarchyItem( + TRANSLATIONS_EDIT, + listOf(translationsView), + ) - val hierarchy = HierarchyItem( - ADMIN, - listOf( - translationsEdit, - HierarchyItem( - KEYS_EDIT, - listOf( - keysView - ) - ), - HierarchyItem( - KEYS_DELETE, - listOf( - keysView - ) - ), - HierarchyItem( - KEYS_CREATE, - listOf(keysView) - ), - HierarchyItem( - SCREENSHOTS_UPLOAD, - listOf( - screenshotsView - ) - ), - HierarchyItem( - SCREENSHOTS_DELETE, - listOf( - screenshotsView - ) - ), - HierarchyItem(ACTIVITY_VIEW), - HierarchyItem(LANGUAGES_EDIT), - HierarchyItem(PROJECT_EDIT), - HierarchyItem( - MEMBERS_EDIT, - listOf(HierarchyItem(MEMBERS_VIEW)) - ), - HierarchyItem( - TRANSLATIONS_COMMENTS_SET_STATE, - listOf(translationsView) - ), - HierarchyItem( - TRANSLATIONS_COMMENTS_ADD, - listOf(translationsView) - ), - HierarchyItem( - TRANSLATIONS_COMMENTS_EDIT, - listOf(translationsView) - ), - HierarchyItem( - TRANSLATIONS_STATE_EDIT, - listOf(HierarchyItem(TRANSLATIONS_VIEW)) + val hierarchy = + HierarchyItem( + ADMIN, + listOf( + translationsEdit, + HierarchyItem( + KEYS_EDIT, + listOf( + keysView, + ), + ), + HierarchyItem( + KEYS_DELETE, + listOf( + keysView, + ), + ), + HierarchyItem( + KEYS_CREATE, + listOf(keysView), + ), + HierarchyItem( + SCREENSHOTS_UPLOAD, + listOf( + screenshotsView, + ), + ), + HierarchyItem( + SCREENSHOTS_DELETE, + listOf( + screenshotsView, + ), + ), + HierarchyItem(ACTIVITY_VIEW), + HierarchyItem(LANGUAGES_EDIT), + HierarchyItem(PROJECT_EDIT), + HierarchyItem( + MEMBERS_EDIT, + listOf(HierarchyItem(MEMBERS_VIEW)), + ), + HierarchyItem( + TRANSLATIONS_COMMENTS_SET_STATE, + listOf(translationsView), + ), + HierarchyItem( + TRANSLATIONS_COMMENTS_ADD, + listOf(translationsView), + ), + HierarchyItem( + TRANSLATIONS_COMMENTS_EDIT, + listOf(translationsView), + ), + HierarchyItem( + TRANSLATIONS_STATE_EDIT, + listOf(HierarchyItem(TRANSLATIONS_VIEW)), + ), + HierarchyItem(BATCH_JOBS_VIEW), + HierarchyItem(BATCH_JOBS_CANCEL), + HierarchyItem(BATCH_PRE_TRANSLATE_BY_TM, listOf(translationsEdit)), + HierarchyItem(BATCH_MACHINE_TRANSLATE, listOf(translationsEdit)), + HierarchyItem(CONTENT_DELIVERY_MANAGE, listOf(HierarchyItem(CONTENT_DELIVERY_PUBLISH))), + HierarchyItem(WEBHOOKS_MANAGE), ), - HierarchyItem(BATCH_JOBS_VIEW), - HierarchyItem(BATCH_JOBS_CANCEL), - HierarchyItem(BATCH_PRE_TRANSLATE_BY_TM, listOf(translationsEdit)), - HierarchyItem(BATCH_MACHINE_TRANSLATE, listOf(translationsEdit)), - HierarchyItem(CONTENT_DELIVERY_MANAGE, listOf(HierarchyItem(CONTENT_DELIVERY_PUBLISH))), - HierarchyItem(WEBHOOKS_MANAGE), ) - ) private fun expand(item: HierarchyItem): MutableSet { - val descendants = item.requires.flatMap { - expand(it) - }.toMutableSet() + val descendants = + item.requires.flatMap { + expand(it) + }.toMutableSet() descendants.add(item.scope) return descendants } - private fun getScopeHierarchyItems(root: HierarchyItem, scope: Scope): List { + private fun getScopeHierarchyItems( + root: HierarchyItem, + scope: Scope, + ): List { val items = mutableListOf() if (root.scope == scope) { items.add(root) @@ -168,7 +174,7 @@ enum class Scope( return scopes.map { stringScope -> Scope.values().find { it.value == stringScope } ?: throw BadRequestException( Message.SCOPE_NOT_FOUND, - listOf(stringScope) + listOf(stringScope), ) }.toSet() } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/enums/TranslationCommentState.kt b/backend/data/src/main/kotlin/io/tolgee/model/enums/TranslationCommentState.kt index 41086ca95e..c461f39c2f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/enums/TranslationCommentState.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/enums/TranslationCommentState.kt @@ -3,5 +3,5 @@ package io.tolgee.model.enums enum class TranslationCommentState { RESOLUTION_NOT_NEEDED, NEEDS_RESOLUTION, - RESOLVED + RESOLVED, } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/enums/TranslationState.kt b/backend/data/src/main/kotlin/io/tolgee/model/enums/TranslationState.kt index 114bff604c..1f294f174e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/enums/TranslationState.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/enums/TranslationState.kt @@ -4,5 +4,5 @@ enum class TranslationState { UNTRANSLATED, TRANSLATED, REVIEWED, - DISABLED + DISABLED, } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/key/Key.kt b/backend/data/src/main/kotlin/io/tolgee/model/key/Key.kt index b9760915ae..7f69704899 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/key/Key.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/key/Key.kt @@ -64,7 +64,7 @@ class Key( constructor( name: String, project: Project, - translations: MutableList = mutableListOf() + translations: MutableList = mutableListOf(), ) : this(name) { this.project = project this.translations = translations diff --git a/backend/data/src/main/kotlin/io/tolgee/model/key/KeyCodeReference.kt b/backend/data/src/main/kotlin/io/tolgee/model/key/KeyCodeReference.kt index fbdd2e0bcf..3b20ace36a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/key/KeyCodeReference.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/key/KeyCodeReference.kt @@ -13,7 +13,6 @@ import jakarta.validation.constraints.NotNull class KeyCodeReference( @ManyToOne(optional = false) override var keyMeta: KeyMeta, - @field:NotNull @ManyToOne(optional = false, fetch = FetchType.LAZY) var author: UserAccount? = null, diff --git a/backend/data/src/main/kotlin/io/tolgee/model/key/KeyComment.kt b/backend/data/src/main/kotlin/io/tolgee/model/key/KeyComment.kt index 465e94ffa6..f86127bb17 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/key/KeyComment.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/key/KeyComment.kt @@ -13,12 +13,10 @@ import jakarta.validation.constraints.NotNull class KeyComment( @ManyToOne(optional = false) override var keyMeta: KeyMeta, - @field:NotNull @ManyToOne(optional = false, fetch = FetchType.LAZY) - var author: UserAccount? = null + var author: UserAccount? = null, ) : StandardAuditModel(), WithKeyMetaReference { - var fromImport: Boolean = false @field:NotBlank diff --git a/backend/data/src/main/kotlin/io/tolgee/model/key/KeyMeta.kt b/backend/data/src/main/kotlin/io/tolgee/model/key/KeyMeta.kt index 8dba03f54d..85e540d090 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/key/KeyMeta.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/key/KeyMeta.kt @@ -23,11 +23,9 @@ import jakarta.persistence.PreUpdate class KeyMeta( @OneToOne var key: Key? = null, - @OneToOne var importKey: ImportKey? = null, ) : StandardAuditModel() { - @OneToMany(mappedBy = "keyMeta") @OrderBy("id") var comments = mutableListOf() @@ -41,14 +39,20 @@ class KeyMeta( @ActivityLoggedProp(TagsPropChangesProvider::class) var tags: MutableSet = mutableSetOf() - fun addComment(author: UserAccount? = null, ft: KeyComment.() -> Unit) { + fun addComment( + author: UserAccount? = null, + ft: KeyComment.() -> Unit, + ) { KeyComment(this, author).apply { ft() comments.add(this) } } - fun addCodeReference(author: UserAccount? = null, ft: KeyCodeReference.() -> Unit) { + fun addCodeReference( + author: UserAccount? = null, + ft: KeyCodeReference.() -> Unit, + ) { KeyCodeReference(this, author).apply { ft() codeReferences.add(this) diff --git a/backend/data/src/main/kotlin/io/tolgee/model/key/Namespace.kt b/backend/data/src/main/kotlin/io/tolgee/model/key/Namespace.kt index 5ad95afb05..9d090f96a4 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/key/Namespace.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/key/Namespace.kt @@ -19,7 +19,7 @@ import org.hibernate.validator.constraints.Length @ActivityReturnsExistence @Table( uniqueConstraints = [UniqueConstraint(columnNames = ["project_id", "name"], name = "namespace_name_project")], - indexes = [Index(columnList = "name")] + indexes = [Index(columnList = "name")], ) class Namespace( @ActivityLoggedProp @@ -27,7 +27,6 @@ class Namespace( @field:NotBlank @field:Length(max = 100) var name: String = "", - @ManyToOne - var project: Project + var project: Project, ) : StandardAuditModel() diff --git a/backend/data/src/main/kotlin/io/tolgee/model/key/screenshotReference/KeyInScreenshotPosition.kt b/backend/data/src/main/kotlin/io/tolgee/model/key/screenshotReference/KeyInScreenshotPosition.kt index 836b0fd942..2c76a53110 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/key/screenshotReference/KeyInScreenshotPosition.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/key/screenshotReference/KeyInScreenshotPosition.kt @@ -4,5 +4,5 @@ data class KeyInScreenshotPosition( val x: Int, val y: Int, val width: Int, - val height: Int + val height: Int, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/model/key/screenshotReference/KeyScreenshotReferenceId.kt b/backend/data/src/main/kotlin/io/tolgee/model/key/screenshotReference/KeyScreenshotReferenceId.kt index c081af295c..5cf4049cef 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/key/screenshotReference/KeyScreenshotReferenceId.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/key/screenshotReference/KeyScreenshotReferenceId.kt @@ -4,5 +4,5 @@ import java.io.Serializable data class KeyScreenshotReferenceId( var key: Long? = null, - var screenshot: Long? = null + var screenshot: Long? = null, ) : Serializable diff --git a/backend/data/src/main/kotlin/io/tolgee/model/keyBigMeta/KeysDistance.kt b/backend/data/src/main/kotlin/io/tolgee/model/keyBigMeta/KeysDistance.kt index 9ed1c72147..793c84f99c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/keyBigMeta/KeysDistance.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/keyBigMeta/KeysDistance.kt @@ -17,15 +17,14 @@ import org.springframework.data.domain.Persistable Index(columnList = "key1Id, key2Id", unique = true), Index(columnList = "key1Id"), Index(columnList = "key2Id"), - ] + ], ) @IdClass(KeysDistanceId::class) class KeysDistance( @Id var key1Id: Long = 0, - @Id - var key2Id: Long = 0 + var key2Id: Long = 0, ) : AuditModel(), Persistable { @ManyToOne(fetch = FetchType.LAZY) lateinit var project: Project @@ -33,6 +32,7 @@ class KeysDistance( var score: Long = MAX_SCORE var hits: Long = 1 + override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false diff --git a/backend/data/src/main/kotlin/io/tolgee/model/keyBigMeta/KeysDistanceId.kt b/backend/data/src/main/kotlin/io/tolgee/model/keyBigMeta/KeysDistanceId.kt index 9a9d2b678b..6d40e40ac5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/keyBigMeta/KeysDistanceId.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/keyBigMeta/KeysDistanceId.kt @@ -4,5 +4,5 @@ import java.io.Serializable data class KeysDistanceId( var key1Id: Long = 0, - var key2Id: Long = 0 + var key2Id: Long = 0, ) : Serializable diff --git a/backend/data/src/main/kotlin/io/tolgee/model/mtServiceConfig/Formality.kt b/backend/data/src/main/kotlin/io/tolgee/model/mtServiceConfig/Formality.kt index 19f49cfa9a..8df5d30dd9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/mtServiceConfig/Formality.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/mtServiceConfig/Formality.kt @@ -1,5 +1,7 @@ package io.tolgee.model.mtServiceConfig enum class Formality { - FORMAL, INFORMAL, DEFAULT + FORMAL, + INFORMAL, + DEFAULT, } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/mtServiceConfig/MtServiceConfig.kt b/backend/data/src/main/kotlin/io/tolgee/model/mtServiceConfig/MtServiceConfig.kt index 4e2c207473..6d8363038c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/mtServiceConfig/MtServiceConfig.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/mtServiceConfig/MtServiceConfig.kt @@ -58,17 +58,18 @@ class MtServiceConfig : StandardAuditModel() { companion object { fun getServiceInfo( config: MtServiceConfig, - serviceType: MtServiceType? + serviceType: MtServiceType?, ): MtServiceInfo? { if (serviceType == null) { return null } - val formality = when (serviceType) { - MtServiceType.AWS -> config.awsFormality - MtServiceType.DEEPL -> config.deeplFormality - MtServiceType.TOLGEE -> config.tolgeeFormality - else -> null - } + val formality = + when (serviceType) { + MtServiceType.AWS -> config.awsFormality + MtServiceType.DEEPL -> config.deeplFormality + MtServiceType.TOLGEE -> config.tolgeeFormality + else -> null + } return MtServiceInfo(serviceType, formality) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/translation/Translation.kt b/backend/data/src/main/kotlin/io/tolgee/model/translation/Translation.kt index d89a516f5a..08e8801b92 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/translation/Translation.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/translation/Translation.kt @@ -31,9 +31,9 @@ import org.hibernate.annotations.ColumnDefault uniqueConstraints = [ UniqueConstraint( columnNames = ["key_id", "language_id"], - name = "translation_key_language" - ) - ] + name = "translation_key_language", + ), + ], ) @ActivityLoggedEntity @EntityListeners(Translation.Companion.UpdateStatsListener::class, Translation.Companion.StateListener::class) @@ -42,7 +42,7 @@ class Translation( @Column(columnDefinition = "text") @ActivityLoggedProp @ActivityDescribingProp - var text: String? = null + var text: String? = null, ) : StandardAuditModel() { @ManyToOne(optional = false, fetch = FetchType.LAZY) @field:NotNull diff --git a/backend/data/src/main/kotlin/io/tolgee/model/translation/TranslationComment.kt b/backend/data/src/main/kotlin/io/tolgee/model/translation/TranslationComment.kt index cf47b17650..8b20e7121e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/translation/TranslationComment.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/translation/TranslationComment.kt @@ -20,7 +20,7 @@ import org.hibernate.validator.constraints.Length @ActivityLoggedEntity @ActivityEntityDescribingPaths(paths = ["translation"]) @Table( - indexes = [Index(columnList = "state")] + indexes = [Index(columnList = "state")], ) class TranslationComment( @field:Length(max = 10000) @@ -29,12 +29,10 @@ class TranslationComment( @ActivityLoggedProp @ActivityDescribingProp var text: String = "", - @ActivityLoggedProp var state: TranslationCommentState = TranslationCommentState.NEEDS_RESOLUTION, - @ManyToOne - var translation: Translation + var translation: Translation, ) : StandardAuditModel() { @ManyToOne(optional = false, fetch = LAZY) lateinit var author: UserAccount diff --git a/backend/data/src/main/kotlin/io/tolgee/model/views/BatchJobView.kt b/backend/data/src/main/kotlin/io/tolgee/model/views/BatchJobView.kt index ea4e84503b..914b188dc0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/views/BatchJobView.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/views/BatchJobView.kt @@ -6,5 +6,5 @@ import io.tolgee.model.batch.BatchJob class BatchJobView( val batchJob: BatchJob, val progress: Int, - val errorMessage: Message? + val errorMessage: Message?, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/model/views/ExtendedUserAccountInProject.kt b/backend/data/src/main/kotlin/io/tolgee/model/views/ExtendedUserAccountInProject.kt index 3939f1e50e..5e078bc29b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/views/ExtendedUserAccountInProject.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/views/ExtendedUserAccountInProject.kt @@ -11,5 +11,5 @@ class ExtendedUserAccountInProject( val organizationBasePermission: Permission, val directPermission: Permission?, val permittedLanguageIds: List?, - val avatarHash: String? + val avatarHash: String?, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/model/views/KeyWithTranslationsView.kt b/backend/data/src/main/kotlin/io/tolgee/model/views/KeyWithTranslationsView.kt index 3c38001b5e..3ce9cee563 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/views/KeyWithTranslationsView.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/views/KeyWithTranslationsView.kt @@ -19,32 +19,37 @@ data class KeyWithTranslationsView( var screenshots: Collection? = null companion object { - fun of(queryData: Array, languages: List): KeyWithTranslationsView { + fun of( + queryData: Array, + languages: List, + ): KeyWithTranslationsView { val data = mutableListOf(*queryData) - val result = KeyWithTranslationsView( - keyId = data.removeFirst() as Long, - keyName = data.removeFirst() as String, - keyNamespaceId = data.removeFirst() as Long?, - keyNamespace = data.removeFirst() as String?, - screenshotCount = data.removeFirst() as Long, - contextPresent = data.removeFirst() as Boolean - ) + val result = + KeyWithTranslationsView( + keyId = data.removeFirst() as Long, + keyName = data.removeFirst() as String, + keyNamespaceId = data.removeFirst() as Long?, + keyNamespace = data.removeFirst() as String?, + screenshotCount = data.removeFirst() as Long, + contextPresent = data.removeFirst() as Boolean, + ) (0 until data.size step 8).forEach { i -> val language = languages[i / 8].tag val id = data[i] as Long? if (id != null) { - result.translations[language] = TranslationView( - id = id, - text = data[i + 1] as String?, - state = (data[i + 2] ?: TranslationState.TRANSLATED) as TranslationState, - outdated = data[i + 3] as Boolean, - auto = data[i + 4] as Boolean, - mtProvider = data[i + 5] as MtServiceType?, - commentCount = (data[i + 6]) as Long, - unresolvedCommentCount = (data[i + 7]) as Long - ) + result.translations[language] = + TranslationView( + id = id, + text = data[i + 1] as String?, + state = (data[i + 2] ?: TranslationState.TRANSLATED) as TranslationState, + outdated = data[i + 3] as Boolean, + auto = data[i + 4] as Boolean, + mtProvider = data[i + 5] as MtServiceType?, + commentCount = (data[i + 6]) as Long, + unresolvedCommentCount = (data[i + 7]) as Long, + ) } } return result diff --git a/backend/data/src/main/kotlin/io/tolgee/model/views/OrganizationView.kt b/backend/data/src/main/kotlin/io/tolgee/model/views/OrganizationView.kt index c73a679a64..ac967c8550 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/views/OrganizationView.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/views/OrganizationView.kt @@ -8,7 +8,10 @@ interface OrganizationView { val currentUserRole: OrganizationRoleType? companion object { - fun of(entity: Organization, currentUserRole: OrganizationRoleType?): OrganizationView { + fun of( + entity: Organization, + currentUserRole: OrganizationRoleType?, + ): OrganizationView { return object : OrganizationView { override val organization = entity override val currentUserRole = currentUserRole diff --git a/backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithLanguagesView.kt b/backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithLanguagesView.kt index c4ca285319..56c7a52e02 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithLanguagesView.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithLanguagesView.kt @@ -15,10 +15,13 @@ open class ProjectWithLanguagesView( override val organizationOwner: Organization, override val organizationRole: OrganizationRoleType?, override val directPermission: Permission?, - val permittedLanguageIds: List? + val permittedLanguageIds: List?, ) : ProjectView { companion object { - fun fromProjectView(view: ProjectView, permittedLanguageIds: List?): ProjectWithLanguagesView { + fun fromProjectView( + view: ProjectView, + permittedLanguageIds: List?, + ): ProjectWithLanguagesView { return ProjectWithLanguagesView( id = view.id, name = view.name, @@ -29,7 +32,7 @@ open class ProjectWithLanguagesView( organizationOwner = view.organizationOwner, organizationRole = view.organizationRole, directPermission = view.directPermission, - permittedLanguageIds = permittedLanguageIds + permittedLanguageIds = permittedLanguageIds, ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithStatsView.kt b/backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithStatsView.kt index f946b05ffa..b9432f2bd9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithStatsView.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/views/ProjectWithStatsView.kt @@ -1,20 +1,20 @@ package io.tolgee.model.views -import io.tolgee.dtos.query_results.ProjectStatistics +import io.tolgee.dtos.queryResults.ProjectStatistics class ProjectWithStatsView( view: ProjectWithLanguagesView, val stats: ProjectStatistics, val languages: List, ) : ProjectWithLanguagesView( - view.id, - view.name, - view.description, - view.slug, - view.avatarHash, - view.baseLanguage, - view.organizationOwner, - view.organizationRole, - view.directPermission, - view.permittedLanguageIds -) + view.id, + view.name, + view.description, + view.slug, + view.avatarHash, + view.baseLanguage, + view.organizationOwner, + view.organizationRole, + view.directPermission, + view.permittedLanguageIds, + ) diff --git a/backend/data/src/main/kotlin/io/tolgee/model/views/TranslationView.kt b/backend/data/src/main/kotlin/io/tolgee/model/views/TranslationView.kt index 1b66800228..5c6aaad418 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/views/TranslationView.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/views/TranslationView.kt @@ -11,5 +11,5 @@ data class TranslationView( val mtProvider: MtServiceType?, val commentCount: Long, val unresolvedCommentCount: Long, - val outdated: Boolean + val outdated: Boolean, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/model/views/activity/ProjectActivityView.kt b/backend/data/src/main/kotlin/io/tolgee/model/views/activity/ProjectActivityView.kt index 8b1031db92..20df0767c2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/views/activity/ProjectActivityView.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/views/activity/ProjectActivityView.kt @@ -14,5 +14,5 @@ class ProjectActivityView( var modifications: List? = null, val meta: Map? = null, val counts: MutableMap? = null, - val params: Any? = null + val params: Any? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/model/views/projectStats/ProjectStatsView.kt b/backend/data/src/main/kotlin/io/tolgee/model/views/projectStats/ProjectStatsView.kt index faf44814c1..2be32f71a5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/model/views/projectStats/ProjectStatsView.kt +++ b/backend/data/src/main/kotlin/io/tolgee/model/views/projectStats/ProjectStatsView.kt @@ -4,5 +4,5 @@ data class ProjectStatsView( val id: Long, val keyCount: Long, val memberCount: Long, - val tagCount: Long + val tagCount: Long, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/pubSub/RedisPubSubReceiver.kt b/backend/data/src/main/kotlin/io/tolgee/pubSub/RedisPubSubReceiver.kt index 1ff37c07f1..66e1e70264 100644 --- a/backend/data/src/main/kotlin/io/tolgee/pubSub/RedisPubSubReceiver.kt +++ b/backend/data/src/main/kotlin/io/tolgee/pubSub/RedisPubSubReceiver.kt @@ -11,9 +11,8 @@ import org.springframework.messaging.simp.SimpMessagingTemplate class RedisPubSubReceiver( private val template: SimpMessagingTemplate, - private val applicationEventPublisher: ApplicationEventPublisher + private val applicationEventPublisher: ApplicationEventPublisher, ) : Logging { - fun receiveWebsocketMessage(message: String) { val data = jacksonObjectMapper().readValue(message, RedisWebsocketEventWrapper::class.java) template.convertAndSend(data.destination, data.message) diff --git a/backend/data/src/main/kotlin/io/tolgee/pubSub/RedisPubSubReceiverConfiguration.kt b/backend/data/src/main/kotlin/io/tolgee/pubSub/RedisPubSubReceiverConfiguration.kt index 4c8262ff48..002d9a43be 100644 --- a/backend/data/src/main/kotlin/io/tolgee/pubSub/RedisPubSubReceiverConfiguration.kt +++ b/backend/data/src/main/kotlin/io/tolgee/pubSub/RedisPubSubReceiverConfiguration.kt @@ -14,15 +14,14 @@ import org.springframework.messaging.simp.SimpMessagingTemplate @Configuration @ConditionalOnExpression( "\${tolgee.websocket.use-redis:false} or " + - "(\${tolgee.cache.use-redis:false} and \${tolgee.cache.enabled:false})" + "(\${tolgee.cache.use-redis:false} and \${tolgee.cache.enabled:false})", ) class RedisPubSubReceiverConfiguration( private val template: SimpMessagingTemplate, private val connectionFactory: RedisConnectionFactory, private val applicationEventPublisher: ApplicationEventPublisher, - private val tolgeeProperties: TolgeeProperties + private val tolgeeProperties: TolgeeProperties, ) { - companion object { const val WEBSOCKET_TOPIC = "websocket" const val JOB_QUEUE_TOPIC = "job_queue" diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/AnnouncementRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/AnnouncementRepository.kt index 42453e81e1..f1a64fcfa0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/AnnouncementRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/AnnouncementRepository.kt @@ -14,7 +14,10 @@ interface AnnouncementRepository : JpaRepository 0 from DismissedAnnouncement as an where an.user.id = :userId and an.announcement = :announcement - """ + """, ) - fun isDismissed(userId: Long, announcement: Announcement): Boolean + fun isDismissed( + userId: Long, + announcement: Announcement, + ): Boolean } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/ApiKeyRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/ApiKeyRepository.kt index 4b1a080be6..438f416725 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/ApiKeyRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/ApiKeyRepository.kt @@ -15,8 +15,14 @@ interface ApiKeyRepository : JpaRepository { fun findByKeyHash(hash: String): Optional fun getAllByUserAccountIdOrderById(userAccountId: Long): LinkedHashSet + fun getAllByProjectId(projectId: Long): Set - fun getAllByProjectId(projectId: Long, pageable: Pageable): Page + + fun getAllByProjectId( + projectId: Long, + pageable: Pageable, + ): Page + fun deleteAllByProjectId(projectId: Long) @EntityGraph(attributePaths = ["project", "userAccount", "scopesEnum"]) @@ -26,11 +32,18 @@ interface ApiKeyRepository : JpaRepository { left join ak.userAccount u where u.id = :userAccountId and (p.id = :filterProjectId or :filterProjectId is null) - """ + """, ) - fun getAllByUserAccount(userAccountId: Long, filterProjectId: Long?, pageable: Pageable): Page + fun getAllByUserAccount( + userAccountId: Long, + filterProjectId: Long?, + pageable: Pageable, + ): Page @Modifying @Query("UPDATE ApiKey ak SET ak.lastUsedAt = ?2 WHERE ak.id = ?1") - fun updateLastUsedById(id: Long, lastUsed: Date) + fun updateLastUsedById( + id: Long, + lastUsed: Date, + ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/AutoTranslationConfigRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/AutoTranslationConfigRepository.kt index 0fcfda563a..5140868709 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/AutoTranslationConfigRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/AutoTranslationConfigRepository.kt @@ -8,14 +8,21 @@ import org.springframework.stereotype.Repository @Repository interface AutoTranslationConfigRepository : JpaRepository { - fun findOneByProjectAndTargetLanguageId(project: Project, languageId: Long?): AutoTranslationConfig? - fun findByProjectAndTargetLanguageIdIn(project: Project, languageIds: List): List + fun findOneByProjectAndTargetLanguageId( + project: Project, + languageId: Long?, + ): AutoTranslationConfig? + + fun findByProjectAndTargetLanguageIdIn( + project: Project, + languageIds: List, + ): List @Query( """ select atc from AutoTranslationConfig atc where atc.project = :project and atc.targetLanguage is null - """ + """, ) fun findDefaultForProject(project: Project): AutoTranslationConfig? diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/AutomationRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/AutomationRepository.kt index 4ec0ce9fe7..d843b4284e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/AutomationRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/AutomationRepository.kt @@ -12,9 +12,17 @@ interface AutomationRepository : JpaRepository { from Automation a join fetch a.actions where a.id = :id - """ + """, ) fun find(id: Long): Automation? - fun deleteByIdAndProjectId(automationId: Long, projectId: Long): Long - fun findByIdAndProjectId(automationId: Long, projectId: Long): Automation? + + fun deleteByIdAndProjectId( + automationId: Long, + projectId: Long, + ): Long + + fun findByIdAndProjectId( + automationId: Long, + projectId: Long, + ): Automation? } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/BatchJobRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/BatchJobRepository.kt index dca8d8ebfd..31fcda61cc 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/BatchJobRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/BatchJobRepository.kt @@ -24,9 +24,13 @@ interface BatchJobRepository : JpaRepository { select count(j) from BatchJob j where j.project.id = :projectId and (:userAccountId is null or j.author.id = :userAccountId) - """ + """, ) - fun getJobs(projectId: Long, userAccountId: Long?, pageable: Pageable): Page + fun getJobs( + projectId: Long, + userAccountId: Long?, + pageable: Pageable, + ): Page @Query( value = """ @@ -37,13 +41,13 @@ interface BatchJobRepository : JpaRepository { and (:userAccountId is null or j.author.id = :userAccountId) and (j.status not in :completedStatuses or j.updatedAt > :oneHourAgo) order by j.updatedAt - """ + """, ) fun getCurrentJobs( projectId: Long, userAccountId: Long?, oneHourAgo: Date, - completedStatuses: List + completedStatuses: List, ): List @Query( @@ -53,7 +57,7 @@ interface BatchJobRepository : JpaRepository { from tolgee_batch_job_chunk_execution where batch_job_id in :jobIds group by tolgee_batch_job_chunk_execution.batch_job_id - """ + """, ) fun getProgresses(jobIds: List): List> @@ -63,9 +67,10 @@ interface BatchJobRepository : JpaRepository { from BatchJobChunkExecution bjce where bjce.batchJob.id in :jobIds and bjce.errorMessage is not null - """ + """, ) fun getErrorMessages(jobIds: List): List + fun findAllByProjectId(projectId: Long): List @Query( @@ -74,12 +79,12 @@ interface BatchJobRepository : JpaRepository { where j.id in :lockedJobIds and j.status in :completedStatuses and j.updatedAt < :before - """ + """, ) fun getCompletedJobs( lockedJobIds: Iterable, before: Date, - completedStatuses: List = BatchJobStatus.values().filter { it.completed } + completedStatuses: List = BatchJobStatus.values().filter { it.completed }, ): List @Query( @@ -89,7 +94,7 @@ interface BatchJobRepository : JpaRepository { where j.id in :jobIds group by j.id having max(bjce.updatedAt) < :before - """ + """, ) fun getStuckJobIds( jobIds: MutableSet, @@ -101,7 +106,7 @@ interface BatchJobRepository : JpaRepository { from BatchJob j where j.debouncingKey = :debouncingKey and j.status = 'PENDING' - """ + """, ) fun findBatchJobByDebouncingKey(debouncingKey: String?): BatchJob? } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/InvitationRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/InvitationRepository.kt index fd97d14ebb..732b620575 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/InvitationRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/InvitationRepository.kt @@ -11,8 +11,11 @@ import java.util.* @Repository interface InvitationRepository : JpaRepository { fun deleteAllByCreatedAtLessThan(date: Date) + fun findOneByCode(code: String?): Optional + fun findAllByPermissionProjectOrderByCreatedAt(project: Project): LinkedHashSet + @Query( """ from Invitation i @@ -20,7 +23,7 @@ interface InvitationRepository : JpaRepository { left join fetch i.permission p where i.organizationRole.organization = :organization order by i.createdAt - """ + """, ) fun getAllForOrganization(organization: Organization): List @@ -32,9 +35,12 @@ interface InvitationRepository : JpaRepository { where (i.email = :email or u.username = :email) and p.project = :project - """ + """, ) - fun countByUserOrInvitationWithEmailAndProject(email: String, project: Project): Int + fun countByUserOrInvitationWithEmailAndProject( + email: String, + project: Project, + ): Int @Query( """ @@ -44,7 +50,10 @@ interface InvitationRepository : JpaRepository { where (i.email = :email or u.username = :email) and orl.organization = :organization - """ + """, ) - fun countByUserOrInvitationWithEmailAndOrganization(email: String, organization: Organization): Int + fun countByUserOrInvitationWithEmailAndOrganization( + email: String, + organization: Organization, + ): Int } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/KeyCodeReferenceRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/KeyCodeReferenceRepository.kt index 756322b006..46fa50df8b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/KeyCodeReferenceRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/KeyCodeReferenceRepository.kt @@ -13,7 +13,7 @@ interface KeyCodeReferenceRepository : JpaRepository { @Transactional @Query( """delete from KeyCodeReference kcr where kcr.keyMeta in - (select km from kcr.keyMeta km where km.importKey.id in :keyIds)""" + (select km from kcr.keyMeta km where km.importKey.id in :keyIds)""", ) fun deleteAllByImportKeyIds(keyIds: List) @@ -21,7 +21,7 @@ interface KeyCodeReferenceRepository : JpaRepository { @Transactional @Query( """delete from KeyCodeReference kcr where kcr.keyMeta in - (select km from kcr.keyMeta km where km.key.id in :keyIds)""" + (select km from kcr.keyMeta km where km.key.id in :keyIds)""", ) fun deleteAllByKeyIds(keyIds: Collection) @@ -29,7 +29,7 @@ interface KeyCodeReferenceRepository : JpaRepository { @Query( """delete from KeyCodeReference kcr where kcr.keyMeta in (select km from kcr.keyMeta km where km.key.id in - (select k.id from Key k where k.project.id = :projectId))""" + (select k.id from Key k where k.project.id = :projectId))""", ) fun deleteAllByProject(projectId: Long) } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/KeyCommentRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/KeyCommentRepository.kt index 7dbbbf09f1..02bfcd50b1 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/KeyCommentRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/KeyCommentRepository.kt @@ -9,12 +9,11 @@ import org.springframework.transaction.annotation.Transactional @Repository interface KeyCommentRepository : JpaRepository { - @Modifying @Transactional @Query( "delete from KeyComment kc " + - "where kc.keyMeta in (select km from kc.keyMeta km where km.importKey.id in :keyIds)" + "where kc.keyMeta in (select km from kc.keyMeta km where km.importKey.id in :keyIds)", ) fun deleteAllByImportKeyIds(keyIds: List) @@ -22,7 +21,7 @@ interface KeyCommentRepository : JpaRepository { @Transactional @Query( "delete from KeyComment kc " + - "where kc.keyMeta in (select km from kc.keyMeta km where km.key.id in :keyIds)" + "where kc.keyMeta in (select km from kc.keyMeta km where km.key.id in :keyIds)", ) fun deleteAllByKeyIds(keyIds: Collection) @@ -30,7 +29,7 @@ interface KeyCommentRepository : JpaRepository { @Query( "delete from KeyComment kc " + "where kc.keyMeta in (select km from kc.keyMeta km where km.key.id in " + - "(select k.id from Key k where k.project.id = :projectId))" + "(select k.id from Key k where k.project.id = :projectId))", ) fun deleteAllByProject(projectId: Long) } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/KeyMetaRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/KeyMetaRepository.kt index efa4d7eee9..982e90ce11 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/KeyMetaRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/KeyMetaRepository.kt @@ -9,12 +9,11 @@ import org.springframework.transaction.annotation.Transactional @Repository interface KeyMetaRepository : JpaRepository { - @Modifying @Transactional @Query( """delete from KeyComment kc where kc.keyMeta in - (select km from kc.keyMeta km join km.key k where k.project.id = :projectId)""" + (select km from kc.keyMeta km join km.key k where k.project.id = :projectId)""", ) fun deleteAllKeyCommentsByProjectId(projectId: Long) @@ -22,7 +21,7 @@ interface KeyMetaRepository : JpaRepository { @Transactional @Query( """delete from KeyCodeReference kcr where kcr.keyMeta in - (select km from kcr.keyMeta km join km.key k where k.project.id = :projectId)""" + (select km from kcr.keyMeta km join km.key k where k.project.id = :projectId)""", ) fun deleteAllKeyCodeReferencesByProjectId(projectId: Long) diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/KeyRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/KeyRepository.kt index 55b5e7dbb6..8a0783d028 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/KeyRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/KeyRepository.kt @@ -12,7 +12,6 @@ import java.util.* @Repository interface KeyRepository : JpaRepository { - @Query( """ from Key k @@ -21,27 +20,33 @@ interface KeyRepository : JpaRepository { k.name = :name and k.project.id = :projectId and (ns.name = :namespace or (ns is null and :namespace is null)) - """ + """, ) - fun getByNameAndNamespace(projectId: Long, name: String, namespace: String?): Optional + fun getByNameAndNamespace( + projectId: Long, + name: String, + namespace: String?, + ): Optional @Query( """ from Key k left join fetch k.namespace left join fetch k.keyMeta where k.project.id = :projectId - """ + """, ) fun getAllByProjectId(projectId: Long): Set @Query( """ from Key k left join fetch k.namespace where k.project.id = :projectId order by k.id - """ + """, ) fun getAllByProjectIdSortedById(projectId: Long): List @Query("select k from Key k left join fetch k.keyMeta km where k.project.id = :projectId") fun getByProjectIdWithFetchedMetas(projectId: Long?): List + fun deleteAllByIdIn(ids: Collection) + fun findAllByIdIn(ids: Collection): List @Query( @@ -51,7 +56,7 @@ interface KeyRepository : JpaRepository { left join fetch k.keyMeta left join fetch k.keyScreenshotReferences where k.id in :ids - """ + """, ) fun findAllByIdInForDelete(ids: Collection): List @@ -100,9 +105,14 @@ interface KeyRepository : JpaRepository { or lower(f_unaccent(t.text)) %> searchUnaccent or lower(f_unaccent(bt.text)) %> searchUnaccent ) - """ + """, ) - fun searchKeys(search: String, projectId: Long, languageTag: String?, pageable: Pageable): Page + fun searchKeys( + search: String, + projectId: Long, + languageTag: String?, + pageable: Pageable, + ): Page @Query( """ @@ -112,9 +122,12 @@ interface KeyRepository : JpaRepository { countQuery = """ select count(k) from Key k where k.project.id = :projectId - """ + """, ) - fun getAllByProjectId(projectId: Long, pageable: Pageable): Page + fun getAllByProjectId( + projectId: Long, + pageable: Pageable, + ): Page @Query( """ @@ -122,7 +135,7 @@ interface KeyRepository : JpaRepository { left join fetch k.keyMeta km left join fetch km.tags where k in :keys - """ + """, ) fun getWithTags(keys: Set): List @@ -132,14 +145,14 @@ interface KeyRepository : JpaRepository { left join fetch k.keyMeta km left join fetch km.tags where k.id in :keyIds - """ + """, ) fun getWithTagsByIds(keyIds: Iterable): Set @Query( """ select k.project.id from Key k where k.id in :keysIds - """ + """, ) fun getProjectIdsForKeyIds(keysIds: List): List @@ -148,7 +161,7 @@ interface KeyRepository : JpaRepository { select k from Key k left join fetch k.namespace where k.id in :keyIds - """ + """, ) fun getKeysWithNamespaces(keyIds: List): List @@ -160,9 +173,15 @@ interface KeyRepository : JpaRepository { and l.project.id = :projectId and t.state = io.tolgee.model.enums.TranslationState.DISABLED order by l.id - """ + """, ) - fun getDisabledLanguages(projectId: Long, keyId: Long): List - - fun findByProjectIdAndId(projectId: Long, keyId: Long): Key? + fun getDisabledLanguages( + projectId: Long, + keyId: Long, + ): List + + fun findByProjectIdAndId( + projectId: Long, + keyId: Long, + ): Key? } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/KeyScreenshotReferenceRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/KeyScreenshotReferenceRepository.kt index 19a0bc127b..2260378714 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/KeyScreenshotReferenceRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/KeyScreenshotReferenceRepository.kt @@ -10,14 +10,13 @@ import org.springframework.stereotype.Repository @Repository interface KeyScreenshotReferenceRepository : JpaRepository { - fun getAllByScreenshot(screenshot: Screenshot): List @Query( """ FROM KeyScreenshotReference ksr WHERE ksr.screenshot.id IN :screenshotIds - """ + """, ) fun findAll(screenshotIds: Collection): List @@ -25,16 +24,19 @@ interface KeyScreenshotReferenceRepository : JpaRepository): List + fun findAll( + key: Key, + screenshotIds: List, + ): List @Query( """ from KeyScreenshotReference ksr left join fetch ksr.screenshot where ksr.key.id in :keyIds - """ + """, ) fun getAllByKeyIdIn(keyIds: Collection): List } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/KeysDistanceRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/KeysDistanceRepository.kt index 537e26863b..2da8f596f4 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/KeysDistanceRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/KeysDistanceRepository.kt @@ -10,16 +10,18 @@ import org.springframework.stereotype.Repository @Repository interface KeysDistanceRepository : JpaRepository { - @Query( """ select (case when kd.key1Id = :keyId then kd.key2Id else kd.key1Id end) from KeysDistance kd where kd.key1Id = :keyId or kd.key2Id = :keyId order by kd.score desc - """ + """, ) - fun getCloseKeys(keyId: Long, pageable: Pageable = PageRequest.of(0, 10)): List + fun getCloseKeys( + keyId: Long, + pageable: Pageable = PageRequest.of(0, 10), + ): List @Query( """ @@ -34,12 +36,13 @@ interface KeysDistanceRepository : JpaRepository { kd.key2Id = :keyId order by kd.score desc ) and k.project.id = :projectId - """ + """, ) fun getCloseKeysWithBaseTranslation( keyId: Long, projectId: Long, - pageable: Pageable = PageRequest.of(0, 10) + pageable: Pageable = PageRequest.of(0, 10), ): List + fun deleteAllByProjectId(id: Long) } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/LanguageRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/LanguageRepository.kt index 5803647611..7e84bb395b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/LanguageRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/LanguageRepository.kt @@ -11,9 +11,21 @@ import java.util.* @Repository interface LanguageRepository : JpaRepository { - fun findByTagAndProject(abbreviation: String, project: io.tolgee.model.Project): Optional - fun findByNameAndProject(name: String?, project: io.tolgee.model.Project): Optional - fun findByTagAndProjectId(abbreviation: String?, projectId: Long): Optional + fun findByTagAndProject( + abbreviation: String, + project: io.tolgee.model.Project, + ): Optional + + fun findByNameAndProject( + name: String?, + project: io.tolgee.model.Project, + ): Optional + + fun findByTagAndProjectId( + abbreviation: String?, + projectId: Long, + ): Optional + fun findAllByProjectId(projectId: Long?): Set @Query( @@ -23,10 +35,18 @@ interface LanguageRepository : JpaRepository { join l.project p left join p.baseLanguage pb where l.project.id = :projectId - """ + """, ) - fun findAllByProjectId(projectId: Long?, pageable: Pageable): Page - fun findAllByTagInAndProjectId(abbreviation: Collection?, projectId: Long?): List + fun findAllByProjectId( + projectId: Long?, + pageable: Pageable, + ): Page + + fun findAllByTagInAndProjectId( + abbreviation: Collection?, + projectId: Long?, + ): List + fun deleteAllByProjectId(projectId: Long?) @Query( @@ -36,7 +56,7 @@ interface LanguageRepository : JpaRepository { join l.project p join p.baseLanguage bl where l.id = :id - """ + """, ) fun findView(id: Long): LanguageView? @@ -47,9 +67,17 @@ interface LanguageRepository : JpaRepository { join l.project p left join p.baseLanguage bl where l.project.id in :projectIds - """ + """, ) fun getViewsOfProjects(projectIds: List): List - fun countByIdInAndProjectId(languageIds: Set, projectId: Long): Int - fun findAllByProjectIdAndIdInOrderById(projectId: Long, languageIds: List): List + + fun countByIdInAndProjectId( + languageIds: Set, + projectId: Long, + ): Int + + fun findAllByProjectIdAndIdInOrderById( + projectId: Long, + languageIds: List, + ): List } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/LanguageStatsRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/LanguageStatsRepository.kt index 75d28c273c..4be1e153d0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/LanguageStatsRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/LanguageStatsRepository.kt @@ -14,7 +14,7 @@ interface LanguageStatsRepository : JpaRepository { from LanguageStats ls join ls.language l where l.project.id = :projectId - """ + """, ) fun getAllByProjectId(projectId: Long): List @@ -23,7 +23,7 @@ interface LanguageStatsRepository : JpaRepository { @Query( """ delete from LanguageStats ls where ls.language.id = :languageId - """ + """, ) fun deleteAllByLanguage(languageId: Long) @@ -33,7 +33,7 @@ interface LanguageStatsRepository : JpaRepository { join fetch ls.language l join fetch l.project where l.project.id in :projectIds - """ + """, ) fun getAllByProjectIds(projectIds: List): List } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/NamespaceRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/NamespaceRepository.kt index 3e05424e4a..3ea334c752 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/NamespaceRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/NamespaceRepository.kt @@ -10,45 +10,58 @@ import org.springframework.stereotype.Repository @Repository interface NamespaceRepository : JpaRepository { - fun findByNameAndProjectId(name: String, projectId: Long): Namespace? + fun findByNameAndProjectId( + name: String, + projectId: Long, + ): Namespace? @Query( """ select ns.id, count(k.id) from Key k join k.namespace ns on ns.id in :namespaceIds group by ns.id - """ + """, ) fun getKeysInNamespaceCount(namespaceIds: Collection): List> + fun getAllByProjectId(id: Long): List - fun getAllByProjectId(id: Long, pageable: Pageable): Page + fun getAllByProjectId( + id: Long, + pageable: Pageable, + ): Page @Query( """ select count(k) > 0 from Key k where k.namespace is null and k.project.id = :projectId - """ + """, ) fun isDefaultUsed(projectId: Long): Boolean @Query( """ from Namespace n where n.id = :namespaceId and n.project.id = :projectId - """ + """, ) - fun findOneByProjectIdAndId(projectId: Long, namespaceId: Long): Namespace? + fun findOneByProjectIdAndId( + projectId: Long, + namespaceId: Long, + ): Namespace? @Query( """ from Namespace n where n.name = :name and n.project.id = :projectId - """ + """, ) - fun findOneByProjectIdAndName(projectId: Long, name: String): Namespace? + fun findOneByProjectIdAndName( + projectId: Long, + name: String, + ): Namespace? @Modifying @Query( """ delete from namespace where project_id = :projectId """, - nativeQuery = true + nativeQuery = true, ) fun deleteAllByProjectId(projectId: Long) } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/OrganizationRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/OrganizationRepository.kt index 4062bdb6ce..db8c1b2777 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/OrganizationRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/OrganizationRepository.kt @@ -12,13 +12,12 @@ import org.springframework.stereotype.Repository @Repository interface OrganizationRepository : JpaRepository { - @Query( """ from Organization o left join fetch o.basePermission as bp where o.slug = :slug and o.deletedAt is null - """ + """, ) fun findBySlug(slug: String): Organization? @@ -35,7 +34,7 @@ interface OrganizationRepository : JpaRepository { and (:exceptOrganizationId is null or (o.id <> :exceptOrganizationId)) and o.deletedAt is null """, countQuery = - """select count(o) + """select count(o) from Organization o left join OrganizationRole r on r.user.id = :userId and r.organization = o and (r.type = :roleType or :roleType is null) @@ -44,14 +43,14 @@ interface OrganizationRepository : JpaRepository { where (perm is not null or r is not null) and (:search is null or (lower(o.name) like lower(concat('%', cast(:search as text), '%')))) and (:exceptOrganizationId is null or (o.id <> :exceptOrganizationId)) and o.deletedAt is null - """ + """, ) fun findAllPermitted( userId: Long?, pageable: Pageable, roleType: OrganizationRoleType? = null, search: String? = null, - exceptOrganizationId: Long? = null + exceptOrganizationId: Long? = null, ): Page @Query( @@ -65,12 +64,12 @@ interface OrganizationRepository : JpaRepository { where (perm is not null or mr is not null) and o.id <> :exceptOrganizationId and o.deletedAt is null group by mr.id, o.id, bp.id order by mr.id asc nulls last - """ + """, ) fun findPreferred( userId: Long, exceptOrganizationId: Long, - pageable: Pageable + pageable: Pageable, ): Page @Query( @@ -81,16 +80,19 @@ interface OrganizationRepository : JpaRepository { left join o.projects p on p.deletedAt is null left join p.permissions perm on perm.user.id = :userId where (perm is not null or mr is not null) and o.id = :organizationId and o.deletedAt is null - """ + """, ) - fun canUserView(userId: Long, organizationId: Long): Boolean + fun canUserView( + userId: Long, + organizationId: Long, + ): Boolean @Query( """ select count(o) > 0 from Organization o where o.slug = :slug - """ + """, ) fun organizationWithSlugExists(slug: String): Boolean @@ -98,7 +100,7 @@ interface OrganizationRepository : JpaRepository { """ from Organization o where o.name = :name and o.deletedAt is null - """ + """, ) fun findAllByName(name: String): List @@ -108,7 +110,7 @@ interface OrganizationRepository : JpaRepository { join o.memberRoles mr on mr.user = :user join mr.user u where o.name = u.name and mr.type = 1 and o.deletedAt is null - """ + """, ) fun findUsersDefaultOrganization(user: UserAccount): Organization? @@ -121,13 +123,17 @@ interface OrganizationRepository : JpaRepository { and o.deletedAt is null """, countQuery = - """select count(o) + """select count(o) from Organization o where (:search is null or (lower(o.name) like lower(concat('%', cast(:search as text), '%')))) and o.deletedAt is null - """ + """, ) - fun findAllViews(pageable: Pageable, search: String?, userId: Long): Page + fun findAllViews( + pageable: Pageable, + search: String?, + userId: Long, + ): Page @Query( """select o @@ -137,11 +143,11 @@ interface OrganizationRepository : JpaRepository { where o.deletedAt is null group by o.id, mr.id having count(mra.id) = 1 - """ + """, ) fun getAllSingleOwnedByUser( userAccount: UserAccount, - type: OrganizationRoleType = OrganizationRoleType.OWNER + type: OrganizationRoleType = OrganizationRoleType.OWNER, ): List @Query( @@ -150,7 +156,7 @@ interface OrganizationRepository : JpaRepository { join o.projects p on p.id = :projectId and p.deletedAt is null join fetch o.basePermission where o.deletedAt is null - """ + """, ) fun getProjectOwner(projectId: Long): Organization @@ -160,7 +166,7 @@ interface OrganizationRepository : JpaRepository { left join fetch o.basePermission left join fetch o.mtCreditBucket where o = :organization - """ + """, ) fun fetchData(organization: Organization): Organization @@ -168,7 +174,7 @@ interface OrganizationRepository : JpaRepository { """ from Organization o where o.id = :id and o.deletedAt is null - """ + """, ) fun find(id: Long): Organization? } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/OrganizationRoleRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/OrganizationRoleRepository.kt index f2da16e00f..6ce577f7f8 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/OrganizationRoleRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/OrganizationRoleRepository.kt @@ -8,12 +8,15 @@ import org.springframework.stereotype.Repository @Repository interface OrganizationRoleRepository : JpaRepository { - fun findOneByUserIdAndOrganizationId(userId: Long, organizationId: Long): OrganizationRole? + fun findOneByUserIdAndOrganizationId( + userId: Long, + organizationId: Long, + ): OrganizationRole? fun countAllByOrganizationIdAndTypeAndUserIdNot( id: Long, owner: OrganizationRoleType, - userId: Long + userId: Long, ): Long fun deleteByOrganization(organization: Organization) diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/PatRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/PatRepository.kt index 5774110a98..66dcfb512f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/PatRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/PatRepository.kt @@ -11,9 +11,15 @@ import java.util.* interface PatRepository : JpaRepository { fun findByTokenHash(tokenHash: String): Pat? - fun findAllByUserAccountId(userId: Long, pageable: Pageable): Page + fun findAllByUserAccountId( + userId: Long, + pageable: Pageable, + ): Page @Modifying @Query("UPDATE Pat p SET p.lastUsedAt = ?2 WHERE p.id = ?1") - fun updateLastUsedById(id: Long, lastUsed: Date) + fun updateLastUsedById( + id: Long, + lastUsed: Date, + ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/PermissionRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/PermissionRepository.kt index 90fb92e37f..828de80567 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/PermissionRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/PermissionRepository.kt @@ -8,7 +8,6 @@ import org.springframework.stereotype.Repository @Repository interface PermissionRepository : JpaRepository { - @Query( """ from Permission p @@ -16,12 +15,12 @@ interface PermissionRepository : JpaRepository { ((:projectId is null and p.project.id is null) or p.project.id = :projectId) and ((:userId is null and p.user.id is null) or p.user.id = :userId) and ((:organizationId is null and p.organization.id is null) or p.organization.id = :organizationId) - """ + """, ) fun findOneByProjectIdAndUserIdAndOrganizationId( projectId: Long?, userId: Long?, - organizationId: Long? = null + organizationId: Long? = null, ): Permission? fun getAllByProjectAndUserNotNull(project: io.tolgee.model.Project?): Set @@ -36,7 +35,7 @@ interface PermissionRepository : JpaRepository { left join fetch p.viewLanguages left join fetch p.translateLanguages left join fetch p.stateChangeLanguages - where p.project.id = :projectId""" + where p.project.id = :projectId""", ) fun getByProjectWithFetchedLanguages(projectId: Long): List @@ -47,7 +46,7 @@ interface PermissionRepository : JpaRepository { left join p.viewLanguages vl on vl = :language left join p.stateChangeLanguages scl on scl = :language where tl.id is not null or vl.id is not null or scl.id is not null - """ + """, ) fun findAllByPermittedLanguage(language: Language): List @@ -57,9 +56,12 @@ interface PermissionRepository : JpaRepository { join p.translateLanguages l where p.user.id in :userIds and p.project.id = :projectId - """ + """, ) - fun getUserPermittedLanguageIds(userIds: List, projectId: Long): List> + fun getUserPermittedLanguageIds( + userIds: List, + projectId: Long, + ): List> @Query( """ @@ -67,14 +69,17 @@ interface PermissionRepository : JpaRepository { join p.translateLanguages l where p.project.id in :projectIds and p.user.id = :userId - """ + """, ) - fun getProjectPermittedLanguageIds(projectIds: List, userId: Long): List> + fun getProjectPermittedLanguageIds( + projectIds: List, + userId: Long, + ): List> @Query( """ from Permission p where p.organization.id in :ids - """ + """, ) fun getOrganizationBasePermissions(ids: Iterable): List @@ -84,7 +89,10 @@ interface PermissionRepository : JpaRepository { join p.project pr join pr.organizationOwner oo on oo.id = :organizationId where p.user.id = :userId - """ + """, ) - fun findAllByOrganizationAndUserId(organizationId: Long, userId: Long): List + fun findAllByOrganizationAndUserId( + organizationId: Long, + userId: Long, + ): List } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/ProjectRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/ProjectRepository.kt index 276f0f157a..d2246efe7e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/ProjectRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/ProjectRepository.kt @@ -32,7 +32,7 @@ interface ProjectRepository : JpaRepository { left join fetch OrganizationRole role on role.organization = o and role.user.id = :userAccountId where (p is not null or (role is not null)) and r.deletedAt is null order by r.name - """ + """, ) fun findAllPermitted(userAccountId: Long): List> @@ -50,13 +50,13 @@ interface ProjectRepository : JpaRepository { or lower(o.name) like lower(concat('%', cast(:search as text),'%'))) ) and (:organizationId is null or o.id = :organizationId) and r.deletedAt is null - """ + """, ) fun findAllPermitted( userAccountId: Long, pageable: Pageable, @Param("search") search: String? = null, - organizationId: Long? = null + organizationId: Long? = null, ): Page fun findAllByOrganizationOwnerId(organizationOwnerId: Long): List @@ -68,14 +68,17 @@ interface ProjectRepository : JpaRepository { """ $BASE_VIEW_QUERY where r.id = :projectId and r.deletedAt is null - """ + """, ) - fun findViewById(userAccountId: Long, projectId: Long): ProjectView? + fun findViewById( + userAccountId: Long, + projectId: Long, + ): ProjectView? @Query( """ from Project p where p.name = :name and p.deletedAt is null - """ + """, ) fun findAllByName(name: String): List @@ -83,15 +86,18 @@ interface ProjectRepository : JpaRepository { """ from Project p where p.name = :name and p.organizationOwner = :organization and p.deletedAt is null - """ + """, ) - fun findAllByNameAndOrganizationOwner(name: String, organization: Organization): List + fun findAllByNameAndOrganizationOwner( + name: String, + organization: Organization, + ): List @Query( """ from Project p where p.organizationOwner is null and p.userOwner is not null and p.deletedAt is null - """ + """, ) fun findAllWithUserOwner(pageable: Pageable): Page @@ -100,7 +106,7 @@ interface ProjectRepository : JpaRepository { select p.id from Project p where p.organizationOwner is null and p.deletedAt is null - """ + """, ) fun findAllWithUserOwnerIds(): List @@ -111,14 +117,17 @@ interface ProjectRepository : JpaRepository { join p.permissions pp on pp.user.id in :userIds join fetch p.baseLanguage where p.organizationOwner.id = :organizationId and p.deletedAt is null - """ + """, ) - fun getProjectsWithDirectPermissions(organizationId: Long, userIds: List): List> + fun getProjectsWithDirectPermissions( + organizationId: Long, + userIds: List, + ): List> @Query( """ from Project where id = :id and deletedAt is null - """ + """, ) fun find(id: Long): Project? } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/QuickStartRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/QuickStartRepository.kt index 377067bdc5..345c3cb8e6 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/QuickStartRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/QuickStartRepository.kt @@ -7,5 +7,9 @@ import org.springframework.stereotype.Repository @Repository interface QuickStartRepository : JpaRepository { fun findByUserAccountId(userAccountId: Long): QuickStart? - fun findByUserAccountIdAndOrganizationId(userAccountId: Long, organizationId: Long): QuickStart? + + fun findByUserAccountIdAndOrganizationId( + userAccountId: Long, + organizationId: Long, + ): QuickStart? } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/ScreenshotRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/ScreenshotRepository.kt index 7e9ee3c36d..6079e3dd05 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/ScreenshotRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/ScreenshotRepository.kt @@ -12,20 +12,20 @@ interface ScreenshotRepository : JpaRepository { @Query( """FROM Screenshot s where s.id in (select ksr.screenshot.id from Key k join k.keyScreenshotReferences ksr where k = :key) - """ + """, ) fun findAllByKey(key: Key): List @Query( """FROM Screenshot s join fetch s.keyScreenshotReferences ksr where s.id in (select ksr.screenshot.id from Key k join k.keyScreenshotReferences ksr where k.project.id = :projectId) - """ + """, ) fun getAllByKeyProjectId(projectId: Long): List @Query( """SELECT count(s.id) FROM Screenshot s where s.id in - (select ksr.screenshot.id from Key k join k.keyScreenshotReferences ksr where k = :key)""" + (select ksr.screenshot.id from Key k join k.keyScreenshotReferences ksr where k = :key)""", ) fun countByKey(key: Key): Long @@ -37,7 +37,7 @@ interface ScreenshotRepository : JpaRepository { left join fetch k.namespace n where k.id in :keyIds order by k.id, ksr.screenshot.id - """ + """, ) fun getKeysWithScreenshots(keyIds: Collection): List @@ -48,7 +48,7 @@ interface ScreenshotRepository : JpaRepository { left join fetch k.namespace where ksr.screenshot in :screenshots order by k.id, ksr.screenshot.id - """ + """, ) fun getScreenshotReferences(screenshots: Collection): List @@ -58,7 +58,7 @@ interface ScreenshotRepository : JpaRepository { join fetch s.keyScreenshotReferences ksr join fetch ksr.key k where s in :screenshots - """ + """, ) fun getScreenshotsWithReferences(screenshots: Collection): List @@ -67,7 +67,7 @@ interface ScreenshotRepository : JpaRepository { from Screenshot s join fetch s.keyScreenshotReferences ksr where s.id in :ids - """ + """, ) fun findAllById(ids: Collection): List @@ -78,7 +78,10 @@ interface ScreenshotRepository : JpaRepository { join fetch ksr.screenshot s where k in :keys and s.location in :locations - """ + """, ) - fun getKeyScreenshotReferences(keys: List, locations: List): List + fun getKeyScreenshotReferences( + keys: List, + locations: List, + ): List } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/TagRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/TagRepository.kt index 4044360707..4908d0ea95 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/TagRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/TagRepository.kt @@ -11,22 +11,32 @@ import org.springframework.data.jpa.repository.Modifying import org.springframework.data.jpa.repository.Query interface TagRepository : JpaRepository { - fun findByProjectAndName(project: Project, name: String): Tag? + fun findByProjectAndName( + project: Project, + name: String, + ): Tag? @Query( """ from Tag t where t.project.id = :projectId and (:search is null or lower(name) like lower(concat('%', cast(:search as text),'%'))) - """ + """, ) - fun findAllByProject(projectId: Long, search: String? = null, pageable: Pageable): Page + fun findAllByProject( + projectId: Long, + search: String? = null, + pageable: Pageable, + ): Page @Query( """ from Tag t where t.project.id = :projectId and t.name in :tags - """ + """, ) - fun findAllByProject(projectId: Long, tags: Collection): List + fun findAllByProject( + projectId: Long, + tags: Collection, + ): List @Query( """ @@ -34,7 +44,7 @@ interface TagRepository : JpaRepository { left join fetch k.keyMeta km left join fetch km.tags where k.id in :keyIds - """ + """, ) fun getKeysWithTags(keyIds: Iterable): List @@ -44,7 +54,7 @@ interface TagRepository : JpaRepository { join fetch k.keyMeta km join fetch km.tags where k.id in :keyIds - """ + """, ) fun getImportKeysWithTags(keyIds: Iterable): List @@ -53,9 +63,10 @@ interface TagRepository : JpaRepository { from Tag t join fetch t.keyMetas where t.id in :tagIds - """ + """, ) fun getTagsWithKeyMetas(tagIds: Iterable): List + fun findAllByProjectId(projectId: Long): List @Modifying(flushAutomatically = true) @@ -65,7 +76,7 @@ interface TagRepository : JpaRepository { where t.id in (select tag.id from Tag tag left join tag.keyMetas km group by tag.id having count(km) = 0) and t.project.id = :projectId - """ + """, ) fun deleteAllUnused(projectId: Long) @@ -74,7 +85,7 @@ interface TagRepository : JpaRepository { """ delete from Tag t where (t.id in (select tag.id from Tag tag join tag.keyMetas km join km.key k where k in :keys)) - """ + """, ) fun deleteAllByKeyIn(keys: Collection) @@ -83,7 +94,7 @@ interface TagRepository : JpaRepository { from Tag t join fetch t.keyMetas km where km.key.id in :keyIds - """ + """, ) fun getAllByKeyIds(keyIds: Collection): List } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/TranslationRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/TranslationRepository.kt index 6d6200583f..6ce9db72e0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/TranslationRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/TranslationRepository.kt @@ -28,23 +28,39 @@ interface TranslationRepository : JpaRepository { and l.tag in :languages and ((n.name is null and :namespace is null) or n.name = :namespace) order by k.name - """ + """, ) - fun getTranslations(languages: Set, namespace: String?, projectId: Long): List + fun getTranslations( + languages: Set, + namespace: String?, + projectId: Long, + ): List @Query( "from Translation t " + "join fetch Key k on t.key = k " + - "where k = :key and k.project = :project and t.language in :languages" + "where k = :key and k.project = :project and t.language in :languages", ) - fun getTranslations(key: Key, project: Project, languages: Collection): Set - fun findOneByKeyAndLanguage(key: Key, language: Language): Optional - fun findOneByKeyIdAndLanguageId(key: Long, language: Long): Translation? + fun getTranslations( + key: Key, + project: Project, + languages: Collection, + ): Set + + fun findOneByKeyAndLanguage( + key: Key, + language: Language, + ): Optional + + fun findOneByKeyIdAndLanguageId( + key: Long, + language: Long, + ): Translation? @Query( """ from Translation t join fetch t.key k left join fetch k.keyMeta where t.language.id = :languageId - """ + """, ) fun getAllByLanguageId(languageId: Long): List @@ -53,13 +69,13 @@ interface TranslationRepository : JpaRepository { join fetch t.key k left join fetch k.keyMeta left join fetch t.comments - where t.key.id in :keyIds""" + where t.key.id in :keyIds""", ) fun getAllByKeyIdIn(keyIds: Collection): Collection @Query( """select t.id from Translation t where t.key.id in - (select k.id from t.key k where k.project.id = :projectId)""" + (select k.id from t.key k where k.project.id = :projectId)""", ) fun selectIdsByProject(projectId: Long): List @@ -84,14 +100,14 @@ interface TranslationRepository : JpaRepository { cast(similarity(baseTranslation.text, :baseTranslationText) as float)> 0.5F and (:key is null or key <> :key) order by similarity desc - """ + """, ) fun getTranslateMemorySuggestions( baseTranslationText: String, key: Key? = null, baseLanguage: Language, targetLanguage: Language, - pageable: Pageable + pageable: Pageable, ): Page @Query( @@ -108,21 +124,21 @@ interface TranslationRepository : JpaRepository { where baseTranslation.language = :baseLanguage and baseTranslation.text = :baseTranslationText and key <> :key - """ + """, ) fun getTranslationMemoryValue( baseTranslationText: String, key: Key, baseLanguage: Language, targetLanguage: Language, - pageable: Pageable = PageRequest.of(0, 1) + pageable: Pageable = PageRequest.of(0, 1), ): List @Query( """ select t.id as id, t.text as text, t.language.tag as languageTag from Translation t - """ + """, ) fun findAllForStatsUpdate(pageable: Pageable): Page @@ -130,9 +146,9 @@ interface TranslationRepository : JpaRepository { """ select t.id from Translation t - where t.text <> null and (t.wordCount is null or t.characterCount is null or (length(text) <> 0 and t.characterCount = 0)) + where t.text is not null and (t.wordCount is null or t.characterCount is null or (length(text) <> 0 and t.characterCount = 0)) order by t.id - """ + """, ) fun findAllIdsForStatsUpdate(): List @@ -147,7 +163,7 @@ interface TranslationRepository : JpaRepository { join k.project p where t.language.id <> p.baseLanguage.id ) - """ + """, ) @Modifying fun setOutdated(keyIds: List) @@ -157,26 +173,40 @@ interface TranslationRepository : JpaRepository { from Translation t join t.language l on l.tag in :languageTags where t.key.id in :keys - """ + """, ) - fun getForKeys(keys: List, languageTags: List): List + fun getForKeys( + keys: List, + languageTags: List, + ): List + + fun findAllByKeyIdInAndLanguageIdIn( + keysIds: List, + languagesIds: List, + ): List - fun findAllByKeyIdInAndLanguageIdIn(keysIds: List, languagesIds: List): List - fun getAllByKeyIdInAndLanguageIdIn(keyIds: List, languageIds: List): List + fun getAllByKeyIdInAndLanguageIdIn( + keyIds: List, + languageIds: List, + ): List @Query( """ from Translation t join t.key k where k.project.id = :projectId - """ + """, ) fun getAllByProjectId(projectId: Long): List + @Query( """ from Translation t where t.key = :key and t.language.tag in :languageTags - """ + """, ) - fun findForKeyByLanguages(key: Key, languageTags: Collection): List + fun findForKeyByLanguages( + key: Key, + languageTags: Collection, + ): List } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/UserAccountRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/UserAccountRepository.kt index cdd65fbb78..e5d6b4fe87 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/UserAccountRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/UserAccountRepository.kt @@ -39,9 +39,12 @@ interface UserAccountRepository : JpaRepository { ua.username = 'former', ua.name = 'Former user' where ua = :user - """ + """, + ) + fun softDeleteUser( + user: UserAccount, + now: Date, ) - fun softDeleteUser(user: UserAccount, now: Date) @Query( """ @@ -50,11 +53,11 @@ interface UserAccountRepository : JpaRepository { and ua.thirdPartyAuthType = :thirdPartyAuthType and ua.deletedAt is null and ua.disabledAt is null - """ + """, ) fun findThirdByThirdParty( thirdPartyAuthId: String, - thirdPartyAuthType: String + thirdPartyAuthType: String, ): Optional @Query( @@ -70,12 +73,12 @@ interface UserAccountRepository : JpaRepository { or lower(ua.username) like lower(concat('%', cast(:search as text),'%'))) or cast(:search as text) is null) and ua.deletedAt is null group by ua.id, mr.type - """ + """, ) fun getAllInOrganization( organizationId: Long, pageable: Pageable, - search: String + search: String, ): Page @Query( @@ -92,13 +95,13 @@ interface UserAccountRepository : JpaRepository { like lower(concat('%', cast(:search as text),'%')) or lower(ua.username) like lower(concat('%', cast(:search as text),'%'))) or cast(:search as text) is null) and ua.deletedAt is null - """ + """, ) fun getAllInProject( projectId: Long, pageable: Pageable, search: String? = "", - exceptUserId: Long? = null + exceptUserId: Long? = null, ): Page @Query( @@ -108,7 +111,7 @@ interface UserAccountRepository : JpaRepository { left join ua.organizationRoles orl where orl is null and ua.deletedAt is null - """ + """, ) fun findAllWithoutAnyOrganization(pageable: Pageable): Page @@ -119,7 +122,7 @@ interface UserAccountRepository : JpaRepository { left join ua.organizationRoles orl where orl is null and ua.deletedAt is null - """ + """, ) fun findAllWithoutAnyOrganizationIds(): List @@ -130,28 +133,31 @@ interface UserAccountRepository : JpaRepository { like lower(concat('%', cast(:search as text),'%')) or lower(userAccount.username) like lower(concat('%', cast(:search as text),'%'))) or cast(:search as text) is null) and userAccount.deletedAt is null - """ + """, ) - fun findAllWithDisabledPaged(search: String?, pageable: Pageable): Page + fun findAllWithDisabledPaged( + search: String?, + pageable: Pageable, + ): Page @Query( value = """ select ua from UserAccount ua where id in (:ids) - """ + """, ) fun getAllByIdsIncludingDeleted(ids: Set): MutableList @Query( value = """ select count(ua) from UserAccount ua where ua.disabledAt is null and ua.deletedAt is null - """ + """, ) fun countAllEnabled(): Long @Query( value = """ select ua from UserAccount ua where ua.id = :id and ua.disabledAt is not null - """ + """, ) fun findDisabled(id: Long): UserAccount @@ -161,7 +167,7 @@ interface UserAccountRepository : JpaRepository { left join fetch ua.emailVerification left join fetch ua.permissions where ua.id = :id - """ + """, ) fun findWithFetchedEmailVerificationAndPermissions(id: Long): UserAccount? @@ -171,7 +177,7 @@ interface UserAccountRepository : JpaRepository { left join fetch ua.emailVerification left join fetch ua.permissions where ua.username in :usernames and ua.deletedAt is null - """ + """, ) fun findActiveWithFetchedDataByUserNames(usernames: List): List } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/WebhookConfigRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/WebhookConfigRepository.kt index 6cc424ddaa..41e9282063 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/WebhookConfigRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/WebhookConfigRepository.kt @@ -10,23 +10,28 @@ import org.springframework.stereotype.Repository @Repository interface WebhookConfigRepository : JpaRepository { - @Query( """ from WebhookConfig wc left join fetch wc.automationActions aa where wc.id = :id and wc.project.id = :projectId - """ + """, ) - fun findByIdAndProjectId(id: Long, projectId: Long): WebhookConfig? + fun findByIdAndProjectId( + id: Long, + projectId: Long, + ): WebhookConfig? @Query( """ from WebhookConfig wc where wc.project.id = :projectId - """ + """, ) - fun findByProjectId(projectId: Long, pageable: Pageable): Page + fun findByProjectId( + projectId: Long, + pageable: Pageable, + ): Page fun countByProject(project: Project): Int } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/activity/ActivityModifiedEntityRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/activity/ActivityModifiedEntityRepository.kt index 722d91452f..133fd0d748 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/activity/ActivityModifiedEntityRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/activity/ActivityModifiedEntityRepository.kt @@ -1,7 +1,7 @@ package io.tolgee.repository.activity import io.tolgee.activity.data.ActivityType -import io.tolgee.dtos.query_results.TranslationHistoryView +import io.tolgee.dtos.queryResults.TranslationHistoryView import io.tolgee.model.activity.ActivityModifiedEntity import io.tolgee.model.activity.ActivityModifiedEntityId import org.springframework.data.domain.Page @@ -12,7 +12,6 @@ import org.springframework.stereotype.Repository @Repository interface ActivityModifiedEntityRepository : JpaRepository { - @Query( """ select ame.modifications as modifications, ar.timestamp as timestamp, @@ -23,11 +22,11 @@ interface ActivityModifiedEntityRepository : JpaRepository + ignoredActivityTypes: List, ): Page } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/activity/ActivityRevisionRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/activity/ActivityRevisionRepository.kt index 3fa61f499f..0ad3e237a4 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/activity/ActivityRevisionRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/activity/ActivityRevisionRepository.kt @@ -15,9 +15,13 @@ interface ActivityRevisionRepository : JpaRepository { """ from ActivityRevision ar where ar.projectId = :projectId and ar.type is not null and ar.batchJobChunkExecution is null and ar.type in :types - """ + """, ) - fun getForProject(projectId: Long, pageable: Pageable, types: List): Page + fun getForProject( + projectId: Long, + pageable: Pageable, + types: List, + ): Page @Query( """ @@ -26,11 +30,11 @@ interface ActivityRevisionRepository : JpaRepository { join ar.describingRelations dr where ar.id in :revisionIds and ar.type in :allowedTypes - """ + """, ) fun getRelationsForRevisions( revisionIds: List, - allowedTypes: Collection + allowedTypes: Collection, ): List @Query( @@ -41,9 +45,12 @@ interface ActivityRevisionRepository : JpaRepository { where ar.id in :revisionIds and ar.type in :allowedTypes group by ar.id, me.entityClass - """ + """, ) - fun getModifiedEntityTypeCounts(revisionIds: List, allowedTypes: Collection): List> + fun getModifiedEntityTypeCounts( + revisionIds: List, + allowedTypes: Collection, + ): List> @Query( """ @@ -52,7 +59,7 @@ interface ActivityRevisionRepository : JpaRepository { where ar.projectId = :projectId group by date order by date - """ + """, ) fun getProjectDailyActivity(projectId: Long): List> } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/contentDelivery/ContentDeliveryConfigRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/contentDelivery/ContentDeliveryConfigRepository.kt index ceccf2e3f1..0fb67b855b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/contentDelivery/ContentDeliveryConfigRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/contentDelivery/ContentDeliveryConfigRepository.kt @@ -14,9 +14,12 @@ interface ContentDeliveryConfigRepository : JpaRepository + fun findAllByProjectId( + projectId: Long, + pageable: Pageable, + ): Page @Query( """ from ContentDeliveryConfig e left join fetch e.automationActions where e.id = :contentDeliveryConfigId and e.project.id = :projectId - """ + """, ) - fun getByProjectIdAndId(projectId: Long, contentDeliveryConfigId: Long): ContentDeliveryConfig + fun getByProjectIdAndId( + projectId: Long, + contentDeliveryConfigId: Long, + ): ContentDeliveryConfig + fun countByProject(project: Project): Int } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/contentDelivery/ContentStorageRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/contentDelivery/ContentStorageRepository.kt index fa6bf8ead3..56c4b8f377 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/contentDelivery/ContentStorageRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/contentDelivery/ContentStorageRepository.kt @@ -9,13 +9,20 @@ import org.springframework.stereotype.Repository @Repository interface ContentStorageRepository : JpaRepository { - fun findAllByProjectId(projectId: Long, pageable: Pageable): Page - fun getByProjectIdAndId(projectId: Long, contentDeliveryConfigId: Long): ContentStorage + fun findAllByProjectId( + projectId: Long, + pageable: Pageable, + ): Page + + fun getByProjectIdAndId( + projectId: Long, + contentDeliveryConfigId: Long, + ): ContentStorage @Query( """ select count(*) > 0 from ContentDeliveryConfig cdc where cdc.contentStorage = :storage - """ + """, ) fun isStorageInUse(storage: ContentStorage): Boolean } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/ImportKeyRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/ImportKeyRepository.kt index 48fc1674ad..cbe795c7b8 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/ImportKeyRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/ImportKeyRepository.kt @@ -16,7 +16,7 @@ interface ImportKeyRepository : JpaRepository { left join fetch ik.keyMeta km join fetch ik.file if join fetch if.import im where im.id = :importId - """ + """, ) fun findAllByImport(importId: Long): List diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/ImportLanguageRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/ImportLanguageRepository.kt index a70b103acf..e63130eff8 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/ImportLanguageRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/ImportLanguageRepository.kt @@ -15,7 +15,6 @@ import java.util.* @Repository interface ImportLanguageRepository : JpaRepository { - companion object { private const val VIEW_BASE_QUERY = """ select il.id as id, il.name as name, el.id as existingLanguageId, @@ -48,15 +47,18 @@ interface ImportLanguageRepository : JpaRepository { where if.import.id = :importId $VIEW_GROUP_BY order by il.id - """ + """, ) - fun findImportLanguagesView(importId: Long, pageable: Pageable): Page + fun findImportLanguagesView( + importId: Long, + pageable: Pageable, + ): Page @Modifying @Transactional @Query( """delete from ImportLanguage l where l.file in - (select f from ImportFile f where f.import = :import)""" + (select f from ImportFile f where f.import = :import)""", ) fun deleteAllByImport(import: Import) @@ -65,7 +67,7 @@ interface ImportLanguageRepository : JpaRepository { $VIEW_BASE_QUERY where il.id = :languageId $VIEW_GROUP_BY - """ + """, ) fun findViewById(languageId: Long): Optional @@ -76,7 +78,7 @@ interface ImportLanguageRepository : JpaRepository { join il.file if where if.import.id = :importId and il.existingLanguage.id is not null - """ + """, ) fun findAssignedExistingLanguageIds(importId: Long): List } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/ImportRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/ImportRepository.kt index 86cd65fc3d..8c5bc0139e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/ImportRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/ImportRepository.kt @@ -7,32 +7,34 @@ import org.springframework.stereotype.Repository @Repository interface ImportRepository : JpaRepository { - @Query( """ select i from Import i where i.project.id = :projectId and i.author.id = :authorId and i.deletedAt is null - """ + """, ) - fun findByProjectIdAndAuthorId(projectId: Long, authorId: Long): Import? + fun findByProjectIdAndAuthorId( + projectId: Long, + authorId: Long, + ): Import? @Query( """ select i from Import i where i.project.id = :projectId and i.deletedAt is null - """ + """, ) fun findAllByProjectId(projectId: Long): List @Query( """ select distinct if.namespace from ImportFile if where if.import.id = :importId - """ + """, ) fun getAllNamespaces(importId: Long): Set @Query( """ from Import i where i.id = :importId and i.deletedAt is not null - """ + """, ) fun findDeleted(importId: Long): Import? } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/ImportTranslationRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/ImportTranslationRepository.kt index 4a82ea5dcb..a166843ac1 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/ImportTranslationRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/ImportTranslationRepository.kt @@ -24,7 +24,7 @@ interface ImportTranslationRepository : JpaRepository { left join fetch ick.keyMeta join it.language il on il.id = :languageId join il.file if - """ + """, ) fun findAllByImportAndLanguageId(languageId: Long): List @@ -42,14 +42,14 @@ interface ImportTranslationRepository : JpaRepository { and it.language.id = :languageId and (:search is null or lower(it.text) like lower(concat('%', cast(:search as text), '%')) or lower(ik.name) like lower(concat('%', cast(:search as text), '%'))) - """ + """, ) fun findImportTranslationsView( languageId: Long, pageable: Pageable, onlyConflicts: Boolean = false, onlyUnresolved: Boolean = false, - search: String? = null + search: String? = null, ): Page @Transactional @@ -60,7 +60,7 @@ interface ImportTranslationRepository : JpaRepository { @Transactional @Query( """delete from ImportTranslation it where it.key.id in - (select k.id from ImportKey k join k.file f where f.import = :import)""" + (select k.id from ImportKey k join k.file f where f.import = :import)""", ) @Modifying fun deleteAllByImport(import: Import) diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/issues/ImportFileIssueParamRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/issues/ImportFileIssueParamRepository.kt index bd64bc1900..a35de151b5 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/issues/ImportFileIssueParamRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/issues/ImportFileIssueParamRepository.kt @@ -10,13 +10,12 @@ import org.springframework.transaction.annotation.Transactional @Repository interface ImportFileIssueParamRepository : JpaRepository { - @Transactional @Modifying @Query( """delete from ImportFileIssueParam ifip where ifip.issue in (select ifi from ifip.issue ifi join ifi.file if where if.import = :import) - """ + """, ) fun deleteAllByImport(import: Import) } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/issues/ImportFileIssueRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/issues/ImportFileIssueRepository.kt index 83c9daeded..c351a39779 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/issues/ImportFileIssueRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/dataImport/issues/ImportFileIssueRepository.kt @@ -13,14 +13,16 @@ import org.springframework.transaction.annotation.Transactional @Repository interface ImportFileIssueRepository : JpaRepository { - @Query("""select ifi from ImportFileIssue ifi where ifi.file.id = :fileId""") - fun findAllByFileIdView(fileId: Long, pageable: Pageable): Page + fun findAllByFileIdView( + fileId: Long, + pageable: Pageable, + ): Page @Transactional @Query( """delete from ImportFileIssue ifi where ifi.file in - (select f from ImportFile f where f.import = :import)""" + (select f from ImportFile f where f.import = :import)""", ) @Modifying fun deleteAllByImport(import: Import) diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/machineTranslation/MtServiceConfigRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/machineTranslation/MtServiceConfigRepository.kt index 68cc901cda..18c260aa9b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/machineTranslation/MtServiceConfigRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/machineTranslation/MtServiceConfigRepository.kt @@ -16,7 +16,7 @@ interface MtServiceConfigRepository : JpaRepository { ptsc.targetLanguage.id = :languageId or (ptsc.targetLanguage.id is null and ptsc.project.id = l.project.id) ) - """ + """, ) fun findAllByTargetLanguageId(languageId: Long): List @@ -31,7 +31,10 @@ interface MtServiceConfigRepository : JpaRepository { select ptsc from MtServiceConfig ptsc where ptsc.targetLanguage.id in :languageIds or (ptsc.targetLanguage.id is null and ptsc.project = :project) - """ + """, ) - fun findAllByTargetLanguageIdIn(languageIds: List, project: Project): List + fun findAllByTargetLanguageIdIn( + languageIds: List, + project: Project, + ): List } diff --git a/backend/data/src/main/kotlin/io/tolgee/repository/translation/TranslationCommentRepository.kt b/backend/data/src/main/kotlin/io/tolgee/repository/translation/TranslationCommentRepository.kt index 243c05fac6..eb217c7c8d 100644 --- a/backend/data/src/main/kotlin/io/tolgee/repository/translation/TranslationCommentRepository.kt +++ b/backend/data/src/main/kotlin/io/tolgee/repository/translation/TranslationCommentRepository.kt @@ -13,7 +13,10 @@ interface TranslationCommentRepository : JpaRepository fun deleteAllByIdIn(ids: List) @Query("select tc from TranslationComment tc left join fetch tc.author where tc.translation = :translation") - fun getPagedByTranslation(translation: Translation, pageable: Pageable): Page + fun getPagedByTranslation( + translation: Translation, + pageable: Pageable, + ): Page fun deleteAllByTranslationIdIn(translationIds: Collection) @@ -25,7 +28,7 @@ interface TranslationCommentRepository : JpaRepository join tc.translation t join t.key k where k.project.id = :projectId - """ + """, ) fun getAllByProjectId(projectId: Long): List @@ -34,7 +37,7 @@ interface TranslationCommentRepository : JpaRepository from TranslationComment tc left join fetch tc.author where tc.id = :id - """ + """, ) fun findWithFetchedAuthor(id: Long): TranslationComment? } diff --git a/backend/data/src/main/kotlin/io/tolgee/security/OrganizationHolder.kt b/backend/data/src/main/kotlin/io/tolgee/security/OrganizationHolder.kt index 9ce894064f..6511364a6c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/security/OrganizationHolder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/security/OrganizationHolder.kt @@ -5,7 +5,7 @@ import io.tolgee.model.Organization import io.tolgee.service.organization.OrganizationService open class OrganizationHolder( - private val organizationService: OrganizationService + private val organizationService: OrganizationService, ) { open val organizationEntity: Organization by lazy { organizationService.get(organization.id) diff --git a/backend/data/src/main/kotlin/io/tolgee/security/ProjectHolder.kt b/backend/data/src/main/kotlin/io/tolgee/security/ProjectHolder.kt index 3a5fca4129..207f90798c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/security/ProjectHolder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/security/ProjectHolder.kt @@ -5,7 +5,7 @@ import io.tolgee.model.Project import io.tolgee.service.project.ProjectService open class ProjectHolder( - private val projectService: ProjectService + private val projectService: ProjectService, ) { open val projectEntity: Project by lazy { projectService.get(project.id) diff --git a/backend/data/src/main/kotlin/io/tolgee/security/authentication/AuthenticationConfig.kt b/backend/data/src/main/kotlin/io/tolgee/security/authentication/AuthenticationConfig.kt index f0550be086..440879a604 100644 --- a/backend/data/src/main/kotlin/io/tolgee/security/authentication/AuthenticationConfig.kt +++ b/backend/data/src/main/kotlin/io/tolgee/security/authentication/AuthenticationConfig.kt @@ -28,10 +28,12 @@ import java.security.Key @Configuration class AuthenticationConfig( private val authenticationProperties: AuthenticationProperties, - private val fileStorage: FileStorage + private val fileStorage: FileStorage, ) { @Bean("jwt_signing_key") - fun jwtSigningKey(@Qualifier("jwt_signing_secret") bytes: ByteArray): Key { + fun jwtSigningKey( + @Qualifier("jwt_signing_secret") bytes: ByteArray, + ): Key { return Keys.hmacShaKeyFor(bytes) } diff --git a/backend/data/src/main/kotlin/io/tolgee/security/authentication/AuthenticationFacade.kt b/backend/data/src/main/kotlin/io/tolgee/security/authentication/AuthenticationFacade.kt index 6683760e46..9d767130fd 100644 --- a/backend/data/src/main/kotlin/io/tolgee/security/authentication/AuthenticationFacade.kt +++ b/backend/data/src/main/kotlin/io/tolgee/security/authentication/AuthenticationFacade.kt @@ -41,8 +41,9 @@ class AuthenticationFacade( get() = SecurityContextHolder.getContext().authentication is TolgeeAuthentication val authentication: TolgeeAuthentication - get() = SecurityContextHolder.getContext().authentication as? TolgeeAuthentication - ?: throw AuthenticationException(Message.UNAUTHENTICATED) + get() = + SecurityContextHolder.getContext().authentication as? TolgeeAuthentication + ?: throw AuthenticationException(Message.UNAUTHENTICATED) // -- CURRENT USER val authenticatedUser: UserAccountDto @@ -55,13 +56,14 @@ class AuthenticationFacade( get() = authenticatedUserEntityOrNull ?: throw AuthenticationException(Message.UNAUTHENTICATED) val authenticatedUserEntityOrNull: UserAccount? - get() = authenticatedUserOrNull?.let { - if (authentication.userAccountEntity == null) { - authentication.userAccountEntity = userAccountService.findActive(it.id) - } + get() = + authenticatedUserOrNull?.let { + if (authentication.userAccountEntity == null) { + authentication.userAccountEntity = userAccountService.findActive(it.id) + } - return authentication.userAccountEntity - } + return authentication.userAccountEntity + } // -- AUTHENTICATION METHOD AND DETAILS val isUserSuperAuthenticated: Boolean diff --git a/backend/data/src/main/kotlin/io/tolgee/security/authentication/JwtService.kt b/backend/data/src/main/kotlin/io/tolgee/security/authentication/JwtService.kt index eb90b268e1..7563edb179 100644 --- a/backend/data/src/main/kotlin/io/tolgee/security/authentication/JwtService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/security/authentication/JwtService.kt @@ -16,7 +16,13 @@ package io.tolgee.security.authentication -import io.jsonwebtoken.* +import io.jsonwebtoken.Claims +import io.jsonwebtoken.ExpiredJwtException +import io.jsonwebtoken.Jws +import io.jsonwebtoken.JwtParser +import io.jsonwebtoken.Jwts +import io.jsonwebtoken.MalformedJwtException +import io.jsonwebtoken.UnsupportedJwtException import io.jsonwebtoken.security.SignatureException import io.tolgee.component.CurrentDateProvider import io.tolgee.configuration.tolgee.AuthenticationProperties @@ -37,10 +43,11 @@ class JwtService( private val currentDateProvider: CurrentDateProvider, private val userAccountService: UserAccountService, ) { - private val jwtParser: JwtParser = Jwts.parserBuilder() - .setClock { currentDateProvider.date } - .setSigningKey(signingKey) - .build() + private val jwtParser: JwtParser = + Jwts.parserBuilder() + .setClock { currentDateProvider.date } + .setSigningKey(signingKey) + .build() /** * Emits an authentication token for the given user. @@ -49,16 +56,20 @@ class JwtService( * @param isSuper Whether to emit a super-powered token or not. * @return An authentication token. */ - fun emitToken(userAccountId: Long, isSuper: Boolean = false): String { + fun emitToken( + userAccountId: Long, + isSuper: Boolean = false, + ): String { val now = currentDateProvider.date val expiration = Date(now.time + authenticationProperties.jwtExpiration) - val builder = Jwts.builder() - .signWith(signingKey) - .setIssuedAt(now) - .setAudience(JWT_TOKEN_AUDIENCE) - .setSubject(userAccountId.toString()) - .setExpiration(expiration) + val builder = + Jwts.builder() + .signWith(signingKey) + .setIssuedAt(now) + .setAudience(JWT_TOKEN_AUDIENCE) + .setSubject(userAccountId.toString()) + .setExpiration(expiration) if (isSuper) { val superExpiration = Date(now.time + authenticationProperties.jwtSuperExpiration) @@ -85,13 +96,14 @@ class JwtService( ): String { val now = currentDateProvider.date - val builder = Jwts.builder() - .signWith(signingKey) - .setIssuedAt(now) - .setAudience(JWT_TICKET_AUDIENCE) - .setSubject(userAccountId.toString()) - .setExpiration(Date(now.time + expiresAfter)) - .claim(JWT_TICKET_TYPE_CLAIM, ticketType.name) + val builder = + Jwts.builder() + .signWith(signingKey) + .setIssuedAt(now) + .setAudience(JWT_TICKET_AUDIENCE) + .setSubject(userAccountId.toString()) + .setExpiration(Date(now.time + expiresAfter)) + .claim(JWT_TICKET_TYPE_CLAIM, ticketType.name) if (data != null) { builder.claim(JWT_TICKET_DATA_CLAIM, data) @@ -126,7 +138,7 @@ class JwtService( return TolgeeAuthentication( jws, account, - TolgeeAuthenticationDetails(hasSuperPowers) + TolgeeAuthenticationDetails(hasSuperPowers), ) } @@ -138,15 +150,19 @@ class JwtService( * @return The authenticated user account. * @throws AuthenticationException The ticket is invalid or expired. */ - fun validateTicket(token: String, expectedType: TicketType): TicketAuthentication { + fun validateTicket( + token: String, + expectedType: TicketType, + ): TicketAuthentication { val jws = parseJwt(token) if (jws.body.audience != JWT_TICKET_AUDIENCE) { // This is not a token - possibly a token or something else. throw AuthenticationException(Message.INVALID_JWT_TOKEN) } - val rawJwsType = jws.body[JWT_TICKET_TYPE_CLAIM] as? String - ?: throw AuthenticationException(Message.INVALID_JWT_TOKEN) + val rawJwsType = + jws.body[JWT_TICKET_TYPE_CLAIM] as? String + ?: throw AuthenticationException(Message.INVALID_JWT_TOKEN) val jwsType = TicketType.valueOf(rawJwsType) if (jwsType != expectedType) { @@ -162,8 +178,9 @@ class JwtService( } private fun validateJwt(claims: Claims): UserAccountDto { - val account = userAccountService.findDto(claims.subject.toLong()) - ?: throw AuthenticationException(Message.INVALID_JWT_TOKEN) + val account = + userAccountService.findDto(claims.subject.toLong()) + ?: throw AuthenticationException(Message.INVALID_JWT_TOKEN) if (account.tokensValidNotBefore != null && claims.issuedAt.before(account.tokensValidNotBefore)) { throw AuthenticationException(Message.EXPIRED_JWT_TOKEN) @@ -180,7 +197,8 @@ class JwtService( is SignatureException, is MalformedJwtException, is UnsupportedJwtException, - is IllegalArgumentException -> throw AuthenticationException(Message.INVALID_JWT_TOKEN) + is IllegalArgumentException, + -> throw AuthenticationException(Message.INVALID_JWT_TOKEN) is ExpiredJwtException -> throw AuthenticationException(Message.EXPIRED_JWT_TOKEN) else -> throw ex } diff --git a/backend/data/src/main/kotlin/io/tolgee/security/authentication/TicketAuthentication.kt b/backend/data/src/main/kotlin/io/tolgee/security/authentication/TicketAuthentication.kt index c69eccbf84..a40477d5e7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/security/authentication/TicketAuthentication.kt +++ b/backend/data/src/main/kotlin/io/tolgee/security/authentication/TicketAuthentication.kt @@ -20,5 +20,5 @@ import io.tolgee.dtos.cacheable.UserAccountDto data class TicketAuthentication( val userAccount: UserAccountDto, - val data: Map? + val data: Map?, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/security/authentication/TolgeeAuthentication.kt b/backend/data/src/main/kotlin/io/tolgee/security/authentication/TolgeeAuthentication.kt index 3c0d4ac461..b4a53d6157 100644 --- a/backend/data/src/main/kotlin/io/tolgee/security/authentication/TolgeeAuthentication.kt +++ b/backend/data/src/main/kotlin/io/tolgee/security/authentication/TolgeeAuthentication.kt @@ -40,10 +40,11 @@ class TolgeeAuthentication( override fun getAuthorities(): Collection { return when (userAccount.role) { UserAccount.Role.USER -> listOf(SimpleGrantedAuthority(ROLE_USER)) - UserAccount.Role.ADMIN -> listOf( - SimpleGrantedAuthority(ROLE_USER), - SimpleGrantedAuthority(ROLE_ADMIN) - ) + UserAccount.Role.ADMIN -> + listOf( + SimpleGrantedAuthority(ROLE_USER), + SimpleGrantedAuthority(ROLE_ADMIN), + ) null -> emptyList() } } diff --git a/backend/data/src/main/kotlin/io/tolgee/security/authentication/TolgeeAuthenticationDetails.kt b/backend/data/src/main/kotlin/io/tolgee/security/authentication/TolgeeAuthenticationDetails.kt index 4241dc9866..15f08bae49 100644 --- a/backend/data/src/main/kotlin/io/tolgee/security/authentication/TolgeeAuthenticationDetails.kt +++ b/backend/data/src/main/kotlin/io/tolgee/security/authentication/TolgeeAuthenticationDetails.kt @@ -20,5 +20,5 @@ data class TolgeeAuthenticationDetails( /** * Whether the user is super-authenticated */ - val isSuperToken: Boolean + val isSuperToken: Boolean, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/security/ratelimit/Bucket.kt b/backend/data/src/main/kotlin/io/tolgee/security/ratelimit/Bucket.kt index 8fdd1a6d32..bf08b38533 100644 --- a/backend/data/src/main/kotlin/io/tolgee/security/ratelimit/Bucket.kt +++ b/backend/data/src/main/kotlin/io/tolgee/security/ratelimit/Bucket.kt @@ -20,5 +20,5 @@ import java.io.Serializable data class Bucket( val tokens: Int, - val refillAt: Long + val refillAt: Long, ) : Serializable diff --git a/backend/data/src/main/kotlin/io/tolgee/security/ratelimit/RateLimitService.kt b/backend/data/src/main/kotlin/io/tolgee/security/ratelimit/RateLimitService.kt index 00ba30ade5..43e36d6042 100644 --- a/backend/data/src/main/kotlin/io/tolgee/security/ratelimit/RateLimitService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/security/ratelimit/RateLimitService.kt @@ -53,7 +53,10 @@ class RateLimitService( * @param policy The rate limit policy. * @throws RateLimitedException There are no longer any tokens in the bucket. */ - fun consumeBucketUnless(policy: RateLimitPolicy?, cond: () -> Boolean) { + fun consumeBucketUnless( + policy: RateLimitPolicy?, + cond: () -> Boolean, + ) { if (policy == null) return val lockName = getLockName(policy) @@ -88,7 +91,7 @@ class RateLimitService( rateLimitProperties.ipRequestLimit, Duration.ofMillis(rateLimitProperties.ipRequestWindow), true, - ) + ), ) } @@ -99,7 +102,10 @@ class RateLimitService( * @param userId The authenticated user ID. * @return The applicable rate limit policy, if any. */ - fun consumeGlobalUserRateLimitPolicy(request: HttpServletRequest, userId: Long) { + fun consumeGlobalUserRateLimitPolicy( + request: HttpServletRequest, + userId: Long, + ) { @Suppress("DEPRECATION") // TODO: remove for Tolgee 4 release if (!rateLimitProperties.enabled) return if (!rateLimitProperties.globalLimits) return @@ -110,7 +116,7 @@ class RateLimitService( rateLimitProperties.userRequestLimit, Duration.ofMillis(rateLimitProperties.userRequestWindow), true, - ) + ), ) } @@ -141,7 +147,10 @@ class RateLimitService( * @return The updated rate limit bucket. * @throws RateLimitedException There are no longer any tokens in the bucket. */ - private fun doConsumeBucket(policy: RateLimitPolicy, bucket: Bucket?): Bucket { + private fun doConsumeBucket( + policy: RateLimitPolicy, + bucket: Bucket?, + ): Bucket { val time = currentDateProvider.date.time if (bucket == null || bucket.refillAt < time) { val tokensRemaining = policy.limit - 1 diff --git a/backend/data/src/main/kotlin/io/tolgee/service/AnnouncementService.kt b/backend/data/src/main/kotlin/io/tolgee/service/AnnouncementService.kt index d9502c31c3..bb16db4ebd 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/AnnouncementService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/AnnouncementService.kt @@ -16,24 +16,29 @@ class AnnouncementService( private val currentDateProvider: CurrentDateProvider, private val userAccountService: UserAccountService, ) { - @Cacheable( cacheNames = [Caches.DISMISSED_ANNOUNCEMENT], - key = "{#announcement, #userId}" + key = "{#announcement, #userId}", ) - fun isAnnouncementDismissed(announcement: Announcement, userId: Long): Boolean { + fun isAnnouncementDismissed( + announcement: Announcement, + userId: Long, + ): Boolean { return announcementRepository.isDismissed(userId, announcement) } @CacheEvict( cacheNames = [Caches.DISMISSED_ANNOUNCEMENT], - key = "{#announcement, #userId}" + key = "{#announcement, #userId}", ) - fun dismissAnnouncement(announcement: Announcement, userId: Long) { + fun dismissAnnouncement( + announcement: Announcement, + userId: Long, + ) { val user = this.userAccountService.get(userId) if (!isAnnouncementDismissed(announcement, user.id)) { announcementRepository.save( - DismissedAnnouncement(announcement = announcement, user = user) + DismissedAnnouncement(announcement = announcement, user = user), ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/AvatarService.kt b/backend/data/src/main/kotlin/io/tolgee/service/AvatarService.kt index 9bba1426c5..fce4889cfa 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/AvatarService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/AvatarService.kt @@ -16,16 +16,20 @@ import java.security.MessageDigest @Service class AvatarService( private val fileStorage: FileStorage, - private val tolgeeProperties: TolgeeProperties + private val tolgeeProperties: TolgeeProperties, ) { companion object { - fun getAvatarPaths(hash: String) = Avatar( - large = "${FileStoragePath.AVATARS}/$hash.png", - thumbnail = "${FileStoragePath.AVATARS}/$hash-thumb.png" - ) + fun getAvatarPaths(hash: String) = + Avatar( + large = "${FileStoragePath.AVATARS}/$hash.png", + thumbnail = "${FileStoragePath.AVATARS}/$hash-thumb.png", + ) } - fun storeAvatarFiles(avatar: InputStream, entity: ModelWithAvatar): String { + fun storeAvatarFiles( + avatar: InputStream, + entity: ModelWithAvatar, + ): String { val avatarBytes = avatar.readAllBytes() val converter = ImageConverter(avatarBytes.inputStream()) val large = converter.getImage(-1f, Dimension(200, 200)).toByteArray() @@ -41,7 +45,10 @@ class AvatarService( } @Transactional - fun setAvatar(entity: ModelWithAvatar, avatar: InputStream) { + fun setAvatar( + entity: ModelWithAvatar, + avatar: InputStream, + ) { val hash = storeAvatarFiles(avatar, entity) removeAvatar(entity) entity.avatarHash = hash @@ -68,8 +75,9 @@ class AvatarService( } } - fun getAvatarLinks(paths: Avatar) = Avatar( - tolgeeProperties.fileStorageUrl + "/" + paths.large, - tolgeeProperties.fileStorageUrl + "/" + paths.thumbnail - ) + fun getAvatarLinks(paths: Avatar) = + Avatar( + tolgeeProperties.fileStorageUrl + "/" + paths.large, + tolgeeProperties.fileStorageUrl + "/" + paths.thumbnail, + ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/CachedPermissionService.kt b/backend/data/src/main/kotlin/io/tolgee/service/CachedPermissionService.kt index 83e813e6ba..9cf66c7ff4 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/CachedPermissionService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/CachedPermissionService.kt @@ -16,7 +16,7 @@ import org.springframework.transaction.annotation.Transactional @Service class CachedPermissionService( - private val permissionRepository: PermissionRepository + private val permissionRepository: PermissionRepository, ) { @set:Autowired lateinit var projectService: ProjectService @@ -31,7 +31,7 @@ class CachedPermissionService( @CacheEvict( cacheNames = [Caches.PERMISSIONS], - key = "{#permission.user?.id, #permission.project?.id, #permission.organization?.id}" + key = "{#permission.user?.id, #permission.project?.id, #permission.organization?.id}", ) fun delete(permission: Permission) { permissionRepository.delete(permission) @@ -39,14 +39,18 @@ class CachedPermissionService( @Cacheable( cacheNames = [Caches.PERMISSIONS], - key = "{#userId, #projectId, #organizationId}" + key = "{#userId, #projectId, #organizationId}", ) @Transactional - fun find(projectId: Long? = null, userId: Long? = null, organizationId: Long? = null): PermissionDto? { + fun find( + projectId: Long? = null, + userId: Long? = null, + organizationId: Long? = null, + ): PermissionDto? { return permissionRepository.findOneByProjectIdAndUserIdAndOrganizationId( projectId = projectId, userId = userId, - organizationId = organizationId + organizationId = organizationId, )?.let { permission -> PermissionDto( id = permission.id, @@ -59,16 +63,19 @@ class CachedPermissionService( viewLanguageIds = permission.viewLanguageIds, stateChangeLanguageIds = permission.stateChangeLanguageIds, type = permission.type, - granular = permission.granular + granular = permission.granular, ) } } @CacheEvict( cacheNames = [Caches.PERMISSIONS], - key = "{#permission.user?.id, #permission.project?.id, #permission.organization?.id}" + key = "{#permission.user?.id, #permission.project?.id, #permission.organization?.id}", ) - fun acceptInvitation(permission: Permission, userAccount: UserAccount): Permission { + fun acceptInvitation( + permission: Permission, + userAccount: UserAccount, + ): Permission { permission.invitation = null permission.user = userAccount return permissionRepository.save(permission) @@ -76,7 +83,7 @@ class CachedPermissionService( @CacheEvict( cacheNames = [Caches.PERMISSIONS], - key = "{#result.user?.id, #result.project?.id, #result.organization?.id}" + key = "{#result.user?.id, #result.project?.id, #result.organization?.id}", ) fun save(permission: Permission): Permission { return permissionRepository.save(permission) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/EmailVerificationService.kt b/backend/data/src/main/kotlin/io/tolgee/service/EmailVerificationService.kt index 5990a8e534..e227c043e2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/EmailVerificationService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/EmailVerificationService.kt @@ -28,7 +28,7 @@ class EmailVerificationService( private val tolgeeProperties: TolgeeProperties, private val emailVerificationRepository: EmailVerificationRepository, private val applicationEventPublisher: ApplicationEventPublisher, - private val emailVerificationSender: EmailVerificationSender + private val emailVerificationSender: EmailVerificationSender, ) { @Lazy @Autowired @@ -38,16 +38,17 @@ class EmailVerificationService( fun createForUser( userAccount: UserAccount, callbackUrl: String? = null, - newEmail: String? = null + newEmail: String? = null, ): EmailVerification? { if (tolgeeProperties.authentication.needsEmailVerification) { val resultCallbackUrl = getCallbackUrl(callbackUrl) val code = generateCode() - val emailVerification = userAccount.emailVerification?.also { - it.newEmail = newEmail - it.code = code - } ?: EmailVerification(userAccount = userAccount, code = code, newEmail = newEmail) + val emailVerification = + userAccount.emailVerification?.also { + it.newEmail = newEmail + it.code = code + } ?: EmailVerification(userAccount = userAccount, code = code, newEmail = newEmail) emailVerificationRepository.save(emailVerification) userAccount.emailVerification = emailVerification @@ -72,7 +73,10 @@ class EmailVerificationService( } @Transactional - fun verify(userId: Long, code: String) { + fun verify( + userId: Long, + code: String, + ) { val user = userAccountService.findActive(userId) ?: throw NotFoundException() val old = UserAccountDto.fromEntity(user) val emailVerification = user.emailVerification @@ -99,7 +103,10 @@ class EmailVerificationService( } } - private fun setNewEmailIfChanged(newEmail: String?, user: UserAccount) { + private fun setNewEmailIfChanged( + newEmail: String?, + user: UserAccount, + ) { newEmail?.let { user.username = newEmail } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/ImageUploadService.kt b/backend/data/src/main/kotlin/io/tolgee/service/ImageUploadService.kt index 3ee1719d89..359e5ea908 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/ImageUploadService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/ImageUploadService.kt @@ -27,7 +27,7 @@ class ImageUploadService( val uploadedImageRepository: UploadedImageRepository, val fileStorage: FileStorage, val dateProvider: CurrentDateProvider, - val maxUploadedFilesByUserProvider: MaxUploadedFilesByUserProvider + val maxUploadedFilesByUserProvider: MaxUploadedFilesByUserProvider, ) { val logger = LoggerFactory.getLogger(ImageUploadService::class.java) @@ -36,7 +36,11 @@ class ImageUploadService( } @Transactional - fun store(image: InputStreamSource, userAccount: UserAccount, info: ImageUploadInfoDto?): UploadedImage { + fun store( + image: InputStreamSource, + userAccount: UserAccount, + info: ImageUploadInfoDto?, + ): UploadedImage { if (uploadedImageRepository.countAllByUserAccount(userAccount) > maxUploadedFilesByUserProvider()) { throw BadRequestException(Message.TOO_MANY_UPLOADED_IMAGES) } @@ -44,15 +48,16 @@ class ImageUploadService( val imageConverter = ImageConverter(image.inputStream) val dimension = imageConverter.originalDimension - val uploadedImageEntity = UploadedImage(generateFilename(), userAccount) - .apply { - extension = "png" - originalWidth = dimension.width - originalHeight = dimension.height - width = imageConverter.targetDimension.width - height = imageConverter.targetDimension.height - location = info?.location - } + val uploadedImageEntity = + UploadedImage(generateFilename(), userAccount) + .apply { + extension = "png" + originalWidth = dimension.width + originalHeight = dimension.height + width = imageConverter.targetDimension.width + height = imageConverter.targetDimension.height + location = info?.location + } save(uploadedImageEntity) val processedImage = imageConverter.getImage() diff --git a/backend/data/src/main/kotlin/io/tolgee/service/InstanceIdService.kt b/backend/data/src/main/kotlin/io/tolgee/service/InstanceIdService.kt index 40375ae536..a63be5445f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/InstanceIdService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/InstanceIdService.kt @@ -11,19 +11,20 @@ import org.springframework.transaction.annotation.Transactional @Service class InstanceIdService( private val entityManager: EntityManager, - private val platformTransactionManager: PlatformTransactionManager + private val platformTransactionManager: PlatformTransactionManager, ) { @Transactional fun getInstanceId(): String { return tryUntilItDoesntBreakConstraint { executeInNewTransaction(platformTransactionManager) { - val entity = entityManager.find(InstanceId::class.java, 1) - ?: let { - val instanceId = InstanceId() - entityManager.persist(instanceId) - entityManager.flush() - instanceId - } + val entity = + entityManager.find(InstanceId::class.java, 1) + ?: let { + val instanceId = InstanceId() + entityManager.persist(instanceId) + entityManager.flush() + instanceId + } entity.instanceId } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/InvitationService.kt b/backend/data/src/main/kotlin/io/tolgee/service/InvitationService.kt index 3a55ba423f..f3b832c857 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/InvitationService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/InvitationService.kt @@ -41,7 +41,7 @@ class InvitationService( return create(params) { invitation -> permissionService.createForInvitation( invitation = invitation, - params + params, ) } } @@ -55,7 +55,7 @@ class InvitationService( @Transactional fun create( params: CreateProjectInvitationParams, - setPermissionFn: (invitation: Invitation) -> Permission + setPermissionFn: (invitation: Invitation) -> Permission, ): Invitation { checkEmailNotAlreadyInvited(params) val invitation = getInvitationInstance(params) @@ -70,11 +70,12 @@ class InvitationService( val invitation = getInvitationInstance(params) - invitation.organizationRole = organizationRoleService.createForInvitation( - invitation = invitation, - type = params.type, - organization = params.organization - ) + invitation.organizationRole = + organizationRoleService.createForInvitation( + invitation = invitation, + type = params.type, + organization = params.organization, + ) invitationRepository.save(invitation) invitationEmailSender.sendInvitation(invitation) @@ -101,7 +102,10 @@ class InvitationService( } @Transactional - fun accept(code: String?, userAccount: UserAccount) { + fun accept( + code: String?, + userAccount: UserAccount, + ) { val invitation = getInvitation(code) val permission = invitation.permission val organizationRole = invitation.organizationRole @@ -117,20 +121,26 @@ class InvitationService( invitationRepository.delete(invitation) } - private fun acceptProjectInvitation(permission: Permission?, userAccount: UserAccount) { + private fun acceptProjectInvitation( + permission: Permission?, + userAccount: UserAccount, + ) { permission?.let { acceptProjectInvitation(permission, userAccount) businessEventPublisher.publish( OnBusinessEventToCaptureEvent( eventName = "PROJECT_INVITATION_ACCEPTED", userAccountId = userAccount.id, - userAccountDto = UserAccountDto.fromEntity(userAccount) - ) + userAccountDto = UserAccountDto.fromEntity(userAccount), + ), ) } } - private fun acceptOrganizationInvitation(organizationRole: OrganizationRole?, userAccount: UserAccount) { + private fun acceptOrganizationInvitation( + organizationRole: OrganizationRole?, + userAccount: UserAccount, + ) { organizationRole?.let { acceptOrganizationInvitation(userAccount, organizationRole) businessEventPublisher.publish( @@ -139,15 +149,15 @@ class InvitationService( userAccountId = userAccount.id, userAccountDto = UserAccountDto.fromEntity(userAccount), organizationId = it.organization?.id, - organizationName = it.organization?.name - ) + organizationName = it.organization?.name, + ), ) } } private fun validateProjectXorOrganization( permission: Permission?, - organizationRole: OrganizationRole? + organizationRole: OrganizationRole?, ) { if (!(permission == null).xor(organizationRole == null)) { throw IllegalStateException("Exactly of permission and organizationRole may be set") @@ -156,7 +166,7 @@ class InvitationService( private fun acceptOrganizationInvitation( userAccount: UserAccount, - organizationRole: OrganizationRole + organizationRole: OrganizationRole, ) { if (organizationRoleService.isUserMemberOrOwner(userAccount.id, organizationRole.organization!!.id)) { throw BadRequestException(Message.USER_ALREADY_HAS_ROLE) @@ -166,7 +176,7 @@ class InvitationService( private fun acceptProjectInvitation( permission: Permission, - userAccount: UserAccount + userAccount: UserAccount, ): Permission { if (permissionService.find(projectId = permission.project!!.id, userId = userAccount.id) != null) { throw BadRequestException(Message.USER_ALREADY_HAS_PERMISSIONS) @@ -223,11 +233,17 @@ class InvitationService( } } - fun userOrInvitationWithEmailExists(email: String, project: Project): Boolean { + fun userOrInvitationWithEmailExists( + email: String, + project: Project, + ): Boolean { return invitationRepository.countByUserOrInvitationWithEmailAndProject(email, project) > 0 } - fun userOrInvitationWithEmailExists(email: String, organization: Organization): Boolean { + fun userOrInvitationWithEmailExists( + email: String, + organization: Organization, + ): Boolean { return invitationRepository.countByUserOrInvitationWithEmailAndOrganization(email, organization) > 0 } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/LanguageService.kt b/backend/data/src/main/kotlin/io/tolgee/service/LanguageService.kt index 2f05bf8cfa..f734d6c1cc 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/LanguageService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/LanguageService.kt @@ -39,7 +39,10 @@ class LanguageService( lateinit var translationService: TranslationService @Transactional - fun createLanguage(dto: LanguageDto?, project: Project): Language { + fun createLanguage( + dto: LanguageDto?, + project: Project, + ): Language { val language = fromRequestDTO(dto!!) language.project = project projectService.refresh(project).languages.add(language) @@ -56,29 +59,41 @@ class LanguageService( } @Transactional - fun editLanguage(id: Long, dto: LanguageDto): Language { + fun editLanguage( + id: Long, + dto: LanguageDto, + ): Language { val language = languageRepository.findById(id).orElseThrow { NotFoundException() } return editLanguage(language, dto) } @Transactional - fun editLanguage(language: Language, dto: LanguageDto): Language { + fun editLanguage( + language: Language, + dto: LanguageDto, + ): Language { language.updateByDTO(dto) entityManager.persist(language) return language } - fun getImplicitLanguages(projectId: Long, userId: Long): Set { + fun getImplicitLanguages( + projectId: Long, + userId: Long, + ): Set { val all = languageRepository.findAllByProjectId(projectId) - val viewLanguageIds = permissionService.getProjectPermissionData( - projectId, - userId - ).computedPermissions.viewLanguageIds + val viewLanguageIds = + permissionService.getProjectPermissionData( + projectId, + userId, + ).computedPermissions.viewLanguageIds - val permitted = if (viewLanguageIds.isNullOrEmpty()) - all - else - all.filter { viewLanguageIds.contains(it.id) } + val permitted = + if (viewLanguageIds.isNullOrEmpty()) { + all + } else { + all.filter { viewLanguageIds.contains(it.id) } + } return permitted.sortedBy { it.id }.take(2).toSet() } @@ -111,24 +126,38 @@ class LanguageService( return languageRepository.findById(id) } - fun findByTag(tag: String, project: Project): Optional { + fun findByTag( + tag: String, + project: Project, + ): Optional { return languageRepository.findByTagAndProject(tag, project) } - fun findByTag(tag: String?, projectId: Long): Optional { + fun findByTag( + tag: String?, + projectId: Long, + ): Optional { return languageRepository.findByTagAndProjectId(tag, projectId) } - fun findByTags(tags: Collection, projectId: Long): Set { + fun findByTags( + tags: Collection, + projectId: Long, + ): Set { val languages = languageRepository.findAllByTagInAndProjectId(tags, projectId) - val sortedByTagsParam = languages.sortedBy { language -> - tags.indexOfFirst { tag -> language.tag == tag } - } + val sortedByTagsParam = + languages.sortedBy { language -> + tags.indexOfFirst { tag -> language.tag == tag } + } return sortedByTagsParam.toSet() } @Transactional - fun getLanguagesForExport(languages: Set?, projectId: Long, userId: Long): Set { + fun getLanguagesForExport( + languages: Set?, + projectId: Long, + userId: Long, + ): Set { if (languages == null) { return permissionService.getPermittedViewLanguages(projectId, userId).toSet() } else { @@ -138,7 +167,11 @@ class LanguageService( } @Transactional - fun getLanguagesForTranslationsView(languages: Set?, projectId: Long, userId: Long): Set { + fun getLanguagesForTranslationsView( + languages: Set?, + projectId: Long, + userId: Long, + ): Set { val canViewTranslations = permissionService.getProjectPermissionScopes(projectId, userId)?.contains(Scope.TRANSLATIONS_VIEW) == true @@ -155,12 +188,13 @@ class LanguageService( private fun findByTagsAndFilterPermitted( projectId: Long, userId: Long, - languages: Set + languages: Set, ): Set { - val viewLanguageIds = permissionService.getProjectPermissionData( - projectId, - userId - ).computedPermissions.viewLanguageIds + val viewLanguageIds = + permissionService.getProjectPermissionData( + projectId, + userId, + ).computedPermissions.viewLanguageIds return if (viewLanguageIds.isNullOrEmpty()) { findByTags(languages, projectId) } else { @@ -168,7 +202,10 @@ class LanguageService( } } - fun findByName(name: String?, project: Project): Optional { + fun findByName( + name: String?, + project: Project, + ): Optional { return languageRepository.findByNameAndProject(name, project) } @@ -177,7 +214,7 @@ class LanguageService( autoTranslationService.deleteConfigsByProject(projectId) entityManager.createNativeQuery( "delete from language_stats " + - "where language_id in (select id from language where project_id = :projectId)" + "where language_id in (select id from language where project_id = :projectId)", ) .setParameter("projectId", projectId) .executeUpdate() @@ -194,7 +231,10 @@ class LanguageService( return this.languageRepository.saveAll(languages) } - fun getPaged(projectId: Long, pageable: Pageable): Page { + fun getPaged( + projectId: Long, + pageable: Pageable, + ): Page { return this.languageRepository.findAllByProjectId(projectId, pageable) } @@ -202,7 +242,10 @@ class LanguageService( return languageRepository.findAllById(ids) } - fun getLanguageIdsByTags(projectId: Long, languageTags: Collection): Map { + fun getLanguageIdsByTags( + projectId: Long, + languageTags: Collection, + ): Map { return languageRepository.findAllByTagInAndProjectId(languageTags, projectId).associateBy { it.tag } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/QuickStartService.kt b/backend/data/src/main/kotlin/io/tolgee/service/QuickStartService.kt index ad93917f00..2cf9555d7c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/QuickStartService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/QuickStartService.kt @@ -13,16 +13,22 @@ import org.springframework.stereotype.Component @Component class QuickStartService( private val quickStartRepository: QuickStartRepository, - private val applicationContext: ApplicationContext + private val applicationContext: ApplicationContext, ) { - fun create(userAccount: UserAccount, organization: Organization) { + fun create( + userAccount: UserAccount, + organization: Organization, + ) { val quickStart = QuickStart(userAccount) quickStart.organization = organization quickStartRepository.save(quickStart) DemoProjectCreator(organization, applicationContext).createDemoProject() } - fun completeStep(userAccount: UserAccountDto, step: String): QuickStart? { + fun completeStep( + userAccount: UserAccountDto, + step: String, + ): QuickStart? { val quickStart = quickStartRepository.findByUserAccountId(userAccount.id) if (quickStart?.completedSteps?.let { !it.contains(step) } == true) { quickStart.completedSteps = quickStart.completedSteps.plus(step) @@ -31,23 +37,34 @@ class QuickStartService( return quickStart } - fun setFinishState(userAccount: UserAccountDto, finished: Boolean): QuickStart { - val quickStart = quickStartRepository.findByUserAccountId(userAccount.id) - ?: throw ChangeSetPersister.NotFoundException() + fun setFinishState( + userAccount: UserAccountDto, + finished: Boolean, + ): QuickStart { + val quickStart = + quickStartRepository.findByUserAccountId(userAccount.id) + ?: throw ChangeSetPersister.NotFoundException() quickStart.finished = finished quickStartRepository.save(quickStart) return quickStart } - fun setOpenState(userAccount: UserAccountDto, open: Boolean): QuickStart { - val quickStart = quickStartRepository.findByUserAccountId(userAccount.id) - ?: throw ChangeSetPersister.NotFoundException() + fun setOpenState( + userAccount: UserAccountDto, + open: Boolean, + ): QuickStart { + val quickStart = + quickStartRepository.findByUserAccountId(userAccount.id) + ?: throw ChangeSetPersister.NotFoundException() quickStart.open = open quickStartRepository.save(quickStart) return quickStart } - fun find(userAccountId: Long, organizationId: Long?): QuickStart? { + fun find( + userAccountId: Long, + organizationId: Long?, + ): QuickStart? { organizationId ?: return null return quickStartRepository.findByUserAccountIdAndOrganizationId(userAccountId, organizationId) } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/StartupImportService.kt b/backend/data/src/main/kotlin/io/tolgee/service/StartupImportService.kt index 060ed8e317..2569232d7c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/StartupImportService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/StartupImportService.kt @@ -36,9 +36,8 @@ class StartupImportService( private val properties: TolgeeProperties, private val apiKeyService: ApiKeyService, private val applicationContext: ApplicationContext, - private val entityManager: EntityManager + private val entityManager: EntityManager, ) : Logging { - @Transactional fun importFiles() { getDirsToImport()?.forEach { projectDir -> @@ -50,7 +49,7 @@ class StartupImportService( private fun importAsInitialUserProject( projectName: String, - fileDtos: List + fileDtos: List, ) { val userAccount = getInitialUserAccount() ?: return val organization = getInitialUserOrganization(userAccount) @@ -77,15 +76,18 @@ class StartupImportService( }.filterNotNull().toList() private fun setAuthentication(userAccount: UserAccount) { - SecurityContextHolder.getContext().authentication = TolgeeAuthentication( - credentials = null, - userAccount = UserAccountDto.fromEntity(userAccount), - details = TolgeeAuthenticationDetails(false) - ) + SecurityContextHolder.getContext().authentication = + TolgeeAuthentication( + credentials = null, + userAccount = UserAccountDto.fromEntity(userAccount), + details = TolgeeAuthenticationDetails(false), + ) } - private fun isProjectExisting(projectName: String, organization: Organization) = - projectService.findAllByNameAndOrganizationOwner(projectName, organization).isNotEmpty() + private fun isProjectExisting( + projectName: String, + organization: Organization, + ) = projectService.findAllByNameAndOrganizationOwner(projectName, organization).isNotEmpty() private fun getDirsToImport(): List? { properties.import.dir?.let { dir -> @@ -100,7 +102,7 @@ class StartupImportService( private fun importData( fileDtos: List, project: Project, - userAccount: UserAccount + userAccount: UserAccount, ) { importService.addFiles(fileDtos, project, userAccount) entityManager.flush() @@ -114,28 +116,30 @@ class StartupImportService( private fun assignProjectHolder(project: Project) { applicationContext.getBean( "transactionProjectHolder", - ProjectHolder::class.java + ProjectHolder::class.java, ).project = ProjectDto.fromEntity(project) } private fun createProject( projectName: String, fileDtos: List, - organization: Organization + organization: Organization, ): Project { - val languages = fileDtos.map { file -> - // remove extension - val name = getLanguageName(file) - LanguageDto(name, name, name) - }.toSet().toList() - - val project = projectService.createProject( - CreateProjectDTO( - name = projectName, - languages = languages, - organizationId = organization.id - ), - ) + val languages = + fileDtos.map { file -> + // remove extension + val name = getLanguageName(file) + LanguageDto(name, name, name) + }.toSet().toList() + + val project = + projectService.createProject( + CreateProjectDTO( + name = projectName, + languages = languages, + organizationId = organization.id, + ), + ) setBaseLanguage(project) @@ -161,23 +165,25 @@ class StartupImportService( private fun createImplicitApiKey( userAccount: UserAccount, - project: Project + project: Project, ) { if (properties.import.createImplicitApiKey) { - val apiKey = ApiKey( - key = "${project.name.lowercase(Locale.getDefault())}-${userAccount.name}-imported-project-implicit", - scopesEnum = Scope.values().toMutableSet(), - userAccount = userAccount, - project = project - ) + val apiKey = + ApiKey( + key = "${project.name.lowercase(Locale.getDefault())}-${userAccount.name}-imported-project-implicit", + scopesEnum = Scope.values().toMutableSet(), + userAccount = userAccount, + project = project, + ) apiKeyService.save(apiKey) project.apiKeys.add(apiKey) } } private fun getInitialUserAccount(): UserAccount? { - val userAccount = userAccountService - .findActive(properties.authentication.initialUsername) + val userAccount = + userAccountService + .findActive(properties.authentication.initialUsername) return userAccount } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/TelemetryService.kt b/backend/data/src/main/kotlin/io/tolgee/service/TelemetryService.kt index 7b4d83a184..cc219abfb7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/TelemetryService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/TelemetryService.kt @@ -14,7 +14,7 @@ class TelemetryService( private val instanceIdService: InstanceIdService, private val entityManager: EntityManager, private val httpClient: HttpClient, - private val telemetryProperties: TelemetryProperties + private val telemetryProperties: TelemetryProperties, ) { companion object { const val TELEMETRY_REPORT_PERIOD_MS = 24 * 60 * 60 * 1000L @@ -31,7 +31,7 @@ class TelemetryService( "${telemetryProperties.server}/v2/public/telemetry/report", data, HttpMethod.POST, - Unit::class.java + Unit::class.java, ) } @@ -51,7 +51,7 @@ class TelemetryService( """ select count(u) from UserAccount u """, - Long::class.javaObjectType + Long::class.javaObjectType, ).singleResult } @@ -60,7 +60,7 @@ class TelemetryService( """ select count(distinct l.tag) from Language l """, - Long::class.javaObjectType + Long::class.javaObjectType, ).singleResult } @@ -69,7 +69,7 @@ class TelemetryService( """ select count(l) from Language l """, - Long::class.javaObjectType + Long::class.javaObjectType, ).singleResult } @@ -78,7 +78,7 @@ class TelemetryService( """ select count(t) from Translation t """, - Long::class.javaObjectType + Long::class.javaObjectType, ).singleResult } @@ -87,7 +87,7 @@ class TelemetryService( """ select count(p) from Project p """, - Long::class.javaObjectType + Long::class.javaObjectType, ).singleResult } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/automations/AutomationService.kt b/backend/data/src/main/kotlin/io/tolgee/service/automations/AutomationService.kt index ded8e1c022..5f0964b265 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/automations/AutomationService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/automations/AutomationService.kt @@ -31,7 +31,7 @@ class AutomationService( fun getProjectAutomations( projectId: Long, automationTriggerType: AutomationTriggerType, - activityType: ActivityType? = null + activityType: ActivityType? = null, ): List { val automations = getAutomationWithFetchedData(projectId, automationTriggerType, activityType) return automations.map { AutomationDto.fromEntity(it) } @@ -77,7 +77,7 @@ class AutomationService( join fetch aa.automation where aa.id = :actionId """, - AutomationAction::class.java + AutomationAction::class.java, ) .setParameter("actionId", actionId) .singleResult ?: throw NotFoundException() @@ -121,9 +121,7 @@ class AutomationService( return save(automation) } - private fun getAutomationForExistingWebhookConfig( - webhookConfig: WebhookConfig, - ): Automation { + private fun getAutomationForExistingWebhookConfig(webhookConfig: WebhookConfig): Automation { val automations = webhookConfig.automationActions.map { it.automation } if (automations.size == 1) { return automations[0] @@ -143,14 +141,14 @@ class AutomationService( this.type = AutomationTriggerType.ACTIVITY this.activityType = null this.debounceDurationInMs = 0 - } + }, ) automation.actions.add( AutomationAction(automation).apply { this.type = AutomationActionType.WEBHOOK this.webhookConfig = webhookConfig - } + }, ) } @@ -181,7 +179,10 @@ class AutomationService( } @Transactional - fun delete(projectId: Long, automationId: Long) { + fun delete( + projectId: Long, + automationId: Long, + ) { val deletedCunt = automationRepository.deleteByIdAndProjectId(automationId, projectId) if (deletedCunt == 0L) { throw NotFoundException() @@ -196,7 +197,10 @@ class AutomationService( } @Transactional - fun get(projectId: Long, automationId: Long): Automation { + fun get( + projectId: Long, + automationId: Long, + ): Automation { return automationRepository.findByIdAndProjectId(automationId, projectId) ?: throw NotFoundException() } @@ -204,54 +208,55 @@ class AutomationService( private fun getAutomationWithFetchedData( projectId: Long, automationTriggerType: AutomationTriggerType, - activityType: ActivityType? = null + activityType: ActivityType? = null, ): MutableList { val automations = getAutomationsWithTriggerOfType(projectId, automationTriggerType, activityType) return entityManager.createQuery( """from Automation a join fetch a.actions where a in :automations""", - Automation::class.java + Automation::class.java, ).setParameter("automations", automations).resultList } private fun getAutomationsWithTriggerOfType( projectId: Long, automationTriggerType: AutomationTriggerType, - activityType: ActivityType? - ): MutableList? = entityManager.createQuery( - """ - from Automation a join fetch a.triggers - where a.id in ( - select a2.id from Automation a2 - join a2.triggers at - where a2.project.id = :projectId - and at.type = :automationTriggerType - and (at.activityType = :activityType or at.activityType is null) - ) - """.trimIndent(), - Automation::class.java - ) - .setParameter("projectId", projectId) - .setParameter("automationTriggerType", automationTriggerType) - .setParameter("activityType", activityType) - .resultList + activityType: ActivityType?, + ): MutableList? = + entityManager.createQuery( + """ + from Automation a join fetch a.triggers + where a.id in ( + select a2.id from Automation a2 + join a2.triggers at + where a2.project.id = :projectId + and at.type = :automationTriggerType + and (at.activityType = :activityType or at.activityType is null) + ) + """.trimIndent(), + Automation::class.java, + ) + .setParameter("projectId", projectId) + .setParameter("automationTriggerType", automationTriggerType) + .setParameter("activityType", activityType) + .resultList private fun addContentDeliveryTriggersAndActions( contentDeliveryConfig: ContentDeliveryConfig, - automation: Automation + automation: Automation, ) { automation.triggers.add( AutomationTrigger(automation).apply { this.type = AutomationTriggerType.TRANSLATION_DATA_MODIFICATION this.debounceDurationInMs = 30000 - } + }, ) automation.actions.add( AutomationAction(automation).apply { this.type = AutomationActionType.CONTENT_DELIVERY_PUBLISH this.contentDeliveryConfig = contentDeliveryConfig - } + }, ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/bigMeta/BigMetaService.kt b/backend/data/src/main/kotlin/io/tolgee/service/bigMeta/BigMetaService.kt index 8efbb92944..ffbdf4cea3 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/bigMeta/BigMetaService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/bigMeta/BigMetaService.kt @@ -3,7 +3,7 @@ package io.tolgee.service.bigMeta import io.tolgee.component.CurrentDateProvider import io.tolgee.dtos.BigMetaDto import io.tolgee.dtos.RelatedKeyDto -import io.tolgee.dtos.query_results.KeyIdFindResult +import io.tolgee.dtos.queryResults.KeyIdFindResult import io.tolgee.events.OnProjectActivityEvent import io.tolgee.exceptions.NotFoundException import io.tolgee.model.Project @@ -35,7 +35,7 @@ class BigMetaService( private val entityManager: EntityManager, private val transactionManager: PlatformTransactionManager, private val jdbcTemplate: JdbcTemplate, - private val currentDateProvider: CurrentDateProvider + private val currentDateProvider: CurrentDateProvider, ) : Logging { companion object { const val MAX_DISTANCE_SCORE = 10000L @@ -48,14 +48,17 @@ class BigMetaService( } @Transactional - fun store(data: BigMetaDto, project: Project) { + fun store( + data: BigMetaDto, + project: Project, + ) { store(data.relatedKeysInOrder, project) } @Transactional fun store( relatedKeysInOrder: MutableList?, - project: Project + project: Project, ) { if (relatedKeysInOrder.isNullOrEmpty()) { return @@ -75,7 +78,7 @@ class BigMetaService( on conflict (key1id, key2id) do update set score = excluded.score, hits = excluded.hits, updated_at = ? """, toInsert, - 100 + 100, ) { ps, dto -> ps.setLong(1, dto.key1Id) ps.setLong(2, dto.key2Id) @@ -90,7 +93,7 @@ class BigMetaService( fun getKeyIdsForItems( relatedKeysInOrder: List, - projectId: Long + projectId: Long, ): List { // we need to chunk it to avoid stack overflow return relatedKeysInOrder.chunked(1000) @@ -101,7 +104,10 @@ class BigMetaService( } @Transactional - fun findExistingKeyDistances(keys: List, project: Project): Set { + fun findExistingKeyDistances( + keys: List, + project: Project, + ): Set { val keyIds = keys.map { it.id } return findExistingKeysDistancesDtosByIds(keyIds) } @@ -117,7 +123,7 @@ class BigMetaService( select kd3.key2Id from KeysDistance kd3 where kd3.key1Id in :data or kd3.key2Id in :data ) """, - KeysDistanceDto::class.java + KeysDistanceDto::class.java, ) .setParameter("data", keyIds) .resultList.toSet() @@ -131,11 +137,12 @@ class BigMetaService( return this.keysDistanceRepository.findById(id).orElse(null) } - fun getCloseKeyIds(keyId: Long): List = - this.keysDistanceRepository.getCloseKeys(keyId) + fun getCloseKeyIds(keyId: Long): List = this.keysDistanceRepository.getCloseKeys(keyId) - fun getCloseKeysWithBaseTranslation(keyId: Long, projectId: Long) = - this.keysDistanceRepository.getCloseKeysWithBaseTranslation(keyId, projectId) + fun getCloseKeysWithBaseTranslation( + keyId: Long, + projectId: Long, + ) = this.keysDistanceRepository.getCloseKeysWithBaseTranslation(keyId, projectId) @EventListener(OnProjectActivityEvent::class) @Async @@ -154,7 +161,7 @@ class BigMetaService( """ delete from KeysDistance kd where kd.key1Id in :ids or kd.key2Id in :ids - """ + """, ).setParameter("ids", ids).executeUpdate() } } @@ -162,18 +169,19 @@ class BigMetaService( private fun getKeyIdsForItemsQuery( relatedKeysInOrderChunk: List, - projectId: Long + projectId: Long, ): CriteriaQuery? { val cb: CriteriaBuilder = entityManager.criteriaBuilder val query = cb.createQuery(KeyIdFindResult::class.java) val root = query.from(Key::class.java) val namespace = root.join(Key_.namespace, JoinType.LEFT) - val predicates = relatedKeysInOrderChunk.map { key -> - cb.and( - cb.equal(root.get(Key_.name), key.keyName), - cb.equalNullable(namespace.get(Namespace_.name), key.namespace) - ) - } + val predicates = + relatedKeysInOrderChunk.map { key -> + cb.and( + cb.equal(root.get(Key_.name), key.keyName), + cb.equalNullable(namespace.get(Namespace_.name), key.namespace), + ) + } val keyPredicates = cb.or(*predicates.toTypedArray()) query.where(cb.and(keyPredicates, cb.equal(root.get(Key_.project).get(Project_.id), projectId))) query.multiselect( diff --git a/backend/data/src/main/kotlin/io/tolgee/service/bigMeta/KeysDistanceDto.kt b/backend/data/src/main/kotlin/io/tolgee/service/bigMeta/KeysDistanceDto.kt index 265d7402cb..477af97f81 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/bigMeta/KeysDistanceDto.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/bigMeta/KeysDistanceDto.kt @@ -7,5 +7,5 @@ data class KeysDistanceDto( var key2Id: Long = 0, var score: Long = MAX_SCORE, var projectId: Long, - var hits: Long = 1 + var hits: Long = 1, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/bigMeta/KeysDistanceUtil.kt b/backend/data/src/main/kotlin/io/tolgee/service/bigMeta/KeysDistanceUtil.kt index 7599f86f30..3fd0e30084 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/bigMeta/KeysDistanceUtil.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/bigMeta/KeysDistanceUtil.kt @@ -10,7 +10,7 @@ import kotlin.math.min class KeysDistanceUtil( private val relatedKeysInOrder: MutableList, private val project: Project, - private val bigMetaService: BigMetaService + private val bigMetaService: BigMetaService, ) : Logging { val newDistances by lazy { increaseRelevant() @@ -27,8 +27,9 @@ class KeysDistanceUtil( } val key2Id = keyIdMap[item2.namespace to item2.keyName] ?: return@forEach2 - val distance = distances[min(key1Id, key2Id) to max(key1Id, key2Id)] - ?: createDistance(key1Id, key2Id) + val distance = + distances[min(key1Id, key2Id) to max(key1Id, key2Id)] + ?: createDistance(key1Id, key2Id) relevant[distance.key1Id to distance.key2Id] = distance distance.score = computeDistanceScore(distance.score, distance.hits, relatedKeysSize, index1, index2) distance.hits++ @@ -67,7 +68,10 @@ class KeysDistanceUtil( private val relatedKeysSize = relatedKeysInOrder.size - private fun createDistance(key1Id: Long, key2Id: Long): KeysDistanceDto { + private fun createDistance( + key1Id: Long, + key2Id: Long, + ): KeysDistanceDto { return KeysDistanceDto( key1Id = min(a = key1Id, b = key2Id), key2Id = max(key1Id, key2Id), @@ -82,12 +86,13 @@ class KeysDistanceUtil( hits: Long, relatedKeysSize: Int, index1: Int, - index2: Int + index2: Int, ): Long { val maxDistance = (relatedKeysSize - 2) - val points = ( - (maxDistance - (abs(index1 - index2) - 1)) / maxDistance.toDouble() + val points = + ( + (maxDistance - (abs(index1 - index2) - 1)) / maxDistance.toDouble() ) * BigMetaService.MAX_POINTS val baseDistance = BigMetaService.MAX_DISTANCE_SCORE - BigMetaService.MAX_POINTS diff --git a/backend/data/src/main/kotlin/io/tolgee/service/contentDelivery/ContentDeliveryConfigService.kt b/backend/data/src/main/kotlin/io/tolgee/service/contentDelivery/ContentDeliveryConfigService.kt index d388505768..8718e699d7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/contentDelivery/ContentDeliveryConfigService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/contentDelivery/ContentDeliveryConfigService.kt @@ -31,10 +31,13 @@ class ContentDeliveryConfigService( private val automationService: AutomationService, @Lazy private val contentDeliveryUploader: ContentDeliveryUploader, - private val enabledFeaturesProvider: EnabledFeaturesProvider + private val enabledFeaturesProvider: EnabledFeaturesProvider, ) { @Transactional - fun create(projectId: Long, dto: ContentDeliveryConfigRequest): ContentDeliveryConfig { + fun create( + projectId: Long, + dto: ContentDeliveryConfigRequest, + ): ContentDeliveryConfig { val project = entityManager.getReference(Project::class.java, projectId) checkMultipleConfigsFeature(project) val contentDeliveryConfig = ContentDeliveryConfig(project) @@ -50,11 +53,14 @@ class ContentDeliveryConfigService( return contentDeliveryConfig } - private fun checkMultipleConfigsFeature(project: Project, maxCurrentAllowed: Int = 0) { + private fun checkMultipleConfigsFeature( + project: Project, + maxCurrentAllowed: Int = 0, + ) { if (contentDeliveryConfigRepository.countByProject(project) > maxCurrentAllowed) { enabledFeaturesProvider.checkFeatureEnabled( project.organizationOwner.id, - Feature.MULTIPLE_CONTENT_DELIVERY_CONFIGS + Feature.MULTIPLE_CONTENT_DELIVERY_CONFIGS, ) } } @@ -71,7 +77,10 @@ class ContentDeliveryConfigService( return (1..32).joinToString("") { Random.nextInt(0, 16).toString(16) } } - private fun getStorage(projectId: Long, contentStorageId: Long?): ContentStorage? { + private fun getStorage( + projectId: Long, + contentStorageId: Long?, + ): ContentStorage? { contentStorageId ?: return null return contentStorageProvider.getStorage(projectId, contentStorageId) } @@ -81,7 +90,11 @@ class ContentDeliveryConfigService( fun find(id: Long) = contentDeliveryConfigRepository.findById(id).orElse(null) @Transactional - fun update(projectId: Long, id: Long, dto: ContentDeliveryConfigRequest): ContentDeliveryConfig { + fun update( + projectId: Long, + id: Long, + dto: ContentDeliveryConfigRequest, + ): ContentDeliveryConfig { checkMultipleConfigsFeature(projectService.get(projectId), maxCurrentAllowed = 1) val config = get(projectId, id) config.contentStorage = getStorage(projectId, dto.contentStorageId) @@ -91,7 +104,10 @@ class ContentDeliveryConfigService( return save(config) } - private fun handleUpdateAutoPublish(dto: ContentDeliveryConfigRequest, exporter: ContentDeliveryConfig) { + private fun handleUpdateAutoPublish( + dto: ContentDeliveryConfigRequest, + exporter: ContentDeliveryConfig, + ) { if (dto.autoPublish && exporter.automationActions.isEmpty()) { automationService.createForContentDelivery(exporter) } @@ -100,7 +116,10 @@ class ContentDeliveryConfigService( } } - fun delete(projectId: Long, id: Long) { + fun delete( + projectId: Long, + id: Long, + ) { val config = get(projectId, id) config.automationActions.map { it.automation }.forEach { automationService.delete(it) @@ -108,11 +127,17 @@ class ContentDeliveryConfigService( contentDeliveryConfigRepository.deleteById(config.id) } - fun getAllInProject(projectId: Long, pageable: Pageable): Page { + fun getAllInProject( + projectId: Long, + pageable: Pageable, + ): Page { return contentDeliveryConfigRepository.findAllByProjectId(projectId, pageable) } - fun get(projectId: Long, contentDeliveryConfigId: Long): ContentDeliveryConfig { + fun get( + projectId: Long, + contentDeliveryConfigId: Long, + ): ContentDeliveryConfig { return contentDeliveryConfigRepository.getByProjectIdAndId(projectId, contentDeliveryConfigId) } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/AsyncImportHardDeleter.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/AsyncImportHardDeleter.kt index 0608b41c78..70c10a9dcf 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/AsyncImportHardDeleter.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/AsyncImportHardDeleter.kt @@ -7,7 +7,7 @@ import org.springframework.transaction.event.TransactionalEventListener @Component class AsyncImportHardDeleter( - private val importService: ImportService + private val importService: ImportService, ) { @Async @TransactionalEventListener diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/CoreImportFilesProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/CoreImportFilesProcessor.kt index c5fa91bc00..785936815f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/CoreImportFilesProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/CoreImportFilesProcessor.kt @@ -32,10 +32,7 @@ class CoreImportFilesProcessor( ) } - fun processFiles( - files: Collection?, - ): MutableList { - + fun processFiles(files: Collection?): MutableList { val errors = mutableListOf() files?.forEach { try { @@ -50,9 +47,7 @@ class CoreImportFilesProcessor( return errors } - private fun processFileOrArchive( - file: ImportFileDto, - ): MutableList { + private fun processFileOrArchive(file: ImportFileDto): MutableList { val errors = mutableListOf() if (file.isArchive) { @@ -63,16 +58,15 @@ class CoreImportFilesProcessor( return mutableListOf() } - private fun processFile( - file: ImportFileDto, - ) { + private fun processFile(file: ImportFileDto) { val savedFileEntity = file.saveFileEntity() - val fileProcessorContext = FileProcessorContext( - file = file, - fileEntity = savedFileEntity, - maxTranslationTextLength = tolgeeProperties.maxTranslationTextLength, - params = params - ) + val fileProcessorContext = + FileProcessorContext( + file = file, + fileEntity = savedFileEntity, + maxTranslationTextLength = tolgeeProperties.maxTranslationTextLength, + params = params, + ) val processor = processorFactory.getProcessor(file, fileProcessorContext) processor.process() processor.context.processResult() @@ -80,7 +74,7 @@ class CoreImportFilesProcessor( private fun processArchive( archive: ImportFileDto, - errors: MutableList + errors: MutableList, ): MutableList { val processor = processorFactory.getArchiveProcessor(archive) val files = processor.process(archive) @@ -95,10 +89,11 @@ class CoreImportFilesProcessor( } private fun ImportFileDto.saveFileEntity(): ImportFile { - val entity = ImportFile( - name, - import - ) + val entity = + ImportFile( + name, + import, + ) import.files.add(entity) return importService.saveFile(entity) } @@ -154,8 +149,8 @@ class CoreImportFilesProcessor( FileIssueType.MULTIPLE_VALUES_FOR_KEY_AND_LANGUAGE, mapOf( FileIssueParamType.KEY_ID to collidingTranslations.key.id.toString(), - FileIssueParamType.LANGUAGE_ID to collidingTranslations.language.id.toString() - ) + FileIssueParamType.LANGUAGE_ID to collidingTranslations.language.id.toString(), + ), ) } return@translationForeach diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/ForceMode.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/ForceMode.kt index fdc4ee4ddd..286240a6bf 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/ForceMode.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/ForceMode.kt @@ -3,5 +3,5 @@ package io.tolgee.service.dataImport enum class ForceMode { OVERRIDE, KEEP, - NO_FORCE + NO_FORCE, } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/ImportDataManager.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/ImportDataManager.kt index c4d1a48a49..ec2540ef99 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/ImportDataManager.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/ImportDataManager.kt @@ -52,10 +52,11 @@ class ImportDataManager( val result = mutableMapOf, Translation>>() this.storedLanguages.asSequence().map { it.existingLanguage }.toSet().forEach { language -> if (language != null && result[language.id] == null) { - result[language.id] = mutableMapOf, Translation>().apply { - translationService.getAllByLanguageId(language.id) - .forEach { translation -> put(translation.key.namespace?.name to translation.key.name, translation) } - } + result[language.id] = + mutableMapOf, Translation>().apply { + translationService.getAllByLanguageId(language.id) + .forEach { translation -> put(translation.key.namespace?.name to translation.key.name, translation) } + } } } result @@ -87,7 +88,10 @@ class ImportDataManager( * It returns collection since translations could collide, when a user uploads multiple files with different values * for a key */ - fun getStoredTranslations(key: ImportKey, language: ImportLanguage): MutableList { + fun getStoredTranslations( + key: ImportKey, + language: ImportLanguage, + ): MutableList { this.populateStoredTranslations(language) val languageData = this.storedTranslations[language]!! @@ -111,10 +115,11 @@ class ImportDataManager( storedTranslations[language] = languageData val translations = importService.findTranslations(language.id) translations.forEach { importTranslation -> - val keyTranslations = languageData[importTranslation.key] ?: let { - languageData[importTranslation.key] = mutableListOf() - languageData[importTranslation.key]!! - } + val keyTranslations = + languageData[importTranslation.key] ?: let { + languageData[importTranslation.key] = mutableListOf() + languageData[importTranslation.key]!! + } keyTranslations.add(importTranslation) } return languageData @@ -129,8 +134,9 @@ class ImportDataManager( languageTranslations.forEach { importedTranslation -> val existingLanguage = importedTranslation.language.existingLanguage if (existingLanguage != null) { - val existingTranslation = existingTranslations[existingLanguage.id] - ?.let { it[importedTranslation.language.file.namespace to importedTranslation.key.name] } + val existingTranslation = + existingTranslations[existingLanguage.id] + ?.let { it[importedTranslation.language.file.namespace to importedTranslation.key.name] } if (existingTranslation != null) { // remove if text is the same if (existingTranslation.text == importedTranslation.text) { @@ -178,9 +184,7 @@ class ImportDataManager( } } - fun resetLanguage( - importLanguage: ImportLanguage - ) { + fun resetLanguage(importLanguage: ImportLanguage) { this.populateStoredTranslations(importLanguage) this.resetConflicts(importLanguage) this.handleConflicts(false) @@ -191,7 +195,10 @@ class ImportDataManager( this.saveAllStoredTranslations() } - private fun isExistingLanguageUsed(existing: Language?, imported: ImportLanguage): Boolean { + private fun isExistingLanguageUsed( + existing: Language?, + imported: ImportLanguage, + ): Boolean { existing ?: return false return this.storedLanguages.any { storedLang -> imported != storedLang && // ignore when is assigned to self @@ -201,9 +208,10 @@ class ImportDataManager( } fun findMatchingExistingLanguage(importLanguage: ImportLanguage): Language? { - val possibleTag = """(?:.*?)/?([a-zA-Z0-9-_]+)[^/]*?""".toRegex() - .matchEntire(importLanguage.name)?.groups?.get(1)?.value - ?: return null + val possibleTag = + """(?:.*?)/?([a-zA-Z0-9-_]+)[^/]*?""".toRegex() + .matchEntire(importLanguage.name)?.groups?.get(1)?.value + ?: return null val candidate = languageService.findByTag(possibleTag, import.project.id).orElse(null) ?: return null diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/ImportDeleteService.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/ImportDeleteService.kt index 29fc7f5646..d57770e631 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/ImportDeleteService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/ImportDeleteService.kt @@ -6,7 +6,7 @@ import org.springframework.stereotype.Service @Service class ImportDeleteService( - private val entityManager: EntityManager + private val entityManager: EntityManager, ) { fun deleteImport(importId: Long) { entityManager.unwrap(Session::class.java).doWork { connection -> @@ -24,7 +24,11 @@ class ImportDeleteService( } } - fun executeUpdate(connection: java.sql.Connection, query: String, importId: Long) { + fun executeUpdate( + connection: java.sql.Connection, + query: String, + importId: Long, + ) { @Suppress("SqlSourceToSinkFlow") connection.prepareStatement(query).use { statement -> statement.setLong(1, importId) @@ -32,7 +36,10 @@ class ImportDeleteService( } } - fun deleteImportTranslations(connection: java.sql.Connection, importId: Long) { + fun deleteImportTranslations( + connection: java.sql.Connection, + importId: Long, + ) { val query = "delete from import_translation " + "where id in (" + @@ -42,7 +49,10 @@ class ImportDeleteService( executeUpdate(connection, query, importId) } - fun deleteImportLanguages(connection: java.sql.Connection, importId: Long) { + fun deleteImportLanguages( + connection: java.sql.Connection, + importId: Long, + ) { val query = "delete from import_language " + "where id in (select il.id from import_language il " + @@ -50,7 +60,10 @@ class ImportDeleteService( executeUpdate(connection, query, importId) } - fun deleteImportKeys(connection: java.sql.Connection, importId: Long) { + fun deleteImportKeys( + connection: java.sql.Connection, + importId: Long, + ) { val query = "delete from import_key " + "where id in (select ik.id from import_key ik " + @@ -58,7 +71,10 @@ class ImportDeleteService( executeUpdate(connection, query, importId) } - fun deleteImportKeyMetaTags(connection: java.sql.Connection, importId: Long) { + fun deleteImportKeyMetaTags( + connection: java.sql.Connection, + importId: Long, + ) { val query = "delete from key_meta_tags " + "where key_metas_id in (select ikm.id from key_meta ikm " + @@ -67,7 +83,10 @@ class ImportDeleteService( executeUpdate(connection, query, importId) } - fun deleteImportKeyMetaComments(connection: java.sql.Connection, importId: Long) { + fun deleteImportKeyMetaComments( + connection: java.sql.Connection, + importId: Long, + ) { val query = "delete from key_comment " + "where key_meta_id in (select ikm.id from key_meta ikm " + @@ -76,7 +95,10 @@ class ImportDeleteService( executeUpdate(connection, query, importId) } - fun deleteImportKeyMetaCodeReferences(connection: java.sql.Connection, importId: Long) { + fun deleteImportKeyMetaCodeReferences( + connection: java.sql.Connection, + importId: Long, + ) { val query = "delete from key_code_reference " + "where key_meta_id in (select ikm.id from key_meta ikm " + @@ -85,7 +107,10 @@ class ImportDeleteService( executeUpdate(connection, query, importId) } - fun deleteImportKeyMeta(connection: java.sql.Connection, importId: Long) { + fun deleteImportKeyMeta( + connection: java.sql.Connection, + importId: Long, + ) { val query = "delete from key_meta " + "where id in (select ikm.id from key_meta ikm " + @@ -94,7 +119,10 @@ class ImportDeleteService( executeUpdate(connection, query, importId) } - fun deleteImportFileIssueParams(connection: java.sql.Connection, importId: Long) { + fun deleteImportFileIssueParams( + connection: java.sql.Connection, + importId: Long, + ) { val query = "delete from import_file_issue_param " + "where import_file_issue_param.issue_id in (select ifi.id from import_file_issue ifi " + @@ -102,7 +130,10 @@ class ImportDeleteService( executeUpdate(connection, query, importId) } - fun deleteImportFileIssues(connection: java.sql.Connection, importId: Long) { + fun deleteImportFileIssues( + connection: java.sql.Connection, + importId: Long, + ) { val query = "delete from import_file_issue " + "where id in (select ifi.id from import_file_issue ifi " + @@ -110,13 +141,20 @@ class ImportDeleteService( executeUpdate(connection, query, importId) } - fun deleteImportFiles(connection: java.sql.Connection, importId: Long) { - val query = "delete from import_file " + - "where id in (select if.id from import_file if where if.import_id = ?)" + fun deleteImportFiles( + connection: java.sql.Connection, + importId: Long, + ) { + val query = + "delete from import_file " + + "where id in (select if.id from import_file if where if.import_id = ?)" executeUpdate(connection, query, importId) } - fun deleteTheImport(connection: java.sql.Connection, importId: Long) { + fun deleteTheImport( + connection: java.sql.Connection, + importId: Long, + ) { val query = "delete from import where id = ?" executeUpdate(connection, query, importId) } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/ImportService.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/ImportService.kt index 3aa049b966..ed62f78580 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/ImportService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/ImportService.kt @@ -55,18 +55,19 @@ class ImportService( private val entityManager: EntityManager, private val businessEventPublisher: BusinessEventPublisher, private val importDeleteService: ImportDeleteService, - private val currentDateProvider: CurrentDateProvider + private val currentDateProvider: CurrentDateProvider, ) { @Transactional fun addFiles( files: List, project: Project, userAccount: UserAccount, - params: ImportAddFilesParams = ImportAddFilesParams() + params: ImportAddFilesParams = ImportAddFilesParams(), ): List { - val import = findNotExpired(project.id, userAccount.id) ?: Import(project).also { - it.author = userAccount - } + val import = + findNotExpired(project.id, userAccount.id) ?: Import(project).also { + it.author = userAccount + } val languages = findLanguages(import) @@ -75,11 +76,12 @@ class ImportService( } importRepository.save(import) - val fileProcessor = CoreImportFilesProcessor( - applicationContext = applicationContext, - import = import, - params = params - ) + val fileProcessor = + CoreImportFilesProcessor( + applicationContext = applicationContext, + import = import, + params = params, + ) val errors = fileProcessor.processFiles(files) if (findLanguages(import).isEmpty()) { @@ -89,34 +91,45 @@ class ImportService( } @Transactional(noRollbackFor = [ImportConflictNotResolvedException::class]) - fun import(projectId: Long, authorId: Long, forceMode: ForceMode = ForceMode.NO_FORCE) { + fun import( + projectId: Long, + authorId: Long, + forceMode: ForceMode = ForceMode.NO_FORCE, + ) { import(getNotExpired(projectId, authorId), forceMode) } @Transactional(noRollbackFor = [ImportConflictNotResolvedException::class]) - fun import(import: Import, forceMode: ForceMode = ForceMode.NO_FORCE) { + fun import( + import: Import, + forceMode: ForceMode = ForceMode.NO_FORCE, + ) { StoredDataImporter(applicationContext, import, forceMode).doImport() deleteImport(import) businessEventPublisher.publish( OnBusinessEventToCaptureEvent( eventName = "IMPORT", projectId = import.project.id, - userAccountId = import.author.id - ) + userAccountId = import.author.id, + ), ) } @Transactional - fun selectExistingLanguage(importLanguage: ImportLanguage, existingLanguage: Language?) { + fun selectExistingLanguage( + importLanguage: ImportLanguage, + existingLanguage: Language?, + ) { if (importLanguage.existingLanguage == existingLanguage) { return } val import = importLanguage.file.import val dataManager = ImportDataManager(applicationContext, import) existingLanguage?.let { - val langAlreadySelectedInTheSameNS = dataManager.storedLanguages.any { - it.existingLanguage?.id == existingLanguage.id && it.file.namespace == importLanguage.file.namespace - } + val langAlreadySelectedInTheSameNS = + dataManager.storedLanguages.any { + it.existingLanguage?.id == existingLanguage.id && it.file.namespace == importLanguage.file.namespace + } if (langAlreadySelectedInTheSameNS) { throw BadRequestException(Message.LANGUAGE_ALREADY_SELECTED) } @@ -127,7 +140,10 @@ class ImportService( } @Transactional - fun selectNamespace(file: ImportFile, namespace: String?) { + fun selectNamespace( + file: ImportFile, + namespace: String?, + ) { val import = file.import val dataManager = ImportDataManager(applicationContext, import) file.namespace = getSafeNamespace(namespace) @@ -141,14 +157,16 @@ class ImportService( return this.importRepository.save(import) } - fun saveFile(importFile: ImportFile): ImportFile = - importFileRepository.save(importFile) + fun saveFile(importFile: ImportFile): ImportFile = importFileRepository.save(importFile) /** * Returns import when not expired. * When expired import is found, it is removed */ - fun getNotExpired(projectId: Long, authorId: Long): Import { + fun getNotExpired( + projectId: Long, + authorId: Long, + ): Import { return findNotExpired(projectId, authorId) ?: throw NotFoundException() } @@ -156,16 +174,25 @@ class ImportService( return importRepository.findDeleted(importId) } - private fun findNotExpired(projectId: Long, userAccountId: Long): Import? { + private fun findNotExpired( + projectId: Long, + userAccountId: Long, + ): Import? { val import = this.find(projectId, userAccountId) return removeExpiredImportService.removeIfExpired(import) } - fun find(projectId: Long, authorId: Long): Import? { + fun find( + projectId: Long, + authorId: Long, + ): Import? { return this.importRepository.findByProjectIdAndAuthorId(projectId, authorId) } - fun get(projectId: Long, authorId: Long): Import { + fun get( + projectId: Long, + authorId: Long, + ): Import { return this.find(projectId, authorId) ?: throw NotFoundException() } @@ -176,30 +203,31 @@ class ImportService( fun findLanguages(import: Import) = importLanguageRepository.findAllByImport(import.id) @Suppress("UNCHECKED_CAST") - fun findKeys(import: Import): List { - var result: List = entityManager.createQuery( - """ + var result: List = + entityManager.createQuery( + """ select distinct ik from ImportKey ik left join fetch ik.keyMeta ikm left join fetch ikm.comments ikc join ik.file if where if.import = :import - """ - ) - .setParameter("import", import) - .resultList as List + """, + ) + .setParameter("import", import) + .resultList as List - result = entityManager.createQuery( - """ + result = + entityManager.createQuery( + """ select distinct ik from ImportKey ik left join fetch ik.keyMeta ikm left join fetch ikm.codeReferences ikc join ik.file if where ik in :keys - """ - ).setParameter("keys", result) - .resultList as List + """, + ).setParameter("keys", result) + .resultList as List return result } @@ -208,8 +236,7 @@ class ImportService( importLanguageRepository.saveAll(entries) } - fun findTranslations(languageId: Long) = - this.importTranslationRepository.findAllByImportAndLanguageId(languageId) + fun findTranslations(languageId: Long) = this.importTranslationRepository.findAllByImportAndLanguageId(languageId) fun saveTranslations(translations: List) { this.importTranslationRepository.saveAll(translations) @@ -231,7 +258,11 @@ class ImportService( this.importTranslationRepository.removeExistingTranslationConflictReferences(translationIds) } - fun getResult(projectId: Long, userId: Long, pageable: Pageable): Page { + fun getResult( + projectId: Long, + userId: Long, + pageable: Pageable, + ): Page { return this.getNotExpired(projectId, userId).let { this.importLanguageRepository.findImportLanguagesView(it.id, pageable) } @@ -250,10 +281,14 @@ class ImportService( pageable: Pageable, onlyConflicts: Boolean, onlyUnresolved: Boolean, - search: String? = null + search: String? = null, ): Page { return importTranslationRepository.findImportTranslationsView( - languageId, pageable, onlyConflicts, onlyUnresolved, search + languageId, + pageable, + onlyConflicts, + onlyUnresolved, + search, ) } @@ -270,8 +305,10 @@ class ImportService( } @Transactional - fun deleteImport(projectId: Long, authorId: Long) = - this.deleteImport(get(projectId, authorId)) + fun deleteImport( + projectId: Long, + authorId: Long, + ) = this.deleteImport(get(projectId, authorId)) @Transactional fun deleteLanguage(language: ImportLanguage) { @@ -287,13 +324,19 @@ class ImportService( return importTranslationRepository.findById(translationId).orElse(null) } - fun resolveTranslationConflict(translation: ImportTranslation, override: Boolean) { + fun resolveTranslationConflict( + translation: ImportTranslation, + override: Boolean, + ) { translation.override = override translation.resolve() importTranslationRepository.save(translation) } - fun resolveAllOfLanguage(language: ImportLanguage, override: Boolean) { + fun resolveAllOfLanguage( + language: ImportLanguage, + override: Boolean, + ) { val translations = findTranslations(language.id) translations.forEach { it.resolve() @@ -306,7 +349,10 @@ class ImportService( return importFileRepository.findById(fileId).orElse(null) } - fun getFileIssues(fileId: Long, pageable: Pageable): Page { + fun getFileIssues( + fileId: Long, + pageable: Pageable, + ): Page { return importFileIssueRepository.findAllByFileIdView(fileId, pageable) } @@ -318,8 +364,7 @@ class ImportService( this.importFileIssueRepository.saveAll(issues) } - fun getAllByProject(projectId: Long) = - this.importRepository.findAllByProjectId(projectId) + fun getAllByProject(projectId: Long) = this.importRepository.findAllByProjectId(projectId) fun saveAllFileIssueParams(params: List): MutableList = importFileIssueParamRepository.saveAll(params) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/RemoveExpiredImportService.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/RemoveExpiredImportService.kt index 3453450de6..5048c0d300 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/RemoveExpiredImportService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/RemoveExpiredImportService.kt @@ -11,9 +11,8 @@ import org.springframework.transaction.annotation.Transactional class RemoveExpiredImportService( @Lazy private val importService: ImportService, - private val currentDateProvider: io.tolgee.component.CurrentDateProvider + private val currentDateProvider: io.tolgee.component.CurrentDateProvider, ) { - @Transactional(propagation = Propagation.REQUIRES_NEW) fun removeIfExpired(import: Import?): Import? { if (import == null) { diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/StoredDataImporter.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/StoredDataImporter.kt index 45aa54c0fc..aa61ca32cd 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/StoredDataImporter.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/StoredDataImporter.kt @@ -24,7 +24,6 @@ class StoredDataImporter( private val import: Import, private val forceMode: ForceMode = ForceMode.NO_FORCE, ) { - private val importDataManager = ImportDataManager(applicationContext, import) private val keyService = applicationContext.getBean(KeyService::class.java) private val namespaceService = applicationContext.getBean(NamespaceService::class.java) @@ -142,9 +141,10 @@ class StoredDataImporter( keysToSave[fileNamePair.first.namespace to importKey.name]?.let { newKey -> // if key is obtained or created and meta exists, take it and import the data from the imported one // persist is cascaded on key, so it should be fine - val keyMeta = importDataManager.existingMetas[fileNamePair.first.namespace to importKey.name]?.also { - keyMetaService.import(it, importedKeyMeta) - } ?: importedKeyMeta + val keyMeta = + importDataManager.existingMetas[fileNamePair.first.namespace to importKey.name]?.also { + keyMetaService.import(it, importedKeyMeta) + } ?: importedKeyMeta // also set key and remove import key keyMeta.also { it.key = newKey @@ -172,11 +172,13 @@ class StoredDataImporter( private fun ImportTranslation.doImport() { this.checkConflictResolved() if (this.conflict == null || (this.override && this.resolved) || forceMode == ForceMode.OVERRIDE) { - val language = this.language.existingLanguage - ?: throw BadRequestException(io.tolgee.constants.Message.EXISTING_LANGUAGE_NOT_SELECTED) - val translation = this.conflict ?: Translation().apply { - this.language = language - } + val language = + this.language.existingLanguage + ?: throw BadRequestException(io.tolgee.constants.Message.EXISTING_LANGUAGE_NOT_SELECTED) + val translation = + this.conflict ?: Translation().apply { + this.language = language + } translation.key = existingKey if (language == language.project.baseLanguage && translation.text != this.text) { outdatedFlagKeys.add(translation.key.id) @@ -192,17 +194,21 @@ class StoredDataImporter( // get key from already saved keys to save return keysToSave.computeIfAbsent(this.key.file.namespace to this.key.name) { // or get it from conflict or create new one - val newKey = this.conflict?.key - ?: importDataManager.existingKeys[this.key.file.namespace to this.key.name] - ?: Key(name = this.key.name).apply { - project = import.project - namespace = getNamespace(this@existingKey.key.file.namespace) - } + val newKey = + this.conflict?.key + ?: importDataManager.existingKeys[this.key.file.namespace to this.key.name] + ?: Key(name = this.key.name).apply { + project = import.project + namespace = getNamespace(this@existingKey.key.file.namespace) + } newKey } } - private fun addKeyToSave(namespace: String?, keyName: String): Key { + private fun addKeyToSave( + namespace: String?, + keyName: String, + ): Key { return keysToSave.computeIfAbsent(namespace to keyName) { importDataManager.existingKeys[namespace to keyName] ?: Key(name = keyName).apply { project = import.project @@ -215,7 +221,7 @@ class StoredDataImporter( if (forceMode == ForceMode.NO_FORCE && this.conflict != null && !this.resolved) { importDataManager.saveAllStoredTranslations() throw ImportConflictNotResolvedException( - mutableListOf(this.key.name, this.language.name, this.text).filterNotNull().toMutableList() + mutableListOf(this.key.name, this.language.name, this.text).filterNotNull().toMutableList(), ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/SupportedFormats.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/SupportedFormats.kt index c649a8919b..0d7bd7e810 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/SupportedFormats.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/SupportedFormats.kt @@ -1,8 +1,8 @@ package io.tolgee.service.dataImport enum class SupportedFormats( - val extension: String + val extension: String, ) { JSON(".json"), - PO(".po") + PO(".po"), } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/FileProcessorContext.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/FileProcessorContext.kt index bdbc84bfaf..9e863ea58d 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/FileProcessorContext.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/FileProcessorContext.kt @@ -22,7 +22,12 @@ data class FileProcessorContext( lateinit var languageNameGuesses: List - fun addTranslation(keyName: String, languageName: String, value: Any?, idx: Int = 0) { + fun addTranslation( + keyName: String, + languageName: String, + value: Any?, + idx: Int = 0, + ) { val stringValue = value as? String if (keyName.isBlank()) { @@ -62,14 +67,21 @@ data class FileProcessorContext( } } - fun addKeyComment(key: String, text: String) { + fun addKeyComment( + key: String, + text: String, + ) { val keyMeta = getOrCreateKeyMeta(key) keyMeta.addComment { this.text = text } } - fun addKeyCodeReference(key: String, path: String, line: Long? = null) { + fun addKeyCodeReference( + key: String, + path: String, + line: Long? = null, + ) { val keyMeta = getOrCreateKeyMeta(key) keyMeta.addCodeReference { this.path = path diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/ImportFileProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/ImportFileProcessor.kt index 7e02c7fe47..e24182db46 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/ImportFileProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/ImportFileProcessor.kt @@ -2,18 +2,20 @@ package io.tolgee.service.dataImport.processors abstract class ImportFileProcessor { abstract val context: FileProcessorContext + abstract fun process() val languageNameGuesses: List by lazy { val fileName = context.file.name - val result = arrayOf( - "^(.*?)\\..*".toRegex(), - "^(.*?)-.*".toRegex(), - "^(.*?)_.*".toRegex() - ).map { - fileName.replace(it, "$1") - }.filter { it.isNotBlank() } + val result = + arrayOf( + "^(.*?)\\..*".toRegex(), + "^(.*?)-.*".toRegex(), + "^(.*?)_.*".toRegex(), + ).map { + fileName.replace(it, "$1") + }.filter { it.isNotBlank() } context.languageNameGuesses = result result diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/ProcessorFactory.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/ProcessorFactory.kt index 81dc09e453..463ad405e3 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/ProcessorFactory.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/ProcessorFactory.kt @@ -15,7 +15,10 @@ class ProcessorFactory { } } - fun getProcessor(file: ImportFileDto, context: FileProcessorContext): ImportFileProcessor { + fun getProcessor( + file: ImportFileDto, + context: FileProcessorContext, + ): ImportFileProcessor { return when (file.name.fileNameExtension) { "json" -> JsonFileProcessor(context) "po" -> PoFileProcessor(context) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/ZipTypeProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/ZipTypeProcessor.kt index 722989d364..5a90c0e9dd 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/ZipTypeProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/ZipTypeProcessor.kt @@ -30,7 +30,7 @@ class ZipTypeProcessor : ImportArchiveProcessor { files[fileName] = ImportFileDto( name = fileName, - data.inputStream() + data.inputStream(), ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/FormatDetector.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/FormatDetector.kt index 1d0d6735d0..982be7a656 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/FormatDetector.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/FormatDetector.kt @@ -5,11 +5,12 @@ class FormatDetector(private val messages: List) { * Tries to detect message format by on all messages in file */ operator fun invoke(): SupportedFormat { - val regulars = mapOf( - SupportedFormat.C to ToICUConverter.C_PARAM_REGEX, - SupportedFormat.PHP to ToICUConverter.PHP_PARAM_REGEX, - SupportedFormat.PYTHON to ToICUConverter.PYTHON_PARAM_REGEX - ) + val regulars = + mapOf( + SupportedFormat.C to ToICUConverter.C_PARAM_REGEX, + SupportedFormat.PHP to ToICUConverter.PHP_PARAM_REGEX, + SupportedFormat.PYTHON to ToICUConverter.PYTHON_PARAM_REGEX, + ) val hitsMap = mutableMapOf() regulars.forEach { regularEntry -> diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/SupportedFormat.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/SupportedFormat.kt index 0ad58b349c..a403f71e8e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/SupportedFormat.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/SupportedFormat.kt @@ -3,11 +3,10 @@ package io.tolgee.service.dataImport.processors.messageFormat enum class SupportedFormat(val poFlag: String) { PHP(poFlag = "php-format"), C(poFlag = "c-format"), - PYTHON(poFlag = "python-format") + PYTHON(poFlag = "python-format"), ; companion object { - fun findByFlag(poFlag: String) = - values().find { it.poFlag == poFlag } + fun findByFlag(poFlag: String) = values().find { it.poFlag == poFlag } } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/ToICUConverter.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/ToICUConverter.kt index 19a761008b..7672213bf6 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/ToICUConverter.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/ToICUConverter.kt @@ -8,41 +8,46 @@ import io.tolgee.service.dataImport.processors.messageFormat.data.PluralData class ToICUConverter( private val locale: ULocale, private val format: SupportedFormat?, - private val context: FileProcessorContext + private val context: FileProcessorContext, ) { - companion object { - val PHP_PARAM_REGEX = """(?x)( - % - (?:(?\d+)${"\\$"})? - (?(?:[-+\s0]|'.)+)? - (?\d+)? - (?.\d+)? - (?[bcdeEfFgGhHosuxX%]) - ) - """.trimIndent().toRegex() - - val C_PARAM_REGEX = """(?x)( - % - (?:(?\d+)${"\\$"})? - (?[-+\s0\#]+)? - (?\d+)? - (?.\d+)? - (?hh|h|l|ll|j|z|t|L)? - (?[diuoxXfFeEgGaAcspn%]) - ) - """.trimIndent().toRegex() - - val PYTHON_PARAM_REGEX = """(?x)( - % - (?:\((?[\w-]+)\))? - (?[-+\s0\#]+)? - (?[\d*]+)? - (?.[\d*]+)? - (?[hlL])? - (?[diouxXeEfFgGcrs%]) - ) - """.trimIndent().toRegex() + val PHP_PARAM_REGEX = + """ + (?x)( + % + (?:(?\d+)${"\\$"})? + (?(?:[-+\s0]|'.)+)? + (?\d+)? + (?.\d+)? + (?[bcdeEfFgGhHosuxX%]) + ) + """.trimIndent().toRegex() + + val C_PARAM_REGEX = + """ + (?x)( + % + (?:(?\d+)${"\\$"})? + (?[-+\s0\#]+)? + (?\d+)? + (?.\d+)? + (?hh|h|l|ll|j|z|t|L)? + (?[diuoxXfFeEgGaAcspn%]) + ) + """.trimIndent().toRegex() + + val PYTHON_PARAM_REGEX = + """ + (?x)( + % + (?:\((?[\w-]+)\))? + (?[-+\s0\#]+)? + (?[\d*]+)? + (?.[\d*]+)? + (?[hlL])? + (?[diouxXeEfFgGcrs%]) + ) + """.trimIndent().toRegex() val PHP_NUMBER_SPECIFIERS = "dfeEfFgGhH" val C_NUMBER_SPECIFIERS = "diuoxXfFeEgG" @@ -86,30 +91,35 @@ class ToICUConverter( return convertCLike(message, PYTHON_PARAM_REGEX, PYTHON_NUMBER_SPECIFIERS) } - private fun convertCLike(message: String, regex: Regex, numberSpecifiers: String): String { + private fun convertCLike( + message: String, + regex: Regex, + numberSpecifiers: String, + ): String { var result = message var keyIdx = 0 - result = result.replace(regex) { - var paramName = keyIdx.toString() - val specifier = it.groups["specifier"]!!.value + result = + result.replace(regex) { + var paramName = keyIdx.toString() + val specifier = it.groups["specifier"]!!.value - if (specifier == "%") { - return@replace "%" - } + if (specifier == "%") { + return@replace "%" + } - it.groups.getGroupOrNull("argnum")?.let { grp -> - paramName = (grp.value.toInt() - 1).toString() - } + it.groups.getGroupOrNull("argnum")?.let { grp -> + paramName = (grp.value.toInt() - 1).toString() + } - it.groups.getGroupOrNull("argname")?.let { grp -> - paramName = grp.value - } + it.groups.getGroupOrNull("argname")?.let { grp -> + paramName = grp.value + } - val typeStr = if (numberSpecifiers.contains(specifier)) ", number" else "" - keyIdx++ - "{${paramName}$typeStr}" - } + val typeStr = if (numberSpecifiers.contains(specifier)) ", number" else "" + keyIdx++ + "{${paramName}$typeStr}" + } return result } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/data/PluralData.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/data/PluralData.kt index 062a2f95e3..1ca8d345a3 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/data/PluralData.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/data/PluralData.kt @@ -2,2347 +2,2821 @@ package io.tolgee.service.dataImport.processors.messageFormat.data class PluralData { companion object { - val DATA = mapOf( - "ach" to PluralLanguage( - tag = "ach", - name = "Acholi", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "af" to PluralLanguage( - tag = "af", - name = "Afrikaans", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "ak" to PluralLanguage( - tag = "ak", - name = "Akan", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "am" to PluralLanguage( - tag = "am", - name = "Amharic", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "an" to PluralLanguage( - tag = "an", - name = "Aragonese", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "ar" to PluralLanguage( - tag = "ar", - name = "Arabic", - examples = listOf( - PluralExample( - plural = 0, - sample = 0 - ), - PluralExample( - plural = 1, - sample = 1 - ), - PluralExample( - plural = 2, - sample = 2 - ), - PluralExample( - plural = 3, - sample = 3 - ), - PluralExample( - plural = 4, - sample = 11 - ), - PluralExample( - plural = 5, - sample = 100 - ) - ), - pluralsText = "nplurals = 6; plural = (n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5)", - nplurals = 6, - pluralsFunc = { n -> if (n == 0) 0 else if (n == 1) 1 else if (n == 2) 2 else if (n % 100 >= 3 && n % 100 <= 10) 3 else if (n % 100 >= 11) 4 else 5 } - ), - "arn" to PluralLanguage( - tag = "arn", - name = "Mapudungun", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "ast" to PluralLanguage( - tag = "ast", - name = "Asturian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "ay" to PluralLanguage( - tag = "ay", - name = "Aymará", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "az" to PluralLanguage( - tag = "az", - name = "Azerbaijani", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "be" to PluralLanguage( - tag = "be", - name = "Belarusian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ), - PluralExample( - plural = 2, - sample = 5 - ) - ), - pluralsText = "nplurals = 3; plural = (n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", - nplurals = 3, - pluralsFunc = { n -> if (n % 10 == 1 && n % 100 != 11) 0 else if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)) 1 else 2 } - ), - "bg" to PluralLanguage( - tag = "bg", - name = "Bulgarian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "bn" to PluralLanguage( - tag = "bn", - name = "Bengali", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "bo" to PluralLanguage( - tag = "bo", - name = "Tibetan", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "br" to PluralLanguage( - tag = "br", - name = "Breton", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "brx" to PluralLanguage( - tag = "brx", - name = "Bodo", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "bs" to PluralLanguage( - tag = "bs", - name = "Bosnian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ), - PluralExample( - plural = 2, - sample = 5 - ) - ), - pluralsText = "nplurals = 3; plural = (n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", - nplurals = 3, - pluralsFunc = { n -> if (n % 10 == 1 && n % 100 != 11) 0 else if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)) 1 else 2 } - ), - "ca" to PluralLanguage( - tag = "ca", - name = "Catalan", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "cgg" to PluralLanguage( - tag = "cgg", - name = "Chiga", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "cs" to PluralLanguage( - tag = "cs", - name = "Czech", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ), - PluralExample( - plural = 2, - sample = 5 - ) - ), - pluralsText = "nplurals = 3; plural = (n === 1 ? 0 : (n >= 2 && n <= 4) ? 1 : 2)", - nplurals = 3, - pluralsFunc = { n -> if (n == 1) 0 else if ((n >= 2 && n <= 4)) 1 else 2 } - ), - "csb" to PluralLanguage( - tag = "csb", - name = "Kashubian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ), - PluralExample( - plural = 2, - sample = 5 - ) - ), - pluralsText = "nplurals = 3; plural = (n === 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", - nplurals = 3, - pluralsFunc = { n -> if (n == 1) 0 else if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)) 1 else 2 } - ), - "cy" to PluralLanguage( - tag = "cy", - name = "Welsh", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ), - PluralExample( - plural = 2, - sample = 3 - ), - PluralExample( - plural = 3, - sample = 8 - ) - ), - pluralsText = "nplurals = 4; plural = (n === 1 ? 0 : n === 2 ? 1 : (n !== 8 && n !== 11) ? 2 : 3)", - nplurals = 4, - pluralsFunc = { n -> if (n == 1) 0 else if (n == 2) 1 else if ((n != 8 && n != 11)) 2 else 3 } - ), - "da" to PluralLanguage( - tag = "da", - name = "Danish", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "de" to PluralLanguage( - tag = "de", - name = "German", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "doi" to PluralLanguage( - tag = "doi", - name = "Dogri", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "dz" to PluralLanguage( - tag = "dz", - name = "Dzongkha", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "el" to PluralLanguage( - tag = "el", - name = "Greek", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "en" to PluralLanguage( - tag = "en", - name = "English", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "eo" to PluralLanguage( - tag = "eo", - name = "Esperanto", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "es" to PluralLanguage( - tag = "es", - name = "Spanish", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "et" to PluralLanguage( - tag = "et", - name = "Estonian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "eu" to PluralLanguage( - tag = "eu", - name = "Basque", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "fa" to PluralLanguage( - tag = "fa", - name = "Persian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "ff" to PluralLanguage( - tag = "ff", - name = "Fulah", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "fi" to PluralLanguage( - tag = "fi", - name = "Finnish", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "fil" to PluralLanguage( - tag = "fil", - name = "Filipino", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "fo" to PluralLanguage( - tag = "fo", - name = "Faroese", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "fr" to PluralLanguage( - tag = "fr", - name = "French", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "fur" to PluralLanguage( - tag = "fur", - name = "Friulian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "fy" to PluralLanguage( - tag = "fy", - name = "Frisian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "ga" to PluralLanguage( - tag = "ga", - name = "Irish", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ), - PluralExample( - plural = 2, - sample = 3 - ), - PluralExample( - plural = 3, - sample = 7 - ), - PluralExample( - plural = 4, - sample = 11 - ) - ), - pluralsText = "nplurals = 5; plural = (n === 1 ? 0 : n === 2 ? 1 : n < 7 ? 2 : n < 11 ? 3 : 4)", - nplurals = 5, - pluralsFunc = { n -> if (n == 1) 0 else if (n == 2) 1 else if (n < 7) 2 else if (n < 11) 3 else 4 } - ), - "gd" to PluralLanguage( - tag = "gd", - name = "Scottish Gaelic", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ), - PluralExample( - plural = 2, - sample = 3 - ), - PluralExample( - plural = 3, - sample = 20 - ) - ), - pluralsText = "nplurals = 4; plural = ((n === 1 || n === 11) ? 0 : (n === 2 || n === 12) ? 1 : (n > 2 && n < 20) ? 2 : 3)", - nplurals = 4, - pluralsFunc = { n -> if ((n == 1 || n == 11)) 0 else if ((n == 2 || n == 12)) 1 else if ((n > 2 && n < 20)) 2 else 3 } - ), - "gl" to PluralLanguage( - tag = "gl", - name = "Galician", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "gu" to PluralLanguage( - tag = "gu", - name = "Gujarati", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "gun" to PluralLanguage( - tag = "gun", - name = "Gun", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "ha" to PluralLanguage( - tag = "ha", - name = "Hausa", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "he" to PluralLanguage( - tag = "he", - name = "Hebrew", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "hi" to PluralLanguage( - tag = "hi", - name = "Hindi", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "hne" to PluralLanguage( - tag = "hne", - name = "Chhattisgarhi", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "hr" to PluralLanguage( - tag = "hr", - name = "Croatian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ), - PluralExample( - plural = 2, - sample = 5 - ) - ), - pluralsText = "nplurals = 3; plural = (n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", - nplurals = 3, - pluralsFunc = { n -> if (n % 10 == 1 && n % 100 != 11) 0 else if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)) 1 else 2 } - ), - "hu" to PluralLanguage( - tag = "hu", - name = "Hungarian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "hy" to PluralLanguage( - tag = "hy", - name = "Armenian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "id" to PluralLanguage( - tag = "id", - name = "Indonesian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "is" to PluralLanguage( - tag = "is", - name = "Icelandic", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n % 10 !== 1 || n % 100 === 11)", - nplurals = 2, - pluralsFunc = { n -> if (n % 10 != 1 || n % 100 == 11) 0 else 1 } - ), - "it" to PluralLanguage( - tag = "it", - name = "Italian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "ja" to PluralLanguage( - tag = "ja", - name = "Japanese", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "jbo" to PluralLanguage( - tag = "jbo", - name = "Lojban", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "jv" to PluralLanguage( - tag = "jv", - name = "Javanese", - examples = listOf( - PluralExample( - plural = 0, - sample = 0 - ), - PluralExample( - plural = 1, - sample = 1 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 0)", - nplurals = 2, - pluralsFunc = { n -> if (n != 0) 0 else 1 } - ), - "ka" to PluralLanguage( - tag = "ka", - name = "Georgian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "kk" to PluralLanguage( - tag = "kk", - name = "Kazakh", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "km" to PluralLanguage( - tag = "km", - name = "Khmer", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "kn" to PluralLanguage( - tag = "kn", - name = "Kannada", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "ko" to PluralLanguage( - tag = "ko", - name = "Korean", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "ku" to PluralLanguage( - tag = "ku", - name = "Kurdish", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "kw" to PluralLanguage( - tag = "kw", - name = "Cornish", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ), - PluralExample( - plural = 2, - sample = 3 - ), - PluralExample( - plural = 3, - sample = 4 - ) - ), - pluralsText = "nplurals = 4; plural = (n === 1 ? 0 : n === 2 ? 1 : n === 3 ? 2 : 3)", - nplurals = 4, - pluralsFunc = { n -> if (n == 1) 0 else if (n == 2) 1 else if (n == 3) 2 else 3 } - ), - "ky" to PluralLanguage( - tag = "ky", - name = "Kyrgyz", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "lb" to PluralLanguage( - tag = "lb", - name = "Letzeburgesch", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "ln" to PluralLanguage( - tag = "ln", - name = "Lingala", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "lo" to PluralLanguage( - tag = "lo", - name = "Lao", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "lt" to PluralLanguage( - tag = "lt", - name = "Lithuanian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ), - PluralExample( - plural = 2, - sample = 10 - ) - ), - pluralsText = "nplurals = 3; plural = (n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", - nplurals = 3, - pluralsFunc = { n -> if (n % 10 == 1 && n % 100 != 11) 0 else if (n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20)) 1 else 2 } - ), - "lv" to PluralLanguage( - tag = "lv", - name = "Latvian", - examples = listOf( - PluralExample( - plural = 2, - sample = 0 - ), - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 3; plural = (n % 10 === 1 && n % 100 !== 11 ? 0 : n !== 0 ? 1 : 2)", - nplurals = 3, - pluralsFunc = { n -> if (n % 10 == 1 && n % 100 != 11) 0 else if (n != 0) 1 else 2 } - ), - "mai" to PluralLanguage( - tag = "mai", - name = "Maithili", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "mfe" to PluralLanguage( - tag = "mfe", - name = "Mauritian Creole", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "mg" to PluralLanguage( - tag = "mg", - name = "Malagasy", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "mi" to PluralLanguage( - tag = "mi", - name = "Maori", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "mk" to PluralLanguage( - tag = "mk", - name = "Macedonian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n === 1 || n % 10 === 1 ? 0 : 1)", - nplurals = 2, - pluralsFunc = { n -> if (n == 1 || n % 10 == 1) 0 else 1 } - ), - "ml" to PluralLanguage( - tag = "ml", - name = "Malayalam", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "mn" to PluralLanguage( - tag = "mn", - name = "Mongolian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "mni" to PluralLanguage( - tag = "mni", - name = "Manipuri", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "mnk" to PluralLanguage( - tag = "mnk", - name = "Mandinka", - examples = listOf( - PluralExample( - plural = 0, - sample = 0 - ), - PluralExample( - plural = 1, - sample = 1 - ), - PluralExample( - plural = 2, - sample = 2 - ) - ), - pluralsText = "nplurals = 3; plural = (n === 0 ? 0 : n === 1 ? 1 : 2)", - nplurals = 3, - pluralsFunc = { n -> if (n == 0) 0 else if (n == 1) 1 else 2 } - ), - "mr" to PluralLanguage( - tag = "mr", - name = "Marathi", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "ms" to PluralLanguage( - tag = "ms", - name = "Malay", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "mt" to PluralLanguage( - tag = "mt", - name = "Maltese", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ), - PluralExample( - plural = 2, - sample = 11 - ), - PluralExample( - plural = 3, - sample = 20 - ) - ), - pluralsText = "nplurals = 4; plural = (n === 1 ? 0 : n === 0 || ( n % 100 > 1 && n % 100 < 11) ? 1 : (n % 100 > 10 && n % 100 < 20 ) ? 2 : 3)", - nplurals = 4, - pluralsFunc = { n -> if (n == 1) 0 else if (n == 0 || (n % 100 > 1 && n % 100 < 11)) 1 else if ((n % 100 > 10 && n % 100 < 20)) 2 else 3 } - ), - "my" to PluralLanguage( - tag = "my", - name = "Burmese", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "nah" to PluralLanguage( - tag = "nah", - name = "Nahuatl", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "nap" to PluralLanguage( - tag = "nap", - name = "Neapolitan", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "nb" to PluralLanguage( - tag = "nb", - name = "Norwegian Bokmal", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "ne" to PluralLanguage( - tag = "ne", - name = "Nepali", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "nl" to PluralLanguage( - tag = "nl", - name = "Dutch", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "nn" to PluralLanguage( - tag = "nn", - name = "Norwegian Nynorsk", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "no" to PluralLanguage( - tag = "no", - name = "Norwegian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "nso" to PluralLanguage( - tag = "nso", - name = "Northern Sotho", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "oc" to PluralLanguage( - tag = "oc", - name = "Occitan", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "or" to PluralLanguage( - tag = "or", - name = "Oriya", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "pa" to PluralLanguage( - tag = "pa", - name = "Punjabi", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "pap" to PluralLanguage( - tag = "pap", - name = "Papiamento", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "pl" to PluralLanguage( - tag = "pl", - name = "Polish", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ), - PluralExample( - plural = 2, - sample = 5 - ) - ), - pluralsText = "nplurals = 3; plural = (n === 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", - nplurals = 3, - pluralsFunc = { n -> if (n == 1) 0 else if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)) 1 else 2 } - ), - "pms" to PluralLanguage( - tag = "pms", - name = "Piemontese", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "ps" to PluralLanguage( - tag = "ps", - name = "Pashto", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "pt" to PluralLanguage( - tag = "pt", - name = "Portuguese", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "rm" to PluralLanguage( - tag = "rm", - name = "Romansh", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "ro" to PluralLanguage( - tag = "ro", - name = "Romanian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ), - PluralExample( - plural = 2, - sample = 20 - ) - ), - pluralsText = "nplurals = 3; plural = (n === 1 ? 0 : (n === 0 || (n % 100 > 0 && n % 100 < 20)) ? 1 : 2)", - nplurals = 3, - pluralsFunc = { n -> if (n == 1) 0 else if ((n == 0 || (n % 100 > 0 && n % 100 < 20))) 1 else 2 } - ), - "ru" to PluralLanguage( - tag = "ru", - name = "Russian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ), - PluralExample( - plural = 2, - sample = 5 - ) - ), - pluralsText = "nplurals = 3; plural = (n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", - nplurals = 3, - pluralsFunc = { n -> if (n % 10 == 1 && n % 100 != 11) 0 else if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)) 1 else 2 } - ), - "rw" to PluralLanguage( - tag = "rw", - name = "Kinyarwanda", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "sah" to PluralLanguage( - tag = "sah", - name = "Yakut", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "sat" to PluralLanguage( - tag = "sat", - name = "Santali", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "sco" to PluralLanguage( - tag = "sco", - name = "Scots", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "sd" to PluralLanguage( - tag = "sd", - name = "Sindhi", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "se" to PluralLanguage( - tag = "se", - name = "Northern Sami", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "si" to PluralLanguage( - tag = "si", - name = "Sinhala", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "sk" to PluralLanguage( - tag = "sk", - name = "Slovak", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ), - PluralExample( - plural = 2, - sample = 5 - ) - ), - pluralsText = "nplurals = 3; plural = (n === 1 ? 0 : (n >= 2 && n <= 4) ? 1 : 2)", - nplurals = 3, - pluralsFunc = { n -> if (n == 1) 0 else if ((n >= 2 && n <= 4)) 1 else 2 } - ), - "sl" to PluralLanguage( - tag = "sl", - name = "Slovenian", - examples = listOf( - PluralExample( - plural = 1, - sample = 1 - ), - PluralExample( - plural = 2, - sample = 2 - ), - PluralExample( - plural = 3, - sample = 3 - ), - PluralExample( - plural = 0, - sample = 5 - ) - ), - pluralsText = "nplurals = 4; plural = (n % 100 === 1 ? 1 : n % 100 === 2 ? 2 : n % 100 === 3 || n % 100 === 4 ? 3 : 0)", - nplurals = 4, - pluralsFunc = { n -> if (n % 100 == 1) 1 else if (n % 100 == 2) 2 else if (n % 100 == 3 || n % 100 == 4) 3 else 0 } - ), - "so" to PluralLanguage( - tag = "so", - name = "Somali", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "son" to PluralLanguage( - tag = "son", - name = "Songhay", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "sq" to PluralLanguage( - tag = "sq", - name = "Albanian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "sr" to PluralLanguage( - tag = "sr", - name = "Serbian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ), - PluralExample( - plural = 2, - sample = 5 - ) - ), - pluralsText = "nplurals = 3; plural = (n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", - nplurals = 3, - pluralsFunc = { n -> if (n % 10 == 1 && n % 100 != 11) 0 else if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)) 1 else 2 } - ), - "su" to PluralLanguage( - tag = "su", - name = "Sundanese", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "sv" to PluralLanguage( - tag = "sv", - name = "Swedish", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "sw" to PluralLanguage( - tag = "sw", - name = "Swahili", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "ta" to PluralLanguage( - tag = "ta", - name = "Tamil", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "te" to PluralLanguage( - tag = "te", - name = "Telugu", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "tg" to PluralLanguage( - tag = "tg", - name = "Tajik", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "th" to PluralLanguage( - tag = "th", - name = "Thai", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "ti" to PluralLanguage( - tag = "ti", - name = "Tigrinya", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "tk" to PluralLanguage( - tag = "tk", - name = "Turkmen", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "tr" to PluralLanguage( - tag = "tr", - name = "Turkish", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "tt" to PluralLanguage( - tag = "tt", - name = "Tatar", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "ug" to PluralLanguage( - tag = "ug", - name = "Uyghur", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "uk" to PluralLanguage( - tag = "uk", - name = "Ukrainian", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ), - PluralExample( - plural = 2, - sample = 5 - ) - ), - pluralsText = "nplurals = 3; plural = (n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", - nplurals = 3, - pluralsFunc = { n -> if (n % 10 == 1 && n % 100 != 11) 0 else if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)) 1 else 2 } - ), - "ur" to PluralLanguage( - tag = "ur", - name = "Urdu", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "uz" to PluralLanguage( - tag = "uz", - name = "Uzbek", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "vi" to PluralLanguage( - tag = "vi", - name = "Vietnamese", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "wa" to PluralLanguage( - tag = "wa", - name = "Walloon", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n > 1)", - nplurals = 2, - pluralsFunc = { n -> if (n > 1) 0 else 1 } - ), - "wo" to PluralLanguage( - tag = "wo", - name = "Wolof", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - "yo" to PluralLanguage( - tag = "yo", - name = "Yoruba", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ), - PluralExample( - plural = 1, - sample = 2 - ) - ), - pluralsText = "nplurals = 2; plural = (n !== 1)", - nplurals = 2, - pluralsFunc = { n -> if (n != 1) 0 else 1 } - ), - "zh" to PluralLanguage( - tag = "zh", - name = "Chinese", - examples = listOf( - PluralExample( - plural = 0, - sample = 1 - ) - ), - pluralsText = "nplurals = 1; plural = 0", - nplurals = 1, - pluralsFunc = { n -> 0 } - ), - ) + val DATA = + mapOf( + "ach" to + PluralLanguage( + tag = "ach", + name = "Acholi", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "af" to + PluralLanguage( + tag = "af", + name = "Afrikaans", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "ak" to + PluralLanguage( + tag = "ak", + name = "Akan", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "am" to + PluralLanguage( + tag = "am", + name = "Amharic", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "an" to + PluralLanguage( + tag = "an", + name = "Aragonese", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "ar" to + PluralLanguage( + tag = "ar", + name = "Arabic", + examples = + listOf( + PluralExample( + plural = 0, + sample = 0, + ), + PluralExample( + plural = 1, + sample = 1, + ), + PluralExample( + plural = 2, + sample = 2, + ), + PluralExample( + plural = 3, + sample = 3, + ), + PluralExample( + plural = 4, + sample = 11, + ), + PluralExample( + plural = 5, + sample = 100, + ), + ), + pluralsText = "nplurals = 6; plural = (n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5)", + nplurals = 6, + pluralsFunc = { + n -> + if (n == 0) { + 0 + } else if (n == 1) { + 1 + } else if (n == 2) { + 2 + } else if (n % 100 >= 3 && n % 100 <= 10) { + 3 + } else if (n % 100 >= 11) { + 4 + } else { + 5 + } + }, + ), + "arn" to + PluralLanguage( + tag = "arn", + name = "Mapudungun", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "ast" to + PluralLanguage( + tag = "ast", + name = "Asturian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "ay" to + PluralLanguage( + tag = "ay", + name = "Aymará", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "az" to + PluralLanguage( + tag = "az", + name = "Azerbaijani", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "be" to + PluralLanguage( + tag = "be", + name = "Belarusian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + PluralExample( + plural = 2, + sample = 5, + ), + ), + pluralsText = "nplurals = 3; plural = (n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", + nplurals = 3, + pluralsFunc = { + n -> + if (n % 10 == 1 && n % 100 != 11) { + 0 + } else if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)) { + 1 + } else { + 2 + } + }, + ), + "bg" to + PluralLanguage( + tag = "bg", + name = "Bulgarian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "bn" to + PluralLanguage( + tag = "bn", + name = "Bengali", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "bo" to + PluralLanguage( + tag = "bo", + name = "Tibetan", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "br" to + PluralLanguage( + tag = "br", + name = "Breton", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "brx" to + PluralLanguage( + tag = "brx", + name = "Bodo", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "bs" to + PluralLanguage( + tag = "bs", + name = "Bosnian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + PluralExample( + plural = 2, + sample = 5, + ), + ), + pluralsText = "nplurals = 3; plural = (n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", + nplurals = 3, + pluralsFunc = { + n -> + if (n % 10 == 1 && n % 100 != 11) { + 0 + } else if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)) { + 1 + } else { + 2 + } + }, + ), + "ca" to + PluralLanguage( + tag = "ca", + name = "Catalan", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "cgg" to + PluralLanguage( + tag = "cgg", + name = "Chiga", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "cs" to + PluralLanguage( + tag = "cs", + name = "Czech", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + PluralExample( + plural = 2, + sample = 5, + ), + ), + pluralsText = "nplurals = 3; plural = (n === 1 ? 0 : (n >= 2 && n <= 4) ? 1 : 2)", + nplurals = 3, + pluralsFunc = { n -> + if (n == 1) { + 0 + } else if ((n >= 2 && n <= 4)) { + 1 + } else { + 2 + } + }, + ), + "csb" to + PluralLanguage( + tag = "csb", + name = "Kashubian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + PluralExample( + plural = 2, + sample = 5, + ), + ), + pluralsText = "nplurals = 3; plural = (n === 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", + nplurals = 3, + pluralsFunc = { + n -> + if (n == 1) { + 0 + } else if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)) { + 1 + } else { + 2 + } + }, + ), + "cy" to + PluralLanguage( + tag = "cy", + name = "Welsh", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + PluralExample( + plural = 2, + sample = 3, + ), + PluralExample( + plural = 3, + sample = 8, + ), + ), + pluralsText = "nplurals = 4; plural = (n === 1 ? 0 : n === 2 ? 1 : (n !== 8 && n !== 11) ? 2 : 3)", + nplurals = 4, + pluralsFunc = { n -> + if (n == 1) { + 0 + } else if (n == 2) { + 1 + } else if ((n != 8 && n != 11)) { + 2 + } else { + 3 + } + }, + ), + "da" to + PluralLanguage( + tag = "da", + name = "Danish", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "de" to + PluralLanguage( + tag = "de", + name = "German", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "doi" to + PluralLanguage( + tag = "doi", + name = "Dogri", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "dz" to + PluralLanguage( + tag = "dz", + name = "Dzongkha", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "el" to + PluralLanguage( + tag = "el", + name = "Greek", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "en" to + PluralLanguage( + tag = "en", + name = "English", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "eo" to + PluralLanguage( + tag = "eo", + name = "Esperanto", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "es" to + PluralLanguage( + tag = "es", + name = "Spanish", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "et" to + PluralLanguage( + tag = "et", + name = "Estonian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "eu" to + PluralLanguage( + tag = "eu", + name = "Basque", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "fa" to + PluralLanguage( + tag = "fa", + name = "Persian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "ff" to + PluralLanguage( + tag = "ff", + name = "Fulah", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "fi" to + PluralLanguage( + tag = "fi", + name = "Finnish", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "fil" to + PluralLanguage( + tag = "fil", + name = "Filipino", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "fo" to + PluralLanguage( + tag = "fo", + name = "Faroese", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "fr" to + PluralLanguage( + tag = "fr", + name = "French", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "fur" to + PluralLanguage( + tag = "fur", + name = "Friulian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "fy" to + PluralLanguage( + tag = "fy", + name = "Frisian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "ga" to + PluralLanguage( + tag = "ga", + name = "Irish", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + PluralExample( + plural = 2, + sample = 3, + ), + PluralExample( + plural = 3, + sample = 7, + ), + PluralExample( + plural = 4, + sample = 11, + ), + ), + pluralsText = "nplurals = 5; plural = (n === 1 ? 0 : n === 2 ? 1 : n < 7 ? 2 : n < 11 ? 3 : 4)", + nplurals = 5, + pluralsFunc = { n -> + if (n == 1) { + 0 + } else if (n == 2) { + 1 + } else if (n < 7) { + 2 + } else if (n < 11) { + 3 + } else { + 4 + } + }, + ), + "gd" to + PluralLanguage( + tag = "gd", + name = "Scottish Gaelic", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + PluralExample( + plural = 2, + sample = 3, + ), + PluralExample( + plural = 3, + sample = 20, + ), + ), + pluralsText = "nplurals = 4; plural = ((n === 1 || n === 11) ? 0 : (n === 2 || n === 12) ? 1 : (n > 2 && n < 20) ? 2 : 3)", + nplurals = 4, + pluralsFunc = { + n -> + if ((n == 1 || n == 11)) { + 0 + } else if ((n == 2 || n == 12)) { + 1 + } else if ((n > 2 && n < 20)) { + 2 + } else { + 3 + } + }, + ), + "gl" to + PluralLanguage( + tag = "gl", + name = "Galician", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "gu" to + PluralLanguage( + tag = "gu", + name = "Gujarati", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "gun" to + PluralLanguage( + tag = "gun", + name = "Gun", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "ha" to + PluralLanguage( + tag = "ha", + name = "Hausa", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "he" to + PluralLanguage( + tag = "he", + name = "Hebrew", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "hi" to + PluralLanguage( + tag = "hi", + name = "Hindi", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "hne" to + PluralLanguage( + tag = "hne", + name = "Chhattisgarhi", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "hr" to + PluralLanguage( + tag = "hr", + name = "Croatian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + PluralExample( + plural = 2, + sample = 5, + ), + ), + pluralsText = "nplurals = 3; plural = (n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", + nplurals = 3, + pluralsFunc = { + n -> + if (n % 10 == 1 && n % 100 != 11) { + 0 + } else if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)) { + 1 + } else { + 2 + } + }, + ), + "hu" to + PluralLanguage( + tag = "hu", + name = "Hungarian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "hy" to + PluralLanguage( + tag = "hy", + name = "Armenian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "id" to + PluralLanguage( + tag = "id", + name = "Indonesian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "is" to + PluralLanguage( + tag = "is", + name = "Icelandic", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n % 10 !== 1 || n % 100 === 11)", + nplurals = 2, + pluralsFunc = { n -> if (n % 10 != 1 || n % 100 == 11) 0 else 1 }, + ), + "it" to + PluralLanguage( + tag = "it", + name = "Italian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "ja" to + PluralLanguage( + tag = "ja", + name = "Japanese", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "jbo" to + PluralLanguage( + tag = "jbo", + name = "Lojban", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "jv" to + PluralLanguage( + tag = "jv", + name = "Javanese", + examples = + listOf( + PluralExample( + plural = 0, + sample = 0, + ), + PluralExample( + plural = 1, + sample = 1, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 0)", + nplurals = 2, + pluralsFunc = { n -> if (n != 0) 0 else 1 }, + ), + "ka" to + PluralLanguage( + tag = "ka", + name = "Georgian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "kk" to + PluralLanguage( + tag = "kk", + name = "Kazakh", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "km" to + PluralLanguage( + tag = "km", + name = "Khmer", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "kn" to + PluralLanguage( + tag = "kn", + name = "Kannada", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "ko" to + PluralLanguage( + tag = "ko", + name = "Korean", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "ku" to + PluralLanguage( + tag = "ku", + name = "Kurdish", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "kw" to + PluralLanguage( + tag = "kw", + name = "Cornish", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + PluralExample( + plural = 2, + sample = 3, + ), + PluralExample( + plural = 3, + sample = 4, + ), + ), + pluralsText = "nplurals = 4; plural = (n === 1 ? 0 : n === 2 ? 1 : n === 3 ? 2 : 3)", + nplurals = 4, + pluralsFunc = { n -> + if (n == 1) { + 0 + } else if (n == 2) { + 1 + } else if (n == 3) { + 2 + } else { + 3 + } + }, + ), + "ky" to + PluralLanguage( + tag = "ky", + name = "Kyrgyz", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "lb" to + PluralLanguage( + tag = "lb", + name = "Letzeburgesch", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "ln" to + PluralLanguage( + tag = "ln", + name = "Lingala", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "lo" to + PluralLanguage( + tag = "lo", + name = "Lao", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "lt" to + PluralLanguage( + tag = "lt", + name = "Lithuanian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + PluralExample( + plural = 2, + sample = 10, + ), + ), + pluralsText = "nplurals = 3; plural = (n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", + nplurals = 3, + pluralsFunc = { + n -> + if (n % 10 == 1 && n % 100 != 11) { + 0 + } else if (n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20)) { + 1 + } else { + 2 + } + }, + ), + "lv" to + PluralLanguage( + tag = "lv", + name = "Latvian", + examples = + listOf( + PluralExample( + plural = 2, + sample = 0, + ), + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 3; plural = (n % 10 === 1 && n % 100 !== 11 ? 0 : n !== 0 ? 1 : 2)", + nplurals = 3, + pluralsFunc = { n -> + if (n % 10 == 1 && n % 100 != 11) { + 0 + } else if (n != 0) { + 1 + } else { + 2 + } + }, + ), + "mai" to + PluralLanguage( + tag = "mai", + name = "Maithili", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "mfe" to + PluralLanguage( + tag = "mfe", + name = "Mauritian Creole", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "mg" to + PluralLanguage( + tag = "mg", + name = "Malagasy", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "mi" to + PluralLanguage( + tag = "mi", + name = "Maori", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "mk" to + PluralLanguage( + tag = "mk", + name = "Macedonian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n === 1 || n % 10 === 1 ? 0 : 1)", + nplurals = 2, + pluralsFunc = { n -> if (n == 1 || n % 10 == 1) 0 else 1 }, + ), + "ml" to + PluralLanguage( + tag = "ml", + name = "Malayalam", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "mn" to + PluralLanguage( + tag = "mn", + name = "Mongolian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "mni" to + PluralLanguage( + tag = "mni", + name = "Manipuri", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "mnk" to + PluralLanguage( + tag = "mnk", + name = "Mandinka", + examples = + listOf( + PluralExample( + plural = 0, + sample = 0, + ), + PluralExample( + plural = 1, + sample = 1, + ), + PluralExample( + plural = 2, + sample = 2, + ), + ), + pluralsText = "nplurals = 3; plural = (n === 0 ? 0 : n === 1 ? 1 : 2)", + nplurals = 3, + pluralsFunc = { n -> + if (n == 0) { + 0 + } else if (n == 1) { + 1 + } else { + 2 + } + }, + ), + "mr" to + PluralLanguage( + tag = "mr", + name = "Marathi", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "ms" to + PluralLanguage( + tag = "ms", + name = "Malay", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "mt" to + PluralLanguage( + tag = "mt", + name = "Maltese", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + PluralExample( + plural = 2, + sample = 11, + ), + PluralExample( + plural = 3, + sample = 20, + ), + ), + pluralsText = "nplurals = 4; plural = (n === 1 ? 0 : n === 0 || ( n % 100 > 1 && n % 100 < 11) ? 1 : (n % 100 > 10 && n % 100 < 20 ) ? 2 : 3)", + nplurals = 4, + pluralsFunc = { + n -> + if (n == 1) { + 0 + } else if (n == 0 || (n % 100 > 1 && n % 100 < 11)) { + 1 + } else if ((n % 100 > 10 && n % 100 < 20)) { + 2 + } else { + 3 + } + }, + ), + "my" to + PluralLanguage( + tag = "my", + name = "Burmese", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "nah" to + PluralLanguage( + tag = "nah", + name = "Nahuatl", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "nap" to + PluralLanguage( + tag = "nap", + name = "Neapolitan", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "nb" to + PluralLanguage( + tag = "nb", + name = "Norwegian Bokmal", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "ne" to + PluralLanguage( + tag = "ne", + name = "Nepali", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "nl" to + PluralLanguage( + tag = "nl", + name = "Dutch", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "nn" to + PluralLanguage( + tag = "nn", + name = "Norwegian Nynorsk", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "no" to + PluralLanguage( + tag = "no", + name = "Norwegian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "nso" to + PluralLanguage( + tag = "nso", + name = "Northern Sotho", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "oc" to + PluralLanguage( + tag = "oc", + name = "Occitan", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "or" to + PluralLanguage( + tag = "or", + name = "Oriya", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "pa" to + PluralLanguage( + tag = "pa", + name = "Punjabi", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "pap" to + PluralLanguage( + tag = "pap", + name = "Papiamento", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "pl" to + PluralLanguage( + tag = "pl", + name = "Polish", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + PluralExample( + plural = 2, + sample = 5, + ), + ), + pluralsText = "nplurals = 3; plural = (n === 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", + nplurals = 3, + pluralsFunc = { + n -> + if (n == 1) { + 0 + } else if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)) { + 1 + } else { + 2 + } + }, + ), + "pms" to + PluralLanguage( + tag = "pms", + name = "Piemontese", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "ps" to + PluralLanguage( + tag = "ps", + name = "Pashto", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "pt" to + PluralLanguage( + tag = "pt", + name = "Portuguese", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "rm" to + PluralLanguage( + tag = "rm", + name = "Romansh", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "ro" to + PluralLanguage( + tag = "ro", + name = "Romanian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + PluralExample( + plural = 2, + sample = 20, + ), + ), + pluralsText = "nplurals = 3; plural = (n === 1 ? 0 : (n === 0 || (n % 100 > 0 && n % 100 < 20)) ? 1 : 2)", + nplurals = 3, + pluralsFunc = { n -> + if (n == 1) { + 0 + } else if ((n == 0 || (n % 100 > 0 && n % 100 < 20))) { + 1 + } else { + 2 + } + }, + ), + "ru" to + PluralLanguage( + tag = "ru", + name = "Russian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + PluralExample( + plural = 2, + sample = 5, + ), + ), + pluralsText = "nplurals = 3; plural = (n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", + nplurals = 3, + pluralsFunc = { + n -> + if (n % 10 == 1 && n % 100 != 11) { + 0 + } else if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)) { + 1 + } else { + 2 + } + }, + ), + "rw" to + PluralLanguage( + tag = "rw", + name = "Kinyarwanda", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "sah" to + PluralLanguage( + tag = "sah", + name = "Yakut", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "sat" to + PluralLanguage( + tag = "sat", + name = "Santali", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "sco" to + PluralLanguage( + tag = "sco", + name = "Scots", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "sd" to + PluralLanguage( + tag = "sd", + name = "Sindhi", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "se" to + PluralLanguage( + tag = "se", + name = "Northern Sami", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "si" to + PluralLanguage( + tag = "si", + name = "Sinhala", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "sk" to + PluralLanguage( + tag = "sk", + name = "Slovak", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + PluralExample( + plural = 2, + sample = 5, + ), + ), + pluralsText = "nplurals = 3; plural = (n === 1 ? 0 : (n >= 2 && n <= 4) ? 1 : 2)", + nplurals = 3, + pluralsFunc = { n -> + if (n == 1) { + 0 + } else if ((n >= 2 && n <= 4)) { + 1 + } else { + 2 + } + }, + ), + "sl" to + PluralLanguage( + tag = "sl", + name = "Slovenian", + examples = + listOf( + PluralExample( + plural = 1, + sample = 1, + ), + PluralExample( + plural = 2, + sample = 2, + ), + PluralExample( + plural = 3, + sample = 3, + ), + PluralExample( + plural = 0, + sample = 5, + ), + ), + pluralsText = "nplurals = 4; plural = (n % 100 === 1 ? 1 : n % 100 === 2 ? 2 : n % 100 === 3 || n % 100 === 4 ? 3 : 0)", + nplurals = 4, + pluralsFunc = { + n -> + if (n % 100 == 1) { + 1 + } else if (n % 100 == 2) { + 2 + } else if (n % 100 == 3 || n % 100 == 4) { + 3 + } else { + 0 + } + }, + ), + "so" to + PluralLanguage( + tag = "so", + name = "Somali", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "son" to + PluralLanguage( + tag = "son", + name = "Songhay", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "sq" to + PluralLanguage( + tag = "sq", + name = "Albanian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "sr" to + PluralLanguage( + tag = "sr", + name = "Serbian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + PluralExample( + plural = 2, + sample = 5, + ), + ), + pluralsText = "nplurals = 3; plural = (n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", + nplurals = 3, + pluralsFunc = { + n -> + if (n % 10 == 1 && n % 100 != 11) { + 0 + } else if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)) { + 1 + } else { + 2 + } + }, + ), + "su" to + PluralLanguage( + tag = "su", + name = "Sundanese", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "sv" to + PluralLanguage( + tag = "sv", + name = "Swedish", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "sw" to + PluralLanguage( + tag = "sw", + name = "Swahili", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "ta" to + PluralLanguage( + tag = "ta", + name = "Tamil", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "te" to + PluralLanguage( + tag = "te", + name = "Telugu", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "tg" to + PluralLanguage( + tag = "tg", + name = "Tajik", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "th" to + PluralLanguage( + tag = "th", + name = "Thai", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "ti" to + PluralLanguage( + tag = "ti", + name = "Tigrinya", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "tk" to + PluralLanguage( + tag = "tk", + name = "Turkmen", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "tr" to + PluralLanguage( + tag = "tr", + name = "Turkish", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "tt" to + PluralLanguage( + tag = "tt", + name = "Tatar", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "ug" to + PluralLanguage( + tag = "ug", + name = "Uyghur", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "uk" to + PluralLanguage( + tag = "uk", + name = "Ukrainian", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + PluralExample( + plural = 2, + sample = 5, + ), + ), + pluralsText = "nplurals = 3; plural = (n % 10 === 1 && n % 100 !== 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2)", + nplurals = 3, + pluralsFunc = { + n -> + if (n % 10 == 1 && n % 100 != 11) { + 0 + } else if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)) { + 1 + } else { + 2 + } + }, + ), + "ur" to + PluralLanguage( + tag = "ur", + name = "Urdu", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "uz" to + PluralLanguage( + tag = "uz", + name = "Uzbek", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "vi" to + PluralLanguage( + tag = "vi", + name = "Vietnamese", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "wa" to + PluralLanguage( + tag = "wa", + name = "Walloon", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n > 1)", + nplurals = 2, + pluralsFunc = { n -> if (n > 1) 0 else 1 }, + ), + "wo" to + PluralLanguage( + tag = "wo", + name = "Wolof", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + "yo" to + PluralLanguage( + tag = "yo", + name = "Yoruba", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + PluralExample( + plural = 1, + sample = 2, + ), + ), + pluralsText = "nplurals = 2; plural = (n !== 1)", + nplurals = 2, + pluralsFunc = { n -> if (n != 1) 0 else 1 }, + ), + "zh" to + PluralLanguage( + tag = "zh", + name = "Chinese", + examples = + listOf( + PluralExample( + plural = 0, + sample = 1, + ), + ), + pluralsText = "nplurals = 1; plural = 0", + nplurals = 1, + pluralsFunc = { n -> 0 }, + ), + ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/data/PluralExample.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/data/PluralExample.kt index c2dbf4dbc6..7274e53447 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/data/PluralExample.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/data/PluralExample.kt @@ -2,5 +2,5 @@ package io.tolgee.service.dataImport.processors.messageFormat.data data class PluralExample( val plural: Int, - val sample: Int + val sample: Int, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/data/PluralLanguage.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/data/PluralLanguage.kt index a8a6715846..942dcc2864 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/data/PluralLanguage.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/messageFormat/data/PluralLanguage.kt @@ -6,5 +6,5 @@ data class PluralLanguage( val examples: List, val nplurals: Int, val pluralsText: String, - val pluralsFunc: (n: Int) -> Int + val pluralsFunc: (n: Int) -> Int, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/PoFileProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/PoFileProcessor.kt index 3257384cc5..77ba674155 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/PoFileProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/PoFileProcessor.kt @@ -13,9 +13,8 @@ import io.tolgee.service.dataImport.processors.po.data.PoParsedTranslation import io.tolgee.service.dataImport.processors.po.data.PoParserResult class PoFileProcessor( - override val context: FileProcessorContext + override val context: FileProcessorContext, ) : ImportFileProcessor() { - lateinit var languageId: String lateinit var parsed: PoParserResult var poParser: PoParser = PoParser(context) @@ -34,8 +33,9 @@ class PoFileProcessor( return@forEachIndexed } if (poTranslation.msgid.isNotBlank()) { - val icuMessage = getToIcuConverter(poTranslation) - .convert(poTranslation.msgstr.toString()) + val icuMessage = + getToIcuConverter(poTranslation) + .convert(poTranslation.msgstr.toString()) context.addTranslation(keyName, languageId, icuMessage, idx) poTranslation.meta.references.forEach { reference -> @@ -62,11 +62,15 @@ class PoFileProcessor( } } - private fun addPlural(poTranslation: PoParsedTranslation, idx: Int) { + private fun addPlural( + poTranslation: PoParsedTranslation, + idx: Int, + ) { val plurals = poTranslation.msgstrPlurals?.map { it.key to it.value.toString() }?.toMap() plurals?.let { - val icuMessage = ToICUConverter(ULocale(languageId), getMessageFormat(poTranslation), context) - .convertPoPlural(plurals) + val icuMessage = + ToICUConverter(ULocale(languageId), getMessageFormat(poTranslation), context) + .convertPoPlural(plurals) context.addTranslation(poTranslation.msgidPlural.toString(), languageId, icuMessage, idx) } } @@ -75,9 +79,7 @@ class PoFileProcessor( return ToICUConverter(ULocale(languageId), getMessageFormat(poTranslation), context) } - private fun getMessageFormat( - poParsedTranslation: PoParsedTranslation, - ): SupportedFormat { + private fun getMessageFormat(poParsedTranslation: PoParsedTranslation): SupportedFormat { poParsedTranslation.meta.flags.forEach { SupportedFormat.findByFlag(it) ?.let { found -> return found } @@ -86,14 +88,16 @@ class PoFileProcessor( } private val detectedFormat by lazy { - val messages = parsed.translations.flatMap { poParsed -> - if (poParsed.msgidPlural.isNotBlank() && !poParsed.msgstrPlurals.isNullOrEmpty()) - poParsed.msgstrPlurals!!.values.asSequence().map { it.toString() } - else - sequence { - yield(poParsed.msgstr.toString()) + val messages = + parsed.translations.flatMap { poParsed -> + if (poParsed.msgidPlural.isNotBlank() && !poParsed.msgstrPlurals.isNullOrEmpty()) { + poParsed.msgstrPlurals!!.values.asSequence().map { it.toString() } + } else { + sequence { + yield(poParsed.msgstr.toString()) + } } - } + } FormatDetector(messages.toList())() } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/PoParser.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/PoParser.kt index 5c111ffabb..b3ee4e08b3 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/PoParser.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/PoParser.kt @@ -10,7 +10,7 @@ import io.tolgee.service.dataImport.processors.po.data.PoParserResult import java.util.* class PoParser( - private val context: FileProcessorContext + private val context: FileProcessorContext, ) { private var expectMsgId = false private var expectMsgStr = false @@ -44,7 +44,7 @@ class PoParser( return PoParserResult( meta = processHeader(), - translations + translations, ) } @@ -232,7 +232,7 @@ class PoParser( isKeyword("msgctxt") -> { context.fileEntity.addIssue( FileIssueType.PO_MSGCTXT_NOT_SUPPORTED, - mapOf(FileIssueParamType.LINE to currentLine.toString()) + mapOf(FileIssueParamType.LINE to currentLine.toString()), ) } current.matches("^msgstr\\[\\d+]$".toRegex()) -> { diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/data/PoParsedTranslation.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/data/PoParsedTranslation.kt index e0fbc5efa6..1e23a9ad4a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/data/PoParsedTranslation.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/data/PoParsedTranslation.kt @@ -8,14 +8,18 @@ class PoParsedTranslation { var meta: PoTranslationMeta = PoTranslationMeta() var raw: StringBuilder = StringBuilder() - fun addToPlurals(variant: Int, value: String) { + fun addToPlurals( + variant: Int, + value: String, + ) { val map = msgstrPlurals ?: mutableMapOf() msgstrPlurals = map - val builder = map[variant] ?: let { - val newBuilder = StringBuilder() - map[variant] = newBuilder - newBuilder - } + val builder = + map[variant] ?: let { + val newBuilder = StringBuilder() + map[variant] = newBuilder + newBuilder + } builder.append(value) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/data/PoParserResult.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/data/PoParserResult.kt index 676a82b645..eb4591eef3 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/data/PoParserResult.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/data/PoParserResult.kt @@ -2,5 +2,5 @@ package io.tolgee.service.dataImport.processors.po.data data class PoParserResult( val meta: PoParserMeta, - val translations: List + val translations: List, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/data/PoTranslationMeta.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/data/PoTranslationMeta.kt index 59d47868cf..dd9b33aeca 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/data/PoTranslationMeta.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/po/data/PoTranslationMeta.kt @@ -9,6 +9,7 @@ class PoTranslationMeta { override fun toString(): String { return """PoTranslationMeta(translatorComments=$translatorComments, - |extractedComments=$extractedComments, reference=$references, flags=$flags)""".trimMargin() + |extractedComments=$extractedComments, reference=$references, flags=$flags) + """.trimMargin() } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/xliff/Xliff12FileProcessor.kt b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/xliff/Xliff12FileProcessor.kt index 5b2b66e9b9..382d5c559a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/xliff/Xliff12FileProcessor.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/dataImport/processors/xliff/Xliff12FileProcessor.kt @@ -14,9 +14,8 @@ import javax.xml.stream.events.StartElement class Xliff12FileProcessor( override val context: FileProcessorContext, - val xmlEventReader: XMLEventReader + val xmlEventReader: XMLEventReader, ) : ImportFileProcessor() { - private val openElements = mutableListOf("xliff") private val currentOpenElement: String? get() = openElements.lastOrNull() @@ -46,12 +45,15 @@ class Xliff12FileProcessor( openElements.add(startElement.name.localPart.lowercase(Locale.getDefault())) when (currentOpenElement) { "file" -> { - fileOriginal = startElement - .getAttributeByName(QName(null, "original"))?.value - sourceLanguage = startElement - .getAttributeByName(QName(null, "source-language"))?.value - targetLanguage = startElement - .getAttributeByName(QName(null, "target-language"))?.value + fileOriginal = + startElement + .getAttributeByName(QName(null, "original"))?.value + sourceLanguage = + startElement + .getAttributeByName(QName(null, "source-language"))?.value + targetLanguage = + startElement + .getAttributeByName(QName(null, "target-language"))?.value } "trans-unit" -> { id = startElement.getAttributeByName(QName(null, "id"))?.value @@ -61,7 +63,7 @@ class Xliff12FileProcessor( if (fileOriginal != null && id == null) { context.fileEntity.addIssue( FileIssueType.ID_ATTRIBUTE_NOT_PROVIDED, - mapOf(FileIssueParamType.FILE_NODE_ORIGINAL to fileOriginal!!) + mapOf(FileIssueParamType.FILE_NODE_ORIGINAL to fileOriginal!!), ) } } @@ -69,12 +71,13 @@ class Xliff12FileProcessor( } } event.isCharacters -> { - if (currentOpenElement != null) + if (currentOpenElement != null) { when (currentOpenElement!!) { in "source", "target", "note" -> { currentTextValue = (currentTextValue ?: "") + event.asCharacters().data } } + } } event.isEndElement -> if (event.isEndElement) { @@ -90,7 +93,7 @@ class Xliff12FileProcessor( if (id != null && !targetProvided) { context.fileEntity.addIssue( FileIssueType.TARGET_NOT_PROVIDED, - mapOf(FileIssueParamType.KEY_NAME to id!!) + mapOf(FileIssueParamType.KEY_NAME to id!!), ) id = null } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/export/ExportService.kt b/backend/data/src/main/kotlin/io/tolgee/service/export/ExportService.kt index 00e7f469e0..da1ed64414 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/export/ExportService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/export/ExportService.kt @@ -19,29 +19,33 @@ class ExportService( private val fileExporterFactory: FileExporterFactory, private val projectService: ProjectService, private val entityManager: EntityManager, - private val businessEventPublisher: BusinessEventPublisher + private val businessEventPublisher: BusinessEventPublisher, ) { - fun export(projectId: Long, exportParams: IExportParams): Map { + fun export( + projectId: Long, + exportParams: IExportParams, + ): Map { val data = getDataForExport(projectId, exportParams) val baseLanguage = getProjectBaseLanguage(projectId) - val baseTranslationsProvider = getBaseTranslationsProvider( - exportParams = exportParams, - projectId = projectId, - baseLanguage = baseLanguage - ) + val baseTranslationsProvider = + getBaseTranslationsProvider( + exportParams = exportParams, + projectId = projectId, + baseLanguage = baseLanguage, + ) return fileExporterFactory.create( data = data, exportParams = exportParams, baseTranslationsProvider = baseTranslationsProvider, - baseLanguage + baseLanguage, ).produceFiles().also { businessEventPublisher.publishOnceInTime( OnBusinessEventToCaptureEvent( eventName = "EXPORT", - projectId = projectId + projectId = projectId, ), - Duration.ofDays(1) + Duration.ofDays(1), ) } } @@ -53,7 +57,7 @@ class ExportService( private fun getBaseTranslationsProvider( exportParams: IExportParams, projectId: Long, - baseLanguage: Language + baseLanguage: Language, ): () -> List { return { getDataForExport(projectId, exportParams, listOf(baseLanguage.tag)) @@ -63,13 +67,13 @@ class ExportService( private fun getDataForExport( projectId: Long, exportParams: IExportParams, - overrideLanguageTags: List? = null + overrideLanguageTags: List? = null, ): List { return ExportDataProvider( entityManager = entityManager, exportParams = exportParams, projectId = projectId, - overrideLanguageTag = overrideLanguageTags + overrideLanguageTag = overrideLanguageTags, ).getData() } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/export/FileExporterFactory.kt b/backend/data/src/main/kotlin/io/tolgee/service/export/FileExporterFactory.kt index 3e2f43dda9..3610681022 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/export/FileExporterFactory.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/export/FileExporterFactory.kt @@ -15,7 +15,7 @@ class FileExporterFactory { data: List, exportParams: IExportParams, baseTranslationsProvider: () -> List, - baseLanguage: Language + baseLanguage: Language, ): FileExporter { return when (exportParams.format) { ExportFormat.JSON -> JsonFileExporter(data, exportParams) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/export/dataProvider/ExportDataProvider.kt b/backend/data/src/main/kotlin/io/tolgee/service/export/dataProvider/ExportDataProvider.kt index 9ffb9ca9d6..0a17fb4336 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/export/dataProvider/ExportDataProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/export/dataProvider/ExportDataProvider.kt @@ -30,7 +30,7 @@ class ExportDataProvider( private val entityManager: EntityManager, private val exportParams: IExportParams, private val projectId: Long, - private val overrideLanguageTag: List? = null + private val overrideLanguageTag: List? = null, ) { private val cb: CriteriaBuilder = entityManager.criteriaBuilder val query: CriteriaQuery = cb.createQuery(ExportDataView::class.java) @@ -147,11 +147,11 @@ class ExportDataProvider( private fun joinTranslation( key: Root, - language: SetJoin + language: SetJoin, ): ListJoin { val translation = key.join(Key_.translations, JoinType.LEFT) translation.on( - cb.equal(language, translation.get(Translation_.language)) + cb.equal(language, translation.get(Translation_.language)), ) return translation } @@ -175,17 +175,19 @@ class ExportDataProvider( private fun transformResult(resultList: MutableList): HashMap { val keyMap = LinkedHashMap() resultList.forEach { dataView -> - val keyView = keyMap.computeIfAbsent(dataView.keyId) { - ExportKeyView(dataView.keyId, dataView.keyName, dataView.namespace) - } - - keyView.translations[dataView.languageTag] = ExportTranslationView( - id = dataView.translationId, - text = dataView.translationText, - state = dataView.translationState ?: TranslationState.UNTRANSLATED, - key = keyView, - languageTag = dataView.languageTag - ) + val keyView = + keyMap.computeIfAbsent(dataView.keyId) { + ExportKeyView(dataView.keyId, dataView.keyName, dataView.namespace) + } + + keyView.translations[dataView.languageTag] = + ExportTranslationView( + id = dataView.translationId, + text = dataView.translationText, + state = dataView.translationState ?: TranslationState.UNTRANSLATED, + key = keyView, + languageTag = dataView.languageTag, + ) } return keyMap } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/export/dataProvider/ExportDataView.kt b/backend/data/src/main/kotlin/io/tolgee/service/export/dataProvider/ExportDataView.kt index 9f405f6b3b..74fb816a92 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/export/dataProvider/ExportDataView.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/export/dataProvider/ExportDataView.kt @@ -10,5 +10,5 @@ data class ExportDataView( val languageTag: String, val translationId: Long?, val translationText: String?, - val translationState: TranslationState? + val translationState: TranslationState?, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/export/dataProvider/ExportKeyView.kt b/backend/data/src/main/kotlin/io/tolgee/service/export/dataProvider/ExportKeyView.kt index f20a893f75..5a3c61692c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/export/dataProvider/ExportKeyView.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/export/dataProvider/ExportKeyView.kt @@ -4,5 +4,5 @@ class ExportKeyView( val id: Long, val name: String, val namespace: String? = null, - val translations: MutableMap = mutableMapOf() + val translations: MutableMap = mutableMapOf(), ) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/export/dataProvider/ExportTranslationView.kt b/backend/data/src/main/kotlin/io/tolgee/service/export/dataProvider/ExportTranslationView.kt index 7f3c2e0246..a260f62e06 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/export/dataProvider/ExportTranslationView.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/export/dataProvider/ExportTranslationView.kt @@ -7,5 +7,5 @@ class ExportTranslationView( val text: String?, val state: TranslationState, val key: ExportKeyView, - val languageTag: String + val languageTag: String, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/export/exporters/JsonFileExporter.kt b/backend/data/src/main/kotlin/io/tolgee/service/export/exporters/JsonFileExporter.kt index 2e6f081826..7073a301c9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/export/exporters/JsonFileExporter.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/export/exporters/JsonFileExporter.kt @@ -9,9 +9,8 @@ import java.io.InputStream class JsonFileExporter( override val translations: List, - override val exportParams: IExportParams + override val exportParams: IExportParams, ) : FileExporter { - override val fileExtension: String = ExportFormat.JSON.extension val result: LinkedHashMap> = LinkedHashMap() @@ -31,9 +30,7 @@ class JsonFileExporter( } } - private fun getFileContentResultMap( - translation: ExportTranslationView - ): LinkedHashMap { + private fun getFileContentResultMap(translation: ExportTranslationView): LinkedHashMap { val absolutePath = translation.getFilePath(translation.key.namespace) return result[absolutePath] ?: let { LinkedHashMap().also { result[absolutePath] = it } @@ -43,14 +40,15 @@ class JsonFileExporter( private fun addToMap( content: LinkedHashMap, pathItems: List, - translation: ExportTranslationView + translation: ExportTranslationView, ) { val pathItemsMutable = pathItems.toMutableList() val pathItem = pathItemsMutable.removeFirst() if (pathItemsMutable.size > 0) { - val map = content[pathItem] ?: LinkedHashMap().also { - content[pathItem] = it - } + val map = + content[pathItem] ?: LinkedHashMap().also { + content[pathItem] = it + } if (map !is Map<*, *>) { handleExistingStringScopeCollision(pathItems, content, translation) @@ -68,7 +66,7 @@ class JsonFileExporter( private fun handleExistingStringScopeCollision( pathItems: List, content: LinkedHashMap, - translation: ExportTranslationView + translation: ExportTranslationView, ) { val delimiter = exportParams.structureDelimiter.toString() val last2joined = pathItems.takeLast(2).joinToString(delimiter) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/export/exporters/XliffFileExporter.kt b/backend/data/src/main/kotlin/io/tolgee/service/export/exporters/XliffFileExporter.kt index e15ca18c96..e5912b5795 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/export/exporters/XliffFileExporter.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/export/exporters/XliffFileExporter.kt @@ -19,7 +19,7 @@ class XliffFileExporter( override val translations: List, override val exportParams: IExportParams, baseTranslationsProvider: () -> List, - val baseLanguage: Language + val baseLanguage: Language, ) : FileExporter { override val fileExtension: String = ExportFormat.XLIFF.extension @@ -51,11 +51,12 @@ class XliffFileExporter( private fun addToFileElement( fileBodyElement: Element, pathItems: List, - translation: ExportTranslationView + translation: ExportTranslationView, ) { - val transUnitElement = fileBodyElement.addElement("trans-unit") - .addAttribute("id", pathItems.joinToString(exportParams.structureDelimiter.toString())) - .addAttribute("datatype", "html") + val transUnitElement = + fileBodyElement.addElement("trans-unit") + .addAttribute("id", pathItems.joinToString(exportParams.structureDelimiter.toString())) + .addAttribute("datatype", "html") baseTranslations[translation.key.name]?.text?.let { transUnitElement.addElement("source").addFromHtmlOrText(it) @@ -77,21 +78,23 @@ class XliffFileExporter( private fun createBaseDocumentStructure(translation: ExportTranslationView): ResultItem { val document = DocumentHelper.createDocument() document.xmlEncoding = "UTF-8" - val fileBodyElement = document.addElement("xliff") - .addNamespace("", "urn:oasis:names:tc:xliff:document:1.2") - .addAttribute("version", "1.2") - .addElement("file", "urn:oasis:names:tc:xliff:document:1.2") - .addAttribute("original", "undefined") - .addAttribute("datatype", "plaintext") - .addAttribute("source-language", baseLanguage.tag) - .addAttribute("target-language", translation.languageTag) - .addElement("body") + val fileBodyElement = + document.addElement("xliff") + .addNamespace("", "urn:oasis:names:tc:xliff:document:1.2") + .addAttribute("version", "1.2") + .addElement("file", "urn:oasis:names:tc:xliff:document:1.2") + .addAttribute("original", "undefined") + .addAttribute("datatype", "plaintext") + .addAttribute("source-language", baseLanguage.tag) + .addAttribute("target-language", translation.languageTag) + .addElement("body") return ResultItem(document, fileBodyElement) } private fun String.parseHtml(): MutableIterator { - val fragment = DocumentHelper - .parseText("$this") + val fragment = + DocumentHelper + .parseText("$this") return fragment.rootElement.nodeIterator() } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/key/KeyMetaService.kt b/backend/data/src/main/kotlin/io/tolgee/service/key/KeyMetaService.kt index 44ddd5b564..2f576c718c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/key/KeyMetaService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/key/KeyMetaService.kt @@ -29,13 +29,15 @@ class KeyMetaService( fun saveAll(entities: Iterable): MutableList = keyMetaRepository.saveAll(entities) - fun saveAllComments(entities: Iterable): MutableList = - keyCommentRepository.saveAll(entities) + fun saveAllComments(entities: Iterable): MutableList = keyCommentRepository.saveAll(entities) fun saveAllCodeReferences(entities: Iterable): MutableList = keyCodeReferenceRepository.saveAll(entities) - fun import(target: KeyMeta, source: KeyMeta) { + fun import( + target: KeyMeta, + source: KeyMeta, + ) { target.comments.import(target, source.comments.toList()) { a, b -> a.text == b.text && a.fromImport == b.fromImport } @@ -47,7 +49,7 @@ class KeyMetaService( private inline fun List.import( target: KeyMeta, source: Collection, - equalsFn: (a: T, b: T) -> Boolean + equalsFn: (a: T, b: T) -> Boolean, ) { source.forEach { otherItem -> if (!this.any { equalsFn(it, otherItem) }) { @@ -58,53 +60,57 @@ class KeyMetaService( @Suppress("UNCHECKED_CAST") fun getWithFetchedData(import: Import): List { - var result: List = entityManager.createQuery( - """ + var result: List = + entityManager.createQuery( + """ select distinct ikm from KeyMeta ikm join fetch ikm.importKey ik left join fetch ikm.comments ikc join ik.file if where if.import = :import - """ - ) - .setParameter("import", import) - .resultList as List + """, + ) + .setParameter("import", import) + .resultList as List - result = entityManager.createQuery( - """ + result = + entityManager.createQuery( + """ select distinct ikm from KeyMeta ikm join ikm.importKey ik left join fetch ikm.codeReferences ikc join ik.file if where ikm in :metas - """ - ).setParameter("metas", result) - .resultList as List + """, + ).setParameter("metas", result) + .resultList as List return result } fun getWithFetchedData(project: Project): List { - var result: List = entityManager.createQuery( - """ + var result: List = + entityManager.createQuery( + """ select distinct ikm from KeyMeta ikm join fetch ikm.key k left join fetch ikm.comments ikc where k.project = :project - """ - ) - .setParameter("project", project) - .resultList as List + """, + ) + .setParameter("project", project) + .resultList as List - result = entityManager.createQuery( - """ + result = + entityManager.createQuery( + """ select distinct ikm from KeyMeta ikm join ikm.key k left join fetch ikm.codeReferences ikc where ikm in :metas - """ - ).setParameter("metas", result) - .resultList as List + """, + ).setParameter("metas", result) + .resultList as List return result } @@ -141,7 +147,7 @@ class KeyMetaService( select id from key where project_id = :projectId ) ) - """ + """, ).setParameter("projectId", projectId) .executeUpdate() @@ -152,7 +158,7 @@ class KeyMetaService( select id from key where project_id = :projectId ) ) - """ + """, ).setParameter("projectId", projectId) .executeUpdate() @@ -161,7 +167,7 @@ class KeyMetaService( delete from key_meta where key_id in ( select id from key where project_id = :projectId ) - """ + """, ).setParameter("projectId", projectId) .executeUpdate() } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/key/KeyService.kt b/backend/data/src/main/kotlin/io/tolgee/service/key/KeyService.kt index a0cf78c451..b797c8c7ca 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/key/KeyService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/key/KeyService.kt @@ -46,7 +46,7 @@ class KeyService( @Lazy private var translationService: TranslationService, private val languageRepository: LanguageRepository, - private val bigMetaService: BigMetaService + private val bigMetaService: BigMetaService, ) : Logging { fun getAll(projectId: Long): Set { return keyRepository.getAllByProjectId(projectId) @@ -56,16 +56,28 @@ class KeyService( return keyRepository.getAllByProjectIdSortedById(projectId) } - fun get(projectId: Long, name: String, namespace: String?): Key { + fun get( + projectId: Long, + name: String, + namespace: String?, + ): Key { return keyRepository.getByNameAndNamespace(projectId, name, namespace) .orElseThrow { NotFoundException(Message.KEY_NOT_FOUND) }!! } - fun find(projectId: Long, name: String, namespace: String?): Key? { + fun find( + projectId: Long, + name: String, + namespace: String?, + ): Key? { return this.findOptional(projectId, name, namespace).orElseGet { null } } - private fun findOptional(projectId: Long, name: String, namespace: String?): Optional { + private fun findOptional( + projectId: Long, + name: String, + namespace: String?, + ): Optional { return keyRepository.getByNameAndNamespace(projectId, name, namespace) } @@ -91,18 +103,23 @@ class KeyService( } @Transactional - fun create(project: Project, dto: CreateKeyDto): Key { + fun create( + project: Project, + dto: CreateKeyDto, + ): Key { val key = create(project, dto.name, dto.namespace) - val created = dto.translations?.let { - if (it.isEmpty()) { - return@let null + val created = + dto.translations?.let { + if (it.isEmpty()) { + return@let null + } + translationService.setForKey(key, it) } - translationService.setForKey(key, it) - } dto.states?.map { - val translation = created?.get(it.key) - ?: throw BadRequestException(Message.CANNOT_SET_STATE_FOR_MISSING_TRANSLATION) + val translation = + created?.get(it.key) + ?: throw BadRequestException(Message.CANNOT_SET_STATE_FOR_MISSING_TRANSLATION) translation to it.value.translationState }?.toMap()?.let { translationService.setStateBatch(it) } @@ -117,7 +134,10 @@ class KeyService( return key } - private fun storeScreenshots(dto: CreateKeyDto, key: Key) { + private fun storeScreenshots( + dto: CreateKeyDto, + key: Key, + ) { @Suppress("DEPRECATION") val screenshotUploadedImageIds = dto.screenshotUploadedImageIds val screenshots = dto.screenshots @@ -138,13 +158,21 @@ class KeyService( } @Transactional - fun create(project: Project, name: String, namespace: String?): Key { + fun create( + project: Project, + name: String, + namespace: String?, + ): Key { checkKeyNotExisting(projectId = project.id, name = name, namespace = namespace) return createWithoutExistenceCheck(project, name, namespace) } @Transactional - fun createWithoutExistenceCheck(project: Project, name: String, namespace: String?): Key { + fun createWithoutExistenceCheck( + project: Project, + name: String, + namespace: String?, + ): Key { val key = Key(name = name, project = project) if (!namespace.isNullOrBlank()) { key.namespace = namespaceService.findOrCreate(namespace, project.id) @@ -153,12 +181,19 @@ class KeyService( } @Transactional - fun edit(keyId: Long, dto: EditKeyDto): Key { + fun edit( + keyId: Long, + dto: EditKeyDto, + ): Key { val key = findOptional(keyId).orElseThrow { NotFoundException() } return edit(key, dto.name, dto.namespace) } - fun edit(key: Key, newName: String, newNamespace: String?): Key { + fun edit( + key: Key, + newName: String, + newNamespace: String?, + ): Key { if (key.name == newName && key.namespace?.name == newNamespace) { return key } @@ -183,27 +218,36 @@ class KeyService( } @Transactional - fun setNamespace(keyIds: List, namespace: String?) { + fun setNamespace( + keyIds: List, + namespace: String?, + ) { val keys = keyRepository.getKeysWithNamespaces(keyIds) val projectId = keys.map { it.project.id }.distinct().singleOrNull() ?: return val namespaceEntity = namespaceService.findOrCreate(namespace, projectId) - val oldNamespaces = keys.map { - val oldNamespace = it.namespace - it.namespace = namespaceEntity - oldNamespace - } + val oldNamespaces = + keys.map { + val oldNamespace = it.namespace + it.namespace = namespaceEntity + oldNamespace + } - val modifiedNamespaces = oldNamespaces - .filter { it?.name != namespace } - .filterNotNull() - .distinctBy { it.id } + val modifiedNamespaces = + oldNamespaces + .filter { it?.name != namespace } + .filterNotNull() + .distinctBy { it.id } namespaceService.deleteIfUnused(modifiedNamespaces) keyRepository.saveAll(keys) } - fun checkKeyNotExisting(projectId: Long, name: String, namespace: String?) { + fun checkKeyNotExisting( + projectId: Long, + name: String, + namespace: String?, + ) { if (findOptional(projectId, name, namespace).isPresent) { throw ValidationException(Message.KEY_EXISTS) } @@ -233,9 +277,10 @@ class KeyService( screenshotService.deleteAllByKeyId(ids) } - val keys = traceLogMeasureTime("delete multiple keys: fetch keys") { - keyRepository.findAllByIdInForDelete(ids) - } + val keys = + traceLogMeasureTime("delete multiple keys: fetch keys") { + keyRepository.findAllByIdInForDelete(ids) + } val namespaces = keys.map { it.namespace } @@ -258,7 +303,10 @@ class KeyService( namespaceService.deleteAllByProject(projectId) } - fun checkInProject(key: Key, projectId: Long) { + fun checkInProject( + key: Key, + projectId: Long, + ) { if (key.project.id != projectId) { throw BadRequestException(Message.KEY_NOT_FROM_PROJECT) } @@ -267,7 +315,10 @@ class KeyService( fun saveAll(entities: Collection): MutableList = entities.map { save(it) }.toMutableList() @Transactional - fun importKeys(keys: List, project: Project) { + fun importKeys( + keys: List, + project: Project, + ) { KeysImporter(applicationContext, keys, project).import() } @@ -276,29 +327,41 @@ class KeyService( search: String, languageTag: String?, project: ProjectDto, - pageable: Pageable + pageable: Pageable, ): Page { entityManager.setSimilarityLimit(0.00001) return keyRepository.searchKeys(search, project.id, languageTag, pageable) } @Transactional - fun importKeysResolvable(keys: List, projectEntity: Project): KeyImportResolvableResult { - val importer = ResolvingKeyImporter( - applicationContext = applicationContext, - keysToImport = keys, - projectEntity = projectEntity - ) + fun importKeysResolvable( + keys: List, + projectEntity: Project, + ): KeyImportResolvableResult { + val importer = + ResolvingKeyImporter( + applicationContext = applicationContext, + keysToImport = keys, + projectEntity = projectEntity, + ) return importer() } @Suppress("UNCHECKED_CAST") - fun getKeysInfo(dto: GetKeysRequestDto, projectId: Long): List>> { + fun getKeysInfo( + dto: GetKeysRequestDto, + projectId: Long, + ): List>> { return KeyInfoProvider(applicationContext, projectId, dto).get() } - fun getPaged(projectId: Long, pageable: Pageable): Page = keyRepository.getAllByProjectId(projectId, pageable) + fun getPaged( + projectId: Long, + pageable: Pageable, + ): Page = keyRepository.getAllByProjectId(projectId, pageable) + fun getKeysWithTags(keys: Set): List = keyRepository.getWithTags(keys) + fun getKeysWithTagsById(keysIds: Iterable): Set = keyRepository.getWithTagsByIds(keysIds) fun find(id: List): List { @@ -306,18 +369,29 @@ class KeyService( } @Transactional - fun getDisabledLanguages(projectId: Long, keyId: Long): List { + fun getDisabledLanguages( + projectId: Long, + keyId: Long, + ): List { return keyRepository.getDisabledLanguages(projectId, keyId) } @Transactional - fun setDisabledLanguages(projectId: Long, keyId: Long, languageIds: List): List { + fun setDisabledLanguages( + projectId: Long, + keyId: Long, + languageIds: List, + ): List { val key = keyRepository.findByProjectIdAndId(projectId, keyId) ?: throw NotFoundException() enableRestOfLanguages(projectId, languageIds, key) return disableLanguages(projectId, languageIds, key) } - private fun enableRestOfLanguages(projectId: Long, languageIdsToDisable: List, key: Key) { + private fun enableRestOfLanguages( + projectId: Long, + languageIdsToDisable: List, + key: Key, + ) { val currentlyDisabledLanguages = keyRepository.getDisabledLanguages(projectId, key.id) val languagesToEnable = currentlyDisabledLanguages.filter { !languageIdsToDisable.contains(it.id) } languagesToEnable.forEach { language -> @@ -330,7 +404,7 @@ class KeyService( private fun disableLanguages( projectId: Long, languageIds: List, - key: Key + key: Key, ): List { val languages = languageRepository.findAllByProjectIdAndIdInOrderById(projectId, languageIds) languages.map { language -> diff --git a/backend/data/src/main/kotlin/io/tolgee/service/key/KeyWithBaseTranslationView.kt b/backend/data/src/main/kotlin/io/tolgee/service/key/KeyWithBaseTranslationView.kt index dc2d15bacc..e5f4e35fe4 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/key/KeyWithBaseTranslationView.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/key/KeyWithBaseTranslationView.kt @@ -1,4 +1,5 @@ package io.tolgee.service.key + interface KeyWithBaseTranslationView { val id: Long val name: String diff --git a/backend/data/src/main/kotlin/io/tolgee/service/key/NamespaceService.kt b/backend/data/src/main/kotlin/io/tolgee/service/key/NamespaceService.kt index dd4aedc8a1..fc624df2cc 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/key/NamespaceService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/key/NamespaceService.kt @@ -30,9 +30,10 @@ class NamespaceService( fun deleteUnusedNamespaces(namespaces: List) { val namespaceIds = namespaces.mapNotNull { it?.id }.toSet() - val counts = namespaceRepository - .getKeysInNamespaceCount(namespaceIds) - .associate { it[0] to it[1] } + val counts = + namespaceRepository + .getKeysInNamespaceCount(namespaceIds) + .associate { it[0] to it[1] } namespaceIds.forEach { if (counts[it] == 0L || counts[it] == null) { @@ -67,33 +68,43 @@ class NamespaceService( namespaceRepository.save(namespace) } - fun find(name: String?, projectId: Long): Namespace? { + fun find( + name: String?, + projectId: Long, + ): Namespace? { name ?: return null return namespaceRepository.findByNameAndProjectId(name, projectId) } - fun findOrCreate(name: String?, projectId: Long): Namespace? { + fun findOrCreate( + name: String?, + projectId: Long, + ): Namespace? { return tryUntilItDoesntBreakConstraint { find(getSafeNamespace(name), projectId) ?: create(name, projectId) } } - fun create(name: String?, projectId: Long): Namespace? { + fun create( + name: String?, + projectId: Long, + ): Namespace? { if (name.isNullOrBlank()) { return null } return Namespace( name = name, - project = entityManager.getReference(Project::class.java, projectId) + project = entityManager.getReference(Project::class.java, projectId), ).apply { namespaceRepository.save(this) } } fun getAllInProject(projectId: Long) = namespaceRepository.getAllByProjectId(projectId) + fun getAllInProject( projectId: Long, - pageable: Pageable + pageable: Pageable, ) = namespaceRepository.getAllByProjectId(projectId, pageable) fun saveAll(entities: Collection) { @@ -104,23 +115,38 @@ class NamespaceService( return namespaceRepository.isDefaultUsed(projectId) } - fun get(projectId: Long, namespaceId: Long): Namespace { + fun get( + projectId: Long, + namespaceId: Long, + ): Namespace { return this.find(projectId, namespaceId) ?: throw NotFoundException(Message.NAMESPACE_NOT_FOUND) } - fun get(projectId: Long, name: String): Namespace { + fun get( + projectId: Long, + name: String, + ): Namespace { return this.find(projectId, name) ?: throw NotFoundException(Message.NAMESPACE_NOT_FOUND) } - fun find(projectId: Long, name: String): Namespace? { + fun find( + projectId: Long, + name: String, + ): Namespace? { return namespaceRepository.findOneByProjectIdAndName(projectId, name) } - fun find(projectId: Long, namespaceId: Long): Namespace? { + fun find( + projectId: Long, + namespaceId: Long, + ): Namespace? { return namespaceRepository.findOneByProjectIdAndId(projectId, namespaceId) } - fun update(namespace: Namespace, dto: UpdateNamespaceDto) { + fun update( + namespace: Namespace, + dto: UpdateNamespaceDto, + ) { this.find(dto.name, namespace.project.id)?.let { throw BadRequestException(Message.NAMESPACE_EXISTS) } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/key/ResolvingKeyImporter.kt b/backend/data/src/main/kotlin/io/tolgee/service/key/ResolvingKeyImporter.kt index 411711306b..92f06a9a3a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/key/ResolvingKeyImporter.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/key/ResolvingKeyImporter.kt @@ -36,7 +36,7 @@ import java.io.Serializable class ResolvingKeyImporter( val applicationContext: ApplicationContext, val keysToImport: List, - val projectEntity: Project + val projectEntity: Project, ) { private val entityManager = applicationContext.getBean(EntityManager::class.java) private val keyService = applicationContext.getBean(KeyService::class.java) @@ -81,10 +81,11 @@ class ResolvingKeyImporter( } if (isNew) { - val translation = Translation(resolvable.text).apply { - this.key = key - this.language = language - } + val translation = + Translation(resolvable.text).apply { + this.key = key + this.language = language + } translationService.save(translation) } } @@ -93,31 +94,35 @@ class ResolvingKeyImporter( } private fun importScreenshots(): Map { - val uploadedImagesIds = keysToImport.flatMap { - it.screenshots?.map { screenshot -> screenshot.uploadedImageId } ?: listOf() - } + val uploadedImagesIds = + keysToImport.flatMap { + it.screenshots?.map { screenshot -> screenshot.uploadedImageId } ?: listOf() + } val images = imageUploadService.find(uploadedImagesIds) checkImageUploadermissions(images) - val createdScreenshots = images.associate { - it.id to screenshotService.saveScreenshot(it) - } + val createdScreenshots = + images.associate { + it.id to screenshotService.saveScreenshot(it) + } val locations = images.map { it.location } - val allReferences = screenshotService.getKeyScreenshotReferences( - importedKeys, - locations - ).toMutableList() + val allReferences = + screenshotService.getKeyScreenshotReferences( + importedKeys, + locations, + ).toMutableList() val referencesToDelete = mutableListOf() keysToImport.forEach { val key = getOrCreateKey(it) it.screenshots?.forEach { screenshot -> - val screenshotResult = createdScreenshots[screenshot.uploadedImageId] - ?: throw NotFoundException(Message.ONE_OR_MORE_IMAGES_NOT_FOUND) + val screenshotResult = + createdScreenshots[screenshot.uploadedImageId] + ?: throw NotFoundException(Message.ONE_OR_MORE_IMAGES_NOT_FOUND) val info = ScreenshotInfoDto(screenshot.text, screenshot.positions) screenshotService.addReference( @@ -125,13 +130,14 @@ class ResolvingKeyImporter( screenshot = screenshotResult.screenshot, info = info, originalDimension = screenshotResult.originalDimension, - targetDimension = screenshotResult.targetDimension + targetDimension = screenshotResult.targetDimension, ) - val toDelete = allReferences.filter { reference -> - reference.key.id == key.id && - reference.screenshot.location == screenshotResult.screenshot.location - } + val toDelete = + allReferences.filter { reference -> + reference.key.id == key.id && + reference.screenshot.location == screenshotResult.screenshot.location + } referencesToDelete.addAll(toDelete) } @@ -175,18 +181,18 @@ class ResolvingKeyImporter( translationExists: Boolean, resolvable: ImportTranslationResolvableDto, key: Key, - language: Language + language: Language, ): Boolean { if (translationExists && resolvable.resolution == ImportTranslationResolution.NEW) { errors.add( - listOf(Message.TRANSLATION_EXISTS.code, key.namespace?.name, key.name, language.tag) + listOf(Message.TRANSLATION_EXISTS.code, key.namespace?.name, key.name, language.tag), ) return true } if (!translationExists && resolvable.resolution != ImportTranslationResolution.NEW) { errors.add( - listOf(Message.TRANSLATION_NOT_FOUND.code, key.namespace?.name, key.name, language.tag) + listOf(Message.TRANSLATION_NOT_FOUND.code, key.namespace?.name, key.name, language.tag), ) return true } @@ -195,7 +201,7 @@ class ResolvingKeyImporter( private fun getExistingTranslation( key: Key, - language: Language + language: Language, ) = existingTranslations[key.namespace?.name to key.name]?.get(language.tag) private fun ImportKeysResolvableItemDto.mapLanguageAsKey() = @@ -210,11 +216,14 @@ class ResolvingKeyImporter( keyService.createWithoutExistenceCheck( name = keyToImport.name, namespace = keyToImport.namespace, - project = projectEntity + project = projectEntity, ) } - private fun getAllByNamespaceAndName(projectId: Long, keys: List>): List { + private fun getAllByNamespaceAndName( + projectId: Long, + keys: List>, + ): List { val cb = entityManager.criteriaBuilder val query = cb.createQuery(Key::class.java) val root = query.from(Key::class.java) @@ -222,12 +231,13 @@ class ResolvingKeyImporter( @Suppress("UNCHECKED_CAST") val namespaceJoin: Join = root.fetch(Key_.namespace, JoinType.LEFT) as Join - val predicates = keys.map { (namespace, name) -> - cb.and( - cb.equal(root.get(Key_.name), name), - cb.equalNullable(namespaceJoin.get(Namespace_.name), namespace) - ) - }.toTypedArray() + val predicates = + keys.map { (namespace, name) -> + cb.and( + cb.equal(root.get(Key_.name), name), + cb.equalNullable(namespaceJoin.get(Namespace_.name), namespace), + ) + }.toTypedArray() val projectIdPath = root.get(Key_.project).get(Project_.id) @@ -239,7 +249,7 @@ class ResolvingKeyImporter( private val existingKeys by lazy { this.getAllByNamespaceAndName( projectId = projectEntity.id, - keys = keysToImport.map { it.namespace to it.name } + keys = keysToImport.map { it.namespace to it.name }, ).associateBy { (it.namespace?.name to it.name) }.toMutableMap() } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/key/ScreenshotService.kt b/backend/data/src/main/kotlin/io/tolgee/service/key/ScreenshotService.kt index 1bb266d045..33a57597d8 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/key/ScreenshotService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/key/ScreenshotService.kt @@ -38,18 +38,22 @@ class ScreenshotService( private val imageUploadService: ImageUploadService, private val authenticationFacade: AuthenticationFacade, private val entityManager: EntityManager, - private val keyScreenshotReferenceRepository: KeyScreenshotReferenceRepository + private val keyScreenshotReferenceRepository: KeyScreenshotReferenceRepository, ) { companion object { const val SCREENSHOTS_STORAGE_FOLDER_NAME = "screenshots" } @Transactional - fun store(screenshotImage: InputStreamSource, key: Key, info: ScreenshotInfoDto?): Screenshot { + fun store( + screenshotImage: InputStreamSource, + key: Key, + info: ScreenshotInfoDto?, + ): Screenshot { if (getScreenshotsCountForKey(key) >= tolgeeProperties.maxScreenshotsPerKey) { throw BadRequestException( io.tolgee.constants.Message.MAX_SCREENSHOTS_EXCEEDED, - listOf(tolgeeProperties.maxScreenshotsPerKey) + listOf(tolgeeProperties.maxScreenshotsPerKey), ) } @@ -57,19 +61,20 @@ class ScreenshotService( val image = converter.getImage() val thumbnail = converter.getThumbnail() - val screenshot = saveScreenshot( - image.toByteArray(), - thumbnail.toByteArray(), - info?.location, - converter.targetDimension - ) + val screenshot = + saveScreenshot( + image.toByteArray(), + thumbnail.toByteArray(), + info?.location, + converter.targetDimension, + ) return addReference( key = key, screenshot = screenshot, info = info, originalDimension = converter.originalDimension, - targetDimension = converter.targetDimension + targetDimension = converter.targetDimension, ) } @@ -78,7 +83,7 @@ class ScreenshotService( screenshot: Screenshot, info: ScreenshotInfoDto?, originalDimension: Dimension?, - targetDimension: Dimension? + targetDimension: Dimension?, ): Screenshot { val reference = KeyScreenshotReference() reference.key = key @@ -93,15 +98,17 @@ class ScreenshotService( private fun KeyScreenshotReference.setInfo( info: ScreenshotInfoDto?, originalDimension: Dimension?, - newDimension: Dimension? + newDimension: Dimension?, ) { info?.let { this.originalText = info.text it.positions?.forEach { positionDto -> - val xRatio = newDimension?.width?.toDouble() - ?.div(originalDimension?.width?.toDouble() ?: 1.0) ?: 1.0 - val yRatio = newDimension?.height?.toDouble() - ?.div(originalDimension?.height?.toDouble() ?: 1.0) ?: 1.0 + val xRatio = + newDimension?.width?.toDouble() + ?.div(originalDimension?.width?.toDouble() ?: 1.0) ?: 1.0 + val yRatio = + newDimension?.height?.toDouble() + ?.div(originalDimension?.height?.toDouble() ?: 1.0) ?: 1.0 positions = positions ?: mutableListOf() positions!!.add( KeyInScreenshotPosition( @@ -109,7 +116,7 @@ class ScreenshotService( positionDto.y.adjustByRation(yRatio), positionDto.width.adjustByRation(xRatio), positionDto.height.adjustByRation(yRatio), - ) + ), ) } } @@ -120,30 +127,39 @@ class ScreenshotService( } @Transactional - fun saveUploadedImages(uploadedImageIds: Collection, key: Key): Map { - val screenshots = uploadedImageIds.map { - KeyScreenshotDto().apply { uploadedImageId = it } - } + fun saveUploadedImages( + uploadedImageIds: Collection, + key: Key, + ): Map { + val screenshots = + uploadedImageIds.map { + KeyScreenshotDto().apply { uploadedImageId = it } + } return saveUploadedImages(screenshots, key) } /** * @return Map of uploaded image id and screenshot */ - fun saveUploadedImages(screenshots: List, key: Key): Map { + fun saveUploadedImages( + screenshots: List, + key: Key, + ): Map { val imageIds = screenshots.map { it.uploadedImageId } val images = imageUploadService.find(imageIds).associateBy { it.id } return screenshots.map { screenshotInfo -> - val image = images[screenshotInfo.uploadedImageId] - ?: throw NotFoundException(io.tolgee.constants.Message.ONE_OR_MORE_IMAGES_NOT_FOUND) + val image = + images[screenshotInfo.uploadedImageId] + ?: throw NotFoundException(io.tolgee.constants.Message.ONE_OR_MORE_IMAGES_NOT_FOUND) if (authenticationFacade.authenticatedUser.id != image.userAccount.id) { throw PermissionException() } - val info = screenshotInfo.let { - ScreenshotInfoDto(it.text, it.positions) - } + val info = + screenshotInfo.let { + ScreenshotInfoDto(it.text, it.positions) + } val (screenshot, originalDimension, targetDimension) = saveScreenshot(image) @@ -157,20 +173,22 @@ class ScreenshotService( * Creates and saves screenshot entity and the corresponding file */ fun saveScreenshot(image: UploadedImage): CreateScreenshotResult { - val img = fileStorage - .readFile( - UPLOADED_IMAGES_STORAGE_FOLDER_NAME + "/" + image.filenameWithExtension - ) - val thumbnail = fileStorage - .readFile( - UPLOADED_IMAGES_STORAGE_FOLDER_NAME + "/" + image.thumbnailFilenameWithExtension - ) + val img = + fileStorage + .readFile( + UPLOADED_IMAGES_STORAGE_FOLDER_NAME + "/" + image.filenameWithExtension, + ) + val thumbnail = + fileStorage + .readFile( + UPLOADED_IMAGES_STORAGE_FOLDER_NAME + "/" + image.thumbnailFilenameWithExtension, + ) val screenshot = saveScreenshot(img, thumbnail, image.location, Dimension(image.width, image.height)) imageUploadService.delete(image) return CreateScreenshotResult( screenshot = screenshot, originalDimension = Dimension(image.originalWidth, image.originalHeight), - targetDimension = Dimension(image.width, image.height) + targetDimension = Dimension(image.width, image.height), ) } @@ -181,7 +199,7 @@ class ScreenshotService( image: ByteArray, thumbnail: ByteArray, location: String?, - dimension: Dimension + dimension: Dimension, ): Screenshot { val screenshot = Screenshot() screenshot.extension = "png" @@ -193,7 +211,11 @@ class ScreenshotService( return screenshot } - fun storeFiles(screenshot: Screenshot, image: ByteArray?, thumbnail: ByteArray?) { + fun storeFiles( + screenshot: Screenshot, + image: ByteArray?, + thumbnail: ByteArray?, + ) { thumbnail?.let { fileStorage.storeFile(screenshot.getThumbnailPath(), it) } image?.let { fileStorage.storeFile(screenshot.getFilePath(), it) } } @@ -216,23 +238,33 @@ class ScreenshotService( deleteFile(screenshot) } - fun removeScreenshotReference(key: Key, screenshot: Screenshot) { + fun removeScreenshotReference( + key: Key, + screenshot: Screenshot, + ) { removeScreenshotReferences(key, listOf(screenshot)) } @Transactional - fun removeScreenshotReferences(key: Key, screenshots: List) { + fun removeScreenshotReferences( + key: Key, + screenshots: List, + ) { removeScreenshotReferencesById(key, screenshots.map { it.id }) } @Transactional - fun removeScreenshotReferencesById(key: Key, screenshotIds: List?) { + fun removeScreenshotReferencesById( + key: Key, + screenshotIds: List?, + ) { screenshotIds ?: return val references = keyScreenshotReferenceRepository.findAll(key, screenshotIds) keyScreenshotReferenceRepository.deleteAll(references) - val screenshotReferences = keyScreenshotReferenceRepository - .findAll(screenshotIds) - .groupBy { it.screenshot.id } + val screenshotReferences = + keyScreenshotReferenceRepository + .findAll(screenshotIds) + .groupBy { it.screenshot.id } screenshotIds.forEach { if (screenshotReferences[it] == null) { delete(it) @@ -244,9 +276,10 @@ class ScreenshotService( fun removeScreenshotReferences(references: List) { val screenshotIds = references.map { it.screenshot.id }.toSet() keyScreenshotReferenceRepository.deleteAll(references) - val screenshotReferences = keyScreenshotReferenceRepository - .findAll(screenshotIds) - .groupBy { it.screenshot.id } + val screenshotReferences = + keyScreenshotReferenceRepository + .findAll(screenshotIds) + .groupBy { it.screenshot.id } screenshotIds.forEach { if (screenshotReferences[it].isNullOrEmpty()) { delete(it) @@ -275,7 +308,7 @@ class ScreenshotService( DELETE FROM key_screenshot_reference WHERE key_id IN ( SELECT id FROM key WHERE project_id = :projectId ) - """ + """, ).setParameter("projectId", projectId) .executeUpdate() @@ -286,7 +319,7 @@ class ScreenshotService( SELECT id FROM key WHERE project_id = :projectId ) ) - """ + """, ).setParameter("projectId", projectId) .executeUpdate() } @@ -333,7 +366,10 @@ class ScreenshotService( .associate { it.id to it.keyScreenshotReferences.map { it.screenshot }.toSet().toList() } } - fun getKeyScreenshotReferences(importedKeys: List, locations: List): List { + fun getKeyScreenshotReferences( + importedKeys: List, + locations: List, + ): List { return screenshotRepository.getKeyScreenshotReferences(importedKeys, locations) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/key/TagService.kt b/backend/data/src/main/kotlin/io/tolgee/service/key/TagService.kt index f4597d9d3d..d46442d618 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/key/TagService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/key/TagService.kt @@ -22,24 +22,28 @@ class TagService( private val keyMetaService: KeyMetaService, @Lazy private val keyService: KeyService, - private val entityManager: EntityManager + private val entityManager: EntityManager, ) : Logging { - fun tagKey(key: Key, tagName: String): Tag { + fun tagKey( + key: Key, + tagName: String, + ): Tag { val keyMeta = keyMetaService.getOrCreateForKey(key) - val tag = find(key.project, tagName)?.let { - if (!keyMeta.tags.contains(it)) { - it.keyMetas.add(keyMeta) - keyMeta.tags.add(it) - } - it - } ?: let { - Tag().apply { - project = key.project - keyMetas.add(keyMeta) - name = tagName - keyMeta.tags.add(this) + val tag = + find(key.project, tagName)?.let { + if (!keyMeta.tags.contains(it)) { + it.keyMetas.add(keyMeta) + keyMeta.tags.add(it) + } + it + } ?: let { + Tag().apply { + project = key.project + keyMetas.add(keyMeta) + name = tagName + keyMeta.tags.add(this) + } } - } if (tag.name.length > 100) { throw BadRequestException(io.tolgee.constants.Message.TAG_TOO_LOG) @@ -74,7 +78,10 @@ class TagService( tagKeys(keysWithTags, map) } - private fun tagKeys(keysWithFetchedTags: Iterable, map: Map>) { + private fun tagKeys( + keysWithFetchedTags: Iterable, + map: Map>, + ) { val keysByIdMap = keysWithFetchedTags.associateBy { it.id } val projectId = getSingleProjectId(keysByIdMap) @@ -85,21 +92,22 @@ class TagService( tagsToAdd.forEach { tagToAdd -> val keyWithData = keysByIdMap[keyId] ?: throw NotFoundException(Message.KEY_NOT_FOUND) val keyMeta = keyMetaService.getOrCreateForKey(keyWithData) - val tag = existingTags[tagToAdd]?.let { - if (!keyMeta.tags.contains(it)) { - it.keyMetas.add(keyMeta) - keyMeta.tags.add(it) - } - it - } ?: let { - Tag().apply { - project = keysByIdMap[keyId]?.project ?: throw NotFoundException(Message.KEY_NOT_FOUND) - keyMetas.add(keyMeta) - name = tagToAdd - keyMeta.tags.add(this) - existingTags[tagToAdd] = this + val tag = + existingTags[tagToAdd]?.let { + if (!keyMeta.tags.contains(it)) { + it.keyMetas.add(keyMeta) + keyMeta.tags.add(it) + } + it + } ?: let { + Tag().apply { + project = keysByIdMap[keyId]?.project ?: throw NotFoundException(Message.KEY_NOT_FOUND) + keyMetas.add(keyMeta) + name = tagToAdd + keyMeta.tags.add(this) + existingTags[tagToAdd] = this + } } - } tagRepository.save(tag) keyMetaService.save(keyMeta) } @@ -115,7 +123,10 @@ class TagService( untagKeys(keysWithTags, map) } - private fun untagKeys(keysWithFetchedTags: Iterable, map: Map>) { + private fun untagKeys( + keysWithFetchedTags: Iterable, + map: Map>, + ) { val keysByIdMap = keysWithFetchedTags.associateBy { it.id } map.forEach { (keyId, tagsToRemove) -> @@ -148,11 +159,17 @@ class TagService( return projectIds.single() } - private fun getFromProject(projectId: Long, tags: Collection): List { + private fun getFromProject( + projectId: Long, + tags: Collection, + ): List { return tagRepository.findAllByProject(projectId, tags) } - fun remove(key: Key, tag: Tag) { + fun remove( + key: Key, + tag: Tag, + ) { key.keyMeta?.let { keyMeta -> tag.keyMetas.remove(keyMeta) keyMeta.tags.remove(tag) @@ -165,7 +182,10 @@ class TagService( } @Transactional - fun updateTags(key: Key, newTags: List) { + fun updateTags( + key: Key, + newTags: List, + ) { key.keyMeta?.tags?.forEach { oldTag -> if (newTags.find { oldTag.name == it } == null) { this.remove(key, oldTag) @@ -176,7 +196,11 @@ class TagService( } } - fun getProjectTags(projectId: Long, search: String? = null, pageable: Pageable): Page { + fun getProjectTags( + projectId: Long, + search: String? = null, + pageable: Pageable, + ): Page { return tagRepository.findAllByProject(projectId, search, pageable) } @@ -201,7 +225,10 @@ class TagService( return tagRepository.findAllByProjectId(projectId) } - fun find(project: Project, tagName: String): Tag? { + fun find( + project: Project, + tagName: String, + ): Tag? { return tagRepository.findByProjectAndName(project, tagName) } @@ -211,9 +238,10 @@ class TagService( } fun deleteAllByKeyIdIn(keyIds: Collection) { - val keys = traceLogMeasureTime("tagService: deleteAllByKeyIdIn: getKeysWithTags") { - tagRepository.getKeysWithTags(keyIds) - } + val keys = + traceLogMeasureTime("tagService: deleteAllByKeyIdIn: getKeysWithTags") { + tagRepository.getKeysWithTags(keyIds) + } deleteAllTagsForKeys(keys) } @@ -251,12 +279,12 @@ class TagService( """ delete from key_meta_tags kmt where kmt.key_metas_id in - (select km.id from key_meta km join key k on km.key_id = k.id where k.project_id = :projectId)""" + (select km.id from key_meta km join key k on km.key_id = k.id where k.project_id = :projectId)""", ).setParameter("projectId", projectId).executeUpdate() entityManager.createNativeQuery( """ delete from tag where project_id = :projectId - """ + """, ).setParameter("projectId", projectId).executeUpdate() } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/key/utils/KeyInfoProvider.kt b/backend/data/src/main/kotlin/io/tolgee/service/key/utils/KeyInfoProvider.kt index 077e3e4c14..629ab45c68 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/key/utils/KeyInfoProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/key/utils/KeyInfoProvider.kt @@ -20,7 +20,7 @@ import org.springframework.context.ApplicationContext class KeyInfoProvider( applicationContext: ApplicationContext, val projectId: Long, - val dto: GetKeysRequestDto + val dto: GetKeysRequestDto, ) { private val entityManager: EntityManager = applicationContext.getBean(EntityManager::class.java) private val screenshotService: ScreenshotService = applicationContext.getBean(ScreenshotService::class.java) @@ -35,12 +35,13 @@ class KeyInfoProvider( val namespace = root.fetch(Key_.namespace, JoinType.LEFT) as Join val keyMeta = root.fetch(Key_.keyMeta, JoinType.LEFT) keyMeta.fetch(KeyMeta_.tags, JoinType.LEFT) - val predicates = dto.keys.map { key -> - cb.and( - cb.equal(root.get(Key_.name), key.name), - cb.equalNullable(namespace.get(Namespace_.name), key.namespace) - ) - } + val predicates = + dto.keys.map { key -> + cb.and( + cb.equal(root.get(Key_.name), key.name), + cb.equalNullable(namespace.get(Namespace_.name), key.namespace), + ) + } val keyPredicates = cb.or(*predicates.toTypedArray()) @@ -50,8 +51,9 @@ class KeyInfoProvider( val result = entityManager.createQuery(query).resultList val screenshots = screenshotService.getScreenshotsForKeys(result.map { it.id }) - val translations = translationService.getForKeys(result.map { it.id }, dto.languageTags) - .groupBy { it.key.id } + val translations = + translationService.getForKeys(result.map { it.id }, dto.languageTags) + .groupBy { it.key.id } result.map { it.translations = translations[it.id]?.toMutableList() ?: mutableListOf() diff --git a/backend/data/src/main/kotlin/io/tolgee/service/key/utils/KeysImporter.kt b/backend/data/src/main/kotlin/io/tolgee/service/key/utils/KeysImporter.kt index af3ce7bc8e..bcab87d94e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/key/utils/KeysImporter.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/key/utils/KeysImporter.kt @@ -16,7 +16,7 @@ import org.springframework.context.ApplicationContext class KeysImporter( applicationContext: ApplicationContext, val keys: List, - val project: Project + val project: Project, ) { private val translationService: TranslationService = applicationContext.getBean(TranslationService::class.java) private val keyService: KeyService = applicationContext.getBean(KeyService::class.java) @@ -26,9 +26,10 @@ class KeysImporter( private val securityService: SecurityService = applicationContext.getBean(SecurityService::class.java) fun import() { - val existing = keyService.getAll(project.id) - .associateBy { ((it.namespace?.name to it.name)) } - .toMutableMap() + val existing = + keyService.getAll(project.id) + .associateBy { ((it.namespace?.name to it.name)) } + .toMutableMap() val namespaces = mutableMapOf() namespaceService.getAllInProject(project.id).associateByTo(namespaces) { it.name } val languageTags = keys.flatMap { it.translations.keys }.toSet() @@ -41,18 +42,19 @@ class KeysImporter( keys.forEach { keyDto -> val safeNamespace = getSafeNamespace(keyDto.namespace) if (!existing.containsKey(safeNamespace to keyDto.name)) { - val key = Key( - name = keyDto.name, - project = project - ).apply { - if (safeNamespace != null && !namespaces.containsKey(safeNamespace)) { - val ns = namespaceService.create(safeNamespace, project.id) - if (ns != null) { - namespaces[safeNamespace] = ns + val key = + Key( + name = keyDto.name, + project = project, + ).apply { + if (safeNamespace != null && !namespaces.containsKey(safeNamespace)) { + val ns = namespaceService.create(safeNamespace, project.id) + if (ns != null) { + namespaces[safeNamespace] = ns + } } + this.namespace = namespaces[safeNamespace] } - this.namespace = namespaces[safeNamespace] - } keyService.save(key) keyDto.translations.entries.forEach { (languageTag, value) -> languages[languageTag]?.let { language -> diff --git a/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MetaMapper.kt b/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MetaMapper.kt index 5d8ace982b..be38747c8f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MetaMapper.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MetaMapper.kt @@ -5,7 +5,6 @@ import com.fasterxml.jackson.core.type.TypeReference import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper class MetaMapper { - fun getMeta(data: String): List? { val mapper = jacksonObjectMapper() val typeRef = object : TypeReference>() {} @@ -16,7 +15,7 @@ class MetaMapper { @JsonIgnoreProperties(ignoreUnknown = true) class MetaKey( val keyName: String, - val namespace: String? + val namespace: String?, ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtCreditBucketService.kt b/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtCreditBucketService.kt index d3d6d5a517..3dd38e22b8 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtCreditBucketService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtCreditBucketService.kt @@ -34,7 +34,10 @@ class MtCreditBucketService( private val lockingProvider: LockingProvider, private val transactionManager: PlatformTransactionManager, ) : Logging { - fun consumeCredits(project: Project, amount: Int): MtCreditBucket { + fun consumeCredits( + project: Project, + amount: Int, + ): MtCreditBucket { return lockingProvider.withLocking(getMtCreditBucketLockName(project)) { tryUntilItDoesntBreakConstraint { executeInNewTransaction(transactionManager) { @@ -48,7 +51,10 @@ class MtCreditBucketService( private fun getMtCreditBucketLockName(project: Project) = "mt-credit-lock-${project.organizationOwner.id}" - private fun consumeCredits(bucket: MtCreditBucket, amount: Int) { + private fun consumeCredits( + bucket: MtCreditBucket, + amount: Int, + ) { refillIfItsTime(bucket) // The check for sufficient credit amount (bucket, extra credits, pay as you go spending limit) @@ -68,10 +74,11 @@ class MtCreditBucketService( lockingProvider.withLocking(getMtCreditBucketLockName(project)) { tryUntilItDoesntBreakConstraint { executeInNewTransaction(transactionManager) { - val time = measureTime { - val bucket = findOrCreateBucket(project) - checkPositiveBalance(bucket) - } + val time = + measureTime { + val bucket = findOrCreateBucket(project) + checkPositiveBalance(bucket) + } logger.debug("Checked for positive credits in $time") } } @@ -95,10 +102,13 @@ class MtCreditBucketService( return balances.creditBalance + balances.extraCreditBalance + availablePayAsYouGoCredits } - private fun MtCreditBucket.consumeSufficientCredits(amount: Int, organizationId: Long) { + private fun MtCreditBucket.consumeSufficientCredits( + amount: Int, + organizationId: Long, + ) { logger.debug( "Consuming $amount credits for organization $organizationId, " + - "credits: $credits, extraCredits: $extraCredits" + "credits: $credits, extraCredits: $extraCredits", ) if (this.credits >= amount) { this.credits -= amount @@ -120,19 +130,25 @@ class MtCreditBucketService( OnConsumePayAsYouGoMtCredits( this@MtCreditBucketService, organizationId, - amountToConsumeFromPayAsYouGo - ) + amountToConsumeFromPayAsYouGo, + ), ) } @Transactional - fun addExtraCredits(organization: Organization, amount: Long) { + fun addExtraCredits( + organization: Organization, + amount: Long, + ) { val bucket = findOrCreateBucket(organization) addExtraCredits(bucket, amount) } @Transactional - fun addExtraCredits(bucket: MtCreditBucket, amount: Long) { + fun addExtraCredits( + bucket: MtCreditBucket, + amount: Long, + ) { bucket.extraCredits += amount save(bucket) } @@ -156,7 +172,7 @@ class MtCreditBucketService( bucketSize = bucket.bucketSize, extraCreditBalance = bucket.extraCredits, refilledAt = bucket.refilled, - nextRefillAt = bucket.getNextRefillDate() + nextRefillAt = bucket.getNextRefillDate(), ) } @@ -172,7 +188,10 @@ class MtCreditBucketService( refillBucket(bucket, getRefillAmount(bucket.organization)) } - fun refillBucket(bucket: MtCreditBucket, bucketSize: Long) { + fun refillBucket( + bucket: MtCreditBucket, + bucketSize: Long, + ) { bucket.credits = bucketSize bucket.refilled = currentDateProvider.date bucket.bucketSize = bucket.credits @@ -191,7 +210,7 @@ class MtCreditBucketService( private fun findOrCreateBucket(organization: Organization): MtCreditBucket { return tryUntilItDoesntBreakConstraint { machineTranslationCreditBucketRepository.findByOrganization(organization) ?: createBucket( - organization + organization, ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtLanguageInfo.kt b/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtLanguageInfo.kt index 4858fa5042..973dc65717 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtLanguageInfo.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtLanguageInfo.kt @@ -4,5 +4,5 @@ import io.tolgee.model.Language data class MtLanguageInfo( val language: Language, - val supportedServices: List + val supportedServices: List, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtService.kt b/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtService.kt index f1982ea8f3..f7cf5961d8 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtService.kt @@ -32,7 +32,7 @@ class MtService( private val mtServiceConfigService: MtServiceConfigService, private val tolgeeProperties: TolgeeProperties, private val bigMetaService: BigMetaService, - private val keyService: KeyService + private val keyService: KeyService, ) { @Transactional fun getMachineTranslations( @@ -40,7 +40,7 @@ class MtService( key: Key?, baseTranslationText: String?, targetLanguage: Language, - services: Set? + services: Set?, ): Map { val baseLanguage = projectService.getOrCreateBaseLanguageOrThrow(project.id) @@ -52,33 +52,38 @@ class MtService( keyId = key?.id, baseLanguage = baseLanguage, targetLanguage = targetLanguage, - services = services + services = services, ) } fun getBaseTranslation( baseTranslationText: String?, key: Key?, - baseLanguage: Language + baseLanguage: Language, ): String? { - val baseTranslationTextSafe = baseTranslationText ?: key?.let { - translationService.find(it, baseLanguage).orElse(null)?.text - } + val baseTranslationTextSafe = + baseTranslationText ?: key?.let { + translationService.find(it, baseLanguage).orElse(null)?.text + } return baseTranslationTextSafe } - fun getPrimaryMachineTranslations(key: Key, targetLanguages: List, isBatch: Boolean): - List { + fun getPrimaryMachineTranslations( + key: Key, + targetLanguages: List, + isBatch: Boolean, + ): List { val baseLanguage = projectService.getOrCreateBaseLanguage(key.project.id)!! - val baseTranslationText = translationService.find(key, baseLanguage).orElse(null)?.text - ?: return targetLanguages.map { null } + val baseTranslationText = + translationService.find(key, baseLanguage).orElse(null)?.text + ?: return targetLanguages.map { null } return getPrimaryMachineTranslations( key.project, baseTranslationText, key.id, baseLanguage, targetLanguages, - isBatch + isBatch, ) } @@ -88,7 +93,7 @@ class MtService( keyId: Long?, baseLanguage: Language, targetLanguages: List, - isBatch: Boolean + isBatch: Boolean, ): List { publishBeforeEvent(project) @@ -100,45 +105,50 @@ class MtService( val primaryServices = mtServiceConfigService.getPrimaryServices(targetLanguageIds, project) val prepared = TextHelper.replaceIcuParams(baseTranslationText) - val serviceIndexedLanguagesMap = targetLanguages - .asSequence() - .mapIndexed { idx, lang -> idx to lang } - .groupBy { primaryServices[it.second.id] } + val serviceIndexedLanguagesMap = + targetLanguages + .asSequence() + .mapIndexed { idx, lang -> idx to lang } + .groupBy { primaryServices[it.second.id] } val keyName = keyId?.let { projectService.keyService.get(it) }?.name - val metadata = getMetadata( - baseLanguage, - targetLanguages.filter { primaryServices[it.id]?.serviceType?.usesMetadata == true }, - baseTranslationText, - keyId, - true, - ) + val metadata = + getMetadata( + baseLanguage, + targetLanguages.filter { primaryServices[it.id]?.serviceType?.usesMetadata == true }, + baseTranslationText, + keyId, + true, + ) - val translationResults = serviceIndexedLanguagesMap - .map { (service, languageIdxPairs) -> - service?.let { - val translateResults = machineTranslationManager.translate( - prepared.text, - baseTranslationText, - keyName, - baseLanguage.tag, - languageIdxPairs.map { it.second.tag }, - service, - metadata = metadata, - isBatch = isBatch - ) - - val withReplacedParams = translateResults.map { translateResult -> - translateResult.translatedText = translateResult.translatedText?.replaceParams(prepared.params) - translateResult - } - languageIdxPairs.map { it.first }.zip(withReplacedParams) - } ?: languageIdxPairs.map { it.first to null } - } - .flatten() - .sortedBy { it.first } - .map { it.second } + val translationResults = + serviceIndexedLanguagesMap + .map { (service, languageIdxPairs) -> + service?.let { + val translateResults = + machineTranslationManager.translate( + prepared.text, + baseTranslationText, + keyName, + baseLanguage.tag, + languageIdxPairs.map { it.second.tag }, + service, + metadata = metadata, + isBatch = isBatch, + ) + + val withReplacedParams = + translateResults.map { translateResult -> + translateResult.translatedText = translateResult.translatedText?.replaceParams(prepared.params) + translateResult + } + languageIdxPairs.map { it.first }.zip(withReplacedParams) + } ?: languageIdxPairs.map { it.first to null } + } + .flatten() + .sortedBy { it.first } + .map { it.second } val actualPrice = translationResults.sumOf { it?.actualPrice ?: 0 } @@ -153,7 +163,7 @@ class MtService( keyId: Long?, baseLanguage: Language, targetLanguage: Language, - services: Set? + services: Set?, ): Map { checkTextLength(baseTranslationText) val servicesToUse = getServicesToUse(targetLanguage, services) @@ -173,17 +183,18 @@ class MtService( val keyName = keyId?.let { keyService.get(it) }?.name - val results = machineTranslationManager - .translate( - text = prepared.text, - textRaw = baseTranslationText, - keyName = keyName, - sourceLanguageTag = baseLanguage.tag, - targetLanguageTag = targetLanguage.tag, - serviceInfos = servicesToUse, - metadata = metadata, - isBatch = false - ) + val results = + machineTranslationManager + .translate( + text = prepared.text, + textRaw = baseTranslationText, + keyName = keyName, + sourceLanguageTag = baseLanguage.tag, + targetLanguageTag = targetLanguage.tag, + serviceInfos = servicesToUse, + metadata = metadata, + isBatch = false, + ) val actualPrice = results.entries.sumOf { it.value.actualPrice } @@ -203,14 +214,14 @@ class MtService( contextDescription = null, actualPrice = 0, usedService = it.serviceType, - baseBlank = true + baseBlank = true, ) } } fun getServicesToUse( targetLanguage: Language, - desiredServices: Set? + desiredServices: Set?, ): Set { val enabledServices = mtServiceConfigService.getEnabledServiceInfos(targetLanguage) checkServices(desired = desiredServices?.toSet(), enabled = enabledServices.map { it.serviceType }) @@ -218,7 +229,10 @@ class MtService( .toSet() } - private fun checkServices(desired: Set?, enabled: List) { + private fun checkServices( + desired: Set?, + enabled: List, + ) { if (desired != null && desired.any { !enabled.contains(it) }) { throw BadRequestException(Message.MT_SERVICE_NOT_ENABLED) } @@ -226,18 +240,16 @@ class MtService( private fun publishAfterEvent( project: Project, - actualPrice: Int + actualPrice: Int, ) { applicationEventPublisher.publishEvent( - OnAfterMachineTranslationEvent(this, project, actualPrice) + OnAfterMachineTranslationEvent(this, project, actualPrice), ) } - private fun publishBeforeEvent( - project: Project, - ) { + private fun publishBeforeEvent(project: Project) { applicationEventPublisher.publishEvent( - OnBeforeMachineTranslationEvent(this, project) + OnBeforeMachineTranslationEvent(this, project), ) } @@ -260,14 +272,14 @@ class MtService( sourceLanguage: Language, targetLanguage: Language, text: String, - keyId: Long? + keyId: Long?, ): List { return translationService.getTranslationMemorySuggestions( sourceTranslationText = text, key = null, sourceLanguage = sourceLanguage, targetLanguage = targetLanguage, - pageable = PageRequest.of(0, 5) + pageable = PageRequest.of(0, 5), ).content .filter { it.keyId != keyId } .map { @@ -279,13 +291,13 @@ class MtService( sourceLanguage: Language, targetLanguage: Language, closeKeyIds: List, - keyId: Long? + keyId: Long?, ): List { - - val translations = this.translationService.findAllByKeyIdsAndLanguageIds( - closeKeyIds, - languageIds = listOf(sourceLanguage.id, targetLanguage.id) - ) + val translations = + this.translationService.findAllByKeyIdsAndLanguageIds( + closeKeyIds, + languageIds = listOf(sourceLanguage.id, targetLanguage.id), + ) val sourceTranslations = translations.filter { it.language.id == sourceLanguage.id } @@ -297,9 +309,12 @@ class MtService( ExampleItem( key = it.key.name, source = it.text ?: "", - target = if (it.key.id != keyId) { - targetTranslations.find { target -> target.key.id == it.key.id }?.text ?: "" - } else "" + target = + if (it.key.id != keyId) { + targetTranslations.find { target -> target.key.id == it.key.id }?.text ?: "" + } else { + "" + }, ) } } @@ -334,7 +349,7 @@ class MtService( needsMetadata: Boolean = true, ): Metadata? { return getMetadata(sourceLanguage, listOf(targetLanguages), text, keyId, needsMetadata)?.get( - targetLanguages.tag + targetLanguages.tag, ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtServiceConfigService.kt b/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtServiceConfigService.kt index 279debc126..e537c37ad9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtServiceConfigService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtServiceConfigService.kt @@ -39,7 +39,10 @@ class MtServiceConfigService( return getEnabledServiceInfosByStoredConfig(language) ?: getEnabledServicesByDefaultServerConfig(language) } - fun getPrimaryServices(languagesIds: List, project: Project): Map { + fun getPrimaryServices( + languagesIds: List, + project: Project, + ): Map { val configs = getStoredConfigs(languagesIds, project) return languagesIds.associateWith { languageId -> configs[languageId]?.primaryServiceInfo @@ -83,26 +86,29 @@ class MtServiceConfigService( return services[serviceType]?.second?.isLanguageSupported(this.tag) ?: return false } - private fun isServiceEnabledByServerConfig(it: MtServiceInfo) = - getServiceProcessor(it)?.isEnabled ?: false + private fun isServiceEnabledByServerConfig(it: MtServiceInfo) = getServiceProcessor(it)?.isEnabled ?: false - private fun isServiceEnabledByServerConfig(it: MtServiceType) = - this.services[it]?.second?.isEnabled ?: false + private fun isServiceEnabledByServerConfig(it: MtServiceType) = this.services[it]?.second?.isEnabled ?: false @Transactional - fun setProjectSettings(project: Project, dto: SetMachineTranslationSettingsDto) { + fun setProjectSettings( + project: Project, + dto: SetMachineTranslationSettingsDto, + ) { val storedConfigs = getStoredConfigs(project.id) val allLanguages = languageService.findAll(project.id).associateBy { it.id } validateSettings(dto.settings, allLanguages) dto.settings.forEach { languageSetting -> - val entity = storedConfigs.find { it.targetLanguage?.id == languageSetting.targetLanguageId } - ?: MtServiceConfig().apply { - this.project = project - this.targetLanguage = languageSetting.targetLanguageId - ?.let { allLanguages.getLanguageOrThrow(it) } - } + val entity = + storedConfigs.find { it.targetLanguage?.id == languageSetting.targetLanguageId } + ?: MtServiceConfig().apply { + this.project = project + this.targetLanguage = + languageSetting.targetLanguageId + ?.let { allLanguages.getLanguageOrThrow(it) } + } setPrimaryService(entity, languageSetting) entity.enabledServices = getEnabledServices(languageSetting) @@ -110,16 +116,17 @@ class MtServiceConfigService( save(entity) } - val toDelete = storedConfigs.filter { storedConfig -> - dto.settings.find { it.targetLanguageId == storedConfig.targetLanguage?.id } == null - } + val toDelete = + storedConfigs.filter { storedConfig -> + dto.settings.find { it.targetLanguageId == storedConfig.targetLanguage?.id } == null + } delete(toDelete) } private fun setPrimaryService( entity: MtServiceConfig, - languageSetting: MachineTranslationLanguagePropsDto + languageSetting: MachineTranslationLanguagePropsDto, ) { // this setting is already deprecated (it doesn't support formality), but we need to support it for now entity.primaryService = languageSetting.primaryService @@ -136,7 +143,10 @@ class MtServiceConfigService( return this[id] ?: throw NotFoundException(Message.LANGUAGE_NOT_FOUND) } - private fun validateSettings(settings: List, allLanguages: Map) { + private fun validateSettings( + settings: List, + allLanguages: Map, + ) { settings.forEach { validateSetting(allLanguages, it) } @@ -144,7 +154,7 @@ class MtServiceConfigService( private fun validateSetting( allLanguages: Map, - languageProps: MachineTranslationLanguagePropsDto + languageProps: MachineTranslationLanguagePropsDto, ) { val language = allLanguages.getLanguageOrThrow(languageProps.targetLanguageId) ?: return validateLanguageSupported(languageProps, language) @@ -161,14 +171,15 @@ class MtServiceConfigService( private fun validatePrimaryServiceFormality( languageProps: MachineTranslationLanguagePropsDto, - language: Language + language: Language, ) { val primaryServiceInfo = languageProps.primaryServiceInfo ?: return if (primaryServiceInfo.formality === null) { return } - val isSupported = getServiceProcessor(primaryServiceInfo)?.isLanguageFormalitySupported(language.tag) - ?: false + val isSupported = + getServiceProcessor(primaryServiceInfo)?.isLanguageFormalitySupported(language.tag) + ?: false if (!isSupported) { throwFormalityNotSupported(primaryServiceInfo, language) @@ -197,16 +208,15 @@ class MtServiceConfigService( ) { throw BadRequestException( Message.FORMALITY_NOT_SUPPORTED_BY_SERVICE, - listOf(mtServiceInfo.serviceType.name, language.tag, mtServiceInfo.formality!!) + listOf(mtServiceInfo.serviceType.name, language.tag, mtServiceInfo.formality!!), ) } - private fun getServiceProcessor(it: MtServiceInfo) = - this.services[it.serviceType]?.second + private fun getServiceProcessor(it: MtServiceInfo) = this.services[it.serviceType]?.second private fun validateLanguageSupported( it: MachineTranslationLanguagePropsDto, - language: Language + language: Language, ) { val allServices = getAllEnabledOrPrimaryServices(it) allServices.forEach { @@ -229,7 +239,10 @@ class MtServiceConfigService( return allServiceTypes.filter { isServiceEnabledByServerConfig(it) }.toMutableSet() } - private fun setFormalities(entity: MtServiceConfig, languageSetting: MachineTranslationLanguagePropsDto) { + private fun setFormalities( + entity: MtServiceConfig, + languageSetting: MachineTranslationLanguagePropsDto, + ) { languageSetting.enabledServicesInfoNotNull.forEach { when (it.serviceType) { MtServiceType.AWS -> entity.awsFormality = it.formality ?: Formality.DEFAULT @@ -259,17 +272,19 @@ class MtServiceConfigService( } configs.forEach { config -> // put primary service first - config.enabledServices = config.enabledServices - .sortedByDescending { config.primaryService == it } - .toSortedSet() + config.enabledServices = + config.enabledServices + .sortedByDescending { config.primaryService == it } + .toSortedSet() } } } private fun getDefaultConfig(project: Project): MtServiceConfig { return MtServiceConfig().apply { - enabledServices = services.filter { it.value.first.defaultEnabled && it.value.second.isEnabled } - .keys.toMutableSet() + enabledServices = + services.filter { it.value.first.defaultEnabled && it.value.second.isEnabled } + .keys.toMutableSet() this.project = project primaryService = services.entries.find { it.value.first.defaultPrimary }?.key } @@ -300,7 +315,10 @@ class MtServiceConfigService( return entities.find { it.targetLanguage != null } ?: entities.find { it.targetLanguage == null } } - private fun getStoredConfigs(languageIds: List, project: Project): Map { + private fun getStoredConfigs( + languageIds: List, + project: Project, + ): Map { val entities = mtServiceConfigRepository.findAllByTargetLanguageIdIn(languageIds, project) return languageIds.associateWith { languageId -> entities.find { it.targetLanguage?.id == languageId } ?: entities.find { it.targetLanguage == null } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtServiceInfo.kt b/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtServiceInfo.kt index 571218d626..c0dd172415 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtServiceInfo.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtServiceInfo.kt @@ -5,5 +5,5 @@ import io.tolgee.model.mtServiceConfig.Formality data class MtServiceInfo( val serviceType: MtServiceType, - val formality: Formality? = null + val formality: Formality? = null, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtSupportedService.kt b/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtSupportedService.kt index fce4cce6df..df300b2fcb 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtSupportedService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/machineTranslation/MtSupportedService.kt @@ -4,5 +4,5 @@ import io.tolgee.constants.MtServiceType data class MtSupportedService( val serviceType: MtServiceType, - val formalitySupported: Boolean + val formalitySupported: Boolean, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/organization/OrganizationRoleService.kt b/backend/data/src/main/kotlin/io/tolgee/service/organization/OrganizationRoleService.kt index bca55dae0c..8b1f3ccadc 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/organization/OrganizationRoleService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/organization/OrganizationRoleService.kt @@ -36,38 +36,53 @@ class OrganizationRoleService( fun checkUserCanViewStrict(organizationId: Long) { checkUserCanViewStrict( authenticationFacade.authenticatedUser.id, - organizationId + organizationId, ) } - private fun checkUserCanViewStrict(userId: Long, organizationId: Long) { + private fun checkUserCanViewStrict( + userId: Long, + organizationId: Long, + ) { if (!canUserViewStrict(userId, organizationId)) throw PermissionException() } - fun canUserViewStrict(userId: Long, organizationId: Long) = - this.organizationRepository.canUserView(userId, organizationId) + fun canUserViewStrict( + userId: Long, + organizationId: Long, + ) = this.organizationRepository.canUserView(userId, organizationId) fun checkUserCanView(organizationId: Long) { checkUserCanView( authenticationFacade.authenticatedUser.id, organizationId, - authenticationFacade.authenticatedUser.role == UserAccount.Role.ADMIN + authenticationFacade.authenticatedUser.role == UserAccount.Role.ADMIN, ) } - private fun checkUserCanView(userId: Long, organizationId: Long, isAdmin: Boolean = false) { + private fun checkUserCanView( + userId: Long, + organizationId: Long, + isAdmin: Boolean = false, + ) { if (!isAdmin && !canUserViewStrict(userId, organizationId)) throw PermissionException() } - fun canUserView(userId: Long, organizationId: Long): Boolean { - val userAccountDto = userAccountService.findDto(userId) - ?: return false + fun canUserView( + userId: Long, + organizationId: Long, + ): Boolean { + val userAccountDto = + userAccountService.findDto(userId) + ?: return false return canUserView(userAccountDto, organizationId) } - fun canUserView(user: UserAccountDto, organizationId: Long) = - user.role === UserAccount.Role.ADMIN || this.organizationRepository.canUserView(user.id, organizationId) + fun canUserView( + user: UserAccountDto, + organizationId: Long, + ) = user.role === UserAccount.Role.ADMIN || this.organizationRepository.canUserView(user.id, organizationId) /** * Verifies the user has a role equal or higher than a given role. @@ -77,7 +92,11 @@ class OrganizationRoleService( * @param role The minimum role the user should have. * @return Whether the user has at least the [role] role in the organization. */ - fun isUserOfRole(userId: Long, organizationId: Long, role: OrganizationRoleType): Boolean { + fun isUserOfRole( + userId: Long, + organizationId: Long, + role: OrganizationRoleType, + ): Boolean { // The use of a when here is an intentional code design choice. // If a new role gets added, this will not compile and will need to be addressed. return when (role) { @@ -88,7 +107,10 @@ class OrganizationRoleService( } } - fun checkUserIsOwner(userId: Long, organizationId: Long) { + fun checkUserIsOwner( + userId: Long, + organizationId: Long, + ) { val isServerAdmin = userAccountService.get(userId).role == UserAccount.Role.ADMIN if (this.isUserOwner(userId, organizationId) || isServerAdmin) return else throw PermissionException() } @@ -97,7 +119,10 @@ class OrganizationRoleService( this.checkUserIsOwner(authenticationFacade.authenticatedUser.id, organizationId) } - fun checkUserIsMemberOrOwner(userId: Long, organizationId: Long) { + fun checkUserIsMemberOrOwner( + userId: Long, + organizationId: Long, + ) { val isServerAdmin = userAccountService.get(userId).role == UserAccount.Role.ADMIN if (isUserMemberOrOwner(userId, organizationId) || isServerAdmin) { return @@ -109,12 +134,18 @@ class OrganizationRoleService( this.checkUserIsMemberOrOwner(this.authenticationFacade.authenticatedUser.id, organizationId) } - fun isUserMemberOrOwner(userId: Long, organizationId: Long): Boolean { + fun isUserMemberOrOwner( + userId: Long, + organizationId: Long, + ): Boolean { val role = organizationRoleRepository.findOneByUserIdAndOrganizationId(userId, organizationId) return role != null } - fun isUserOwner(userId: Long, organizationId: Long): Boolean { + fun isUserOwner( + userId: Long, + organizationId: Long, + ): Boolean { val role = organizationRoleRepository.findOneByUserIdAndOrganizationId(userId, organizationId) return role?.type == OrganizationRoleType.OWNER } @@ -123,7 +154,10 @@ class OrganizationRoleService( return organizationRoleRepository.findById(id).orElse(null) } - fun getType(userId: Long, organizationId: Long): OrganizationRoleType { + fun getType( + userId: Long, + organizationId: Long, + ): OrganizationRoleType { organizationRoleRepository.findOneByUserIdAndOrganizationId(userId, organizationId) ?.let { return it.type!! } throw PermissionException() @@ -137,7 +171,10 @@ class OrganizationRoleService( return findType(authenticationFacade.authenticatedUser.id, organizationId) } - fun findType(userId: Long, organizationId: Long): OrganizationRoleType? { + fun findType( + userId: Long, + organizationId: Long, + ): OrganizationRoleType? { organizationRoleRepository.findOneByUserIdAndOrganizationId(userId, organizationId) ?.let { return it.type } return null @@ -146,7 +183,7 @@ class OrganizationRoleService( fun grantRoleToUser( user: UserAccount, organization: Organization, - organizationRoleType: OrganizationRoleType + organizationRoleType: OrganizationRoleType, ) { OrganizationRole(user = user, organization = organization, type = organizationRoleType) .let { @@ -160,11 +197,15 @@ class OrganizationRoleService( this.removeUser(organizationId, authenticationFacade.authenticatedUser.id) } - fun removeUser(organizationId: Long, userId: Long) { - val role = organizationRoleRepository.findOneByUserIdAndOrganizationId(userId, organizationId)?.let { - organizationRoleRepository.delete(it) - it - } + fun removeUser( + organizationId: Long, + userId: Long, + ) { + val role = + organizationRoleRepository.findOneByUserIdAndOrganizationId(userId, organizationId)?.let { + organizationRoleRepository.delete(it) + it + } val permissions = permissionService.removeAllProjectInOrganization(organizationId, userId) if (role == null && permissions.isEmpty()) { @@ -182,15 +223,25 @@ class OrganizationRoleService( organizationRoleRepository.deleteById(id) } - fun grantMemberRoleToUser(user: UserAccount, organization: Organization) { + fun grantMemberRoleToUser( + user: UserAccount, + organization: Organization, + ) { this.grantRoleToUser(user, organization, organizationRoleType = OrganizationRoleType.MEMBER) } - fun grantOwnerRoleToUser(user: UserAccount, organization: Organization) { + fun grantOwnerRoleToUser( + user: UserAccount, + organization: Organization, + ) { this.grantRoleToUser(user, organization, organizationRoleType = OrganizationRoleType.OWNER) } - fun setMemberRole(organizationId: Long, userId: Long, dto: SetOrganizationRoleDto) { + fun setMemberRole( + organizationId: Long, + userId: Long, + dto: SetOrganizationRoleDto, + ) { val user = userAccountService.findActive(userId) ?: throw NotFoundException() organizationRoleRepository.findOneByUserIdAndOrganizationId(user.id, organizationId)?.let { it.type = dto.roleType @@ -201,14 +252,17 @@ class OrganizationRoleService( fun createForInvitation( invitation: Invitation, type: OrganizationRoleType, - organization: Organization + organization: Organization, ): OrganizationRole { return OrganizationRole(invitation = invitation, type = type, organization = organization).let { organizationRoleRepository.save(it) } } - fun acceptInvitation(organizationRole: OrganizationRole, userAccount: UserAccount) { + fun acceptInvitation( + organizationRole: OrganizationRole, + userAccount: UserAccount, + ) { organizationRole.invitation = null organizationRole.user = userAccount organizationRoleRepository.save(organizationRole) @@ -223,7 +277,7 @@ class OrganizationRoleService( .countAllByOrganizationIdAndTypeAndUserIdNot( id, OrganizationRoleType.OWNER, - authenticationFacade.authenticatedUser.id + authenticationFacade.authenticatedUser.id, ) > 0 } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/organization/OrganizationService.kt b/backend/data/src/main/kotlin/io/tolgee/service/organization/OrganizationService.kt index e1b0e15b44..1b922c42e4 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/organization/OrganizationService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/organization/OrganizationService.kt @@ -55,7 +55,7 @@ class OrganizationService( private val permissionService: PermissionService, private val cacheManager: CacheManager, private val currentDateProvider: CurrentDateProvider, - private val eventPublisher: ApplicationEventPublisher + private val eventPublisher: ApplicationEventPublisher, ) : Logging { private val cache: Cache? by lazy { cacheManager.getCache(Caches.ORGANIZATIONS) } @@ -63,33 +63,34 @@ class OrganizationService( lateinit var projectService: ProjectService @Transactional - fun create( - createDto: OrganizationDto, - ): Organization { + fun create(createDto: OrganizationDto): Organization { return create(createDto, authenticationFacade.authenticatedUserEntity) } @Transactional fun create( createDto: OrganizationDto, - userAccount: UserAccount + userAccount: UserAccount, ): Organization { if (createDto.slug != null && !validateSlugUniqueness(createDto.slug!!)) { throw ValidationException(Message.ADDRESS_PART_NOT_UNIQUE) } - val slug = createDto.slug - ?: generateSlug(createDto.name) + val slug = + createDto.slug + ?: generateSlug(createDto.name) - val basePermission = Permission( - type = ProjectPermissionType.VIEW, - ) + val basePermission = + Permission( + type = ProjectPermissionType.VIEW, + ) - val organization = Organization( - name = createDto.name, - description = createDto.description, - slug = slug, - ) + val organization = + Organization( + name = createDto.name, + description = createDto.description, + slug = slug, + ) organization.basePermission = basePermission @@ -101,11 +102,16 @@ class OrganizationService( return organization } - fun createPreferred(userAccount: UserAccount, name: String = userAccount.name): Organization { - val safeName = if (name.isNotEmpty() || name.length >= 3) - name - else - "${userAccount.username.take(3)} Organization" + fun createPreferred( + userAccount: UserAccount, + name: String = userAccount.name, + ): Organization { + val safeName = + if (name.isNotEmpty() || name.length >= 3) { + name + } else { + "${userAccount.username.take(3)} Organization" + } return this.create(OrganizationDto(name = safeName), userAccount = userAccount) } @@ -117,18 +123,24 @@ class OrganizationService( /** * Returns any organizations accessible by user. */ - fun findPreferred(userAccountId: Long, exceptOrganizationId: Long = 0): Organization? { + fun findPreferred( + userAccountId: Long, + exceptOrganizationId: Long = 0, + ): Organization? { return organizationRepository.findPreferred( userId = userAccountId, exceptOrganizationId, - PageRequest.of(0, 1) + PageRequest.of(0, 1), ).content.firstOrNull() } /** * Returns existing or created organization which seems to be potentially preferred. */ - fun findOrCreatePreferred(userAccount: UserAccount, exceptOrganizationId: Long = 0): Organization? { + fun findOrCreatePreferred( + userAccount: UserAccount, + exceptOrganizationId: Long = 0, + ): Organization? { return findPreferred(userAccount.id, exceptOrganizationId) ?: let { if (tolgeeProperties.authentication.userCanCreateOrganizations || userAccount.role == UserAccount.Role.ADMIN) { return@let createPreferred(userAccount) @@ -140,13 +152,13 @@ class OrganizationService( fun findPermittedPaged( pageable: Pageable, requestParamsDto: OrganizationRequestParamsDto, - exceptOrganizationId: Long? = null + exceptOrganizationId: Long? = null, ): Page { return findPermittedPaged( pageable, requestParamsDto.filterCurrentUserOwner, requestParamsDto.search, - exceptOrganizationId + exceptOrganizationId, ) } @@ -154,14 +166,14 @@ class OrganizationService( pageable: Pageable, filterCurrentUserOwner: Boolean = false, search: String? = null, - exceptOrganizationId: Long? = null + exceptOrganizationId: Long? = null, ): Page { return organizationRepository.findAllPermitted( userId = authenticationFacade.authenticatedUser.id, pageable = pageable, roleType = if (filterCurrentUserOwner) OrganizationRoleType.OWNER else null, search = search, - exceptOrganizationId = exceptOrganizationId + exceptOrganizationId = exceptOrganizationId, ) } @@ -192,7 +204,10 @@ class OrganizationService( } @CacheEvict(cacheNames = [Caches.ORGANIZATIONS], key = "{'id', #id}") - fun edit(id: Long, editDto: OrganizationDto): OrganizationView { + fun edit( + id: Long, + editDto: OrganizationDto, + ): OrganizationView { val organization = this.find(id) ?: throw NotFoundException() // Evict slug-based cache entry @@ -216,7 +231,7 @@ class OrganizationService( evict = [ CacheEvict(cacheNames = [Caches.ORGANIZATIONS], key = "{'id', #organization.id}"), CacheEvict(cacheNames = [Caches.ORGANIZATIONS], key = "{'slug', #organization.slug}"), - ] + ], ) fun delete(organization: Organization) { organization.deletedAt = currentDateProvider.date @@ -225,10 +240,11 @@ class OrganizationService( organization.preferredBy .toList() // we need to clone it so hibernate doesn't change it concurrently .forEach { - it.preferredOrganization = findOrCreatePreferred( - userAccount = it.userAccount, - exceptOrganizationId = organization.id - ) + it.preferredOrganization = + findOrCreatePreferred( + userAccount = it.userAccount, + exceptOrganizationId = organization.id, + ) userPreferencesService.save(it) } } @@ -265,7 +281,7 @@ class OrganizationService( evict = [ CacheEvict(cacheNames = [Caches.ORGANIZATIONS], key = "#organization.id"), CacheEvict(cacheNames = [Caches.ORGANIZATIONS], key = "#organization.slug"), - ] + ], ) fun removeAvatar(organization: Organization) { avatarService.removeAvatar(organization) @@ -276,9 +292,12 @@ class OrganizationService( evict = [ CacheEvict(cacheNames = [Caches.ORGANIZATIONS], key = "#organization.id"), CacheEvict(cacheNames = [Caches.ORGANIZATIONS], key = "#organization.slug"), - ] + ], ) - fun setAvatar(organization: Organization, avatar: InputStream) { + fun setAvatar( + organization: Organization, + avatar: InputStream, + ) { avatarService.setAvatar(organization, avatar) } @@ -294,7 +313,10 @@ class OrganizationService( return organizationRoleService.isAnotherOwnerInOrganization(id) } - fun generateSlug(name: String, oldSlug: String? = null): String { + fun generateSlug( + name: String, + oldSlug: String? = null, + ): String { return slugGenerator.generate(name, 3, 60) { if (it == oldSlug) { return@generate true @@ -318,13 +340,17 @@ class OrganizationService( evict = [ CacheEvict(cacheNames = [Caches.ORGANIZATIONS], key = "#organization.id"), CacheEvict(cacheNames = [Caches.ORGANIZATIONS], key = "#organization.slug"), - ] + ], ) fun save(organization: Organization) { organizationRepository.save(organization) } - fun findAllPaged(pageable: Pageable, search: String?, userId: Long): Page { + fun findAllPaged( + pageable: Pageable, + search: String?, + userId: Long, + ): Page { return organizationRepository.findAllViews(pageable, search, userId) } @@ -336,7 +362,10 @@ class OrganizationService( return organizationRepository.getProjectOwner(projectId) } - fun setBasePermission(organizationId: Long, permissionType: ProjectPermissionType) { + fun setBasePermission( + organizationId: Long, + permissionType: ProjectPermissionType, + ) { // Cache eviction: Not necessary, base permission is not cached here val organization = get(organizationId) val basePermission = organization.basePermission diff --git a/backend/data/src/main/kotlin/io/tolgee/service/organization/OrganizationStatsService.kt b/backend/data/src/main/kotlin/io/tolgee/service/organization/OrganizationStatsService.kt index 4660c11f93..f40fa8d5d6 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/organization/OrganizationStatsService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/organization/OrganizationStatsService.kt @@ -6,15 +6,15 @@ import java.math.BigDecimal @Service class OrganizationStatsService( - private val entityManager: EntityManager + private val entityManager: EntityManager, ) { fun getProjectLanguageCount(projectId: Long): Long { return entityManager .createQuery( """ - select count(l) from Language l - where l.project.id = :projectId and l.project.deletedAt is null - """.trimIndent() + select count(l) from Language l + where l.project.id = :projectId and l.project.deletedAt is null + """.trimIndent(), ) .setParameter("projectId", projectId) .singleResult as Long @@ -24,31 +24,32 @@ class OrganizationStatsService( return entityManager .createQuery( """ - select count(k) from Key k - where k.project.id = :projectId and k.project.deletedAt is null - """.trimIndent() + select count(k) from Key k + where k.project.id = :projectId and k.project.deletedAt is null + """.trimIndent(), ) .setParameter("projectId", projectId) .singleResult as Long } fun getCurrentTranslationSlotCount(organizationId: Long): Long { - val result = entityManager.createNativeQuery( - """ - select - (select sum(keyCount * languageCount) as translationCount - from (select p.id as projectId, count(l.id) as languageCount - from project as p - join language as l on l.project_id = p.id - where p.organization_owner_id = :organizationId and p.deleted_at is null - group by p.id) as languageCounts - join (select p.id as projectId, count(k.id) as keyCount - from project as p - join key as k on k.project_id = p.id - where p.organization_owner_id = :organizationId and p.deleted_at is null - group by p.id) as keyCounts on keyCounts.projectId = languageCounts.projectId) - """.trimIndent() - ).setParameter("organizationId", organizationId).singleResult as BigDecimal? ?: 0 + val result = + entityManager.createNativeQuery( + """ + select + (select sum(keyCount * languageCount) as translationCount + from (select p.id as projectId, count(l.id) as languageCount + from project as p + join language as l on l.project_id = p.id + where p.organization_owner_id = :organizationId and p.deleted_at is null + group by p.id) as languageCounts + join (select p.id as projectId, count(k.id) as keyCount + from project as p + join key as k on k.project_id = p.id + where p.organization_owner_id = :organizationId and p.deleted_at is null + group by p.id) as keyCounts on keyCounts.projectId = languageCounts.projectId) + """.trimIndent(), + ).setParameter("organizationId", organizationId).singleResult as BigDecimal? ?: 0 return result.toLong() } @@ -58,7 +59,7 @@ class OrganizationStatsService( select count(t) from Translation t where t.key.project.organizationOwner.id = :organizationId and t.state <> io.tolgee.model.enums.TranslationState.UNTRANSLATED and t.key.project.deletedAt is null - """.trimIndent() + """.trimIndent(), ).setParameter("organizationId", organizationId).singleResult as Long? ?: 0 } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/project/LanguageStatsService.kt b/backend/data/src/main/kotlin/io/tolgee/service/project/LanguageStatsService.kt index ebdd31eb18..eaae08b2ca 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/project/LanguageStatsService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/project/LanguageStatsService.kt @@ -6,7 +6,7 @@ import io.tolgee.model.LanguageStats import io.tolgee.model.views.projectStats.ProjectLanguageStatsResultView import io.tolgee.repository.LanguageStatsRepository import io.tolgee.service.LanguageService -import io.tolgee.service.query_builders.LanguageStatsProvider +import io.tolgee.service.queryBuilders.LanguageStatsProvider import io.tolgee.util.Logging import io.tolgee.util.debug import io.tolgee.util.executeInNewRepeatableTransaction @@ -26,7 +26,7 @@ class LanguageStatsService( private val entityManager: EntityManager, private val projectService: ProjectService, private val lockingProvider: LockingProvider, - private val platformTransactionManager: PlatformTransactionManager + private val platformTransactionManager: PlatformTransactionManager, ) : Logging { fun refreshLanguageStats(projectId: Long) { lockingProvider.withLocking("refresh-lang-stats-$projectId") { @@ -34,14 +34,15 @@ class LanguageStatsService( val languages = languageService.findAll(projectId) val allRawLanguageStats = getLanguageStatsRaw(projectId) try { - val baseLanguage = projectService.getOrCreateBaseLanguage(projectId) - val rawBaseLanguageStats = allRawLanguageStats.find { it.languageId == baseLanguage?.id } - ?: return@tx + val rawBaseLanguageStats = + allRawLanguageStats.find { it.languageId == baseLanguage?.id } + ?: return@tx val projectStats = projectStatsService.getProjectStats(projectId) - val languageStats = languageStatsRepository.getAllByProjectId(projectId) - .associateBy { it.language.id } - .toMutableMap() + val languageStats = + languageStatsRepository.getAllByProjectId(projectId) + .associateBy { it.language.id } + .toMutableMap() allRawLanguageStats .sortedBy { it.languageName } @@ -52,9 +53,10 @@ class LanguageStatsService( val translatedOrReviewedWords = rawLanguageStats.translatedWords + rawLanguageStats.reviewedWords val untranslatedWords = baseWords - translatedOrReviewedWords val language = languages.find { it.id == rawLanguageStats.languageId } ?: return@tx - val stats = languageStats.computeIfAbsent(language.id) { - LanguageStats(language) - } + val stats = + languageStats.computeIfAbsent(language.id) { + LanguageStats(language) + } stats.apply { translatedKeys = rawLanguageStats.translatedKeys translatedWords = rawLanguageStats.translatedWords @@ -74,9 +76,9 @@ class LanguageStatsService( } logger.debug { "Language stats refreshed for project $projectId: ${ - languageStats.values.joinToString("\n") { - "${it.language.id} reviewed words: ${it.reviewedWords} translated words:${it.translatedWords}" - } + languageStats.values.joinToString("\n") { + "${it.language.id} reviewed words: ${it.reviewedWords} translated words:${it.translatedWords}" + } }" } } catch (e: NotFoundException) { diff --git a/backend/data/src/main/kotlin/io/tolgee/service/project/ProjectService.kt b/backend/data/src/main/kotlin/io/tolgee/service/project/ProjectService.kt index 6147040074..53bd8ae75b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/project/ProjectService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/project/ProjectService.kt @@ -64,7 +64,7 @@ class ProjectService( private val projectHolder: ProjectHolder, @Lazy private val batchJobService: BatchJobService, - private val currentDateProvider: CurrentDateProvider + private val currentDateProvider: CurrentDateProvider, ) : Logging { @set:Autowired @set:Lazy @@ -131,11 +131,12 @@ class ProjectService( @Transactional fun getView(id: Long): ProjectWithLanguagesView { val perms = permissionService.getProjectPermissionData(id, authenticationFacade.authenticatedUser.id) - val withoutPermittedLanguages = projectRepository.findViewById(authenticationFacade.authenticatedUser.id, id) - ?: throw NotFoundException(Message.PROJECT_NOT_FOUND) + val withoutPermittedLanguages = + projectRepository.findViewById(authenticationFacade.authenticatedUser.id, id) + ?: throw NotFoundException(Message.PROJECT_NOT_FOUND) return ProjectWithLanguagesView.fromProjectView( withoutPermittedLanguages, - perms.directPermissions?.translateLanguageIds?.toList() + perms.directPermissions?.translateLanguageIds?.toList(), ) } @@ -161,15 +162,20 @@ class ProjectService( @Transactional @CacheEvict(cacheNames = [Caches.PROJECTS], key = "#result.id") - fun editProject(id: Long, dto: EditProjectDTO): Project { - val project = projectRepository.findById(id) - .orElseThrow { NotFoundException() }!! + fun editProject( + id: Long, + dto: EditProjectDTO, + ): Project { + val project = + projectRepository.findById(id) + .orElseThrow { NotFoundException() }!! project.name = dto.name project.description = dto.description dto.baseLanguageId?.let { - val language = project.languages.find { it.id == dto.baseLanguageId } - ?: throw BadRequestException(Message.LANGUAGE_NOT_FROM_PROJECT) + val language = + project.languages.find { it.id == dto.baseLanguageId } + ?: throw BadRequestException(Message.LANGUAGE_NOT_FROM_PROJECT) project.baseLanguage = language } @@ -195,12 +201,13 @@ class ProjectService( val permission = result[1] as Permission? val organization = result[2] as Organization val organizationRole = result[3] as OrganizationRole? - val scopes = permissionService.computeProjectPermission( - organizationRole?.type, - organization.basePermission, - permission, - userAccount.role ?: UserAccount.Role.USER - ).scopes + val scopes = + permissionService.computeProjectPermission( + organizationRole?.type, + organization.basePermission, + permission, + userAccount.role ?: UserAccount.Role.USER, + ).scopes fromEntityAndPermission(project, scopes) }.toList() } @@ -211,15 +218,17 @@ class ProjectService( private fun addPermittedLanguagesToProjects( projectsPage: Page, - userId: Long + userId: Long, ): Page { - val projectLanguageMap = permissionService.getPermittedTranslateLanguagesForProjectIds( - projectsPage.content.map { it.id }, - userId - ) - val newContent = projectsPage.content.map { - ProjectWithLanguagesView.fromProjectView(it, projectLanguageMap[it.id]) - } + val projectLanguageMap = + permissionService.getPermittedTranslateLanguagesForProjectIds( + projectsPage.content.map { it.id }, + userId, + ) + val newContent = + projectsPage.content.map { + ProjectWithLanguagesView.fromProjectView(it, projectLanguageMap[it.id]) + } return PageImpl(newContent, projectsPage.pageable, projectsPage.totalElements) } @@ -319,7 +328,10 @@ class ProjectService( @Transactional @CacheEvict(cacheNames = [Caches.PROJECTS], key = "#project.id") - fun setAvatar(project: Project, avatar: InputStream) { + fun setAvatar( + project: Project, + avatar: InputStream, + ) { avatarService.setAvatar(project, avatar) } @@ -327,7 +339,10 @@ class ProjectService( return projectRepository.countAllBySlug(slug) < 1 } - fun generateSlug(name: String, oldSlug: String? = null): String { + fun generateSlug( + name: String, + oldSlug: String? = null, + ): String { return slugGenerator.generate(name, 3, 60) { if (oldSlug == it) { return@generate true @@ -339,13 +354,13 @@ class ProjectService( fun findPermittedInOrganizationPaged( pageable: Pageable, search: String?, - organizationId: Long? = null + organizationId: Long? = null, ): Page { return findPermittedInOrganizationPaged( pageable = pageable, search = search, organizationId = organizationId, - userAccountId = authenticationFacade.authenticatedUser.id + userAccountId = authenticationFacade.authenticatedUser.id, ) } @@ -353,20 +368,20 @@ class ProjectService( pageable: Pageable, search: String?, organizationId: Long? = null, - userAccountId: Long + userAccountId: Long, ): Page { - val withoutPermittedLanguages = projectRepository.findAllPermitted( - userAccountId, - pageable, - search, - organizationId - ) + val withoutPermittedLanguages = + projectRepository.findAllPermitted( + userAccountId, + pageable, + search, + organizationId, + ) return addPermittedLanguagesToProjects(withoutPermittedLanguages, userAccountId) } @CacheEvict(cacheNames = [Caches.PROJECTS], allEntries = true) - fun saveAll(projects: Collection): MutableList = - projectRepository.saveAll(projects) + fun saveAll(projects: Collection): MutableList = projectRepository.saveAll(projects) @CacheEvict(cacheNames = [Caches.PROJECTS], key = "#result.id") fun save(project: Project): Project { @@ -386,7 +401,10 @@ class ProjectService( return this.projectRepository.findById(project.id).orElseThrow { NotFoundException() } } - private fun getOrCreateBaseLanguage(dto: CreateProjectDTO, createdLanguages: List): Language { + private fun getOrCreateBaseLanguage( + dto: CreateProjectDTO, + createdLanguages: List, + ): Language { if (dto.baseLanguageTag != null) { return createdLanguages.find { it.tag == dto.baseLanguageTag } ?: throw BadRequestException(Message.LANGUAGE_WITH_BASE_LANGUAGE_TAG_NOT_FOUND) @@ -395,18 +413,27 @@ class ProjectService( } @CacheEvict(cacheNames = [Caches.PROJECTS], key = "#projectId") - fun transferToOrganization(projectId: Long, organizationId: Long) { + fun transferToOrganization( + projectId: Long, + organizationId: Long, + ) { val project = get(projectId) val organization = organizationService.find(organizationId) ?: throw NotFoundException() project.organizationOwner = organization save(project) } - fun findAllByNameAndOrganizationOwner(name: String, organization: Organization): List { + fun findAllByNameAndOrganizationOwner( + name: String, + organization: Organization, + ): List { return projectRepository.findAllByNameAndOrganizationOwner(name, organization) } - fun getProjectsWithDirectPermissions(id: Long, userIds: List): Map> { + fun getProjectsWithDirectPermissions( + id: Long, + userIds: List, + ): Map> { val result = projectRepository.getProjectsWithDirectPermissions(id, userIds) return result .map { it[0] as Long to it[1] as Project } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/project/ProjectStatsService.kt b/backend/data/src/main/kotlin/io/tolgee/service/project/ProjectStatsService.kt index 89e794f7ce..b042148d5d 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/project/ProjectStatsService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/project/ProjectStatsService.kt @@ -6,7 +6,7 @@ import io.tolgee.model.Project import io.tolgee.model.Project_ import io.tolgee.model.views.projectStats.ProjectStatsView import io.tolgee.repository.activity.ActivityRevisionRepository -import io.tolgee.service.query_builders.ProjectStatsProvider +import io.tolgee.service.queryBuilders.ProjectStatsProvider import jakarta.persistence.EntityManager import jakarta.persistence.criteria.JoinType import org.springframework.stereotype.Service @@ -17,9 +17,8 @@ import java.time.LocalDate @Service class ProjectStatsService( private val entityManager: EntityManager, - private val activityRevisionRepository: ActivityRevisionRepository + private val activityRevisionRepository: ActivityRevisionRepository, ) { - fun getProjectStats(projectId: Long): ProjectStatsView { return ProjectStatsProvider(entityManager, projectId).getResult() } @@ -53,10 +52,11 @@ class ProjectStatsService( fun computeProjectTotals( baseLanguage: Language?, - languageStats: List + languageStats: List, ): ProjectStateTotals { - val baseStats = languageStats.find { it.language.id == baseLanguage?.id } - ?: return ProjectStateTotals(0, 0.0, 0.0) + val baseStats = + languageStats.find { it.language.id == baseLanguage?.id } + ?: return ProjectStateTotals(0, 0.0, 0.0) val baseWordsCount = baseStats.translatedWords + baseStats.reviewedWords val nonBaseLanguages = languageStats.filterNot { it.language.id == baseLanguage?.id } @@ -71,18 +71,18 @@ class ProjectStatsService( return ProjectStateTotals( baseWordsCount = baseWordsCount, translatedPercent = translatedPercent, - reviewedPercent = reviewedPercent + reviewedPercent = reviewedPercent, ) } data class ProjectStateTotals( val baseWordsCount: Long, val translatedPercent: Double, - val reviewedPercent: Double + val reviewedPercent: Double, ) data class ProjectTotals( val languageCount: Long, - val keyCount: Long + val keyCount: Long, ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/CursorUtil.kt b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/CursorUtil.kt similarity index 75% rename from backend/data/src/main/kotlin/io/tolgee/service/query_builders/CursorUtil.kt rename to backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/CursorUtil.kt index bace971a81..37687b849a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/CursorUtil.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/CursorUtil.kt @@ -1,4 +1,4 @@ -package io.tolgee.service.query_builders +package io.tolgee.service.queryBuilders import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.readValue @@ -10,19 +10,27 @@ import java.util.* class CursorUtil { companion object { - fun getCursor(item: KeyWithTranslationsView?, sort: Sort): String { - val cursor = sort.map { - it.property to CursorValue( - direction = it.direction, - value = getCursorValue(property = it.property, item) - ) - }.toMap().toMutableMap() + fun getCursor( + item: KeyWithTranslationsView?, + sort: Sort, + ): String { + val cursor = + sort.map { + it.property to + CursorValue( + direction = it.direction, + value = getCursorValue(property = it.property, item), + ) + }.toMap().toMutableMap() val json = jacksonObjectMapper().writer().writeValueAsString(cursor) return Base64.getEncoder().encodeToString(json.toByteArray()) } - private fun getCursorValue(property: String, item: KeyWithTranslationsView?): String? { + private fun getCursorValue( + property: String, + item: KeyWithTranslationsView?, + ): String? { val path = property.split(".") return when (path[0]) { KeyWithTranslationsView::keyId.name -> item?.keyId.toString() diff --git a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/LanguageStatsProvider.kt b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/LanguageStatsProvider.kt similarity index 78% rename from backend/data/src/main/kotlin/io/tolgee/service/query_builders/LanguageStatsProvider.kt rename to backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/LanguageStatsProvider.kt index 170bdc6954..b4a5c34362 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/LanguageStatsProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/LanguageStatsProvider.kt @@ -1,4 +1,4 @@ -package io.tolgee.service.query_builders +package io.tolgee.service.queryBuilders import io.tolgee.model.Language_ import io.tolgee.model.Project @@ -20,9 +20,8 @@ import jakarta.persistence.criteria.Selection open class LanguageStatsProvider( val entityManager: EntityManager, - private val projectIds: List + private val projectIds: List, ) { - private val cb: CriteriaBuilder = entityManager.criteriaBuilder val query: CriteriaQuery = cb.createQuery(ProjectLanguageStatsResultView::class.java) @@ -35,20 +34,22 @@ open class LanguageStatsProvider( } private fun initQuery() { - val counts = listOf(TranslationState.TRANSLATED, TranslationState.REVIEWED).map { state -> - selectWordCount(state) to selectKeyCount(state) - } + val counts = + listOf(TranslationState.TRANSLATED, TranslationState.REVIEWED).map { state -> + selectWordCount(state) to selectKeyCount(state) + } val projectId = project.get(Project_.id) val languageId = languageJoin.get(Language_.id) - val selection = mutableListOf>( - projectId, - languageId, - languageJoin.get(Language_.tag), - languageJoin.get(Language_.name), - languageJoin.get(Language_.originalName), - languageJoin.get(Language_.flagEmoji) - ) + val selection = + mutableListOf>( + projectId, + languageId, + languageJoin.get(Language_.tag), + languageJoin.get(Language_.name), + languageJoin.get(Language_.originalName), + languageJoin.get(Language_.flagEmoji), + ) counts.forEach { (wordCount, keyCount) -> selection.add(keyCount) @@ -82,11 +83,12 @@ open class LanguageStatsProvider( joinTargetTranslations(keyJoin, state) - val baseTranslationJoin = keyJoin.join(Key_.translations, JoinType.LEFT).also { translation -> - translation.on( - cb.equal(translation.get(Translation_.language), project.get(Project_.baseLanguage)) - ) - } + val baseTranslationJoin = + keyJoin.join(Key_.translations, JoinType.LEFT).also { translation -> + translation.on( + cb.equal(translation.get(Translation_.language), project.get(Project_.baseLanguage)), + ) + } val count = cb.sum(baseTranslationJoin.get(Translation_.wordCount)) val coalesceCount = cb.coalesce() @@ -98,19 +100,19 @@ open class LanguageStatsProvider( private fun joinTargetTranslations( keyJoin: ListJoin, - state: TranslationState + state: TranslationState, ): ListJoin { return keyJoin.join(Key_.translations).also { translation -> translation.on( cb.and( cb.equal( translation.get( - Translation_.state + Translation_.state, ), - state + state, ), - cb.equal(translation.get(Translation_.language), languageJoin) - ) + cb.equal(translation.get(Translation_.language), languageJoin), + ), ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/ProjectStatsProvider.kt b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/ProjectStatsProvider.kt similarity index 90% rename from backend/data/src/main/kotlin/io/tolgee/service/query_builders/ProjectStatsProvider.kt rename to backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/ProjectStatsProvider.kt index 14620a7ddf..b470c2ba4a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/ProjectStatsProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/ProjectStatsProvider.kt @@ -1,4 +1,4 @@ -package io.tolgee.service.query_builders +package io.tolgee.service.queryBuilders import io.tolgee.model.OrganizationRole_ import io.tolgee.model.Organization_ @@ -20,9 +20,8 @@ import jakarta.persistence.criteria.Selection open class ProjectStatsProvider( val entityManager: EntityManager, - private val projectId: Long + private val projectId: Long, ) : KotlinCriteriaBuilder(entityManager, ProjectStatsView::class.java) { - private var project: Root = query.from(Project::class.java) fun getResult(): ProjectStatsView { @@ -31,12 +30,13 @@ open class ProjectStatsProvider( } private fun initQuery() { - val selection = mutableListOf>( - project.get(Project_.id), - getKeyCountSelection(), - getMemberCountSelection(), - getTagSelection() - ) + val selection = + mutableListOf>( + project.get(Project_.id), + getKeyCountSelection(), + getMemberCountSelection(), + getTagSelection(), + ) query.multiselect(selection) @@ -72,7 +72,7 @@ open class ProjectStatsProvider( ( subUserAccount equal permissionJoin.get(Permission_.user) or (subUserAccount equal rolesJoin.get(OrganizationRole_.user)) - ) + ), ) return sub.select(cb.countDistinct(subUserAccount.get(UserAccount_.id))) } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/CursorPredicateProvider.kt b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/CursorPredicateProvider.kt similarity index 72% rename from backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/CursorPredicateProvider.kt rename to backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/CursorPredicateProvider.kt index 9fbe9b2b66..e5f1914d50 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/CursorPredicateProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/CursorPredicateProvider.kt @@ -1,4 +1,4 @@ -package io.tolgee.service.query_builders.translationViewBuilder +package io.tolgee.service.queryBuilders.translationViewBuilder import io.tolgee.constants.Message import io.tolgee.dtos.response.CursorValue @@ -17,9 +17,8 @@ import org.springframework.data.domain.Sort class CursorPredicateProvider( private val cb: CriteriaBuilder, private val cursor: Map? = null, - private var selection: LinkedHashMap> = LinkedHashMap() + private var selection: LinkedHashMap> = LinkedHashMap(), ) { - @Suppress("UNCHECKED_CAST", "TYPE_MISMATCH_WARNING") /** * This function body is inspired by this thread @@ -29,22 +28,27 @@ class CursorPredicateProvider( var result: Predicate? = null cursor?.entries?.reversed()?.forEach { (property, value) -> val isUnique = property === KeyWithTranslationsView::keyId.name - val expression = selection[property] as? Expression - ?: throw BadRequestException(Message.CANNOT_SORT_BY_THIS_COLUMN) + val expression = + selection[property] as? Expression + ?: throw BadRequestException(Message.CANNOT_SORT_BY_THIS_COLUMN) val strongCondition: Predicate val condition: Predicate if (value.direction == Sort.Direction.ASC) { - condition = if (isUnique) - cb.greaterThan(expression, value.value!!) - else - cb.greaterThanOrEqualToNullable(expression, value.value) + condition = + if (isUnique) { + cb.greaterThan(expression, value.value!!) + } else { + cb.greaterThanOrEqualToNullable(expression, value.value) + } strongCondition = cb.greaterThanNullable(expression, value.value) } else { - condition = if (isUnique) - cb.lessThan(expression, value.value!!) - else - cb.lessThanOrEqualToNullable(expression, value.value) + condition = + if (isUnique) { + cb.lessThan(expression, value.value!!) + } else { + cb.lessThanOrEqualToNullable(expression, value.value) + } strongCondition = cb.lessThanNullable(expression, value.value) } result = result?.let { diff --git a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/QueryBase.kt b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/QueryBase.kt similarity index 94% rename from backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/QueryBase.kt rename to backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/QueryBase.kt index 8de494f7a9..f5c2a22333 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/QueryBase.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/QueryBase.kt @@ -1,4 +1,4 @@ -package io.tolgee.service.query_builders.translationViewBuilder +package io.tolgee.service.queryBuilders.translationViewBuilder import io.tolgee.dtos.request.translation.TranslationFilters import io.tolgee.model.Language @@ -34,7 +34,7 @@ class QueryBase( private val query: CriteriaQuery, private val languages: Set, params: TranslationFilters, - private var isKeyIdsQuery: Boolean = false + private var isKeyIdsQuery: Boolean = false, ) { val whereConditions: MutableSet = HashSet() val root: Root = query.from(Key::class.java) @@ -87,7 +87,10 @@ class QueryBase( queryTranslationFiltering.apply(outdatedFieldMap) } - private fun addTranslationOutdatedField(translation: ListJoin, language: Language): Path { + private fun addTranslationOutdatedField( + translation: ListJoin, + language: Language, + ): Path { val translationOutdated = translation.get(Translation_.outdated) this.querySelection[language to TranslationView::outdated] = translationOutdated return translationOutdated @@ -95,7 +98,7 @@ class QueryBase( private fun addComments( translation: ListJoin, - language: Language + language: Language, ) { val commentsJoin = translation.join(Translation_.comments, JoinType.LEFT) val commentsExpression = cb.countDistinct(commentsJoin) @@ -103,7 +106,7 @@ class QueryBase( val unresolvedCommentsJoin = translation.join(Translation_.comments, JoinType.LEFT) unresolvedCommentsJoin.on( - cb.equal(unresolvedCommentsJoin.get(TranslationComment_.state), TranslationCommentState.NEEDS_RESOLUTION) + cb.equal(unresolvedCommentsJoin.get(TranslationComment_.state), TranslationCommentState.NEEDS_RESOLUTION), ) val unresolvedCommentsExpression = cb.countDistinct(unresolvedCommentsJoin) @@ -112,7 +115,7 @@ class QueryBase( private fun addTranslationStateField( translation: ListJoin, - language: Language + language: Language, ): Path { val translationStateField = translation.get(Translation_.state) this.querySelection[language to TranslationView::state] = translationStateField @@ -121,7 +124,7 @@ class QueryBase( private fun addTranslationText( translation: ListJoin, - language: Language + language: Language, ): Path { val translationTextField = translation.get(Translation_.text) this.querySelection[language to TranslationView::text] = translationTextField @@ -157,7 +160,7 @@ class QueryBase( private fun addNotFilteringTranslationFields( language: Language, - translation: ListJoin + translation: ListJoin, ) { if (!isKeyIdsQuery) { this.querySelection[language to TranslationView::auto] = translation.get(Translation_.auto) @@ -184,8 +187,8 @@ class QueryBase( contextSubquery.where( cb.or( cb.equal(this.root.get(Key_.id), contextRoot.get(KeysDistance_.key1Id)), - cb.equal(this.root.get(Key_.id), contextRoot.get(KeysDistance_.key2Id)) - ) + cb.equal(this.root.get(Key_.id), contextRoot.get(KeysDistance_.key2Id)), + ), ) this.querySelection[KeyWithTranslationsView::contextPresent.name] = cb.exists(contextSubquery) } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/QueryGlobalFiltering.kt b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/QueryGlobalFiltering.kt similarity index 81% rename from backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/QueryGlobalFiltering.kt rename to backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/QueryGlobalFiltering.kt index 112e2147e7..b4b596c933 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/QueryGlobalFiltering.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/QueryGlobalFiltering.kt @@ -1,4 +1,4 @@ -package io.tolgee.service.query_builders.translationViewBuilder +package io.tolgee.service.queryBuilders.translationViewBuilder import io.tolgee.dtos.request.translation.TranslationFilters import io.tolgee.model.key.KeyMeta_ @@ -12,9 +12,8 @@ import java.util.* class QueryGlobalFiltering( private val params: TranslationFilters, private val queryBase: QueryBase<*>, - private val cb: CriteriaBuilder + private val cb: CriteriaBuilder, ) { - fun apply() { filterTag() filterNamespace() @@ -35,8 +34,8 @@ class QueryGlobalFiltering( fullTextRestrictions.add( cb.like( cb.upper(fullTextField), - "%" + search.uppercase(Locale.getDefault()) + "%" - ) + "%" + search.uppercase(Locale.getDefault()) + "%", + ), ) } queryBase.whereConditions.add(cb.or(*fullTextRestrictions.toTypedArray())) @@ -57,18 +56,20 @@ class QueryGlobalFiltering( private fun filterTranslatedAny() { if (params.filterTranslatedAny) { - val predicates = queryBase.translationsTextFields - .map { with(queryBase) { it.isNotNullOrBlank } } - .toTypedArray() + val predicates = + queryBase.translationsTextFields + .map { with(queryBase) { it.isNotNullOrBlank } } + .toTypedArray() queryBase.whereConditions.add(cb.or(*predicates)) } } private fun filterUntranslatedAny() { if (params.filterUntranslatedAny) { - val predicates = queryBase.translationsTextFields - .map { with(queryBase) { it.isNullOrBlank } } - .toTypedArray() + val predicates = + queryBase.translationsTextFields + .map { with(queryBase) { it.isNullOrBlank } } + .toTypedArray() queryBase.whereConditions.add(cb.or(*predicates)) } } @@ -90,10 +91,12 @@ class QueryGlobalFiltering( if (filterNamespace != null) { val inCondition = queryBase.namespaceNameExpression.`in`(filterNamespace) val hasDefaultNamespace = filterNamespace.contains("") - val condition = if (hasDefaultNamespace) - cb.or(inCondition, queryBase.namespaceNameExpression.isNull) - else - inCondition + val condition = + if (hasDefaultNamespace) { + cb.or(inCondition, queryBase.namespaceNameExpression.isNull) + } else { + inCondition + } queryBase.whereConditions.add(condition) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/QuerySelection.kt b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/QuerySelection.kt similarity index 69% rename from backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/QuerySelection.kt rename to backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/QuerySelection.kt index f8c94c0a27..7687b98987 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/QuerySelection.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/QuerySelection.kt @@ -1,4 +1,4 @@ -package io.tolgee.service.query_builders.translationViewBuilder +package io.tolgee.service.queryBuilders.translationViewBuilder import io.tolgee.model.Language import io.tolgee.model.views.KeyWithTranslationsView @@ -7,8 +7,10 @@ import jakarta.persistence.criteria.Selection import kotlin.reflect.KProperty1 class QuerySelection : LinkedHashMap>() { - - operator fun set(field: Pair>, value: Selection<*>) { + operator fun set( + field: Pair>, + value: Selection<*>, + ) { this[KeyWithTranslationsView::translations.name + "." + field.first.tag + "." + field.second.name] = value } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/QueryTranslationFiltering.kt b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/QueryTranslationFiltering.kt similarity index 81% rename from backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/QueryTranslationFiltering.kt rename to backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/QueryTranslationFiltering.kt index 77a0eb19c6..06dfc599e9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/QueryTranslationFiltering.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/QueryTranslationFiltering.kt @@ -1,4 +1,4 @@ -package io.tolgee.service.query_builders.translationViewBuilder +package io.tolgee.service.queryBuilders.translationViewBuilder import io.tolgee.dtos.request.translation.TranslationFilterByState import io.tolgee.dtos.request.translation.TranslationFilters @@ -12,9 +12,8 @@ import jakarta.persistence.criteria.Predicate class QueryTranslationFiltering( private val params: TranslationFilters, private val queryBase: QueryBase<*>, - private val cb: CriteriaBuilder + private val cb: CriteriaBuilder, ) { - fun apply( language: Language, translationTextField: Path, @@ -42,16 +41,17 @@ class QueryTranslationFiltering( } fun apply(languageSourceChangeMap: MutableMap>) { - val conditions = ( - params.filterOutdatedLanguage?.mapNotNull { - val field = languageSourceChangeMap[it] ?: return@mapNotNull null - cb.isTrue(field) - }?.toList() ?: listOf() + val conditions = + ( + params.filterOutdatedLanguage?.mapNotNull { + val field = languageSourceChangeMap[it] ?: return@mapNotNull null + cb.isTrue(field) + }?.toList() ?: listOf() ) + ( - params.filterNotOutdatedLanguage?.mapNotNull { - val field = languageSourceChangeMap[it] ?: return@mapNotNull null - cb.isFalse(field) - }?.toList() ?: listOf() + params.filterNotOutdatedLanguage?.mapNotNull { + val field = languageSourceChangeMap[it] ?: return@mapNotNull null + cb.isFalse(field) + }?.toList() ?: listOf() ) if (conditions.isNotEmpty()) { diff --git a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/TranslationViewDataProvider.kt b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/TranslationViewDataProvider.kt similarity index 79% rename from backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/TranslationViewDataProvider.kt rename to backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/TranslationViewDataProvider.kt index b68bc9fc54..0b89b164f3 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/TranslationViewDataProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/TranslationViewDataProvider.kt @@ -1,10 +1,10 @@ -package io.tolgee.service.query_builders.translationViewBuilder +package io.tolgee.service.queryBuilders.translationViewBuilder import io.tolgee.dtos.request.translation.TranslationFilters import io.tolgee.model.Language import io.tolgee.model.views.KeyWithTranslationsView import io.tolgee.service.key.TagService -import io.tolgee.service.query_builders.CursorUtil +import io.tolgee.service.queryBuilders.CursorUtil import jakarta.persistence.EntityManager import org.springframework.data.domain.Page import org.springframework.data.domain.PageImpl @@ -15,14 +15,14 @@ import org.springframework.stereotype.Component @Component class TranslationViewDataProvider( private val em: EntityManager, - private val tagService: TagService + private val tagService: TagService, ) { fun getData( projectId: Long, languages: Set, pageable: Pageable, params: TranslationFilters = TranslationFilters(), - cursor: String? = null + cursor: String? = null, ): Page { // otherwise it takes forever for postgres to plan the execution em.createNativeQuery("SET join_collapse_limit TO 1").executeUpdate() @@ -50,15 +50,16 @@ class TranslationViewDataProvider( fun getSelectAllKeys( projectId: Long, languages: Set, - params: TranslationFilters = TranslationFilters() + params: TranslationFilters = TranslationFilters(), ): MutableList { - val translationsViewQueryBuilder = TranslationsViewQueryBuilder( - cb = em.criteriaBuilder, - projectId = projectId, - languages = languages, - params = params, - sort = Sort.by(Sort.Order.asc(KeyWithTranslationsView::keyId.name)) - ) + val translationsViewQueryBuilder = + TranslationsViewQueryBuilder( + cb = em.criteriaBuilder, + projectId = projectId, + languages = languages, + params = params, + sort = Sort.by(Sort.Order.asc(KeyWithTranslationsView::keyId.name)), + ) return em.createQuery(translationsViewQueryBuilder.keyIdsQuery).resultList } @@ -67,13 +68,13 @@ class TranslationViewDataProvider( languages: Set, params: TranslationFilters, pageable: Pageable, - cursor: String? + cursor: String?, ) = TranslationsViewQueryBuilder( cb = em.criteriaBuilder, projectId = projectId, languages = languages, params = params, sort = pageable.sort, - cursor = cursor?.let { CursorUtil.parseCursor(it) } + cursor = cursor?.let { CursorUtil.parseCursor(it) }, ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/TranslationsViewQueryBuilder.kt b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/TranslationsViewQueryBuilder.kt similarity index 82% rename from backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/TranslationsViewQueryBuilder.kt rename to backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/TranslationsViewQueryBuilder.kt index 3730852fc9..69173ff61f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/query_builders/translationViewBuilder/TranslationsViewQueryBuilder.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/queryBuilders/translationViewBuilder/TranslationsViewQueryBuilder.kt @@ -1,4 +1,4 @@ -package io.tolgee.service.query_builders.translationViewBuilder +package io.tolgee.service.queryBuilders.translationViewBuilder import io.tolgee.dtos.request.translation.TranslationFilters import io.tolgee.dtos.response.CursorValue @@ -17,14 +17,17 @@ class TranslationsViewQueryBuilder( private val sort: Sort, private val cursor: Map? = null, ) { - private fun getBaseQuery(query: CriteriaQuery, isKeyIdsQuery: Boolean = false): QueryBase { + private fun getBaseQuery( + query: CriteriaQuery, + isKeyIdsQuery: Boolean = false, + ): QueryBase { return QueryBase( cb = cb, projectId = projectId, query = query, languages = languages, params = params, - isKeyIdsQuery = isKeyIdsQuery + isKeyIdsQuery = isKeyIdsQuery, ) } @@ -49,13 +52,14 @@ class TranslationsViewQueryBuilder( } private fun getOrderList(queryBase: QueryBase>): MutableList { - val orderList = sort.asSequence().filter { queryBase.querySelection[it.property] != null }.map { - val expression = queryBase.querySelection[it.property] as Expression<*> - when (it.direction) { - Sort.Direction.DESC -> cb.desc(expression) - else -> cb.asc(expression) - } - }.toMutableList() + val orderList = + sort.asSequence().filter { queryBase.querySelection[it.property] != null }.map { + val expression = queryBase.querySelection[it.property] as Expression<*> + when (it.direction) { + Sort.Direction.DESC -> cb.desc(expression) + else -> cb.asc(expression) + } + }.toMutableList() if (orderList.isEmpty()) { orderList.add(cb.asc(queryBase.keyNameExpression)) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/security/ApiKeyService.kt b/backend/data/src/main/kotlin/io/tolgee/service/security/ApiKeyService.kt index e14027dfb4..a768b1763b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/security/ApiKeyService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/security/ApiKeyService.kt @@ -51,17 +51,18 @@ class ApiKeyService( scopes: Set, project: Project, expiresAt: Long? = null, - description: String? = null + description: String? = null, ): ApiKey { - val apiKey = ApiKey( - key = generateKey(), - project = project, - userAccount = userAccount, - scopesEnum = scopes - ).apply { - this.description = description ?: "" - this.expiresAt = expiresAt?.let { Date(expiresAt) } - } + val apiKey = + ApiKey( + key = generateKey(), + project = project, + userAccount = userAccount, + scopesEnum = scopes, + ).apply { + this.description = description ?: "" + this.expiresAt = expiresAt?.let { Date(expiresAt) } + } return save(apiKey) } @@ -71,7 +72,11 @@ class ApiKeyService( return apiKeyRepository.getAllByUserAccountIdOrderById(userAccountId) } - fun getAllByUser(userAccountId: Long, filterProjectId: Long?, pageable: Pageable): Page { + fun getAllByUser( + userAccountId: Long, + filterProjectId: Long?, + pageable: Pageable, + ): Page { return apiKeyRepository.getAllByUserAccount(userAccountId, filterProjectId, pageable) } @@ -79,7 +84,10 @@ class ApiKeyService( return apiKeyRepository.getAllByProjectId(projectId) } - fun getAllByProject(projectId: Long, pageable: Pageable): Page { + fun getAllByProject( + projectId: Long, + pageable: Pageable, + ): Page { return apiKeyRepository.getAllByProjectId(projectId, pageable) } @@ -113,14 +121,21 @@ class ApiKeyService( apiKeyRepository.delete(apiKey) } - fun getAvailableScopes(userAccountId: Long, project: Project): Array { - val permittedScopes = permissionService.getProjectPermissionScopes(project.id, userAccountId) - ?: throw NotFoundException() + fun getAvailableScopes( + userAccountId: Long, + project: Project, + ): Array { + val permittedScopes = + permissionService.getProjectPermissionScopes(project.id, userAccountId) + ?: throw NotFoundException() return Scope.expand(permittedScopes) } @CacheEvict(cacheNames = [Caches.PROJECT_API_KEYS], key = "#apiKey.keyHash") - fun editApiKey(apiKey: ApiKey, dto: V2EditApiKeyDto): ApiKey { + fun editApiKey( + apiKey: ApiKey, + dto: V2EditApiKeyDto, + ): ApiKey { apiKey.scopesEnum = dto.scopes.toMutableSet() dto.description?.let { apiKey.description = it @@ -153,7 +168,10 @@ class ApiKeyService( return this.apiKeyRepository.save(entity) } - fun encodeKey(key: String, projectId: Long): String { + fun encodeKey( + key: String, + projectId: Long, + ): String { val stringToEncode = "${projectId}_$key" return BaseEncoding.base32().omitPadding().lowerCase().encode(stringToEncode.toByteArray()) } @@ -188,7 +206,10 @@ class ApiKeyService( apiKeyRepository.updateLastUsedById(apiKeyId, currentDateProvider.date) } - fun regenerate(id: Long, expiresAt: Long?): ApiKey { + fun regenerate( + id: Long, + expiresAt: Long?, + ): ApiKey { val apiKey = get(id) // Manual cache eviction cache?.evict(apiKey.keyHash) @@ -221,14 +242,15 @@ class ApiKeyService( private fun logTransactionIsolation() { if (logger.isDebugEnabled) { - val isolationLevel = entityManager.createNativeQuery("show transaction_isolation") - .singleResult as String + val isolationLevel = + entityManager.createNativeQuery("show transaction_isolation") + .singleResult as String logger.debug("Transaction isolation level: $isolationLevel") } } class DecodedApiKey( val projectId: Long, - val apiKey: String + val apiKey: String, ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/security/LanguageDeletedPermissionUpdater.kt b/backend/data/src/main/kotlin/io/tolgee/service/security/LanguageDeletedPermissionUpdater.kt index fd0ef8d4d2..cf759fbb82 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/security/LanguageDeletedPermissionUpdater.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/security/LanguageDeletedPermissionUpdater.kt @@ -14,7 +14,7 @@ import org.springframework.context.ApplicationContext class LanguageDeletedPermissionUpdater( private val applicationContext: ApplicationContext, private val permission: Permission, - private val language: Language + private val language: Language, ) { operator fun invoke() { if (permission.scopes.isNotEmpty()) { @@ -37,7 +37,7 @@ class LanguageDeletedPermissionUpdater( arrayOf( permission.translateLanguages, permission.viewLanguages, - permission.stateChangeLanguages + permission.stateChangeLanguages, ).forEach { languages -> languages.removeIf { it.id == language.id } } @@ -87,25 +87,33 @@ class LanguageDeletedPermissionUpdater( } } - private fun shouldLowerPermissions(languages: MutableSet, type: ProjectPermissionType): Boolean { + private fun shouldLowerPermissions( + languages: MutableSet, + type: ProjectPermissionType, + ): Boolean { return hasOnlyAccessToDeletedLanguage(languages) && hasPermissionType(type) } - private fun shouldLowerPermissions(languages: MutableSet, scope: Scope): Boolean { + private fun shouldLowerPermissions( + languages: MutableSet, + scope: Scope, + ): Boolean { return hasOnlyAccessToDeletedLanguage(languages) && hasScope(scope) } - private fun scopesWithout(scope: Scope) = Scope.expand(permission.scopes) - .toMutableList() - .also { it.remove(scope) } - .toTypedArray() + private fun scopesWithout(scope: Scope) = + Scope.expand(permission.scopes) + .toMutableList() + .also { it.remove(scope) } + .toTypedArray() private fun hasScope(scope: Scope) = permission.granular && permission.scopes.contains(scope) private fun hasPermissionType(type: ProjectPermissionType) = permission.type == type - private fun hasOnlyAccessToDeletedLanguage(languages: MutableSet) = languages.size == 1 && - languages.first().id == language.id + private fun hasOnlyAccessToDeletedLanguage(languages: MutableSet) = + languages.size == 1 && + languages.first().id == language.id val permissionService: PermissionService get() = applicationContext.getBean(PermissionService::class.java) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/security/MfaService.kt b/backend/data/src/main/kotlin/io/tolgee/service/security/MfaService.kt index 91ec636d92..20b7e69dd6 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/security/MfaService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/security/MfaService.kt @@ -22,11 +22,14 @@ class MfaService( private val totpGenerator: TimeBasedOneTimePasswordGenerator, private val userAccountService: UserAccountService, private val userCredentialsService: UserCredentialsService, - private val keyGenerator: KeyGenerator + private val keyGenerator: KeyGenerator, ) { private val base32 = Base32() - fun enableTotpFor(user: UserAccount, dto: UserTotpEnableRequestDto) { + fun enableTotpFor( + user: UserAccount, + dto: UserTotpEnableRequestDto, + ) { try { userCredentialsService.checkUserCredentials(user, dto.password) } catch (e: AuthenticationException) { @@ -46,7 +49,10 @@ class MfaService( userAccountService.enableMfaTotp(user, key) } - fun disableTotpFor(user: UserAccount, dto: UserTotpDisableRequestDto) { + fun disableTotpFor( + user: UserAccount, + dto: UserTotpDisableRequestDto, + ) { try { userCredentialsService.checkUserCredentials(user, dto.password) } catch (e: AuthenticationException) { @@ -61,7 +67,10 @@ class MfaService( userAccountService.disableMfaTotp(user) } - fun regenerateRecoveryCodes(user: UserAccount, dto: UserMfaRecoveryRequestDto): List { + fun regenerateRecoveryCodes( + user: UserAccount, + dto: UserMfaRecoveryRequestDto, + ): List { try { userCredentialsService.checkUserCredentials(user, dto.password) } catch (e: AuthenticationException) { @@ -73,10 +82,11 @@ class MfaService( throw BadRequestException(Message.MFA_NOT_ENABLED) } - val codes = List(10) { - val key = keyGenerator.generate() - "${key.substring(0, 4)}-${key.substring(4, 8)}-${key.substring(8, 12)}-${key.substring(12, 16)}" - } + val codes = + List(10) { + val key = keyGenerator.generate() + "${key.substring(0, 4)}-${key.substring(4, 8)}-${key.substring(8, 12)}-${key.substring(12, 16)}" + } userAccountService.setMfaRecoveryCodes(user, codes) return codes @@ -86,7 +96,10 @@ class MfaService( return user.totpKey?.isNotEmpty() == true } - fun checkMfa(user: UserAccount, otp: String?) { + fun checkMfa( + user: UserAccount, + otp: String?, + ) { if (!user.isMfaEnabled) { return } @@ -104,12 +117,18 @@ class MfaService( } } - fun validateTotpCode(user: UserAccount, code: String): Boolean { + fun validateTotpCode( + user: UserAccount, + code: String, + ): Boolean { if (user.totpKey?.isNotEmpty() != true) return true return validateTotpCode(user.totpKey!!, code) } - fun validateTotpCode(key: ByteArray, code: String): Boolean { + fun validateTotpCode( + key: ByteArray, + code: String, + ): Boolean { if (code.length != 6) return false return try { diff --git a/backend/data/src/main/kotlin/io/tolgee/service/security/PatService.kt b/backend/data/src/main/kotlin/io/tolgee/service/security/PatService.kt index e7c5473a18..73be875841 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/security/PatService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/security/PatService.kt @@ -65,32 +65,44 @@ class PatService( return keyGenerator.generate(256) } - fun create(dto: CreatePatDto, userAccount: UserAccount): Pat { - val pat = Pat().apply { - expiresAt = dto.expiresAt.epochToDate() - description = dto.description - this.userAccount = userAccount - } + fun create( + dto: CreatePatDto, + userAccount: UserAccount, + ): Pat { + val pat = + Pat().apply { + expiresAt = dto.expiresAt.epochToDate() + description = dto.description + this.userAccount = userAccount + } return save(pat) } - fun regenerate(id: Long, expiresAt: Long?): Pat { - val pat = get(id).apply { - // Manual cache eviction - cache?.evict(this.tokenHash) + fun regenerate( + id: Long, + expiresAt: Long?, + ): Pat { + val pat = + get(id).apply { + // Manual cache eviction + cache?.evict(this.tokenHash) - this.expiresAt = expiresAt.epochToDate() - this.regenerateToken() - save(this) - } + this.expiresAt = expiresAt.epochToDate() + this.regenerateToken() + save(this) + } return pat } - fun update(id: Long, updatePatDto: UpdatePatDto): Pat { + fun update( + id: Long, + updatePatDto: UpdatePatDto, + ): Pat { // Cache eviction: Not necessary, description is not cached - val pat = get(id).apply { - this.description = updatePatDto.description - } + val pat = + get(id).apply { + this.description = updatePatDto.description + } return save(pat) } @@ -103,7 +115,10 @@ class PatService( return patRepository.deleteById(pat.id) } - fun findAll(userId: Long, pageable: Pageable): Page { + fun findAll( + userId: Long, + pageable: Pageable, + ): Page { return patRepository.findAllByUserAccountId(userId, pageable) } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/security/PermissionService.kt b/backend/data/src/main/kotlin/io/tolgee/service/security/PermissionService.kt index 2ec387e1c6..6deb2ccaaa 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/security/PermissionService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/security/PermissionService.kt @@ -66,62 +66,84 @@ class PermissionService( return cachedPermissionService.find(id) } - fun getProjectPermissionScopes(projectId: Long, userAccount: UserAccount) = - getProjectPermissionScopes(projectId, userAccount.id) + fun getProjectPermissionScopes( + projectId: Long, + userAccount: UserAccount, + ) = getProjectPermissionScopes(projectId, userAccount.id) - fun getProjectPermissionScopes(projectId: Long, userAccountId: Long): Array? { + fun getProjectPermissionScopes( + projectId: Long, + userAccountId: Long, + ): Array? { return getProjectPermissionData(projectId, userAccountId).computedPermissions.expandedScopes } - fun getProjectPermissionData(project: ProjectDto, userAccountId: Long): ProjectPermissionData { + fun getProjectPermissionData( + project: ProjectDto, + userAccountId: Long, + ): ProjectPermissionData { val projectPermission = find(projectId = project.id, userId = userAccountId) - val organizationRole = project.organizationOwnerId - .let { organizationRoleService.findType(userAccountId, it) } + val organizationRole = + project.organizationOwnerId + .let { organizationRoleService.findType(userAccountId, it) } - val organizationBasePermission = find(organizationId = project.organizationOwnerId) - ?: throw IllegalStateException("Organization has no base permission") + val organizationBasePermission = + find(organizationId = project.organizationOwnerId) + ?: throw IllegalStateException("Organization has no base permission") - val computed = computeProjectPermission( - organizationRole = organizationRole, - organizationBasePermission = organizationBasePermission, - directPermission = projectPermission, - userAccountService.findDto(userAccountId)?.role ?: throw IllegalStateException("User not found") - ) + val computed = + computeProjectPermission( + organizationRole = organizationRole, + organizationBasePermission = organizationBasePermission, + directPermission = projectPermission, + userAccountService.findDto(userAccountId)?.role ?: throw IllegalStateException("User not found"), + ) return ProjectPermissionData( organizationRole = organizationRole, organizationBasePermissions = organizationBasePermission, computedPermissions = computed, - directPermissions = projectPermission + directPermissions = projectPermission, ) } - fun getPermittedTranslateLanguagesForUserIds(userIds: List, projectId: Long): Map> { + fun getPermittedTranslateLanguagesForUserIds( + userIds: List, + projectId: Long, + ): Map> { val data = permissionRepository.getUserPermittedLanguageIds(userIds, projectId) val result = mutableMapOf>() data.forEach { - val languageIds = result.computeIfAbsent(it[0]) { - mutableListOf() - } + val languageIds = + result.computeIfAbsent(it[0]) { + mutableListOf() + } languageIds.add(it[1]) } return result } - fun getPermittedTranslateLanguagesForProjectIds(projectIds: List, userId: Long): Map> { + fun getPermittedTranslateLanguagesForProjectIds( + projectIds: List, + userId: Long, + ): Map> { val data = permissionRepository.getProjectPermittedLanguageIds(projectIds, userId) val result = mutableMapOf>() data.forEach { - val languageIds = result.computeIfAbsent(it[0]) { - mutableListOf() - } + val languageIds = + result.computeIfAbsent(it[0]) { + mutableListOf() + } languageIds.add(it[1]) } return result } - fun getProjectPermissionData(projectId: Long, userAccountId: Long): ProjectPermissionData { + fun getProjectPermissionData( + projectId: Long, + userAccountId: Long, + ): ProjectPermissionData { val project = projectService.findDto(projectId) ?: throw NotFoundException() return getProjectPermissionData(project, userAccountId) } @@ -156,12 +178,16 @@ class PermissionService( } @Transactional - fun grantFullAccessToProject(userAccount: UserAccount, project: Project) { - val permission = Permission( - type = ProjectPermissionType.MANAGE, - project = project, - user = userAccount - ) + fun grantFullAccessToProject( + userAccount: UserAccount, + project: Project, + ) { + val permission = + Permission( + type = ProjectPermissionType.MANAGE, + project = project, + user = userAccount, + ) create(permission) } @@ -169,18 +195,20 @@ class PermissionService( organizationRole: OrganizationRoleType?, organizationBasePermission: IPermission, directPermission: IPermission?, - userRole: UserAccount.Role? = null + userRole: UserAccount.Role? = null, ): ComputedPermissionDto { - val computed = when { - organizationRole == OrganizationRoleType.OWNER -> ComputedPermissionDto.ORGANIZATION_OWNER - directPermission != null -> ComputedPermissionDto(directPermission, ComputedPermissionOrigin.DIRECT) - organizationRole == OrganizationRoleType.MEMBER -> ComputedPermissionDto( - organizationBasePermission, - ComputedPermissionOrigin.ORGANIZATION_BASE - ) - - else -> ComputedPermissionDto.NONE - } + val computed = + when { + organizationRole == OrganizationRoleType.OWNER -> ComputedPermissionDto.ORGANIZATION_OWNER + directPermission != null -> ComputedPermissionDto(directPermission, ComputedPermissionOrigin.DIRECT) + organizationRole == OrganizationRoleType.MEMBER -> + ComputedPermissionDto( + organizationBasePermission, + ComputedPermissionOrigin.ORGANIZATION_BASE, + ) + + else -> ComputedPermissionDto.NONE + } return userRole?.let { computed.getAdminPermissions(userRole) @@ -189,17 +217,18 @@ class PermissionService( fun createForInvitation( invitation: Invitation, - params: CreateProjectInvitationParams + params: CreateProjectInvitationParams, ): Permission { val type = params.type ?: throw IllegalStateException("Permission type cannot be null") validateLanguagePermissions(params.languagePermissions, type) - val permission = Permission( - invitation = invitation, - project = params.project, - type = type - ) + val permission = + Permission( + invitation = invitation, + project = params.project, + type = type, + ) setPermissionLanguages(permission, params.languagePermissions, params.project.id) @@ -207,11 +236,18 @@ class PermissionService( } @Transactional - fun find(projectId: Long? = null, userId: Long? = null, organizationId: Long? = null): PermissionDto? { + fun find( + projectId: Long? = null, + userId: Long? = null, + organizationId: Long? = null, + ): PermissionDto? { return cachedPermissionService.find(projectId = projectId, userId = userId, organizationId = organizationId) } - fun acceptInvitation(permission: Permission, userAccount: UserAccount): Permission { + fun acceptInvitation( + permission: Permission, + userAccount: UserAccount, + ): Permission { // switch user to the organization when accepted invitation userPreferencesService.setPreferredOrganization(permission.project!!.organizationOwner, userAccount) return cachedPermissionService.acceptInvitation(permission, userAccount) @@ -221,11 +257,11 @@ class PermissionService( projectId: Long, userId: Long, newPermissionType: ProjectPermissionType, - languages: LanguagePermissions + languages: LanguagePermissions, ): Permission? { validateLanguagePermissions( languagePermissions = languages, - newPermissionType = newPermissionType + newPermissionType = newPermissionType, ) val permission = getOrCreateDirectPermission(projectId, userId) @@ -240,7 +276,7 @@ class PermissionService( fun getOrCreateDirectPermission( projectId: Long, - userId: Long + userId: Long, ): Permission { val data = this.getProjectPermissionData(projectId, userId) @@ -252,11 +288,12 @@ class PermissionService( } } - val permission = data.directPermissions?.let { findById(it.id) } ?: let { - val userAccount = userAccountService.get(userId) - val project = projectService.get(projectId) - Permission(user = userAccount, project = project) - } + val permission = + data.directPermissions?.let { findById(it.id) } ?: let { + val userAccount = userAccountService.get(userId) + val project = projectService.get(projectId) + Permission(user = userAccount, project = project) + } return permission } @@ -280,7 +317,7 @@ class PermissionService( fun setPermissionLanguages( permission: Permission, languagePermissions: LanguagePermissions, - projectId: Long + projectId: Long, ) { permission.translateLanguages = languagePermissions.translate.standardize() permission.stateChangeLanguages = languagePermissions.stateChange.standardize() @@ -294,7 +331,7 @@ class PermissionService( private fun validateLanguagePermissions( languagePermissions: LanguagePermissions, - newPermissionType: ProjectPermissionType + newPermissionType: ProjectPermissionType, ) { val isTranslate = newPermissionType == ProjectPermissionType.TRANSLATE val isReview = newPermissionType == ProjectPermissionType.REVIEW @@ -316,11 +353,12 @@ class PermissionService( } if (isReview && (hasTranslateLanguages || hasStateChangeLanguages)) { - val equal = languagePermissions.stateChange?.size == languagePermissions.translate?.size && - languagePermissions.stateChange?.containsAll(languagePermissions.translate ?: emptyList()) ?: false + val equal = + languagePermissions.stateChange?.size == languagePermissions.translate?.size && + languagePermissions.stateChange?.containsAll(languagePermissions.translate ?: emptyList()) ?: false if (!equal) { throw BadRequestException( - Message.CANNOT_SET_DIFFERENT_TRANSLATE_AND_STATE_CHANGE_LANGUAGES_FOR_LEVEL_BASED_PERMISSIONS + Message.CANNOT_SET_DIFFERENT_TRANSLATE_AND_STATE_CHANGE_LANGUAGES_FOR_LEVEL_BASED_PERMISSIONS, ) } } @@ -334,7 +372,10 @@ class PermissionService( return cachedPermissionService.save(permission) } - fun revoke(projectId: Long, userId: Long) { + fun revoke( + projectId: Long, + userId: Long, + ) { val data = this.getProjectPermissionData(projectId, userId) if (data.organizationRole != null) { throw BadRequestException(Message.USER_IS_ORGANIZATION_MEMBER) @@ -357,48 +398,64 @@ class PermissionService( } @Transactional - fun leave(project: Project, userId: Long) { + fun leave( + project: Project, + userId: Long, + ) { val permissionData = this.getProjectPermissionData(project.id, userId) if (permissionData.organizationRole != null) { throw BadRequestException(Message.CANNOT_LEAVE_PROJECT_WITH_ORGANIZATION_ROLE) } - val directPermissions = permissionData.directPermissions - ?: throw BadRequestException(Message.DONT_HAVE_DIRECT_PERMISSIONS) + val directPermissions = + permissionData.directPermissions + ?: throw BadRequestException(Message.DONT_HAVE_DIRECT_PERMISSIONS) - val permissionEntity = this.findById(directPermissions.id) - ?: throw NotFoundException() + val permissionEntity = + this.findById(directPermissions.id) + ?: throw NotFoundException() this.delete(permissionEntity) } - fun getPermittedViewLanguages(projectId: Long, userId: Long): Collection { + fun getPermittedViewLanguages( + projectId: Long, + userId: Long, + ): Collection { val permissionData = this.getProjectPermissionData(projectId, userId) val allLanguages = languageService.findAll(projectId) val viewLanguageIds = permissionData.computedPermissions.viewLanguageIds - val permittedLanguages = if (viewLanguageIds.isNullOrEmpty()) - allLanguages - else - allLanguages.filter { - viewLanguageIds.contains( - it.id - ) + val permittedLanguages = + if (viewLanguageIds.isNullOrEmpty()) { + allLanguages + } else { + allLanguages.filter { + viewLanguageIds.contains( + it.id, + ) + } } return permittedLanguages } @Transactional - fun setOrganizationBasePermissions(projectId: Long, userId: Long) { + fun setOrganizationBasePermissions( + projectId: Long, + userId: Long, + ) { val project = projectService.get(projectId) organizationRoleService.checkUserIsMemberOrOwner(userId, project.organizationOwner.id) val permission = getProjectPermissionData(projectId, userId).directPermissions ?: return delete(permission.id) } - fun removeAllProjectInOrganization(organizationId: Long, userId: Long): List { + fun removeAllProjectInOrganization( + organizationId: Long, + userId: Long, + ): List { val permissions = permissionRepository.findAllByOrganizationAndUserId(organizationId, userId) permissions.forEach { delete(it) } return permissions diff --git a/backend/data/src/main/kotlin/io/tolgee/service/security/ReCaptchaValidationService.kt b/backend/data/src/main/kotlin/io/tolgee/service/security/ReCaptchaValidationService.kt index ab1ce3afc2..d3379287c2 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/security/ReCaptchaValidationService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/security/ReCaptchaValidationService.kt @@ -17,7 +17,10 @@ class ReCaptchaValidationService( private val tolgeeProperties: TolgeeProperties, private val restTemplate: RestTemplate, ) { - fun validate(token: String?, ip: String): Boolean { + fun validate( + token: String?, + ip: String, + ): Boolean { if (tolgeeProperties.recaptcha.secretKey == null || // for e2e testing purposes tolgeeProperties.recaptcha.secretKey == "dummy_secret_key" @@ -41,10 +44,11 @@ class ReCaptchaValidationService( requestBody.add("secret", tolgeeProperties.recaptcha.secretKey) requestBody.add("response", token) - val response = restTemplate.postForEntity( - "https://www.google.com/recaptcha/api/siteverify", - requestBody - ) + val response = + restTemplate.postForEntity( + "https://www.google.com/recaptcha/api/siteverify", + requestBody, + ) return response.body?.success ?: throw UnexpectedGoogleApiResponseException(response) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/security/SecurityService.kt b/backend/data/src/main/kotlin/io/tolgee/service/security/SecurityService.kt index f0243529f6..dfb984d162 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/security/SecurityService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/security/SecurityService.kt @@ -23,9 +23,8 @@ import java.io.Serializable class SecurityService( private val authenticationFacade: AuthenticationFacade, private val languageService: LanguageService, - private val keyRepository: KeyRepository + private val keyRepository: KeyRepository, ) { - @set:Autowired lateinit var apiKeyService: ApiKeyService @@ -39,46 +38,58 @@ class SecurityService( if ( getProjectPermissionScopes(projectId).isNullOrEmpty() && !isCurrentUserServerAdmin() - ) + ) { throw PermissionException() + } } - fun checkProjectPermission(projectId: Long, requiredScopes: Scope, apiKey: ApiKeyDto) { + fun checkProjectPermission( + projectId: Long, + requiredScopes: Scope, + apiKey: ApiKeyDto, + ) { checkProjectPermission(listOf(requiredScopes), apiKey) } - private fun checkProjectPermission(requiredScopes: List, apiKey: ApiKeyDto) { + private fun checkProjectPermission( + requiredScopes: List, + apiKey: ApiKeyDto, + ) { this.checkApiKeyScopes(requiredScopes, apiKey) } fun checkProjectPermissionNoApiKey( projectId: Long, requiredScope: Scope, - userAccountDto: UserAccountDto + userAccountDto: UserAccountDto, ) { if (isUserAdmin(userAccountDto)) { return } - val allowedScopes = getProjectPermissionScopes(projectId, userAccountDto.id) - ?: throw PermissionException(Message.USER_HAS_NO_PROJECT_ACCESS) + val allowedScopes = + getProjectPermissionScopes(projectId, userAccountDto.id) + ?: throw PermissionException(Message.USER_HAS_NO_PROJECT_ACCESS) checkPermission(requiredScope, allowedScopes) } private fun checkPermission( requiredScope: Scope, - allowedScopes: Array + allowedScopes: Array, ) { if (!allowedScopes.contains(requiredScope)) { throw PermissionException( Message.OPERATION_NOT_PERMITTED, - listOf(requiredScope.value) as List + listOf(requiredScope.value) as List, ) } } - fun checkProjectPermission(projectId: Long, requiredPermission: Scope) { + fun checkProjectPermission( + projectId: Long, + requiredPermission: Scope, + ) { // Always check for the current user even if we're using an API key for security reasons. // This prevents improper preservation of permissions. checkProjectPermissionNoApiKey(projectId, requiredPermission, activeUser) @@ -87,52 +98,73 @@ class SecurityService( checkProjectPermission(projectId, requiredPermission, apiKey) } - fun checkLanguageViewPermissionByTag(projectId: Long, languageTags: Collection) { + fun checkLanguageViewPermissionByTag( + projectId: Long, + languageTags: Collection, + ) { checkProjectPermission(projectId, Scope.TRANSLATIONS_VIEW) checkLanguagePermissionByTag( projectId, - languageTags + languageTags, ) { data, languageIds -> data.checkViewPermitted(*languageIds.toLongArray()) } } - fun checkLanguageTranslatePermissionByTag(projectId: Long, languageTags: Collection) { + fun checkLanguageTranslatePermissionByTag( + projectId: Long, + languageTags: Collection, + ) { checkProjectPermission(projectId, Scope.TRANSLATIONS_EDIT) checkLanguagePermissionByTag( projectId, - languageTags + languageTags, ) { data, languageIds -> data.checkTranslatePermitted(*languageIds.toLongArray()) } } - fun checkStateEditPermissionByTag(projectId: Long, languageTags: Collection) { + fun checkStateEditPermissionByTag( + projectId: Long, + languageTags: Collection, + ) { checkProjectPermission(projectId, Scope.TRANSLATIONS_STATE_EDIT) checkLanguagePermissionByTag( projectId, - languageTags + languageTags, ) { data, languageIds -> data.checkTranslatePermitted(*languageIds.toLongArray()) } } - fun checkLanguageViewPermission(projectId: Long, languageIds: Collection) { + fun checkLanguageViewPermission( + projectId: Long, + languageIds: Collection, + ) { checkProjectPermission(projectId, Scope.TRANSLATIONS_VIEW) checkLanguagePermission( projectId, ) { data -> data.checkViewPermitted(*languageIds.toLongArray()) } } - fun checkLanguageTranslatePermission(projectId: Long, languageIds: Collection) { + fun checkLanguageTranslatePermission( + projectId: Long, + languageIds: Collection, + ) { checkProjectPermission(projectId, Scope.TRANSLATIONS_EDIT) checkLanguagePermission( projectId, ) { data -> data.checkTranslatePermitted(*languageIds.toLongArray()) } } - fun checkLanguageStateChangePermission(projectId: Long, languageIds: Collection) { + fun checkLanguageStateChangePermission( + projectId: Long, + languageIds: Collection, + ) { checkProjectPermission(projectId, Scope.TRANSLATIONS_STATE_EDIT) checkLanguagePermission( projectId, ) { data -> data.checkStateChangePermitted(*languageIds.toLongArray()) } } - fun filterViewPermissionByTag(projectId: Long, languageTags: Collection): Set { + fun filterViewPermissionByTag( + projectId: Long, + languageTags: Collection, + ): Set { try { checkLanguageViewPermissionByTag(projectId, languageTags) } catch (e: LanguageNotPermittedException) { @@ -143,34 +175,36 @@ class SecurityService( private fun checkLanguagePermission( projectId: Long, - permissionCheckFn: (data: ComputedPermissionDto) -> Unit + permissionCheckFn: (data: ComputedPermissionDto) -> Unit, ) { if (isCurrentUserServerAdmin()) { return } - val usersPermission = permissionService.getProjectPermissionData( - projectId, - authenticationFacade.authenticatedUser.id - ) + val usersPermission = + permissionService.getProjectPermissionData( + projectId, + authenticationFacade.authenticatedUser.id, + ) permissionCheckFn(usersPermission.computedPermissions) } private fun checkLanguagePermissionByTag( projectId: Long, languageTags: Collection, - fn: (data: ComputedPermissionDto, languageIds: Collection) -> Unit + fn: (data: ComputedPermissionDto, languageIds: Collection) -> Unit, ) { val languageIds = languageService.getLanguageIdsByTags(projectId, languageTags) try { - val usersPermission = permissionService.getProjectPermissionData( - projectId, - authenticationFacade.authenticatedUser.id - ) + val usersPermission = + permissionService.getProjectPermissionData( + projectId, + authenticationFacade.authenticatedUser.id, + ) fn(usersPermission.computedPermissions, languageIds.values.map { it.id }) } catch (e: LanguageNotPermittedException) { throw LanguageNotPermittedException( e.languageIds, - e.languageIds.mapNotNull { languageId -> languageIds.entries.find { it.value.id == languageId }?.key } + e.languageIds.mapNotNull { languageId -> languageIds.entries.find { it.value.id == languageId }?.key }, ) } } @@ -185,25 +219,41 @@ class SecurityService( checkLanguageStateChangePermission(language.project.id, listOf(language.id)) } - fun checkLanguageTranslatePermissionsByTag(tags: Set, projectId: Long) { + fun checkLanguageTranslatePermissionsByTag( + tags: Set, + projectId: Long, + ) { val languages = languageService.findByTags(tags, projectId) this.checkLanguageTranslatePermission(projectId, languages.map { it.id }) } - fun checkLanguageTranslatePermissionsByLanguageId(languageIds: Collection, projectId: Long) { + fun checkLanguageTranslatePermissionsByLanguageId( + languageIds: Collection, + projectId: Long, + ) { this.checkLanguageTranslatePermission(projectId, languageIds) } - fun checkLanguageStateChangePermissionsByTag(projectId: Long, tags: Collection) { + fun checkLanguageStateChangePermissionsByTag( + projectId: Long, + tags: Collection, + ) { val languages = languageService.findByTags(tags, projectId) this.checkLanguageStateChangePermission(projectId, languages.map { it.id }) } - fun checkLanguageChangeStatePermissionsByLanguageId(languageIds: Collection, projectId: Long) { + fun checkLanguageChangeStatePermissionsByLanguageId( + languageIds: Collection, + projectId: Long, + ) { this.checkLanguageStateChangePermission(projectId, languageIds) } - fun checkApiKeyScopes(scopes: Set, project: Project?, user: UserAccount? = null) { + fun checkApiKeyScopes( + scopes: Set, + project: Project?, + user: UserAccount? = null, + ) { try { val availableScopes = apiKeyService.getAvailableScopes(user?.id ?: activeUser.id, project!!) val userCanSelectTheScopes = availableScopes.toList().containsAll(scopes) @@ -224,7 +274,7 @@ class SecurityService( apiKey.scopesEnum.removeIf { getProjectPermissionScopes( apiKey.project.id, - apiKey.userAccount.id + apiKey.userAccount.id, )?.contains(it) != true } if (oldSize != apiKey.scopesEnum.size) { @@ -232,7 +282,10 @@ class SecurityService( } } - fun checkApiKeyScopes(scopes: Set, apiKey: ApiKeyDto) { + fun checkApiKeyScopes( + scopes: Set, + apiKey: ApiKeyDto, + ) { checkApiKeyScopes(apiKey) { expandedScopes -> if (!expandedScopes.toList().containsAll(scopes)) { throw PermissionException() @@ -240,7 +293,10 @@ class SecurityService( } } - fun checkApiKeyScopes(scopes: Collection, apiKey: ApiKeyDto) { + fun checkApiKeyScopes( + scopes: Collection, + apiKey: ApiKeyDto, + ) { checkApiKeyScopes(apiKey) { expandedScopes -> val hasRequiredPermission = scopes.all { expandedScopes.contains(it) } if (!hasRequiredPermission) { @@ -249,7 +305,10 @@ class SecurityService( } } - private fun checkApiKeyScopes(apiKey: ApiKeyDto, checkFn: (expandedScopes: Array) -> Unit) { + private fun checkApiKeyScopes( + apiKey: ApiKeyDto, + checkFn: (expandedScopes: Array) -> Unit, + ) { val expandedScopes = Scope.expand(apiKey.scopes) checkFn(expandedScopes) } @@ -267,11 +326,17 @@ class SecurityService( } } - fun getProjectPermissionScopes(projectId: Long, userId: Long = activeUser.id): Array? { + fun getProjectPermissionScopes( + projectId: Long, + userId: Long = activeUser.id, + ): Array? { return permissionService.getProjectPermissionScopes(projectId, userId) } - fun checkKeyIdsExistAndIsFromProject(keyIds: List, projectId: Long) { + fun checkKeyIdsExistAndIsFromProject( + keyIds: List, + projectId: Long, + ) { val projectIds = keyRepository.getProjectIdsForKeyIds(keyIds) if (projectIds.size != keyIds.size) { diff --git a/backend/data/src/main/kotlin/io/tolgee/service/security/SignUpService.kt b/backend/data/src/main/kotlin/io/tolgee/service/security/SignUpService.kt index d5181d8d06..3430f3d367 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/security/SignUpService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/security/SignUpService.kt @@ -26,7 +26,7 @@ class SignUpService( private val emailVerificationService: EmailVerificationService, private val organizationService: OrganizationService, private val quickStartService: QuickStartService, - private val passwordEncoder: PasswordEncoder + private val passwordEncoder: PasswordEncoder, ) { @Transactional fun signUp(dto: SignUpDto): JwtAuthenticationResponse? { @@ -46,7 +46,11 @@ class SignUpService( return null } - fun signUp(entity: UserAccount, invitationCode: String?, organizationName: String?): UserAccount { + fun signUp( + entity: UserAccount, + invitationCode: String?, + organizationName: String?, + ): UserAccount { val invitation = findAndCheckInvitationOnRegistration(invitationCode) val user = userAccountService.createUser(entity) if (invitation != null) { diff --git a/backend/data/src/main/kotlin/io/tolgee/service/security/UserAccountService.kt b/backend/data/src/main/kotlin/io/tolgee/service/security/UserAccountService.kt index 09e55cf3bc..02ff39979a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/security/UserAccountService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/security/UserAccountService.kt @@ -52,7 +52,7 @@ class UserAccountService( private val organizationService: OrganizationService, private val entityManager: EntityManager, private val currentDateProvider: CurrentDateProvider, - private val cacheManager: CacheManager + private val cacheManager: CacheManager, ) : Logging { @Autowired lateinit var emailVerificationService: EmailVerificationService @@ -99,7 +99,10 @@ class UserAccountService( } @Transactional - fun createUser(userAccount: UserAccount, rawPassword: String): UserAccount { + fun createUser( + userAccount: UserAccount, + rawPassword: String, + ): UserAccount { userAccountRepository.saveAndFlush(userAccount) userAccount.password = passwordEncoder.encode(rawPassword) applicationEventPublisher.publishEvent(OnUserCreated(this, userAccount)) @@ -164,34 +167,49 @@ class UserAccountService( } } - fun findByThirdParty(type: String, id: String): Optional { + fun findByThirdParty( + type: String, + id: String, + ): Optional { return userAccountRepository.findThirdByThirdParty(id, type) } @Transactional @CacheEvict(cacheNames = [Caches.USER_ACCOUNTS], key = "#result.id") - fun setAccountType(userAccount: UserAccount, accountType: UserAccount.AccountType): UserAccount { + fun setAccountType( + userAccount: UserAccount, + accountType: UserAccount.AccountType, + ): UserAccount { userAccount.accountType = accountType return userAccountRepository.save(userAccount) } @Transactional @CacheEvict(cacheNames = [Caches.USER_ACCOUNTS], key = "#result.id") - fun setResetPasswordCode(userAccount: UserAccount, code: String?): UserAccount { + fun setResetPasswordCode( + userAccount: UserAccount, + code: String?, + ): UserAccount { userAccount.resetPasswordCode = passwordEncoder.encode(code) return userAccountRepository.save(userAccount) } @Transactional @CacheEvict(cacheNames = [Caches.USER_ACCOUNTS], key = "#result.id") - fun setUserPassword(userAccount: UserAccount, password: String?): UserAccount { + fun setUserPassword( + userAccount: UserAccount, + password: String?, + ): UserAccount { userAccount.tokensValidNotBefore = DateUtils.truncate(Date(), Calendar.SECOND) userAccount.password = passwordEncoder.encode(password) return userAccountRepository.save(userAccount) } @Transactional - fun isResetCodeValid(userAccount: UserAccount, code: String?): Boolean { + fun isResetCodeValid( + userAccount: UserAccount, + code: String?, + ): Boolean { return passwordEncoder.matches(code, userAccount.resetPasswordCode) } @@ -204,7 +222,10 @@ class UserAccountService( @Transactional @CacheEvict(cacheNames = [Caches.USER_ACCOUNTS], key = "#result.id") - fun enableMfaTotp(userAccount: UserAccount, key: ByteArray): UserAccount { + fun enableMfaTotp( + userAccount: UserAccount, + key: ByteArray, + ): UserAccount { userAccount.totpKey = key userAccount.tokensValidNotBefore = DateUtils.truncate(Date(), Calendar.SECOND) return userAccountRepository.save(userAccount) @@ -222,7 +243,10 @@ class UserAccountService( @Transactional @CacheEvict(cacheNames = [Caches.USER_ACCOUNTS], key = "#result.id") - fun consumeMfaRecoveryCode(userAccount: UserAccount, token: String): UserAccount { + fun consumeMfaRecoveryCode( + userAccount: UserAccount, + token: String, + ): UserAccount { if (!userAccount.mfaRecoveryCodes.contains(token)) { throw AuthenticationException(Message.INVALID_OTP_CODE) } @@ -233,7 +257,10 @@ class UserAccountService( @Transactional @CacheEvict(cacheNames = [Caches.USER_ACCOUNTS], key = "#result.id") - fun setMfaRecoveryCodes(userAccount: UserAccount, codes: List): UserAccount { + fun setMfaRecoveryCodes( + userAccount: UserAccount, + codes: List, + ): UserAccount { userAccount.mfaRecoveryCodes = codes return userAccountRepository.save(userAccount) } @@ -246,14 +273,17 @@ class UserAccountService( @Transactional @CacheEvict(cacheNames = [Caches.USER_ACCOUNTS], key = "#userAccount.id") - fun setAvatar(userAccount: UserAccount, avatar: InputStream) { + fun setAvatar( + userAccount: UserAccount, + avatar: InputStream, + ) { avatarService.setAvatar(userAccount, avatar) } fun getAllInOrganization( organizationId: Long, pageable: Pageable, - search: String? + search: String?, ): Page { return userAccountRepository.getAllInOrganization(organizationId, pageable, search = search ?: "") } @@ -262,7 +292,7 @@ class UserAccountService( projectId: Long, pageable: Pageable, search: String?, - exceptUserId: Long? = null + exceptUserId: Long? = null, ): Page { return userAccountRepository.getAllInProject(projectId, pageable, search = search, exceptUserId) } @@ -271,15 +301,16 @@ class UserAccountService( projectId: Long, pageable: Pageable, search: String?, - exceptUserId: Long? = null + exceptUserId: Long? = null, ): Page { val users = getAllInProject(projectId, pageable, search, exceptUserId) val organizationBasePermission = organizationService.getProjectOwner(projectId = projectId).basePermission - val permittedLanguageMap = permissionService.getPermittedTranslateLanguagesForUserIds( - users.content.map { it.id }, - projectId - ) + val permittedLanguageMap = + permissionService.getPermittedTranslateLanguagesForUserIds( + users.content.map { it.id }, + projectId, + ) return users.map { ExtendedUserAccountInProject( id = it.id, @@ -289,14 +320,17 @@ class UserAccountService( directPermission = it.directPermission, organizationBasePermission = organizationBasePermission, permittedLanguageIds = permittedLanguageMap[it.id], - avatarHash = it.avatarHash + avatarHash = it.avatarHash, ) } } @Transactional @CacheEvict(cacheNames = [Caches.USER_ACCOUNTS], key = "#result.id") - fun update(userAccount: UserAccount, dto: UserUpdateRequestDto): UserAccount { + fun update( + userAccount: UserAccount, + dto: UserUpdateRequestDto, + ): UserAccount { // Current password required to change email or password if (dto.email != userAccount.username) { if (userAccount.accountType == UserAccount.AccountType.MANAGED) { @@ -317,7 +351,10 @@ class UserAccountService( } @CacheEvict(cacheNames = [Caches.USER_ACCOUNTS], key = "#result.id") - fun updatePassword(userAccount: UserAccount, dto: UserUpdatePasswordRequestDto): UserAccount { + fun updatePassword( + userAccount: UserAccount, + dto: UserUpdatePasswordRequestDto, + ): UserAccount { if (userAccount.accountType == UserAccount.AccountType.MANAGED) { throw BadRequestException(Message.OPERATION_UNAVAILABLE_FOR_ACCOUNT_TYPE) } @@ -333,7 +370,7 @@ class UserAccountService( private fun updateUserEmail( userAccount: UserAccount, - dto: UserUpdateRequestDto + dto: UserUpdateRequestDto, ) { if (userAccount.username != dto.email) { if (!emailValidator.isValid(dto.email, null)) { @@ -352,7 +389,7 @@ class UserAccountService( private fun publishUserInfoUpdatedEvent( old: UserAccountDto, - userAccount: UserAccount + userAccount: UserAccount, ) { val event = OnUserUpdated(this, old, UserAccountDto.fromEntity(userAccount)) applicationEventPublisher.publishEvent(event) @@ -375,7 +412,10 @@ class UserAccountService( return userAccountRepository.getAllByIdsIncludingDeleted(ids) } - fun findAllWithDisabledPaged(pageable: Pageable, search: String?): Page { + fun findAllWithDisabledPaged( + pageable: Pageable, + search: String?, + ): Page { return userAccountRepository.findAllWithDisabledPaged(search, pageable) } @@ -406,8 +446,9 @@ class UserAccountService( } fun transferLegacyNoAuthUser() { - val legacyImplicitUser = findActive("___implicit_user") - ?: return + val legacyImplicitUser = + findActive("___implicit_user") + ?: return // We need to migrate what's owned by `___implicit_user` to the initial user val initialUser = findInitialUser() ?: throw IllegalStateException("Initial user does not exist?") diff --git a/backend/data/src/main/kotlin/io/tolgee/service/security/UserCredentialsService.kt b/backend/data/src/main/kotlin/io/tolgee/service/security/UserCredentialsService.kt index c3752ca333..678938895e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/security/UserCredentialsService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/security/UserCredentialsService.kt @@ -14,22 +14,33 @@ class UserCredentialsService( @set:Autowired lateinit var userAccountService: UserAccountService - fun checkUserCredentials(username: String, password: String): UserAccount { - val userAccount = userAccountService.findActive(username) - ?: throw AuthenticationException(Message.BAD_CREDENTIALS) + fun checkUserCredentials( + username: String, + password: String, + ): UserAccount { + val userAccount = + userAccountService.findActive(username) + ?: throw AuthenticationException(Message.BAD_CREDENTIALS) - if (userAccount.accountType == UserAccount.AccountType.MANAGED) + if (userAccount.accountType == UserAccount.AccountType.MANAGED) { throw AuthenticationException(Message.OPERATION_UNAVAILABLE_FOR_ACCOUNT_TYPE) + } checkNativeUserCredentials(userAccount, password) return userAccount } - fun checkUserCredentials(user: UserAccount, password: String) { + fun checkUserCredentials( + user: UserAccount, + password: String, + ) { checkNativeUserCredentials(user, password) } - private fun checkNativeUserCredentials(user: UserAccount, password: String) { + private fun checkNativeUserCredentials( + user: UserAccount, + password: String, + ) { if (!passwordEncoder.matches(password, user.password)) { throw AuthenticationException(Message.BAD_CREDENTIALS) } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/security/UserPreferencesService.kt b/backend/data/src/main/kotlin/io/tolgee/service/security/UserPreferencesService.kt index ad7b6b1599..1af31a92e4 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/security/UserPreferencesService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/security/UserPreferencesService.kt @@ -18,7 +18,10 @@ class UserPreferencesService( private val organizationService: OrganizationService, private val organizationRoleService: OrganizationRoleService, ) { - fun setLanguage(tag: String, userAccount: UserAccount) { + fun setLanguage( + tag: String, + userAccount: UserAccount, + ) { val preferences = findOrCreate(userAccount.id) preferences.language = tag userPreferencesRepository.save(preferences) @@ -26,7 +29,7 @@ class UserPreferencesService( fun setPreferredOrganization( organization: Organization, - userAccount: UserAccount + userAccount: UserAccount, ) { val preferences = find(userAccount.id) ?: create(userAccount, organization) preferences.preferredOrganization = organization @@ -40,11 +43,15 @@ class UserPreferencesService( } } - private fun create(userAccount: UserAccount, preferredOrganization: Organization? = null): UserPreferences { - val preferences = UserPreferences( - userAccount = userAccount, - preferredOrganization = preferredOrganization ?: organizationService.findOrCreatePreferred(userAccount) - ) + private fun create( + userAccount: UserAccount, + preferredOrganization: Organization? = null, + ): UserPreferences { + val preferences = + UserPreferences( + userAccount = userAccount, + preferredOrganization = preferredOrganization ?: organizationService.findOrCreatePreferred(userAccount), + ) return save(preferences) } @@ -68,17 +75,19 @@ class UserPreferencesService( * Sets different organization as preferred if user has no access to the current one */ fun refreshPreferredOrganization(preferences: UserPreferences): Organization? { - val canUserView = preferences.preferredOrganization?.let { po -> - organizationRoleService.canUserView( - preferences.userAccount.id, - po.id - ) - } ?: false + val canUserView = + preferences.preferredOrganization?.let { po -> + organizationRoleService.canUserView( + preferences.userAccount.id, + po.id, + ) + } ?: false if (!canUserView) { - preferences.preferredOrganization = organizationService.findOrCreatePreferred( - userAccount = preferences.userAccount - ) + preferences.preferredOrganization = + organizationService.findOrCreatePreferred( + userAccount = preferences.userAccount, + ) save(preferences) } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/translation/AutoTranslationService.kt b/backend/data/src/main/kotlin/io/tolgee/service/translation/AutoTranslationService.kt index 5fa2fae753..7156567ffa 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/translation/AutoTranslationService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/translation/AutoTranslationService.kt @@ -34,17 +34,21 @@ class AutoTranslationService( private val batchJobService: BatchJobService, private val authenticationFacade: AuthenticationFacade, private val entityManager: EntityManager, - private val transactionManager: PlatformTransactionManager + private val transactionManager: PlatformTransactionManager, ) { val logger: Logger = LoggerFactory.getLogger(this::class.java) - fun autoTranslateViaBatchJob(project: Project, request: AutoTranslationRequest, isHiddenJob: Boolean) { + fun autoTranslateViaBatchJob( + project: Project, + request: AutoTranslationRequest, + isHiddenJob: Boolean, + ) { batchJobService.startJob( request, project, authenticationFacade.authenticatedUserEntity, BatchJobType.AUTO_TRANSLATE, - isHiddenJob + isHiddenJob, ) } @@ -60,19 +64,21 @@ class AutoTranslationService( val project = entityManager.getReference(Project::class.java, projectId) val languageIds = languageService.findAll(projectId).map { it.id }.filter { it != baseLanguageId } val configs = this.getConfigs(project, languageIds) - val request = AutoTranslationRequest().apply { - target = languageIds.flatMap { languageId -> - if (configs[languageId]?.usingTm == false && configs[languageId]?.usingPrimaryMtService == false) { - return@flatMap listOf() - } - keyIds.map { keyId -> - BatchTranslationTargetItem( - keyId = keyId, - languageId = languageId, - ) - } + val request = + AutoTranslationRequest().apply { + target = + languageIds.flatMap { languageId -> + if (configs[languageId]?.usingTm == false && configs[languageId]?.usingPrimaryMtService == false) { + return@flatMap listOf() + } + keyIds.map { keyId -> + BatchTranslationTargetItem( + keyId = keyId, + languageId = languageId, + ) + } + } } - } autoTranslateViaBatchJob(project, request, isHiddenJob) } @@ -82,7 +88,7 @@ class AutoTranslationService( fun softAutoTranslate( projectId: Long, keyId: Long, - languageId: Long + languageId: Long, ) { val config = getConfig(entityManager.getReference(Project::class.java, projectId), languageId) val translation = @@ -91,8 +97,9 @@ class AutoTranslationService( language = entityManager.getReference(Language::class.java, languageId) } - val shouldTranslate = translation.state != TranslationState.DISABLED && ( - translation.auto || translation.state == TranslationState.UNTRANSLATED || translation.text.isNullOrEmpty() + val shouldTranslate = + translation.state != TranslationState.DISABLED && ( + translation.auto || translation.state == TranslationState.UNTRANSLATED || translation.text.isNullOrEmpty() ) if (!shouldTranslate) { @@ -107,14 +114,14 @@ class AutoTranslationService( private fun getAutoTranslatedValue( config: AutoTranslationConfig, - translation: Translation + translation: Translation, ): Pair? { - if (config.usingTm) { - val value = translationMemoryService.getAutoTranslatedValue( - translation.key, - translation.language - )?.targetTranslationText + val value = + translationMemoryService.getAutoTranslatedValue( + translation.key, + translation.language, + )?.targetTranslationText if (!value.isNullOrBlank()) { return value to null @@ -122,8 +129,9 @@ class AutoTranslationService( } if (config.usingPrimaryMtService) { - val result = mtService.getPrimaryMachineTranslations(translation.key, listOf(translation.language), true) - .singleOrNull() + val result = + mtService.getPrimaryMachineTranslations(translation.key, listOf(translation.language), true) + .singleOrNull() return result?.let { it.translatedText to it.usedService } } @@ -154,15 +162,16 @@ class AutoTranslationService( ) { val adjustedConfigs = getAdjustedConfigs(key, forcedLanguageTags, useTranslationMemory, useMachineTranslation) - val translations = adjustedConfigs.map { - if (it.override) { - return@map it to translationService.getOrCreate(key, it.language) - } + val translations = + adjustedConfigs.map { + if (it.override) { + return@map it to translationService.getOrCreate(key, it.language) + } - it to getUntranslatedTranslations(key, listOf(it.language)).firstOrNull() - }.filter { - it.second?.state != TranslationState.DISABLED - } + it to getUntranslatedTranslations(key, listOf(it.language)).firstOrNull() + }.filter { + it.second?.state != TranslationState.DISABLED + } val toTmTranslate = translations.filter { it.first.usingTm }.mapNotNull { it.second } @@ -182,7 +191,7 @@ class AutoTranslationService( key: Key, forcedLanguageTags: List?, useTranslationMemory: Boolean?, - useMachineTranslation: Boolean? + useMachineTranslation: Boolean?, ) = getPerLanguageConfigs(key.project).mapNotNull { if (forcedLanguageTags != null) { // if we got languages provided, we want to override the existing language values @@ -218,13 +227,13 @@ class AutoTranslationService( val language: Language, var usingTm: Boolean, var usingPrimaryMtService: Boolean, - var override: Boolean = false + var override: Boolean = false, ) private fun autoTranslateUsingMachineTranslation( translations: List, key: Key, - isBatch: Boolean + isBatch: Boolean, ) { val languages = translations.map { it.language } @@ -258,7 +267,10 @@ class AutoTranslationService( } } - private fun Translation.setValueAndState(text: String, usedService: MtServiceType?) { + private fun Translation.setValueAndState( + text: String, + usedService: MtServiceType?, + ) { this.resetFlags() this.state = TranslationState.TRANSLATED this.auto = true @@ -267,11 +279,17 @@ class AutoTranslationService( translationService.save(this) } - private fun getUntranslatedTranslations(key: Key, languages: List?): List { + private fun getUntranslatedTranslations( + key: Key, + languages: List?, + ): List { return getUntranslatedExistingTranslations(key, languages) + createNonExistingTranslations(key, languages) } - private fun createNonExistingTranslations(key: Key, languages: List?): List { + private fun createNonExistingTranslations( + key: Key, + languages: List?, + ): List { return getLanguagesWithNoTranslation(key, languages).map { language -> val translation = Translation(key = key, language = language) key.translations.add(translation) @@ -279,7 +297,10 @@ class AutoTranslationService( } } - fun saveDefaultConfig(project: Project, dto: AutoTranslationSettingsDto): AutoTranslationConfig { + fun saveDefaultConfig( + project: Project, + dto: AutoTranslationSettingsDto, + ): AutoTranslationConfig { val config = getDefaultConfig(project) config.usingTm = dto.usingTranslationMemory config.usingPrimaryMtService = dto.usingMachineTranslation @@ -289,7 +310,7 @@ class AutoTranslationService( fun deleteConfigsByProject(projectId: Long) { entityManager.createNativeQuery( - "DELETE FROM auto_translation_config WHERE project_id = :projectId" + "DELETE FROM auto_translation_config WHERE project_id = :projectId", ) .setParameter("projectId", projectId) .executeUpdate() @@ -302,38 +323,51 @@ class AutoTranslationService( fun getConfigs(project: Project) = addDefaultConfig(project, autoTranslationConfigRepository.findAllByProject(project)) - private fun addDefaultConfig(project: Project, list: List?): List { - val hasDefault = list?.any { autoTranslationConfig -> autoTranslationConfig.targetLanguage == null } - ?: false + private fun addDefaultConfig( + project: Project, + list: List?, + ): List { + val hasDefault = + list?.any { autoTranslationConfig -> autoTranslationConfig.targetLanguage == null } + ?: false if (!hasDefault) { return (list ?: listOf()) + listOf(AutoTranslationConfig().also { it.project = project }) } return list!! } - fun getConfigs(project: Project, targetLanguageIds: List): Map { + fun getConfigs( + project: Project, + targetLanguageIds: List, + ): Map { val configs = autoTranslationConfigRepository.findByProjectAndTargetLanguageIdIn(project, targetLanguageIds) - val default = autoTranslationConfigRepository.findDefaultForProject(project) - ?: autoTranslationConfigRepository.findDefaultForProject(project) ?: AutoTranslationConfig().also { - it.project = project - } + val default = + autoTranslationConfigRepository.findDefaultForProject(project) + ?: autoTranslationConfigRepository.findDefaultForProject(project) ?: AutoTranslationConfig().also { + it.project = project + } return targetLanguageIds.associateWith { languageId -> (configs.find { it.targetLanguage?.id == languageId } ?: default) } } - fun getConfig(project: Project, targetLanguageId: Long) = - autoTranslationConfigRepository.findOneByProjectAndTargetLanguageId(project, targetLanguageId) - ?: autoTranslationConfigRepository.findDefaultForProject(project) ?: AutoTranslationConfig().also { - it.project = project - } + fun getConfig( + project: Project, + targetLanguageId: Long, + ) = autoTranslationConfigRepository.findOneByProjectAndTargetLanguageId(project, targetLanguageId) + ?: autoTranslationConfigRepository.findDefaultForProject(project) ?: AutoTranslationConfig().also { + it.project = project + } fun getDefaultConfig(project: Project) = autoTranslationConfigRepository.findOneByProjectAndTargetLanguageId(project, null) ?: AutoTranslationConfig() .also { it.project = project } - private fun getLanguagesWithNoTranslation(key: Key, languages: List?): List { + private fun getLanguagesWithNoTranslation( + key: Key, + languages: List?, + ): List { return (languages ?: key.project.languages) .filter { projectLanguage -> key.translations.find { it.language.id == projectLanguage.id } == null @@ -343,26 +377,34 @@ class AutoTranslationService( /** * Returns existing translations with null or empty value */ - private fun getUntranslatedExistingTranslations(key: Key, languages: List?) = key.translations + private fun getUntranslatedExistingTranslations( + key: Key, + languages: List?, + ) = key.translations .filter { languages?.contains(it.language) != false && it.text.isNullOrEmpty() } - fun saveConfig(projectEntity: Project, dtos: List): List { + fun saveConfig( + projectEntity: Project, + dtos: List, + ): List { val configs = getConfigs(projectEntity).associateBy { it.targetLanguage?.id } val languages = languageService.findAll(projectEntity.id) - val result = dtos.map { dto -> - val config = (configs[dto.languageId] ?: AutoTranslationConfig()) - config.usingTm = dto.usingTranslationMemory - config.usingPrimaryMtService = dto.usingMachineTranslation - config.enableForImport = dto.enableForImport - config.project = projectEntity - config.targetLanguage = languages.find { it.id == dto.languageId } - config - } + val result = + dtos.map { dto -> + val config = (configs[dto.languageId] ?: AutoTranslationConfig()) + config.usingTm = dto.usingTranslationMemory + config.usingPrimaryMtService = dto.usingMachineTranslation + config.enableForImport = dto.enableForImport + config.project = projectEntity + config.targetLanguage = languages.find { it.id == dto.languageId } + config + } - val toDelete = configs.values.filter { config -> - result.find { it.targetLanguage?.id == config.targetLanguage?.id } == null - } + val toDelete = + configs.values.filter { config -> + result.find { it.targetLanguage?.id == config.targetLanguage?.id } == null + } autoTranslationConfigRepository.deleteAll(toDelete) autoTranslationConfigRepository.saveAll(result) diff --git a/backend/data/src/main/kotlin/io/tolgee/service/translation/TranslationCommentService.kt b/backend/data/src/main/kotlin/io/tolgee/service/translation/TranslationCommentService.kt index a082c98c84..2e51fe7abd 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/translation/TranslationCommentService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/translation/TranslationCommentService.kt @@ -19,18 +19,18 @@ import org.springframework.transaction.annotation.Transactional class TranslationCommentService( private val translationCommentRepository: TranslationCommentRepository, private val authenticationFacade: AuthenticationFacade, - private val entityManager: EntityManager + private val entityManager: EntityManager, ) { @Transactional fun create( dto: ITranslationCommentDto, translation: Translation, - author: UserAccount + author: UserAccount, ): TranslationComment { return TranslationComment( text = dto.text, state = dto.state, - translation = translation + translation = translation, ).let { it.author = author create(it) @@ -58,19 +58,28 @@ class TranslationCommentService( } @Transactional - fun update(dto: TranslationCommentDto, entity: TranslationComment): TranslationComment { + fun update( + dto: TranslationCommentDto, + entity: TranslationComment, + ): TranslationComment { entity.text = dto.text entity.state = dto.state return this.update(entity) } @Transactional - fun setState(entity: TranslationComment, state: TranslationCommentState): TranslationComment { + fun setState( + entity: TranslationComment, + state: TranslationCommentState, + ): TranslationComment { entity.state = state return this.update(entity) } - fun getPaged(translation: Translation, pageable: Pageable): Page { + fun getPaged( + translation: Translation, + pageable: Pageable, + ): Page { return translationCommentRepository.getPagedByTranslation(translation, pageable) } @@ -94,7 +103,7 @@ class TranslationCommentService( fun update( entity: TranslationComment, - updatedBy: UserAccount = authenticationFacade.authenticatedUserEntity + updatedBy: UserAccount = authenticationFacade.authenticatedUserEntity, ): TranslationComment { return translationCommentRepository.save(entity) } @@ -107,7 +116,7 @@ class TranslationCommentService( entityManager.createNativeQuery( "DELETE FROM translation_comment WHERE translation_id IN " + "(SELECT id FROM translation WHERE key_id IN " + - "(SELECT id FROM key WHERE project_id = :projectId))" + "(SELECT id FROM key WHERE project_id = :projectId))", ).setParameter("projectId", projectId).executeUpdate() } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/translation/TranslationMemoryService.kt b/backend/data/src/main/kotlin/io/tolgee/service/translation/TranslationMemoryService.kt index 0d3c16c59d..099259c26c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/translation/TranslationMemoryService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/translation/TranslationMemoryService.kt @@ -11,10 +11,9 @@ import org.springframework.stereotype.Service class TranslationMemoryService( private val translationsService: TranslationService, ) { - fun getAutoTranslatedValue( key: Key, - targetLanguage: Language + targetLanguage: Language, ): TranslationMemoryItemView? { return translationsService.getTranslationMemoryValue(key, targetLanguage) } @@ -22,7 +21,7 @@ class TranslationMemoryService( fun suggest( key: Key, targetLanguage: Language, - pageable: Pageable + pageable: Pageable, ): Page { return translationsService.getTranslationMemorySuggestions(key, targetLanguage, pageable) } @@ -30,13 +29,13 @@ class TranslationMemoryService( fun suggest( baseTranslationText: String, targetLanguage: Language, - pageable: Pageable + pageable: Pageable, ): Page { return translationsService.getTranslationMemorySuggestions( baseTranslationText, null, targetLanguage, - pageable + pageable, ) } } diff --git a/backend/data/src/main/kotlin/io/tolgee/service/translation/TranslationService.kt b/backend/data/src/main/kotlin/io/tolgee/service/translation/TranslationService.kt index 5ce23a670a..79d6f36c5a 100644 --- a/backend/data/src/main/kotlin/io/tolgee/service/translation/TranslationService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/service/translation/TranslationService.kt @@ -22,7 +22,7 @@ import io.tolgee.service.LanguageService import io.tolgee.service.dataImport.ImportService import io.tolgee.service.key.KeyService import io.tolgee.service.project.ProjectService -import io.tolgee.service.query_builders.translationViewBuilder.TranslationViewDataProvider +import io.tolgee.service.queryBuilders.translationViewBuilder.TranslationViewDataProvider import jakarta.persistence.EntityManager import org.springframework.beans.factory.annotation.Autowired import org.springframework.context.ApplicationEventPublisher @@ -42,7 +42,7 @@ class TranslationService( private val applicationEventPublisher: ApplicationEventPublisher, private val translationViewDataProvider: TranslationViewDataProvider, private val entityManager: EntityManager, - private val translationCommentService: TranslationCommentService + private val translationCommentService: TranslationCommentService, ) { @set:Autowired @set:Lazy @@ -62,16 +62,17 @@ class TranslationService( languageTags: Set, namespace: String?, projectId: Long, - structureDelimiter: Char? + structureDelimiter: Char?, ): Map { val safeNamespace = if (namespace == "") null else namespace val allByLanguages = translationRepository.getTranslations(languageTags, safeNamespace, projectId) val langTranslations: HashMap = LinkedHashMap() for (translation in allByLanguages) { - val map = langTranslations - .computeIfAbsent( - translation.languageTag - ) { LinkedHashMap() } as MutableMap + val map = + langTranslations + .computeIfAbsent( + translation.languageTag, + ) { LinkedHashMap() } as MutableMap addToMap(translation, map, structureDelimiter) } return langTranslations @@ -81,19 +82,31 @@ class TranslationService( return translationRepository.getAllByLanguageId(languageId) } - fun getKeyTranslations(languages: Set, project: Project, key: Key?): Set { + fun getKeyTranslations( + languages: Set, + project: Project, + key: Key?, + ): Set { return if (key != null) { translationRepository.getTranslations(key, project, languages) - } else LinkedHashSet() + } else { + LinkedHashSet() + } } - fun getOrCreate(key: Key, language: Language): Translation { + fun getOrCreate( + key: Key, + language: Language, + ): Translation { return find(key, language).orElseGet { Translation(language = language, key = key) } } - fun getOrCreate(keyId: Long, languageId: Long): Translation { + fun getOrCreate( + keyId: Long, + languageId: Long, + ): Translation { return translationRepository.findOneByKeyIdAndLanguageId(keyId, languageId) ?: let { val key = keyService.findOptional(keyId).orElseThrow { NotFoundException() } @@ -105,7 +118,10 @@ class TranslationService( } } - fun find(key: Key, language: Language): Optional { + fun find( + key: Key, + language: Language, + ): Optional { return translationRepository.findOneByKeyAndLanguage(key, language) } @@ -121,7 +137,7 @@ class TranslationService( projectId: Long, pageable: Pageable, params: GetTranslationsParams, - languages: Set + languages: Set, ): Page { return translationViewDataProvider.getData(projectId, languages, pageable, params, params.cursor) } @@ -129,18 +145,27 @@ class TranslationService( fun getSelectAllKeys( projectId: Long, params: TranslationFilters, - languages: Set + languages: Set, ): List { return translationViewDataProvider.getSelectAllKeys(projectId, languages, params) } - fun setTranslation(key: Key, languageTag: String?, text: String?): Translation? { - val language = languageService.findByTag(languageTag!!, key.project) - .orElseThrow { NotFoundException(Message.LANGUAGE_NOT_FOUND) } + fun setTranslation( + key: Key, + languageTag: String?, + text: String?, + ): Translation? { + val language = + languageService.findByTag(languageTag!!, key.project) + .orElseThrow { NotFoundException(Message.LANGUAGE_NOT_FOUND) } return setTranslation(key, language, text) } - fun setTranslation(key: Key, language: Language, text: String?): Translation { + fun setTranslation( + key: Key, + language: Language, + text: String?, + ): Translation { val translation = getOrCreate(key, language) setTranslation(translation, text) key.translations.add(translation) @@ -149,7 +174,7 @@ class TranslationService( fun setTranslation( translation: Translation, - text: String? + text: String?, ): Translation { if (translation.text !== text) { translation.resetFlags() @@ -174,57 +199,73 @@ class TranslationService( } @Transactional - fun setForKey(key: Key, translations: Map): Map { + fun setForKey( + key: Key, + translations: Map, + ): Map { val languages = languageService.findByTags(translations.keys, key.project.id) - val oldTranslations = getKeyTranslations(languages, key.project, key).associate { - languageByIdFromLanguages( - it.language.id, - languages - ) to it.text - } + val oldTranslations = + getKeyTranslations(languages, key.project, key).associate { + languageByIdFromLanguages( + it.language.id, + languages, + ) to it.text + } return setForKey( key, translations.map { languageByTagFromLanguages(it.key, languages) to it.value } .toMap(), - oldTranslations + oldTranslations, ).mapKeys { it.key.tag } } - fun findForKeyByLanguages(key: Key, languageTags: Collection): List { + fun findForKeyByLanguages( + key: Key, + languageTags: Collection, + ): List { return translationRepository.findForKeyByLanguages(key, languageTags) } - private fun languageByTagFromLanguages(tag: String, languages: Collection) = - languages.find { it.tag == tag } ?: throw NotFoundException(Message.LANGUAGE_NOT_FOUND) + private fun languageByTagFromLanguages( + tag: String, + languages: Collection, + ) = languages.find { it.tag == tag } ?: throw NotFoundException(Message.LANGUAGE_NOT_FOUND) - private fun languageByIdFromLanguages(id: Long, languages: Collection) = - languages.find { it.id == id } ?: throw NotFoundException(Message.LANGUAGE_NOT_FOUND) + private fun languageByIdFromLanguages( + id: Long, + languages: Collection, + ) = languages.find { it.id == id } ?: throw NotFoundException(Message.LANGUAGE_NOT_FOUND) @Transactional fun setForKey( key: Key, translations: Map, - oldTranslations: Map + oldTranslations: Map, ): Map { - val result = translations.entries.associate { (language, value) -> - language to setTranslation(key, language, value) - }.filterValues { it != null }.mapValues { it.value } + val result = + translations.entries.associate { (language, value) -> + language to setTranslation(key, language, value) + }.filterValues { it != null }.mapValues { it.value } applicationEventPublisher.publishEvent( OnTranslationsSet( source = this, key = key, oldValues = oldTranslations.map { it.key.tag to it.value }.toMap(), - translations = result.values.toList() - ) + translations = result.values.toList(), + ), ) return result } @Suppress("UNCHECKED_CAST") - private fun addToMap(translation: SimpleTranslationView, map: MutableMap, delimiter: Char?) { + private fun addToMap( + translation: SimpleTranslationView, + map: MutableMap, + delimiter: Char?, + ) { var currentMap = map val path = TextHelper.splitOnNonEscapedDelimiter(translation.key, delimiter).toMutableList() val name = path.removeLast() @@ -267,7 +308,10 @@ class TranslationService( entities.forEach { save(it) } } - fun setStateBatch(translation: Translation, state: TranslationState): Translation { + fun setStateBatch( + translation: Translation, + state: TranslationState, + ): Translation { translation.state = state translation.resetFlags() return this.save(translation) @@ -292,8 +336,9 @@ class TranslationService( key: Key, targetLanguage: Language, ): TranslationMemoryItemView? { - val baseLanguage = projectService.getOrCreateBaseLanguage(targetLanguage.project.id) - ?: throw NotFoundException(Message.BASE_LANGUAGE_NOT_FOUND) + val baseLanguage = + projectService.getOrCreateBaseLanguage(targetLanguage.project.id) + ?: throw NotFoundException(Message.BASE_LANGUAGE_NOT_FOUND) val baseTranslationText = findBaseTranslation(key)?.text ?: return null @@ -301,14 +346,14 @@ class TranslationService( baseTranslationText, key, baseLanguage, - targetLanguage + targetLanguage, ).firstOrNull() } fun getTranslationMemorySuggestions( key: Key, targetLanguage: Language, - pageable: Pageable + pageable: Pageable, ): Page { val baseTranslation = findBaseTranslation(key) ?: return Page.empty() @@ -321,10 +366,11 @@ class TranslationService( baseTranslationText: String, key: Key?, targetLanguage: Language, - pageable: Pageable + pageable: Pageable, ): Page { - val baseLanguage = projectService.getOrCreateBaseLanguage(targetLanguage.project.id) - ?: throw NotFoundException(Message.BASE_LANGUAGE_NOT_FOUND) + val baseLanguage = + projectService.getOrCreateBaseLanguage(targetLanguage.project.id) + ?: throw NotFoundException(Message.BASE_LANGUAGE_NOT_FOUND) return getTranslationMemorySuggestions(baseTranslationText, key, baseLanguage, targetLanguage, pageable) } @@ -334,7 +380,7 @@ class TranslationService( key: Key?, sourceLanguage: Language, targetLanguage: Language, - pageable: Pageable + pageable: Pageable, ): Page { if ((sourceTranslationText.length) < 3) { return Page.empty(pageable) @@ -345,7 +391,7 @@ class TranslationService( key = key, baseLanguage = sourceLanguage, targetLanguage = targetLanguage, - pageable = pageable + pageable = pageable, ) } @@ -357,12 +403,18 @@ class TranslationService( } @Transactional - fun setOutdated(translation: Translation, value: Boolean) { + fun setOutdated( + translation: Translation, + value: Boolean, + ) { translation.outdated = value save(translation) } - fun setOutdated(key: Key, excludeTranslationIds: Set = emptySet()) { + fun setOutdated( + key: Key, + excludeTranslationIds: Set = emptySet(), + ) { val baseLanguage = key.project.baseLanguage key.translations.forEach { val isBase = it.language.id == baseLanguage?.id @@ -386,31 +438,39 @@ class TranslationService( val query = cb.createQuery(Translation::class.java) val root = query.from(Translation::class.java) - val predicates = keyLanguagesMap.map { (key, languages) -> - cb.and( - cb.equal(root.get(Translation_.key), key), - root.get(Translation_.language).`in`(languages) - ) - }.toTypedArray() + val predicates = + keyLanguagesMap.map { (key, languages) -> + cb.and( + cb.equal(root.get(Translation_.key), key), + root.get(Translation_.language).`in`(languages), + ) + }.toTypedArray() query.where(cb.or(*predicates)) return entityManager.createQuery(query).resultList } - fun getForKeys(keyIds: List, languageTags: List): List { + fun getForKeys( + keyIds: List, + languageTags: List, + ): List { return translationRepository.getForKeys(keyIds, languageTags) } fun findAllByKeyIdsAndLanguageIds( keyIds: List, - languageIds: List + languageIds: List, ): List { return translationRepository.findAllByKeyIdInAndLanguageIdIn(keyIds, languageIds) } @Transactional - fun setStateBatch(keyIds: List, languageIds: List, state: TranslationState) { + fun setStateBatch( + keyIds: List, + languageIds: List, + state: TranslationState, + ) { val translations = getTargetTranslations(keyIds, languageIds) translations.filter { it.state != TranslationState.DISABLED }.forEach { it.state = state } saveAll(translations) @@ -418,10 +478,13 @@ class TranslationService( fun getTranslations( keyIds: List, - languageIds: List + languageIds: List, ) = translationRepository.getAllByKeyIdInAndLanguageIdIn(keyIds, languageIds) - fun clearBatch(keyIds: List, languageIds: List) { + fun clearBatch( + keyIds: List, + languageIds: List, + ) { val translations = getTargetTranslations(keyIds, languageIds) translations.forEach { it.clear() @@ -429,35 +492,41 @@ class TranslationService( saveAll(translations) } - fun copyBatch(keyIds: List, sourceLanguageId: Long, targetLanguageIds: List) { + fun copyBatch( + keyIds: List, + sourceLanguageId: Long, + targetLanguageIds: List, + ) { val sourceTranslations = getTargetTranslations(keyIds, listOf(sourceLanguageId)).associateBy { it.key.id } - val targetTranslations = getTargetTranslations(keyIds, targetLanguageIds).onEach { - it.text = sourceTranslations[it.key.id]?.text - if (!it.text.isNullOrEmpty()) { - it.state = TranslationState.TRANSLATED + val targetTranslations = + getTargetTranslations(keyIds, targetLanguageIds).onEach { + it.text = sourceTranslations[it.key.id]?.text + if (!it.text.isNullOrEmpty()) { + it.state = TranslationState.TRANSLATED + } + it.auto = false + it.mtProvider = null + it.outdated = false } - it.auto = false - it.mtProvider = null - it.outdated = false - } saveAll(targetTranslations) } private fun getTargetTranslations( keyIds: List, - targetLanguageIds: List + targetLanguageIds: List, ): List { val existing = getTranslations(keyIds, targetLanguageIds) - val existingMap = existing.groupBy { it.key.id } - .map { entry -> - entry.key to - entry.value.associateBy { translation -> translation.language.id } - }.toMap() + val existingMap = + existing.groupBy { it.key.id } + .map { entry -> + entry.key to + entry.value.associateBy { translation -> translation.language.id } + }.toMap() return keyIds.flatMap { keyId -> targetLanguageIds.map { languageId -> existingMap[keyId]?.get(languageId) ?: getOrCreate( entityManager.getReference(Key::class.java, keyId), - entityManager.getReference(Language::class.java, languageId) + entityManager.getReference(Language::class.java, languageId), ) }.filter { it.state !== TranslationState.DISABLED } } @@ -469,7 +538,7 @@ class TranslationService( "DELETE FROM translation " + "WHERE " + "key_id IN (SELECT id FROM key WHERE project_id = :projectId) or " + - "language_id IN (SELECT id FROM language WHERE project_id = :projectId)" + "language_id IN (SELECT id FROM language WHERE project_id = :projectId)", ).setParameter("projectId", projectId).executeUpdate() } } diff --git a/backend/data/src/main/kotlin/io/tolgee/util/EntityUtil.kt b/backend/data/src/main/kotlin/io/tolgee/util/EntityUtil.kt index 965e94538b..d58a9b5107 100644 --- a/backend/data/src/main/kotlin/io/tolgee/util/EntityUtil.kt +++ b/backend/data/src/main/kotlin/io/tolgee/util/EntityUtil.kt @@ -6,9 +6,8 @@ import java.util.concurrent.ConcurrentHashMap @Component class EntityUtil( - private val entityManager: EntityManager + private val entityManager: EntityManager, ) { - companion object { val REGEX = "\\$.*$".toRegex() } diff --git a/backend/data/src/main/kotlin/io/tolgee/util/ImageConverter.kt b/backend/data/src/main/kotlin/io/tolgee/util/ImageConverter.kt index ad88188ede..facce67d84 100644 --- a/backend/data/src/main/kotlin/io/tolgee/util/ImageConverter.kt +++ b/backend/data/src/main/kotlin/io/tolgee/util/ImageConverter.kt @@ -24,13 +24,19 @@ class ImageConverter( Dimension(sourceBufferedImage.width, sourceBufferedImage.height) } - fun getImage(compressionQuality: Float = 0.8f, targetDimension: Dimension? = null): ByteArrayOutputStream { + fun getImage( + compressionQuality: Float = 0.8f, + targetDimension: Dimension? = null, + ): ByteArrayOutputStream { val resultingTargetDimension = targetDimension ?: this.targetDimension val resizedImage = getScaledImage(resultingTargetDimension) return writeImage(resizedImage, compressionQuality) } - fun getThumbnail(size: Int = 150, compressionQuality: Float = 0.8f): ByteArrayOutputStream { + fun getThumbnail( + size: Int = 150, + compressionQuality: Float = 0.8f, + ): ByteArrayOutputStream { val originalWidth = sourceBufferedImage.width val originalHeight = sourceBufferedImage.height val newWidth: Int @@ -48,7 +54,10 @@ class ImageConverter( return writeImage(resizedImage, compressionQuality) } - private fun writeImage(bufferedImage: BufferedImage, compressionQuality: Float): ByteArrayOutputStream { + private fun writeImage( + bufferedImage: BufferedImage, + compressionQuality: Float, + ): ByteArrayOutputStream { val imageWriter = getWriter() val writerParams = getWriterParams(imageWriter, compressionQuality) val outputStream = ByteArrayOutputStream() @@ -61,7 +70,10 @@ class ImageConverter( return outputStream } - private fun getWriterParams(writer: ImageWriter, compressionQuality: Float): ImageWriteParam? { + private fun getWriterParams( + writer: ImageWriter, + compressionQuality: Float, + ): ImageWriteParam? { val writerParams = writer.defaultWriteParam if (compressionQuality > 0) { writerParams.compressionMode = ImageWriteParam.MODE_EXPLICIT @@ -75,11 +87,11 @@ class ImageConverter( val g = resized.createGraphics() g.setRenderingHint( RenderingHints.KEY_INTERPOLATION, - RenderingHints.VALUE_INTERPOLATION_BILINEAR + RenderingHints.VALUE_INTERPOLATION_BILINEAR, ) g.drawImage( sourceBufferedImage, 0, 0, targetDimension.width, targetDimension.height, 0, 0, sourceBufferedImage.width, - sourceBufferedImage.height, null + sourceBufferedImage.height, null, ) g.dispose() return resized @@ -99,15 +111,21 @@ class ImageConverter( return@lazy Dimension(sourceBufferedImage.width, sourceBufferedImage.height) } - private fun convertToBufferedImage(img: Image, width: Int, height: Int): BufferedImage { + private fun convertToBufferedImage( + img: Image, + width: Int, + height: Int, + ): BufferedImage { if (img is BufferedImage) { return img } - val bi = BufferedImage( - width, height, - BufferedImage.TYPE_INT_ARGB - ) + val bi = + BufferedImage( + width, + height, + BufferedImage.TYPE_INT_ARGB, + ) val graphics2D = bi.createGraphics() graphics2D.drawImage(img, 0, 0, null) graphics2D.dispose() diff --git a/backend/data/src/main/kotlin/io/tolgee/util/SequenceIdProvider.kt b/backend/data/src/main/kotlin/io/tolgee/util/SequenceIdProvider.kt index 3f54dc5ee6..86d781bd67 100644 --- a/backend/data/src/main/kotlin/io/tolgee/util/SequenceIdProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/util/SequenceIdProvider.kt @@ -4,9 +4,8 @@ import java.sql.Connection class SequenceIdProvider( private val sequenceName: String, - private val allocationSize: Int + private val allocationSize: Int, ) { - private var currentId: Long? = null private var currentMaxId: Long? = null diff --git a/backend/data/src/main/kotlin/io/tolgee/util/SlugGenerator.kt b/backend/data/src/main/kotlin/io/tolgee/util/SlugGenerator.kt index 9863b43e25..7c35a437c3 100644 --- a/backend/data/src/main/kotlin/io/tolgee/util/SlugGenerator.kt +++ b/backend/data/src/main/kotlin/io/tolgee/util/SlugGenerator.kt @@ -9,7 +9,6 @@ import java.util.* @Suppress("SpringJavaInjectionPointsAutowiringInspection") @Component class SlugGenerator { - companion object { const val DELIMITER = "-" } @@ -18,11 +17,12 @@ class SlugGenerator { name: String, minLength: Int, maxLength: Int, - checkUniquenessCallback: (name: String) -> Boolean + checkUniquenessCallback: (name: String) -> Boolean, ): String { - var namePart = StringUtils.stripAccents(name).lowercase(Locale.getDefault()) - .replace("[^a-z0-9]+".toRegex(), DELIMITER) - .let { it.substring(0, min(it.length, maxLength)) } + var namePart = + StringUtils.stripAccents(name).lowercase(Locale.getDefault()) + .replace("[^a-z0-9]+".toRegex(), DELIMITER) + .let { it.substring(0, min(it.length, maxLength)) } namePart = namePart.removePrefix(DELIMITER) @@ -43,7 +43,6 @@ class SlugGenerator { val result = namePart + numPart.emptyOnZero() if (result.length >= minLength && checkUniquenessCallback(result)) { - // has to contain letter if (result.matches(".*[a-z]+.*+".toRegex())) { return result diff --git a/backend/data/src/main/kotlin/io/tolgee/util/StreamingResponseBodyProvider.kt b/backend/data/src/main/kotlin/io/tolgee/util/StreamingResponseBodyProvider.kt index 1322db53e0..1a7bc7fb3f 100644 --- a/backend/data/src/main/kotlin/io/tolgee/util/StreamingResponseBodyProvider.kt +++ b/backend/data/src/main/kotlin/io/tolgee/util/StreamingResponseBodyProvider.kt @@ -24,7 +24,7 @@ import java.io.OutputStream @Component class StreamingResponseBodyProvider( - private val entityManager: EntityManager + private val entityManager: EntityManager, ) { fun createStreamingResponseBody(fn: (os: OutputStream) -> Unit): StreamingResponseBody { return StreamingResponseBody { diff --git a/backend/data/src/main/kotlin/io/tolgee/util/TranslationStatsUtil.kt b/backend/data/src/main/kotlin/io/tolgee/util/TranslationStatsUtil.kt index fc43fbd09c..06a32ca230 100644 --- a/backend/data/src/main/kotlin/io/tolgee/util/TranslationStatsUtil.kt +++ b/backend/data/src/main/kotlin/io/tolgee/util/TranslationStatsUtil.kt @@ -1,7 +1,10 @@ package io.tolgee.util object TranslationStatsUtil { - fun getWordCount(text: String?, languageTag: String): Int { + fun getWordCount( + text: String?, + languageTag: String, + ): Int { return text?.let { WordCounter.countWords(it, languageTag) } ?: 0 } diff --git a/backend/data/src/main/kotlin/io/tolgee/util/WordCounter.kt b/backend/data/src/main/kotlin/io/tolgee/util/WordCounter.kt index 9d8d49227e..7d808eba7c 100644 --- a/backend/data/src/main/kotlin/io/tolgee/util/WordCounter.kt +++ b/backend/data/src/main/kotlin/io/tolgee/util/WordCounter.kt @@ -7,7 +7,10 @@ object WordCounter { private val NON_WORD = """[\p{P} \t\n\r~!@#$%^&*()_+{}\[\]:;,.<>/?-]""".toRegex() private val LANGUAGE_PART = "^([A-Za-z]+).*".toRegex() - fun countWords(text: String, languageTag: String): Int { + fun countWords( + text: String, + languageTag: String, + ): Int { val uLocale = getLocaleFromTag(languageTag) val iterator: BreakIterator = BreakIterator.getWordInstance(uLocale) iterator.setText(text) diff --git a/backend/data/src/main/kotlin/io/tolgee/util/criteriaBuilderExt.kt b/backend/data/src/main/kotlin/io/tolgee/util/criteriaBuilderExt.kt index 58e546ce6c..c4b721a1fd 100644 --- a/backend/data/src/main/kotlin/io/tolgee/util/criteriaBuilderExt.kt +++ b/backend/data/src/main/kotlin/io/tolgee/util/criteriaBuilderExt.kt @@ -10,7 +10,7 @@ import jakarta.persistence.criteria.Root fun CriteriaBuilder.greaterThanNullable( expression: Expression, - value: String? + value: String?, ): Predicate { if (value == null) { return expression.isNotNull @@ -20,7 +20,7 @@ fun CriteriaBuilder.greaterThanNullable( fun CriteriaBuilder.lessThanNullable( expression: Expression, - value: String? + value: String?, ): Predicate { if (value == null) { return this.isTrue(this.literal(false)) @@ -30,7 +30,7 @@ fun CriteriaBuilder.lessThanNullable( fun CriteriaBuilder.greaterThanOrEqualToNullable( expression: Expression, - value: String? + value: String?, ): Predicate { if (value == null) { return this.isTrue(this.literal(true)) @@ -40,7 +40,7 @@ fun CriteriaBuilder.greaterThanOrEqualToNullable( fun CriteriaBuilder.lessThanOrEqualToNullable( expression: Expression, - value: String? + value: String?, ): Predicate { if (value == null) { return this.isNull(expression) @@ -50,7 +50,7 @@ fun CriteriaBuilder.lessThanOrEqualToNullable( fun CriteriaBuilder.equalNullable( expression: Expression, - value: Any? + value: Any?, ): Predicate { if (value == null) { return this.isNull(expression) @@ -59,7 +59,7 @@ fun CriteriaBuilder.equalNullable( } inline fun EntityManager.query( - fn: CriteriaQuery.(cb: CriteriaBuilder, root: Root) -> Unit + fn: CriteriaQuery.(cb: CriteriaBuilder, root: Root) -> Unit, ): TypedQuery { val cb = this.criteriaBuilder val cq = cb.createQuery(Result::class.java) diff --git a/backend/data/src/main/kotlin/io/tolgee/util/loggerExtension.kt b/backend/data/src/main/kotlin/io/tolgee/util/loggerExtension.kt index 490b74634a..a3a78c1b1b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/util/loggerExtension.kt +++ b/backend/data/src/main/kotlin/io/tolgee/util/loggerExtension.kt @@ -15,7 +15,10 @@ interface Logging { val timeSums = mutableMapOf, String>, Duration>() } - fun traceLogMeasureTime(operationName: String, fn: () -> T): T { + fun traceLogMeasureTime( + operationName: String, + fn: () -> T, + ): T { if (logger.isTraceEnabled) { val start = System.currentTimeMillis() logger.trace("Operation $operationName started") @@ -42,24 +45,37 @@ fun Logger.debug(message: () -> String) { } } -inline fun Logger.traceMeasureTime(message: String, block: () -> T): T { +inline fun Logger.traceMeasureTime( + message: String, + block: () -> T, +): T { if (this.isTraceEnabled) { return measureTime(message, this::trace, block) } return block() } -inline fun Logger.infoMeasureTime(message: String, block: () -> T): T { +inline fun Logger.infoMeasureTime( + message: String, + block: () -> T, +): T { return measureTime(message, this::info, block) } -inline fun Logger.measureTime(message: String, printFn: (String) -> Unit, block: () -> T): T { +inline fun Logger.measureTime( + message: String, + printFn: (String) -> Unit, + block: () -> T, +): T { val (result, duration) = measureTimedValue(block) printFn("$message: $duration") return result } -inline fun Logger.storeTraceTimeSum(id: String, block: () -> T): T { +inline fun Logger.storeTraceTimeSum( + id: String, + block: () -> T, +): T { return if (this.isTraceEnabled) { val (result, duration) = measureTimedValue(block) Logging.timeSums.compute(this::class to id) { _, v -> @@ -71,7 +87,10 @@ inline fun Logger.storeTraceTimeSum(id: String, block: () -> T): T { } } -fun Logger.traceLogTimeSum(id: String, unit: DurationUnit = DurationUnit.MILLISECONDS) { +fun Logger.traceLogTimeSum( + id: String, + unit: DurationUnit = DurationUnit.MILLISECONDS, +) { if (this.isTraceEnabled) { val duration = Logging.timeSums[this::class to id] if (duration != null) { diff --git a/backend/data/src/main/kotlin/io/tolgee/util/transactionUtil.kt b/backend/data/src/main/kotlin/io/tolgee/util/transactionUtil.kt index 3190354c5e..701ff47ce1 100644 --- a/backend/data/src/main/kotlin/io/tolgee/util/transactionUtil.kt +++ b/backend/data/src/main/kotlin/io/tolgee/util/transactionUtil.kt @@ -12,7 +12,7 @@ fun executeInNewTransaction( transactionManager: PlatformTransactionManager, isolationLevel: Int = TransactionDefinition.ISOLATION_READ_COMMITTED, propagationBehavior: Int = TransactionDefinition.PROPAGATION_REQUIRES_NEW, - fn: (ts: TransactionStatus) -> T + fn: (ts: TransactionStatus) -> T, ): T { val tt = TransactionTemplate(transactionManager) tt.propagationBehavior = propagationBehavior @@ -25,12 +25,12 @@ fun executeInNewTransaction( fun executeInNewTransaction( transactionManager: PlatformTransactionManager, - fn: (ts: TransactionStatus) -> T + fn: (ts: TransactionStatus) -> T, ): T { return executeInNewTransaction( transactionManager = transactionManager, fn = fn, - propagationBehavior = TransactionDefinition.PROPAGATION_REQUIRES_NEW + propagationBehavior = TransactionDefinition.PROPAGATION_REQUIRES_NEW, ) } @@ -38,7 +38,7 @@ fun executeInNewRepeatableTransaction( transactionManager: PlatformTransactionManager, propagationBehavior: Int = TransactionDefinition.PROPAGATION_REQUIRES_NEW, isolationLevel: Int = TransactionDefinition.ISOLATION_READ_COMMITTED, - fn: () -> T + fn: () -> T, ): T { var exception: Exception? = null var repeats = 0 @@ -47,7 +47,7 @@ fun executeInNewRepeatableTransaction( return executeInNewTransaction( transactionManager, propagationBehavior = propagationBehavior, - isolationLevel = isolationLevel + isolationLevel = isolationLevel, ) { fn() } diff --git a/backend/data/src/main/kotlin/io/tolgee/util/tryUntilItDoesntBreakContraint.kt b/backend/data/src/main/kotlin/io/tolgee/util/tryUntilItDoesntBreakContraint.kt index 8730fa0950..fd1924885e 100644 --- a/backend/data/src/main/kotlin/io/tolgee/util/tryUntilItDoesntBreakContraint.kt +++ b/backend/data/src/main/kotlin/io/tolgee/util/tryUntilItDoesntBreakContraint.kt @@ -4,7 +4,10 @@ import jakarta.persistence.PersistenceException import org.springframework.dao.CannotAcquireLockException import org.springframework.dao.DataIntegrityViolationException -inline fun tryUntilItDoesntBreakConstraint(maxRepeats: Int = 100, fn: () -> T): T { +inline fun tryUntilItDoesntBreakConstraint( + maxRepeats: Int = 100, + fn: () -> T, +): T { var exception: Exception? = null var repeats = 0 for (it in 1..maxRepeats) { diff --git a/backend/data/src/main/kotlin/io/tolgee/util/withTimeoutRetrying.kt b/backend/data/src/main/kotlin/io/tolgee/util/withTimeoutRetrying.kt index 1f5cf0c0e4..56f7c30de9 100644 --- a/backend/data/src/main/kotlin/io/tolgee/util/withTimeoutRetrying.kt +++ b/backend/data/src/main/kotlin/io/tolgee/util/withTimeoutRetrying.kt @@ -5,7 +5,11 @@ import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withTimeout -fun withTimeoutRetrying(timeout: Long, retries: Int = 3, fn: () -> T): T { +fun withTimeoutRetrying( + timeout: Long, + retries: Int = 3, + fn: () -> T, +): T { var repeats = 0 for (it in 0..retries) { try { diff --git a/backend/data/src/main/kotlin/io/tolgee/websocket/ActorInfo.kt b/backend/data/src/main/kotlin/io/tolgee/websocket/ActorInfo.kt index 0272db567e..8e17fb7944 100644 --- a/backend/data/src/main/kotlin/io/tolgee/websocket/ActorInfo.kt +++ b/backend/data/src/main/kotlin/io/tolgee/websocket/ActorInfo.kt @@ -2,5 +2,5 @@ package io.tolgee.websocket data class ActorInfo( val data: Any?, - val type: ActorType + val type: ActorType, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/websocket/ActorType.kt b/backend/data/src/main/kotlin/io/tolgee/websocket/ActorType.kt index 3dfbf11c2c..02384dc9e0 100644 --- a/backend/data/src/main/kotlin/io/tolgee/websocket/ActorType.kt +++ b/backend/data/src/main/kotlin/io/tolgee/websocket/ActorType.kt @@ -3,5 +3,5 @@ package io.tolgee.websocket enum class ActorType { USER, UNKNOWN, - MACHINE + MACHINE, } diff --git a/backend/data/src/main/kotlin/io/tolgee/websocket/RedisWebsocketEventWrapper.kt b/backend/data/src/main/kotlin/io/tolgee/websocket/RedisWebsocketEventWrapper.kt index e02dff526d..d36eab1bb1 100644 --- a/backend/data/src/main/kotlin/io/tolgee/websocket/RedisWebsocketEventWrapper.kt +++ b/backend/data/src/main/kotlin/io/tolgee/websocket/RedisWebsocketEventWrapper.kt @@ -2,5 +2,5 @@ package io.tolgee.websocket class RedisWebsocketEventWrapper( val destination: String, - val message: T + val message: T, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/websocket/WebsocketEvent.kt b/backend/data/src/main/kotlin/io/tolgee/websocket/WebsocketEvent.kt index 6ef6a41904..e0f7e6e70b 100644 --- a/backend/data/src/main/kotlin/io/tolgee/websocket/WebsocketEvent.kt +++ b/backend/data/src/main/kotlin/io/tolgee/websocket/WebsocketEvent.kt @@ -8,5 +8,5 @@ data class WebsocketEvent( val sourceActivity: ActivityType?, val activityId: Long?, val dataCollapsed: Boolean, - val timestamp: Long + val timestamp: Long, ) diff --git a/backend/data/src/main/kotlin/io/tolgee/websocket/WebsocketEventPublisher.kt b/backend/data/src/main/kotlin/io/tolgee/websocket/WebsocketEventPublisher.kt index 21f12e5104..a64f582288 100644 --- a/backend/data/src/main/kotlin/io/tolgee/websocket/WebsocketEventPublisher.kt +++ b/backend/data/src/main/kotlin/io/tolgee/websocket/WebsocketEventPublisher.kt @@ -1,5 +1,8 @@ package io.tolgee.websocket interface WebsocketEventPublisher { - operator fun invoke(destination: String, message: WebsocketEvent) + operator fun invoke( + destination: String, + message: WebsocketEvent, + ) } diff --git a/backend/data/src/main/kotlin/io/tolgee/websocket/WebsocketEventType.kt b/backend/data/src/main/kotlin/io/tolgee/websocket/WebsocketEventType.kt index 020d0b52d7..59dbe78be7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/websocket/WebsocketEventType.kt +++ b/backend/data/src/main/kotlin/io/tolgee/websocket/WebsocketEventType.kt @@ -2,7 +2,8 @@ package io.tolgee.websocket enum class WebsocketEventType() { TRANSLATION_DATA_MODIFIED, - BATCH_JOB_PROGRESS; + BATCH_JOB_PROGRESS, + ; val typeName get() = name.lowercase().replace("_", "-") } diff --git a/backend/data/src/test/kotlin/io/tolgee/security/RequestContextServiceTest.kt b/backend/data/src/test/kotlin/io/tolgee/security/RequestContextServiceTest.kt index 8fc1558cb5..10f6061b64 100644 --- a/backend/data/src/test/kotlin/io/tolgee/security/RequestContextServiceTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/security/RequestContextServiceTest.kt @@ -82,7 +82,10 @@ class RequestContextServiceTest { Mockito.`when`(authenticationFacade.projectApiKey).thenReturn(apiKey) } - private fun makeRequest(path: String, id: String = ""): MockHttpServletRequest { + private fun makeRequest( + path: String, + id: String = "", + ): MockHttpServletRequest { val req = MockHttpServletRequest("GET", path.replace("{id}", id)) req.setAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE, path) req.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, mapOf("id" to id)) diff --git a/backend/data/src/test/kotlin/io/tolgee/security/authentication/JwtServiceTest.kt b/backend/data/src/test/kotlin/io/tolgee/security/authentication/JwtServiceTest.kt index 9c672d3e6b..a61b31a09c 100644 --- a/backend/data/src/test/kotlin/io/tolgee/security/authentication/JwtServiceTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/security/authentication/JwtServiceTest.kt @@ -52,12 +52,13 @@ class JwtServiceTest { private val userAccount = Mockito.mock(UserAccountDto::class.java) - private val jwtService: JwtService = JwtService( - testSigningKey, - authenticationProperties, - currentDateProvider, - userAccountService, - ) + private val jwtService: JwtService = + JwtService( + testSigningKey, + authenticationProperties, + currentDateProvider, + userAccountService, + ) @BeforeEach fun setupMocks() { @@ -178,7 +179,7 @@ class JwtServiceTest { assertDoesNotThrow { jwtService.validateTicket(ticketLong, JwtService.TicketType.AUTH_MFA) } Mockito.`when`(currentDateProvider.date).thenReturn( - Date(now + JwtService.DEFAULT_TICKET_EXPIRATION_TIME + 1000) + Date(now + JwtService.DEFAULT_TICKET_EXPIRATION_TIME + 1000), ) assertThrows { jwtService.validateTicket(ticket, JwtService.TicketType.AUTH_MFA) } @@ -193,10 +194,12 @@ class JwtServiceTest { @Test fun `it rejects invalid tokens and tickets`() { val invalidToken = "this certainly does not look like a token to me!" - val badToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." + - "eyJzdWIiOiIxMzM3IiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE5MTYyMzkwMjJ9.kn_amo5h7__tlveBus_215x3Zq9UGFI6O_QpJ2rKi9o" - val noSigToken = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0." + - "eyJzdWIiOiIxMzM3IiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE5MTYyMzkwMjJ9" + val badToken = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." + + "eyJzdWIiOiIxMzM3IiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE5MTYyMzkwMjJ9.kn_amo5h7__tlveBus_215x3Zq9UGFI6O_QpJ2rKi9o" + val noSigToken = + "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0." + + "eyJzdWIiOiIxMzM3IiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE5MTYyMzkwMjJ9" val token = jwtService.emitToken(TEST_USER_ID) val ticket = jwtService.emitTicket(TEST_USER_ID, JwtService.TicketType.AUTH_MFA) diff --git a/backend/data/src/test/kotlin/io/tolgee/security/ratelimit/RateLimitServiceTest.kt b/backend/data/src/test/kotlin/io/tolgee/security/ratelimit/RateLimitServiceTest.kt index 1db2600832..c754d6bb09 100644 --- a/backend/data/src/test/kotlin/io/tolgee/security/ratelimit/RateLimitServiceTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/security/ratelimit/RateLimitServiceTest.kt @@ -57,14 +57,15 @@ class RateLimitServiceTest { private val rateLimitProperties = Mockito.spy(RateLimitProperties::class.java) - private val rateLimitService = Mockito.spy( - RateLimitService( - cacheManager, - lockingProvider, - currentDateProvider, - rateLimitProperties, + private val rateLimitService = + Mockito.spy( + RateLimitService( + cacheManager, + lockingProvider, + currentDateProvider, + rateLimitProperties, + ), ) - ) private val userAccount = Mockito.mock(UserAccount::class.java) @@ -125,9 +126,10 @@ class RateLimitServiceTest { assertThrows { rateLimitService.consumeBucketUnless(testPolicy) { throw TestException() } } rateLimitService.consumeBucketUnless(testPolicy) { true } assertThrows { rateLimitService.consumeBucketUnless(testPolicy) { throw TestException() } } - val ex1 = assertThrows { - rateLimitService.consumeBucketUnless(testPolicy) { throw TestException() } - } + val ex1 = + assertThrows { + rateLimitService.consumeBucketUnless(testPolicy) { throw TestException() } + } val ex2 = assertThrows { rateLimitService.consumeBucketUnless(testPolicy) { true } } assertThat(ex1.retryAfter).isEqualTo(1000) @@ -228,9 +230,13 @@ class RateLimitServiceTest { // Accessing the one from API package is a pain here. class TestLockingProvider : LockingProvider { private val lock = ReentrantLock() + override fun getLock(name: String): Lock = lock - override fun withLocking(name: String, fn: () -> T): T { + override fun withLocking( + name: String, + fn: () -> T, + ): T { lock.lock() try { return fn() diff --git a/backend/data/src/test/kotlin/io/tolgee/unit/CoreImportFileProcessorUnitTest.kt b/backend/data/src/test/kotlin/io/tolgee/unit/CoreImportFileProcessorUnitTest.kt index 95f229a662..b192c7fd49 100644 --- a/backend/data/src/test/kotlin/io/tolgee/unit/CoreImportFileProcessorUnitTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/unit/CoreImportFileProcessorUnitTest.kt @@ -33,7 +33,6 @@ import org.springframework.context.ApplicationContext import java.util.* class CoreImportFileProcessorUnitTest { - private lateinit var applicationContextMock: ApplicationContext private lateinit var importMock: Import private lateinit var processorFactoryMock: ProcessorFactory @@ -100,7 +99,7 @@ class CoreImportFileProcessorUnitTest { this.first().run { name == "lng" && existingLanguage!!.name == "lng" } - } + }, ) } @@ -115,8 +114,8 @@ class CoreImportFileProcessorUnitTest { existingTranslation, Translation("equal text").also { it.key = Key("equal key") - } - ) + }, + ), ) processor.processFiles(listOf(importFileDto)) verify(importServiceMock).saveTranslations( @@ -125,7 +124,7 @@ class CoreImportFileProcessorUnitTest { assertThat(this[1].conflict).isNull() assertThat(this[2].conflict).isNull() true - } + }, ) } @@ -141,12 +140,12 @@ class CoreImportFileProcessorUnitTest { verify(keyMetaServiceMock).save( argThat { this.comments.any { it.text == "test comment" } - } + }, ) verify(keyMetaServiceMock).save( argThat { this.codeReferences.any { it.path == "hello.php" } - } + }, ) verify(importServiceMock).saveTranslations( argThat { @@ -154,7 +153,7 @@ class CoreImportFileProcessorUnitTest { assertThat(this[0].key.keyMeta?.codeReferences).hasSize(2) assertThat(this[0].key.keyMeta?.comments).hasSize(1) true - } + }, ) } } diff --git a/backend/data/src/test/kotlin/io/tolgee/unit/KeysDistanceUtilTest.kt b/backend/data/src/test/kotlin/io/tolgee/unit/KeysDistanceUtilTest.kt index 797dfc326b..82a45b5d23 100644 --- a/backend/data/src/test/kotlin/io/tolgee/unit/KeysDistanceUtilTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/unit/KeysDistanceUtilTest.kt @@ -1,7 +1,7 @@ package io.tolgee.unit import io.tolgee.dtos.RelatedKeyDto -import io.tolgee.dtos.query_results.KeyIdFindResult +import io.tolgee.dtos.queryResults.KeyIdFindResult import io.tolgee.model.Project import io.tolgee.service.bigMeta.BigMetaService import io.tolgee.service.bigMeta.KeysDistanceDto @@ -17,7 +17,7 @@ class KeysDistanceUtilTest { mutableListOf( RelatedKeyDto(keyName = "key1", namespace = "a"), RelatedKeyDto(keyName = "key2", namespace = null), - RelatedKeyDto(keyName = "key3", namespace = "a") + RelatedKeyDto(keyName = "key3", namespace = "a"), ) private val project: Project = mock() @@ -36,39 +36,40 @@ class KeysDistanceUtilTest { KeysDistanceDto(3, 4, projectId = 0).also { keysDistance -> keysDistance.score = 10000 keysDistance.hits = 1 - } - ) + }, + ), ) whenever(bigMetaService.getKeyIdsForItems(any(), any())).thenReturn( mutableListOf( KeyIdFindResult( id = 1, name = "key1", - namespace = "a" + namespace = "a", ), KeyIdFindResult( id = 2, name = "key2", - namespace = null + namespace = null, ), KeyIdFindResult( id = 3, name = "key3", - namespace = "a" + namespace = "a", ), KeyIdFindResult( id = 4, name = "key4", - namespace = "a" + namespace = "a", ), - ) + ), ) } @Test fun `it works`() { - val result = KeysDistanceUtil(relatedKeysRequest, project, bigMetaService) - .newDistances + val result = + KeysDistanceUtil(relatedKeysRequest, project, bigMetaService) + .newDistances result.assert.hasSize(4) result.singleOrNull { it.key1Id == 1L && it.key2Id == 2L }!!.score.assert.isEqualTo(10000) diff --git a/backend/data/src/test/kotlin/io/tolgee/unit/PathDTOTest.kt b/backend/data/src/test/kotlin/io/tolgee/unit/PathDTOTest.kt index 4f09a1b305..849af7af05 100644 --- a/backend/data/src/test/kotlin/io/tolgee/unit/PathDTOTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/unit/PathDTOTest.kt @@ -6,9 +6,10 @@ import org.junit.jupiter.api.Test import java.util.* class PathDTOTest { - private val testList = LinkedList( - listOf(*testFullPath.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) - ) + private val testList = + LinkedList( + listOf(*TEST_FULL_PATH.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()), + ) private fun getTestList(): LinkedList { return LinkedList(testList) @@ -61,6 +62,6 @@ class PathDTOTest { } companion object { - private const val testFullPath = "item1.item2.item1.item1.last" + private const val TEST_FULL_PATH = "item1.item2.item1.item1.last" } } diff --git a/backend/data/src/test/kotlin/io/tolgee/unit/TextHelperTest.kt b/backend/data/src/test/kotlin/io/tolgee/unit/TextHelperTest.kt index b15d547147..c08f923f94 100644 --- a/backend/data/src/test/kotlin/io/tolgee/unit/TextHelperTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/unit/TextHelperTest.kt @@ -10,7 +10,7 @@ class TextHelperTest { val str = "this.is.escaped\\.delimiter.aaa.once\\.more.and.multiple\\\\\\.and.\\\\\\\\.text" val split = TextHelper.splitOnNonEscapedDelimiter(str, '.') assertThat(split).isEqualTo( - listOf("this", "is", "escaped.delimiter", "aaa", "once.more", "and", "multiple\\.and", "\\\\", "text") + listOf("this", "is", "escaped.delimiter", "aaa", "once.more", "and", "multiple\\.and", "\\\\", "text"), ) } @@ -25,13 +25,14 @@ class TextHelperTest { @Test fun `replaces ICU params in text with params`() { - val result = TextHelper.replaceIcuParams( - "{name} Hello! " + - "{aaa, plural, " + - "one {What} " + - "other {what} } " + - "I am standard text! {anotherParam}" - ) + val result = + TextHelper.replaceIcuParams( + "{name} Hello! " + + "{aaa, plural, " + + "one {What} " + + "other {what} } " + + "I am standard text! {anotherParam}", + ) assertThat(result.text) .isEqualTo("{xx0xx} Hello! {xx1xx} I am standard text! {xx2xx}") assertThat(result.isComplex).isEqualTo(true) @@ -43,14 +44,15 @@ class TextHelperTest { @Test fun `replaces ICU params with escaping`() { - val result = TextHelper.replaceIcuParams( - "'{name} Hello! " + - "{aaa, plural, " + - "one {What} " + - "other {what} } " + - "I am standard text! {anotherParam}" + - "That's cool! That''s cool as well!" - ) + val result = + TextHelper.replaceIcuParams( + "'{name} Hello! " + + "{aaa, plural, " + + "one {What} " + + "other {what} } " + + "I am standard text! {anotherParam}" + + "That's cool! That''s cool as well!", + ) assertThat(result.text) .isEqualTo("{name} Hello! {xx0xx} I am standard text! {xx1xx}That's cool! That's cool as well!") assertThat(result.isComplex).isEqualTo(true) diff --git a/backend/data/src/test/kotlin/io/tolgee/unit/cachePurging/AzureContentStorageConfigCachePurgingTest.kt b/backend/data/src/test/kotlin/io/tolgee/unit/cachePurging/AzureContentStorageConfigCachePurgingTest.kt index 8b8d4fba4a..ab992d94cb 100644 --- a/backend/data/src/test/kotlin/io/tolgee/unit/cachePurging/AzureContentStorageConfigCachePurgingTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/unit/cachePurging/AzureContentStorageConfigCachePurgingTest.kt @@ -23,24 +23,25 @@ import org.springframework.web.client.RestTemplate class AzureContentStorageConfigCachePurgingTest() { @Test fun `correctly purges`() { - val config = object : AzureFrontDoorConfig { - override val clientId: String - get() = "fake-client-id" - override val clientSecret: String - get() = "fake-client-secret" - override val tenantId: String - get() = "fake-tenant-id" - override val contentRoot: String - get() = "/fake-content-root/" - override val subscriptionId: String - get() = "fake-subscription-id" - override val endpointName: String - get() = "fake-endpoint-name" - override val profileName: String - get() = "fake-profile-name" - override val resourceGroupName: String - get() = "fake-resource-group-name" - } + val config = + object : AzureFrontDoorConfig { + override val clientId: String + get() = "fake-client-id" + override val clientSecret: String + get() = "fake-client-secret" + override val tenantId: String + get() = "fake-tenant-id" + override val contentRoot: String + get() = "/fake-content-root/" + override val subscriptionId: String + get() = "fake-subscription-id" + override val endpointName: String + get() = "fake-endpoint-name" + override val profileName: String + get() = "fake-profile-name" + override val resourceGroupName: String + get() = "fake-resource-group-name" + } val restTemplateMock: RestTemplate = mock() val azureCredentialProviderMock: AzureCredentialProvider = mock() val purging = AzureContentDeliveryCachePurging(config, restTemplateMock, azureCredentialProviderMock) @@ -73,7 +74,7 @@ class AzureContentStorageConfigCachePurgingTest() { "/resourceGroups/${config.resourceGroupName}" + "/providers/Microsoft.Cdn/profiles/${config.profileName}" + "/afdEndpoints/${config.endpointName}" + - "/purge?api-version=2023-05-01" + "/purge?api-version=2023-05-01", ) } } diff --git a/backend/data/src/test/kotlin/io/tolgee/unit/component/machineTranslation/LanguageTagConvertorTest.kt b/backend/data/src/test/kotlin/io/tolgee/unit/component/machineTranslation/LanguageTagConvertorTest.kt index 47123f0323..bb7146170d 100644 --- a/backend/data/src/test/kotlin/io/tolgee/unit/component/machineTranslation/LanguageTagConvertorTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/unit/component/machineTranslation/LanguageTagConvertorTest.kt @@ -5,7 +5,6 @@ import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test class LanguageTagConvertorTest { - @Test fun `it converts correctly`() { assertThat(LanguageTagConvertor.findSuitableTag(arrayOf("cs", "en", "de"), "cs-CZ_80")) diff --git a/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/PropertiesParserTest.kt b/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/PropertiesParserTest.kt index e26a9e9eaa..ffe2047d90 100644 --- a/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/PropertiesParserTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/PropertiesParserTest.kt @@ -21,11 +21,12 @@ class PropertiesParserTest { fun setup() { importMock = mock() importFile = ImportFile("messages_en.properties", importMock) - importFileDto = ImportFileDto( - "messages_en.properties", - File("src/test/resources/import/example.properties") - .inputStream() - ) + importFileDto = + ImportFileDto( + "messages_en.properties", + File("src/test/resources/import/example.properties") + .inputStream(), + ) fileProcessorContext = FileProcessorContext(importFileDto, importFile) } diff --git a/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/messageFormat/FormatDetectorTest.kt b/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/messageFormat/FormatDetectorTest.kt index bf2f01299b..95aa3572af 100644 --- a/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/messageFormat/FormatDetectorTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/messageFormat/FormatDetectorTest.kt @@ -22,11 +22,12 @@ class FormatDetectorTest { fun setup() { importMock = mock() importFile = ImportFile("exmample.po", importMock) - importFileDto = ImportFileDto( - "exmample.po", - File("src/test/resources/import/po/example.po") - .inputStream() - ) + importFileDto = + ImportFileDto( + "exmample.po", + File("src/test/resources/import/po/example.po") + .inputStream(), + ) fileProcessorContext = FileProcessorContext(importFileDto, importFile) } diff --git a/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/messageFormat/ToICUConverterTest.kt b/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/messageFormat/ToICUConverterTest.kt index 82dbe825ec..dfd4925570 100644 --- a/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/messageFormat/ToICUConverterTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/messageFormat/ToICUConverterTest.kt @@ -23,78 +23,87 @@ class ToICUConverterTest { fun setup() { importMock = mock() importFile = ImportFile("exmample.po", importMock) - importFileDto = ImportFileDto( - "exmample.po", - File("src/test/resources/import/po/example.po") - .inputStream() - ) + importFileDto = + ImportFileDto( + "exmample.po", + File("src/test/resources/import/po/example.po") + .inputStream(), + ) context = FileProcessorContext(importFileDto, importFile) } @Test fun testPhpPlurals() { - val result = ToICUConverter(ULocale("cs"), SupportedFormat.PHP, context).convertPoPlural( - mapOf( - 0 to "Petr má jednoho psa.", - 1 to "Petr má %d psi.", - 2 to "Petr má %d psů." + val result = + ToICUConverter(ULocale("cs"), SupportedFormat.PHP, context).convertPoPlural( + mapOf( + 0 to "Petr má jednoho psa.", + 1 to "Petr má %d psi.", + 2 to "Petr má %d psů.", + ), ) - ) assertThat(result).isEqualTo( "{0, plural,\n" + "one {Petr má jednoho psa.}\n" + "few {Petr má {0, number} psi.}\n" + "other {Petr má {0, number} psů.}\n" + - "}" + "}", ) } @Test fun testPhpMessage() { - val result = ToICUConverter(ULocale("cs"), SupportedFormat.PHP, context) - .convert("hello this is string %s, this is digit %d") + val result = + ToICUConverter(ULocale("cs"), SupportedFormat.PHP, context) + .convert("hello this is string %s, this is digit %d") assertThat(result).isEqualTo("hello this is string {0}, this is digit {1, number}") } @Test fun testPhpMessageEscapes() { - val result = ToICUConverter(ULocale("cs"), SupportedFormat.PHP, context) - .convert("%%s %%s %%%s %%%%s") + val result = + ToICUConverter(ULocale("cs"), SupportedFormat.PHP, context) + .convert("%%s %%s %%%s %%%%s") assertThat(result).isEqualTo("%s %s %{0} %%s") } @Test fun testPhpMessageWithFlags() { - val result = ToICUConverter(ULocale("cs"), SupportedFormat.PHP, context) - .convert("%+- 'as %+- 10s %1$'a +-010s") + val result = + ToICUConverter(ULocale("cs"), SupportedFormat.PHP, context) + .convert("%+- 'as %+- 10s %1$'a +-010s") assertThat(result).isEqualTo("{0} {1} {0}") } @Test fun testPhpMessageMultiple() { - val result = ToICUConverter(ULocale("cs"), SupportedFormat.PHP, context) - .convert("%s %d %d %s") + val result = + ToICUConverter(ULocale("cs"), SupportedFormat.PHP, context) + .convert("%s %d %d %s") assertThat(result).isEqualTo("{0} {1, number} {2, number} {3}") } @Test fun testCMessage() { - val result = ToICUConverter(ULocale("cs"), SupportedFormat.C, context) - .convert("%s %d %c %+- #0f %+- #0llf %+-hhs %0hs %jd") + val result = + ToICUConverter(ULocale("cs"), SupportedFormat.C, context) + .convert("%s %d %c %+- #0f %+- #0llf %+-hhs %0hs %jd") assertThat(result).isEqualTo("{0} {1, number} {2} {3, number} {4, number} {5} {6} {7, number}") } @Test fun testPythonMessage() { - val result = ToICUConverter(ULocale("cs"), SupportedFormat.PYTHON, context) - .convert("%(one)s %(two)d %c %(three)+- #0f %(four)+- #0lf %(five)+-hs %(six)0hs %(seven)ld") + val result = + ToICUConverter(ULocale("cs"), SupportedFormat.PYTHON, context) + .convert("%(one)s %(two)d %c %(three)+- #0f %(four)+- #0lf %(five)+-hs %(six)0hs %(seven)ld") assertThat(result).isEqualTo("{one} {two, number} {2} {three, number} {four, number} {five} {six} {seven, number}") } @Test fun testPhpMessageKey() { - val result = ToICUConverter(ULocale("cs"), SupportedFormat.PHP, context) - .convert("%3${'$'}d hello this is string %2${'$'}s, this is digit %1${'$'}d, and another digit %s") + val result = + ToICUConverter(ULocale("cs"), SupportedFormat.PHP, context) + .convert("%3${'$'}d hello this is string %2${'$'}s, this is digit %1${'$'}d, and another digit %s") assertThat(result) .isEqualTo("{2, number} hello this is string {1}, this is digit {0, number}, and another digit {3}") diff --git a/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/po/PoFileProcessorTest.kt b/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/po/PoFileProcessorTest.kt index 99c194efbf..4ce4c4f4b2 100644 --- a/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/po/PoFileProcessorTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/po/PoFileProcessorTest.kt @@ -32,7 +32,7 @@ class PoFileProcessorTest { "{0, plural,\n" + "one {Eine Seite gelesen wurde.}\n" + "other {{0, number} Seiten gelesen wurden.}\n" + - "}" + "}", ) assertThat(fileProcessorContext.translations.values.toList()[2][0].text) .isEqualTo("Willkommen zurück, {0}! Dein letzter Besuch war am {1}") @@ -42,15 +42,16 @@ class PoFileProcessorTest { fun `adds metadata`() { mockImportFile("example.po") PoFileProcessor(fileProcessorContext).process() - val keyMeta = fileProcessorContext.keys[ - "We connect developers and translators around the globe " + - "in Tolgee for a fantastic localization experience." - ]!!.keyMeta!! + val keyMeta = + fileProcessorContext.keys[ + "We connect developers and translators around the globe " + + "in Tolgee for a fantastic localization experience.", + ]!!.keyMeta!! assertThat(keyMeta.comments).hasSize(2) assertThat(keyMeta.comments[0].text).isEqualTo( "This is the text that should appear next to menu accelerators" + " * that use the super key. If the text on this key isn't typically" + - " * translated on keyboards used for your language, don't translate * this." + " * translated on keyboards used for your language, don't translate * this.", ) assertThat(keyMeta.comments[1].text).isEqualTo("some other comment and other") assertThat(keyMeta.codeReferences).hasSize(6) @@ -79,10 +80,11 @@ class PoFileProcessorTest { private fun mockImportFile(inputStream: InputStream) { importMock = mock() importFile = ImportFile("exmample.po", importMock) - importFileDto = ImportFileDto( - "exmample.po", - inputStream - ) + importFileDto = + ImportFileDto( + "exmample.po", + inputStream, + ) fileProcessorContext = FileProcessorContext(importFileDto, importFile) } } diff --git a/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/po/PoParserTest.kt b/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/po/PoParserTest.kt index b8a97fd04e..05ef19e369 100644 --- a/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/po/PoParserTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/po/PoParserTest.kt @@ -21,11 +21,12 @@ class PoParserTest { fun setup() { importMock = mock() importFile = ImportFile("exmample.po", importMock) - importFileDto = ImportFileDto( - "exmample.po", - File("src/test/resources/import/po/example.po") - .inputStream() - ) + importFileDto = + ImportFileDto( + "exmample.po", + File("src/test/resources/import/po/example.po") + .inputStream(), + ) fileProcessorContext = FileProcessorContext(importFileDto, importFile) } diff --git a/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/xliff/Xliff12FileProcessorTest.kt b/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/xliff/Xliff12FileProcessorTest.kt index 394b229531..4cbc710b96 100644 --- a/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/xliff/Xliff12FileProcessorTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/xliff/Xliff12FileProcessorTest.kt @@ -33,11 +33,12 @@ class Xliff12FileProcessorTest { fun setup() { importMock = mock() importFile = ImportFile("exmample.xliff", importMock) - importFileDto = ImportFileDto( - "exmample.xliff", - File("src/test/resources/import/xliff/example.xliff") - .inputStream() - ) + importFileDto = + ImportFileDto( + "exmample.xliff", + File("src/test/resources/import/xliff/example.xliff") + .inputStream(), + ) fileProcessorContext = FileProcessorContext(importFileDto, importFile) } @@ -55,28 +56,29 @@ class Xliff12FileProcessorTest { assertThat(keyMeta.comments).hasSize(1) assertThat(keyMeta.comments[0].text).isEqualTo( "Refers to the installed version." + - " For example: \"Release Version: 1.23\"" + " For example: \"Release Version: 1.23\"", ) assertThat(keyMeta.codeReferences).hasSize(1) assertThat(keyMeta.codeReferences[0].path).isEqualTo("../src/ui/components/VPNAboutUs.qml") assertThat(fileProcessorContext.translations["systray.quit"]!![0].text).isEqualTo( "" + " 'Add to favorites'}}\" id=\"INTERPOLATION\">", ) assertThat(fileProcessorContext.translations["systray.quit"]!![1].text) .isEqualTo( "" + " 'Add to favorites'}}\" id=\"INTERPOLATION\">", ) } @Test fun `processes xliff 12 fast enough`() { - importFileDto = ImportFileDto( - "exmample.xliff", - File("src/test/resources/import/xliff/larger.xlf") - .inputStream() - ) + importFileDto = + ImportFileDto( + "exmample.xliff", + File("src/test/resources/import/xliff/larger.xlf") + .inputStream(), + ) fileProcessorContext = FileProcessorContext(importFileDto, importFile) xmlStreamReader = inputFactory.createXMLEventReader(importFileDto.inputStream) val start = System.currentTimeMillis() @@ -86,11 +88,12 @@ class Xliff12FileProcessorTest { @Test fun `handles errors correctly`() { - importFileDto = ImportFileDto( - "exmample.xliff", - File("src/test/resources/import/xliff/error_example.xliff") - .inputStream() - ) + importFileDto = + ImportFileDto( + "exmample.xliff", + File("src/test/resources/import/xliff/error_example.xliff") + .inputStream(), + ) xmlStreamReader = inputFactory.createXMLEventReader(importFileDto.inputStream) fileProcessorContext = FileProcessorContext(importFileDto, importFile) Xliff12FileProcessor(fileProcessorContext, xmlEventReader).process() diff --git a/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/xliff/XliffFileProcessorTest.kt b/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/xliff/XliffFileProcessorTest.kt index 999cec7430..2ea25fb1f0 100644 --- a/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/xliff/XliffFileProcessorTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/unit/service/dataImport/processors/processors/xliff/XliffFileProcessorTest.kt @@ -21,11 +21,12 @@ class XliffFileProcessorTest { fun setup() { importMock = mock() importFile = ImportFile("exmample.xliff", importMock) - importFileDto = ImportFileDto( - "exmample.xliff", - File("src/test/resources/import/xliff/example.xliff") - .inputStream() - ) + importFileDto = + ImportFileDto( + "exmample.xliff", + File("src/test/resources/import/xliff/example.xliff") + .inputStream(), + ) fileProcessorContext = FileProcessorContext(importFileDto, importFile) } diff --git a/backend/data/src/test/kotlin/io/tolgee/unit/util/SlugGeneratorTest.kt b/backend/data/src/test/kotlin/io/tolgee/unit/util/SlugGeneratorTest.kt index 2a399d7c11..35ff02382a 100644 --- a/backend/data/src/test/kotlin/io/tolgee/unit/util/SlugGeneratorTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/unit/util/SlugGeneratorTest.kt @@ -7,7 +7,6 @@ import io.tolgee.util.SlugGenerator import org.junit.jupiter.api.Test class SlugGeneratorTest { - private val slugGenerator: SlugGenerator = SlugGenerator() @Test diff --git a/backend/data/src/test/kotlin/io/tolgee/util/WordCounterTest.kt b/backend/data/src/test/kotlin/io/tolgee/util/WordCounterTest.kt index e8f150cbf0..cdfbb4408c 100644 --- a/backend/data/src/test/kotlin/io/tolgee/util/WordCounterTest.kt +++ b/backend/data/src/test/kotlin/io/tolgee/util/WordCounterTest.kt @@ -4,7 +4,6 @@ import io.tolgee.testing.assertions.Assertions.assertThat import org.junit.jupiter.api.Test internal class WordCounterTest { - @Test fun `returns ULocale from tag`() { assertThat(WordCounter.getLocaleFromTag("cs_CZ").language).isEqualTo("cs") diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/DebugFeaturesController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/DebugFeaturesController.kt index e6408d3181..3c2fb96ec4 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/DebugFeaturesController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/DebugFeaturesController.kt @@ -18,23 +18,25 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping(value = ["internal/features"]) @Transactional class DebugFeaturesController( - val enabledFeaturesProvider: EnabledFeaturesProvider + val enabledFeaturesProvider: EnabledFeaturesProvider, ) { @PutMapping(value = ["/toggle"]) @Transactional fun toggleFeature( feature: Feature, @Schema( - description = "If true, feature will be enabled, if false, disabled, " + - "if null features will behave as if they were not set" + description = + "If true, feature will be enabled, if false, disabled, " + + "if null features will behave as if they were not set", ) - enabled: Boolean? + enabled: Boolean?, ) { - val provider = enabledFeaturesProvider as? PublicEnabledFeaturesProvider - ?: throw BadRequestException( - "EnabledFeaturesProvider is not PublicEnabledFeaturesProvider. " + - "Disable billing module to use this endpoint." - ) + val provider = + enabledFeaturesProvider as? PublicEnabledFeaturesProvider + ?: throw BadRequestException( + "EnabledFeaturesProvider is not PublicEnabledFeaturesProvider. " + + "Disable billing module to use this endpoint.", + ) if (enabled == null) { provider.forceEnabled = null diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/PropertiesController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/PropertiesController.kt index 3efd5c466b..1b2d553ff2 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/PropertiesController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/PropertiesController.kt @@ -24,11 +24,14 @@ import kotlin.reflect.full.hasAnnotation @RequestMapping(value = ["internal/properties"]) @Transactional class PropertiesController( - val tolgeeProperties: TolgeeProperties + val tolgeeProperties: TolgeeProperties, ) { @PutMapping(value = ["/set"]) @Transactional - fun setProperty(@RequestBody @Valid setPropertyDto: SetPropertyDto) { + fun setProperty( + @RequestBody @Valid + setPropertyDto: SetPropertyDto, + ) { val name = setPropertyDto.name var instance: Any = tolgeeProperties name.split(".").let { namePath -> diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/SqlController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/SqlController.kt index 70b420016f..a2a948835e 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/SqlController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/SqlController.kt @@ -15,18 +15,21 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping(value = ["internal/sql"]) @Transactional class SqlController( - val entityManager: EntityManager + val entityManager: EntityManager, ) { - @PostMapping(value = ["/list"]) @Transactional - fun getList(@RequestBody query: String): MutableList? { + fun getList( + @RequestBody query: String, + ): MutableList? { return entityManager.createNativeQuery(query).resultList } @PostMapping(value = ["/execute"]) @Transactional - fun execute(@RequestBody query: String) { + fun execute( + @RequestBody query: String, + ) { entityManager.createNativeQuery(query).executeUpdate() } } diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/TestClockController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/TestClockController.kt index 8a155e5ddd..92dccdb44e 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/TestClockController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/TestClockController.kt @@ -19,14 +19,14 @@ import java.util.* @RequestMapping(value = ["internal/time"]) @Transactional class TestClockController( - val currentDateProvider: CurrentDateProvider + val currentDateProvider: CurrentDateProvider, ) { @PutMapping(value = ["/{dateTimeString}"]) @Operation(description = "Set's the time machine, so the app is using this date as current date") fun setTime( @PathVariable @Schema(description = "Current unix timestamp (milliseconds), or in yyyy-MM-dd HH:mm:ss z") - dateTimeString: String + dateTimeString: String, ) { try { currentDateProvider.forcedDate = Date(dateTimeString.toLong()) diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/WebhookTestingController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/WebhookTestingController.kt index 7330a5711e..22352a56bb 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/WebhookTestingController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/WebhookTestingController.kt @@ -16,7 +16,7 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping(value = ["internal/webhook-testing"]) @Transactional class WebhookTestingController( - val tolgeeProperties: TolgeeProperties + val tolgeeProperties: TolgeeProperties, ) { @PostMapping(value = [""]) @Transactional diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/AbstractE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/AbstractE2eDataController.kt similarity index 79% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/AbstractE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/AbstractE2eDataController.kt index 89af35817e..8e410f6c07 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/AbstractE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/AbstractE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.tolgee.development.testDataBuilder.TestDataService import io.tolgee.development.testDataBuilder.builders.TestDataBuilder @@ -50,15 +50,18 @@ abstract class AbstractE2eDataController { fun getStandardResult(data: TestDataBuilder): StandardTestDataResult { return StandardTestDataResult( - projects = data.data.projects.map { - StandardTestDataResult.ProjectModel(name = it.self.name, id = it.self.id) - }, - users = data.data.userAccounts.map { - StandardTestDataResult.UserModel(name = it.self.name, username = it.self.username, id = it.self.id) - }, - organizations = data.data.organizations.map { - StandardTestDataResult.OrganizationModel(id = it.self.id, name = it.self.name, slug = it.self.slug) - } + projects = + data.data.projects.map { + StandardTestDataResult.ProjectModel(name = it.self.name, id = it.self.id) + }, + users = + data.data.userAccounts.map { + StandardTestDataResult.UserModel(name = it.self.name, username = it.self.username, id = it.self.id) + }, + organizations = + data.data.organizations.map { + StandardTestDataResult.OrganizationModel(id = it.self.id, name = it.self.name, slug = it.self.slug) + }, ) } @@ -80,23 +83,23 @@ abstract class AbstractE2eDataController { data class StandardTestDataResult( val projects: List, val users: List, - val organizations: List + val organizations: List, ) { data class UserModel( val name: String, val username: String, - val id: Long + val id: Long, ) data class ProjectModel( val name: String, - val id: Long + val id: Long, ) data class OrganizationModel( val id: Long, val slug: String, - val name: String + val name: String, ) } } diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/AdministrationE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/AdministrationE2eDataController.kt similarity index 95% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/AdministrationE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/AdministrationE2eDataController.kt index 2bc154f4c1..d5df687fda 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/AdministrationE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/AdministrationE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.builders.TestDataBuilder diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ApiKeysE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ApiKeysE2eDataController.kt similarity index 94% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ApiKeysE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ApiKeysE2eDataController.kt index eac7988b8d..ad53631929 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ApiKeysE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ApiKeysE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.builders.TestDataBuilder diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/AvatarsE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/AvatarsE2eDataController.kt similarity index 91% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/AvatarsE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/AvatarsE2eDataController.kt index 755fd2f90e..88c9bd50d0 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/AvatarsE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/AvatarsE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.builders.TestDataBuilder @@ -22,7 +22,7 @@ class AvatarsE2eDataController() : AbstractE2eDataController() { testDataService.saveTestData(data.root) return mapOf( "projectId" to data.projectBuilder.self.id, - "organizationSlug" to data.organization.slug + "organizationSlug" to data.organization.slug, ) } diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/BatchJobsE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/BatchJobsE2eDataController.kt similarity index 94% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/BatchJobsE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/BatchJobsE2eDataController.kt index b8ba0e3dff..1f0dc4f0a9 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/BatchJobsE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/BatchJobsE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.builders.TestDataBuilder diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ContentDeliveryE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ContentDeliveryE2eDataController.kt similarity index 94% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ContentDeliveryE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ContentDeliveryE2eDataController.kt index 3eb9b63d21..8bc4111e5e 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ContentDeliveryE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ContentDeliveryE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.builders.TestDataBuilder diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/FormerUserE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/FormerUserE2eDataController.kt similarity index 85% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/FormerUserE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/FormerUserE2eDataController.kt index d95a77aee1..248ae6a06f 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/FormerUserE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/FormerUserE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.builders.TestDataBuilder @@ -17,9 +17,10 @@ import org.springframework.web.bind.annotation.RestController class FormerUserE2eDataController() : AbstractE2eDataController() { @GetMapping(value = ["/generate"]) fun generateBasicTestData(): Map { - val testData = FormerUserTestData().also { - testDataService.saveTestData(it.root) - } + val testData = + FormerUserTestData().also { + testDataService.saveTestData(it.root) + } return mapOf("projectId" to testData.project.id) } diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ImportE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ImportE2eDataController.kt similarity index 84% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ImportE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ImportE2eDataController.kt index 12193b6da1..1d2e0e2852 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ImportE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ImportE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.TestDataService @@ -25,7 +25,7 @@ class ImportE2eDataController( private val entityManager: EntityManager, private val testDataService: TestDataService, private val projectService: ProjectService, - private val userAccountService: UserAccountService + private val userAccountService: UserAccountService, ) { @GetMapping(value = ["/generate"]) @Transactional @@ -92,7 +92,6 @@ class ImportE2eDataController( val file = data.importBuilder.data.importFiles[0] (0..90).forEach { file.addImportLanguage { - name = "lng $it" } } @@ -103,28 +102,30 @@ class ImportE2eDataController( @GetMapping(value = ["/generate-base"]) @Transactional fun generateBaseData(): Map { - val data = testDataService.saveTestData { - val userAccountBuilder = addUserAccount { - username = "franta" - name = "Frantisek Dobrota" - } + val data = + testDataService.saveTestData { + val userAccountBuilder = + addUserAccount { + username = "franta" + name = "Frantisek Dobrota" + } - userAccountBuilder.build buildUserAccount@{ - addProject { - organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self - name = "Repo" - }.build buildProject@{ - val english = addEnglish() - addGerman() - self.baseLanguage = english.self - addPermission { - type = ProjectPermissionType.MANAGE - user = this@buildUserAccount.self - project = this@buildProject.self + userAccountBuilder.build buildUserAccount@{ + addProject { + organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self + name = "Repo" + }.build buildProject@{ + val english = addEnglish() + addGerman() + self.baseLanguage = english.self + addPermission { + type = ProjectPermissionType.MANAGE + user = this@buildUserAccount.self + project = this@buildProject.self + } } } } - } return mapOf("id" to data.data.projects[0].self.id) } diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ImportNamespacesE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ImportNamespacesE2eDataController.kt similarity index 93% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ImportNamespacesE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ImportNamespacesE2eDataController.kt index 1757545c28..88a8a45a31 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ImportNamespacesE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ImportNamespacesE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.builders.TestDataBuilder diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/LanguageE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/LanguageE2eDataController.kt similarity index 53% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/LanguageE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/LanguageE2eDataController.kt index 99cab6dfdf..d652f208d3 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/LanguageE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/LanguageE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.TestDataService @@ -19,46 +19,47 @@ import org.springframework.web.bind.annotation.RestController class LanguageE2eDataController( private val testDataService: TestDataService, private val projectService: ProjectService, - private val userAccountService: UserAccountService + private val userAccountService: UserAccountService, ) { @GetMapping(value = ["/generate"]) @Transactional fun generateBaseData(): Map { - val data = testDataService.saveTestData { - val userAccountBuilder = addUserAccount { - username = "franta" - name = "Frantisek Dobrota" - } - val userAccount = userAccountBuilder.self - userAccountBuilder.build { - val projectBuilder = addProject { - organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self - name = "Project" - } - - projectBuilder.build { - addPermission { - type = ProjectPermissionType.MANAGE - user = userAccount - project = projectBuilder.self + val data = + testDataService.saveTestData { + val userAccountBuilder = + addUserAccount { + username = "franta" + name = "Frantisek Dobrota" } - addLanguage { + val userAccount = userAccountBuilder.self + userAccountBuilder.build { + val projectBuilder = + addProject { + organizationOwner = userAccountBuilder.defaultOrganizationBuilder.self + name = "Project" + } - name = "English" - tag = "en" - flagEmoji = "\uD83C\uDDEC\uD83C\uDDE7" - originalName = "English" - } - addLanguage { - - name = "German" - tag = "de" - flagEmoji = "\uD83C\uDDE9\uD83C\uDDEA" - originalName = "Deutsch" + projectBuilder.build { + addPermission { + type = ProjectPermissionType.MANAGE + user = userAccount + project = projectBuilder.self + } + addLanguage { + name = "English" + tag = "en" + flagEmoji = "\uD83C\uDDEC\uD83C\uDDE7" + originalName = "English" + } + addLanguage { + name = "German" + tag = "de" + flagEmoji = "\uD83C\uDDE9\uD83C\uDDEA" + originalName = "Deutsch" + } } } } - } return mapOf("id" to data.data.projects[0].self.id) } diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/LanguagePermissionsE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/LanguagePermissionsE2eDataController.kt similarity index 95% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/LanguagePermissionsE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/LanguagePermissionsE2eDataController.kt index 20ede165f9..0a5a1ea292 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/LanguagePermissionsE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/LanguagePermissionsE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.builders.TestDataBuilder diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/NamespacesE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/NamespacesE2eDataController.kt similarity index 93% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/NamespacesE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/NamespacesE2eDataController.kt index 0bf7b52e3e..197d479a84 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/NamespacesE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/NamespacesE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.builders.TestDataBuilder diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/NewOrganizationE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/NewOrganizationE2eDataController.kt similarity index 95% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/NewOrganizationE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/NewOrganizationE2eDataController.kt index b01902c9f4..17df7ba6d9 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/NewOrganizationE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/NewOrganizationE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.builders.TestDataBuilder diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/OrganizationE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/OrganizationE2eDataController.kt similarity index 61% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/OrganizationE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/OrganizationE2eDataController.kt index c5573b4572..cd594fef79 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/OrganizationE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/OrganizationE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.DbPopulatorReal @@ -27,17 +27,18 @@ class OrganizationE2eDataController( private val userAccountService: UserAccountService, private val dbPopulatorReal: DbPopulatorReal, private val organizationRoleService: OrganizationRoleService, - private val transactionManager: PlatformTransactionManager + private val transactionManager: PlatformTransactionManager, ) : Logging { @GetMapping(value = ["/generate"]) @Transactional fun createOrganizations(): Map> { - val organizations = data.map { - organizationService.create( - it.dto, - this.dbPopulatorReal.createUserIfNotExists(it.owner.email, null, it.owner.name) - ) - } + val organizations = + data.map { + organizationService.create( + it.dto, + this.dbPopulatorReal.createUserIfNotExists(it.owner.email, null, it.owner.name), + ) + } data.forEach { dataItem -> organizationService.findAllByName(dataItem.dto.name).forEach { organization -> @@ -60,7 +61,7 @@ class OrganizationE2eDataController( traceLogMeasureTime("cleanupOrganizations") { executeInNewRepeatableTransaction( transactionManager, - isolationLevel = TransactionDefinition.ISOLATION_SERIALIZABLE + isolationLevel = TransactionDefinition.ISOLATION_SERIALIZABLE, ) { traceLogMeasureTime("delete what-a-nice-organization") { organizationService.findAllByName("What a nice organization").forEach { @@ -81,10 +82,11 @@ class OrganizationE2eDataController( } } traceLogMeasureTime("delete users") { - val owners = data.mapNotNull { - if (it.owner.name == "admin") return@mapNotNull null - it.owner.email - } + val owners = + data.mapNotNull { + if (it.owner.name == "admin") return@mapNotNull null + it.owner.email + } userAccountService.deleteByUserNames(owners) } } @@ -94,7 +96,7 @@ class OrganizationE2eDataController( companion object { data class UserData( val email: String, - val name: String = email + val name: String = email, ) data class OrganizationDataItem( @@ -104,79 +106,88 @@ class OrganizationE2eDataController( val members: MutableList = mutableListOf(), ) - val data = mutableListOf( - OrganizationDataItem( - dto = OrganizationDto( - name = "Google", - description = "An organization made by google company", + val data = + mutableListOf( + OrganizationDataItem( + dto = + OrganizationDto( + name = "Google", + description = "An organization made by google company", + ), + owner = UserData("admin"), ), - owner = UserData("admin") - ), - OrganizationDataItem( - dto = OrganizationDto( - name = "Netsuite", - description = "A system for everything", + OrganizationDataItem( + dto = + OrganizationDto( + name = "Netsuite", + description = "A system for everything", + ), + owner = UserData("evan@netsuite.com", "Evan Goldberg"), ), - owner = UserData("evan@netsuite.com", "Evan Goldberg") - ), - OrganizationDataItem( - dto = OrganizationDto( - name = "Microsoft", - description = "A first software company ever or something like that.", + OrganizationDataItem( + dto = + OrganizationDto( + name = "Microsoft", + description = "A first software company ever or something like that.", + ), + owner = UserData("gates@microsoft.com", "Bill Gates"), + members = mutableListOf("admin"), ), - owner = UserData("gates@microsoft.com", "Bill Gates"), - members = mutableListOf("admin") - ), - OrganizationDataItem( - dto = OrganizationDto( - name = "Tolgee", - description = "This is us", + OrganizationDataItem( + dto = + OrganizationDto( + name = "Tolgee", + description = "This is us", + ), + owner = UserData("admin"), + otherOwners = mutableListOf("evan@netsuite.com"), + members = mutableListOf("gates@microsoft.com", "cukrberg@facebook.com"), ), - owner = UserData("admin"), - otherOwners = mutableListOf("evan@netsuite.com"), - members = mutableListOf("gates@microsoft.com", "cukrberg@facebook.com") - ), - OrganizationDataItem( - dto = OrganizationDto( - name = "Facebook", - description = """ + OrganizationDataItem( + dto = + OrganizationDto( + name = "Facebook", + description = + """ |This is an organization providing a great service to everyone for free. |They also develop amazing things like react and other open source stuff. |However, they sell our data to companies. - """.trimMargin(), + """.trimMargin(), + ), + owner = UserData("cukrberg@facebook.com", "Mark Cukrberg"), + otherOwners = mutableListOf("admin"), ), - owner = UserData("cukrberg@facebook.com", "Mark Cukrberg"), - otherOwners = mutableListOf("admin") - ), - OrganizationDataItem( - dto = OrganizationDto( - name = "Unknown company", - description = "We are very unknown.", + OrganizationDataItem( + dto = + OrganizationDto( + name = "Unknown company", + description = "We are very unknown.", + ), + owner = UserData("admin"), ), - owner = UserData("admin") - ), - OrganizationDataItem( - dto = OrganizationDto( - name = "Techfides solutions s.r.o", - description = "Lets develop the future", - + OrganizationDataItem( + dto = + OrganizationDto( + name = "Techfides solutions s.r.o", + description = "Lets develop the future", + ), + owner = UserData("admin"), ), - owner = UserData("admin") ) - ) init { (1..20).forEach { number -> val email = "owner@zzzcool$number.com" data.add( OrganizationDataItem( - dto = OrganizationDto( - name = "ZZZ Cool company $number", - description = "We are Z Cool company $number. What a nice day!", - ), + dto = + OrganizationDto( + name = "ZZZ Cool company $number", + description = "We are Z Cool company $number. What a nice day!", + ), otherOwners = mutableListOf("admin"), owner = UserData(email), - ) + ), ) data.find { item -> item.dto.name == "Facebook" }!!.otherOwners.add(email) } diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/PatE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/PatE2eDataController.kt similarity index 94% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/PatE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/PatE2eDataController.kt index 5af9d749f1..14921e04c0 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/PatE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/PatE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.builders.TestDataBuilder diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/PermissionsE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/PermissionsE2eDataController.kt similarity index 92% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/PermissionsE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/PermissionsE2eDataController.kt index 49b931c312..b52c0d2e37 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/PermissionsE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/PermissionsE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.builders.TestDataBuilder @@ -20,7 +20,6 @@ import org.springframework.web.context.annotation.RequestScope @Transactional @RequestScope class PermissionsE2eDataController() : AbstractE2eDataController() { - @GetMapping(value = ["/generate-with-user"]) @Transactional fun generateWithPermissions( @@ -28,14 +27,14 @@ class PermissionsE2eDataController() : AbstractE2eDataController() { @RequestParam type: ProjectPermissionType?, @RequestParam viewLanguageTags: List?, @RequestParam translateLanguageTags: List?, - @RequestParam stateChangeLanguageTags: List? + @RequestParam stateChangeLanguageTags: List?, ): StandardTestDataResult { this.permissionsTestData.addUserWithPermissions( scopes = Scope.parse(scopes).toList(), type = type, viewLanguageTags = viewLanguageTags, translateLanguageTags = translateLanguageTags, - stateChangeLanguageTags = stateChangeLanguageTags + stateChangeLanguageTags = stateChangeLanguageTags, ) return generate() } diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ProjectLeavingE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectLeavingE2eDataController.kt similarity index 94% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ProjectLeavingE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectLeavingE2eDataController.kt index b661e21979..dcfd4cbeec 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ProjectLeavingE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectLeavingE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.TestDataService @@ -21,7 +21,7 @@ class ProjectLeavingE2eDataController( private val testDataService: TestDataService, private val projectService: ProjectService, private val userAccountService: UserAccountService, - private val organizationService: OrganizationService + private val organizationService: OrganizationService, ) { @GetMapping(value = ["/generate"]) @Transactional diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ProjectListDashboardE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectListDashboardE2eDataController.kt similarity index 93% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ProjectListDashboardE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectListDashboardE2eDataController.kt index 92863775a8..32ce1d2e80 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ProjectListDashboardE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectListDashboardE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.TestDataService @@ -19,7 +19,7 @@ import org.springframework.web.bind.annotation.RestController class ProjectListDashboardE2eDataController( private val testDataService: TestDataService, private val projectService: ProjectService, - private val userAccountService: UserAccountService + private val userAccountService: UserAccountService, ) { @GetMapping(value = ["/generate"]) @Transactional diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ProjectTransferringE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectTransferringE2eDataController.kt similarity index 94% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ProjectTransferringE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectTransferringE2eDataController.kt index 3210a5706b..2056baffe8 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ProjectTransferringE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectTransferringE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.TestDataService @@ -21,7 +21,7 @@ class ProjectTransferringE2eDataController( private val testDataService: TestDataService, private val projectService: ProjectService, private val userAccountService: UserAccountService, - private val organizationService: OrganizationService + private val organizationService: OrganizationService, ) { @GetMapping(value = ["/generate"]) @Transactional diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectsE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectsE2eDataController.kt new file mode 100644 index 0000000000..44fd1223d9 --- /dev/null +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/ProjectsE2eDataController.kt @@ -0,0 +1,310 @@ +package io.tolgee.controllers.internal.e2eData + +import io.swagger.v3.oas.annotations.Hidden +import io.tolgee.dtos.request.LanguageDto +import io.tolgee.dtos.request.auth.SignUpDto +import io.tolgee.dtos.request.key.CreateKeyDto +import io.tolgee.model.Organization +import io.tolgee.model.Permission +import io.tolgee.model.Project +import io.tolgee.model.UserAccount +import io.tolgee.model.enums.ProjectPermissionType +import io.tolgee.repository.OrganizationRepository +import io.tolgee.repository.PermissionRepository +import io.tolgee.repository.ProjectRepository +import io.tolgee.repository.UserAccountRepository +import io.tolgee.service.LanguageService +import io.tolgee.service.key.KeyService +import io.tolgee.service.organization.OrganizationRoleService +import io.tolgee.service.organization.OrganizationService +import io.tolgee.service.project.ProjectService +import io.tolgee.service.security.SignUpService +import io.tolgee.service.security.UserAccountService +import io.tolgee.util.Logging +import io.tolgee.util.executeInNewRepeatableTransaction +import jakarta.persistence.EntityManager +import org.springframework.transaction.PlatformTransactionManager +import org.springframework.transaction.annotation.Transactional +import org.springframework.web.bind.annotation.CrossOrigin +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@CrossOrigin(origins = ["*"]) +@Hidden +@RequestMapping(value = ["internal/e2e-data/projects"]) +@Transactional +class ProjectsE2eDataController( + private val organizationService: OrganizationService, + private val userAccountService: UserAccountService, + private val organizationRoleService: OrganizationRoleService, + private val organizationRepository: OrganizationRepository, + private val projectService: ProjectService, + private val projectRepository: ProjectRepository, + private val userAccountRepository: UserAccountRepository, + private val permissionRepository: PermissionRepository, + private val keyService: KeyService, + private val languageService: LanguageService, + private val entityManager: EntityManager, + private val transactionManager: PlatformTransactionManager, + private val signUpService: SignUpService, +) : Logging { + @GetMapping(value = ["/generate"]) + @Transactional + fun createProjects() { + val createdUsers = mutableMapOf() + + users.forEach { + createdUsers[it.email] = + signUpService.dtoToEntity( + SignUpDto( + name = it.name, + email = it.email, + password = "admin", + ), + ) + } + + userAccountRepository.saveAll(createdUsers.values) + + val createdOrganizations = + organizations.map { + val organization = + Organization( + name = it.name, + slug = organizationService.generateSlug(it.name), + ) + + val basePermission = Permission(organization = organization) + organization.basePermission = basePermission + permissionRepository.save(basePermission) + organizationRepository.save(organization) + + it.owners.forEach { + createdUsers[it]!!.let { user -> + organizationRoleService.grantOwnerRoleToUser(user, organization) + } + } + + it.members.forEach { + createdUsers[it]!!.let { user -> + organizationRoleService.grantMemberRoleToUser(user, organization) + } + } + organization + } + + projects.forEach { projectData -> + val organizationOwner = + createdOrganizations.find { + it.name.lowercase().replace("[^A-Za-z0-9]".toRegex(), "-") == projectData.organizationOwner.lowercase() + } + + val project = + projectRepository.save( + Project( + name = projectData.name, + slug = projectService.generateSlug(projectData.name), + organizationOwner = organizationOwner!!, + ), + ) + + projectData.permittedUsers.forEach { + val user = createdUsers[it.userName]!! + permissionRepository.save(Permission(project = project, user = user, type = it.permission)) + } + + val createdLanguages = mutableListOf() + + projectData.keyData.forEach { + it.value.keys.forEach { + if (!createdLanguages.contains(it)) { + languageService.createLanguage(LanguageDto(name = it, tag = it), project) + createdLanguages.add(it) + } + } + keyService.create(project, CreateKeyDto(it.key, null, it.value)) + } + } + } + + @GetMapping(value = ["/clean"]) + fun cleanupProjects() { + executeInNewRepeatableTransaction(transactionManager = transactionManager) { + entityManager.createNativeQuery("SET join_collapse_limit TO 1").executeUpdate() + projectService.deleteAllByName("I am a great project") + + projects.forEach { + traceLogMeasureTime("deleteAllByName: ${it.name}") { + projectService.deleteAllByName(it.name) + } + } + + organizations.forEach { + organizationService.findAllByName(it.name).forEach { org -> + organizationService.delete(org) + } + } + + traceLogMeasureTime("deleteUsers") { + val usernames = users.map { it.email } + userAccountService.deleteByUserNames(usernames) + } + } + } + + companion object { + data class PermittedUserData( + val userName: String, + val permission: ProjectPermissionType, + ) + + data class UserData( + val email: String, + val name: String = email, + ) + + data class OrganizationData( + val basePermission: ProjectPermissionType, + val name: String, + val owners: MutableList = mutableListOf(), + val members: MutableList = mutableListOf(), + ) + + data class ProjectDataItem( + val name: String, + val organizationOwner: String, + val permittedUsers: MutableList = mutableListOf(), + val keyData: Map> = mutableMapOf(), + ) + + val users = + mutableListOf( + UserData("gates@microsoft.com", "Bill Gates"), + UserData("evan@netsuite.com", "Evan Goldberg"), + UserData("cukrberg@facebook.com", "Mark Cukrberg"), + UserData("vaclav.novak@fake.com", "Vaclav Novak"), + UserData("john@doe.com", "John Doe"), + ) + + val organizations = + mutableListOf( + OrganizationData( + name = "Facebook", + basePermission = ProjectPermissionType.MANAGE, + owners = mutableListOf("cukrberg@facebook.com"), + members = mutableListOf("john@doe.com"), + ), + OrganizationData( + name = "Microsoft", + basePermission = ProjectPermissionType.EDIT, + owners = mutableListOf("gates@microsoft.com"), + members = mutableListOf("john@doe.com", "cukrberg@facebook.com"), + ), + OrganizationData( + name = "Vaclav organization", + basePermission = ProjectPermissionType.EDIT, + owners = mutableListOf("vaclav.novak@fake.com"), + ), + ) + + val projects = + mutableListOf( + ProjectDataItem( + name = "Facebook itself", + organizationOwner = "facebook", + permittedUsers = + mutableListOf( + PermittedUserData( + "vaclav.novak@fake.com", + ProjectPermissionType.TRANSLATE, + ), + ), + keyData = mapOf(Pair("test", mapOf(Pair("en", "This is test text!")))), + ), + ProjectDataItem( + name = "Microsoft Word", + organizationOwner = "microsoft", + permittedUsers = + mutableListOf( + PermittedUserData( + "vaclav.novak@fake.com", + ProjectPermissionType.MANAGE, + ), + ), + keyData = mapOf(Pair("test", mapOf(Pair("en", "This is test text!")))), + ), + ProjectDataItem( + name = "Microsoft Excel", + organizationOwner = "microsoft", + permittedUsers = + mutableListOf( + PermittedUserData( + "vaclav.novak@fake.com", + ProjectPermissionType.EDIT, + ), + ), + keyData = mapOf(Pair("test", mapOf(Pair("en", "This is test text!")))), + ), + ProjectDataItem( + name = "Microsoft Powerpoint", + organizationOwner = "microsoft", + permittedUsers = + mutableListOf( + PermittedUserData( + "vaclav.novak@fake.com", + ProjectPermissionType.TRANSLATE, + ), + ), + keyData = mapOf(Pair("test", mapOf(Pair("en", "This is test text!")))), + ), + ProjectDataItem( + name = "Microsoft Frontpage", + organizationOwner = "microsoft", + permittedUsers = + mutableListOf( + PermittedUserData( + "vaclav.novak@fake.com", + ProjectPermissionType.VIEW, + ), + ), + keyData = mapOf(Pair("test", mapOf(Pair("en", "This is test text!")))), + ), + ProjectDataItem( + name = "Vaclav's cool project", + permittedUsers = + mutableListOf( + PermittedUserData( + "cukrberg@facebook.com", + ProjectPermissionType.VIEW, + ), + ), + keyData = mapOf(Pair("test", mapOf(Pair("en", "This is test text!")))), + organizationOwner = "vaclav-organization", + ), + ProjectDataItem( + name = "Vaclav's funny project", + organizationOwner = "vaclav-organization", + permittedUsers = + mutableListOf( + PermittedUserData( + "cukrberg@facebook.com", + ProjectPermissionType.MANAGE, + ), + ), + keyData = mapOf(Pair("test", mapOf(Pair("en", "This is test text!")))), + ), + ) + + init { + (1..20).forEach { number -> + val email = "owner@zzzcool$number.com" + users.add(UserData(email)) + projects.find { item -> item.name == "Microsoft Word" }!!.permittedUsers.add( + PermittedUserData(email, ProjectPermissionType.EDIT), + ) + } + } + } +} diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/SensitiveOperationProtectionE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/SensitiveOperationProtectionE2eDataController.kt similarity index 97% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/SensitiveOperationProtectionE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/SensitiveOperationProtectionE2eDataController.kt index fe78b2c2ef..a63ca1c30e 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/SensitiveOperationProtectionE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/SensitiveOperationProtectionE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.component.CurrentDateProvider @@ -40,7 +40,7 @@ class SensitiveOperationProtectionE2eDataController( "frantasProjectId" to data.frantasProject.id, "pepasProjectId" to data.pepasProject.id, "frantaExpiredSuperJwt" to expiredToken, - "pepaExpiredSuperJwt" to jwtService.emitToken(data.pepa.id, false) + "pepaExpiredSuperJwt" to jwtService.emitToken(data.pepa.id, false), ) } diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/TranslationCommentsE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/TranslationCommentsE2eDataController.kt similarity index 97% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/TranslationCommentsE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/TranslationCommentsE2eDataController.kt index 8c9441da6c..882389707d 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/TranslationCommentsE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/TranslationCommentsE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.TestDataService diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/TranslationDisabledE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/TranslationDisabledE2eDataController.kt similarity index 93% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/TranslationDisabledE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/TranslationDisabledE2eDataController.kt index 835578ec76..98b06d5592 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/TranslationDisabledE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/TranslationDisabledE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.builders.TestDataBuilder diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/TranslationNsAndTagsE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/TranslationNsAndTagsE2eDataController.kt similarity index 93% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/TranslationNsAndTagsE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/TranslationNsAndTagsE2eDataController.kt index d1ce062c00..f4825ee13e 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/TranslationNsAndTagsE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/TranslationNsAndTagsE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.builders.TestDataBuilder diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/TranslationSingleE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/TranslationSingleE2eDataController.kt similarity index 97% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/TranslationSingleE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/TranslationSingleE2eDataController.kt index e6c5d262f2..ac640734fa 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/TranslationSingleE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/TranslationSingleE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.TestDataService diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/TranslationsE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/TranslationsE2eDataController.kt similarity index 88% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/TranslationsE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/TranslationsE2eDataController.kt index 51b0343fd4..72f88934a4 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/TranslationsE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/TranslationsE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.TestDataService @@ -23,11 +23,14 @@ class TranslationsE2eDataController( private val keyService: KeyService, private val projectService: ProjectService, private val testDataService: TestDataService, - private val userAccountService: UserAccountService + private val userAccountService: UserAccountService, ) { @GetMapping(value = ["/generate/{projectId}/{number}"]) @Transactional - fun generateKeys(@PathVariable projectId: Long, @PathVariable number: Long) { + fun generateKeys( + @PathVariable projectId: Long, + @PathVariable number: Long, + ) { val project = projectService.get(projectId) (0..(number - 1)).forEach { num -> val paddedNum = num.toString().padStart(2, '0') @@ -38,9 +41,9 @@ class TranslationsE2eDataController( null, mapOf( Pair("en", "Cool translated text $paddedNum"), - Pair("cs", "Studený přeložený text $paddedNum") - ) - ) + Pair("cs", "Studený přeložený text $paddedNum"), + ), + ), ) } } diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/UserDeletionE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/UserDeletionE2eDataController.kt similarity index 94% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/UserDeletionE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/UserDeletionE2eDataController.kt index 1ab186584f..e7f53a7109 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/UserDeletionE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/UserDeletionE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.builders.TestDataBuilder diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/WebsocketTranslationsE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/WebsocketTranslationsE2eDataController.kt similarity index 95% rename from backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/WebsocketTranslationsE2eDataController.kt rename to backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/WebsocketTranslationsE2eDataController.kt index 9f6366c2f8..ac269c5be9 100644 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/WebsocketTranslationsE2eDataController.kt +++ b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2eData/WebsocketTranslationsE2eDataController.kt @@ -1,4 +1,4 @@ -package io.tolgee.controllers.internal.e2e_data +package io.tolgee.controllers.internal.e2eData import io.swagger.v3.oas.annotations.Hidden import io.tolgee.development.testDataBuilder.builders.TestDataBuilder diff --git a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ProjectsE2eDataController.kt b/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ProjectsE2eDataController.kt deleted file mode 100644 index 86133cda28..0000000000 --- a/backend/development/src/main/kotlin/io/tolgee/controllers/internal/e2e_data/ProjectsE2eDataController.kt +++ /dev/null @@ -1,294 +0,0 @@ -package io.tolgee.controllers.internal.e2e_data - -import io.swagger.v3.oas.annotations.Hidden -import io.tolgee.dtos.request.LanguageDto -import io.tolgee.dtos.request.auth.SignUpDto -import io.tolgee.dtos.request.key.CreateKeyDto -import io.tolgee.model.Organization -import io.tolgee.model.Permission -import io.tolgee.model.Project -import io.tolgee.model.UserAccount -import io.tolgee.model.enums.ProjectPermissionType -import io.tolgee.repository.OrganizationRepository -import io.tolgee.repository.PermissionRepository -import io.tolgee.repository.ProjectRepository -import io.tolgee.repository.UserAccountRepository -import io.tolgee.service.LanguageService -import io.tolgee.service.key.KeyService -import io.tolgee.service.organization.OrganizationRoleService -import io.tolgee.service.organization.OrganizationService -import io.tolgee.service.project.ProjectService -import io.tolgee.service.security.SignUpService -import io.tolgee.service.security.UserAccountService -import io.tolgee.util.Logging -import io.tolgee.util.executeInNewRepeatableTransaction -import jakarta.persistence.EntityManager -import org.springframework.transaction.PlatformTransactionManager -import org.springframework.transaction.annotation.Transactional -import org.springframework.web.bind.annotation.CrossOrigin -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController - -@RestController -@CrossOrigin(origins = ["*"]) -@Hidden -@RequestMapping(value = ["internal/e2e-data/projects"]) -@Transactional -class ProjectsE2eDataController( - private val organizationService: OrganizationService, - private val userAccountService: UserAccountService, - private val organizationRoleService: OrganizationRoleService, - private val organizationRepository: OrganizationRepository, - private val projectService: ProjectService, - private val projectRepository: ProjectRepository, - private val userAccountRepository: UserAccountRepository, - private val permissionRepository: PermissionRepository, - private val keyService: KeyService, - private val languageService: LanguageService, - private val entityManager: EntityManager, - private val transactionManager: PlatformTransactionManager, - private val signUpService: SignUpService -) : Logging { - @GetMapping(value = ["/generate"]) - @Transactional - fun createProjects() { - val createdUsers = mutableMapOf() - - users.forEach { - createdUsers[it.email] = signUpService.dtoToEntity( - SignUpDto( - name = it.name, email = it.email, password = "admin" - ) - ) - } - - userAccountRepository.saveAll(createdUsers.values) - - val createdOrganizations = organizations.map { - val organization = Organization( - name = it.name, - slug = organizationService.generateSlug(it.name), - ) - - val basePermission = Permission(organization = organization) - organization.basePermission = basePermission - permissionRepository.save(basePermission) - organizationRepository.save(organization) - - it.owners.forEach { - createdUsers[it]!!.let { user -> - organizationRoleService.grantOwnerRoleToUser(user, organization) - } - } - - it.members.forEach { - createdUsers[it]!!.let { user -> - organizationRoleService.grantMemberRoleToUser(user, organization) - } - } - organization - } - - projects.forEach { projectData -> - val organizationOwner = createdOrganizations.find { - it.name.lowercase().replace("[^A-Za-z0-9]".toRegex(), "-") == projectData.organizationOwner.lowercase() - } - - val project = projectRepository.save( - Project( - name = projectData.name, - slug = projectService.generateSlug(projectData.name), - organizationOwner = organizationOwner!! - ) - ) - - projectData.permittedUsers.forEach { - val user = createdUsers[it.userName]!! - permissionRepository.save(Permission(project = project, user = user, type = it.permission)) - } - - val createdLanguages = mutableListOf() - - projectData.keyData.forEach { - it.value.keys.forEach { - if (!createdLanguages.contains(it)) { - languageService.createLanguage(LanguageDto(name = it, tag = it), project) - createdLanguages.add(it) - } - } - keyService.create(project, CreateKeyDto(it.key, null, it.value)) - } - } - } - - @GetMapping(value = ["/clean"]) - fun cleanupProjects() { - executeInNewRepeatableTransaction(transactionManager = transactionManager) { - entityManager.createNativeQuery("SET join_collapse_limit TO 1").executeUpdate() - projectService.deleteAllByName("I am a great project") - - projects.forEach { - traceLogMeasureTime("deleteAllByName: ${it.name}") { - projectService.deleteAllByName(it.name) - } - } - - organizations.forEach { - organizationService.findAllByName(it.name).forEach { org -> - organizationService.delete(org) - } - } - - traceLogMeasureTime("deleteUsers") { - val usernames = users.map { it.email } - userAccountService.deleteByUserNames(usernames) - } - } - } - - companion object { - data class PermittedUserData( - val userName: String, - val permission: ProjectPermissionType, - ) - - data class UserData( - val email: String, - val name: String = email - ) - - data class OrganizationData( - val basePermission: ProjectPermissionType, - val name: String, - val owners: MutableList = mutableListOf(), - val members: MutableList = mutableListOf(), - ) - - data class ProjectDataItem( - val name: String, - val organizationOwner: String, - val permittedUsers: MutableList = mutableListOf(), - val keyData: Map> = mutableMapOf() - ) - - val users = mutableListOf( - UserData("gates@microsoft.com", "Bill Gates"), - UserData("evan@netsuite.com", "Evan Goldberg"), - UserData("cukrberg@facebook.com", "Mark Cukrberg"), - UserData("vaclav.novak@fake.com", "Vaclav Novak"), - UserData("john@doe.com", "John Doe"), - ) - - val organizations = mutableListOf( - OrganizationData( - name = "Facebook", - basePermission = ProjectPermissionType.MANAGE, - owners = mutableListOf("cukrberg@facebook.com"), - members = mutableListOf("john@doe.com") - ), - OrganizationData( - name = "Microsoft", - basePermission = ProjectPermissionType.EDIT, - owners = mutableListOf("gates@microsoft.com"), - members = mutableListOf("john@doe.com", "cukrberg@facebook.com") - ), - OrganizationData( - name = "Vaclav organization", - basePermission = ProjectPermissionType.EDIT, - owners = mutableListOf("vaclav.novak@fake.com"), - ) - ) - - val projects = mutableListOf( - ProjectDataItem( - name = "Facebook itself", - organizationOwner = "facebook", - permittedUsers = mutableListOf( - PermittedUserData( - "vaclav.novak@fake.com", - ProjectPermissionType.TRANSLATE - - ) - ), - keyData = mapOf(Pair("test", mapOf(Pair("en", "This is test text!")))) - ), - ProjectDataItem( - name = "Microsoft Word", - organizationOwner = "microsoft", - permittedUsers = mutableListOf( - PermittedUserData( - "vaclav.novak@fake.com", - ProjectPermissionType.MANAGE - ) - ), - keyData = mapOf(Pair("test", mapOf(Pair("en", "This is test text!")))) - ), - ProjectDataItem( - name = "Microsoft Excel", - organizationOwner = "microsoft", - permittedUsers = mutableListOf( - PermittedUserData( - "vaclav.novak@fake.com", - ProjectPermissionType.EDIT - ) - ), - keyData = mapOf(Pair("test", mapOf(Pair("en", "This is test text!")))) - ), - ProjectDataItem( - name = "Microsoft Powerpoint", - organizationOwner = "microsoft", - permittedUsers = mutableListOf( - PermittedUserData( - "vaclav.novak@fake.com", - ProjectPermissionType.TRANSLATE - ) - ), - keyData = mapOf(Pair("test", mapOf(Pair("en", "This is test text!")))) - ), - ProjectDataItem( - name = "Microsoft Frontpage", - organizationOwner = "microsoft", - permittedUsers = mutableListOf( - PermittedUserData( - "vaclav.novak@fake.com", - ProjectPermissionType.VIEW - ) - ), - keyData = mapOf(Pair("test", mapOf(Pair("en", "This is test text!")))) - ), - ProjectDataItem( - name = "Vaclav's cool project", - permittedUsers = mutableListOf( - PermittedUserData( - "cukrberg@facebook.com", - ProjectPermissionType.VIEW - ) - ), - keyData = mapOf(Pair("test", mapOf(Pair("en", "This is test text!")))), - organizationOwner = "vaclav-organization" - ), - ProjectDataItem( - name = "Vaclav's funny project", - organizationOwner = "vaclav-organization", - permittedUsers = mutableListOf( - PermittedUserData( - "cukrberg@facebook.com", - ProjectPermissionType.MANAGE - ) - ), - keyData = mapOf(Pair("test", mapOf(Pair("en", "This is test text!")))) - ) - ) - - init { - (1..20).forEach { number -> - val email = "owner@zzzcool$number.com" - users.add(UserData(email)) - projects.find { item -> item.name == "Microsoft Word" }!!.permittedUsers.add( - PermittedUserData(email, ProjectPermissionType.EDIT) - ) - } - } - } -} diff --git a/backend/misc/src/main/kotlin/io/tolgee/fixtures/verifySignatureHeader.kt b/backend/misc/src/main/kotlin/io/tolgee/fixtures/verifySignatureHeader.kt index 8ab93d96ef..49b6263625 100644 --- a/backend/misc/src/main/kotlin/io/tolgee/fixtures/verifySignatureHeader.kt +++ b/backend/misc/src/main/kotlin/io/tolgee/fixtures/verifySignatureHeader.kt @@ -3,7 +3,7 @@ package io.tolgee.fixtures import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.readValue import java.nio.charset.StandardCharsets -import java.util.HexFormat +import java.util.* import javax.crypto.Mac import javax.crypto.spec.SecretKeySpec @@ -12,7 +12,7 @@ fun verifyWebhookSignatureHeader( sigHeader: String, secret: String, tolerance: Long, - currentTimeInMs: Long + currentTimeInMs: Long, ): Boolean { val headerMap = jacksonObjectMapper().readValue>(sigHeader) @@ -22,22 +22,23 @@ fun verifyWebhookSignatureHeader( if (timestamp == null || timestamp <= 0 || signature == null) { throw SignatureVerificationException( - "Unable to extract timestamp and signature from header" + "Unable to extract timestamp and signature from header", ) } val signedPayload = "$timestamp.$payload" - val expectedSignature: String = try { - computeHmacSha256(secret, signedPayload) - } catch (e: Exception) { - throw SignatureVerificationException( - "Unable to compute signature for payload" - ) - } + val expectedSignature: String = + try { + computeHmacSha256(secret, signedPayload) + } catch (e: Exception) { + throw SignatureVerificationException( + "Unable to compute signature for payload", + ) + } if (signature != expectedSignature) { throw SignatureVerificationException( - "Wrong signature" + "Wrong signature", ) } @@ -50,7 +51,10 @@ fun verifyWebhookSignatureHeader( class SignatureVerificationException(message: String) : Exception(message) -fun computeHmacSha256(key: String, message: String): String { +fun computeHmacSha256( + key: String, + message: String, +): String { val hasher = Mac.getInstance("HmacSHA256") hasher.init(SecretKeySpec(key.toByteArray(StandardCharsets.UTF_8), "HmacSHA256")) val hash = hasher.doFinal(message.toByteArray(StandardCharsets.UTF_8)) diff --git a/backend/misc/src/main/kotlin/io/tolgee/fixtures/waitFor.kt b/backend/misc/src/main/kotlin/io/tolgee/fixtures/waitFor.kt index 37b61e6e8c..2975685aad 100644 --- a/backend/misc/src/main/kotlin/io/tolgee/fixtures/waitFor.kt +++ b/backend/misc/src/main/kotlin/io/tolgee/fixtures/waitFor.kt @@ -2,7 +2,11 @@ package io.tolgee.fixtures import kotlin.reflect.KClass -fun waitFor(timeout: Long = 10000, pollTime: Long = 10, fn: () -> Boolean) { +fun waitFor( + timeout: Long = 10000, + pollTime: Long = 10, + fn: () -> Boolean, +) { val time = System.currentTimeMillis() var done = false while (!done && System.currentTimeMillis() - time < timeout) { @@ -18,13 +22,14 @@ fun waitFor(timeout: Long = 10000, pollTime: Long = 10, fn: () -> Boolean) { } class WaitNotSatisfiedException : RuntimeException() + class WaitNotSatisfiedStillThrowingException(throwable: Throwable) : RuntimeException(throwable) fun waitForNotThrowing( throwableClass: KClass = Throwable::class, timeout: Long = 10000, pollTime: Long = 10, - fn: () -> Unit + fn: () -> Unit, ) { lateinit var throwable: Throwable try { diff --git a/backend/misc/src/main/kotlin/io/tolgee/misc/dockerRunner/DockerContainerRunner.kt b/backend/misc/src/main/kotlin/io/tolgee/misc/dockerRunner/DockerContainerRunner.kt index 8978514de9..65ddedacd8 100644 --- a/backend/misc/src/main/kotlin/io/tolgee/misc/dockerRunner/DockerContainerRunner.kt +++ b/backend/misc/src/main/kotlin/io/tolgee/misc/dockerRunner/DockerContainerRunner.kt @@ -9,19 +9,16 @@ class DockerContainerRunner( private val image: String, private val expose: Map = mapOf(), private val waitForLog: String, - /** * How many times should the waitForLog string * be present in the log, when starting new container */ private val waitForLogTimesForNewContainer: Int = 1, - /** * How many times should the waitForLog string * be present in the log, when starting existing container */ private val waitForLogTimesForExistingContainer: Int = 1, - /** * Should container be removed after run? */ @@ -30,9 +27,8 @@ class DockerContainerRunner( private val stopBeforeStart: Boolean = true, private val env: Map? = null, private val command: String = "", - private val timeout: Long = 10000 + private val timeout: Long = 10000, ) { - var containerExisted: Boolean = false private set @@ -72,7 +68,10 @@ class DockerContainerRunner( private fun isContainerRunning() = "docker ps".runCommand().contains(" $containerName\n") - private fun waitForContainerLoggedOutput(startTime: Long, times: Int) { + private fun waitForContainerLoggedOutput( + startTime: Long, + times: Int, + ) { waitFor(timeout) { val since = System.currentTimeMillis() - startTime val sinceString = String.format(Locale.US, "%.03f", since.toFloat() / 1000) @@ -110,7 +109,7 @@ class DockerContainerRunner( private fun String.runCommand( workingDir: File = File("."), timeoutAmount: Long = 120, - timeoutUnit: TimeUnit = TimeUnit.SECONDS + timeoutUnit: TimeUnit = TimeUnit.SECONDS, ): String { val process = startProcess(workingDir, timeoutAmount, timeoutUnit) @@ -122,7 +121,11 @@ class DockerContainerRunner( process.errorStream.bufferedReader().readText() } - private fun String.startProcess(workingDir: File, timeoutAmount: Long, timeoutUnit: TimeUnit): Process { + private fun String.startProcess( + workingDir: File, + timeoutAmount: Long, + timeoutUnit: TimeUnit, + ): Process { return ProcessBuilder("\\s+".toRegex().split(this.trim())) .directory(workingDir) .redirectOutput(ProcessBuilder.Redirect.PIPE) diff --git a/backend/security/src/main/kotlin/io/tolgee/security/authentication/AllowApiAccess.kt b/backend/security/src/main/kotlin/io/tolgee/security/authentication/AllowApiAccess.kt index 1889dae602..273649e60a 100644 --- a/backend/security/src/main/kotlin/io/tolgee/security/authentication/AllowApiAccess.kt +++ b/backend/security/src/main/kotlin/io/tolgee/security/authentication/AllowApiAccess.kt @@ -33,7 +33,7 @@ import io.tolgee.API_KEY_HEADER_NAME schema = Schema(type = "string"), explode = Explode.TRUE, example = "tgpak_gm2dcxzynjvdqm3fozwwgmdjmvwdgojqonvxamldnu4hi5lp", - description = "API key provided via query parameter. Will be deprecated in the future." + description = "API key provided via query parameter. Will be deprecated in the future.", ) @Parameter( `in` = ParameterIn.HEADER, @@ -42,7 +42,7 @@ import io.tolgee.API_KEY_HEADER_NAME schema = Schema(type = "string"), explode = Explode.TRUE, example = "tgpak_gm2dcxzynjvdqm3fozwwgmdjmvwdgojqonvxamldnu4hi5lp", - description = "API key provided via header. Safer since headers are not stored in server logs." + description = "API key provided via header. Safer since headers are not stored in server logs.", ) @Target(AnnotationTarget.FUNCTION, AnnotationTarget.ANNOTATION_CLASS) annotation class AllowApiAccess(val tokenType: AuthTokenType = AuthTokenType.ANY) diff --git a/backend/security/src/main/kotlin/io/tolgee/security/authentication/AuthenticationDisabledFilter.kt b/backend/security/src/main/kotlin/io/tolgee/security/authentication/AuthenticationDisabledFilter.kt index 9ba31b945d..d75cb2b074 100644 --- a/backend/security/src/main/kotlin/io/tolgee/security/authentication/AuthenticationDisabledFilter.kt +++ b/backend/security/src/main/kotlin/io/tolgee/security/authentication/AuthenticationDisabledFilter.kt @@ -32,18 +32,24 @@ class AuthenticationDisabledFilter( private val userAccountService: UserAccountService, ) : OncePerRequestFilter() { private val initialUser by lazy { - val account = userAccountService.findInitialUser() - ?: throw IllegalStateException("Initial user does not exists") + val account = + userAccountService.findInitialUser() + ?: throw IllegalStateException("Initial user does not exists") UserAccountDto.fromEntity(account) } - override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) { + override fun doFilterInternal( + request: HttpServletRequest, + response: HttpServletResponse, + filterChain: FilterChain, + ) { // Set the initial user as current user, always. - SecurityContextHolder.getContext().authentication = TolgeeAuthentication( - null, - initialUser, - TolgeeAuthenticationDetails(true) - ) + SecurityContextHolder.getContext().authentication = + TolgeeAuthentication( + null, + initialUser, + TolgeeAuthenticationDetails(true), + ) filterChain.doFilter(request, response) } diff --git a/backend/security/src/main/kotlin/io/tolgee/security/authentication/AuthenticationFilter.kt b/backend/security/src/main/kotlin/io/tolgee/security/authentication/AuthenticationFilter.kt index 60b8a974f2..36e17c941c 100644 --- a/backend/security/src/main/kotlin/io/tolgee/security/authentication/AuthenticationFilter.kt +++ b/backend/security/src/main/kotlin/io/tolgee/security/authentication/AuthenticationFilter.kt @@ -46,7 +46,11 @@ class AuthenticationFilter( private val apiKeyService: ApiKeyService, private val patService: PatService, ) : OncePerRequestFilter() { - override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) { + override fun doFilterInternal( + request: HttpServletRequest, + response: HttpServletResponse, + filterChain: FilterChain, + ) { val policy = rateLimitService.getIpAuthRateLimitPolicy(request) if (policy == null) { @@ -91,45 +95,52 @@ class AuthenticationFilter( } private fun pakAuth(key: String) { - val parsed = apiKeyService.parseApiKey(key) - ?: throw AuthenticationException(Message.INVALID_PROJECT_API_KEY) + val parsed = + apiKeyService.parseApiKey(key) + ?: throw AuthenticationException(Message.INVALID_PROJECT_API_KEY) val hash = apiKeyService.hashKey(parsed) - val pak = apiKeyService.findDto(hash) - ?: throw AuthenticationException(Message.INVALID_PROJECT_API_KEY) + val pak = + apiKeyService.findDto(hash) + ?: throw AuthenticationException(Message.INVALID_PROJECT_API_KEY) if (pak.expiresAt?.before(currentDateProvider.date) == true) { throw AuthenticationException(Message.PROJECT_API_KEY_EXPIRED) } - val userAccount = userAccountService.findDto(pak.userAccountId) - ?: throw AuthenticationException(Message.USER_NOT_FOUND) + val userAccount = + userAccountService.findDto(pak.userAccountId) + ?: throw AuthenticationException(Message.USER_NOT_FOUND) apiKeyService.updateLastUsedAsync(pak.id) - SecurityContextHolder.getContext().authentication = TolgeeAuthentication( - pak, - userAccount, - TolgeeAuthenticationDetails(false) - ) + SecurityContextHolder.getContext().authentication = + TolgeeAuthentication( + pak, + userAccount, + TolgeeAuthenticationDetails(false), + ) } private fun patAuth(key: String) { val hash = patService.hashToken(key.substring(PAT_PREFIX.length)) - val pat = patService.findDto(hash) - ?: throw AuthenticationException(Message.INVALID_PAT) + val pat = + patService.findDto(hash) + ?: throw AuthenticationException(Message.INVALID_PAT) if (pat.expiresAt?.before(currentDateProvider.date) == true) { throw AuthenticationException(Message.PAT_EXPIRED) } - val userAccount = userAccountService.findDto(pat.userAccountId) - ?: throw AuthenticationException(Message.USER_NOT_FOUND) + val userAccount = + userAccountService.findDto(pat.userAccountId) + ?: throw AuthenticationException(Message.USER_NOT_FOUND) patService.updateLastUsedAsync(pat.id) - SecurityContextHolder.getContext().authentication = TolgeeAuthentication( - pat, - userAccount, - TolgeeAuthenticationDetails(false) - ) + SecurityContextHolder.getContext().authentication = + TolgeeAuthentication( + pat, + userAccount, + TolgeeAuthenticationDetails(false), + ) } } diff --git a/backend/security/src/main/kotlin/io/tolgee/security/authentication/AuthenticationInterceptor.kt b/backend/security/src/main/kotlin/io/tolgee/security/authentication/AuthenticationInterceptor.kt index 7197b9a8c1..217f929b0b 100644 --- a/backend/security/src/main/kotlin/io/tolgee/security/authentication/AuthenticationInterceptor.kt +++ b/backend/security/src/main/kotlin/io/tolgee/security/authentication/AuthenticationInterceptor.kt @@ -32,9 +32,13 @@ import org.springframework.web.servlet.HandlerInterceptor */ @Component class AuthenticationInterceptor( - private val authenticationFacade: AuthenticationFacade + private val authenticationFacade: AuthenticationFacade, ) : HandlerInterceptor, Ordered { - override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean { + override fun preHandle( + request: HttpServletRequest, + response: HttpServletResponse, + handler: Any, + ): Boolean { if (handler !is HandlerMethod || DispatcherType.ASYNC == request.dispatcherType) { return super.preHandle(request, response, handler) } diff --git a/backend/security/src/main/kotlin/io/tolgee/security/authorization/AbstractAuthorizationInterceptor.kt b/backend/security/src/main/kotlin/io/tolgee/security/authorization/AbstractAuthorizationInterceptor.kt index d49a1bb101..2661997599 100644 --- a/backend/security/src/main/kotlin/io/tolgee/security/authorization/AbstractAuthorizationInterceptor.kt +++ b/backend/security/src/main/kotlin/io/tolgee/security/authorization/AbstractAuthorizationInterceptor.kt @@ -1,58 +1,62 @@ -/** - * Copyright (C) 2023 Tolgee s.r.o. and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.tolgee.security.authorization - -import jakarta.servlet.DispatcherType -import jakarta.servlet.http.HttpServletRequest -import jakarta.servlet.http.HttpServletResponse -import org.springframework.core.Ordered -import org.springframework.core.annotation.AnnotationUtils -import org.springframework.web.method.HandlerMethod -import org.springframework.web.servlet.HandlerInterceptor - -abstract class AbstractAuthorizationInterceptor : HandlerInterceptor, Ordered { - override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean { - if (handler !is HandlerMethod || DispatcherType.ASYNC == request.dispatcherType) { - return super.preHandle(request, response, handler) - } - - if (request.method == "OPTIONS") { - // Do not process OPTIONS requests - return true - } - - // Global route; abort here - if (isGlobal(handler)) return true - - return preHandleInternal(request, response, handler) - } - - override fun getOrder(): Int { - return Ordered.HIGHEST_PRECEDENCE - } - - abstract fun preHandleInternal( - request: HttpServletRequest, - response: HttpServletResponse, - handler: HandlerMethod - ): Boolean - - private fun isGlobal(handler: HandlerMethod): Boolean { - val annotation = AnnotationUtils.getAnnotation(handler.method, IsGlobalRoute::class.java) - return annotation != null - } -} +/** + * Copyright (C) 2023 Tolgee s.r.o. and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.tolgee.security.authorization + +import jakarta.servlet.DispatcherType +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse +import org.springframework.core.Ordered +import org.springframework.core.annotation.AnnotationUtils +import org.springframework.web.method.HandlerMethod +import org.springframework.web.servlet.HandlerInterceptor + +abstract class AbstractAuthorizationInterceptor : HandlerInterceptor, Ordered { + override fun preHandle( + request: HttpServletRequest, + response: HttpServletResponse, + handler: Any, + ): Boolean { + if (handler !is HandlerMethod || DispatcherType.ASYNC == request.dispatcherType) { + return super.preHandle(request, response, handler) + } + + if (request.method == "OPTIONS") { + // Do not process OPTIONS requests + return true + } + + // Global route; abort here + if (isGlobal(handler)) return true + + return preHandleInternal(request, response, handler) + } + + override fun getOrder(): Int { + return Ordered.HIGHEST_PRECEDENCE + } + + abstract fun preHandleInternal( + request: HttpServletRequest, + response: HttpServletResponse, + handler: HandlerMethod, + ): Boolean + + private fun isGlobal(handler: HandlerMethod): Boolean { + val annotation = AnnotationUtils.getAnnotation(handler.method, IsGlobalRoute::class.java) + return annotation != null + } +} diff --git a/backend/security/src/main/kotlin/io/tolgee/security/authorization/OrganizationAuthorizationInterceptor.kt b/backend/security/src/main/kotlin/io/tolgee/security/authorization/OrganizationAuthorizationInterceptor.kt index c37869cdf2..8b7fabd2e8 100644 --- a/backend/security/src/main/kotlin/io/tolgee/security/authorization/OrganizationAuthorizationInterceptor.kt +++ b/backend/security/src/main/kotlin/io/tolgee/security/authorization/OrganizationAuthorizationInterceptor.kt @@ -50,14 +50,15 @@ class OrganizationAuthorizationInterceptor( override fun preHandleInternal( request: HttpServletRequest, response: HttpServletResponse, - handler: HandlerMethod + handler: HandlerMethod, ): Boolean { val userId = authenticationFacade.authenticatedUser.id - val organization = requestContextService.getTargetOrganization(request) - // Two possible scenarios: we're on `GET/POST /v2/organization`, or the organization was not found. - // In both cases, there is no authorization to perform and we simply continue. - // It is not the job of the interceptor to return a 404 error. - ?: return true + val organization = + requestContextService.getTargetOrganization(request) + // Two possible scenarios: we're on `GET/POST /v2/organization`, or the organization was not found. + // In both cases, there is no authorization to perform and we simply continue. + // It is not the job of the interceptor to return a 404 error. + ?: return true var bypassed = false val isAdmin = authenticationFacade.authenticatedUser.role == UserAccount.Role.ADMIN @@ -66,7 +67,7 @@ class OrganizationAuthorizationInterceptor( "Checking access to org#{} by user#{} (Requires {})", organization.id, userId, - requiredRole ?: "read-only" + requiredRole ?: "read-only", ) if (!organizationRoleService.canUserViewStrict(userId, organization.id)) { @@ -112,7 +113,10 @@ class OrganizationAuthorizationInterceptor( return true } - private fun getRequiredRole(request: HttpServletRequest, handler: HandlerMethod): OrganizationRoleType? { + private fun getRequiredRole( + request: HttpServletRequest, + handler: HandlerMethod, + ): OrganizationRoleType? { val defaultPerms = AnnotationUtils.getAnnotation(handler.method, UseDefaultPermissions::class.java) val orgPermission = AnnotationUtils.getAnnotation(handler.method, RequiresOrganizationRole::class.java) @@ -124,7 +128,7 @@ class OrganizationAuthorizationInterceptor( if (defaultPerms != null && orgPermission != null) { // Policy doesn't make sense throw RuntimeException( - "Both `@UseDefaultPermissions` and `@RequiresOrganizationRole` have been set for this endpoint!" + "Both `@UseDefaultPermissions` and `@RequiresOrganizationRole` have been set for this endpoint!", ) } diff --git a/backend/security/src/main/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptor.kt b/backend/security/src/main/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptor.kt index 650a1aaef3..9fecd56ddc 100644 --- a/backend/security/src/main/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptor.kt +++ b/backend/security/src/main/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptor.kt @@ -51,14 +51,15 @@ class ProjectAuthorizationInterceptor( override fun preHandleInternal( request: HttpServletRequest, response: HttpServletResponse, - handler: HandlerMethod + handler: HandlerMethod, ): Boolean { val userId = authenticationFacade.authenticatedUser.id - val project = requestContextService.getTargetProject(request) - // Two possible scenarios: we're on a "global" route, or the project was not found. - // In both cases, there is no authorization to perform, and we simply continue. - // It is not the job of the interceptor to return a 404 error. - ?: return true + val project = + requestContextService.getTargetProject(request) + // Two possible scenarios: we're on a "global" route, or the project was not found. + // In both cases, there is no authorization to perform, and we simply continue. + // It is not the job of the interceptor to return a 404 error. + ?: return true var bypassed = false val isAdmin = authenticationFacade.authenticatedUser.role == UserAccount.Role.ADMIN @@ -68,17 +69,18 @@ class ProjectAuthorizationInterceptor( logger.debug("Checking access to proj#${project.id} by user#$userId (Requires $formattedRequirements)") val scopes = - if (authenticationFacade.isProjectApiKeyAuth) + if (authenticationFacade.isProjectApiKeyAuth) { authenticationFacade.projectApiKey.scopes.toTypedArray() - else + } else { securityService.getProjectPermissionScopes(project.id, userId) ?: emptyArray() + } if (scopes.isEmpty()) { if (!isAdmin) { logger.debug( "Rejecting access to proj#{} for user#{} - No view permissions", project.id, - userId + userId, ) // Security consideration: if the user cannot see the project, pretend it does not exist. @@ -94,12 +96,12 @@ class ProjectAuthorizationInterceptor( logger.debug( "Rejecting access to proj#{} for user#{} - Insufficient permissions", project.id, - userId + userId, ) throw PermissionException( Message.OPERATION_NOT_PERMITTED, - requiredScopes.map { s -> s.value } + requiredScopes.map { s -> s.value }, ) } @@ -115,7 +117,7 @@ class ProjectAuthorizationInterceptor( "Rejecting access to proj#{} for user#{} via pak#{} - API Key mismatch", project.id, userId, - pak.id + pak.id, ) throw PermissionException() @@ -128,12 +130,12 @@ class ProjectAuthorizationInterceptor( "Rejecting access to proj#{} for user#{} via pak#{} - Insufficient permissions granted to PAK", project.id, userId, - pak.id + pak.id, ) throw PermissionException( Message.OPERATION_NOT_PERMITTED, - requiredScopes.map { s -> s.value } + requiredScopes.map { s -> s.value }, ) } } @@ -156,7 +158,10 @@ class ProjectAuthorizationInterceptor( return true } - private fun getRequiredScopes(request: HttpServletRequest, handler: HandlerMethod): Array? { + private fun getRequiredScopes( + request: HttpServletRequest, + handler: HandlerMethod, + ): Array? { val defaultPerms = AnnotationUtils.getAnnotation(handler.method, UseDefaultPermissions::class.java) val projectPerms = AnnotationUtils.getAnnotation(handler.method, RequiresProjectPermissions::class.java) @@ -168,14 +173,14 @@ class ProjectAuthorizationInterceptor( if (defaultPerms != null && projectPerms != null) { // Policy doesn't make sense throw RuntimeException( - "Both `@UseDefaultPermissions` and `@RequiresProjectPermissions` have been set for this endpoint!" + "Both `@UseDefaultPermissions` and `@RequiresProjectPermissions` have been set for this endpoint!", ) } if (projectPerms?.scopes?.isEmpty() == true) { // No scopes set for RequiresProjectPermissions throw RuntimeException( - "`@RequiresProjectPermissions` requires at least one scope. Use `@UseDefaultPermissions` for any scope." + "`@RequiresProjectPermissions` requires at least one scope. Use `@UseDefaultPermissions` for any scope.", ) } diff --git a/backend/security/src/main/kotlin/io/tolgee/security/authorization/RequiresProjectPermissions.kt b/backend/security/src/main/kotlin/io/tolgee/security/authorization/RequiresProjectPermissions.kt index 00537a704d..29b4e07833 100644 --- a/backend/security/src/main/kotlin/io/tolgee/security/authorization/RequiresProjectPermissions.kt +++ b/backend/security/src/main/kotlin/io/tolgee/security/authorization/RequiresProjectPermissions.kt @@ -24,5 +24,5 @@ import io.tolgee.model.enums.Scope */ @Target(AnnotationTarget.FUNCTION, AnnotationTarget.ANNOTATION_CLASS) annotation class RequiresProjectPermissions( - val scopes: Array + val scopes: Array, ) diff --git a/backend/security/src/main/kotlin/io/tolgee/security/ratelimit/GlobalIpRateLimitFilter.kt b/backend/security/src/main/kotlin/io/tolgee/security/ratelimit/GlobalIpRateLimitFilter.kt index c92450ea95..7a5caeda37 100644 --- a/backend/security/src/main/kotlin/io/tolgee/security/ratelimit/GlobalIpRateLimitFilter.kt +++ b/backend/security/src/main/kotlin/io/tolgee/security/ratelimit/GlobalIpRateLimitFilter.kt @@ -28,7 +28,11 @@ class GlobalIpRateLimitFilter( private val rateLimitService: RateLimitService, private val authenticationFacade: AuthenticationFacade, ) : OncePerRequestFilter() { - override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) { + override fun doFilterInternal( + request: HttpServletRequest, + response: HttpServletResponse, + filterChain: FilterChain, + ) { if (!authenticationFacade.isAuthenticated) { rateLimitService.consumeGlobalIpRateLimitPolicy(request) } diff --git a/backend/security/src/main/kotlin/io/tolgee/security/ratelimit/GlobalUserRateLimitFilter.kt b/backend/security/src/main/kotlin/io/tolgee/security/ratelimit/GlobalUserRateLimitFilter.kt index ad3587cd82..68d95dc215 100644 --- a/backend/security/src/main/kotlin/io/tolgee/security/ratelimit/GlobalUserRateLimitFilter.kt +++ b/backend/security/src/main/kotlin/io/tolgee/security/ratelimit/GlobalUserRateLimitFilter.kt @@ -28,7 +28,11 @@ class GlobalUserRateLimitFilter( private val rateLimitService: RateLimitService, private val authenticationFacade: AuthenticationFacade, ) : OncePerRequestFilter() { - override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) { + override fun doFilterInternal( + request: HttpServletRequest, + response: HttpServletResponse, + filterChain: FilterChain, + ) { if (authenticationFacade.isAuthenticated) { rateLimitService.consumeGlobalUserRateLimitPolicy(request, authenticationFacade.authenticatedUser.id) } diff --git a/backend/security/src/main/kotlin/io/tolgee/security/ratelimit/RateLimitInterceptor.kt b/backend/security/src/main/kotlin/io/tolgee/security/ratelimit/RateLimitInterceptor.kt index 9dbfaf291d..50abe350bc 100644 --- a/backend/security/src/main/kotlin/io/tolgee/security/ratelimit/RateLimitInterceptor.kt +++ b/backend/security/src/main/kotlin/io/tolgee/security/ratelimit/RateLimitInterceptor.kt @@ -36,7 +36,11 @@ class RateLimitInterceptor( private val rateLimitProperties: RateLimitProperties, private val rateLimitService: RateLimitService, ) : HandlerInterceptor, Ordered { - override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean { + override fun preHandle( + request: HttpServletRequest, + response: HttpServletResponse, + handler: Any, + ): Boolean { if (handler !is HandlerMethod || DispatcherType.ASYNC == request.dispatcherType) { return super.preHandle(request, response, handler) } @@ -52,10 +56,11 @@ class RateLimitInterceptor( fun extractEndpointRateLimit( request: HttpServletRequest, account: UserAccountDto?, - handler: HandlerMethod + handler: HandlerMethod, ): RateLimitPolicy? { - val annotation = AnnotationUtils.getAnnotation(handler.method, RateLimited::class.java) - ?: return null + val annotation = + AnnotationUtils.getAnnotation(handler.method, RateLimited::class.java) + ?: return null if (!shouldRateLimit(annotation)) { return null @@ -78,7 +83,11 @@ class RateLimitInterceptor( (!annotation.isAuthentication && rateLimitProperties.endpointLimits) } - private fun getBucketName(request: HttpServletRequest, annotation: RateLimited, account: UserAccountDto?): String { + private fun getBucketName( + request: HttpServletRequest, + annotation: RateLimited, + account: UserAccountDto?, + ): String { val matchedPath = request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE) as String val pathVariablesMap = request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE) as Map<*, *> diff --git a/backend/security/src/test/kotlin/io/tolgee/security/authentication/AuthenticationFilterTest.kt b/backend/security/src/test/kotlin/io/tolgee/security/authentication/AuthenticationFilterTest.kt index 132325aa64..2d5d776dcd 100644 --- a/backend/security/src/test/kotlin/io/tolgee/security/authentication/AuthenticationFilterTest.kt +++ b/backend/security/src/test/kotlin/io/tolgee/security/authentication/AuthenticationFilterTest.kt @@ -80,21 +80,23 @@ class AuthenticationFilterTest { private val userAccount = Mockito.mock(UserAccount::class.java, Mockito.RETURNS_DEFAULTS) - private val authenticationFilter = AuthenticationFilter( - authProperties, - currentDateProvider, - rateLimitService, - jwtService, - userAccountService, - pakService, - patService, - ) - - private val authenticationFacade = AuthenticationFacade( - userAccountService, - Mockito.mock(ApiKeyService::class.java), - Mockito.mock(PatService::class.java), - ) + private val authenticationFilter = + AuthenticationFilter( + authProperties, + currentDateProvider, + rateLimitService, + jwtService, + userAccountService, + pakService, + patService, + ) + + private val authenticationFacade = + AuthenticationFacade( + userAccountService, + Mockito.mock(ApiKeyService::class.java), + Mockito.mock(PatService::class.java), + ) @BeforeEach fun setupMocksAndSecurityCtx() { @@ -105,7 +107,7 @@ class AuthenticationFilterTest { Mockito.`when`(rateLimitService.getIpAuthRateLimitPolicy(any())) .thenReturn( - RateLimitPolicy("test policy", 5, Duration.ofSeconds(1), true) + RateLimitPolicy("test policy", 5, Duration.ofSeconds(1), true), ) Mockito.`when`(rateLimitService.consumeBucketUnless(any(), any())) @@ -120,7 +122,7 @@ class AuthenticationFilterTest { "uwu", userAccountDto, null, - ) + ), ) Mockito.`when`(jwtService.validateToken(TEST_INVALID_TOKEN)) diff --git a/backend/security/src/test/kotlin/io/tolgee/security/authentication/AuthenticationInterceptorTest.kt b/backend/security/src/test/kotlin/io/tolgee/security/authentication/AuthenticationInterceptorTest.kt index da79fbf41d..0cb7381c6e 100644 --- a/backend/security/src/test/kotlin/io/tolgee/security/authentication/AuthenticationInterceptorTest.kt +++ b/backend/security/src/test/kotlin/io/tolgee/security/authentication/AuthenticationInterceptorTest.kt @@ -19,9 +19,10 @@ class AuthenticationInterceptorTest { private val authenticationInterceptor = AuthenticationInterceptor(authenticationFacade) - private val mockMvc = MockMvcBuilders.standaloneSetup(TestController::class.java) - .addInterceptors(authenticationInterceptor) - .build() + private val mockMvc = + MockMvcBuilders.standaloneSetup(TestController::class.java) + .addInterceptors(authenticationInterceptor) + .build() @BeforeEach fun setupMocks() { diff --git a/backend/security/src/test/kotlin/io/tolgee/security/authorization/OrganizationAuthorizationInterceptorTest.kt b/backend/security/src/test/kotlin/io/tolgee/security/authorization/OrganizationAuthorizationInterceptorTest.kt index 86aa2c0938..05a7dcc0cf 100644 --- a/backend/security/src/test/kotlin/io/tolgee/security/authorization/OrganizationAuthorizationInterceptorTest.kt +++ b/backend/security/src/test/kotlin/io/tolgee/security/authorization/OrganizationAuthorizationInterceptorTest.kt @@ -50,16 +50,18 @@ class OrganizationAuthorizationInterceptorTest { private val userAccount = Mockito.mock(UserAccountDto::class.java) - private val organizationAuthenticationInterceptor = OrganizationAuthorizationInterceptor( - authenticationFacade, - organizationRoleService, - requestContextService, - Mockito.mock(OrganizationHolder::class.java), - ) + private val organizationAuthenticationInterceptor = + OrganizationAuthorizationInterceptor( + authenticationFacade, + organizationRoleService, + requestContextService, + Mockito.mock(OrganizationHolder::class.java), + ) - private val mockMvc = MockMvcBuilders.standaloneSetup(TestController::class.java) - .addInterceptors(organizationAuthenticationInterceptor) - .build() + private val mockMvc = + MockMvcBuilders.standaloneSetup(TestController::class.java) + .addInterceptors(organizationAuthenticationInterceptor) + .build() @BeforeEach fun setupMocks() { @@ -137,19 +139,27 @@ class OrganizationAuthorizationInterceptorTest { fun getAll() = "hello!" @GetMapping("/v2/organizations/{id}/not-annotated") - fun notAnnotated(@PathVariable id: Long) = "henlo from org #$id!" + fun notAnnotated( + @PathVariable id: Long, + ) = "henlo from org #$id!" @GetMapping("/v2/organizations/{id}/default-perms") @UseDefaultPermissions - fun defaultPerms(@PathVariable id: Long) = "henlo from org #$id!" + fun defaultPerms( + @PathVariable id: Long, + ) = "henlo from org #$id!" @GetMapping("/v2/organizations/{id}/requires-admin") @RequiresOrganizationRole(OrganizationRoleType.OWNER) - fun requiresAdmin(@PathVariable id: Long) = "henlo from org #$id!" + fun requiresAdmin( + @PathVariable id: Long, + ) = "henlo from org #$id!" @GetMapping("/v2/organizations/{id}/nonsense-perms") @RequiresOrganizationRole(OrganizationRoleType.OWNER) @UseDefaultPermissions - fun nonsensePerms(@PathVariable id: Long) = "henlo from org #$id!" + fun nonsensePerms( + @PathVariable id: Long, + ) = "henlo from org #$id!" } } diff --git a/backend/security/src/test/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptorTest.kt b/backend/security/src/test/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptorTest.kt index e5fbbd8bc9..f0d9460ce9 100644 --- a/backend/security/src/test/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptorTest.kt +++ b/backend/security/src/test/kotlin/io/tolgee/security/authorization/ProjectAuthorizationInterceptorTest.kt @@ -62,18 +62,20 @@ class ProjectAuthorizationInterceptorTest { private val apiKey = Mockito.mock(ApiKeyDto::class.java) - private val projectAuthenticationInterceptor = ProjectAuthorizationInterceptor( - authenticationFacade, - organizationService, - securityService, - requestContextService, - Mockito.mock(ProjectHolder::class.java), - Mockito.mock(OrganizationHolder::class.java), - ) - - private val mockMvc = MockMvcBuilders.standaloneSetup(TestController::class.java) - .addInterceptors(projectAuthenticationInterceptor) - .build() + private val projectAuthenticationInterceptor = + ProjectAuthorizationInterceptor( + authenticationFacade, + organizationService, + securityService, + requestContextService, + Mockito.mock(ProjectHolder::class.java), + Mockito.mock(OrganizationHolder::class.java), + ) + + private val mockMvc = + MockMvcBuilders.standaloneSetup(TestController::class.java) + .addInterceptors(projectAuthenticationInterceptor) + .build() @BeforeEach fun setupMocks() { @@ -230,24 +232,34 @@ class ProjectAuthorizationInterceptorTest { fun getAll() = "hello!" @GetMapping("/v2/projects/{id}/not-annotated") - fun notAnnotated(@PathVariable id: Long) = "henlo from project $id!" + fun notAnnotated( + @PathVariable id: Long, + ) = "henlo from project $id!" @GetMapping("/v2/projects/{id}/default-perms") @UseDefaultPermissions - fun defaultPerms(@PathVariable id: Long) = "henlo from project $id!" + fun defaultPerms( + @PathVariable id: Long, + ) = "henlo from project $id!" @GetMapping("/v2/projects/{id}/requires-single-scope") @RequiresProjectPermissions([ Scope.KEYS_CREATE ]) - fun requiresSingleScope(@PathVariable id: Long) = "henlo from project $id!" + fun requiresSingleScope( + @PathVariable id: Long, + ) = "henlo from project $id!" @GetMapping("/v2/projects/{id}/requires-multiple-scopes") @RequiresProjectPermissions([ Scope.KEYS_CREATE, Scope.MEMBERS_EDIT ]) - fun requiresMultipleScopes(@PathVariable id: Long) = "henlo from project $id!" + fun requiresMultipleScopes( + @PathVariable id: Long, + ) = "henlo from project $id!" @GetMapping("/v2/projects/{id}/nonsense-perms") @UseDefaultPermissions @RequiresProjectPermissions([ Scope.PROJECT_EDIT ]) - fun nonsensePerms(@PathVariable id: Long) = "henlo from project $id!" + fun nonsensePerms( + @PathVariable id: Long, + ) = "henlo from project $id!" @GetMapping("/v2/projects/implicit-access") @RequiresProjectPermissions([ Scope.KEYS_CREATE ]) diff --git a/backend/security/src/test/kotlin/io/tolgee/security/ratelimit/RateLimitInterceptorTest.kt b/backend/security/src/test/kotlin/io/tolgee/security/ratelimit/RateLimitInterceptorTest.kt index 5703794981..f3bbd1e519 100644 --- a/backend/security/src/test/kotlin/io/tolgee/security/ratelimit/RateLimitInterceptorTest.kt +++ b/backend/security/src/test/kotlin/io/tolgee/security/ratelimit/RateLimitInterceptorTest.kt @@ -51,24 +51,27 @@ class RateLimitInterceptorTest { private val userAccount = Mockito.mock(UserAccountDto::class.java) - private val rateLimitService = Mockito.spy( - RateLimitService( - ConcurrentMapCacheManager(), - TestLockingProvider(), - currentDateProvider, - rateLimitProperties, + private val rateLimitService = + Mockito.spy( + RateLimitService( + ConcurrentMapCacheManager(), + TestLockingProvider(), + currentDateProvider, + rateLimitProperties, + ), ) - ) - private val rateLimitInterceptor = RateLimitInterceptor( - authenticationFacade, - rateLimitProperties, - rateLimitService, - ) + private val rateLimitInterceptor = + RateLimitInterceptor( + authenticationFacade, + rateLimitProperties, + rateLimitService, + ) - private val mockMvc = MockMvcBuilders.standaloneSetup(TestController::class.java) - .addInterceptors(rateLimitInterceptor) - .build() + private val mockMvc = + MockMvcBuilders.standaloneSetup(TestController::class.java) + .addInterceptors(rateLimitInterceptor) + .build() @BeforeEach fun setupMocks() { @@ -243,9 +246,13 @@ class RateLimitInterceptorTest { // Accessing the one from API package is a pain here. class TestLockingProvider : LockingProvider { private val lock = ReentrantLock() + override fun getLock(name: String): Lock = lock - override fun withLocking(name: String, fn: () -> T): T { + override fun withLocking( + name: String, + fn: () -> T, + ): T { lock.lock() try { return fn() diff --git a/backend/testing/src/main/kotlin/io/tolgee/AbstractSpringTest.kt b/backend/testing/src/main/kotlin/io/tolgee/AbstractSpringTest.kt index f9eeb1ba04..257aca184b 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/AbstractSpringTest.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/AbstractSpringTest.kt @@ -8,7 +8,13 @@ import io.tolgee.component.machineTranslation.MtServiceManager import io.tolgee.configuration.tolgee.AuthenticationProperties import io.tolgee.configuration.tolgee.InternalProperties import io.tolgee.configuration.tolgee.TolgeeProperties -import io.tolgee.configuration.tolgee.machineTranslation.* +import io.tolgee.configuration.tolgee.machineTranslation.AwsMachineTranslationProperties +import io.tolgee.configuration.tolgee.machineTranslation.AzureCognitiveTranslationProperties +import io.tolgee.configuration.tolgee.machineTranslation.BaiduMachineTranslationProperties +import io.tolgee.configuration.tolgee.machineTranslation.DeeplMachineTranslationProperties +import io.tolgee.configuration.tolgee.machineTranslation.GoogleMachineTranslationProperties +import io.tolgee.configuration.tolgee.machineTranslation.MachineTranslationProperties +import io.tolgee.configuration.tolgee.machineTranslation.TolgeeMachineTranslationProperties import io.tolgee.constants.MtServiceType import io.tolgee.development.DbPopulatorReal import io.tolgee.development.testDataBuilder.TestDataService @@ -242,7 +248,7 @@ abstract class AbstractSpringTest : AbstractTransactionalTest() { protected fun initMachineTranslationProperties( freeCreditsAmount: Long, - enabledServices: Set = setOf(MtServiceType.GOOGLE) + enabledServices: Set = setOf(MtServiceType.GOOGLE), ) { machineTranslationProperties.freeCreditsAmount = freeCreditsAmount awsMachineTranslationProperties.accessKey = "dummy" @@ -266,7 +272,7 @@ abstract class AbstractSpringTest : AbstractTransactionalTest() { return io.tolgee.util.executeInNewTransaction( transactionManager = platformTransactionManager, fn = fn, - isolationLevel = TransactionDefinition.ISOLATION_DEFAULT + isolationLevel = TransactionDefinition.ISOLATION_DEFAULT, ) } @@ -278,7 +284,10 @@ abstract class AbstractSpringTest : AbstractTransactionalTest() { currentDateProvider.forcedDate = null } - open fun forceDateString(dateString: String, pattern: String = "yyyy-MM-dd HH:mm:ss z") { + open fun forceDateString( + dateString: String, + pattern: String = "yyyy-MM-dd HH:mm:ss z", + ) { currentDateProvider.forceDateString(dateString, pattern) } diff --git a/backend/testing/src/main/kotlin/io/tolgee/CleanDbTestListener.kt b/backend/testing/src/main/kotlin/io/tolgee/CleanDbTestListener.kt index 7f59e19aec..699ae91c44 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/CleanDbTestListener.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/CleanDbTestListener.kt @@ -18,11 +18,12 @@ import kotlin.system.measureTimeMillis class CleanDbTestListener : TestExecutionListener { private val logger = LoggerFactory.getLogger(this::class.java) - private val ignoredTables = listOf( - "mt_credits_price", - "databasechangelog", - "databasechangeloglock" - ) + private val ignoredTables = + listOf( + "mt_credits_price", + "databasechangelog", + "databasechangeloglock", + ) override fun beforeTestMethod(testContext: TestContext) { val appContext: ApplicationContext = testContext.applicationContext @@ -39,27 +40,28 @@ class CleanDbTestListener : TestExecutionListener { private fun cleanWithRetries(testContext: TestContext) { logger.info("Cleaning DB") - val time = measureTimeMillis { - var i = 0 - while (true) { - try { - withTimeout(3000) { - doClean(testContext) - } - break - } catch (e: Exception) { - when (e) { - is PSQLException, is TimeoutCancellationException -> { - if (i > 5) { - throw e + val time = + measureTimeMillis { + var i = 0 + while (true) { + try { + withTimeout(3000) { + doClean(testContext) + } + break + } catch (e: Exception) { + when (e) { + is PSQLException, is TimeoutCancellationException -> { + if (i > 5) { + throw e + } } } - } - i++ + i++ + } } } - } logger.info("DB cleaned in ${time}ms") } @@ -70,15 +72,16 @@ class CleanDbTestListener : TestExecutionListener { val stmt = conn.createStatement() val databaseName: Any = "postgres" val ignoredTablesString = ignoredTables.joinToString(", ") { "'$it'" } - val rs: ResultSet = stmt.executeQuery( - String.format( - "SELECT table_schema, table_name" + - " FROM information_schema.tables" + - " WHERE table_catalog = '%s' and (table_schema in ('public', 'billing', 'ee'))" + - " and table_name not in ($ignoredTablesString)", - databaseName + val rs: ResultSet = + stmt.executeQuery( + String.format( + "SELECT table_schema, table_name" + + " FROM information_schema.tables" + + " WHERE table_catalog = '%s' and (table_schema in ('public', 'billing', 'ee'))" + + " and table_name not in ($ignoredTablesString)", + databaseName, + ), ) - ) val tables: MutableList> = ArrayList() while (rs.next()) { tables.add(rs.getString(1) to rs.getString(2)) @@ -86,8 +89,8 @@ class CleanDbTestListener : TestExecutionListener { stmt.execute( java.lang.String.format( "TRUNCATE TABLE %s", - tables.joinToString(",") { it.first + "." + it.second } - ) + tables.joinToString(",") { it.first + "." + it.second }, + ), ) } } @@ -114,7 +117,10 @@ class CleanDbTestListener : TestExecutionListener { override fun prepareTestInstance(testContext: TestContext) { } - private fun withTimeout(timeout: Long, block: () -> Unit) { + private fun withTimeout( + timeout: Long, + block: () -> Unit, + ) { val executor = Executors.newSingleThreadExecutor() val future: Future = executor.submit(block) diff --git a/backend/testing/src/main/kotlin/io/tolgee/ProjectAuthControllerTest.kt b/backend/testing/src/main/kotlin/io/tolgee/ProjectAuthControllerTest.kt index efdbc05b1d..7f9a996647 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/ProjectAuthControllerTest.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/ProjectAuthControllerTest.kt @@ -1,6 +1,6 @@ package io.tolgee -import io.tolgee.dtos.response.ApiKeyDTO.ApiKeyDTO +import io.tolgee.dtos.response.ApiKeyDTO import io.tolgee.fixtures.AuthRequestPerformer import io.tolgee.fixtures.ProjectApiKeyAuthRequestPerformer import io.tolgee.fixtures.ProjectAuthRequestPerformer @@ -15,16 +15,17 @@ import org.springframework.mock.web.MockMultipartFile import org.springframework.test.web.servlet.ResultActions abstract class ProjectAuthControllerTest( - val projectUrlPrefix: String = "/api/project/" + val projectUrlPrefix: String = "/api/project/", ) : AuthorizedControllerTest(), AuthRequestPerformer { - // for api key auth methods val apiKey: ApiKeyDTO get() { val performer = this.projectAuthRequestPerformer - return if (performer is ProjectApiKeyAuthRequestPerformer) - performer.apiKey else + return if (performer is ProjectApiKeyAuthRequestPerformer) { + performer.apiKey + } else { throw Exception("Method not annotated with ApiKeyAccessTestMethod?") + } } val project: Project @@ -58,7 +59,7 @@ abstract class ProjectAuthControllerTest( { userAccount }, this.scopes, projectUrlPrefix, - this.apiKeyPresentType + this.apiKeyPresentType, ) } } @@ -71,11 +72,17 @@ abstract class ProjectAuthControllerTest( } } - fun performProjectAuthPut(url: String, content: Any? = null): ResultActions { + fun performProjectAuthPut( + url: String, + content: Any? = null, + ): ResultActions { return projectAuthRequestPerformer.performProjectAuthPut(url, content) } - fun performProjectAuthPost(url: String, content: Any? = null): ResultActions { + fun performProjectAuthPost( + url: String, + content: Any? = null, + ): ResultActions { return projectAuthRequestPerformer.performProjectAuthPost(url, content) } @@ -83,14 +90,17 @@ abstract class ProjectAuthControllerTest( return projectAuthRequestPerformer.performProjectAuthGet(url) } - fun performProjectAuthDelete(url: String, content: Any? = null): ResultActions { + fun performProjectAuthDelete( + url: String, + content: Any? = null, + ): ResultActions { return projectAuthRequestPerformer.performProjectAuthDelete(url, content) } fun performProjectAuthMultipart( url: String, files: List, - params: Map> = mapOf() + params: Map> = mapOf(), ): ResultActions { return projectAuthRequestPerformer.performProjectAuthMultipart(url, files, params) } diff --git a/backend/testing/src/main/kotlin/io/tolgee/fixtures/AuthRequestPerformer.kt b/backend/testing/src/main/kotlin/io/tolgee/fixtures/AuthRequestPerformer.kt index d2ab8d66f5..3eabc0ff2a 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/fixtures/AuthRequestPerformer.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/fixtures/AuthRequestPerformer.kt @@ -4,13 +4,26 @@ import org.springframework.mock.web.MockMultipartFile import org.springframework.test.web.servlet.ResultActions interface AuthRequestPerformer : RequestPerformer { - fun performAuthPut(url: String, content: Any?): ResultActions - fun performAuthPost(url: String, content: Any?): ResultActions + fun performAuthPut( + url: String, + content: Any?, + ): ResultActions + + fun performAuthPost( + url: String, + content: Any?, + ): ResultActions + fun performAuthGet(url: String): ResultActions - fun performAuthDelete(url: String, content: Any? = null): ResultActions + + fun performAuthDelete( + url: String, + content: Any? = null, + ): ResultActions + fun performAuthMultipart( url: String, files: List, - params: Map> = mapOf() + params: Map> = mapOf(), ): ResultActions } diff --git a/backend/testing/src/main/kotlin/io/tolgee/fixtures/AuthorizedRequestPerformer.kt b/backend/testing/src/main/kotlin/io/tolgee/fixtures/AuthorizedRequestPerformer.kt index f030f86809..2c0fdf78d5 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/fixtures/AuthorizedRequestPerformer.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/fixtures/AuthorizedRequestPerformer.kt @@ -9,12 +9,17 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders @Component @Scope("prototype") class AuthorizedRequestPerformer : BaseRequestPerformer(), AuthRequestPerformer { - - override fun performAuthPut(url: String, content: Any?): ResultActions { + override fun performAuthPut( + url: String, + content: Any?, + ): ResultActions { return mvc.perform(AuthorizedRequestFactory.loggedPut(url).withJsonContent(content)) } - override fun performAuthPost(url: String, content: Any?): ResultActions { + override fun performAuthPost( + url: String, + content: Any?, + ): ResultActions { return mvc.perform(AuthorizedRequestFactory.loggedPost(url).withJsonContent(content)) } @@ -22,14 +27,17 @@ class AuthorizedRequestPerformer : BaseRequestPerformer(), AuthRequestPerformer return mvc.perform(AuthorizedRequestFactory.loggedGet(url)) } - override fun performAuthDelete(url: String, content: Any?): ResultActions { + override fun performAuthDelete( + url: String, + content: Any?, + ): ResultActions { return mvc.perform(AuthorizedRequestFactory.loggedDelete(url).withJsonContent(content)) } override fun performAuthMultipart( url: String, files: List, - params: Map> + params: Map>, ): ResultActions { val builder = MockMvcRequestBuilders.multipart(url) files.forEach { builder.file(it) } diff --git a/backend/testing/src/main/kotlin/io/tolgee/fixtures/BaseRequestPerformer.kt b/backend/testing/src/main/kotlin/io/tolgee/fixtures/BaseRequestPerformer.kt index 8d0ff31af5..9cdad378cf 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/fixtures/BaseRequestPerformer.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/fixtures/BaseRequestPerformer.kt @@ -16,7 +16,6 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders @Scope("prototype") @Primary class BaseRequestPerformer : RequestPerformer { - @field:Autowired lateinit var mvc: MockMvc @@ -31,20 +30,31 @@ class BaseRequestPerformer : RequestPerformer { override fun performPut( url: String, content: Any?, - httpHeaders: HttpHeaders + httpHeaders: HttpHeaders, ): ResultActions { return perform(MockMvcRequestBuilders.put(url).withJsonContent(content).headers(httpHeaders)) } - override fun performPost(url: String, content: Any?, httpHeaders: HttpHeaders): ResultActions { + override fun performPost( + url: String, + content: Any?, + httpHeaders: HttpHeaders, + ): ResultActions { return perform(MockMvcRequestBuilders.post(url).withJsonContent(content).headers(httpHeaders)) } - override fun performGet(url: String, httpHeaders: HttpHeaders): ResultActions { + override fun performGet( + url: String, + httpHeaders: HttpHeaders, + ): ResultActions { return perform(MockMvcRequestBuilders.get(url).headers(httpHeaders)) } - override fun performDelete(url: String, content: Any?, httpHeaders: HttpHeaders): ResultActions { + override fun performDelete( + url: String, + content: Any?, + httpHeaders: HttpHeaders, + ): ResultActions { return perform(MockMvcRequestBuilders.delete(url).withJsonContent(content).headers(httpHeaders)) } diff --git a/backend/testing/src/main/kotlin/io/tolgee/fixtures/EmailTestUtil.kt b/backend/testing/src/main/kotlin/io/tolgee/fixtures/EmailTestUtil.kt index aa079cbe25..6a0f40ea20 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/fixtures/EmailTestUtil.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/fixtures/EmailTestUtil.kt @@ -19,7 +19,6 @@ import org.springframework.stereotype.Component @Component class EmailTestUtil() { - @Autowired @MockBean lateinit var javaMailSender: JavaMailSender @@ -41,13 +40,14 @@ class EmailTestUtil() { get() = messageContents.first() val messageContents: List - get() = messageArgumentCaptor.allValues.map { - ( - (it.content as MimeMultipart) - .getBodyPart(0).content as MimeMultipart + get() = + messageArgumentCaptor.allValues.map { + ( + (it.content as MimeMultipart) + .getBodyPart(0).content as MimeMultipart ) - .getBodyPart(0).content as String - } + .getBodyPart(0).content as String + } fun verifyEmailSent() { verify(javaMailSender).send(any()) diff --git a/backend/testing/src/main/kotlin/io/tolgee/fixtures/HttpClientMocker.kt b/backend/testing/src/main/kotlin/io/tolgee/fixtures/HttpClientMocker.kt index 9b406996d1..90f0df4550 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/fixtures/HttpClientMocker.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/fixtures/HttpClientMocker.kt @@ -14,7 +14,7 @@ import org.springframework.web.client.RestTemplate class HttpClientMocker(private val restTemplate: RestTemplate) { data class VerifyTools( - val captor: KArgumentCaptor> = argumentCaptor() + val captor: KArgumentCaptor> = argumentCaptor(), ) data class Definition( @@ -34,8 +34,8 @@ class HttpClientMocker(private val restTemplate: RestTemplate) { argThat { definition.url(this) }, argThat { definition.method(this) }, verifyTools.captor.capture(), - eq(String::class.java) - ) + eq(String::class.java), + ), ).apply { if (toThrow != null) { thenThrow(toThrow!!) diff --git a/backend/testing/src/main/kotlin/io/tolgee/fixtures/MimeMessageParser.kt b/backend/testing/src/main/kotlin/io/tolgee/fixtures/MimeMessageParser.kt index 8607c7d5d4..9450608162 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/fixtures/MimeMessageParser.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/fixtures/MimeMessageParser.kt @@ -34,14 +34,14 @@ import java.util.* open class MimeMessageParser(message: jakarta.mail.internet.MimeMessage) { /** The MimeMessage to convert */ private val mimeMessage: jakarta.mail.internet.MimeMessage + /** @return Returns the plainContent if any - */ - /** Plain mail content from MimeMessage */ + Plain mail content from MimeMessage */ var plainContent: String? = null private set + /** @return Returns the htmlContent if any - */ - /** Html mail content from MimeMessage */ + Html mail content from MimeMessage */ var htmlContent: String? = null private set @@ -50,9 +50,9 @@ open class MimeMessageParser(message: jakarta.mail.internet.MimeMessage) { /** Attachments stored by their content-id */ private val cidMap: MutableMap + /** @return Returns the isMultiPart. - */ - /** Is this a Multipart email */ + Is this a Multipart email */ var isMultipart: Boolean private set @@ -126,7 +126,9 @@ open class MimeMessageParser(message: jakarta.mail.internet.MimeMessage) { val addresses: Array = mimeMessage.from return if (addresses == null || addresses.size == 0) { null - } else (addresses[0] as jakarta.mail.internet.InternetAddress).address + } else { + (addresses[0] as jakarta.mail.internet.InternetAddress).address + } } @get:Throws(Exception::class) @@ -139,7 +141,9 @@ open class MimeMessageParser(message: jakarta.mail.internet.MimeMessage) { val addresses: Array = mimeMessage.replyTo return if (addresses == null || addresses.size == 0) { null - } else (addresses[0] as jakarta.mail.internet.InternetAddress).address + } else { + (addresses[0] as jakarta.mail.internet.InternetAddress).address + } } @get:Throws(Exception::class) @@ -159,17 +163,20 @@ open class MimeMessageParser(message: jakarta.mail.internet.MimeMessage) { * @throws IOException parsing the MimeMessage failed */ @Throws(jakarta.mail.MessagingException::class, IOException::class) - protected fun parse(parent: jakarta.mail.Multipart?, part: jakarta.mail.internet.MimePart) { + protected fun parse( + parent: jakarta.mail.Multipart?, + part: jakarta.mail.internet.MimePart, + ) { if (isMimeType( part, - "text/plain" + "text/plain", ) && plainContent == null && !jakarta.mail.Part.ATTACHMENT.equals(part.disposition, ignoreCase = true) ) { plainContent = part.content.toString() } else { if (isMimeType( part, - "text/html" + "text/html", ) && htmlContent == null && !jakarta.mail.Part.ATTACHMENT.equals(part.disposition, ignoreCase = true) ) { htmlContent = part.content.toString() @@ -214,7 +221,10 @@ open class MimeMessageParser(message: jakarta.mail.internet.MimeMessage) { * @throws IOException parsing the MimeMessage failed */ @Throws(jakarta.mail.MessagingException::class, IOException::class) - private fun isMimeType(part: jakarta.mail.internet.MimePart, mimeType: String): Boolean { + private fun isMimeType( + part: jakarta.mail.internet.MimePart, + mimeType: String, + ): Boolean { // Do not use part.isMimeType(String) as it is broken for MimeBodyPart // and does not really check the actual content type. return try { @@ -238,7 +248,7 @@ open class MimeMessageParser(message: jakarta.mail.internet.MimeMessage) { @Throws(jakarta.mail.MessagingException::class, IOException::class) protected fun createDataSource( parent: jakarta.mail.Multipart?, - part: jakarta.mail.internet.MimePart + part: jakarta.mail.internet.MimePart, ): jakarta.activation.DataSource { val dataHandler: jakarta.activation.DataHandler = part.dataHandler val dataSource: jakarta.activation.DataSource = dataHandler.dataSource @@ -330,16 +340,20 @@ open class MimeMessageParser(message: jakarta.mail.internet.MimeMessage) { * @throws UnsupportedEncodingException decoding the text failed */ @Throws(jakarta.mail.MessagingException::class, UnsupportedEncodingException::class) - protected fun getDataSourceName(part: jakarta.mail.Part, dataSource: jakarta.activation.DataSource): String? { + protected fun getDataSourceName( + part: jakarta.mail.Part, + dataSource: jakarta.activation.DataSource, + ): String? { var result: String? = dataSource.name if (result == null || result.isEmpty()) { result = part.fileName } - result = if (result != null && !result.isEmpty()) { - jakarta.mail.internet.MimeUtility.decodeText(result) - } else { - null - } + result = + if (result != null && !result.isEmpty()) { + jakarta.mail.internet.MimeUtility.decodeText(result) + } else { + null + } return result } @@ -374,6 +388,8 @@ open class MimeMessageParser(message: jakarta.mail.internet.MimeMessage) { val pos = fullMimeType.indexOf(';') return if (pos >= 0) { fullMimeType.substring(0, pos) - } else fullMimeType + } else { + fullMimeType + } } } diff --git a/backend/testing/src/main/kotlin/io/tolgee/fixtures/ProjectApiKeyAuthRequestPerformer.kt b/backend/testing/src/main/kotlin/io/tolgee/fixtures/ProjectApiKeyAuthRequestPerformer.kt index 9c826e7ac6..f55129e100 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/fixtures/ProjectApiKeyAuthRequestPerformer.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/fixtures/ProjectApiKeyAuthRequestPerformer.kt @@ -1,7 +1,7 @@ package io.tolgee.fixtures import io.tolgee.API_KEY_HEADER_NAME -import io.tolgee.dtos.response.ApiKeyDTO.ApiKeyDTO +import io.tolgee.dtos.response.ApiKeyDTO import io.tolgee.model.UserAccount import io.tolgee.service.security.ApiKeyService import io.tolgee.testing.annotations.ApiKeyPresentMode @@ -19,23 +19,28 @@ class ProjectApiKeyAuthRequestPerformer( private val userAccountProvider: () -> UserAccount, private val scopes: Array, projectUrlPrefix: String = "/api/project", - private val apiKeyPresentMode: ApiKeyPresentMode = ApiKeyPresentMode.HEADER + private val apiKeyPresentMode: ApiKeyPresentMode = ApiKeyPresentMode.HEADER, ) : ProjectAuthRequestPerformer(userAccountProvider, projectUrlPrefix) { - @field:Autowired lateinit var apiKeyService: ApiKeyService val apiKey: ApiKeyDTO by lazy { - ApiKeyDTO.fromEntity( - apiKeyService.create(userAccountProvider.invoke(), scopes = this.scopes.toSet(), project) + io.tolgee.dtos.response.ApiKeyDTO.fromEntity( + apiKeyService.create(userAccountProvider.invoke(), scopes = this.scopes.toSet(), project), ) } - override fun performProjectAuthPut(url: String, content: Any?): ResultActions { + override fun performProjectAuthPut( + url: String, + content: Any?, + ): ResultActions { return performPut(projectUrlPrefix + url.withApiKey, content, headersWithApiKey) } - override fun performProjectAuthPost(url: String, content: Any?): ResultActions { + override fun performProjectAuthPost( + url: String, + content: Any?, + ): ResultActions { return performPost(projectUrlPrefix + url.withApiKey, content, headersWithApiKey) } @@ -43,22 +48,25 @@ class ProjectApiKeyAuthRequestPerformer( return performGet(projectUrlPrefix + url.withApiKey, headersWithApiKey) } - override fun performProjectAuthDelete(url: String, content: Any?): ResultActions { + override fun performProjectAuthDelete( + url: String, + content: Any?, + ): ResultActions { return performDelete(projectUrlPrefix + url.withApiKey, content, headersWithApiKey) } override fun performProjectAuthMultipart( url: String, files: List, - params: Map> + params: Map>, ): ResultActions { val builder = MockMvcRequestBuilders.multipart(url) files.forEach { builder.file(it) } params.forEach { (name, values) -> builder.param(name, *values) } return mvc.perform( AuthorizedRequestFactory.addToken( - MockMvcRequestBuilders.multipart(projectUrlPrefix + url.withApiKey) - ) + MockMvcRequestBuilders.multipart(projectUrlPrefix + url.withApiKey), + ), ) } diff --git a/backend/testing/src/main/kotlin/io/tolgee/fixtures/ProjectAuthRequestPerformer.kt b/backend/testing/src/main/kotlin/io/tolgee/fixtures/ProjectAuthRequestPerformer.kt index b86a11cbf5..2b2badc280 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/fixtures/ProjectAuthRequestPerformer.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/fixtures/ProjectAuthRequestPerformer.kt @@ -9,9 +9,8 @@ import org.springframework.test.web.servlet.ResultActions abstract class ProjectAuthRequestPerformer( userAccountProvider: () -> UserAccount, - val projectUrlPrefix: String = "/api/project/" + val projectUrlPrefix: String = "/api/project/", ) : AuthorizedRequestPerformer() { - @field:Autowired lateinit var dbPopulator: DbPopulatorReal @@ -24,13 +23,26 @@ abstract class ProjectAuthRequestPerformer( var projectSupplier: (() -> Project)? = null - abstract fun performProjectAuthPut(url: String, content: Any?): ResultActions - abstract fun performProjectAuthPost(url: String, content: Any?): ResultActions + abstract fun performProjectAuthPut( + url: String, + content: Any?, + ): ResultActions + + abstract fun performProjectAuthPost( + url: String, + content: Any?, + ): ResultActions + abstract fun performProjectAuthGet(url: String): ResultActions - abstract fun performProjectAuthDelete(url: String, content: Any?): ResultActions + + abstract fun performProjectAuthDelete( + url: String, + content: Any?, + ): ResultActions + abstract fun performProjectAuthMultipart( url: String, files: List, - params: Map> + params: Map>, ): ResultActions } diff --git a/backend/testing/src/main/kotlin/io/tolgee/fixtures/ProjectJwtAuthRequestPerformer.kt b/backend/testing/src/main/kotlin/io/tolgee/fixtures/ProjectJwtAuthRequestPerformer.kt index 9a7a17594d..735dabb6b5 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/fixtures/ProjectJwtAuthRequestPerformer.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/fixtures/ProjectJwtAuthRequestPerformer.kt @@ -11,14 +11,19 @@ import org.springframework.test.web.servlet.ResultActions @Suppress("SpringJavaInjectionPointsAutowiringInspection") class ProjectJwtAuthRequestPerformer( userAccountProvider: () -> UserAccount, - projectUrlPrefix: String + projectUrlPrefix: String, ) : ProjectAuthRequestPerformer(userAccountProvider, projectUrlPrefix) { - - override fun performProjectAuthPut(url: String, content: Any?): ResultActions { + override fun performProjectAuthPut( + url: String, + content: Any?, + ): ResultActions { return super.performAuthPut(projectUrlPrefix + project.id + "/" + url, content) } - override fun performProjectAuthPost(url: String, content: Any?): ResultActions { + override fun performProjectAuthPost( + url: String, + content: Any?, + ): ResultActions { return performAuthPost(projectUrlPrefix + project.id + "/" + url, content) } @@ -26,14 +31,17 @@ class ProjectJwtAuthRequestPerformer( return performAuthGet(projectUrlPrefix + project.id + "/" + url) } - override fun performProjectAuthDelete(url: String, content: Any?): ResultActions { + override fun performProjectAuthDelete( + url: String, + content: Any?, + ): ResultActions { return performAuthDelete(projectUrlPrefix + project.id + "/" + url, content) } override fun performProjectAuthMultipart( url: String, files: List, - params: Map> + params: Map>, ): ResultActions { return performAuthMultipart(projectUrlPrefix + project.id + "/" + url, files, params) } diff --git a/backend/testing/src/main/kotlin/io/tolgee/fixtures/RedisRunner.kt b/backend/testing/src/main/kotlin/io/tolgee/fixtures/RedisRunner.kt index 5b3ccea487..1d763a213c 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/fixtures/RedisRunner.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/fixtures/RedisRunner.kt @@ -3,13 +3,14 @@ package io.tolgee.fixtures import io.tolgee.misc.dockerRunner.DockerContainerRunner class RedisRunner { - private val runner = DockerContainerRunner( - image = "redis:6", - expose = mapOf("56379" to "6379"), - waitForLog = "Ready to accept connections", - rm = true, - name = "server-integration-test-redis", - ) + private val runner = + DockerContainerRunner( + image = "redis:6", + expose = mapOf("56379" to "6379"), + waitForLog = "Ready to accept connections", + rm = true, + name = "server-integration-test-redis", + ) fun run() { runner.run() diff --git a/backend/testing/src/main/kotlin/io/tolgee/fixtures/RequestPerformer.kt b/backend/testing/src/main/kotlin/io/tolgee/fixtures/RequestPerformer.kt index a418ec712a..ccdd6bd1de 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/fixtures/RequestPerformer.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/fixtures/RequestPerformer.kt @@ -6,8 +6,27 @@ import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilde interface RequestPerformer { fun perform(builder: MockHttpServletRequestBuilder): ResultActions - fun performPut(url: String, content: Any?, httpHeaders: HttpHeaders = HttpHeaders.EMPTY): ResultActions - fun performPost(url: String, content: Any?, httpHeaders: HttpHeaders = HttpHeaders.EMPTY): ResultActions - fun performGet(url: String, httpHeaders: HttpHeaders = HttpHeaders.EMPTY): ResultActions - fun performDelete(url: String, content: Any?, httpHeaders: HttpHeaders = HttpHeaders.EMPTY): ResultActions + + fun performPut( + url: String, + content: Any?, + httpHeaders: HttpHeaders = HttpHeaders.EMPTY, + ): ResultActions + + fun performPost( + url: String, + content: Any?, + httpHeaders: HttpHeaders = HttpHeaders.EMPTY, + ): ResultActions + + fun performGet( + url: String, + httpHeaders: HttpHeaders = HttpHeaders.EMPTY, + ): ResultActions + + fun performDelete( + url: String, + content: Any?, + httpHeaders: HttpHeaders = HttpHeaders.EMPTY, + ): ResultActions } diff --git a/backend/testing/src/main/kotlin/io/tolgee/fixtures/mockHttpRequests.kt b/backend/testing/src/main/kotlin/io/tolgee/fixtures/mockHttpRequests.kt index d7b78a58b6..864f109088 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/fixtures/mockHttpRequests.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/fixtures/mockHttpRequests.kt @@ -2,7 +2,10 @@ package io.tolgee.fixtures import org.springframework.web.client.RestTemplate -fun mockHttpRequest(restTemplate: RestTemplate, mock: HttpClientMocker.() -> Unit) { +fun mockHttpRequest( + restTemplate: RestTemplate, + mock: HttpClientMocker.() -> Unit, +) { val httpClientMocker = HttpClientMocker(restTemplate) mock(httpClientMocker) } diff --git a/backend/testing/src/main/kotlin/io/tolgee/fixtures/retry.kt b/backend/testing/src/main/kotlin/io/tolgee/fixtures/retry.kt index 3c59a72005..ca612bbe64 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/fixtures/retry.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/fixtures/retry.kt @@ -3,7 +3,7 @@ package io.tolgee.fixtures fun retry( retries: Int = 3, exceptionMatcher: (Throwable) -> Boolean = { true }, - fn: () -> Unit + fn: () -> Unit, ) { val thrown = mutableListOf() var passed = false @@ -29,5 +29,6 @@ fun retry( } class RetryException(val retryCount: Int, val causes: List) : Exception( - "Test failed in $retryCount retries", causes.last() + "Test failed in $retryCount retries", + causes.last(), ) diff --git a/backend/testing/src/main/kotlin/io/tolgee/fixtures/scopeAssert.kt b/backend/testing/src/main/kotlin/io/tolgee/fixtures/scopeAssert.kt index 8e85e4cf72..e462cd84a2 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/fixtures/scopeAssert.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/fixtures/scopeAssert.kt @@ -6,9 +6,7 @@ import io.tolgee.model.enums.unpack import io.tolgee.testing.assertions.Assertions import org.assertj.core.api.ObjectArrayAssert -fun ObjectArrayAssert.equalsPermissionType( - permissionType: ProjectPermissionType -): ObjectArrayAssert? { +fun ObjectArrayAssert.equalsPermissionType(permissionType: ProjectPermissionType): ObjectArrayAssert? { return this.satisfies { Assertions.assertThat(it.unpack()).containsExactlyInAnyOrder(*permissionType.availableScopes.unpack()) } diff --git a/backend/testing/src/main/kotlin/io/tolgee/fixtures/statusExpectations.kt b/backend/testing/src/main/kotlin/io/tolgee/fixtures/statusExpectations.kt index 39c82b6c29..fd41a6932b 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/fixtures/statusExpectations.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/fixtures/statusExpectations.kt @@ -84,13 +84,17 @@ val ResultActions.andAssertError get() = assertThat(this.andReturn()).error() val ResultActions.andPrettyPrint: ResultActions - get() = jacksonObjectMapper().let { mapper -> - val parsed = mapper.readValue(this.andGetContentAsString) - println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(parsed)) - return this - } + get() = + jacksonObjectMapper().let { mapper -> + val parsed = mapper.readValue(this.andGetContentAsString) + println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(parsed)) + return this + } -fun JsonAssert.node(node: String, rfn: JsonAssert.() -> Unit): JsonAssert { +fun JsonAssert.node( + node: String, + rfn: JsonAssert.() -> Unit, +): JsonAssert { rfn(node(node)) return this } diff --git a/backend/testing/src/main/kotlin/io/tolgee/testing/AbstractControllerTest.kt b/backend/testing/src/main/kotlin/io/tolgee/testing/AbstractControllerTest.kt index 82a283fdff..f0e95cc71b 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/testing/AbstractControllerTest.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/testing/AbstractControllerTest.kt @@ -25,7 +25,6 @@ import java.io.UnsupportedEncodingException @SpringBootTest abstract class AbstractControllerTest : AbstractSpringTest(), RequestPerformer { - @Autowired protected lateinit var mvc: MockMvc @@ -33,7 +32,10 @@ abstract class AbstractControllerTest : @Autowired protected lateinit var requestPerformer: RequestPerformer - fun decodeJson(json: String?, clazz: Class?): T { + fun decodeJson( + json: String?, + clazz: Class?, + ): T { val mapper = jacksonObjectMapper() return try { mapper.readValue(json, clazz) @@ -42,16 +44,24 @@ abstract class AbstractControllerTest : } } - protected fun login(userName: String, password: String): DefaultAuthenticationResult { - val response = doAuthentication(userName, password) - .andReturn().response.contentAsString + protected fun login( + userName: String, + password: String, + ): DefaultAuthenticationResult { + val response = + doAuthentication(userName, password) + .andReturn().response.contentAsString val userAccount = userAccountService.findActive(userName) ?: throw NotFoundException() return DefaultAuthenticationResult( - mapper.readValue(response, HashMap::class.java)["accessToken"] as String, userAccount + mapper.readValue(response, HashMap::class.java)["accessToken"] as String, + userAccount, ) } - protected fun doAuthentication(username: String, password: String): ResultActions { + protected fun doAuthentication( + username: String, + password: String, + ): ResultActions { val request = LoginRequest() request.username = username request.password = password @@ -60,11 +70,14 @@ abstract class AbstractControllerTest : MockMvcRequestBuilders.post("/api/public/generatetoken") .content(jsonRequest) .accept(MediaType.ALL) - .contentType(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON), ) } - protected fun mapResponse(result: MvcResult, type: JavaType?): T { + protected fun mapResponse( + result: MvcResult, + type: JavaType?, + ): T { return try { mapper.readValue(result.response.contentAsString, type) } catch (e: JsonProcessingException) { @@ -74,7 +87,10 @@ abstract class AbstractControllerTest : } } - protected fun mapResponse(result: MvcResult, clazz: Class?): T { + protected fun mapResponse( + result: MvcResult, + clazz: Class?, + ): T { return try { mapper.readValue(result.response.contentAsString, clazz) } catch (e: JsonProcessingException) { @@ -87,12 +103,12 @@ abstract class AbstractControllerTest : protected fun ?, E> mapResponse( result: MvcResult, collectionType: Class?, - elementType: Class? + elementType: Class?, ): C { return try { mapper.readValue( result.response.contentAsString, - TypeFactory.defaultInstance().constructCollectionType(collectionType, elementType) + TypeFactory.defaultInstance().constructCollectionType(collectionType, elementType), ) } catch (e: JsonProcessingException) { throw RuntimeException(e) @@ -105,19 +121,34 @@ abstract class AbstractControllerTest : return requestPerformer.perform(builder) } - override fun performPut(url: String, content: Any?, httpHeaders: HttpHeaders): ResultActions { + override fun performPut( + url: String, + content: Any?, + httpHeaders: HttpHeaders, + ): ResultActions { return requestPerformer.performPut(url, content, httpHeaders) } - override fun performPost(url: String, content: Any?, httpHeaders: HttpHeaders): ResultActions { + override fun performPost( + url: String, + content: Any?, + httpHeaders: HttpHeaders, + ): ResultActions { return requestPerformer.performPost(url, content, httpHeaders) } - override fun performGet(url: String, httpHeaders: HttpHeaders): ResultActions { + override fun performGet( + url: String, + httpHeaders: HttpHeaders, + ): ResultActions { return requestPerformer.performGet(url, httpHeaders) } - override fun performDelete(url: String, content: Any?, httpHeaders: HttpHeaders): ResultActions { + override fun performDelete( + url: String, + content: Any?, + httpHeaders: HttpHeaders, + ): ResultActions { return requestPerformer.performDelete(url, content, httpHeaders) } } diff --git a/backend/testing/src/main/kotlin/io/tolgee/testing/AbstractTransactionalTest.kt b/backend/testing/src/main/kotlin/io/tolgee/testing/AbstractTransactionalTest.kt index 7acdc02bfd..4079edb18b 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/testing/AbstractTransactionalTest.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/testing/AbstractTransactionalTest.kt @@ -15,8 +15,8 @@ import org.springframework.test.context.transaction.TransactionalTestExecutionLi TransactionalTestExecutionListener::class, DependencyInjectionTestExecutionListener::class, CleanDbTestListener::class, - DirtiesContextTestExecutionListener::class - ] + DirtiesContextTestExecutionListener::class, + ], ) @ActiveProfiles(profiles = ["local"]) abstract class AbstractTransactionalTest { diff --git a/backend/testing/src/main/kotlin/io/tolgee/testing/AuthorizedControllerTest.kt b/backend/testing/src/main/kotlin/io/tolgee/testing/AuthorizedControllerTest.kt index a99d124bc3..f1a49f4afd 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/testing/AuthorizedControllerTest.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/testing/AuthorizedControllerTest.kt @@ -80,28 +80,49 @@ abstract class AuthorizedControllerTest : AbstractControllerTest(), AuthRequestP return requestPerformer.perform(builder) } - override fun performDelete(url: String, content: Any?, httpHeaders: HttpHeaders): ResultActions { + override fun performDelete( + url: String, + content: Any?, + httpHeaders: HttpHeaders, + ): ResultActions { return requestPerformer.performDelete(url, content) } - override fun performGet(url: String, httpHeaders: HttpHeaders): ResultActions { + override fun performGet( + url: String, + httpHeaders: HttpHeaders, + ): ResultActions { return requestPerformer.performGet(url, httpHeaders) } - override fun performPost(url: String, content: Any?, httpHeaders: HttpHeaders): ResultActions { + override fun performPost( + url: String, + content: Any?, + httpHeaders: HttpHeaders, + ): ResultActions { return requestPerformer.performPost(url, content, httpHeaders) } - override fun performPut(url: String, content: Any?, httpHeaders: HttpHeaders): ResultActions { + override fun performPut( + url: String, + content: Any?, + httpHeaders: HttpHeaders, + ): ResultActions { return requestPerformer.performPut(url, content, httpHeaders) } - override fun performAuthPut(url: String, content: Any?): ResultActions { + override fun performAuthPut( + url: String, + content: Any?, + ): ResultActions { loginAsAdminIfNotLogged() return authorizedRequestPerformer.performAuthPut(url, content) } - override fun performAuthPost(url: String, content: Any?): ResultActions { + override fun performAuthPost( + url: String, + content: Any?, + ): ResultActions { loginAsAdminIfNotLogged() return authorizedRequestPerformer.performAuthPost(url, content) } @@ -111,7 +132,10 @@ abstract class AuthorizedControllerTest : AbstractControllerTest(), AuthRequestP return authorizedRequestPerformer.performAuthGet(url) } - override fun performAuthDelete(url: String, content: Any?): ResultActions { + override fun performAuthDelete( + url: String, + content: Any?, + ): ResultActions { loginAsAdminIfNotLogged() return authorizedRequestPerformer.performAuthDelete(url, content) } @@ -119,7 +143,7 @@ abstract class AuthorizedControllerTest : AbstractControllerTest(), AuthRequestP override fun performAuthMultipart( url: String, files: List, - params: Map> + params: Map>, ): ResultActions { loginAsAdminIfNotLogged() return authorizedRequestPerformer.performAuthMultipart(url, files, params) @@ -141,7 +165,10 @@ abstract class AuthorizedControllerTest : AbstractControllerTest(), AuthRequestP refreshJwtToken() } - override fun forceDateString(dateString: String, pattern: String) { + override fun forceDateString( + dateString: String, + pattern: String, + ) { super.forceDateString(dateString, pattern) refreshJwtToken() } diff --git a/backend/testing/src/main/kotlin/io/tolgee/testing/InvitationTestUtil.kt b/backend/testing/src/main/kotlin/io/tolgee/testing/InvitationTestUtil.kt index e0fd991453..81e6a2735d 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/testing/InvitationTestUtil.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/testing/InvitationTestUtil.kt @@ -14,7 +14,7 @@ import org.springframework.test.web.servlet.ResultActions class InvitationTestUtil( private val test: ProjectAuthControllerTest, - private val applicationContext: ApplicationContext + private val applicationContext: ApplicationContext, ) { fun perform(fn: ProjectInviteUserDto.(getLang: LangByTag) -> Unit): ResultActions { val testData = prepareTestData() @@ -23,12 +23,12 @@ class InvitationTestUtil( "/invite", ProjectInviteUserDto().apply { fn( - this + this, ) { tag -> testData.projectBuilder.data.languages.find { it.self.tag == tag }?.self?.id ?: throw NullPointerException("Language $tag not found") } - } + }, ) } diff --git a/backend/testing/src/main/kotlin/io/tolgee/testing/PermissionTestUtil.kt b/backend/testing/src/main/kotlin/io/tolgee/testing/PermissionTestUtil.kt index d4d20d83b1..3e69fe43ec 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/testing/PermissionTestUtil.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/testing/PermissionTestUtil.kt @@ -18,9 +18,8 @@ typealias LangByTag = (tag: String) -> Long @Component class PermissionTestUtil( private val test: AuthorizedControllerTest, - private val applicationContext: ApplicationContext + private val applicationContext: ApplicationContext, ) { - private val organizationRoleService: OrganizationRoleService get() = applicationContext.getBean(OrganizationRoleService::class.java) @@ -39,16 +38,17 @@ class PermissionTestUtil( val langByTag = { tag: String -> languages.find { it.tag == tag }!!.id } val query = getQueryFn(langByTag) - val typeAndQuery = if (type.isEmpty()) { - "?$query" - } else { - "/$type?$query" - } + val typeAndQuery = + if (type.isEmpty()) { + "?$query" + } else { + "/$type?$query" + } test.performAuthPut( "/v2/projects/${project.id}/users/${user.id}" + "/set-permissions$typeAndQuery", - null + null, ) } } @@ -56,23 +56,24 @@ class PermissionTestUtil( fun checkSetPermissionsWithLanguages( type: String, getQueryFn: (langByTag: LangByTag) -> String, - checkFn: (data: ProjectPermissionData, langByTag: LangByTag) -> Unit + checkFn: (data: ProjectPermissionData, langByTag: LangByTag) -> Unit, ) { withPermissionsTestData { project, user -> val languages = project.languages.toList() val langByTag = { tag: String -> languages.find { it.tag == tag }!!.id } val query = getQueryFn(langByTag) - val typeAndQuery = if (type.isEmpty()) { - "?$query" - } else { - "/$type?$query" - } + val typeAndQuery = + if (type.isEmpty()) { + "?$query" + } else { + "/$type?$query" + } test.performAuthPut( "/v2/projects/${project.id}/users/${user.id}" + "/set-permissions$typeAndQuery", - null + null, ).andIsOk checkFn(permissionService.getProjectPermissionData(project.id, user.id), langByTag) @@ -82,10 +83,11 @@ class PermissionTestUtil( fun withPermissionsTestData(fn: (project: Project, user: UserAccount) -> T): T { val usersAndOrganizations = dbPopulator.createUsersAndOrganizations() - val project = usersAndOrganizations[1] - .organizationRoles[0] - .organization!! - .projects[0] + val project = + usersAndOrganizations[1] + .organizationRoles[0] + .organization!! + .projects[0] val user = dbPopulator.createUserIfNotExists("jirina") organizationRoleService.grantMemberRoleToUser(user, project.organizationOwner) diff --git a/backend/testing/src/main/kotlin/io/tolgee/testing/annotations/ApiKeyPresentMode.kt b/backend/testing/src/main/kotlin/io/tolgee/testing/annotations/ApiKeyPresentMode.kt index ae381650ea..f511f26a34 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/testing/annotations/ApiKeyPresentMode.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/testing/annotations/ApiKeyPresentMode.kt @@ -1,5 +1,6 @@ package io.tolgee.testing.annotations enum class ApiKeyPresentMode { - HEADER, QUERY_PARAM + HEADER, + QUERY_PARAM, } diff --git a/backend/testing/src/main/kotlin/io/tolgee/testing/annotations/ProjectApiKeyAuthTestMethod.kt b/backend/testing/src/main/kotlin/io/tolgee/testing/annotations/ProjectApiKeyAuthTestMethod.kt index e5fd9b266e..95987e7fec 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/testing/annotations/ProjectApiKeyAuthTestMethod.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/testing/annotations/ProjectApiKeyAuthTestMethod.kt @@ -6,5 +6,5 @@ import org.junit.jupiter.api.Test @Test annotation class ProjectApiKeyAuthTestMethod( val apiKeyPresentType: ApiKeyPresentMode = ApiKeyPresentMode.HEADER, - val scopes: Array = [Scope.TRANSLATIONS_EDIT, Scope.KEYS_EDIT, Scope.TRANSLATIONS_VIEW, Scope.KEYS_VIEW] + val scopes: Array = [Scope.TRANSLATIONS_EDIT, Scope.KEYS_EDIT, Scope.TRANSLATIONS_VIEW, Scope.KEYS_VIEW], ) diff --git a/backend/testing/src/main/kotlin/io/tolgee/testing/assertions/ErrorResponseAssert.kt b/backend/testing/src/main/kotlin/io/tolgee/testing/assertions/ErrorResponseAssert.kt index c0e6f02495..5573f097f6 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/testing/assertions/ErrorResponseAssert.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/testing/assertions/ErrorResponseAssert.kt @@ -49,9 +49,9 @@ class ErrorResponseAssert(mvcResult: MvcResult?) : try { throw RuntimeException( """ - Can not parse error response: - ${actual!!.response.contentAsString} - """.trimIndent() + Can not parse error response: + ${actual!!.response.contentAsString} + """.trimIndent(), ) } catch (unsupportedEncodingException: UnsupportedEncodingException) { throw RuntimeException(unsupportedEncodingException) @@ -60,9 +60,9 @@ class ErrorResponseAssert(mvcResult: MvcResult?) : try { throw RuntimeException( """ - Can not parse error response: - ${actual!!.response.contentAsString} - """.trimIndent() + Can not parse error response: + ${actual!!.response.contentAsString} + """.trimIndent(), ) } catch (unsupportedEncodingException: UnsupportedEncodingException) { throw RuntimeException(unsupportedEncodingException) diff --git a/backend/testing/src/main/kotlin/io/tolgee/testing/assertions/StandardValidationMessageAssert.kt b/backend/testing/src/main/kotlin/io/tolgee/testing/assertions/StandardValidationMessageAssert.kt index 30434c2ec1..2393bf5324 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/testing/assertions/StandardValidationMessageAssert.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/testing/assertions/StandardValidationMessageAssert.kt @@ -7,7 +7,8 @@ import org.assertj.core.api.StringAssert class StandardValidationMessageAssert(val data: Map) : AbstractAssert>( - data, StandardValidationMessageAssert::class.java + data, + StandardValidationMessageAssert::class.java, ) { fun onField(field: String?): StringAssert { if (!actual!!.containsKey(field)) { @@ -18,8 +19,9 @@ class StandardValidationMessageAssert(val data: Map) : | |$it | - |Error is not on field %s.""".trimMargin(), - field + |Error is not on field %s. + """.trimMargin(), + field, ) } } diff --git a/backend/testing/src/main/kotlin/io/tolgee/testing/utils/InMemoryFileStorage.kt b/backend/testing/src/main/kotlin/io/tolgee/testing/utils/InMemoryFileStorage.kt index a5d332fd0e..c140c4726a 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/testing/utils/InMemoryFileStorage.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/testing/utils/InMemoryFileStorage.kt @@ -31,7 +31,10 @@ class InMemoryFileStorage : FileStorage { files.remove(storageFilePath) } - override fun storeFile(storageFilePath: String, bytes: ByteArray) { + override fun storeFile( + storageFilePath: String, + bytes: ByteArray, + ) { files[storageFilePath] = bytes } diff --git a/build.gradle b/build.gradle index 624ca19c80..c09b5ff8bd 100644 --- a/build.gradle +++ b/build.gradle @@ -10,17 +10,16 @@ buildscript { } } - plugins { - id("org.openrewrite.rewrite") version("6.3.16") -} - -rewrite { - activeRecipe("org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta") + id("org.jlleitschuh.gradle.ktlint") version "12.0.3" } -dependencies { - rewrite("org.openrewrite.recipe:rewrite-migrate-java:2.1.0") +subprojects { + if (project.projectDir.exists()) { + apply { + plugin("org.jlleitschuh.gradle.ktlint") + } + } } project.ext { @@ -33,10 +32,6 @@ if (System.getenv().containsKey("VERSION")) { project.version = 'local' } -configurations { - ktlint -} - apply plugin: 'idea' repositories { @@ -45,14 +40,6 @@ repositories { def unpackTarget = "${project.buildDir}/dependency" -dependencies { - ktlint("com.pinterest:ktlint:0.43.2") { - attributes { - attribute(Bundling.BUNDLING_ATTRIBUTE, getObjects().named(Bundling, Bundling.EXTERNAL)) - } - } -} - project(':server-app').afterEvaluate { task unpack(type: Copy) { from(zipTree(project(':server-app').tasks.findByName("bootJar").outputs.files.singleFile)) @@ -144,19 +131,9 @@ project(':server-app').afterEvaluate { } } -task ktlint(type: JavaExec, group: "verification") { - description = "Check Kotlin code style." - classpath = configurations.ktlint - main = "com.pinterest.ktlint.Main" - args "**/*.kt", "!**/data/PluralData.kt", '../billing/**/*.kt' -} - -task ktlintFormat(type: JavaExec, group: "formatting") { - description = "Fix Kotlin code style deviations." - classpath = configurations.ktlint - main = "com.pinterest.ktlint.Main" - args "-F", "**/*.kt", "!**/data/PluralData.kt", '../billing/**/*.kt' - jvmArgs = ["--add-opens=java.base/java.lang=ALL-UNNAMED"] +ktlint { + debug = true + verbose = true } subprojects { diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/AdvancedPermissionController.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/AdvancedPermissionController.kt index 0d81a04e25..8a695bad70 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/AdvancedPermissionController.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/AdvancedPermissionController.kt @@ -30,7 +30,7 @@ class AdvancedPermissionController( private val eePermissionService: EePermissionService, private val projectHolder: ProjectHolder, private val enabledFeaturesProvider: EnabledFeaturesProvider, - private val organizationRoleService: OrganizationRoleService + private val organizationRoleService: OrganizationRoleService, ) { @Suppress("MVCPathVariableInspection") @PutMapping("projects/{projectId}/users/{userId}/set-permissions") @@ -43,12 +43,13 @@ class AdvancedPermissionController( description = "Granted scopes", example = """["translations.view", "translations.edit"]""", ) - @RequestParam scopes: List?, - @ParameterObject params: SetPermissionLanguageParams + @RequestParam + scopes: List?, + @ParameterObject params: SetPermissionLanguageParams, ) { enabledFeaturesProvider.checkFeatureEnabled( projectHolder.project.organizationOwnerId!!, - Feature.GRANULAR_PERMISSIONS + Feature.GRANULAR_PERMISSIONS, ) val parsedScopes = Scope.parse(scopes) projectPermissionFacade.checkNotCurrentUser(userId) @@ -56,7 +57,7 @@ class AdvancedPermissionController( projectId = projectHolder.project.id, userId = userId, languages = projectPermissionFacade.getLanguages(params, projectHolder.project.id), - scopes = parsedScopes + scopes = parsedScopes, ) } @@ -67,9 +68,10 @@ class AdvancedPermissionController( @PathVariable organizationId: Long, @Parameter( description = "Granted scopes to all projects for all organization users without direct project permissions set", - example = """["translations.view", "translations.edit"]""" + example = """["translations.view", "translations.edit"]""", ) - @RequestParam scopes: List + @RequestParam + scopes: List, ) { enabledFeaturesProvider.checkFeatureEnabled(organizationId, Feature.GRANULAR_PERMISSIONS) val parsedScopes = Scope.parse(scopes) diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/ContentStorageController.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/ContentStorageController.kt index c36c8049a7..33880d9848 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/ContentStorageController.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/ContentStorageController.kt @@ -35,7 +35,7 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping( value = [ "/v2/projects/{projectId}/content-storages", - ] + ], ) @Tag(name = "Content Storages management (EE)") class ContentStorageController( @@ -43,16 +43,19 @@ class ContentStorageController( private val projectHolder: ProjectHolder, private val contentStorageModelAssembler: ContentStorageModelAssembler, private val pageModelAssembler: PagedResourcesAssembler, - private val enabledFeaturesProvider: EnabledFeaturesProvider + private val enabledFeaturesProvider: EnabledFeaturesProvider, ) { @PostMapping("") @Operation(description = "Create Content Storage") @RequiresProjectPermissions([Scope.CONTENT_DELIVERY_MANAGE]) @AllowApiAccess - fun create(@Valid @RequestBody dto: ContentStorageRequest): ContentStorageModel { + fun create( + @Valid @RequestBody + dto: ContentStorageRequest, + ): ContentStorageModel { enabledFeaturesProvider.checkFeatureEnabled( organizationId = projectHolder.project.organizationOwnerId, - Feature.PROJECT_LEVEL_CONTENT_STORAGES + Feature.PROJECT_LEVEL_CONTENT_STORAGES, ) val contentStorage = contentStorageService.create(projectHolder.project.id, dto) return contentStorageModelAssembler.toModel(contentStorage) @@ -64,11 +67,12 @@ class ContentStorageController( @AllowApiAccess fun update( @PathVariable contentStorageId: Long, - @Valid @RequestBody dto: ContentStorageRequest + @Valid @RequestBody + dto: ContentStorageRequest, ): ContentStorageModel { enabledFeaturesProvider.checkFeatureEnabled( organizationId = projectHolder.project.organizationOwnerId, - Feature.PROJECT_LEVEL_CONTENT_STORAGES + Feature.PROJECT_LEVEL_CONTENT_STORAGES, ) val contentStorage = contentStorageService.update(projectHolder.project.id, contentStorageId, dto) return contentStorageModelAssembler.toModel(contentStorage) @@ -78,7 +82,9 @@ class ContentStorageController( @GetMapping("") @Operation(description = "List existing Content Storages") @AllowApiAccess - fun list(@ParameterObject pageable: Pageable): PagedModel { + fun list( + @ParameterObject pageable: Pageable, + ): PagedModel { val page = contentStorageService.getAllInProject(projectHolder.project.id, pageable) return pageModelAssembler.toModel(page, contentStorageModelAssembler) } @@ -87,7 +93,9 @@ class ContentStorageController( @DeleteMapping("/{contentStorageId}") @Operation(description = "Delete Content Storage") @AllowApiAccess - fun delete(@PathVariable contentStorageId: Long) { + fun delete( + @PathVariable contentStorageId: Long, + ) { contentStorageService.delete(projectHolder.project.id, contentStorageId) } @@ -95,7 +103,9 @@ class ContentStorageController( @GetMapping("/{contentStorageId}") @Operation(description = "Get Content Storage") @AllowApiAccess - fun get(@PathVariable contentStorageId: Long): ContentStorageModel { + fun get( + @PathVariable contentStorageId: Long, + ): ContentStorageModel { return contentStorageModelAssembler .toModel(contentStorageService.get(projectHolder.project.id, contentStorageId)) } @@ -104,10 +114,13 @@ class ContentStorageController( @PostMapping("/test") @Operation(description = "Test Content Storage") @AllowApiAccess - fun test(@Valid @RequestBody dto: ContentStorageRequest): StorageTestResult { + fun test( + @Valid @RequestBody + dto: ContentStorageRequest, + ): StorageTestResult { enabledFeaturesProvider.checkFeatureEnabled( organizationId = projectHolder.project.organizationOwnerId, - Feature.PROJECT_LEVEL_CONTENT_STORAGES + Feature.PROJECT_LEVEL_CONTENT_STORAGES, ) return contentStorageService.testStorage(dto) } @@ -115,14 +128,19 @@ class ContentStorageController( @RequiresProjectPermissions([Scope.CONTENT_DELIVERY_MANAGE]) @PostMapping("/{id}/test") @Operation( - description = "Tests existing Content Storage with new configuration." + - " (Uses existing secrets, if nulls provided)" + description = + "Tests existing Content Storage with new configuration." + + " (Uses existing secrets, if nulls provided)", ) @AllowApiAccess - fun testExisting(@Valid @RequestBody dto: ContentStorageRequest, @PathVariable id: Long): StorageTestResult { + fun testExisting( + @Valid @RequestBody + dto: ContentStorageRequest, + @PathVariable id: Long, + ): StorageTestResult { enabledFeaturesProvider.checkFeatureEnabled( organizationId = projectHolder.project.organizationOwnerId, - Feature.PROJECT_LEVEL_CONTENT_STORAGES + Feature.PROJECT_LEVEL_CONTENT_STORAGES, ) return contentStorageService.testStorage(dto, id) } diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/EeLicenseController.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/EeLicenseController.kt index 678778d0b2..b6a3dce524 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/EeLicenseController.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/EeLicenseController.kt @@ -20,12 +20,14 @@ import org.springframework.web.bind.annotation.RestController @Tag(name = "EE Licence (only for self-hosted instances)") class EeLicenseController( private val eeSubscriptionService: EeSubscriptionService, - private val eeSubscriptionModelAssembler: EeSubscriptionModelAssembler + private val eeSubscriptionModelAssembler: EeSubscriptionModelAssembler, ) { @PutMapping("set-license-key") @Operation(summary = "Sets the EE licence key for this instance") @RequiresSuperAuthentication - fun setLicenseKey(@RequestBody body: SetLicenseKeyDto): EeSubscriptionModel { + fun setLicenseKey( + @RequestBody body: SetLicenseKeyDto, + ): EeSubscriptionModel { val eeSubscription = eeSubscriptionService.setLicenceKey(body.licenseKey) return eeSubscriptionModelAssembler.toModel(eeSubscription) } @@ -33,7 +35,9 @@ class EeLicenseController( @PostMapping("prepare-set-license-key") @Operation(summary = "Returns info about the upcoming EE subscription") @RequiresSuperAuthentication - fun prepareSetLicenseKey(@RequestBody body: SetLicenseKeyDto): PrepareSetEeLicenceKeyModel { + fun prepareSetLicenseKey( + @RequestBody body: SetLicenseKeyDto, + ): PrepareSetEeLicenceKeyModel { return eeSubscriptionService.prepareSetLicenceKey(body.licenseKey) } diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/WebhookConfigController.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/WebhookConfigController.kt index 7a17053863..63efa8706a 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/WebhookConfigController.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/controllers/WebhookConfigController.kt @@ -35,7 +35,7 @@ import org.springframework.web.bind.annotation.RestController @RequestMapping( value = [ "/v2/projects/{projectId}/webhook-configs", - ] + ], ) @Tag(name = "Webhooks configuration (EE)") class WebhookConfigController( @@ -44,16 +44,19 @@ class WebhookConfigController( @Suppress("SpringJavaInjectionPointsAutowiringInspection") private val pageModelAssembler: PagedResourcesAssembler, private val projectHolder: ProjectHolder, - private val enabledFeaturesProvider: EnabledFeaturesProvider + private val enabledFeaturesProvider: EnabledFeaturesProvider, ) { @PostMapping("") @Operation(description = "Creates new webhook configuration") @RequiresProjectPermissions([Scope.WEBHOOKS_MANAGE]) @AllowApiAccess - fun create(@Valid @RequestBody dto: WebhookConfigRequest): WebhookConfigModel { + fun create( + @Valid @RequestBody + dto: WebhookConfigRequest, + ): WebhookConfigModel { enabledFeaturesProvider.checkFeatureEnabled( organizationId = projectHolder.project.organizationOwnerId, - Feature.WEBHOOKS + Feature.WEBHOOKS, ) val config = webhookConfigService.create(projectHolder.projectEntity, dto) return webhookConfigModelAssembler.toModel(config) @@ -63,10 +66,15 @@ class WebhookConfigController( @Operation(description = "Updates webhook configuration") @RequiresProjectPermissions([Scope.WEBHOOKS_MANAGE]) @AllowApiAccess - fun update(@PathVariable id: Long, @Valid @RequestBody dto: WebhookConfigRequest): WebhookConfigModel { + fun update( + @PathVariable + id: Long, + @Valid @RequestBody + dto: WebhookConfigRequest, + ): WebhookConfigModel { enabledFeaturesProvider.checkFeatureEnabled( organizationId = projectHolder.project.organizationOwnerId, - Feature.WEBHOOKS + Feature.WEBHOOKS, ) val webhookConfig = webhookConfigService.update(projectId = projectHolder.project.id, id, dto) return webhookConfigModelAssembler.toModel(webhookConfig) @@ -76,7 +84,9 @@ class WebhookConfigController( @GetMapping("") @Operation(description = "List webhook configurations") @AllowApiAccess - fun list(@ParameterObject pageable: Pageable): PagedModel { + fun list( + @ParameterObject pageable: Pageable, + ): PagedModel { val page = webhookConfigService.findAllInProject(projectHolder.project.id, pageable) return pageModelAssembler.toModel(page, webhookConfigModelAssembler) } @@ -85,7 +95,9 @@ class WebhookConfigController( @DeleteMapping("/{id}") @Operation(description = "Deletes webhook configuration") @AllowApiAccess - fun delete(@PathVariable id: Long) { + fun delete( + @PathVariable id: Long, + ) { webhookConfigService.delete(projectHolder.project.id, id) } @@ -93,7 +105,9 @@ class WebhookConfigController( @GetMapping("/{id}") @Operation(description = "Get webhook configuration") @AllowApiAccess - fun get(@PathVariable id: Long): WebhookConfigModel { + fun get( + @PathVariable id: Long, + ): WebhookConfigModel { return webhookConfigModelAssembler.toModel(webhookConfigService.get(projectHolder.project.id, id)) } @@ -101,10 +115,12 @@ class WebhookConfigController( @PostMapping("/{id}/test") @Operation(description = "Tests webhook configuration") @AllowApiAccess - fun test(@PathVariable id: Long): WebhookTestResponse { + fun test( + @PathVariable id: Long, + ): WebhookTestResponse { enabledFeaturesProvider.checkFeatureEnabled( organizationId = projectHolder.project.organizationOwnerId, - Feature.WEBHOOKS + Feature.WEBHOOKS, ) val success = webhookConfigService.test(projectHolder.project.id, id) return WebhookTestResponse(success) diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/PrepareSetLicenseKeyModel.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/PrepareSetLicenseKeyModel.kt index ccaa8f5b6f..109f0a480f 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/PrepareSetLicenseKeyModel.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/PrepareSetLicenseKeyModel.kt @@ -10,5 +10,5 @@ import java.math.BigDecimal open class PrepareSetLicenseKeyModel( val perSetPrice: BigDecimal, val currentSeats: Long, - val total: Long + val total: Long, ) : RepresentationModel(), Serializable diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/contentStorage/AzureContentStorageConfigModel.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/contentStorage/AzureContentStorageConfigModel.kt index d0e569ad3d..7d9d9c4294 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/contentStorage/AzureContentStorageConfigModel.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/contentStorage/AzureContentStorageConfigModel.kt @@ -1,5 +1,5 @@ package io.tolgee.ee.api.v2.hateoas.contentStorage class AzureContentStorageConfigModel( - var containerName: String? = "" + var containerName: String? = "", ) diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/contentStorage/ContentStorageModel.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/contentStorage/ContentStorageModel.kt index 64a5f5f9a3..8a8e289fa9 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/contentStorage/ContentStorageModel.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/contentStorage/ContentStorageModel.kt @@ -11,5 +11,5 @@ class ContentStorageModel( val name: String, val publicUrlPrefix: String?, val azureContentStorageConfig: AzureContentStorageConfigModel?, - val s3ContentStorageConfig: S3ContentStorageConfigModel? + val s3ContentStorageConfig: S3ContentStorageConfigModel?, ) : RepresentationModel(), Serializable diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/contentStorage/ContentStorageModelAssembler.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/contentStorage/ContentStorageModelAssembler.kt index f0824fb6e9..53bcfe78a2 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/contentStorage/ContentStorageModelAssembler.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/contentStorage/ContentStorageModelAssembler.kt @@ -7,23 +7,26 @@ import org.springframework.stereotype.Component @Component class ContentStorageModelAssembler() : RepresentationModelAssemblerSupport( - ContentStorageController::class.java, ContentStorageModel::class.java + ContentStorageController::class.java, + ContentStorageModel::class.java, ) { override fun toModel(entity: ContentStorage): ContentStorageModel { return ContentStorageModel( id = entity.id, name = entity.name, publicUrlPrefix = entity.publicUrlPrefix, - s3ContentStorageConfig = entity.s3ContentStorageConfig?.let { - S3ContentStorageConfigModel( - bucketName = it.bucketName, - endpoint = it.endpoint, - signingRegion = it.signingRegion - ) - }, - azureContentStorageConfig = entity.azureContentStorageConfig?.let { - AzureContentStorageConfigModel(containerName = it.containerName) - } + s3ContentStorageConfig = + entity.s3ContentStorageConfig?.let { + S3ContentStorageConfigModel( + bucketName = it.bucketName, + endpoint = it.endpoint, + signingRegion = it.signingRegion, + ) + }, + azureContentStorageConfig = + entity.azureContentStorageConfig?.let { + AzureContentStorageConfigModel(containerName = it.containerName) + }, ) } } diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/contentStorage/S3ContentStorageConfigModel.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/contentStorage/S3ContentStorageConfigModel.kt index bba9896220..fd868f0320 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/contentStorage/S3ContentStorageConfigModel.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/contentStorage/S3ContentStorageConfigModel.kt @@ -3,5 +3,5 @@ package io.tolgee.ee.api.v2.hateoas.contentStorage class S3ContentStorageConfigModel( var bucketName: String = "", var endpoint: String = "", - var signingRegion: String = "" + var signingRegion: String = "", ) diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/eeSubscription/EeSubscriptionModel.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/eeSubscription/EeSubscriptionModel.kt index 91ac80969a..da69349490 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/eeSubscription/EeSubscriptionModel.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/eeSubscription/EeSubscriptionModel.kt @@ -17,5 +17,5 @@ open class EeSubscriptionModel( val cancelAtPeriodEnd: Boolean, val currentUserCount: Long, val status: SubscriptionStatus, - var lastValidCheck: Date? + var lastValidCheck: Date?, ) : RepresentationModel(), Serializable diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/eeSubscription/EeSubscriptionModelAssembler.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/eeSubscription/EeSubscriptionModelAssembler.kt index b29caba654..585d9bb657 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/eeSubscription/EeSubscriptionModelAssembler.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/eeSubscription/EeSubscriptionModelAssembler.kt @@ -7,9 +7,8 @@ import org.springframework.stereotype.Component @Component class EeSubscriptionModelAssembler( - private val userAccountService: UserAccountService + private val userAccountService: UserAccountService, ) : RepresentationModelAssembler { - override fun toModel(eeSubscription: EeSubscription): EeSubscriptionModel { val currentUserCount = userAccountService.countAll() @@ -21,7 +20,7 @@ class EeSubscriptionModelAssembler( cancelAtPeriodEnd = eeSubscription.cancelAtPeriodEnd, currentUserCount = currentUserCount, status = eeSubscription.status, - lastValidCheck = eeSubscription.lastValidCheck + lastValidCheck = eeSubscription.lastValidCheck, ) } } diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/uasge/UsageModel.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/uasge/UsageModel.kt index 201da7b418..6a8203d132 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/uasge/UsageModel.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/uasge/UsageModel.kt @@ -11,8 +11,9 @@ import java.math.BigDecimal open class UsageModel( val subscriptionPrice: BigDecimal? = 0.toBigDecimal(), @Schema( - description = "Relevant for invoices only. When there are " + - "applied stripe credits, we need to reduce the total price by this amount." + description = + "Relevant for invoices only. When there are " + + "applied stripe credits, we need to reduce the total price by this amount.", ) val appliedStripeCredits: BigDecimal? = null, val seats: AverageProportionalUsageItemModel = AverageProportionalUsageItemModel(), diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/webhooks/WebhookConfigModel.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/webhooks/WebhookConfigModel.kt index cab1d6378f..97cc4507ff 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/webhooks/WebhookConfigModel.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/webhooks/WebhookConfigModel.kt @@ -12,13 +12,13 @@ class WebhookConfigModel( val url: String, val webhookSecret: String, @Schema( - description = "Date of the first failed webhook request. " + - "If the last webhook request is successful, this value is set to null." + description = + "Date of the first failed webhook request. " + + "If the last webhook request is successful, this value is set to null.", ) val firstFailed: Long?, - @Schema( - description = """Date of the last webhook request.""" + description = """Date of the last webhook request.""", ) - var lastExecuted: Long? + var lastExecuted: Long?, ) : RepresentationModel(), Serializable diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/webhooks/WebhookConfigModelAssembler.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/webhooks/WebhookConfigModelAssembler.kt index 59cb566f94..9f7e9bfeb0 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/webhooks/WebhookConfigModelAssembler.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/api/v2/hateoas/webhooks/WebhookConfigModelAssembler.kt @@ -7,7 +7,8 @@ import org.springframework.stereotype.Component @Component class WebhookConfigModelAssembler() : RepresentationModelAssemblerSupport( - WebhookConfigController::class.java, WebhookConfigModel::class.java + WebhookConfigController::class.java, + WebhookConfigModel::class.java, ) { override fun toModel(entity: WebhookConfig): WebhookConfigModel { return WebhookConfigModel( @@ -15,7 +16,7 @@ class WebhookConfigModelAssembler() : RepresentationModelAssemblerSupport? = null diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/component/contentDelivery/AzureContentStorageConfigProcessor.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/component/contentDelivery/AzureContentStorageConfigProcessor.kt index 64faa2c9ff..f5c7a3fc2f 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/component/contentDelivery/AzureContentStorageConfigProcessor.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/component/contentDelivery/AzureContentStorageConfigProcessor.kt @@ -16,7 +16,10 @@ class AzureContentStorageConfigProcessor : ContentStorageConfigProcessor { fun getItemFromDto(dto: ContentStorageRequest): StorageConfig? - fun configDtoToEntity(dto: ContentStorageRequest, storageEntity: ContentStorage, em: EntityManager): EntityType - fun clearParentEntity(storageEntity: ContentStorage, em: EntityManager) - fun fillDtoSecrets(storageEntity: ContentStorage, dto: ContentStorageRequest) + + fun configDtoToEntity( + dto: ContentStorageRequest, + storageEntity: ContentStorage, + em: EntityManager, + ): EntityType + + fun clearParentEntity( + storageEntity: ContentStorage, + em: EntityManager, + ) + + fun fillDtoSecrets( + storageEntity: ContentStorage, + dto: ContentStorageRequest, + ) val type: ContentStorageType } diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/component/contentDelivery/EeContentStorageProvider.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/component/contentDelivery/EeContentStorageProvider.kt index 005e9c1bd2..ffd06cbc8d 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/component/contentDelivery/EeContentStorageProvider.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/component/contentDelivery/EeContentStorageProvider.kt @@ -12,9 +12,12 @@ import org.springframework.stereotype.Component class EeContentStorageProvider( private val contentStorageService: ContentStorageService, private val projectService: ProjectService, - private val enabledFeaturesProvider: EnabledFeaturesProvider + private val enabledFeaturesProvider: EnabledFeaturesProvider, ) : ContentStorageProvider { - override fun getStorage(projectId: Long, contentStorageId: Long): ContentStorage { + override fun getStorage( + projectId: Long, + contentStorageId: Long, + ): ContentStorage { projectService.findDto(projectId)?.let { enabledFeaturesProvider.checkFeatureEnabled(it.organizationOwnerId, Feature.PROJECT_LEVEL_CONTENT_STORAGES) } diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/component/contentDelivery/S3ContentStorageConfigProcessor.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/component/contentDelivery/S3ContentStorageConfigProcessor.kt index e5ba6d9f7e..f40676f7f3 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/component/contentDelivery/S3ContentStorageConfigProcessor.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/component/contentDelivery/S3ContentStorageConfigProcessor.kt @@ -16,7 +16,10 @@ class S3ContentStorageConfigProcessor : ContentStorageConfigProcessor? = null + val params: List? = null, ) diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/data/SubscriptionStatus.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/data/SubscriptionStatus.kt index 05951b3f01..5d6cfd026a 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/data/SubscriptionStatus.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/data/SubscriptionStatus.kt @@ -6,6 +6,7 @@ enum class SubscriptionStatus { PAST_DUE, UNPAID, ERROR, + // might be stored on the EE side, but not license server (billing) side - KEY_USED_BY_ANOTHER_INSTANCE + KEY_USED_BY_ANOTHER_INSTANCE, } diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/data/SumUsageItem.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/data/SumUsageItem.kt index 1039b44d26..455cf985dd 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/data/SumUsageItem.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/data/SumUsageItem.kt @@ -6,5 +6,5 @@ data class SumUsageItem( var total: BigDecimal, var usedQuantityOverPlan: Long, var unusedQuantity: Long, - var usedQuantity: Long + var usedQuantity: Long, ) diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/data/UsageData.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/data/UsageData.kt index 2f39c1d0bf..d3a95e459b 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/data/UsageData.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/data/UsageData.kt @@ -9,10 +9,10 @@ data class UsageData( val subscriptionPrice: BigDecimal?, val appliedStripeCredits: BigDecimal?, ) { - val total: BigDecimal - get() = seatsUsage.sumOf { it.total } + translationsUsage.sumOf { it.total } + ( - subscriptionPrice - ?: 0.toBigDecimal() + get() = + seatsUsage.sumOf { it.total } + translationsUsage.sumOf { it.total } + ( + subscriptionPrice + ?: 0.toBigDecimal() ) + (creditsUsage?.total ?: 0.toBigDecimal()) } diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/ContentStorageService.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/ContentStorageService.kt index 3cda80413f..60bc3cd63b 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/ContentStorageService.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/ContentStorageService.kt @@ -25,10 +25,13 @@ class ContentStorageService( private val contentStorageRepository: ContentStorageRepository, private val entityManager: EntityManager, private val contentDeliveryFileStorageProvider: ContentDeliveryFileStorageProvider, - private val contentStorageConfigProcessors: List> + private val contentStorageConfigProcessors: List>, ) { @Transactional - fun create(projectId: Long, dto: ContentStorageRequest): ContentStorage { + fun create( + projectId: Long, + dto: ContentStorageRequest, + ): ContentStorage { validateStorage(dto) val project = entityManager.getReference(Project::class.java, projectId) val storage = ContentStorage(project, dto.name) @@ -43,7 +46,11 @@ class ContentStorageService( fun find(id: Long) = contentStorageRepository.findById(id).orElse(null) @Transactional - fun update(projectId: Long, id: Long, dto: ContentStorageRequest): ContentStorage { + fun update( + projectId: Long, + id: Long, + dto: ContentStorageRequest, + ): ContentStorage { val contentStorage = get(id) getProcessor(getStorageType(dto)).fillDtoSecrets(contentStorage, dto) validateStorage(dto) @@ -61,7 +68,10 @@ class ContentStorageService( } @Transactional - fun delete(projectId: Long, id: Long) { + fun delete( + projectId: Long, + id: Long, + ) { val storage = get(projectId, id) contentStorageConfigProcessors.forEach { it.clearParentEntity(storage, entityManager) } if (contentStorageRepository.isStorageInUse(storage)) { @@ -70,15 +80,24 @@ class ContentStorageService( contentStorageRepository.delete(storage) } - fun getAllInProject(projectId: Long, pageable: Pageable): Page { + fun getAllInProject( + projectId: Long, + pageable: Pageable, + ): Page { return contentStorageRepository.findAllByProjectId(projectId, pageable) } - fun get(projectId: Long, contentDeliveryConfigId: Long): ContentStorage { + fun get( + projectId: Long, + contentDeliveryConfigId: Long, + ): ContentStorage { return contentStorageRepository.getByProjectIdAndId(projectId, contentDeliveryConfigId) } - fun testStorage(dto: ContentStorageRequest, id: Long? = null): StorageTestResult { + fun testStorage( + dto: ContentStorageRequest, + id: Long? = null, + ): StorageTestResult { val config: StorageConfig = getNonNullConfig(dto) if (id != null) { val existing = get(id) @@ -99,10 +118,12 @@ class ContentStorageService( private fun validateStorage(dto: ContentStorageRequest) { val result = testStorage(dto) @Suppress("UNCHECKED_CAST") - if (!result.success) throw BadRequestException( - Message.CONTENT_STORAGE_CONFIG_INVALID, - listOf(result.message, result.params) as List? - ) + if (!result.success) { + throw BadRequestException( + Message.CONTENT_STORAGE_CONFIG_INVALID, + listOf(result.message, result.params) as List?, + ) + } } private fun getNonNullConfig(dto: ContentStorageRequest): StorageConfig { @@ -115,13 +136,17 @@ class ContentStorageService( fun getStorageType(dto: ContentStorageRequest): ContentStorageType = getNonNullConfig(dto).contentStorageType private fun validateDto(dto: ContentStorageRequest) { - val isSingleConfig = contentStorageConfigProcessors.count { - it.getItemFromDto(dto) != null - } == 1 + val isSingleConfig = + contentStorageConfigProcessors.count { + it.getItemFromDto(dto) != null + } == 1 if (!isSingleConfig) throw BadRequestException(Message.CONTENT_STORAGE_CONFIG_REQUIRED) } - private fun dtoToEntity(dto: ContentStorageRequest, entity: ContentStorage): Any { + private fun dtoToEntity( + dto: ContentStorageRequest, + entity: ContentStorage, + ): Any { entity.name = dto.name entity.publicUrlPrefix = dto.publicUrlPrefix return getProcessorForDto(dto).configDtoToEntity(dto, entity, entityManager)!! @@ -132,6 +157,7 @@ class ContentStorageService( } private val processorCache = mutableMapOf>() + fun getProcessor(type: ContentStorageType): ContentStorageConfigProcessor<*> { return processorCache.computeIfAbsent(type) { contentStorageConfigProcessors.find { it.type == type } diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/EeInvitationService.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/EeInvitationService.kt index a08eb0b0e2..40a4870ba0 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/EeInvitationService.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/EeInvitationService.kt @@ -12,7 +12,7 @@ import org.springframework.transaction.annotation.Transactional class EeInvitationService( private val eePermissionService: EePermissionService, private val invitationService: InvitationService, - private val enabledFeaturesProvider: EnabledFeaturesProvider + private val enabledFeaturesProvider: EnabledFeaturesProvider, ) { @Transactional fun create(params: CreateProjectInvitationParams): Invitation { @@ -20,7 +20,7 @@ class EeInvitationService( return invitationService.create(params) { invitation -> eePermissionService.createForInvitation( invitation = invitation, - params + params, ) } } diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/EePermissionService.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/EePermissionService.kt index 52cd587c03..6d26facb79 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/EePermissionService.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/EePermissionService.kt @@ -22,11 +22,11 @@ class EePermissionService( projectId: Long, userId: Long, scopes: Set, - languages: LanguagePermissions + languages: LanguagePermissions, ): Permission { validateLanguagePermissions( languagePermissions = languages, - scopes = scopes + scopes = scopes, ) val permission = permissionService.getOrCreateDirectPermission(projectId, userId) @@ -39,7 +39,10 @@ class EePermissionService( return permissionService.save(permission) } - fun setOrganizationBasePermission(organizationId: Long, scopes: Set) { + fun setOrganizationBasePermission( + organizationId: Long, + scopes: Set, + ) { val permission = organizationService.get(organizationId).basePermission permission.scopes = scopes.toTypedArray() permission.type = null @@ -48,18 +51,19 @@ class EePermissionService( fun createForInvitation( invitation: Invitation, - params: CreateProjectInvitationParams + params: CreateProjectInvitationParams, ): Permission { val scopes = Scope.parse(params.scopes) validateLanguagePermissions(params.languagePermissions, scopes) - val permission = Permission( - type = null, - invitation = invitation, - project = params.project, - scopes = scopes.toTypedArray(), - ) + val permission = + Permission( + type = null, + invitation = invitation, + project = params.project, + scopes = scopes.toTypedArray(), + ) permissionService.setPermissionLanguages(permission, params.languagePermissions, params.project.id) @@ -68,7 +72,7 @@ class EePermissionService( private fun validateLanguagePermissions( languagePermissions: LanguagePermissions, - scopes: Set? + scopes: Set?, ) { if (scopes.isNullOrEmpty()) { throw BadRequestException(Message.SCOPES_HAS_TO_BE_SET) diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/EeSubscriptionService.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/EeSubscriptionService.kt index 718bd9c880..9dc411aa4f 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/EeSubscriptionService.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/EeSubscriptionService.kt @@ -34,15 +34,15 @@ class EeSubscriptionService( private val userAccountService: UserAccountService, private val currentDateProvider: CurrentDateProvider, private val httpClient: HttpClient, - private val instanceIdService: InstanceIdService + private val instanceIdService: InstanceIdService, ) { companion object { - const val setPath: String = "/v2/public/licensing/set-key" - const val prepareSetKeyPath: String = "/v2/public/licensing/prepare-set-key" - const val subscriptionInfoPath: String = "/v2/public/licensing/subscription" - const val reportUsagePath: String = "/v2/public/licensing/report-usage" - const val releaseKeyPath: String = "/v2/public/licensing/release-key" - const val reportErrorPath: String = "/v2/public/licensing/report-error" + const val SET_PATH: String = "/v2/public/licensing/set-key" + const val PREPARE_SET_KEY_PATH: String = "/v2/public/licensing/prepare-set-key" + const val SUBSCRIPTION_INFO_PATH: String = "/v2/public/licensing/subscription" + const val REPORT_USAGE_PATH: String = "/v2/public/licensing/report-usage" + const val RELEASE_KEY_PATH: String = "/v2/public/licensing/release-key" + const val REPORT_ERROR_PATH: String = "/v2/public/licensing/report-error" } fun findSubscriptionEntity(): EeSubscription? { @@ -55,21 +55,23 @@ class EeSubscriptionService( throw BadRequestException(Message.THIS_INSTANCE_IS_ALREADY_LICENSED) } - val entity = EeSubscription().apply { - this.licenseKey = licenseKey - this.lastValidCheck = currentDateProvider.date - } + val entity = + EeSubscription().apply { + this.licenseKey = licenseKey + this.lastValidCheck = currentDateProvider.date + } - val responseBody = catchingSeatsSpendingLimit { - try { - postRequest( - setPath, - SetLicenseKeyLicensingDto(licenseKey, seats, instanceIdService.getInstanceId()) - ) - } catch (e: HttpClientErrorException.NotFound) { - throw BadRequestException(Message.LICENSE_KEY_NOT_FOUND) + val responseBody = + catchingSeatsSpendingLimit { + try { + postRequest( + SET_PATH, + SetLicenseKeyLicensingDto(licenseKey, seats, instanceIdService.getInstanceId()), + ) + } catch (e: HttpClientErrorException.NotFound) { + throw BadRequestException(Message.LICENSE_KEY_NOT_FOUND) + } } - } if (responseBody != null) { entity.name = responseBody.plan.name @@ -83,16 +85,17 @@ class EeSubscriptionService( fun prepareSetLicenceKey(licenseKey: String): PrepareSetEeLicenceKeyModel { val seats = userAccountService.countAllEnabled() - val responseBody = catchingSeatsSpendingLimit { - try { - postRequest( - prepareSetKeyPath, - PrepareSetLicenseKeyDto(licenseKey, seats), - ) - } catch (e: HttpClientErrorException.NotFound) { - throw BadRequestException(Message.LICENSE_KEY_NOT_FOUND) + val responseBody = + catchingSeatsSpendingLimit { + try { + postRequest( + PREPARE_SET_KEY_PATH, + PrepareSetLicenseKeyDto(licenseKey, seats), + ) + } catch (e: HttpClientErrorException.NotFound) { + throw BadRequestException(Message.LICENSE_KEY_NOT_FOUND) + } } - } if (responseBody != null) { return responseBody @@ -113,7 +116,10 @@ class EeSubscriptionService( } } - private inline fun postRequest(url: String, body: Any): T? { + private inline fun postRequest( + url: String, + body: Any, + ): T? { return httpClient.requestForJson("${eeProperties.licenseServer}$url", body, HttpMethod.POST, T::class.java) } @@ -126,18 +132,19 @@ class EeSubscriptionService( fun refreshSubscription() { val subscription = findSubscriptionEntity() if (subscription != null) { - val responseBody = try { - getRemoteSubscriptionInfo(subscription) - } catch (e: HttpClientErrorException.BadRequest) { - val error = e.parseBody() - if (error.code == Message.LICENSE_KEY_USED_BY_ANOTHER_INSTANCE.code) { - setSubscriptionKeyUsedByOtherInstance(subscription) + val responseBody = + try { + getRemoteSubscriptionInfo(subscription) + } catch (e: HttpClientErrorException.BadRequest) { + val error = e.parseBody() + if (error.code == Message.LICENSE_KEY_USED_BY_ANOTHER_INSTANCE.code) { + setSubscriptionKeyUsedByOtherInstance(subscription) + } + null + } catch (e: Exception) { + reportError(e.stackTraceToString()) + null } - null - } catch (e: Exception) { - reportError(e.stackTraceToString()) - null - } updateLocalSubscription(responseBody, subscription) handleConstantlyFailingRemoteCheck(subscription) } @@ -154,7 +161,7 @@ class EeSubscriptionService( private fun updateLocalSubscription( responseBody: SelfHostedEeSubscriptionModel?, - subscription: EeSubscription + subscription: EeSubscription, ) { if (responseBody != null) { subscription.currentPeriodEnd = responseBody.currentPeriodEnd?.let { Date(it) } @@ -176,22 +183,23 @@ class EeSubscriptionService( } private fun getRemoteSubscriptionInfo(subscription: EeSubscription): SelfHostedEeSubscriptionModel? { - val responseBody = try { - postRequest( - subscriptionInfoPath, - GetMySubscriptionDto(subscription.licenseKey, instanceIdService.getInstanceId()) - ) - } catch (e: HttpClientErrorException.NotFound) { - subscription.status = SubscriptionStatus.CANCELED - null - } + val responseBody = + try { + postRequest( + SUBSCRIPTION_INFO_PATH, + GetMySubscriptionDto(subscription.licenseKey, instanceIdService.getInstanceId()), + ) + } catch (e: HttpClientErrorException.NotFound) { + subscription.status = SubscriptionStatus.CANCELED + null + } return responseBody } fun reportError(error: String) { try { findSubscriptionEntity()?.let { - postRequest(reportErrorPath, ReportErrorDto(error, it.licenseKey)) + postRequest(REPORT_ERROR_PATH, ReportErrorDto(error, it.licenseKey)) } } catch (e: Exception) { e.printStackTrace() @@ -217,17 +225,20 @@ class EeSubscriptionService( } } - private fun reportUsageRemote(subscription: EeSubscription, seats: Long) { + private fun reportUsageRemote( + subscription: EeSubscription, + seats: Long, + ) { postRequest( - reportUsagePath, - ReportUsageDto(subscription.licenseKey, seats) + REPORT_USAGE_PATH, + ReportUsageDto(subscription.licenseKey, seats), ) } private fun releaseKeyRemote(subscription: EeSubscription) { postRequest( - releaseKeyPath, - ReleaseKeyDto(subscription.licenseKey) + RELEASE_KEY_PATH, + ReleaseKeyDto(subscription.licenseKey), ) } diff --git a/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/WebhookConfigService.kt b/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/WebhookConfigService.kt index 5d9b898335..0524dfe464 100644 --- a/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/WebhookConfigService.kt +++ b/ee/backend/app/src/main/kotlin/io/tolgee/ee/service/WebhookConfigService.kt @@ -21,7 +21,10 @@ class WebhookConfigService( private val webhookExecutor: WebhookExecutor, private val automationService: AutomationService, ) { - fun get(projectId: Long, id: Long): WebhookConfig { + fun get( + projectId: Long, + id: Long, + ): WebhookConfig { return webhookConfigRepository.findByIdAndProjectId(id, projectId) ?: throw NotFoundException() } @@ -30,23 +33,32 @@ class WebhookConfigService( return webhookConfigRepository.findById(id).orElseThrow { NotFoundException() } } - fun findAllInProject(projectId: Long, pageable: Pageable): Page { + fun findAllInProject( + projectId: Long, + pageable: Pageable, + ): Page { return webhookConfigRepository.findByProjectId(projectId, pageable) } - fun create(project: Project, dto: WebhookConfigRequest): WebhookConfig { + fun create( + project: Project, + dto: WebhookConfigRequest, + ): WebhookConfig { val webhookConfig = WebhookConfig(project) webhookConfig.url = dto.url webhookConfig.webhookSecret = generateRandomWebhookSecret() return webhookConfigRepository.save(webhookConfig) } - fun test(projectId: Long, webhookConfigId: Long): Boolean { + fun test( + projectId: Long, + webhookConfigId: Long, + ): Boolean { val webhookConfig = get(projectId, webhookConfigId) try { webhookExecutor.signAndExecute( config = webhookConfig, - data = WebhookRequest(webhookConfigId, WebhookEventType.TEST, null) + data = WebhookRequest(webhookConfigId, WebhookEventType.TEST, null), ) } catch (e: WebhookException) { return false @@ -55,7 +67,11 @@ class WebhookConfigService( } @Transactional - fun update(projectId: Long, id: Long, dto: WebhookConfigRequest): WebhookConfig { + fun update( + projectId: Long, + id: Long, + dto: WebhookConfigRequest, + ): WebhookConfig { val webhookConfig = get(projectId, id) webhookConfig.url = dto.url automationService.updateForWebhookConfig(webhookConfig) @@ -63,7 +79,10 @@ class WebhookConfigService( } @Transactional - fun delete(projectId: Long, id: Long) { + fun delete( + projectId: Long, + id: Long, + ) { val webhookConfig = get(projectId, id) automationService.deleteForWebhookConfig(webhookConfig) webhookConfigRepository.delete(webhookConfig) diff --git a/ee/backend/tests/src/test/kotlin/io/tolgee/ee/EeLicensingMockRequestUtil.kt b/ee/backend/tests/src/test/kotlin/io/tolgee/ee/EeLicensingMockRequestUtil.kt index 542430ee96..be597cc390 100644 --- a/ee/backend/tests/src/test/kotlin/io/tolgee/ee/EeLicensingMockRequestUtil.kt +++ b/ee/backend/tests/src/test/kotlin/io/tolgee/ee/EeLicensingMockRequestUtil.kt @@ -23,47 +23,53 @@ class EeLicensingMockRequestUtil { mock(mocker) } - final val mockedPlan = SelfHostedEePlanModel( - id = 19919, - name = "Tolgee", - public = true, - enabledFeatures = arrayOf(Feature.PREMIUM_SUPPORT), - prices = PlanPricesModel( - perSeat = 20.toBigDecimal(), - subscriptionMonthly = 200.toBigDecimal(), - ), - ) - - final val mockedSubscriptionResponse = SelfHostedEeSubscriptionModel( - id = 19919, - currentPeriodEnd = 1624313600000, - createdAt = 1624313600000, - plan = mockedPlan, - status = SubscriptionStatus.ACTIVE, - licenseKey = "mocked_license_key", - estimatedCosts = 200.toBigDecimal(), - currentPeriodStart = 1622313600000, - ) + final val mockedPlan = + SelfHostedEePlanModel( + id = 19919, + name = "Tolgee", + public = true, + enabledFeatures = arrayOf(Feature.PREMIUM_SUPPORT), + prices = + PlanPricesModel( + perSeat = 20.toBigDecimal(), + subscriptionMonthly = 200.toBigDecimal(), + ), + ) - final val mockedPrepareResponse = PrepareSetEeLicenceKeyModel().apply { - plan = mockedPlan - usage = UsageModel( - subscriptionPrice = 200.toBigDecimal(), - seats = - AverageProportionalUsageItemModel( - total = 250.toBigDecimal(), - usedQuantity = 2.toBigDecimal(), - unusedQuantity = 10.toBigDecimal(), - usedQuantityOverPlan = 0.toBigDecimal() - ), - total = 250.toBigDecimal(), - translations = AverageProportionalUsageItemModel( - total = 0.toBigDecimal(), - unusedQuantity = 0.toBigDecimal(), - usedQuantity = 0.toBigDecimal(), - usedQuantityOverPlan = 0.toBigDecimal() - ), - credits = null + final val mockedSubscriptionResponse = + SelfHostedEeSubscriptionModel( + id = 19919, + currentPeriodEnd = 1624313600000, + createdAt = 1624313600000, + plan = mockedPlan, + status = SubscriptionStatus.ACTIVE, + licenseKey = "mocked_license_key", + estimatedCosts = 200.toBigDecimal(), + currentPeriodStart = 1622313600000, ) - } + + final val mockedPrepareResponse = + PrepareSetEeLicenceKeyModel().apply { + plan = mockedPlan + usage = + UsageModel( + subscriptionPrice = 200.toBigDecimal(), + seats = + AverageProportionalUsageItemModel( + total = 250.toBigDecimal(), + usedQuantity = 2.toBigDecimal(), + unusedQuantity = 10.toBigDecimal(), + usedQuantityOverPlan = 0.toBigDecimal(), + ), + total = 250.toBigDecimal(), + translations = + AverageProportionalUsageItemModel( + total = 0.toBigDecimal(), + unusedQuantity = 0.toBigDecimal(), + usedQuantity = 0.toBigDecimal(), + usedQuantityOverPlan = 0.toBigDecimal(), + ), + credits = null, + ) + } } diff --git a/ee/backend/tests/src/test/kotlin/io/tolgee/ee/UsageReportingTest.kt b/ee/backend/tests/src/test/kotlin/io/tolgee/ee/UsageReportingTest.kt index a1fe57443b..c1d5658b7b 100644 --- a/ee/backend/tests/src/test/kotlin/io/tolgee/ee/UsageReportingTest.kt +++ b/ee/backend/tests/src/test/kotlin/io/tolgee/ee/UsageReportingTest.kt @@ -21,7 +21,6 @@ import java.util.* @SpringBootTest() class UsageReportingTest : AbstractSpringTest() { - @Autowired private lateinit var eeSubscriptionRepository: EeSubscriptionRepository @@ -49,7 +48,7 @@ class UsageReportingTest : AbstractSpringTest() { cancelAtPeriodEnd = false enabledFeatures = Feature.values() lastValidCheck = Date() - } + }, ) eeLicenseMockRequestUtil.mock { @@ -62,21 +61,23 @@ class UsageReportingTest : AbstractSpringTest() { } verify { - val user1 = userAccountService.createUser( - UserAccount( - name = "Test", - username = "aa@a.a", - ), - rawPassword = "12345678" - ) + val user1 = + userAccountService.createUser( + UserAccount( + name = "Test", + username = "aa@a.a", + ), + rawPassword = "12345678", + ) captor.assertSeats(1) - val user2 = userAccountService.createUser( - UserAccount( - name = "Test", - username = "ab@a.a", - ), - rawPassword = "12345678" - ) + val user2 = + userAccountService.createUser( + UserAccount( + name = "Test", + username = "ab@a.a", + ), + rawPassword = "12345678", + ) captor.assertSeats(2) userAccountService.delete(user1.id) captor.assertSeats(1) diff --git a/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/AdvancedPermissionControllerTest.kt b/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/AdvancedPermissionControllerTest.kt index 165934891a..44bf2dff13 100644 --- a/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/AdvancedPermissionControllerTest.kt +++ b/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/AdvancedPermissionControllerTest.kt @@ -19,7 +19,6 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.test.web.servlet.ResultActions class AdvancedPermissionControllerTest : AuthorizedControllerTest() { - private val permissionTestUtil: PermissionTestUtil by lazy { PermissionTestUtil(this, applicationContext) } @Autowired @@ -53,7 +52,7 @@ class AdvancedPermissionControllerTest : AuthorizedControllerTest() { fun `fails to set user's permission when feature disabled`() { enabledFeaturesProvider.forceEnabled = setOf() permissionTestUtil.performSetPermissions( - "" + "", ) { getLang -> "scopes=screenshots.upload&viewLanguages=${getLang("en")}" } .andIsBadRequest .andHasErrorMessage(Message.FEATURE_NOT_ENABLED) @@ -62,7 +61,7 @@ class AdvancedPermissionControllerTest : AuthorizedControllerTest() { @Test fun `validates permissions (view languages and scopes)`() { permissionTestUtil.performSetPermissions( - "" + "", ) { getLang -> "scopes=screenshots.upload&viewLanguages=${getLang("en")}" } .andIsBadRequest .andHasErrorMessage(Message.CANNOT_SET_VIEW_LANGUAGES_WITHOUT_TRANSLATIONS_VIEW_SCOPE) @@ -71,7 +70,7 @@ class AdvancedPermissionControllerTest : AuthorizedControllerTest() { @Test fun `validates permissions (translate languages and scopes)`() { permissionTestUtil.performSetPermissions( - "" + "", ) { getLang -> "scopes=translations.view&translateLanguages=${getLang("en")}" } .andIsBadRequest .andHasErrorMessage(Message.CANNOT_SET_TRANSLATE_LANGUAGES_WITHOUT_TRANSLATIONS_EDIT_SCOPE) @@ -80,7 +79,7 @@ class AdvancedPermissionControllerTest : AuthorizedControllerTest() { @Test fun `validates permissions (state change languages and scopes)`() { permissionTestUtil.performSetPermissions( - "" + "", ) { getLang -> "scopes=translations.view&stateChangeLanguages=${getLang("en")}" } .andIsBadRequest .andHasErrorMessage(Message.CANNOT_SET_STATE_CHANGE_LANGUAGES_WITHOUT_TRANSLATIONS_STATE_EDIT_SCOPE) @@ -89,7 +88,7 @@ class AdvancedPermissionControllerTest : AuthorizedControllerTest() { @Test fun `validates permissions (empty scopes)`() { permissionTestUtil.performSetPermissions( - "" + "", ) { "" } .andIsBadRequest .andHasErrorMessage(Message.SCOPES_HAS_TO_BE_SET) @@ -123,7 +122,8 @@ class AdvancedPermissionControllerTest : AuthorizedControllerTest() { performSetScopesBaseOrganization(org).andIsOk organizationService.get(org.id).basePermission.scopes.assert.containsExactlyInAnyOrder( - Scope.TRANSLATIONS_EDIT, Scope.TRANSLATIONS_STATE_EDIT + Scope.TRANSLATIONS_EDIT, + Scope.TRANSLATIONS_STATE_EDIT, ) } } @@ -134,7 +134,7 @@ class AdvancedPermissionControllerTest : AuthorizedControllerTest() { permissionTestUtil.withPermissionsTestData { project, user -> val org = project.organizationOwner performSetScopesBaseOrganization(org).andIsBadRequest.andHasErrorMessage( - Message.FEATURE_NOT_ENABLED + Message.FEATURE_NOT_ENABLED, ) } } @@ -147,7 +147,7 @@ class AdvancedPermissionControllerTest : AuthorizedControllerTest() { performAuthPut( "/v2/organizations/${org.id}/set-base-permissions/TRANSLATE", - null + null, ).andIsOk performSetScopesBaseOrganization(org).andIsOk @@ -168,7 +168,7 @@ class AdvancedPermissionControllerTest : AuthorizedControllerTest() { private fun performSetScopesBaseOrganization(org: Organization): ResultActions { return performAuthPut( "/v2/organizations/${org.id}/set-base-permissions?scopes=translations.edit&scopes=translations.state-edit", - null + null, ) } } diff --git a/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/ContentStorageControllerTest.kt b/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/ContentStorageControllerTest.kt index 5adfa31731..4097cb1e19 100644 --- a/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/ContentStorageControllerTest.kt +++ b/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/ContentStorageControllerTest.kt @@ -32,7 +32,6 @@ import java.math.BigDecimal import java.util.function.Consumer class ContentStorageControllerTest : ProjectAuthControllerTest("/v2/projects/") { - private lateinit var testData: ContentDeliveryConfigTestData @Autowired @@ -99,14 +98,15 @@ class ContentStorageControllerTest : ProjectAuthControllerTest("/v2/projects/") "content-storages/${storage.id}", mapOf( "name" to "S3", - "s3ContentStorageConfig" to mapOf( - "bucketName" to "bucketName", - "accessKey" to "accessKey", - "secretKey" to "secretKey", - "endpoint" to "endpoint", - "signingRegion" to "signingRegion", - ) - ) + "s3ContentStorageConfig" to + mapOf( + "bucketName" to "bucketName", + "accessKey" to "accessKey", + "secretKey" to "secretKey", + "endpoint" to "endpoint", + "signingRegion" to "signingRegion", + ), + ), ).andIsOk.andAssertThatJson { node("name").isEqualTo("S3") } @@ -126,11 +126,12 @@ class ContentStorageControllerTest : ProjectAuthControllerTest("/v2/projects/") "content-storages/${storage.id}", mapOf( "name" to "Azure", - "azureContentStorageConfig" to mapOf( - "connectionString" to "fakeConnectionString", - "containerName" to "fakeContainerName" - ) - ) + "azureContentStorageConfig" to + mapOf( + "connectionString" to "fakeConnectionString", + "containerName" to "fakeContainerName", + ), + ), ).andIsOk.andAssertThatJson { node("name").isEqualTo("Azure") } @@ -142,11 +143,12 @@ class ContentStorageControllerTest : ProjectAuthControllerTest("/v2/projects/") performProjectAuthPost( "content-storages", mapOf( - "azureContentStorageConfig" to mapOf( - "connectionString" to "fakeConnectionString", - "containerName" to "fakeContainerName" - ) - ) + "azureContentStorageConfig" to + mapOf( + "connectionString" to "fakeConnectionString", + "containerName" to "fakeContainerName", + ), + ), ).andIsBadRequest } @@ -155,7 +157,7 @@ class ContentStorageControllerTest : ProjectAuthControllerTest("/v2/projects/") fun `deletes an storage`() { val (storage) = performCreate() performProjectAuthDelete( - "content-storages/${storage.id}" + "content-storages/${storage.id}", ).andIsOk } @@ -163,7 +165,7 @@ class ContentStorageControllerTest : ProjectAuthControllerTest("/v2/projects/") @ProjectJWTAuthTestMethod fun `deletes not delete when in use`() { performProjectAuthDelete( - "content-storages/${testData.azureContentStorage.self.id}" + "content-storages/${testData.azureContentStorage.self.id}", ).andIsBadRequest.andHasErrorMessage(Message.CONTENT_STORAGE_IS_IN_USE) } @@ -174,11 +176,12 @@ class ContentStorageControllerTest : ProjectAuthControllerTest("/v2/projects/") "content-storages/test", mapOf( "name" to "azure", - "azureContentStorageConfig" to mapOf( - "connectionString" to "fakeConnectionString", - "containerName" to "fakeContainerName" - ) - ) + "azureContentStorageConfig" to + mapOf( + "connectionString" to "fakeConnectionString", + "containerName" to "fakeContainerName", + ), + ), ).andAssertThatJson { node("success").isBoolean.isFalse }.andIsOk @@ -192,10 +195,11 @@ class ContentStorageControllerTest : ProjectAuthControllerTest("/v2/projects/") "content-storages/${storage.id}/test", mapOf( "name" to "azure", - "azureContentStorageConfig" to mapOf( - "containerName" to "fakeContainerName" - ) - ) + "azureContentStorageConfig" to + mapOf( + "containerName" to "fakeContainerName", + ), + ), ).andAssertThatJson { node("success").isBoolean.isTrue }.andIsOk @@ -208,14 +212,15 @@ class ContentStorageControllerTest : ProjectAuthControllerTest("/v2/projects/") "content-storages/test", mapOf( "name" to "s3", - "s3ContentStorageConfig" to mapOf( - "bucketName" to "bucketName", - "accessKey" to "accessKey", - "secretKey" to "secretKey", - "endpoint" to "endpoint", - "signingRegion" to "signingRegion", - ) - ) + "s3ContentStorageConfig" to + mapOf( + "bucketName" to "bucketName", + "accessKey" to "accessKey", + "secretKey" to "secretKey", + "endpoint" to "endpoint", + "signingRegion" to "signingRegion", + ), + ), ).andIsOk } @@ -226,18 +231,20 @@ class ContentStorageControllerTest : ProjectAuthControllerTest("/v2/projects/") var id: Long? = null - val result = performProjectAuthPost( - "content-storages", - mapOf( - "name" to "Azure", - "azureContentStorageConfig" to mapOf( - "connectionString" to "fakeConnectionString", - "containerName" to "fakeContainerName" - ) - ) - ).andIsOk.andAssertThatJson { - node("id").isValidId.satisfies(Consumer { it: BigDecimal -> id = it.toLong() }) - } + val result = + performProjectAuthPost( + "content-storages", + mapOf( + "name" to "Azure", + "azureContentStorageConfig" to + mapOf( + "connectionString" to "fakeConnectionString", + "containerName" to "fakeContainerName", + ), + ), + ).andIsOk.andAssertThatJson { + node("id").isValidId.satisfies(Consumer { it: BigDecimal -> id = it.toLong() }) + } val storage = contentStorageService.get(id!!) return storage to result diff --git a/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/EeLicenseControllerTest.kt b/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/EeLicenseControllerTest.kt index 8580e02745..769bfdaee5 100644 --- a/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/EeLicenseControllerTest.kt +++ b/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/EeLicenseControllerTest.kt @@ -23,7 +23,6 @@ import org.springframework.web.client.RestTemplate import java.util.* class EeLicenseControllerTest : AuthorizedControllerTest() { - @Autowired @MockBean lateinit var restTemplate: RestTemplate @@ -67,7 +66,9 @@ class EeLicenseControllerTest : AuthorizedControllerTest() { .andIsOk.andPrettyPrint.andAssertThatJson { } val body = captor.allValues.single().body as String - @Suppress("UNCHECKED_CAST") val req: Map = + + @Suppress("UNCHECKED_CAST") + val req: Map = jacksonObjectMapper().readValue(body, Map::class.java) as Map req["licenseKey"].assert.isEqualTo("mock-mock") @@ -110,7 +111,7 @@ class EeLicenseControllerTest : AuthorizedControllerTest() { verify { performAuthPost( "/v2/ee-license/prepare-set-license-key", - mapOf("licenseKey" to "mock-mock") + mapOf("licenseKey" to "mock-mock"), ).andIsOk.andPrettyPrint.andAssertThatJson { node("plan") { node("id").isNumber @@ -138,7 +139,8 @@ class EeLicenseControllerTest : AuthorizedControllerTest() { verify { performAuthPut( - "/v2/ee-license/refresh", null + "/v2/ee-license/refresh", + null, ).andIsOk eeSubscriptionRepository.findAll().single().status.assert.isEqualTo(SubscriptionStatus.ACTIVE) @@ -151,7 +153,7 @@ class EeLicenseControllerTest : AuthorizedControllerTest() { fun `returns info`() { prepareSubscription() performAuthGet( - "/v2/ee-license/info" + "/v2/ee-license/info", ).andIsOk } @@ -170,7 +172,8 @@ class EeLicenseControllerTest : AuthorizedControllerTest() { verify { performAuthPut( - "/v2/ee-license/release-license-key", null + "/v2/ee-license/release-license-key", + null, ).andIsOk eeSubscriptionRepository.findAll().assert.isEmpty() @@ -191,7 +194,7 @@ class EeLicenseControllerTest : AuthorizedControllerTest() { cancelAtPeriodEnd = false enabledFeatures = Feature.values() lastValidCheck = Date() - } + }, ) } diff --git a/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/V2ProjectsInvitationControllerEeTest.kt b/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/V2ProjectsInvitationControllerEeTest.kt index bf0ad0c941..fbbdede5ad 100644 --- a/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/V2ProjectsInvitationControllerEeTest.kt +++ b/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/V2ProjectsInvitationControllerEeTest.kt @@ -17,7 +17,6 @@ import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired class V2ProjectsInvitationControllerEeTest : ProjectAuthControllerTest("/v2/projects/") { - val invitationTestUtil: InvitationTestUtil by lazy { InvitationTestUtil(this, applicationContext) } @@ -33,9 +32,10 @@ class V2ProjectsInvitationControllerEeTest : ProjectAuthControllerTest("/v2/proj @Test @ProjectJWTAuthTestMethod fun `invites user to project with scopes`() { - val result = invitationTestUtil.perform { - scopes = setOf("translations.edit") - }.andIsOk + val result = + invitationTestUtil.perform { + scopes = setOf("translations.edit") + }.andIsOk val invitation = invitationTestUtil.getInvitation(result) invitation.permission!!.scopes.assert.containsExactlyInAnyOrder(Scope.TRANSLATIONS_EDIT) @@ -53,10 +53,11 @@ class V2ProjectsInvitationControllerEeTest : ProjectAuthControllerTest("/v2/proj @Test @ProjectJWTAuthTestMethod fun `adds the languages to view`() { - val result = invitationTestUtil.perform { getLang -> - scopes = setOf("translations.edit") - translateLanguages = setOf(getLang("en")) - }.andIsOk + val result = + invitationTestUtil.perform { getLang -> + scopes = setOf("translations.edit") + translateLanguages = setOf(getLang("en")) + }.andIsOk val invitation = invitationTestUtil.getInvitation(result) invitation.permission!!.translateLanguages.map { it.tag }.assert.containsExactlyInAnyOrder("en") diff --git a/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/WebhookConfigControllerTest.kt b/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/WebhookConfigControllerTest.kt index ede2cf685d..db62ee62af 100644 --- a/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/WebhookConfigControllerTest.kt +++ b/ee/backend/tests/src/test/kotlin/io/tolgee/ee/api/v2/controllers/WebhookConfigControllerTest.kt @@ -19,7 +19,6 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.test.web.servlet.ResultActions class WebhookConfigControllerTest : ProjectAuthControllerTest("/v2/projects/") { - lateinit var testData: WebhooksTestData @Autowired @@ -64,7 +63,7 @@ class WebhookConfigControllerTest : ProjectAuthControllerTest("/v2/projects/") { private fun createWebhook(): ResultActions { return performProjectAuthPost( "webhook-configs", - mapOf("url" to "https://hello.com") + mapOf("url" to "https://hello.com"), ) } @@ -73,7 +72,7 @@ class WebhookConfigControllerTest : ProjectAuthControllerTest("/v2/projects/") { fun `updates webhook config`() { performProjectAuthPut( "webhook-configs/${testData.webhookConfig.self.id}", - mapOf("url" to "https://hello.com") + mapOf("url" to "https://hello.com"), ).andIsOk.andAssertThatJson { node("id").isValidId node("url").isEqualTo("https://hello.com") @@ -84,7 +83,7 @@ class WebhookConfigControllerTest : ProjectAuthControllerTest("/v2/projects/") { @ProjectJWTAuthTestMethod fun `deletes webhook config`() { performProjectAuthDelete( - "webhook-configs/${testData.webhookConfig.self.id}" + "webhook-configs/${testData.webhookConfig.self.id}", ).andIsOk webhookConfigService.find(testData.webhookConfig.self.id).assert.isNull() @@ -94,7 +93,7 @@ class WebhookConfigControllerTest : ProjectAuthControllerTest("/v2/projects/") { @ProjectJWTAuthTestMethod fun `lists webhook configs`() { performProjectAuthGet( - "webhook-configs" + "webhook-configs", ).andAssertThatJson { node("_embedded.webhookConfigs") { isArray.hasSize(1) @@ -108,7 +107,7 @@ class WebhookConfigControllerTest : ProjectAuthControllerTest("/v2/projects/") { @ProjectJWTAuthTestMethod fun `get single webhook config`() { performProjectAuthGet( - "webhook-configs/${testData.webhookConfig.self.id}" + "webhook-configs/${testData.webhookConfig.self.id}", ).andAssertThatJson { node("id").isValidId node("url").isEqualTo("https://this-will-hopefully-never-exist.com/wh") @@ -121,7 +120,7 @@ class WebhookConfigControllerTest : ProjectAuthControllerTest("/v2/projects/") { fun `tests a config`() { performProjectAuthPost( "webhook-configs/${testData.webhookConfig.self.id}/test", - null + null, ).andIsOk.andAssertThatJson { node("success").isBoolean.isFalse } diff --git a/ee/backend/tests/src/test/kotlin/io/tolgee/ee/service/EeSubscriptionServiceTest.kt b/ee/backend/tests/src/test/kotlin/io/tolgee/ee/service/EeSubscriptionServiceTest.kt index 733161d494..98873a6f13 100644 --- a/ee/backend/tests/src/test/kotlin/io/tolgee/ee/service/EeSubscriptionServiceTest.kt +++ b/ee/backend/tests/src/test/kotlin/io/tolgee/ee/service/EeSubscriptionServiceTest.kt @@ -25,7 +25,6 @@ import java.util.* @Suppress("SpringBootApplicationProperties") @SpringBootTest(properties = ["tolgee.ee.check-period-ms=500"]) class EeSubscriptionServiceTest : AbstractSpringTest() { - @Autowired @MockBean lateinit var restTemplate: RestTemplate @@ -50,7 +49,7 @@ class EeSubscriptionServiceTest : AbstractSpringTest() { cancelAtPeriodEnd = false enabledFeatures = Feature.values() lastValidCheck = Date() - } + }, ) eeLicenseMockRequestUtil.mock { @@ -85,7 +84,7 @@ class EeSubscriptionServiceTest : AbstractSpringTest() { cancelAtPeriodEnd = false enabledFeatures = Feature.values() lastValidCheck = Date() - } + }, ) eeLicenseMockRequestUtil.mock { @@ -103,11 +102,11 @@ class EeSubscriptionServiceTest : AbstractSpringTest() { jacksonObjectMapper().writeValueAsString( ErrorResponseBody( Message.LICENSE_KEY_USED_BY_ANOTHER_INSTANCE.code, - null - ) + null, + ), ).toByteArray(), - null - ) + null, + ), ) verify {