Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
da379ba
RI-7091 - Add an environment variable to skip the EULA screen - updat…
May 23, 2025
949e2c4
RI-7091 - Add an environment variable to skip the EULA screen - updat…
KIvanow May 23, 2025
4c0f105
RI-7091 - Add an environment variable to skip the EULA screen - updat…
KIvanow May 23, 2025
eaff41e
RI-7091 - Add an environment variable to skip the EULA screen - fixed…
KIvanow May 27, 2025
a461c72
RI-7091 - Add an environment variable to skip the EULA screen - fixed…
KIvanow May 27, 2025
0b2993b
RI-7091 - Add an environment variable to skip the EULA screen - fixed…
KIvanow May 27, 2025
15be851
RI-7091 - Add an environment variable to skip the EULA screen - fixed…
KIvanow May 27, 2025
c82e8d8
RI-7091 - Add an environment variable to skip the EULA screen - fixed…
KIvanow May 27, 2025
1e8c099
RI-7091 - Add an environment variable to skip the EULA screen - fixed…
KIvanow May 27, 2025
8fc0333
RI-7091 fix regular autodiscovery
ArtemHoruzhenko May 28, 2025
fc13b7a
Merge pull request #4589 from RedisInsight/feature/RI-7091---autodisc…
May 28, 2025
a81ed32
RI-7091 - Add an environment variable to skip the EULA screen - testi…
May 28, 2025
5c49cbd
testing delaying of the autodiscovery as a way to avoid the odd race …
May 28, 2025
3f07f39
removed setImmediate to check
May 28, 2025
77057c4
removed setTimeouts
KIvanow May 28, 2025
5f4ffd3
RI-7091 - extra logs and removed extra code
May 29, 2025
3b92942
-
May 29, 2025
6f1ff6a
-
KIvanow May 30, 2025
c6f11ba
Merge pull request #4599 from RedisInsight/RI-7091---testig-different…
May 30, 2025
ea03c96
RI-7091 - Add an environment variable to skip the EULA screen - fixed…
KIvanow Jun 2, 2025
b5e238d
RI-7091 - Add an environment variable to skip the EULA screen - added…
Jun 3, 2025
55bf392
RI-7091 - Add an environment variable to skip the EULA screen - added…
Jun 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions redisinsight/api/src/constants/agreements-spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"required": false,
"editable": true,
"disabled": false,
"linkToPrivacyPolicy": true,
"category": "privacy",
"since": "1.0.1",
"title": "Usage Data",
Expand All @@ -19,6 +20,7 @@
"required": false,
"editable": true,
"disabled": false,
"linkToPrivacyPolicy": false,
"category": "notifications",
"since": "1.0.6",
"title": "Notification",
Expand All @@ -37,6 +39,7 @@
"required": false,
"editable": true,
"disabled": false,
"linkToPrivacyPolicy": false,
"category": "privacy",
"since": "1.0.3",
"title": "Encryption",
Expand All @@ -49,6 +52,7 @@
"required": false,
"editable": true,
"disabled": true,
"linkToPrivacyPolicy": false,
"category": "privacy",
"since": "1.0.3",
"title": "Encryption",
Expand All @@ -61,6 +65,7 @@
"required": false,
"editable": true,
"disabled": true,
"linkToPrivacyPolicy": false,
"category": "privacy",
"since": "1.0.5",
"title": "Encryption",
Expand All @@ -75,6 +80,7 @@
"required": true,
"editable": false,
"disabled": false,
"linkToPrivacyPolicy": false,
"since": "1.0.4",
"title": "Server Side Public License",
"label": "I have read and understood the Terms",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class LocalDatabaseDiscoveryService extends DatabaseDiscoveryService {
firstRun?: boolean,
): Promise<void> {
try {
// no need to auto discover for Redis Stack
// No need to auto discover for Redis Stack - quick check
if (SERVER_CONFIG.buildType === 'REDIS_STACK') {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,44 @@ describe('EncryptionService', () => {
});
});

describe('isEncryptionAvailable', () => {
it('should return true when multiple strategies are available (KEYTAR and PLAIN)', async () => {
keytarEncryptionStrategy.isAvailable.mockResolvedValueOnce(true);
keyEncryptionStrategy.isAvailable.mockResolvedValueOnce(false);

const result = await service.isEncryptionAvailable();

expect(result).toBe(true);
});

it('should return true when multiple strategies are available (KEY and PLAIN)', async () => {
keytarEncryptionStrategy.isAvailable.mockResolvedValueOnce(false);
keyEncryptionStrategy.isAvailable.mockResolvedValueOnce(true);

const result = await service.isEncryptionAvailable();

expect(result).toBe(true);
});

it('should return true when all strategies are available (KEY, KEYTAR and PLAIN)', async () => {
keytarEncryptionStrategy.isAvailable.mockResolvedValueOnce(true);
keyEncryptionStrategy.isAvailable.mockResolvedValueOnce(true);

const result = await service.isEncryptionAvailable();

expect(result).toBe(true);
});

it('should return false when only PLAIN strategy is available', async () => {
keytarEncryptionStrategy.isAvailable.mockResolvedValueOnce(false);
keyEncryptionStrategy.isAvailable.mockResolvedValueOnce(false);

const result = await service.isEncryptionAvailable();

expect(result).toBe(false);
});
});

describe('getEncryptionStrategy', () => {
it('Should return KEYTAR strategy based on app agreements', async () => {
expect(await service.getEncryptionStrategy()).toEqual(
Expand Down
2 changes: 1 addition & 1 deletion redisinsight/api/src/modules/init/local.init.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class LocalInitService extends InitService {
await this.initAnalytics(firstStart);
await this.featureService.recalculateFeatureFlags(sessionMetadata);
await this.redisClientFactory.init();
await this.databaseDiscoveryService.discover(sessionMetadata);
await this.databaseDiscoveryService.discover(sessionMetadata, firstStart);
}

async initAnalytics(firstStart: boolean) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,54 @@ describe('LocalAgreementsRepository', () => {
data: undefined,
});
});
it('should create new agreements when entity exists but has no data', async () => {
// Mock an entity that exists but has no data property
const entityWithoutData = Object.assign(new AgreementsEntity(), {
id: mockUserId,
version: '1.0.0',
data: undefined, // This should trigger the !entity?.data check
});

repository.findOneBy.mockResolvedValueOnce(entityWithoutData);

const result = await service.getOrCreate(mockSessionMetadata);

// Verify that save was called to create a new entity
expect(repository.save).toHaveBeenCalledWith({
id: 1,
data: undefined,
});

expect(result).toEqual({
...mockAgreements,
version: undefined,
data: undefined,
});
});
it('should create new agreements when entity exists but has empty string data', async () => {
// Mock an entity that exists but has empty string data
const entityWithEmptyData = Object.assign(new AgreementsEntity(), {
id: mockUserId,
version: '1.0.0',
data: '', // This should also trigger the !entity?.data check
});

repository.findOneBy.mockResolvedValueOnce(entityWithEmptyData);

const result = await service.getOrCreate(mockSessionMetadata);

// Verify that save was called to create a new entity
expect(repository.save).toHaveBeenCalledWith({
id: 1,
data: undefined,
});

expect(result).toEqual({
...mockAgreements,
version: undefined,
data: undefined,
});
});
it('should fail to create with unique constraint and return existing', async () => {
repository.findOneBy.mockResolvedValueOnce(null);
repository.findOneBy.mockResolvedValueOnce(mockAgreements);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ export class LocalAgreementsRepository extends AgreementsRepository {

async getOrCreate(
sessionMetadata: SessionMetadata,
defaultOptions: DefaultAgreementsOptions = {}
defaultOptions: DefaultAgreementsOptions = {},
): Promise<Agreements> {
let entity = await this.repository.findOneBy({});
if (!entity) {
if (!entity?.data) {
try {
entity = await this.repository.save(
classToClass(AgreementsEntity, plainToInstance(Agreements, {
Expand Down
3 changes: 1 addition & 2 deletions redisinsight/api/src/modules/settings/settings.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class SettingsService {

let defaultOptions: object;
if (SERVER_CONFIG.acceptTermsAndConditions) {
const isEncryptionAvailable = await this.encryptionService.isEncryptionAvailable();
const isEncryptionAvailable = await this.encryptionService.isEncryptionAvailable();

defaultOptions = {
data: {
Expand All @@ -84,7 +84,6 @@ export class SettingsService {
sessionMetadata,
);


return classToClass(GetAppSettingsResponse, {
...settings?.data,
acceptTermsAndConditionsOverwritten: SERVER_CONFIG.acceptTermsAndConditions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const agreementItemSchema = Joi.object().keys({
category: Joi.string().optional(),
description: Joi.string().optional(),
requiredText: Joi.string().optional(),
linkToPrivacyPolicy: Joi.boolean().required(),
});

const responseSchema = Joi.object()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import React from 'react'
import { render, screen, fireEvent } from 'uiSrc/utils/test-utils'
import ConsentOption from './ConsentOption'
import { IConsent } from '../ConsentsSettings'

const mockConsent: IConsent = {
agreementName: 'analytics',
title: 'Analytics',
label: 'Share usage data',
description: 'Help us improve Redis Insight by sharing usage data.',
required: false,
editable: true,
disabled: false,
defaultValue: false,
displayInSetting: true,
since: '1.0.0',
linkToPrivacyPolicy: false,
}

const mockOnChangeAgreement = jest.fn()

const defaultProps = {
consent: mockConsent,
onChangeAgreement: mockOnChangeAgreement,
checked: false,
}

describe('ConsentOption', () => {
beforeEach(() => {
jest.clearAllMocks()
})

it('should render', () => {
expect(render(<ConsentOption {...defaultProps} />)).toBeTruthy()
})

it('should render switch with correct test id', () => {
render(<ConsentOption {...defaultProps} />)
expect(screen.getByTestId('switch-option-analytics')).toBeInTheDocument()
})

it('should call onChangeAgreement when switch is clicked', () => {
render(<ConsentOption {...defaultProps} />)

fireEvent.click(screen.getByTestId('switch-option-analytics'))

expect(mockOnChangeAgreement).toHaveBeenCalledWith(true, 'analytics')
})

it('should render description without privacy policy link when linkToPrivacyPolicy is false', () => {
const consentWithDescription = {
...mockConsent,
description: 'Help us improve Redis Insight by sharing usage data.',
linkToPrivacyPolicy: false,
}

render(<ConsentOption {...defaultProps} consent={consentWithDescription} />)

expect(screen.getByText('Help us improve Redis Insight by sharing usage data.')).toBeInTheDocument()
expect(screen.queryByText('Privacy Policy')).not.toBeInTheDocument()
})

it('should render description with privacy policy link when linkToPrivacyPolicy is true', () => {
const consentWithPrivacyLink = {
...mockConsent,
description: 'Help us improve Redis Insight by sharing usage data.',
linkToPrivacyPolicy: true,
}

render(<ConsentOption {...defaultProps} consent={consentWithPrivacyLink} />)

// Verify that the Privacy Policy link is rendered
expect(screen.getByText('Privacy Policy')).toBeInTheDocument()

const privacyPolicyLink = screen.getByText('Privacy Policy')
expect(privacyPolicyLink.closest('a')).toHaveAttribute(
'href',
'https://redis.io/legal/privacy-policy/?utm_source=redisinsight&utm_medium=app&utm_campaign=telemetry'
)
})

it('should render description with privacy policy link on settings page when linkToPrivacyPolicy is true', () => {
const consentWithPrivacyLink = {
...mockConsent,
description: 'Help us improve Redis Insight by sharing usage data.',
linkToPrivacyPolicy: true,
}

render(<ConsentOption {...defaultProps} consent={consentWithPrivacyLink} isSettingsPage />)

// Verify that the Privacy Policy link is rendered
expect(screen.getByText('Privacy Policy')).toBeInTheDocument()
})

it('should not render privacy policy link on settings page when linkToPrivacyPolicy is false', () => {
const consentWithoutPrivacyLink = {
...mockConsent,
description: 'Help us improve Redis Insight by sharing usage data.',
linkToPrivacyPolicy: false,
}

render(<ConsentOption {...defaultProps} consent={consentWithoutPrivacyLink} isSettingsPage />)

expect(screen.getByText('Help us improve Redis Insight by sharing usage data.')).toBeInTheDocument()
expect(screen.queryByText('Privacy Policy')).not.toBeInTheDocument()
})

it('should render disabled switch when consent is disabled', () => {
const disabledConsent = {
...mockConsent,
disabled: true,
}

render(<ConsentOption {...defaultProps} consent={disabledConsent} />)

const switchElement = screen.getByTestId('switch-option-analytics')
expect(switchElement).toBeDisabled()
})

it('should render checked switch when checked prop is true', () => {
render(<ConsentOption {...defaultProps} checked />)

const switchElement = screen.getByTestId('switch-option-analytics')
expect(switchElement).toBeChecked()
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ interface Props {
checked: boolean
isSettingsPage?: boolean
withoutSpacer?: boolean
linkToPrivacyPolicy?: boolean
}

const ConsentOption = (props: Props) => {
Expand All @@ -25,7 +24,6 @@ const ConsentOption = (props: Props) => {
checked,
isSettingsPage = false,
withoutSpacer = false,
linkToPrivacyPolicy = false,
} = props

return (
Expand All @@ -38,7 +36,7 @@ const ConsentOption = (props: Props) => {
color="subdued"
style={{ marginTop: '12px' }}
>
<ItemDescription description={consent.description} withLink={linkToPrivacyPolicy} />
<ItemDescription description={consent.description} withLink={consent.linkToPrivacyPolicy} />
</EuiText>
<Spacer size="m" />
</>
Expand Down Expand Up @@ -66,7 +64,7 @@ const ConsentOption = (props: Props) => {
color="subdued"
style={{ marginTop: '12px' }}
>
<ItemDescription description={consent.description} withLink={linkToPrivacyPolicy} />
<ItemDescription description={consent.description} withLink={consent.linkToPrivacyPolicy} />
</EuiText>
)}
</FlexItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ const ConsentsPrivacy = () => {
onChangeAgreement={onChangeAgreement}
isSettingsPage
key={consent.agreementName}
linkToPrivacyPolicy
/>
))}
</div>
Expand Down
Loading
Loading