Skip to content

Commit

Permalink
2337 cant access connect with user role connect admin (#2566)
Browse files Browse the repository at this point in the history
* test(#2337): e2e test to validate that a user can access only the connect view

* fix(#2337): Change routing from to app-routing.module

* fix(#2337): Fix checkstyle in PipelineElementTemplateResource
  • Loading branch information
tenthe authored Mar 15, 2024
1 parent cc4e2ee commit aaf6018
Show file tree
Hide file tree
Showing 27 changed files with 180 additions and 119 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,18 @@ public class PipelineElementTemplateResource extends AbstractRestResource {

@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Get a list of all pipeline element templates",
tags = {"Pipeline Element Templates"},
responses = {
@ApiResponse(content = {
@Content(
mediaType = "application/json",
array = @ArraySchema(schema = @Schema(implementation = PipelineElementTemplate.class)))
})
})
tags = {"Pipeline Element Templates"},
responses = {
@ApiResponse(content = {
@Content(
mediaType = "application/json",
array = @ArraySchema(schema = @Schema(implementation = PipelineElementTemplate.class)))
})
})
public ResponseEntity<List<PipelineElementTemplate>> getAll(
@Parameter(description = "Filter all templates by this appId")
@RequestParam("appId") String appId) {
@RequestParam("appId") String appId
) {
if (appId == null) {
return ok(getPipelineElementTemplateStorage().getAll());
} else {
Expand All @@ -72,17 +73,19 @@ public ResponseEntity<List<PipelineElementTemplate>> getAll(

@GetMapping(path = "{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Get a single pipeline element template by a given id",
tags = {"Pipeline Element Templates"},
responses = {
@ApiResponse(content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = PipelineElementTemplate.class))
}),
@ApiResponse(responseCode = "400", description = "Template with given id not found")
})
public ResponseEntity<?> getById(@Parameter(description = "The id of the pipeline element template", required = true)
@PathVariable("id") String s) {
tags = {"Pipeline Element Templates"},
responses = {
@ApiResponse(content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = PipelineElementTemplate.class))
}),
@ApiResponse(responseCode = "400", description = "Template with given id not found")
})
public ResponseEntity<?> getById(
@Parameter(description = "The id of the pipeline element template", required = true)
@PathVariable("id") String s
) {
try {
return ok(getPipelineElementTemplateStorage().getElementById(s));
} catch (RuntimeException e) {
Expand All @@ -92,32 +95,35 @@ public ResponseEntity<?> getById(@Parameter(description = "The id of the pipelin

@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Store a new pipeline element template",
tags = {"Pipeline Element Templates"},
responses = {
@ApiResponse(responseCode = "200", description = "Template successfully stored")
})
tags = {"Pipeline Element Templates"},
responses = {
@ApiResponse(responseCode = "200", description = "Template successfully stored")
})
public ResponseEntity<Void> create(
@RequestBody(description = "The pipeline element template to be stored",
content = @Content(schema = @Schema(implementation = PipelineElementTemplate.class)))
@org.springframework.web.bind.annotation.RequestBody PipelineElementTemplate entity) {
content = @Content(schema = @Schema(implementation = PipelineElementTemplate.class)))
@org.springframework.web.bind.annotation.RequestBody PipelineElementTemplate entity
) {
getPipelineElementTemplateStorage().createElement(entity);
return ok();
}

@PutMapping(path = "{id}", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Update a pipeline element template",
tags = {"Pipeline Element Templates"},
responses = {
@ApiResponse(content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = PipelineElementTemplate.class))
}, responseCode = "200", description = "Template successfully updated"),
@ApiResponse(responseCode = "400", description = "Template with given id not found")
})
public ResponseEntity<?> update(@Parameter(description = "The id of the pipeline element template", required = true)
@PathVariable("id") String id,
@RequestBody PipelineElementTemplate entity) {
tags = {"Pipeline Element Templates"},
responses = {
@ApiResponse(content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = PipelineElementTemplate.class))
}, responseCode = "200", description = "Template successfully updated"),
@ApiResponse(responseCode = "400", description = "Template with given id not found")
})
public ResponseEntity<?> update(
@Parameter(description = "The id of the pipeline element template", required = true)
@PathVariable("id") String id,
@RequestBody PipelineElementTemplate entity
) {
try {
if (id.equals(entity.getCouchDbId())) {
return ok(getPipelineElementTemplateStorage().updateElement(entity));
Expand All @@ -131,14 +137,15 @@ public ResponseEntity<?> update(@Parameter(description = "The id of the pipeline

@DeleteMapping(path = "{id}")
@Operation(summary = "Delete a pipeline element template by a given id",
tags = {"Pipeline Element Templates"},
responses = {
@ApiResponse(responseCode = "200", description = "Pipeline element template successfully deleted"),
@ApiResponse(responseCode = "400", description = "Template with given id not found")
})
tags = {"Pipeline Element Templates"},
responses = {
@ApiResponse(responseCode = "200", description = "Pipeline element template successfully deleted"),
@ApiResponse(responseCode = "400", description = "Template with given id not found")
})
public ResponseEntity<Void> delete(
@Parameter(description = "The id of the pipeline element template", required = true)
@PathVariable("id") String s) {
@PathVariable("id") String s
) {
PipelineElementTemplate template = getPipelineElementTemplateStorage().getElementById(s);
getPipelineElementTemplateStorage().deleteElement(template);
return ok();
Expand All @@ -149,44 +156,45 @@ public ResponseEntity<Void> delete(
produces = MediaType.APPLICATION_JSON_VALUE,
consumes = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Configure a data sink with a pipeline element template.",
tags = {"Pipeline Element Templates"},
responses = {
@ApiResponse(content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = DataSinkInvocation.class))
}, responseCode = "200", description = "The configured data sink invocation model"),
})
tags = {"Pipeline Element Templates"},
responses = {
@ApiResponse(content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = DataSinkInvocation.class))
}, responseCode = "200", description = "The configured data sink invocation model"),
})
public ResponseEntity<DataSinkInvocation> getPipelineElementForTemplate(
@Parameter(description = "The id of the pipeline element template", required = true)
@PathVariable("id") String id,

@Parameter(
description = "Overwrite the name and description of the pipeline element"
+ "with the labels given in the pipeline element template")
@RequestParam("overwriteNames") String overwriteNameAndDescription,

@RequestParam(value = "overwriteNames", defaultValue = "false", required = false)
String overwriteNameAndDescription,
@RequestBody(description = "The data sink invocation that should be configured with the template contents",
content = @Content(schema = @Schema(implementation = DataSinkInvocation.class)))
@org.springframework.web.bind.annotation.RequestBody DataSinkInvocation invocation) {
content = @Content(schema = @Schema(implementation = DataSinkInvocation.class)))
@org.springframework.web.bind.annotation.RequestBody DataSinkInvocation invocation
) {
PipelineElementTemplate template = getPipelineElementTemplateStorage().getElementById(id);
return ok(new DataSinkTemplateHandler(template, invocation, Boolean.parseBoolean(overwriteNameAndDescription))
.applyTemplateOnPipelineElement());
.applyTemplateOnPipelineElement());
}

