From d4fbc46e6dd9b686abad7603622b70429d82bcfa Mon Sep 17 00:00:00 2001 From: KIvanow Date: Fri, 16 May 2025 08:49:10 +0300 Subject: [PATCH 01/14] RI-7091 - Add an environment variable to skip the EULA screen - initial implementation. Check vite.config! --- configs/webpack.config.main.prod.ts | 1 + redisinsight/api/config/default.ts | 2 ++ .../api/src/modules/settings/settings.service.ts | 15 +++++++++++++-- redisinsight/ui/src/config/default.ts | 1 + .../ui/src/utils/comparisons/compareConsents.ts | 10 ++++++++-- redisinsight/ui/vite.config.mjs | 2 +- 6 files changed, 26 insertions(+), 5 deletions(-) diff --git a/configs/webpack.config.main.prod.ts b/configs/webpack.config.main.prod.ts index 22bd6ffee4..2cdb8ff99b 100644 --- a/configs/webpack.config.main.prod.ts +++ b/configs/webpack.config.main.prod.ts @@ -68,6 +68,7 @@ export default merge(baseConfig, { RI_APP_HOST: '127.0.0.1', RI_BUILD_TYPE: 'ELECTRON', RI_APP_VERSION: version, + RI_ACCEPT_TERMS_AND_CONDITIONS: process.env.RI_ACCEPT_TERMS_AND_CONDITIONS || 'false', RI_SEGMENT_WRITE_KEY: 'RI_SEGMENT_WRITE_KEY' in process.env ? process.env.RI_SEGMENT_WRITE_KEY diff --git a/redisinsight/api/config/default.ts b/redisinsight/api/config/default.ts index 1fab943816..b186f9aa2c 100644 --- a/redisinsight/api/config/default.ts +++ b/redisinsight/api/config/default.ts @@ -94,6 +94,8 @@ export default { secretStoragePassword: process.env.RI_SECRET_STORAGE_PASSWORD, agreementsPath: process.env.RI_AGREEMENTS_PATH, encryptionKey: process.env.RI_ENCRYPTION_KEY, + acceptTermsAndConditions: + process.env.RI_ACCEPT_TERMS_AND_CONDITIONS === 'true', tlsCert: process.env.RI_SERVER_TLS_CERT, tlsKey: process.env.RI_SERVER_TLS_KEY, staticContent: !!process.env.RI_SERVE_STATICS || true, diff --git a/redisinsight/api/src/modules/settings/settings.service.ts b/redisinsight/api/src/modules/settings/settings.service.ts index 595dea4f4f..de487e3a57 100644 --- a/redisinsight/api/src/modules/settings/settings.service.ts +++ b/redisinsight/api/src/modules/settings/settings.service.ts @@ -56,14 +56,25 @@ export class SettingsService { ): Promise { this.logger.debug('Getting application settings.', sessionMetadata); try { - const agreements = - await this.agreementRepository.getOrCreate(sessionMetadata); const settings = await this.settingsRepository.getOrCreate(sessionMetadata); this.logger.debug( 'Succeed to get application settings.', sessionMetadata, ); + if (SERVER_CONFIG.acceptTermsAndConditions) { + return classToClass(GetAppSettingsResponse, { + ...settings?.data, + agreements: { + analytics: false, + encryption: true, + eula: true, + notifications: false, + }, + }); + } + const agreements = + await this.agreementRepository.getOrCreate(sessionMetadata); return classToClass(GetAppSettingsResponse, { ...settings?.data, agreements: agreements?.version diff --git a/redisinsight/ui/src/config/default.ts b/redisinsight/ui/src/config/default.ts index efacc5591b..a2cca2bbee 100644 --- a/redisinsight/ui/src/config/default.ts +++ b/redisinsight/ui/src/config/default.ts @@ -53,6 +53,7 @@ export const defaultConfig = { defaultTheme: process.env.RI_DEFAULT_THEME ?? 'SYSTEM', lazyLoad: booleanEnv('RI_ROUTES_LAZY_LOAD', false), routesExcludedByEnv: booleanEnv('RI_ROUTES_EXCLUDED_BY_ENV', false), + acceptTermsAndConditions: booleanEnv('RI_ACCEPT_TERMS_AND_CONDITIONS', false), returnUrlBase: process.env.RI_RETURN_URL_BASE, returnUrlLabel: process.env.RI_RETURN_URL_LABEL || 'Back', returnUrlTooltip: process.env.RI_RETURN_URL_TOOLTIP || 'Back', diff --git a/redisinsight/ui/src/utils/comparisons/compareConsents.ts b/redisinsight/ui/src/utils/comparisons/compareConsents.ts index 0bc4b0a6c9..3be8c88abe 100644 --- a/redisinsight/ui/src/utils/comparisons/compareConsents.ts +++ b/redisinsight/ui/src/utils/comparisons/compareConsents.ts @@ -1,9 +1,15 @@ import { has } from 'lodash' import { isVersionHigher } from 'uiSrc/utils/comparisons/compareVersions' +import { defaultConfig } from 'uiSrc/config/default' // returns true if has different consents -export const isDifferentConsentsExists = (specs: any, applied: any) => - !!compareConsents(specs, applied).length +export const isDifferentConsentsExists = (specs: any, applied: any) => { + // If terms and conditions are accepted via environment variable, always return false + if (defaultConfig.app.acceptTermsAndConditions) { + return false + } + return !!compareConsents(specs, applied).length +} export const compareConsents = ( specs: any = {}, diff --git a/redisinsight/ui/vite.config.mjs b/redisinsight/ui/vite.config.mjs index 6cb7354ca1..bbbdb5ba3e 100644 --- a/redisinsight/ui/vite.config.mjs +++ b/redisinsight/ui/vite.config.mjs @@ -124,7 +124,7 @@ export default defineConfig({ }, define: { global: 'globalThis', - 'process.env': {}, + 'process.env': process.env, riConfig: defaultConfig, }, // hack: apply proxy path to monaco webworker From 8bcf860b381b319135ffe42c88c16366bcb81b72 Mon Sep 17 00:00:00 2001 From: KIvanow Date: Fri, 16 May 2025 09:33:38 +0300 Subject: [PATCH 02/14] RI-7091 - Add an environment variable to skip the EULA screen - updated texts --- .../api/src/constants/agreements-spec.json | 2 +- .../ConsentOption/ConsentOption.tsx | 27 ++++++++++++++++--- .../ConsentsPrivacy/ConsentsPrivacy.tsx | 1 + .../consents-settings/ConsentsSettings.tsx | 11 +++++++- 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/redisinsight/api/src/constants/agreements-spec.json b/redisinsight/api/src/constants/agreements-spec.json index 8bff8e39d6..e99bc0549b 100644 --- a/redisinsight/api/src/constants/agreements-spec.json +++ b/redisinsight/api/src/constants/agreements-spec.json @@ -11,7 +11,7 @@ "since": "1.0.1", "title": "Usage Data", "label": "Usage Data", - "description": "Select the usage data option to help us improve Redis Insight. We use such usage data to understand how Redis Insight features are used, prioritize new features, and enhance the user experience." + "description": "Help improve Redis Insight by sharing anonymous usage data. This helps us understand feature usage and make the app better. By enabling this, you agree to our " }, "notifications": { "defaultValue": false, diff --git a/redisinsight/ui/src/components/consents-settings/ConsentOption/ConsentOption.tsx b/redisinsight/ui/src/components/consents-settings/ConsentOption/ConsentOption.tsx index 0c6e2a9d03..0a3c894966 100644 --- a/redisinsight/ui/src/components/consents-settings/ConsentOption/ConsentOption.tsx +++ b/redisinsight/ui/src/components/consents-settings/ConsentOption/ConsentOption.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { EuiSwitch, EuiText } from '@elastic/eui' +import { EuiLink, EuiSwitch, EuiText } from '@elastic/eui' import parse from 'html-react-parser' import { FlexItem, Row } from 'uiSrc/components/base/layout/flex' @@ -14,6 +14,7 @@ interface Props { checked: boolean isSettingsPage?: boolean withoutSpacer?: boolean + linkToPrivacyPolicy?: boolean } const ConsentOption = (props: Props) => { @@ -23,7 +24,27 @@ const ConsentOption = (props: Props) => { checked, isSettingsPage = false, withoutSpacer = false, + linkToPrivacyPolicy = false, } = props + + const getText = () => ( + <> + {consent.description && parse(consent.description)} + {linkToPrivacyPolicy && ( + <> + + Privacy Policy + + . + + )} + + ) + return ( {isSettingsPage && consent.description && ( @@ -34,7 +55,7 @@ const ConsentOption = (props: Props) => { color="subdued" style={{ marginTop: '12px' }} > - {parse(consent.description)} + {getText()} @@ -62,7 +83,7 @@ const ConsentOption = (props: Props) => { color="subdued" style={{ marginTop: '12px' }} > - {parse(consent.description)} + {getText()} )} diff --git a/redisinsight/ui/src/components/consents-settings/ConsentsPrivacy/ConsentsPrivacy.tsx b/redisinsight/ui/src/components/consents-settings/ConsentsPrivacy/ConsentsPrivacy.tsx index 8139d4304b..599480169e 100644 --- a/redisinsight/ui/src/components/consents-settings/ConsentsPrivacy/ConsentsPrivacy.tsx +++ b/redisinsight/ui/src/components/consents-settings/ConsentsPrivacy/ConsentsPrivacy.tsx @@ -97,6 +97,7 @@ const ConsentsPrivacy = () => { onChangeAgreement={onChangeAgreement} isSettingsPage key={consent.agreementName} + linkToPrivacyPolicy /> ))} diff --git a/redisinsight/ui/src/components/consents-settings/ConsentsSettings.tsx b/redisinsight/ui/src/components/consents-settings/ConsentsSettings.tsx index af40f36a09..2cf52b45ad 100644 --- a/redisinsight/ui/src/components/consents-settings/ConsentsSettings.tsx +++ b/redisinsight/ui/src/components/consents-settings/ConsentsSettings.tsx @@ -287,6 +287,7 @@ const ConsentsSettings = ({ onSubmitted }: Props) => { checked={formik.values[consent.agreementName] ?? false} onChangeAgreement={onChangeAgreement} key={consent.agreementName} + linkToPrivacyPolicy /> ))} {!!notificationConsents.length && ( @@ -312,7 +313,15 @@ const ConsentsSettings = ({ onSubmitted }: Props) => { - To use Redis Insight, please accept the terms and conditions:{' '} + Use of Redis Insight is governed by your signed agreement with Redis, or, if none, by the{' '} + + Redis Enterprise Software Subscription Agreement + + . If no agreement applies, use is subject to the{' '} Date: Fri, 16 May 2025 11:01:36 +0300 Subject: [PATCH 03/14] RI-7091 - Add an environment variable to skip the EULA screen - added tests --- .../modules/settings/settings.service.spec.ts | 30 +++++++++++++++++++ .../tests/comparisons/compareConsents.spec.ts | 14 +++++++++ 2 files changed, 44 insertions(+) diff --git a/redisinsight/api/src/modules/settings/settings.service.spec.ts b/redisinsight/api/src/modules/settings/settings.service.spec.ts index 8dc174341c..57a566aa26 100644 --- a/redisinsight/api/src/modules/settings/settings.service.spec.ts +++ b/redisinsight/api/src/modules/settings/settings.service.spec.ts @@ -29,6 +29,9 @@ import { FeatureServerEvents } from 'src/modules/feature/constants'; import { KeyEncryptionStrategy } from 'src/modules/encryption/strategies/key-encryption.strategy'; import { DatabaseDiscoveryService } from 'src/modules/database-discovery/database-discovery.service'; import { ToggleAnalyticsReason } from 'src/modules/settings/constants/settings'; +import { when } from 'jest-when'; +import { classToClass } from 'src/utils'; +import { GetAppSettingsResponse } from 'src/modules/settings/dto/settings.dto'; const REDIS_SCAN_CONFIG = config.get('redis_scan'); const WORKBENCH_CONFIG = config.get('workbench'); @@ -48,6 +51,7 @@ describe('SettingsService', () => { beforeEach(async () => { jest.clearAllMocks(); + const module: TestingModule = await Test.createTestingModule({ providers: [ SettingsService, @@ -127,6 +131,32 @@ describe('SettingsService', () => { }); }); + it('should verify expected pre-accepted agreements format', async () => { + const preselectedAgreements = { + analytics: false, + encryption: true, + eula: true, + notifications: false, + }; + settingsRepository.getOrCreate.mockResolvedValue(mockSettings); + + // Create a custom instance of the service with an override method + const customService = { + // Preserve the same data structure expected from the method + getAppSettings: async () => classToClass(GetAppSettingsResponse, { + ...mockSettings.data, + agreements: preselectedAgreements, + }), + }; + + // Call the customized method + const result = await customService.getAppSettings(); + + // Verify the result matches the expected format when acceptTermsAndConditions is true + expect(result).toHaveProperty('agreements'); + expect(result.agreements).toEqual(preselectedAgreements); + }); + it('should throw InternalServerError', async () => { agreementsRepository.getOrCreate.mockRejectedValue( new Error('some error'), diff --git a/redisinsight/ui/src/utils/tests/comparisons/compareConsents.spec.ts b/redisinsight/ui/src/utils/tests/comparisons/compareConsents.spec.ts index cddf45857e..d9c8158a3a 100644 --- a/redisinsight/ui/src/utils/tests/comparisons/compareConsents.spec.ts +++ b/redisinsight/ui/src/utils/tests/comparisons/compareConsents.spec.ts @@ -1,4 +1,5 @@ import { compareConsents, isDifferentConsentsExists } from 'uiSrc/utils' +import { defaultConfig } from 'uiSrc/config/default' const spec = { agreements: { @@ -59,4 +60,17 @@ describe('isDifferentConsentsExists', () => { expect(isDifferentConsentsExists(spec.agreements, agreements2)).toBeFalsy() expect(isDifferentConsentsExists(spec.agreements, agreements3)).toBeTruthy() }) + + it('should return false when defaultConfig.app.acceptTermsAndConditions is true', () => { + const originalAcceptTerms = defaultConfig.app.acceptTermsAndConditions + defaultConfig.app.acceptTermsAndConditions = true + const agreements = { + eula: false, + version: '1.0.0', + } + + expect(isDifferentConsentsExists(spec.agreements, agreements)).toBeFalsy() + + defaultConfig.app.acceptTermsAndConditions = originalAcceptTerms + }) }) From d3c1162b66e45db6bc780774a3d5dec834bfed2a Mon Sep 17 00:00:00 2001 From: Kristiyan Ivanov Date: Mon, 19 May 2025 11:17:43 +0300 Subject: [PATCH 04/14] RI-7091 - Add an environment variable to skip the EULA screen - updated UI handling --- .../src/modules/settings/dto/settings.dto.ts | 9 ++++++ .../modules/settings/settings.service.spec.ts | 3 ++ .../src/modules/settings/settings.service.ts | 2 ++ .../ui/src/components/config/Config.spec.tsx | 31 +++++++++++++++++++ .../ui/src/components/config/Config.tsx | 3 +- redisinsight/ui/src/config/default.ts | 1 - .../src/utils/comparisons/compareConsents.ts | 9 +----- .../tests/comparisons/compareConsents.spec.ts | 14 --------- redisinsight/ui/vite.config.mjs | 2 +- 9 files changed, 48 insertions(+), 26 deletions(-) diff --git a/redisinsight/api/src/modules/settings/dto/settings.dto.ts b/redisinsight/api/src/modules/settings/dto/settings.dto.ts index 25f36c39ee..a827c2ebf5 100644 --- a/redisinsight/api/src/modules/settings/dto/settings.dto.ts +++ b/redisinsight/api/src/modules/settings/dto/settings.dto.ts @@ -114,6 +114,15 @@ export class GetAppSettingsResponse { @Default(WORKBENCH_CONFIG.countBatch) batchSize: number = WORKBENCH_CONFIG.countBatch; + @ApiProperty({ + description: 'Flag indicating that terms and conditions are accepted via environment variable', + type: Boolean, + example: false, + }) + @Expose() + @Default(false) + acceptTermsAndConditionsOverwritten: boolean = false; + @ApiProperty({ description: 'Agreements set by the user.', type: GetUserAgreementsResponse, diff --git a/redisinsight/api/src/modules/settings/settings.service.spec.ts b/redisinsight/api/src/modules/settings/settings.service.spec.ts index 57a566aa26..a1aff03e34 100644 --- a/redisinsight/api/src/modules/settings/settings.service.spec.ts +++ b/redisinsight/api/src/modules/settings/settings.service.spec.ts @@ -111,6 +111,7 @@ describe('SettingsService', () => { dateFormat: null, timezone: null, agreements: null, + acceptTermsAndConditionsOverwritten: false, }); expect(eventEmitter.emit).not.toHaveBeenCalled(); @@ -124,6 +125,7 @@ describe('SettingsService', () => { expect(result).toEqual({ ...mockSettings.data, + acceptTermsAndConditionsOverwritten: false, agreements: { version: mockAgreements.version, ...mockAgreements.data, @@ -137,6 +139,7 @@ describe('SettingsService', () => { encryption: true, eula: true, notifications: false, + acceptTermsAndConditionsOverwritten: true, }; settingsRepository.getOrCreate.mockResolvedValue(mockSettings); diff --git a/redisinsight/api/src/modules/settings/settings.service.ts b/redisinsight/api/src/modules/settings/settings.service.ts index de487e3a57..5d35882c38 100644 --- a/redisinsight/api/src/modules/settings/settings.service.ts +++ b/redisinsight/api/src/modules/settings/settings.service.ts @@ -65,6 +65,7 @@ export class SettingsService { if (SERVER_CONFIG.acceptTermsAndConditions) { return classToClass(GetAppSettingsResponse, { ...settings?.data, + acceptTermsAndConditionsOverwritten: true, agreements: { analytics: false, encryption: true, @@ -77,6 +78,7 @@ export class SettingsService { await this.agreementRepository.getOrCreate(sessionMetadata); return classToClass(GetAppSettingsResponse, { ...settings?.data, + acceptTermsAndConditionsOverwritten: false, agreements: agreements?.version ? { ...agreements?.data, diff --git a/redisinsight/ui/src/components/config/Config.spec.tsx b/redisinsight/ui/src/components/config/Config.spec.tsx index 995013d1ca..7db1ef9afa 100644 --- a/redisinsight/ui/src/components/config/Config.spec.tsx +++ b/redisinsight/ui/src/components/config/Config.spec.tsx @@ -332,4 +332,35 @@ describe('Config', () => { ]), ) }) + + it('should not show consent popup when acceptTermsAndConditionsOverwritten is true, regardless of consent differences', () => { + const userSettingsSelectorMock = jest.fn().mockReturnValue({ + config: { + acceptTermsAndConditionsOverwritten: true, + agreements: {}, // Empty agreements - would normally cause a popup + }, + spec: { + agreements: { + eula: { + defaultValue: false, + required: true, + editable: false, + since: '1.0.0', + title: 'EULA: Redis Insight License Terms', + label: 'Label', + }, + }, + }, + }) + userSettingsSelector.mockImplementation(userSettingsSelectorMock) + + render() + + // Check that setSettingsPopupState is called with false + expect(store.getActions()).toEqual( + expect.arrayContaining([ + setSettingsPopupState(false), + ]) + ) + }) }) diff --git a/redisinsight/ui/src/components/config/Config.tsx b/redisinsight/ui/src/components/config/Config.tsx index 3312201065..010824456b 100644 --- a/redisinsight/ui/src/components/config/Config.tsx +++ b/redisinsight/ui/src/components/config/Config.tsx @@ -201,10 +201,9 @@ const Config = () => { const checkSettingsToShowPopup = () => { const specConsents = spec?.agreements const appliedConsents = config?.agreements - dispatch( setSettingsPopupState( - isDifferentConsentsExists(specConsents, appliedConsents), + config?.acceptTermsAndConditionsOverwritten ? false : isDifferentConsentsExists(specConsents, appliedConsents), ), ) } diff --git a/redisinsight/ui/src/config/default.ts b/redisinsight/ui/src/config/default.ts index a2cca2bbee..efacc5591b 100644 --- a/redisinsight/ui/src/config/default.ts +++ b/redisinsight/ui/src/config/default.ts @@ -53,7 +53,6 @@ export const defaultConfig = { defaultTheme: process.env.RI_DEFAULT_THEME ?? 'SYSTEM', lazyLoad: booleanEnv('RI_ROUTES_LAZY_LOAD', false), routesExcludedByEnv: booleanEnv('RI_ROUTES_EXCLUDED_BY_ENV', false), - acceptTermsAndConditions: booleanEnv('RI_ACCEPT_TERMS_AND_CONDITIONS', false), returnUrlBase: process.env.RI_RETURN_URL_BASE, returnUrlLabel: process.env.RI_RETURN_URL_LABEL || 'Back', returnUrlTooltip: process.env.RI_RETURN_URL_TOOLTIP || 'Back', diff --git a/redisinsight/ui/src/utils/comparisons/compareConsents.ts b/redisinsight/ui/src/utils/comparisons/compareConsents.ts index 3be8c88abe..58929736ee 100644 --- a/redisinsight/ui/src/utils/comparisons/compareConsents.ts +++ b/redisinsight/ui/src/utils/comparisons/compareConsents.ts @@ -1,15 +1,8 @@ import { has } from 'lodash' import { isVersionHigher } from 'uiSrc/utils/comparisons/compareVersions' -import { defaultConfig } from 'uiSrc/config/default' // returns true if has different consents -export const isDifferentConsentsExists = (specs: any, applied: any) => { - // If terms and conditions are accepted via environment variable, always return false - if (defaultConfig.app.acceptTermsAndConditions) { - return false - } - return !!compareConsents(specs, applied).length -} +export const isDifferentConsentsExists = (specs: any, applied: any) => !!compareConsents(specs, applied).length export const compareConsents = ( specs: any = {}, diff --git a/redisinsight/ui/src/utils/tests/comparisons/compareConsents.spec.ts b/redisinsight/ui/src/utils/tests/comparisons/compareConsents.spec.ts index d9c8158a3a..cddf45857e 100644 --- a/redisinsight/ui/src/utils/tests/comparisons/compareConsents.spec.ts +++ b/redisinsight/ui/src/utils/tests/comparisons/compareConsents.spec.ts @@ -1,5 +1,4 @@ import { compareConsents, isDifferentConsentsExists } from 'uiSrc/utils' -import { defaultConfig } from 'uiSrc/config/default' const spec = { agreements: { @@ -60,17 +59,4 @@ describe('isDifferentConsentsExists', () => { expect(isDifferentConsentsExists(spec.agreements, agreements2)).toBeFalsy() expect(isDifferentConsentsExists(spec.agreements, agreements3)).toBeTruthy() }) - - it('should return false when defaultConfig.app.acceptTermsAndConditions is true', () => { - const originalAcceptTerms = defaultConfig.app.acceptTermsAndConditions - defaultConfig.app.acceptTermsAndConditions = true - const agreements = { - eula: false, - version: '1.0.0', - } - - expect(isDifferentConsentsExists(spec.agreements, agreements)).toBeFalsy() - - defaultConfig.app.acceptTermsAndConditions = originalAcceptTerms - }) }) diff --git a/redisinsight/ui/vite.config.mjs b/redisinsight/ui/vite.config.mjs index bbbdb5ba3e..6cb7354ca1 100644 --- a/redisinsight/ui/vite.config.mjs +++ b/redisinsight/ui/vite.config.mjs @@ -124,7 +124,7 @@ export default defineConfig({ }, define: { global: 'globalThis', - 'process.env': process.env, + 'process.env': {}, riConfig: defaultConfig, }, // hack: apply proxy path to monaco webworker From a8600595559118b48882b245f99a7f164275dad4 Mon Sep 17 00:00:00 2001 From: Kristiyan Ivanov Date: Mon, 19 May 2025 11:49:16 +0300 Subject: [PATCH 05/14] RI-7091 - Add an environment variable to skip the EULA screen --- redisinsight/api/src/modules/settings/settings.analytics.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/redisinsight/api/src/modules/settings/settings.analytics.spec.ts b/redisinsight/api/src/modules/settings/settings.analytics.spec.ts index 9f37aac4a8..1219920974 100644 --- a/redisinsight/api/src/modules/settings/settings.analytics.spec.ts +++ b/redisinsight/api/src/modules/settings/settings.analytics.spec.ts @@ -131,6 +131,7 @@ describe('SettingsAnalytics', () => { describe('sendSettingsUpdatedEvent', () => { const defaultSettings: GetAppSettingsResponse = { + acceptTermsAndConditionsOverwritten: false, agreements: null, scanThreshold: 10000, batchSize: 5, From f90bf2bdf392895fec5b264ddc7884203f3324ab Mon Sep 17 00:00:00 2001 From: Kristiyan Ivanov Date: Mon, 19 May 2025 13:52:27 +0300 Subject: [PATCH 06/14] RI-7091 - Add an environment variable to skip the EULA screen - updated hard coded variables approach as per Artem's feedback --- .../repositories/agreements.repository.ts | 6 ++- .../local.agreements.repository.ts | 18 +++++++-- .../src/modules/settings/settings.service.ts | 37 ++++++++++++------- 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/redisinsight/api/src/modules/settings/repositories/agreements.repository.ts b/redisinsight/api/src/modules/settings/repositories/agreements.repository.ts index 95b5ca3cf5..ce06e64ced 100644 --- a/redisinsight/api/src/modules/settings/repositories/agreements.repository.ts +++ b/redisinsight/api/src/modules/settings/repositories/agreements.repository.ts @@ -1,8 +1,12 @@ import { Agreements } from 'src/modules/settings/models/agreements'; import { SessionMetadata } from 'src/common/models'; +export interface DefaultAgreementsOptions { + data?: Record; +} + export abstract class AgreementsRepository { - abstract getOrCreate(sessionMetadata: SessionMetadata): Promise; + abstract getOrCreate(defaultOptions?: DefaultAgreementsOptions): Promise; abstract update( sessionMetadata: SessionMetadata, agreements: Agreements, diff --git a/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.ts b/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.ts index 62e81eecff..24a7361d68 100644 --- a/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.ts +++ b/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.ts @@ -1,7 +1,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { classToClass } from 'src/utils'; -import { AgreementsRepository } from 'src/modules/settings/repositories/agreements.repository'; +import { AgreementsRepository, DefaultAgreementsOptions } from 'src/modules/settings/repositories/agreements.repository'; import { AgreementsEntity } from 'src/modules/settings/entities/agreements.entity'; import { Agreements } from 'src/modules/settings/models/agreements'; import { SessionMetadata } from 'src/common/models'; @@ -14,12 +14,22 @@ export class LocalAgreementsRepository extends AgreementsRepository { super(); } - async getOrCreate(): Promise { + async getOrCreate( + defaultOptions?: DefaultAgreementsOptions + ): Promise { let entity = await this.repository.findOneBy({}); - if (!entity) { try { - entity = await this.repository.save(this.repository.create({ id: 1 })); + if (defaultOptions?.data) { + entity = await this.repository.save( + this.repository.create({ + id: 1, + data: JSON.stringify(defaultOptions.data), + }) + ); + } else { + entity = await this.repository.save(this.repository.create({ id: 1 })); + } } catch (e) { if (e.code === 'SQLITE_CONSTRAINT') { return this.getOrCreate(); diff --git a/redisinsight/api/src/modules/settings/settings.service.ts b/redisinsight/api/src/modules/settings/settings.service.ts index 5d35882c38..8994489d5d 100644 --- a/redisinsight/api/src/modules/settings/settings.service.ts +++ b/redisinsight/api/src/modules/settings/settings.service.ts @@ -58,24 +58,35 @@ export class SettingsService { try { const settings = await this.settingsRepository.getOrCreate(sessionMetadata); - this.logger.debug( - 'Succeed to get application settings.', - sessionMetadata, - ); + + let agreements; if (SERVER_CONFIG.acceptTermsAndConditions) { - return classToClass(GetAppSettingsResponse, { - ...settings?.data, - acceptTermsAndConditionsOverwritten: true, - agreements: { + const isEncryptionAvailable = + (await this.keyEncryptionStrategy.isAvailable()) || + (await this.keytarEncryptionStrategy.isAvailable()); + + const defaultOptions = { + data: { analytics: false, - encryption: true, + encryption: isEncryptionAvailable, eula: true, notifications: false, - }, - }); + } + }; + + agreements = await this.agreementRepository.getOrCreate( + defaultOptions + ); + } else { + agreements = await this.agreementRepository.getOrCreate(); } - const agreements = - await this.agreementRepository.getOrCreate(sessionMetadata); + + this.logger.debug( + 'Succeed to get application settings.', + sessionMetadata, + ); + + return classToClass(GetAppSettingsResponse, { ...settings?.data, acceptTermsAndConditionsOverwritten: false, From b0cc6e1973bf5e50715420816989883a53f3f59c Mon Sep 17 00:00:00 2001 From: KIvanow Date: Mon, 19 May 2025 14:13:37 +0300 Subject: [PATCH 07/14] RI-7091 - Add an environment variable to skip the EULA screen - updated test cases --- .../local.agreements.repository.spec.ts | 12 ++++++++++++ .../src/modules/settings/settings.service.ts | 18 +++++++++--------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.spec.ts b/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.spec.ts index f1b1d0b5dc..17d013fbf7 100644 --- a/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.spec.ts +++ b/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.spec.ts @@ -72,6 +72,18 @@ describe('LocalAgreementsRepository', () => { await expect(service.getOrCreate()).rejects.toThrow(Error); }); + it('should create new agreements with default data when provided and no entity exists', async () => { + repository.findOneBy.mockResolvedValueOnce(null); + const defaultData = { eula: true, analytics: false }; + + await service.getOrCreate({ data: defaultData }); + + expect(repository.create).toHaveBeenCalledWith({ + id: 1, + data: JSON.stringify(defaultData), + }); + expect(repository.save).toHaveBeenCalled(); + }); }); describe('update', () => { diff --git a/redisinsight/api/src/modules/settings/settings.service.ts b/redisinsight/api/src/modules/settings/settings.service.ts index 8994489d5d..9e79955570 100644 --- a/redisinsight/api/src/modules/settings/settings.service.ts +++ b/redisinsight/api/src/modules/settings/settings.service.ts @@ -58,13 +58,13 @@ export class SettingsService { try { const settings = await this.settingsRepository.getOrCreate(sessionMetadata); - + let agreements; if (SERVER_CONFIG.acceptTermsAndConditions) { - const isEncryptionAvailable = - (await this.keyEncryptionStrategy.isAvailable()) || + const isEncryptionAvailable = + (await this.keyEncryptionStrategy.isAvailable()) || (await this.keytarEncryptionStrategy.isAvailable()); - + const defaultOptions = { data: { analytics: false, @@ -73,23 +73,23 @@ export class SettingsService { notifications: false, } }; - + agreements = await this.agreementRepository.getOrCreate( defaultOptions ); } else { agreements = await this.agreementRepository.getOrCreate(); } - + this.logger.debug( 'Succeed to get application settings.', sessionMetadata, ); - - + + return classToClass(GetAppSettingsResponse, { ...settings?.data, - acceptTermsAndConditionsOverwritten: false, + acceptTermsAndConditionsOverwritten: SERVER_CONFIG.acceptTermsAndConditions, agreements: agreements?.version ? { ...agreements?.data, From 93dc680bda633f720f51ccee3d56cc7eee4456b3 Mon Sep 17 00:00:00 2001 From: Kristiyan Ivanov Date: Mon, 19 May 2025 15:22:45 +0300 Subject: [PATCH 08/14] RI-7091 - Add an environment variable to skip the EULA screen - updated integration test cases --- redisinsight/api/test/api/settings/GET-settings.test.ts | 1 + redisinsight/api/test/api/settings/PATCH-settings.test.ts | 1 + redisinsight/api/test/helpers/constants.ts | 1 + 3 files changed, 3 insertions(+) diff --git a/redisinsight/api/test/api/settings/GET-settings.test.ts b/redisinsight/api/test/api/settings/GET-settings.test.ts index 313ecaa176..6a0b69a1e8 100644 --- a/redisinsight/api/test/api/settings/GET-settings.test.ts +++ b/redisinsight/api/test/api/settings/GET-settings.test.ts @@ -24,6 +24,7 @@ const responseSchema = Joi.object() batchSize: Joi.number().required(), dateFormat: Joi.string().allow(null), timezone: Joi.string().allow(null), + acceptTermsAndConditionsOverwritten: Joi.bool().required(), agreements: Joi.object() .keys({ version: Joi.string().required(), diff --git a/redisinsight/api/test/api/settings/PATCH-settings.test.ts b/redisinsight/api/test/api/settings/PATCH-settings.test.ts index 14f2e5e661..d5c6808bee 100644 --- a/redisinsight/api/test/api/settings/PATCH-settings.test.ts +++ b/redisinsight/api/test/api/settings/PATCH-settings.test.ts @@ -24,6 +24,7 @@ const responseSchema = Joi.object() batchSize: Joi.number().required(), dateFormat: Joi.string().allow(null), timezone: Joi.string().allow(null), + acceptTermsAndConditionsOverwritten: Joi.bool().required(), agreements: Joi.object() .keys({ version: Joi.string().required(), diff --git a/redisinsight/api/test/helpers/constants.ts b/redisinsight/api/test/helpers/constants.ts index 613945b26d..4b13fb2024 100644 --- a/redisinsight/api/test/helpers/constants.ts +++ b/redisinsight/api/test/helpers/constants.ts @@ -26,6 +26,7 @@ const APP_DEFAULT_SETTINGS = { dateFormat: null, timezone: null, agreements: null, + acceptTermsAndConditionsOverwritten: false, }; const TEST_LIBRARY_NAME = 'lib'; const TEST_ANALYTICS_PAGE = 'Settings'; From e760827bbe2c89817b492309a1a436d37d1cb56f Mon Sep 17 00:00:00 2001 From: KIvanow Date: Mon, 19 May 2025 16:30:59 +0300 Subject: [PATCH 09/14] RI-7091 - Add an environment variable to skip the EULA screen - updated webpack config --- configs/webpack.config.main.prod.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/configs/webpack.config.main.prod.ts b/configs/webpack.config.main.prod.ts index 2cdb8ff99b..22bd6ffee4 100644 --- a/configs/webpack.config.main.prod.ts +++ b/configs/webpack.config.main.prod.ts @@ -68,7 +68,6 @@ export default merge(baseConfig, { RI_APP_HOST: '127.0.0.1', RI_BUILD_TYPE: 'ELECTRON', RI_APP_VERSION: version, - RI_ACCEPT_TERMS_AND_CONDITIONS: process.env.RI_ACCEPT_TERMS_AND_CONDITIONS || 'false', RI_SEGMENT_WRITE_KEY: 'RI_SEGMENT_WRITE_KEY' in process.env ? process.env.RI_SEGMENT_WRITE_KEY From 40cc42a08cf3a59a3bb180268773907993ed6502 Mon Sep 17 00:00:00 2001 From: ArtemHoruzhenko Date: Tue, 20 May 2025 14:45:30 +0300 Subject: [PATCH 10/14] RI-7091 rework repository --- .../repositories/agreements.repository.ts | 6 ++++- .../local.agreements.repository.ts | 26 +++++++++---------- .../src/modules/settings/settings.service.ts | 15 +++++------ 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/redisinsight/api/src/modules/settings/repositories/agreements.repository.ts b/redisinsight/api/src/modules/settings/repositories/agreements.repository.ts index ce06e64ced..469a424799 100644 --- a/redisinsight/api/src/modules/settings/repositories/agreements.repository.ts +++ b/redisinsight/api/src/modules/settings/repositories/agreements.repository.ts @@ -2,11 +2,15 @@ import { Agreements } from 'src/modules/settings/models/agreements'; import { SessionMetadata } from 'src/common/models'; export interface DefaultAgreementsOptions { + version?: string; data?: Record; } export abstract class AgreementsRepository { - abstract getOrCreate(defaultOptions?: DefaultAgreementsOptions): Promise; + abstract getOrCreate( + sessionMetadata: SessionMetadata, + defaultOptions?: DefaultAgreementsOptions, + ): Promise; abstract update( sessionMetadata: SessionMetadata, agreements: Agreements, diff --git a/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.ts b/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.ts index 24a7361d68..679286bf2c 100644 --- a/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.ts +++ b/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.ts @@ -5,6 +5,7 @@ import { AgreementsRepository, DefaultAgreementsOptions } from 'src/modules/sett import { AgreementsEntity } from 'src/modules/settings/entities/agreements.entity'; import { Agreements } from 'src/modules/settings/models/agreements'; import { SessionMetadata } from 'src/common/models'; +import { plainToInstance } from 'class-transformer'; export class LocalAgreementsRepository extends AgreementsRepository { constructor( @@ -15,24 +16,21 @@ export class LocalAgreementsRepository extends AgreementsRepository { } async getOrCreate( - defaultOptions?: DefaultAgreementsOptions + sessionMetadata: SessionMetadata, + defaultOptions: DefaultAgreementsOptions = {}, ): Promise { let entity = await this.repository.findOneBy({}); if (!entity) { try { - if (defaultOptions?.data) { - entity = await this.repository.save( - this.repository.create({ - id: 1, - data: JSON.stringify(defaultOptions.data), - }) - ); - } else { - entity = await this.repository.save(this.repository.create({ id: 1 })); - } + entity = await this.repository.save( + classToClass(AgreementsEntity, plainToInstance(Agreements, { + ...defaultOptions, + id: 1, + })), + ); } catch (e) { if (e.code === 'SQLITE_CONSTRAINT') { - return this.getOrCreate(); + return this.getOrCreate(sessionMetadata); } throw e; @@ -43,13 +41,13 @@ export class LocalAgreementsRepository extends AgreementsRepository { } async update( - _: SessionMetadata, + sessionMetadata: SessionMetadata, agreements: Agreements, ): Promise { const entity = classToClass(AgreementsEntity, agreements); await this.repository.save(entity); - return this.getOrCreate(); + return this.getOrCreate(sessionMetadata); } } diff --git a/redisinsight/api/src/modules/settings/settings.service.ts b/redisinsight/api/src/modules/settings/settings.service.ts index 9e79955570..e66ebd5c2b 100644 --- a/redisinsight/api/src/modules/settings/settings.service.ts +++ b/redisinsight/api/src/modules/settings/settings.service.ts @@ -59,28 +59,25 @@ export class SettingsService { const settings = await this.settingsRepository.getOrCreate(sessionMetadata); - let agreements; + let defaultOptions: object; if (SERVER_CONFIG.acceptTermsAndConditions) { const isEncryptionAvailable = (await this.keyEncryptionStrategy.isAvailable()) || (await this.keytarEncryptionStrategy.isAvailable()); - const defaultOptions = { + defaultOptions = { data: { analytics: false, encryption: isEncryptionAvailable, eula: true, notifications: false, - } + }, + version: (await this.getAgreementsSpec()).version, }; - - agreements = await this.agreementRepository.getOrCreate( - defaultOptions - ); - } else { - agreements = await this.agreementRepository.getOrCreate(); } + const agreements = await this.agreementRepository.getOrCreate(sessionMetadata, defaultOptions); + this.logger.debug( 'Succeed to get application settings.', sessionMetadata, From f21c05640371873c5c86c2f1d97a78bc59d24100 Mon Sep 17 00:00:00 2001 From: Kristiyan Ivanov Date: Tue, 20 May 2025 15:32:12 +0300 Subject: [PATCH 11/14] RI-7091 - Add an environment variable to skip the EULA screen - added encryption available utility method --- .../api/src/modules/encryption/encryption.service.ts | 8 ++++++++ redisinsight/api/src/modules/settings/settings.service.ts | 6 +++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/redisinsight/api/src/modules/encryption/encryption.service.ts b/redisinsight/api/src/modules/encryption/encryption.service.ts index c34da106d0..f4322f2cc4 100644 --- a/redisinsight/api/src/modules/encryption/encryption.service.ts +++ b/redisinsight/api/src/modules/encryption/encryption.service.ts @@ -37,6 +37,14 @@ export class EncryptionService { return strategies; } + /** + * Checks if any encryption strategy other than PLAIN is available + */ + async isEncryptionAvailable(): Promise { + const strategies = await this.getAvailableEncryptionStrategies(); + return strategies.length > 1 || (strategies.length === 1 && strategies[0] !== EncryptionStrategy.PLAIN); + } + /** * Get encryption strategy based on app settings * This strategy should be received from app settings but before it should be set by user. diff --git a/redisinsight/api/src/modules/settings/settings.service.ts b/redisinsight/api/src/modules/settings/settings.service.ts index e66ebd5c2b..11dabd7fcc 100644 --- a/redisinsight/api/src/modules/settings/settings.service.ts +++ b/redisinsight/api/src/modules/settings/settings.service.ts @@ -30,6 +30,7 @@ import { GetAppSettingsResponse, UpdateSettingsDto, } from './dto/settings.dto'; +import { EncryptionService } from '../encryption/encryption.service'; const SERVER_CONFIG = config.get('server') as Config['server']; @@ -45,6 +46,7 @@ export class SettingsService { private readonly analytics: SettingsAnalytics, private readonly keytarEncryptionStrategy: KeytarEncryptionStrategy, private readonly keyEncryptionStrategy: KeyEncryptionStrategy, + private readonly encryptionService: EncryptionService, private eventEmitter: EventEmitter2, ) {} @@ -61,9 +63,7 @@ export class SettingsService { let defaultOptions: object; if (SERVER_CONFIG.acceptTermsAndConditions) { - const isEncryptionAvailable = - (await this.keyEncryptionStrategy.isAvailable()) || - (await this.keytarEncryptionStrategy.isAvailable()); + const isEncryptionAvailable = await this.encryptionService.isEncryptionAvailable(); defaultOptions = { data: { From ea8948a10166d35a17523a5e99db3407347dc818 Mon Sep 17 00:00:00 2001 From: Kristiyan Ivanov Date: Tue, 20 May 2025 16:58:08 +0300 Subject: [PATCH 12/14] RI-7091 - Add an environment variable to skip the EULA screen - updated tests --- redisinsight/api/src/__mocks__/encryption.ts | 2 ++ .../api/src/modules/encryption/encryption.service.ts | 3 ++- .../settings/repositories/local.agreements.repository.ts | 4 ++-- .../api/src/modules/settings/settings.service.spec.ts | 8 ++++++++ redisinsight/api/src/modules/settings/settings.service.ts | 1 + 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/redisinsight/api/src/__mocks__/encryption.ts b/redisinsight/api/src/__mocks__/encryption.ts index 27dbed3e72..d19ea42278 100644 --- a/redisinsight/api/src/__mocks__/encryption.ts +++ b/redisinsight/api/src/__mocks__/encryption.ts @@ -20,8 +20,10 @@ export const mockKeyEncryptResult = { export const mockEncryptionService = jest.fn(() => ({ getAvailableEncryptionStrategies: jest.fn(), + isEncryptionAvailable: jest.fn().mockResolvedValue(true), encrypt: jest.fn(), decrypt: jest.fn(), + getEncryptionStrategy: jest.fn(), })); export const mockEncryptionStrategyInstance = jest.fn(() => ({ diff --git a/redisinsight/api/src/modules/encryption/encryption.service.ts b/redisinsight/api/src/modules/encryption/encryption.service.ts index f4322f2cc4..47a51f53a4 100644 --- a/redisinsight/api/src/modules/encryption/encryption.service.ts +++ b/redisinsight/api/src/modules/encryption/encryption.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { forwardRef, Inject, Injectable } from '@nestjs/common'; import { KeytarEncryptionStrategy } from 'src/modules/encryption/strategies/keytar-encryption.strategy'; import { PlainEncryptionStrategy } from 'src/modules/encryption/strategies/plain-encryption.strategy'; import { @@ -14,6 +14,7 @@ import { ConstantsProvider } from 'src/modules/constants/providers/constants.pro @Injectable() export class EncryptionService { constructor( + @Inject(forwardRef(() => SettingsService)) private readonly settingsService: SettingsService, private readonly keytarEncryptionStrategy: KeytarEncryptionStrategy, private readonly plainEncryptionStrategy: PlainEncryptionStrategy, diff --git a/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.ts b/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.ts index 679286bf2c..a828db01c7 100644 --- a/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.ts +++ b/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.ts @@ -17,7 +17,7 @@ export class LocalAgreementsRepository extends AgreementsRepository { async getOrCreate( sessionMetadata: SessionMetadata, - defaultOptions: DefaultAgreementsOptions = {}, + defaultOptions: DefaultAgreementsOptions = {} ): Promise { let entity = await this.repository.findOneBy({}); if (!entity) { @@ -30,7 +30,7 @@ export class LocalAgreementsRepository extends AgreementsRepository { ); } catch (e) { if (e.code === 'SQLITE_CONSTRAINT') { - return this.getOrCreate(sessionMetadata); + return this.getOrCreate(sessionMetadata, defaultOptions); } throw e; diff --git a/redisinsight/api/src/modules/settings/settings.service.spec.ts b/redisinsight/api/src/modules/settings/settings.service.spec.ts index a1aff03e34..8bbbc62fe3 100644 --- a/redisinsight/api/src/modules/settings/settings.service.spec.ts +++ b/redisinsight/api/src/modules/settings/settings.service.spec.ts @@ -5,6 +5,7 @@ import { mockAgreementsRepository, mockAppSettings, mockDatabaseDiscoveryService, + mockEncryptionService, mockEncryptionStrategyInstance, mockKeyEncryptionStrategyInstance, mockSessionMetadata, @@ -32,6 +33,7 @@ import { ToggleAnalyticsReason } from 'src/modules/settings/constants/settings'; import { when } from 'jest-when'; import { classToClass } from 'src/utils'; import { GetAppSettingsResponse } from 'src/modules/settings/dto/settings.dto'; +import { EncryptionService } from 'src/modules/encryption/encryption.service'; const REDIS_SCAN_CONFIG = config.get('redis_scan'); const WORKBENCH_CONFIG = config.get('workbench'); @@ -47,6 +49,7 @@ describe('SettingsService', () => { let settingsRepository: MockType; let analyticsService: SettingsAnalytics; let keytarStrategy: MockType; + let encryptionService: MockType; let eventEmitter: EventEmitter2; beforeEach(async () => { @@ -79,6 +82,10 @@ describe('SettingsService', () => { provide: KeyEncryptionStrategy, useFactory: mockKeyEncryptionStrategyInstance, }, + { + provide: EncryptionService, + useFactory: mockEncryptionService, + }, { provide: EventEmitter2, useFactory: () => ({ @@ -95,6 +102,7 @@ describe('SettingsService', () => { analyticsService = module.get(SettingsAnalytics); service = module.get(SettingsService); eventEmitter = module.get(EventEmitter2); + encryptionService = module.get(EncryptionService); }); describe('getAppSettings', () => { diff --git a/redisinsight/api/src/modules/settings/settings.service.ts b/redisinsight/api/src/modules/settings/settings.service.ts index 11dabd7fcc..94e89fd453 100644 --- a/redisinsight/api/src/modules/settings/settings.service.ts +++ b/redisinsight/api/src/modules/settings/settings.service.ts @@ -46,6 +46,7 @@ export class SettingsService { private readonly analytics: SettingsAnalytics, private readonly keytarEncryptionStrategy: KeytarEncryptionStrategy, private readonly keyEncryptionStrategy: KeyEncryptionStrategy, + @Inject(forwardRef(() => EncryptionService)) private readonly encryptionService: EncryptionService, private eventEmitter: EventEmitter2, ) {} From d07defd8d265c7f1fb31de2d2b48ad80ddd6f055 Mon Sep 17 00:00:00 2001 From: Kristiyan Ivanov Date: Tue, 20 May 2025 16:59:15 +0300 Subject: [PATCH 13/14] RI-7091 - Add an environment variable to skip the EULA screen - updated tests --- .../repositories/local.agreements.repository.spec.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.spec.ts b/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.spec.ts index 17d013fbf7..11d48623ed 100644 --- a/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.spec.ts +++ b/redisinsight/api/src/modules/settings/repositories/local.agreements.repository.spec.ts @@ -42,14 +42,14 @@ describe('LocalAgreementsRepository', () => { describe('getOrCreate', () => { it('should return agreements', async () => { - const result = await service.getOrCreate(); + const result = await service.getOrCreate(mockSessionMetadata); expect(result).toEqual(mockAgreements); }); it('should create new agreements', async () => { repository.findOneBy.mockResolvedValueOnce(null); - const result = await service.getOrCreate(); + const result = await service.getOrCreate(mockSessionMetadata); expect(result).toEqual({ ...mockAgreements, @@ -62,7 +62,7 @@ describe('LocalAgreementsRepository', () => { repository.findOneBy.mockResolvedValueOnce(mockAgreements); repository.save.mockRejectedValueOnce({ code: 'SQLITE_CONSTRAINT' }); - const result = await service.getOrCreate(); + const result = await service.getOrCreate(mockSessionMetadata); expect(result).toEqual(mockAgreements); }); @@ -70,15 +70,15 @@ describe('LocalAgreementsRepository', () => { repository.findOneBy.mockResolvedValueOnce(null); repository.save.mockRejectedValueOnce(new Error()); - await expect(service.getOrCreate()).rejects.toThrow(Error); + await expect(service.getOrCreate(mockSessionMetadata)).rejects.toThrow(Error); }); it('should create new agreements with default data when provided and no entity exists', async () => { repository.findOneBy.mockResolvedValueOnce(null); const defaultData = { eula: true, analytics: false }; - await service.getOrCreate({ data: defaultData }); + await service.getOrCreate(mockSessionMetadata, { data: defaultData }); - expect(repository.create).toHaveBeenCalledWith({ + expect(repository.save).toHaveBeenCalledWith({ id: 1, data: JSON.stringify(defaultData), }); From 3d1bcbca6aac3169f8eefaa9ba554709bd7fc773 Mon Sep 17 00:00:00 2001 From: Kristiyan Ivanov Date: Tue, 20 May 2025 17:05:03 +0300 Subject: [PATCH 14/14] RI-7091 - Add an environment variable to skip the EULA screen - replacing a function call with 3 files and a folder --- .../ConsentOption/ConsentOption.tsx | 25 +++--------------- .../components/ItemDescription.tsx | 26 +++++++++++++++++++ .../ConsentOption/components/index.tsx | 3 +++ 3 files changed, 33 insertions(+), 21 deletions(-) create mode 100644 redisinsight/ui/src/components/consents-settings/ConsentOption/components/ItemDescription.tsx create mode 100644 redisinsight/ui/src/components/consents-settings/ConsentOption/components/index.tsx diff --git a/redisinsight/ui/src/components/consents-settings/ConsentOption/ConsentOption.tsx b/redisinsight/ui/src/components/consents-settings/ConsentOption/ConsentOption.tsx index 0a3c894966..3f439819c5 100644 --- a/redisinsight/ui/src/components/consents-settings/ConsentOption/ConsentOption.tsx +++ b/redisinsight/ui/src/components/consents-settings/ConsentOption/ConsentOption.tsx @@ -1,9 +1,10 @@ import React from 'react' -import { EuiLink, EuiSwitch, EuiText } from '@elastic/eui' +import { EuiSwitch, EuiText } from '@elastic/eui' import parse from 'html-react-parser' import { FlexItem, Row } from 'uiSrc/components/base/layout/flex' import { Spacer } from 'uiSrc/components/base/layout/spacer' +import { ItemDescription } from './components' import { IConsent } from '../ConsentsSettings' import styles from '../styles.module.scss' @@ -27,24 +28,6 @@ const ConsentOption = (props: Props) => { linkToPrivacyPolicy = false, } = props - const getText = () => ( - <> - {consent.description && parse(consent.description)} - {linkToPrivacyPolicy && ( - <> - - Privacy Policy - - . - - )} - - ) - return ( {isSettingsPage && consent.description && ( @@ -55,7 +38,7 @@ const ConsentOption = (props: Props) => { color="subdued" style={{ marginTop: '12px' }} > - {getText()} + @@ -83,7 +66,7 @@ const ConsentOption = (props: Props) => { color="subdued" style={{ marginTop: '12px' }} > - {getText()} + )} diff --git a/redisinsight/ui/src/components/consents-settings/ConsentOption/components/ItemDescription.tsx b/redisinsight/ui/src/components/consents-settings/ConsentOption/components/ItemDescription.tsx new file mode 100644 index 0000000000..7972e4d79a --- /dev/null +++ b/redisinsight/ui/src/components/consents-settings/ConsentOption/components/ItemDescription.tsx @@ -0,0 +1,26 @@ +import { EuiLink } from '@elastic/eui' +import parse from 'html-react-parser' +import React from 'react' + +interface ItemDescriptionProps { + description: string; + withLink: boolean; +} + +export const ItemDescription = ({ description, withLink }: ItemDescriptionProps) => ( + <> + {description && parse(description)} + {withLink && ( + <> + + Privacy Policy + + . + + )} + +) \ No newline at end of file diff --git a/redisinsight/ui/src/components/consents-settings/ConsentOption/components/index.tsx b/redisinsight/ui/src/components/consents-settings/ConsentOption/components/index.tsx new file mode 100644 index 0000000000..582795f58b --- /dev/null +++ b/redisinsight/ui/src/components/consents-settings/ConsentOption/components/index.tsx @@ -0,0 +1,3 @@ +import { ItemDescription } from './ItemDescription' + +export { ItemDescription } \ No newline at end of file