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>

Reply via email to