Skip to content

Commit 5bd49e0

Browse files
Merge branch 'main' into siem-ea-7920
2 parents ca94f7c + d5fc9b0 commit 5bd49e0

13 files changed

Lines changed: 386 additions & 49 deletions

File tree

.buildkite/ftr_configs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ enabled:
318318
- x-pack/test/functional/apps/transform/feature_controls/config.ts
319319
- x-pack/test/functional/apps/upgrade_assistant/config.ts
320320
- x-pack/test/functional/apps/uptime/config.ts
321+
- x-pack/test/functional/apps/user_profiles/config.ts
321322
- x-pack/test/functional/apps/visualize/config.ts
322323
- x-pack/test/functional/apps/watcher/config.ts
323324
- x-pack/test/functional/config_security_basic.ts

x-pack/plugins/security/public/account_management/user_profile/user_profile.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ const UserDetailsEditor: FunctionComponent<UserDetailsEditorProps> = ({ user })
138138
labelAppend={<OptionalText />}
139139
fullWidth
140140
>
141-
<FormField name="user.full_name" fullWidth />
141+
<FormField name="user.full_name" data-test-subj={'userProfileFullName'} fullWidth />
142142
</FormRow>
143143

144144
<FormRow
@@ -153,7 +153,7 @@ const UserDetailsEditor: FunctionComponent<UserDetailsEditorProps> = ({ user })
153153
labelAppend={<OptionalText />}
154154
fullWidth
155155
>
156-
<FormField type="email" name="user.email" fullWidth />
156+
<FormField type="email" name="user.email" data-test-subj={'userProfileEmail'} fullWidth />
157157
</FormRow>
158158
</EuiDescribedFormGroup>
159159
);
@@ -189,6 +189,7 @@ const UserSettingsEditor: FunctionComponent<UserSettingsEditorProps> = ({
189189
<EuiKeyPadMenuItem
190190
name={id}
191191
label={label}
192+
data-test-subj={`themeKeyPadItem${label}`}
192193
checkable="single"
193194
isSelected={idSelected === id}
194195
isDisabled={isThemeOverridden}
@@ -810,7 +811,11 @@ export const UserProfile: FunctionComponent<UserProfileProps> = ({ user, data })
810811
</Form>
811812
</KibanaPageTemplate.Section>
812813
{formChanges.count > 0 ? (
813-
<KibanaPageTemplate.BottomBar paddingSize="m" position="fixed">
814+
<KibanaPageTemplate.BottomBar
815+
paddingSize="m"
816+
position="fixed"
817+
data-test-subj={'userProfileBottomBar'}
818+
>
814819
<SaveChangesBottomBar />
815820
</KibanaPageTemplate.BottomBar>
816821
) : null}
@@ -974,6 +979,7 @@ export const SaveChangesBottomBar: FunctionComponent = () => {
974979
<EuiFlexItem grow={false}>
975980
<EuiButton
976981
onClick={formik.submitForm}
982+
data-test-subj="saveProfileChangesButton"
977983
isLoading={formik.isSubmitting}
978984
isDisabled={formik.submitCount > 0 && !formik.isValid}
979985
color="success"

x-pack/plugins/security_solution/server/lib/telemetry/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ export const TELEMETRY_CHANNEL_LISTS = 'security-lists-v2';
99

1010
export const TELEMETRY_CHANNEL_ENDPOINT_META = 'endpoint-metadata';
1111

12+
export const TELEMETRY_CHANNEL_ENDPOINT_ALERTS = 'alerts-endpoint';
13+
1214
export const TELEMETRY_CHANNEL_DETECTION_ALERTS = 'alerts-detections';
1315

1416
export const TELEMETRY_CHANNEL_TIMELINE = 'alerts-timeline';

x-pack/plugins/security_solution/server/lib/telemetry/tasks/diagnostic.test.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,10 @@ describe('diagnostics telemetry task test', () => {
3737
mockTelemetryEventsSender,
3838
testTaskExecutionPeriod
3939
);
40-
4140
expect(mockTelemetryReceiver.fetchDiagnosticAlerts).toHaveBeenCalledWith(
4241
testTaskExecutionPeriod.last,
4342
testTaskExecutionPeriod.current
4443
);
45-
46-
expect(mockTelemetryEventsSender.queueTelemetryEvents).toHaveBeenCalledWith(
47-
testDiagnosticsAlerts.hits.hits.flatMap((doc) => [doc._source])
48-
);
49-
expect(mockTelemetryEventsSender.sendOnDemand).toBeCalledTimes(1);
44+
expect(mockTelemetryEventsSender.sendOnDemand).toBeCalledTimes(2);
5045
});
5146
});