@PostMapping(
path = "{id}/processor",
produces = MediaType.APPLICATION_JSON_VALUE,
consumes = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Configure a data processor with a pipeline element template.",
tags = {"Pipeline Element Templates"},
responses = {
@ApiResponse(content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = DataProcessorInvocation.class))
}, responseCode = "200", description = "The configured data processor invocation model"),
})
tags = {"Pipeline Element Templates"},
responses = {
@ApiResponse(content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = DataProcessorInvocation.class))
}, responseCode = "200", description = "The configured data processor invocation model"),
})
public ResponseEntity<DataProcessorInvocation> getPipelineElementForTemplate(
@Parameter(description = "The id of the pipeline element template", required = true)
@PathVariable("id") String id,
Expand All @@ -196,26 +204,27 @@ public ResponseEntity<DataProcessorInvocation> getPipelineElementForTemplate(
@RequestParam("overwriteNames") String overwriteNameAndDescription,

@RequestBody(description = "The data processor invocation that should be configured with the template contents",
content = @Content(schema = @Schema(implementation = DataProcessorInvocation.class)))
@org.springframework.web.bind.annotation.RequestBody DataProcessorInvocation invocation) {
content = @Content(schema = @Schema(implementation = DataProcessorInvocation.class)))
@org.springframework.web.bind.annotation.RequestBody DataProcessorInvocation invocation
) {
PipelineElementTemplate template = getPipelineElementTemplateStorage().getElementById(id);
return ok(new DataProcessorTemplateHandler(template, invocation, Boolean.parseBoolean(overwriteNameAndDescription))
.applyTemplateOnPipelineElement());
.applyTemplateOnPipelineElement());
}

