This is an automated email from the ASF dual-hosted git repository.
riemer pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/streampipes.git
The following commit(s) were added to refs/heads/dev by this push:
new afc72791d7 feat(#3944): Improve permission handling (#3946)
afc72791d7 is described below
commit afc72791d729687a0f429ca5845af491ae4ba6e5
Author: Philipp Zehnder <[email protected]>
AuthorDate: Thu Nov 20 16:43:41 2025 +0100
feat(#3944): Improve permission handling (#3946)
---
.../manager/pipeline/PipelineManager.java | 68 ++++++---
.../streampipes/rest/impl/ResetResource.java | 9 ++
ui/cypress/support/utils/UserUtils.ts | 25 +++-
ui/cypress/support/utils/connect/ConnectUtils.ts | 1 -
ui/cypress/support/utils/pipeline/PipelineBtns.ts | 4 +
ui/cypress/support/utils/pipeline/PipelineUtils.ts | 13 +-
ui/cypress/support/utils/user/PermissionUtils.ts | 31 ++++
ui/cypress/support/utils/user/UserBtns.ts | 16 +-
...t.spec.ts => testAddAssetOnResourceCreation.ts} | 2 +-
.../userManagement/testGroupManagement.spec.ts | 13 +-
.../userManagement/testUserRoleConnect.spec.ts | 136 +++++++++++++----
.../userManagement/testUserRolePipeline.spec.ts | 166 +++++++++++++++------
.../object-permission-dialog.component.html | 20 ++-
.../edit-user-dialog.component.html | 1 +
.../security-user-config.component.html | 4 +-
.../pipeline-element-discovery.component.html | 8 +-
16 files changed, 390 insertions(+), 127 deletions(-)
diff --git
a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/PipelineManager.java
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/PipelineManager.java
index d2114f47a9..4bf64286fb 100644
---
a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/PipelineManager.java
+++
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/PipelineManager.java
@@ -26,6 +26,7 @@ import
org.apache.streampipes.model.base.NamedStreamPipesEntity;
import org.apache.streampipes.model.client.user.Permission;
import org.apache.streampipes.model.pipeline.Pipeline;
import org.apache.streampipes.model.pipeline.PipelineOperationStatus;
+import org.apache.streampipes.resource.management.CrudResourceManager;
import org.apache.streampipes.resource.management.NotificationsResourceManager;
import org.apache.streampipes.storage.api.IPermissionStorage;
import org.apache.streampipes.storage.api.IPipelineStorage;
@@ -46,7 +47,9 @@ public class PipelineManager {
* @return all pipelines
*/
public static List<Pipeline> getAllPipelines() {
- return
StorageDispatcher.INSTANCE.getNoSqlStore().getPipelineStorageAPI().findAll();
+ return StorageDispatcher.INSTANCE.getNoSqlStore()
+ .getPipelineStorageAPI()
+ .findAll();
}
/**
@@ -66,12 +69,14 @@ public class PipelineManager {
* @param pipeline to be added
* @return pipelineId of the stored pipeline
*/
- public static String addPipeline(String principalSid,
- Pipeline pipeline) {
+ public static String addPipeline(
+ String principalSid,
+ Pipeline pipeline
+ ) {
String pipelineId = Objects.isNull(pipeline.getPipelineId())
- ? UUIDGenerator.generateUuid()
- : pipeline.getPipelineId();
+ ? UUIDGenerator.generateUuid()
+ : pipeline.getPipelineId();
preparePipelineBasics(principalSid, pipeline, pipelineId);
new PipelineStorageService(pipeline).addPipeline();
@@ -101,8 +106,10 @@ public class PipelineManager {
* containers could be reached
* @return pipeline status of the start operation
*/
- public static PipelineOperationStatus stopPipeline(String pipelineId,
- boolean forceStop) {
+ public static PipelineOperationStatus stopPipeline(
+ String pipelineId,
+ boolean forceStop
+ ) {
Pipeline pipeline = getPipeline(pipelineId);
return new PipelineExecutor(pipeline).stopPipeline(forceStop);
@@ -114,16 +121,20 @@ public class PipelineManager {
* @param pipelineId of pipeline to be deleted
*/
public static void deletePipeline(String pipelineId) {
+ var pipelineCrudResourceManager = new
CrudResourceManager<>(getPipelineStorage(), Pipeline.class);
+
var pipeline = getPipeline(pipelineId);
if (Objects.nonNull(pipeline)) {
- getPipelineStorage().deleteElementById(pipelineId);
+ pipelineCrudResourceManager.delete(pipelineId);
new
NotificationsResourceManager().deleteNotificationsForPipeline(pipeline);
}
}
public static List<PipelineOperationStatus> stopAllPipelines(boolean
forceStop) {
List<PipelineOperationStatus> status = new ArrayList<>();
- List<Pipeline> pipelines =
StorageDispatcher.INSTANCE.getNoSqlStore().getPipelineStorageAPI().findAll();
+ List<Pipeline> pipelines = StorageDispatcher.INSTANCE.getNoSqlStore()
+
.getPipelineStorageAPI()
+ .findAll();
pipelines.forEach(p -> {
if (p.isRunning()) {
@@ -140,36 +151,49 @@ public class PipelineManager {
* @return all pipelines containing the element
*/
public static List<Pipeline> getPipelinesContainingElements(String
elementId) {
- return PipelineManager.getAllPipelines().stream()
- .filter(pipeline -> mergePipelineElement(pipeline)
- .anyMatch(el -> el.getElementId().equals(elementId)))
- .collect(Collectors.toList());
+ return PipelineManager.getAllPipelines()
+ .stream()
+ .filter(pipeline -> mergePipelineElement(pipeline)
+ .anyMatch(el -> el.getElementId()
+ .equals(elementId)))
+ .collect(Collectors.toList());
}
private static Stream<? extends NamedStreamPipesEntity>
mergePipelineElement(Pipeline pipeline) {
return Stream.concat(
Stream.concat(
- pipeline.getStreams().stream(),
- pipeline.getSepas().stream()),
- pipeline.getActions().stream());
+ pipeline.getStreams()
+ .stream(),
+ pipeline.getSepas()
+ .stream()
+ ),
+ pipeline.getActions()
+ .stream()
+ );
}
- private static void preparePipelineBasics(String username,
+ private static void preparePipelineBasics(
+ String username,
Pipeline pipeline,
- String pipelineId) {
+ String pipelineId
+ ) {
pipeline.setPipelineId(pipelineId);
pipeline.setRunning(false);
pipeline.setCreatedByUser(username);
pipeline.setCreatedAt(new Date().getTime());
- pipeline.getSepas().forEach(processor ->
processor.setCorrespondingUser(username));
- pipeline.getActions().forEach(action ->
action.setCorrespondingUser(username));
+ pipeline.getSepas()
+ .forEach(processor -> processor.setCorrespondingUser(username));
+ pipeline.getActions()
+ .forEach(action -> action.setCorrespondingUser(username));
}
private static IPipelineStorage getPipelineStorage() {
- return StorageDispatcher.INSTANCE.getNoSqlStore().getPipelineStorageAPI();
+ return StorageDispatcher.INSTANCE.getNoSqlStore()
+ .getPipelineStorageAPI();
}
private static IPermissionStorage getPermissionStorage() {
- return StorageDispatcher.INSTANCE.getNoSqlStore().getPermissionStorage();
+ return StorageDispatcher.INSTANCE.getNoSqlStore()
+ .getPermissionStorage();
}
}
\ No newline at end of file
diff --git
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/ResetResource.java
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/ResetResource.java
index 4596dbb7b3..bf89dc7778 100644
---
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/ResetResource.java
+++
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/ResetResource.java
@@ -43,6 +43,8 @@ public class ResetResource extends
AbstractAuthGuardedRestResource {
public ResponseEntity<SuccessMessage> reset() {
ResetManagement.reset(getAuthenticatedUsername());
var userStorage = getUserStorage();
+
+
// Delete all users other than current user (admin) and their resources
var allUsers = new ArrayList<Principal>(userStorage.getAllUsers());
for (var user : allUsers) {
@@ -52,6 +54,13 @@ public class ResetResource extends
AbstractAuthGuardedRestResource {
userStorage.deleteUser(user.getPrincipalId());
}
}
+
+ // Delete all user Groups
+ var allUserGroups = getNoSqlStorage().getUserGroupStorage().findAll();
+ for (var group : allUserGroups) {
+
getNoSqlStorage().getUserGroupStorage().deleteElementById(group.getElementId());
+ }
+
var message = Notifications.success("Reset of system successfully
performed");
return ok(message);
}
diff --git a/ui/cypress/support/utils/UserUtils.ts
b/ui/cypress/support/utils/UserUtils.ts
index e5557d0ad1..249a2e6322 100644
--- a/ui/cypress/support/utils/UserUtils.ts
+++ b/ui/cypress/support/utils/UserUtils.ts
@@ -20,6 +20,7 @@ import { User } from '../model/User';
import { UserBuilder } from '../builder/UserBuilder';
import { UserRole } from '../../../src/app/_enums/user-role.enum';
import { UserBtns } from './user/UserBtns';
+import { ConfigurationBtns } from './configuration/ConfigurationBtns';
export class UserUtils {
public static adminUser =
UserBuilder.create('[email protected]')
@@ -76,7 +77,7 @@ export class UserUtils {
0,
);
- UserBtns.editUserBtn(user.email);
+ UserBtns.editUserBtn(user.name);
UserBtns.userRoleCheckbox(role).click();
@@ -117,4 +118,26 @@ export class UserUtils {
UserBtns.deleteUserBtn(user.name).click();
UserBtns.confirmDeleteBtn().click();
}
+
+ public static createGroup(name: string, ...roles: UserRole[]) {
+ this.goToUserConfiguration();
+
+ ConfigurationBtns.newUserGroupBtn().click();
+ ConfigurationBtns.inputGroupName(name);
+ roles.forEach(role => {
+ cy.get(`input[value="${role}"]`).check();
+ });
+ UserBtns.saveEditUserBtn().click();
+ }
+
+ public static addGroupToUser(groupName: string, name: string) {
+ this.goToUserConfiguration();
+ UserBtns.editUserBtn(name);
+
+ cy.dataCy('group-' + groupName)
+ .children()
+ .click();
+
+ UserBtns.saveEditUserBtn().click();
+ }
}
diff --git a/ui/cypress/support/utils/connect/ConnectUtils.ts
b/ui/cypress/support/utils/connect/ConnectUtils.ts
index 4c2f556905..fced3e0d72 100644
--- a/ui/cypress/support/utils/connect/ConnectUtils.ts
+++ b/ui/cypress/support/utils/connect/ConnectUtils.ts
@@ -279,7 +279,6 @@ export class ConnectUtils {
}
public static editAsset(assetNameList = []) {
- //cy.dataCy('show-asset-checkbox').click();
cy.get('mat-tree.asset-tree', { timeout: 10000 }).should('exist');
assetNameList.forEach(assetName => {
diff --git a/ui/cypress/support/utils/pipeline/PipelineBtns.ts
b/ui/cypress/support/utils/pipeline/PipelineBtns.ts
index 41f2f923f6..1ba9c36db7 100644
--- a/ui/cypress/support/utils/pipeline/PipelineBtns.ts
+++ b/ui/cypress/support/utils/pipeline/PipelineBtns.ts
@@ -36,6 +36,10 @@ export class PipelineBtns {
return cy.dataCy('pipelines-navigate-to-editor');
}
+ public static spPipelineElementSelection() {
+ return cy.dataCy('sp-pipeline-element-selection', { timeout: 10000 });
+ }
+
public static editorAddPipelineElement() {
return cy.dataCy('sp-editor-add-pipeline-element', { timeout: 10000 });
}
diff --git a/ui/cypress/support/utils/pipeline/PipelineUtils.ts
b/ui/cypress/support/utils/pipeline/PipelineUtils.ts
index 62d76cd996..7d90bde728 100644
--- a/ui/cypress/support/utils/pipeline/PipelineUtils.ts
+++ b/ui/cypress/support/utils/pipeline/PipelineUtils.ts
@@ -94,11 +94,16 @@ export class PipelineUtils {
PipelineBtns.pipelinesToEditor().click();
}
+ public static checkDataStreamExists(dataSourceName: string) {
+ PipelineBtns.spPipelineElementSelection().should('be.visible');
+ PipelineBtns.editorAddPipelineElement().click();
+ cy.dataCy(dataSourceName).should('exist');
+ cy.dataCy('cancel-pipeline-element-discovery').click();
+ }
+
public static selectDataStream(pipelineInput: PipelineInput) {
// Select a stream
- cy.dataCy('sp-pipeline-element-selection', { timeout: 10000 }).should(
- 'be.visible',
- );
+ PipelineBtns.spPipelineElementSelection().should('be.visible');
PipelineBtns.editorAddPipelineElement().click();
cy.dataCy(pipelineInput.dataSource, { timeout: 10000 }).click();
}
@@ -222,7 +227,7 @@ export class PipelineUtils {
// The wait is needed because the default value is the
no-table-entries element.
// It must be waited till the data is loaded. Once a better
solution is found, this can be removed.
cy.wait(1000);
- cy.dataCy('no-table-entries').should('be.visible');
+ cy.dataCy('no-table-entries').should('have.length', 2);
} else {
PipelineBtns.statusPipeline().should('have.length', amount);
}
diff --git a/ui/cypress/support/utils/user/PermissionUtils.ts
b/ui/cypress/support/utils/user/PermissionUtils.ts
index 3242960d22..4365eed24f 100644
--- a/ui/cypress/support/utils/user/PermissionUtils.ts
+++ b/ui/cypress/support/utils/user/PermissionUtils.ts
@@ -25,6 +25,13 @@ export class PermissionUtils {
cy.dataCy('open-manage-permissions').click();
}
+ public static changeOwnership(resourceName: string, email: string) {
+ PermissionUtils.openManagePermissions(resourceName);
+ cy.dataCy('owner-select').click();
+ cy.get(`[data-cy="owner-option-${email}"]`, { timeout: 10000
}).click();
+ PermissionUtils.save();
+ }
+
public static markElementAsPublic(resourceName: string) {
PermissionUtils.openManagePermissions(resourceName);
StaticPropertyUtils.clickCheckbox('permission-public-element');
@@ -40,7 +47,31 @@ export class PermissionUtils {
PermissionUtils.save();
}
+ public static authorizeGroup(resourceName: string, groupName: string) {
+ PermissionUtils.openManagePermissions(resourceName);
+ cy.dataCy('authorized-group').type(groupName);
+ cy.get(`[data-cy="group-option-${groupName}"]`).click();
+
+ PermissionUtils.save();
+ }
+
public static save() {
cy.dataCy('sp-manage-permissions-save').click();
}
+
+ public static cancel() {
+ cy.dataCy('sp-manage-permissions-cancel').click();
+ }
+
+ public static validateUserCanNotChangePermissions(resourceName: string) {
+ PermissionUtils.openManagePermissions(resourceName);
+ cy.dataCy('warning-permissions-managed-by-owner').should('exist');
+ PermissionUtils.cancel();
+ }
+
+ public static validateUserCanChangePermissions(resourceName: string) {
+ PermissionUtils.openManagePermissions(resourceName);
+ cy.dataCy('permission-public-element').should('exist');
+ PermissionUtils.cancel();
+ }
}
diff --git a/ui/cypress/support/utils/user/UserBtns.ts
b/ui/cypress/support/utils/user/UserBtns.ts
index 6aa8c87052..0f75a04eec 100644
--- a/ui/cypress/support/utils/user/UserBtns.ts
+++ b/ui/cypress/support/utils/user/UserBtns.ts
@@ -17,22 +17,18 @@
*/
export class UserBtns {
- public static editUserBtn(username) {
- cy.get('[data-cy="security-user-config"]')
- .find('tr')
- .contains('b', username)
- .closest('tr')
- .within(() => {
- cy.get('[data-cy="user-edit-btn"]')
- .should('be.visible')
- .click();
- });
+ public static editUserBtn(name: string) {
+ cy.dataCy(`user-edit-${name}`).click();
}
public static userRoleCheckbox(role) {
return cy.dataCy('role-' + role).children();
}
+ public static groupCheckbox(group: string) {
+ return cy.dataCy('group-' + group).children();
+ }
+
public static saveEditUserBtn() {
return cy.dataCy('sp-element-edit-user-save');
}
diff --git a/ui/cypress/tests/userManagement/testUserRoleAsset.spec.ts
b/ui/cypress/tests/userManagement/testAddAssetOnResourceCreation.ts
similarity index 98%
rename from ui/cypress/tests/userManagement/testUserRoleAsset.spec.ts
rename to ui/cypress/tests/userManagement/testAddAssetOnResourceCreation.ts
index ece8fba06d..a27908b732 100644
--- a/ui/cypress/tests/userManagement/testUserRoleAsset.spec.ts
+++ b/ui/cypress/tests/userManagement/testAddAssetOnResourceCreation.ts
@@ -27,7 +27,7 @@ import { DataExplorerUtils } from
'../../support/utils/dataExplorer/DataExplorer
import { DataExplorerBtns } from
'../../support/utils/dataExplorer/DataExplorerBtns';
import { ConnectBtns } from '../../support/utils/connect/ConnectBtns';
-describe('Test User Roles for Pipelines', () => {
+describe('Test that resources can be added to assets on creation', () => {
let newUser;
beforeEach('Setup Test', () => {
cy.initStreamPipesTest();
diff --git a/ui/cypress/tests/userManagement/testGroupManagement.spec.ts
b/ui/cypress/tests/userManagement/testGroupManagement.spec.ts
index 97a2302daa..07bdd5daca 100644
--- a/ui/cypress/tests/userManagement/testGroupManagement.spec.ts
+++ b/ui/cypress/tests/userManagement/testGroupManagement.spec.ts
@@ -85,16 +85,9 @@ describe('Test Group Management for Pipelines', () => {
3,
);
- // Add new user group with pipeline admin role
- ConfigurationBtns.newUserGroupBtn().click();
- ConfigurationBtns.inputGroupName('User_Group');
- cy.get('input[value="ROLE_PIPELINE_ADMIN"]').check();
- UserBtns.saveEditUserBtn().click();
-
- // Add first user to group
- UserBtns.firstEditUserBtn().click();
- cy.get('input[type="checkbox"]').eq(0).check();
- UserBtns.saveEditUserBtn().click();
+ UserUtils.createGroup('User_Group', UserRole.ROLE_PIPELINE_ADMIN);
+
+ UserUtils.addGroupToUser('User_Group', user.name);
// Add user group to pipeline
PipelineUtils.goToPipelines();
diff --git a/ui/cypress/tests/userManagement/testUserRoleConnect.spec.ts
b/ui/cypress/tests/userManagement/testUserRoleConnect.spec.ts
index a517d854d1..c3b5d585b3 100644
--- a/ui/cypress/tests/userManagement/testUserRoleConnect.spec.ts
+++ b/ui/cypress/tests/userManagement/testUserRoleConnect.spec.ts
@@ -19,53 +19,139 @@ import { UserRole } from
'../../../src/app/_enums/user-role.enum';
import { UserUtils } from '../../support/utils/UserUtils';
import { ConnectUtils } from '../../support/utils/connect/ConnectUtils';
import { PermissionUtils } from '../../support/utils/user/PermissionUtils';
-import { NavigationUtils } from
'../../support/utils/navigation/NavigationUtils';
import { User } from '../../support/model/User';
+import { PipelineUtils } from '../../support/utils/pipeline/PipelineUtils';
describe('Test User Roles for Connect', () => {
- let connectAdminUser: User;
+ const adapterName = 'simulator';
+ let user1: User;
+ let user2: User;
+
beforeEach('Setup Test', () => {
cy.initStreamPipesTest();
- connectAdminUser = UserUtils.createUser(
- 'user',
+ user1 = UserUtils.createUser(
+ 'user1',
+ UserRole.ROLE_CONNECT_ADMIN,
+ UserRole.ROLE_PIPELINE_ADMIN,
+ );
+
+ user2 = UserUtils.createUser(
+ 'user2',
UserRole.ROLE_CONNECT_ADMIN,
+ UserRole.ROLE_PIPELINE_ADMIN,
);
- ConnectUtils.addMachineDataSimulator('simulator');
});
- it('Connect admin should not see adapters of other users', () => {
- switchUserAndValidateConnectModuleIsShown();
+ it('Adapter is not shared with other users', () => {
+ // set up
+ UserUtils.switchUser(user1);
+ ConnectUtils.addMachineDataSimulator(adapterName);
- // Validate that no adapter is visible
+ // check admin
+ UserUtils.switchUser(UserUtils.adminUser);
+ validateAdapterIsVisible();
+ PermissionUtils.validateUserCanChangePermissions(adapterName);
+
+ // check other users
+ UserUtils.switchUser(user2);
ConnectUtils.checkAmountOfAdapters(0);
});
- it('Connect admin should see public adapters of other users', () => {
- // Set adapter to public
- PermissionUtils.markElementAsPublic('simulator');
+ it('Make adapter public', () => {
+ // set up
+ UserUtils.switchUser(user1);
+ ConnectUtils.addMachineDataSimulator(adapterName);
+ PermissionUtils.markElementAsPublic(adapterName);
- switchUserAndValidateConnectModuleIsShown();
+ // check admin
+ UserUtils.switchUser(UserUtils.adminUser);
+ validateAdapterIsVisible();
+ PermissionUtils.validateUserCanChangePermissions(adapterName);
- // Validate that adapter is visible
- ConnectUtils.checkAmountOfAdapters(1);
+ // check other users
+ UserUtils.switchUser(user2);
+ validateAdapterIsVisible();
+ PermissionUtils.validateUserCanNotChangePermissions(adapterName);
});
- it('Connect admin should see shared adapters of other users', () => {
- // Share adapter with user
- PermissionUtils.authorizeUser('simulator', connectAdminUser.email);
+ it('Share adapter with other user and change ownership', () => {
+ const user3 = UserUtils.createUser(
+ 'user3',
+ UserRole.ROLE_CONNECT_ADMIN,
+ UserRole.ROLE_PIPELINE_ADMIN,
+ );
+
+ // set up
+ UserUtils.switchUser(user1);
+ ConnectUtils.addMachineDataSimulator(adapterName);
+ PermissionUtils.authorizeUser(adapterName, user2.email);
+
+ // check admin
+ UserUtils.switchUser(UserUtils.adminUser);
+ validateAdapterIsVisible();
+ PermissionUtils.validateUserCanChangePermissions(adapterName);
+
+ // check authorized user
+ UserUtils.switchUser(user2);
+ validateAdapterIsVisible();
+ PermissionUtils.validateUserCanNotChangePermissions(adapterName);
- switchUserAndValidateConnectModuleIsShown();
+ UserUtils.switchUser(user3);
+ ConnectUtils.checkAmountOfAdapters(0);
+
+ // change ownership to user3
+ UserUtils.switchUser(user1);
+ ConnectUtils.goToConnect();
+ PermissionUtils.changeOwnership(adapterName, user3.email);
+ ConnectUtils.checkAmountOfAdapters(0);
- // Validate that adapter is visible
+ UserUtils.switchUser(UserUtils.adminUser);
+ validateAdapterIsVisible();
+ PermissionUtils.validateUserCanChangePermissions(adapterName);
+
+ // check authorized user
+ UserUtils.switchUser(user2);
+ validateAdapterIsVisible();
+ PermissionUtils.validateUserCanNotChangePermissions(adapterName);
+
+ // validate that user3 is owner now
+ UserUtils.switchUser(user3);
+ validateAdapterIsVisible();
+ PermissionUtils.validateUserCanChangePermissions(adapterName);
+ });
+
+ it('Adapter is shared with group for user 2', () => {
+ // Add group with connect admin rights
+ UserUtils.createGroup(
+ 'connect_admin_group',
+ UserRole.ROLE_CONNECT_ADMIN,
+ );
+ UserUtils.addGroupToUser('connect_admin_group', user2.name);
+
+ // set up
+ UserUtils.switchUser(user1);
+ ConnectUtils.addMachineDataSimulator(adapterName);
+
+ PermissionUtils.authorizeGroup(adapterName, 'connect_admin_group');
+
+ // check admin
+ UserUtils.switchUser(UserUtils.adminUser);
+ validateAdapterIsVisible();
+ PermissionUtils.validateUserCanChangePermissions(adapterName);
+
+ // check other users
+ UserUtils.switchUser(user2);
ConnectUtils.checkAmountOfAdapters(1);
});
- function switchUserAndValidateConnectModuleIsShown() {
- UserUtils.switchUser(connectAdminUser);
+ function validateAdapterIsVisible() {
+ ConnectUtils.checkAmountOfAdapters(1);
+
+ ConnectUtils.validateEventsInPreview(adapterName, 7);
+
+ PipelineUtils.goToPipelineEditor();
+ PipelineUtils.checkDataStreamExists(adapterName);
- NavigationUtils.validateActiveModules([
- NavigationUtils.CONNECT,
- NavigationUtils.CONFIGURATION,
- ]);
+ ConnectUtils.goToConnect();
}
});
diff --git a/ui/cypress/tests/userManagement/testUserRolePipeline.spec.ts
b/ui/cypress/tests/userManagement/testUserRolePipeline.spec.ts
index 67024c4ee4..be104523d0 100644
--- a/ui/cypress/tests/userManagement/testUserRolePipeline.spec.ts
+++ b/ui/cypress/tests/userManagement/testUserRolePipeline.spec.ts
@@ -22,87 +22,155 @@ import { ConnectUtils } from
'../../support/utils/connect/ConnectUtils';
import { PipelineUtils } from '../../support/utils/pipeline/PipelineUtils';
import { PermissionUtils } from '../../support/utils/user/PermissionUtils';
import { PipelineBtns } from '../../support/utils/pipeline/PipelineBtns';
-import { NavigationUtils } from
'../../support/utils/navigation/NavigationUtils';
+import { User } from '../../support/model/User';
describe('Test User Roles for Pipelines', () => {
+ const pipelineName = 'Persist simulator';
+ let pipelineUser1: User;
+ let pipelineAdmin1: User;
+ let pipelineAdmin2: User;
+
beforeEach('Setup Test', () => {
cy.initStreamPipesTest();
- // Create a machine data simulator with a sample pipeline for the tests
- ConnectUtils.addMachineDataSimulator('simulator', true);
- });
- it('Pipeline admin should not see pipelines of other users', () => {
- const newUser = UserUtils.createUser(
- 'user',
+ pipelineUser1 = UserUtils.createUser(
+ 'pipelineUser1',
+ UserRole.ROLE_PIPELINE_USER,
+ );
+
+ pipelineAdmin1 = UserUtils.createUser(
+ 'pipelineAdmin1',
+ UserRole.ROLE_CONNECT_ADMIN,
+ UserRole.ROLE_PIPELINE_ADMIN,
+ );
+
+ pipelineAdmin2 = UserUtils.createUser(
+ 'pipelineAdmin2',
UserRole.ROLE_PIPELINE_ADMIN,
);
+ });
- // Login as user and check if pipeline is visible to user
- UserUtils.switchUser(newUser);
+ it('Pipeline is not shared with other users', () => {
+ UserUtils.switchUser(pipelineAdmin1);
+ ConnectUtils.addMachineDataSimulator('simulator', true);
- NavigationUtils.validateActiveModules([
- NavigationUtils.PIPELINES,
- NavigationUtils.CONFIGURATION,
- ]);
+ assertPipelineIsVisibleAndEditableCanChangePermissions(
+ UserUtils.adminUser,
+ );
- PipelineUtils.goToPipelines();
- PipelineUtils.checkAmountOfPipelinesPipeline(0);
+ assertPipelineIsNotVisible(pipelineUser1);
+
+ UserUtils.switchUser(pipelineUser1);
+
+ assertPipelineIsNotVisible(pipelineAdmin2);
});
- it('Pipeline admin should see public pipelines of other users', () => {
- const newUser = UserUtils.createUser(
- 'user',
- UserRole.ROLE_PIPELINE_ADMIN,
- );
+ it('Make pipeline public', () => {
+ UserUtils.switchUser(pipelineAdmin1);
+ ConnectUtils.addMachineDataSimulator('simulator', true);
- // Add new authorized user to pipeline
PipelineUtils.goToPipelines();
- PermissionUtils.markElementAsPublic('Persist simulator');
+ PermissionUtils.markElementAsPublic(pipelineName);
- // Login as user and check if pipeline is visible to user
- UserUtils.switchUser(newUser);
+ assertPipelineIsVisibleAndEditableCanChangePermissions(
+ UserUtils.adminUser,
+ );
- PipelineUtils.goToPipelines();
- PipelineUtils.checkAmountOfPipelinesPipeline(1);
- });
+ assertPipelineIsVisibleButNotEditable(pipelineUser1);
- it(' Pipeline admin should see shared pipelines of other users', () => {
- const newUser = UserUtils.createUser(
- 'user',
- UserRole.ROLE_PIPELINE_ADMIN,
+ assertPipelineIsVisibleAndEditableCannotChangePermissions(
+ pipelineAdmin2,
);
+ });
+
+ it('Share pipeline with other user and change ownership', () => {
+ UserUtils.switchUser(pipelineAdmin1);
+ ConnectUtils.addMachineDataSimulator('simulator', true);
- // Add new authorized user to pipeline
PipelineUtils.goToPipelines();
- PermissionUtils.markElementAsPublic('Persist simulator');
- PermissionUtils.authorizeUser('Persist simulator', newUser.email);
+ PermissionUtils.authorizeUser(pipelineName, pipelineAdmin2.email);
- // Login as user and check if pipeline is visible to user
- UserUtils.switchUser(newUser);
+ assertPipelineIsVisibleAndEditableCanChangePermissions(
+ UserUtils.adminUser,
+ );
+
+ assertPipelineIsVisibleAndEditableCannotChangePermissions(
+ pipelineAdmin2,
+ );
+
+ assertPipelineIsNotVisible(pipelineUser1);
+ UserUtils.switchUser(pipelineAdmin1);
PipelineUtils.goToPipelines();
- PipelineUtils.checkAmountOfPipelinesPipeline(1);
+ PermissionUtils.changeOwnership(pipelineName, pipelineAdmin2.email);
+
+ assertPipelineIsNotVisible(pipelineAdmin1);
+
+ assertPipelineIsVisibleAndEditableCanChangePermissions(
+ UserUtils.adminUser,
+ );
+
+ assertPipelineIsVisibleAndEditableCanChangePermissions(pipelineAdmin2);
+
+ assertPipelineIsNotVisible(pipelineUser1);
});
- it(' Pipeline user should see shared pipelines of other users but not be
able to edit them', () => {
- const newUser = UserUtils.createUser(
- 'user',
- UserRole.ROLE_PIPELINE_USER,
+ it('Pipeline is shared with group for user 2', () => {
+ UserUtils.createGroup(
+ 'pipeline_admin_group',
+ UserRole.ROLE_PIPELINE_ADMIN,
);
+ UserUtils.addGroupToUser('pipeline_admin_group', pipelineAdmin2.name);
+
+ // set up
+ UserUtils.switchUser(pipelineAdmin1);
+ ConnectUtils.addMachineDataSimulator('simulator', true);
- // Add new authorized user to pipeline
PipelineUtils.goToPipelines();
- // PermissionUtils.markElementAsPublic();
- PermissionUtils.authorizeUser('Persist simulator', newUser.email);
+ PermissionUtils.authorizeGroup(pipelineName, 'pipeline_admin_group');
- // Login as user and check if pipeline is visible to user
- UserUtils.switchUser(newUser);
+ assertPipelineIsVisibleAndEditableCanChangePermissions(
+ UserUtils.adminUser,
+ );
+
+ assertPipelineIsNotVisible(pipelineUser1);
+ assertPipelineIsVisibleAndEditableCannotChangePermissions(
+ pipelineAdmin2,
+ );
+ });
+
+ function assertPipelineIsVisibleAndEditableCanChangePermissions(
+ user: User,
+ ) {
+ UserUtils.switchUser(user);
+ PipelineUtils.goToPipelines();
+ PipelineUtils.checkAmountOfPipelinesPipeline(1);
+ PipelineBtns.stopPipeline().should('not.be.disabled');
+ PermissionUtils.validateUserCanChangePermissions(pipelineName);
+ }
+
+ function assertPipelineIsVisibleAndEditableCannotChangePermissions(
+ user: User,
+ ) {
+ UserUtils.switchUser(user);
PipelineUtils.goToPipelines();
PipelineUtils.checkAmountOfPipelinesPipeline(1);
+ PipelineBtns.stopPipeline().should('not.be.disabled');
+ PermissionUtils.validateUserCanNotChangePermissions(pipelineName);
+ }
- // A pipeline user should not be able to stop the pipeline or delete it
- PipelineBtns.deletePipeline().should('not.exist');
+ function assertPipelineIsVisibleButNotEditable(user: User) {
+ UserUtils.switchUser(user);
+ PipelineUtils.goToPipelines();
+ PipelineUtils.checkAmountOfPipelinesPipeline(1);
PipelineBtns.stopPipeline().should('be.disabled');
- });
+ PermissionUtils.validateUserCanNotChangePermissions(pipelineName);
+ }
+
+ function assertPipelineIsNotVisible(user: User) {
+ UserUtils.switchUser(user);
+ PipelineUtils.goToPipelines();
+ PipelineUtils.checkAmountOfPipelinesPipeline(0);
+ }
});
diff --git
a/ui/projects/streampipes/shared-ui/src/lib/dialog/object-permission-dialog/object-permission-dialog.component.html
b/ui/projects/streampipes/shared-ui/src/lib/dialog/object-permission-dialog/object-permission-dialog.component.html
index 6e1cdf3c61..069e4044a4 100644
---
a/ui/projects/streampipes/shared-ui/src/lib/dialog/object-permission-dialog/object-permission-dialog.component.html
+++
b/ui/projects/streampipes/shared-ui/src/lib/dialog/object-permission-dialog/object-permission-dialog.component.html
@@ -35,10 +35,18 @@
}}</span>
<mat-form-field color="accent">
<mat-label>{{ 'Owner' | translate }}</mat-label>
- <mat-select formControlName="owner" fxFlex
required>
+ <mat-select
+ data-cy="owner-select"
+ formControlName="owner"
+ fxFlex
+ required
+ >
<mat-option
*ngFor="let user of allUsers"
[value]="user.principalId"
+ [attr.data-cy]="
+ 'owner-option-' + user.email
+ "
>{{ user.email }}
</mat-option>
</mat-select>
@@ -144,6 +152,7 @@
<input
matInput
[placeholder]="'Add' | translate"
+ data-cy="authorized-group"
#groupInput
[formControl]="groupCtrl"
[matAutocomplete]="groupAuto"
@@ -161,6 +170,9 @@
(optionSelected)="groupSelected($event)"
>
<mat-option
+ [attr.data-cy]="
+ 'group-option-' + group.groupName
+ "
*ngFor="
let group of filteredGroups$ |
async
"
@@ -219,7 +231,10 @@
</div>
</div>
} @else {
- <div class="sp-dialog-content">
+ <div
+ class="sp-dialog-content"
+ data-cy="warning-permissions-managed-by-owner"
+ >
<div fxFlex="100" fxLayoutAlign="center center" fxLayout="column">
<mat-icon>block</mat-icon>
<h5>
@@ -252,6 +267,7 @@
mat-button
mat-flat-button
class="mat-basic"
+ data-cy="sp-manage-permissions-cancel"
(click)="close(false)"
>
{{ 'Cancel' | translate }}
diff --git
a/ui/src/app/configuration/security-configuration/edit-user-dialog/edit-user-dialog.component.html
b/ui/src/app/configuration/security-configuration/edit-user-dialog/edit-user-dialog.component.html
index 3809333f0c..b1bfc9d312 100644
---
a/ui/src/app/configuration/security-configuration/edit-user-dialog/edit-user-dialog.component.html
+++
b/ui/src/app/configuration/security-configuration/edit-user-dialog/edit-user-dialog.component.html
@@ -157,6 +157,7 @@
[value]="group.groupId"
[checked]="user.groups.indexOf(group.groupId) > -1"
(change)="changeGroupAssignment($event)"
+ [attr.data-cy]="'group-' + group.groupName"
>
{{ group.groupName }}
</mat-checkbox>
diff --git
a/ui/src/app/configuration/security-configuration/security-user-configuration/security-user-config.component.html
b/ui/src/app/configuration/security-configuration/security-user-configuration/security-user-config.component.html
index 7ddef77d55..a429801b3f 100644
---
a/ui/src/app/configuration/security-configuration/security-user-configuration/security-user-config.component.html
+++
b/ui/src/app/configuration/security-configuration/security-user-configuration/security-user-config.component.html
@@ -104,7 +104,9 @@
class="mat-basic"
[matTooltip]="'Edit user' | translate"
matTooltipPosition="above"
- [attr.data-cy]="'user-edit-btn'"
+ [attr.data-cy]="
+ 'user-edit-' + account.fullName
+ "
(click)="editUser(account)"
>
<i class="material-icons">edit</i>
diff --git
a/ui/src/app/editor/dialog/pipeline-element-discovery/pipeline-element-discovery.component.html
b/ui/src/app/editor/dialog/pipeline-element-discovery/pipeline-element-discovery.component.html
index 02f4c257dc..eb0bf6a0d0 100644
---
a/ui/src/app/editor/dialog/pipeline-element-discovery/pipeline-element-discovery.component.html
+++
b/ui/src/app/editor/dialog/pipeline-element-discovery/pipeline-element-discovery.component.html
@@ -59,7 +59,13 @@
</div>
<mat-divider></mat-divider>
<div class="sp-dialog-actions">
- <button mat-button mat-flat-button class="mat-basic" (click)="hide()">
+ <button
+ data-cy="cancel-pipeline-element-discovery"
+ mat-button
+ mat-flat-button
+ class="mat-basic"
+ (click)="hide()"
+ >
Cancel
</button>
</div>