security: restrict cluster/pool selection to admin users only

Backend:
- ApplicationsService.create() now accepts userRole parameter
- Non-admin users have clusterId/poolId stripped automatically
- Logs warning when non-admin attempts manual cluster selection

Frontend:
- Deploy wizard hides cluster assignment mode selector for non-admin users
- Non-admin users see a simple 'Default Cluster' info box instead
- Cluster/pool API queries only execute for admin users (enabled: isAdmin)
- Review step shows 'Default Cluster' for non-admin regardless of form state
This commit is contained in:
keyhan
2026-04-06 11:36:58 +03:30
parent 4853fe3020
commit 4fd102468e
4 changed files with 36 additions and 6 deletions
@@ -42,7 +42,7 @@ export class ApplicationsController {
@Post()
@ApiOperation({ summary: 'Create a new application' })
async create(@Request() req: any, @Body() dto: CreateApplicationDto) {
return this.applicationsService.create(req.user.id, dto);
return this.applicationsService.create(req.user.id, dto, req.user.role);
}
@Post(':id/upload')
@@ -7,6 +7,7 @@ import * as path from 'path';
import { Application } from './entities/application.entity';
import { CreateApplicationDto, UpdateApplicationDto } from './dto/application.dto';
import { ClustersService } from '../clusters/clusters.service';
import { UserRole } from '../common/enums';
@Injectable()
export class ApplicationsService {
@@ -19,7 +20,17 @@ export class ApplicationsService {
private configService: ConfigService,
) {}
async create(userId: string, dto: CreateApplicationDto): Promise<Application> {
async create(userId: string, dto: CreateApplicationDto, userRole?: string): Promise<Application> {
// Only admin users can manually select cluster or pool
// Regular users always get the default cluster assignment
if (userRole !== UserRole.ADMIN) {
if (dto.clusterId || dto.poolId) {
this.logger.warn(`Non-admin user ${userId} attempted manual cluster/pool selection — ignoring`);
}
dto.clusterId = undefined;
dto.poolId = undefined;
}
// Cluster assignment: 3 modes
// 1. Manual: specific clusterId provided
// 2. Pool-based LB: poolId provided → pick from pool using pool's strategy