Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,18 @@ export class StreamsApp {
return targetCondition.getByRole('button', { name: 'Create nested step' });
}

async getConditionContextMenuButton(pos: number) {
const conditions = await this.getConditionsListItems();
const targetCondition = conditions[pos];

const allButtons = await targetCondition
.getByTestId('streamsAppStreamDetailEnrichmentStepContextMenuButton')
.all();

// Return the condition's context menu button, not nested conditions / actions.
return allButtons[0];
}

// Gets the first level of nested steps under a condition at position 'pos'
async getConditionNestedStepsList(pos: number) {
const conditions = await this.getConditionsListItems();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,353 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { expect } from '@kbn/scout';
import { test } from '../../../fixtures';
import { generateLogsData } from '../../../fixtures/generators';

test.describe(
'Streams data processing permissions - viewer role (no simulate, no manage)',
{ tag: ['@ess', '@svlOblt'] },
() => {
test.beforeAll(async ({ logsSynthtraceEsClient }) => {
await generateLogsData(logsSynthtraceEsClient)({ index: 'logs-generic-default' });
});

test.beforeEach(async ({ apiServices, browserAuth, pageObjects }) => {
// Setup as admin first to create processors
await browserAuth.loginAsAdmin();
await apiServices.streams.updateStreamProcessors('logs-generic-default', {
steps: [
{
action: 'grok',
from: 'message',
patterns: ['%{WORD:attributes.method}'],
},
],
});

// Now login as viewer for the actual test
await browserAuth.loginAsViewer();
await pageObjects.streams.gotoProcessingTab('logs-generic-default');
});

test.afterAll(async ({ logsSynthtraceEsClient }) => {
await logsSynthtraceEsClient.clean();
});

test('should NOT allow viewer to add processors (requires simulate privilege)', async ({
page,
}) => {
// Verify the "Create step" button is not visible (requires simulate)
const createStepButton = page.getByTestId('streamsAppStreamDetailEnrichmentCreateStepButton');
await expect(createStepButton).toBeHidden();
});

test('should NOT allow viewer to edit existing processors (requires simulate privilege)', async ({
pageObjects,
}) => {
// Verify processors are visible
expect(await pageObjects.streams.getProcessorsListItems()).toHaveLength(1);

// Verify edit button is disabled (requires simulate)
const editButton = await pageObjects.streams.getProcessorEditButton(0);
await expect(editButton).toBeDisabled();
});

test('should NOT allow viewer to duplicate processors (requires manage privilege)', async ({
pageObjects,
}) => {
// Verify processors are visible
expect(await pageObjects.streams.getProcessorsListItems()).toHaveLength(1);

// Verify duplicate button is disabled (requires manage)
const duplicateButton = await pageObjects.streams.getProcessorDuplicateButton(0);
await expect(duplicateButton).toBeDisabled();
});

test('should NOT allow viewer to delete processors (requires manage privilege)', async ({
page,
pageObjects,
}) => {
// Verify processors are visible
expect(await pageObjects.streams.getProcessorsListItems()).toHaveLength(1);

// Try to access the context menu
const processors = await pageObjects.streams.getProcessorsListItems();
const targetProcessor = processors[0];
await targetProcessor.getByRole('button', { name: 'Step context menu' }).click();

// Verify delete option is disabled (requires manage)
const deleteButton = page.getByTestId('stepContextMenuDeleteItem');
await expect(deleteButton).toBeDisabled();
});

test('should NOT allow viewer to add conditions (requires simulate privilege)', async ({
page,
}) => {
// Verify the create step button is not visible (requires simulate)
const createStepButton = page.getByTestId('streamsAppStreamDetailEnrichmentCreateStepButton');
await expect(createStepButton).toBeHidden();
});

test('should NOT show save changes button for viewer (requires manage privilege)', async ({
page,
}) => {
// Save changes button should not be visible (requires manage)
const saveButton = page.getByRole('button', { name: 'Save changes' });
await expect(saveButton).toBeHidden();
});
}
);

test.describe(
'Streams data processing permissions - editor role (no simulate, no manage)',
{ tag: ['@ess', '@svlOblt'] },
() => {
test.beforeAll(async ({ logsSynthtraceEsClient }) => {
await generateLogsData(logsSynthtraceEsClient)({ index: 'logs-generic-default' });
});

test.beforeEach(async ({ apiServices, browserAuth, pageObjects }) => {
// Setup as admin first to create processors
await browserAuth.loginAsAdmin();
await apiServices.streams.updateStreamProcessors('logs-generic-default', {
steps: [
{
action: 'grok',
from: 'message',
patterns: ['%{WORD:attributes.method}'],
},
{
action: 'set',
to: 'test_field',
value: 'test_value',
},
],
});

// Now login as editor for the actual test
await browserAuth.loginAs('editor');
await pageObjects.streams.gotoProcessingTab('logs-generic-default');
});

test.afterAll(async ({ logsSynthtraceEsClient }) => {
await logsSynthtraceEsClient.clean();
});

test('should NOT allow editor to add processors (requires simulate privilege)', async ({
page,
}) => {
// Verify the "Create step" button is not visible (requires simulate)
const createStepButton = page.getByTestId('streamsAppStreamDetailEnrichmentCreateStepButton');
await expect(createStepButton).toBeHidden();
});

test('should NOT allow editor to edit existing processors (requires simulate privilege)', async ({
pageObjects,
}) => {
// Verify processors are visible
expect(await pageObjects.streams.getProcessorsListItems()).toHaveLength(2);

// Verify edit button is disabled (requires simulate)
const editButton = await pageObjects.streams.getProcessorEditButton(0);
await expect(editButton).toBeDisabled();
});

test('should NOT allow editor to duplicate processors (requires manage privilege)', async ({
pageObjects,
}) => {
// Verify processors are visible
expect(await pageObjects.streams.getProcessorsListItems()).toHaveLength(2);

// Verify duplicate button is disabled (requires manage)
const duplicateButton = await pageObjects.streams.getProcessorDuplicateButton(0);
await expect(duplicateButton).toBeDisabled();
});

test('should NOT allow editor to delete processors (requires manage privilege)', async ({
page,
pageObjects,
}) => {
// Verify processors are visible
expect(await pageObjects.streams.getProcessorsListItems()).toHaveLength(2);

// Try to access the context menu
const processors = await pageObjects.streams.getProcessorsListItems();
const targetProcessor = processors[0];
await targetProcessor.getByRole('button', { name: 'Step context menu' }).click();

// Verify delete option is disabled (requires manage)
const deleteButton = page.getByTestId('stepContextMenuDeleteItem');
await expect(deleteButton).toBeDisabled();
});

test('should NOT show save changes button for editor (requires manage privilege)', async ({
page,
}) => {
// Save changes button should not be visible (requires manage)
const saveButton = page.getByRole('button', { name: 'Save changes' });
await expect(saveButton).toBeHidden();
});
}
);

test.describe(
'Streams data processing permissions - editor with conditions (no simulate, no manage)',
{ tag: ['@ess', '@svlOblt'] },
() => {
test.beforeAll(async ({ logsSynthtraceEsClient }) => {
await generateLogsData(logsSynthtraceEsClient)({ index: 'logs-generic-default' });
});

test.beforeEach(async ({ apiServices, browserAuth, pageObjects }) => {
// Setup as admin first to create conditions
await browserAuth.loginAsAdmin();
await apiServices.streams.updateStreamProcessors('logs-generic-default', {
steps: [
{
where: {
field: 'test_field',
contains: 'logs',
steps: [
{
action: 'grok',
from: 'message',
patterns: ['%{WORD:attributes.method}'],
},
],
},
},
],
});

// Now login as editor for the actual test
await browserAuth.loginAs('editor');
await pageObjects.streams.gotoProcessingTab('logs-generic-default');
});

test.afterAll(async ({ logsSynthtraceEsClient }) => {
await logsSynthtraceEsClient.clean();
});

test('should NOT allow editor to edit existing conditions (requires simulate privilege)', async ({
pageObjects,
}) => {
// Verify condition is visible
expect(await pageObjects.streams.getConditionsListItems()).toHaveLength(1);

// Verify edit button is disabled (requires simulate)
const editButton = await pageObjects.streams.getConditionEditButton(0);
await expect(editButton).toBeDisabled();
});

test('should NOT allow editor to delete conditions (requires manage privilege)', async ({
page,
pageObjects,
}) => {
// Verify condition is visible
expect(await pageObjects.streams.getConditionsListItems()).toHaveLength(1);

// Click the condition's own context menu button (not nested processor buttons)
const contextMenuButton = await pageObjects.streams.getConditionContextMenuButton(0);
await contextMenuButton.click();

// Verify delete option is disabled (requires manage)
const deleteButton = page.getByTestId('stepContextMenuDeleteItem');
await expect(deleteButton).toBeDisabled();
});

test('should NOT allow editor to add nested steps to conditions (requires simulate privilege)', async ({
pageObjects,
}) => {
// Verify condition is visible
expect(await pageObjects.streams.getConditionsListItems()).toHaveLength(1);

// Verify the "Create nested step" button is disabled (requires simulate)
const addNestedStepButton = await pageObjects.streams.getConditionAddStepMenuButton(0);
await expect(addNestedStepButton).toBeDisabled();
});
}
);

test.describe(
'Streams data processing permissions - viewer with conditions (no simulate, no manage)',
{ tag: ['@ess', '@svlOblt'] },
() => {
test.beforeAll(async ({ logsSynthtraceEsClient }) => {
await generateLogsData(logsSynthtraceEsClient)({ index: 'logs-generic-default' });
});

test.beforeEach(async ({ apiServices, browserAuth, pageObjects }) => {
// Setup as admin first to create conditions
await browserAuth.loginAsAdmin();
await apiServices.streams.updateStreamProcessors('logs-generic-default', {
steps: [
{
where: {
field: 'test_field',
contains: 'logs',
steps: [
{
action: 'grok',
from: 'message',
patterns: ['%{WORD:attributes.method}'],
},
],
},
},
],
});

// Now login as viewer for the actual test
await browserAuth.loginAsViewer();
await pageObjects.streams.gotoProcessingTab('logs-generic-default');
});

test.afterAll(async ({ logsSynthtraceEsClient }) => {
await logsSynthtraceEsClient.clean();
});

test('should NOT allow viewer to edit existing conditions (requires simulate privilege)', async ({
pageObjects,
}) => {
// Verify condition is visible
expect(await pageObjects.streams.getConditionsListItems()).toHaveLength(1);

// Verify edit button is disabled (requires simulate)
const editButton = await pageObjects.streams.getConditionEditButton(0);
await expect(editButton).toBeDisabled();
});

test('should NOT allow viewer to delete conditions (requires manage privilege)', async ({
page,
pageObjects,
}) => {
// Verify condition is visible
expect(await pageObjects.streams.getConditionsListItems()).toHaveLength(1);

// Click the condition's own context menu button (not nested processor buttons)
const contextMenuButton = await pageObjects.streams.getConditionContextMenuButton(0);
await contextMenuButton.click();

// Verify delete option is disabled (requires manage)
const deleteButton = page.getByTestId('stepContextMenuDeleteItem');
await expect(deleteButton).toBeDisabled();
});

test('should NOT allow viewer to add nested steps to conditions (requires simulate privilege)', async ({
pageObjects,
}) => {
// Verify condition is visible
expect(await pageObjects.streams.getConditionsListItems()).toHaveLength(1);

// Verify the "Create nested step" button is disabled (requires simulate)
const addNestedStepButton = await pageObjects.streams.getConditionAddStepMenuButton(0);
await expect(addNestedStepButton).toBeDisabled();
});
}
);