@PostMapping(
path = "{id}/adapter",
produces = MediaType.APPLICATION_JSON_VALUE,
consumes = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Configure an adapter with a pipeline element template.",
tags = {"Pipeline Element Templates"},
responses = {
@ApiResponse(content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = AdapterDescription.class))
}, responseCode = "200", description = "The configured adapter model"),
})
tags = {"Pipeline Element Templates"},
responses = {
@ApiResponse(content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = AdapterDescription.class))
}, responseCode = "200", description = "The configured adapter model"),
})
public ResponseEntity<AdapterDescription> getPipelineElementForTemplate(
@Parameter(description = "The id of the pipeline element template", required = true)
@PathVariable("id") String id,
Expand All @@ -225,8 +234,9 @@ public ResponseEntity<AdapterDescription> getPipelineElementForTemplate(
@RequestParam("overwriteNames") String overwriteNameAndDescription,

@RequestBody(description = "The adapter that should be configured with the template contents",
content = @Content(schema = @Schema(implementation = AdapterDescription.class)))
@org.springframework.web.bind.annotation.RequestBody AdapterDescription adapterDescription) {
content = @Content(schema = @Schema(implementation = AdapterDescription.class)))
@org.springframework.web.bind.annotation.RequestBody AdapterDescription adapterDescription
) {
PipelineElementTemplate template = getPipelineElementTemplateStorage().getElementById(id);
var desc =
new AdapterTemplateHandler(template, adapterDescription, Boolean.parseBoolean(overwriteNameAndDescription))
Expand Down
62 changes: 62 additions & 0 deletions ui/cypress/tests/userManagement/testUserRoleConnect.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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 { UserBuilder } from '../../support/builder/UserBuilder';
import { UserRole } from '../../../src/app/_enums/user-role.enum';
import { UserUtils } from '../../support/utils/UserUtils';
import { ConnectUtils } from '../../support/utils/connect/ConnectUtils';
import { ConnectBtns } from '../../support/utils/connect/ConnectBtns';

describe('Test User Roles for Connect', () => {
beforeEach('Setup Test', () => {
cy.initStreamPipesTest();
ConnectUtils.addMachineDataSimulator('simulator');
});

it('Perform Test', () => {
// Add connect admin user
const connect_admin = UserBuilder.create('[email protected]')
.setName('connect_admin')
.setPassword('password')
.addRole(UserRole.ROLE_CONNECT_ADMIN)
.build();
UserUtils.addUser(connect_admin);

// Login as user and check if connect is visible to user
cy.switchUser(connect_admin);

cy.dataCy('navigation-icon', { timeout: 10000 }).should(
'have.length',
3,
);

ConnectUtils.goToConnect();
cy.dataCy('all-adapters-table', { timeout: 10000 }).should(
'have.length',
1,
);
cy.dataCy('all-adapters-table', { timeout: 10000 }).should(
'contain',
'simulator',
);

// validate that adapter can be stopped and edited
ConnectBtns.stopAdapter().click();
ConnectBtns.editAdapter().should('not.be.disabled');
ConnectBtns.editAdapter().click();
});
});
2 changes: 1 addition & 1 deletion ui/deployment/app-routing.module.mst
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const routes: Routes = [
{ path: '{{{link}}}', component: {{{ng5_component}}}, data: { authPageNames: [{{{pageNames}}}]}},
{{/componentImport}}
{{^componentImport}}
{ path: '', data: { authPageNames: [{{{pageNames}}}]}, loadChildren: () => import('{{{path}}}').then(m => m.{{{ng5_moduleName}}})},
{ path: '{{{link}}}', data: { authPageNames: [{{{pageNames}}}]}, loadChildren: () => import('{{{path}}}').then(m => m.{{{ng5_moduleName}}})},
{{/componentImport}}
{{/modulesActive}}

Expand Down
7 changes: 2 additions & 5 deletions ui/src/app/_guards/page-auth.can-active.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,14 @@
*
*/

import { ActivatedRouteSnapshot, Router } from '@angular/router';
import { ActivatedRouteSnapshot } from '@angular/router';
import { AuthService } from '../services/auth.service';
import { PageName } from '../_enums/page-name.enum';
import { Injectable } from '@angular/core';

@Injectable()
export class PageAuthGuard {
constructor(
private router: Router,
private authService: AuthService,
) {}
constructor(private authService: AuthService) {}

canActivateChild(activatedRouteSnapshot: ActivatedRouteSnapshot): boolean {
const pageNames: PageName[] = activatedRouteSnapshot.data.authPageNames;
Expand Down
2 changes: 1 addition & 1 deletion ui/src/app/add/add.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import { SharedUiModule } from '../../../projects/streampipes/shared-ui/src/lib/
MatProgressSpinnerModule,
RouterModule.forChild([
{
path: 'add',
path: '',
children: [
{
path: '',
Expand Down
2 changes: 1 addition & 1 deletion ui/src/app/app-overview/app-overview.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import { SharedUiModule } from '@streampipes/shared-ui';
SharedUiModule,
RouterModule.forChild([
{
path: 'apps',
path: '',
children: [
{ path: '', component: AppOverviewComponent },
...(AvailableAppsService.apps.map(app => {
Expand Down
2 changes: 1 addition & 1 deletion ui/src/app/assets/assets.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ import { SpManageAssetLinksDialogComponent } from './dialog/manage-asset-links/m
PlatformServicesModule,
RouterModule.forChild([
{
path: 'assets',
path: '',
children: [
{
path: '',
Expand Down
2 changes: 1 addition & 1 deletion ui/src/app/configuration/configuration.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ import { CodemirrorModule } from '@ctrl/ngx-codemirror';
PlatformServicesModule,
RouterModule.forChild([
{
path: 'configuration',
path: '',
children: [
{
path: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
mat-table
[dataSource]="dataSource"
style="width: 100%"
data-cy="all-adapters-table"
matSort
>
<ng-container matColumnDef="start">
Expand Down
Loading

0 comments on commit aaf6018

Please sign in to comment.