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 276299730 #2151 & #2223: Implement E2E tests for enhanced adapter
deletion and Extend reset REST endpoint to remove users (#2197)
276299730 is described below
commit 276299730301e410501220aff52e7da65a335c9c
Author: Muyang Ye <[email protected]>
AuthorDate: Sun Nov 26 12:55:07 2023 -0800
#2151 & #2223: Implement E2E tests for enhanced adapter deletion and Extend
reset REST endpoint to remove users (#2197)
* implement unit tests for enhanced adapter deletion
* better structure
* fix
* delete other users in reset
* change comment
---
.../streampipes/rest/impl/ResetResource.java | 17 +++-
ui/cypress/support/utils/UserUtils.ts | 17 +++-
ui/cypress/support/utils/connect/ConnectUtils.ts | 73 ++++++++++++++++-
.../adapter/enhancedDeleteAdapter.smoke.spec.ts | 95 ++++++++++++++++++++++
.../delete-adapter-dialog.component.html | 1 +
5 files changed, 195 insertions(+), 8 deletions(-)
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 b3f7b6719..3bcbd6a17 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
@@ -18,8 +18,9 @@
package org.apache.streampipes.rest.impl;
+import org.apache.streampipes.model.client.user.Principal;
+import org.apache.streampipes.model.client.user.PrincipalType;
import org.apache.streampipes.model.message.Notifications;
-import org.apache.streampipes.model.message.SuccessMessage;
import org.apache.streampipes.rest.ResetManagement;
import
org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource;
import org.apache.streampipes.rest.shared.annotation.JacksonSerialized;
@@ -34,6 +35,8 @@ import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
+import java.util.ArrayList;
+
@Path("/v2/reset")
public class ResetResource extends AbstractAuthGuardedRestResource {
private static final Logger logger =
LoggerFactory.getLogger(ResetResource.class);
@@ -44,7 +47,17 @@ public class ResetResource extends
AbstractAuthGuardedRestResource {
@Operation(summary = "Resets StreamPipes instance")
public Response reset() {
ResetManagement.reset(getAuthenticatedUsername());
- SuccessMessage message = Notifications.success("Reset of system
successfully performed");
+ 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) {
+ if (user.getPrincipalType() == PrincipalType.USER_ACCOUNT
+ && !user.getPrincipalId().equals(getAuthenticatedUserSid())) {
+ ResetManagement.reset(user.getUsername());
+ userStorage.deleteUser(user.getPrincipalId());
+ }
+ }
+ 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 60e735e59..fb505aa81 100644
--- a/ui/cypress/support/utils/UserUtils.ts
+++ b/ui/cypress/support/utils/UserUtils.ts
@@ -27,6 +27,15 @@ export class UserUtils {
.addRole(UserRole.ROLE_ADMIN)
.build();
+ public static adapterAndPipelineAdminUser = UserBuilder.create(
+ '[email protected]',
+ )
+ .setName('anpadmin')
+ .setPassword('anpadmin')
+ .addRole(UserRole.ROLE_PIPELINE_ADMIN)
+ .addRole(UserRole.ROLE_CONNECT_ADMIN)
+ .build();
+
public static goToUserConfiguration() {
cy.visit('#/configuration/security');
}
@@ -42,9 +51,11 @@ export class UserUtils {
cy.dataCy('new-user-password-repeat').type(user.password);
// Set role
- cy.dataCy('role-' + user.role[0])
- .children()
- .click();
+ for (var i = 0; i < user.role.length; i++) {
+ cy.dataCy('role-' + user.role[i])
+ .children()
+ .click();
+ }
cy.dataCy('new-user-enabled').children().click();
// Store
diff --git a/ui/cypress/support/utils/connect/ConnectUtils.ts
b/ui/cypress/support/utils/connect/ConnectUtils.ts
index b6a3f28e8..22c57d853 100644
--- a/ui/cypress/support/utils/connect/ConnectUtils.ts
+++ b/ui/cypress/support/utils/connect/ConnectUtils.ts
@@ -22,6 +22,8 @@ import { ConnectEventSchemaUtils } from
'../ConnectEventSchemaUtils';
import { DataLakeUtils } from '../datalake/DataLakeUtils';
import { ConnectBtns } from './ConnectBtns';
import { AdapterBuilder } from '../../builder/AdapterBuilder';
+import { UserUtils } from '../UserUtils';
+import { PipelineUtils } from '../PipelineUtils';
export class ConnectUtils {
public static testAdapter(adapterConfiguration: AdapterInput) {
@@ -193,11 +195,10 @@ export class ConnectUtils {
public static deleteAdapter() {
// Delete adapter
- cy.visit('#/connect');
+ this.goToConnect();
cy.dataCy('delete-adapter').should('have.length', 1);
- cy.dataCy('delete-adapter').click();
- cy.dataCy('delete-adapter-confirmation').click();
+ this.clickDelete();
cy.dataCy('adapter-deletion-in-progress', { timeout: 10000 }).should(
'be.visible',
);
@@ -207,6 +208,72 @@ export class ConnectUtils {
);
}
+ public static deleteAdapterAndAssociatedPipelines(switchUserCheck = false)
{
+ // Delete adapter and associated pipelines
+ this.goToConnect();
+ cy.dataCy('delete-adapter').should('have.length', 1);
+ this.clickDelete();
+ cy.dataCy('delete-adapter-and-associated-pipelines-confirmation', {
+ timeout: 10000,
+ }).should('be.visible');
+ cy.dataCy(
+ 'delete-adapter-and-associated-pipelines-confirmation',
+ ).click();
+ cy.dataCy('adapter-deletion-in-progress', { timeout: 10000 }).should(
+ 'be.visible',
+ );
+ if (switchUserCheck) {
+ cy.switchUser(UserUtils.adapterAndPipelineAdminUser);
+ }
+ this.checkAdapterAndAssociatedPipelinesDeleted();
+ }
+
+ // NOTE: this function will leave the adapter and associated pipelines
running,
+ // please make sure to clean up after calling this function
+ public static deleteAdapterAndAssociatedPipelinesPermissionDenied() {
+ // Associated pipelines not owned by the user (unless admin) should
not be deleted during adapter deletion
+ this.goToConnect();
+ cy.dataCy('delete-adapter').should('have.length', 1);
+ this.clickDelete();
+ cy.dataCy('delete-adapter-and-associated-pipelines-confirmation', {
+ timeout: 10000,
+ }).should('be.visible');
+ cy.dataCy(
+ 'delete-adapter-and-associated-pipelines-confirmation',
+ ).click();
+ cy.dataCy('adapter-deletion-permission-denied', {
+ timeout: 10000,
+ }).should('be.visible');
+ cy.get('.sp-dialog-actions').click();
+ this.checkAdapterNotDeleted();
+ }
+
+ public static clickDelete() {
+ cy.dataCy('delete-adapter').click();
+ cy.dataCy('delete-adapter-confirmation').click();
+ }
+
+ public static checkAdapterNotDeleted() {
+ this.goToConnect();
+ cy.dataCy('delete-adapter', { timeout: 20000 }).should(
+ 'have.length',
+ 1,
+ );
+ }
+
+ public static checkAdapterAndAssociatedPipelinesDeleted() {
+ this.goToConnect();
+ cy.dataCy('delete-adapter', { timeout: 20000 }).should(
+ 'have.length',
+ 0,
+ );
+ PipelineUtils.goToPipelines();
+ cy.dataCy('delete-pipeline', { timeout: 10000 }).should(
+ 'have.length',
+ 0,
+ );
+ }
+
public static setUpPreprocessingRuleTest(): AdapterInput {
const adapterConfiguration = AdapterBuilder.create('File_Stream')
.setStoreInDataLake()
diff --git a/ui/cypress/tests/adapter/enhancedDeleteAdapter.smoke.spec.ts
b/ui/cypress/tests/adapter/enhancedDeleteAdapter.smoke.spec.ts
new file mode 100644
index 000000000..6bb2cc3c5
--- /dev/null
+++ b/ui/cypress/tests/adapter/enhancedDeleteAdapter.smoke.spec.ts
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { AdapterBuilder } from '../../support/builder/AdapterBuilder';
+import { ConnectUtils } from '../../support/utils/connect/ConnectUtils';
+import { PipelineBuilder } from '../../support/builder/PipelineBuilder';
+import { PipelineElementBuilder } from
'../../support/builder/PipelineElementBuilder';
+import { UserUtils } from '../../support/utils/UserUtils';
+import { PipelineUtils } from '../../support/utils/PipelineUtils';
+
+const adapterName = 'simulator';
+
+const adapterInput = AdapterBuilder.create('Machine_Data_Simulator')
+ .setName(adapterName)
+ .addInput('input', 'wait-time-ms', '1000')
+ .build();
+
+const pipelineInput = PipelineBuilder.create('Pipeline Test')
+ .addSource(adapterName)
+ .addProcessingElement(
+ PipelineElementBuilder.create('field_renamer')
+ .addInput('drop-down', 'convert-property', 'timestamp')
+ .addInput('input', 'field-name', 't')
+ .build(),
+ )
+ .addSink(
+ PipelineElementBuilder.create('data_lake')
+ .addInput('input', 'db_measurement', 'demo')
+ .build(),
+ )
+ .build();
+
+describe('Test Enhanced Adapter Deletion', () => {
+ // In the beginning, create the non-admin user
+ before(() => {
+ cy.initStreamPipesTest();
+ UserUtils.addUser(UserUtils.adapterAndPipelineAdminUser);
+ cy.logout();
+ });
+
+ beforeEach('Setup Test', () => {
+ cy.visit('#/login');
+ cy.dataCy('login-email').type(
+ UserUtils.adapterAndPipelineAdminUser.email,
+ );
+ cy.dataCy('login-password').type(
+ UserUtils.adapterAndPipelineAdminUser.password,
+ );
+ cy.dataCy('login-button').click();
+ cy.wait(1000);
+ });
+
+ it('Test Delete Adapter and Associated Pipelines', () => {
+ ConnectUtils.testAdapter(adapterInput);
+ PipelineUtils.addPipeline(pipelineInput);
+ PipelineUtils.addPipeline(pipelineInput);
+ ConnectUtils.deleteAdapterAndAssociatedPipelines();
+ });
+
+ it('Test Admin Should Be Able to Delete Adapter and Not Owned Associated
Pipelines', () => {
+ // Let the user create the adapter and the pipeline
+ ConnectUtils.testAdapter(adapterInput);
+ PipelineUtils.addPipeline(pipelineInput);
+ PipelineUtils.addPipeline(pipelineInput);
+ // Then let the admin delete them
+ cy.switchUser(UserUtils.adminUser);
+ ConnectUtils.deleteAdapterAndAssociatedPipelines(true);
+ });
+
+ it('Test Delete Adapter and Associated Pipelines Permission Denied', () =>
{
+ // Let the admin create the adapter and the pipeline
+ cy.switchUser(UserUtils.adminUser);
+ ConnectUtils.testAdapter(adapterInput);
+ PipelineUtils.addPipeline(pipelineInput);
+ PipelineUtils.addPipeline(pipelineInput);
+ // Then the user shouldn't be able to delete them
+ cy.switchUser(UserUtils.adapterAndPipelineAdminUser);
+ ConnectUtils.deleteAdapterAndAssociatedPipelinesPermissionDenied();
+ });
+});
diff --git
a/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.html
b/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.html
index c5a73031b..0f08cec5c 100644
---
a/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.html
+++
b/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.html
@@ -67,6 +67,7 @@
fxLayoutAlign="center center"
fxLayout="column"
style="width: 100%"
+ data-cy="adapter-deletion-permission-denied"
>
<b>
<h4>