x-pack/plugins/security_solution/server/lib/telemetry/tasks/diagnostic.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type { ITelemetryEventsSender } from '../sender';
1111
import type { TelemetryEvent } from '../types';
1212
import type { ITelemetryReceiver } from '../receiver';
1313
import type { TaskExecutionPeriod } from '../task';
14-
import { TASK_METRICS_CHANNEL } from '../constants';
14+
import { TELEMETRY_CHANNEL_ENDPOINT_ALERTS, TASK_METRICS_CHANNEL } from '../constants';
1515

1616
export function createTelemetryDiagnosticsTaskConfig() {
1717
return {
@@ -49,14 +49,15 @@ export function createTelemetryDiagnosticsTaskConfig() {
4949
return 0;
5050
}
5151
tlog(logger, `Received ${hits.length} diagnostic alerts`);
52-
const diagAlerts: TelemetryEvent[] = hits.flatMap((h) =>
52+
const alerts: TelemetryEvent[] = hits.flatMap((h) =>
5353
h._source != null ? [h._source] : []
5454
);
55-
sender.queueTelemetryEvents(diagAlerts);
55+
56+
await sender.sendOnDemand(TELEMETRY_CHANNEL_ENDPOINT_ALERTS, alerts);
5657
await sender.sendOnDemand(TASK_METRICS_CHANNEL, [
5758
createTaskMetric(taskName, true, startTime),
5859
]);
59-
return diagAlerts.length;
60+
return alerts.length;
6061
} catch (err) {
6162
await sender.sendOnDemand(TASK_METRICS_CHANNEL, [
6263
createTaskMetric(taskName, false, startTime, err.message),

x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -423,49 +423,48 @@ export class SyntheticsService {
423423
};
424424

425425
for await (const result of finder.find()) {
426-
if (result.saved_objects.length === 0) {
427-
return;
428-
}
429-
try {
430-
if (!output) {
431-
output = await this.getOutput();
426+
if (result.saved_objects.length > 0) {
427+
try {
432428
if (!output) {
433-
sendErrorTelemetryEvents(service.logger, service.server.telemetry, {
434-
reason: 'API key is not valid.',
435-
message: 'Failed to push configs. API key is not valid.',
436-
type: 'invalidApiKey',
437-
stackVersion: service.server.stackVersion,
438-
});
439-
return;
429+
output = await this.getOutput();
430+
if (!output) {
431+
sendErrorTelemetryEvents(service.logger, service.server.telemetry, {
432+
reason: 'API key is not valid.',
433+
message: 'Failed to push configs. API key is not valid.',
434+
type: 'invalidApiKey',
435+
stackVersion: service.server.stackVersion,
436+
});
437+
return;
438+
}
440439
}
441-
}
442440

443-
const monitors = result.saved_objects.filter(({ error }) => !error);
444-
const formattedConfigs = this.normalizeConfigs(monitors, paramsBySpace);
441+
const monitors = result.saved_objects.filter(({ error }) => !error);
442+
const formattedConfigs = this.normalizeConfigs(monitors, paramsBySpace);
445443

446-
this.logger.debug(
447-
`${formattedConfigs.length} monitors will be pushed to synthetics service.`
448-
);
444+
this.logger.debug(
445+
`${formattedConfigs.length} monitors will be pushed to synthetics service.`
446+
);
449447

450-
formattedConfigs.forEach((monitor) => {
451-
monitor.locations.forEach((location) => {
452-
if (location.isServiceManaged) {
453-
bucketsByLocation[location.id]?.push(monitor);
454-
}
448+
formattedConfigs.forEach((monitor) => {
449+
monitor.locations.forEach((location) => {
450+
if (location.isServiceManaged) {
451+
bucketsByLocation[location.id]?.push(monitor);
452+
}
453+
});
455454
});
456-
});
457455

458-
await syncAllLocations(PER_PAGE);
459-
} catch (e) {
460-
sendErrorTelemetryEvents(service.logger, service.server.telemetry, {
461-
reason: 'Failed to push configs to service',
462-
message: e?.message,
463-
type: 'pushConfigsError',
464-
code: e?.code,
465-
status: e.status,
466-
stackVersion: service.server.stackVersion,
467-
});
468-
this.logger.error(e);
456+
await syncAllLocations(PER_PAGE);
457+
} catch (e) {
458+
sendErrorTelemetryEvents(service.logger, service.server.telemetry, {
459+
reason: 'Failed to push configs to service',
460+
message: e?.message,
461+
type: 'pushConfigsError',
462+
code: e?.code,
463+
status: e.status,
464+
stackVersion: service.server.stackVersion,
465+
});
466+
this.logger.error(e);
467+
}
469468
}
470469
}
471470

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { FtrConfigProviderContext } from '@kbn/test';
9+
10+
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
11+
const functionalConfig = await readConfigFile(require.resolve('../../config.base.js'));
12+
13+
return {
14+
...functionalConfig.getAll(),
15+
testFiles: [require.resolve('.')],
16+
};
17+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { FtrProviderContext } from '../../ftr_provider_context';
9+
10+
export default ({ loadTestFile }: FtrProviderContext) => {
11+
describe('User Profiles page', function () {
12+
loadTestFile(require.resolve('./user_profiles'));
13+
});
14+
};
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import expect from '@kbn/expect';
9+
import { FtrProviderContext } from '../../ftr_provider_context';
10+
11+
export default ({ getPageObjects }: FtrProviderContext) => {
12+
const pageObjects = getPageObjects(['common', 'userProfiles', 'settings']);
13+
14+
describe('User Profile Page', async () => {
15+
before(async () => {});
16+
17+
describe('Details', async () => {
18+
before(async () => {
19+
await pageObjects.common.navigateToApp('security_account');
20+
});
21+
22+
it('should set the full name', async () => {
23+
await pageObjects.userProfiles.setFullNameInputField('Test User 2');
24+
25+
await pageObjects.userProfiles.saveUserProfileChanges();
26+
27+
let toast = await pageObjects.common.closeToast();
28+
29+
expect(toast).to.be('Profile updated');
30+
31+
await pageObjects.userProfiles.setFullNameInputField('test user');
32+
33+
await pageObjects.userProfiles.saveUserProfileChanges();
34+
35+
toast = await pageObjects.common.closeToast();
36+
37+
expect(toast).to.be('Profile updated');
38+
});
39+
40+
it('should set the email', async () => {
41+
await pageObjects.userProfiles.setEmailInputField('test@test.com');
42+
43+
await pageObjects.userProfiles.saveUserProfileChanges();
44+
45+
let toast = await pageObjects.common.closeToast();
46+
47+
expect(toast).to.be('Profile updated');
48+
49+
await pageObjects.userProfiles.setEmailInputField('', true);
50+
51+
await pageObjects.userProfiles.saveUserProfileChanges();
52+
53+
toast = await pageObjects.common.closeToast();
54+
55+
expect(toast).to.be('Profile updated');
56+
});
57+
});
58+
59+
describe('Change Password', async () => {
60+
before(async () => {
61+
await pageObjects.common.navigateToApp('security_account');
62+
});
63+
64+
it('should set the current password and enter a new password, then submit', async () => {
65+
const changePasswordButton = await pageObjects.userProfiles.getChangePasswordButton();
66+
await changePasswordButton.click();
67+
68+
await pageObjects.userProfiles.setCurrentPasswordField('changeme');
69+
await pageObjects.userProfiles.setNewPasswordField('changeme2');
70+
await pageObjects.userProfiles.setConfirmPasswordField('changeme2');
71+
72+
const submitButton = await pageObjects.userProfiles.getChangePasswordFormSubmitButton();
73+
await submitButton.click();
74+
75+
const initialToast = await pageObjects.common.closeToast();
76+
77+
expect(initialToast).to.be('Password successfully changed');
78+
79+
await changePasswordButton.click();
80+
81+
await pageObjects.userProfiles.setCurrentPasswordField('changeme2');
82+
await pageObjects.userProfiles.setNewPasswordField('changeme');
83+
await pageObjects.userProfiles.setConfirmPasswordField('changeme');
84+
85+
await submitButton.click();
86+
87+
const resetToast = await pageObjects.common.closeToast();
88+
89+
expect(resetToast).to.be('Password successfully changed');
90+
});
91+
});
92+
93+
describe('Theme', async () => {
94+
it('should change theme based on the User Profile Theme control with default Adv. Settings value (light)', async () => {
95+
await pageObjects.common.navigateToApp('security_account');
96+
97+
const themeKeyPadMenu = await pageObjects.userProfiles.getThemeKeypadMenu();
98+
expect(themeKeyPadMenu).not.to.be(null);
99+
100+
await pageObjects.userProfiles.changeUserProfileTheme('Dark');
101+
const darkModeTag = await pageObjects.userProfiles.getThemeTag();
102+
expect(darkModeTag).to.be('v8dark');
103+
104+
await pageObjects.userProfiles.changeUserProfileTheme('Light');
105+
const lightModeTag = await pageObjects.userProfiles.getThemeTag();
106+
expect(lightModeTag).to.be('v8light');
107+
108+
await pageObjects.userProfiles.changeUserProfileTheme('Space default');
109+
const spaceDefaultModeTag = await pageObjects.userProfiles.getThemeTag();
110+
expect(spaceDefaultModeTag).to.be('v8light');
111+
});
112+
113+
it('should change theme based on the User Profile Theme control with default Adv. Settings value set to dark', async () => {
114+
await pageObjects.common.navigateToUrl('management', 'kibana/settings', {
115+
basePath: '',
116+
ensureCurrentUrl: false,
117+
shouldLoginIfPrompted: false,
118+
shouldUseHashForSubUrl: false,
119+
});
120+
121+
let advancedSetting = await pageObjects.settings.getAdvancedSettingCheckbox(
122+
'theme:darkMode'
123+
);
124+
expect(advancedSetting).to.be(null);
125+
126+
await pageObjects.settings.toggleAdvancedSettingCheckbox('theme:darkMode', true);
127+
advancedSetting = await pageObjects.settings.getAdvancedSettingCheckbox('theme:darkMode');
128+
expect(advancedSetting).to.be('true');
129+
130+
await pageObjects.common.navigateToApp('security_account');
131+
132+
let spaceDefaultModeTag = await pageObjects.userProfiles.getThemeTag();
133+
expect(spaceDefaultModeTag).to.be('v8dark');
134+
135+
await pageObjects.userProfiles.changeUserProfileTheme('Light');
136+
const lightModeTag = await pageObjects.userProfiles.getThemeTag();
137+
expect(lightModeTag).to.be('v8light');
138+
139+
await pageObjects.userProfiles.changeUserProfileTheme('Dark');
140+
const darkModeTag = await pageObjects.userProfiles.getThemeTag();
141+
expect(darkModeTag).to.be('v8dark');
142+
143+
await pageObjects.userProfiles.changeUserProfileTheme('Space default');
144+
spaceDefaultModeTag = await pageObjects.userProfiles.getThemeTag();
145+
expect(spaceDefaultModeTag).to.be('v8dark');
146+
147+
await pageObjects.common.navigateToUrl('management', 'kibana/settings', {
148+
basePath: '',
149+
ensureCurrentUrl: false,
150+
shouldLoginIfPrompted: false,
151+
shouldUseHashForSubUrl: false,
152+
});
153+
154+
await pageObjects.settings.toggleAdvancedSettingCheckbox('theme:darkMode', false);
155+
advancedSetting = await pageObjects.settings.getAdvancedSettingCheckbox('theme:darkMode');
156+
expect(advancedSetting).to.be(null);
157+
});
158+
});
159+
});
160+
};

0 commit comments

Comments
 (0)