Skip to content

Commit

Permalink
IOT-1420: Api-key auth in swagger ui (#233)
Browse files Browse the repository at this point in the history
  • Loading branch information
fcv-iteratorIt authored Dec 15, 2023
1 parent e28031b commit 070e174
Show file tree
Hide file tree
Showing 23 changed files with 294 additions and 796 deletions.
6 changes: 6 additions & 0 deletions src/auth/swagger-auth-decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { applyDecorators } from "@nestjs/common";
import { ApiBearerAuth, ApiSecurity } from "@nestjs/swagger";

export function ApiAuth() {
return applyDecorators(ApiBearerAuth(), ApiSecurity("X-API-KEY"));
}
86 changes: 19 additions & 67 deletions src/controllers/admin-controller/application.controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BadRequestException } from "@nestjs/common";
import {
BadRequestException,
Body,
Controller,
Delete,
Expand All @@ -17,17 +17,16 @@ import {
} from "@nestjs/common";
import {
ApiBadRequestResponse,
ApiBearerAuth,
ApiForbiddenResponse,
ApiNotFoundResponse,
ApiOperation,
ApiProduces,
ApiResponse,
ApiTags,
ApiUnauthorizedResponse,
} from "@nestjs/swagger";
import { ApiResponse } from "@nestjs/swagger";

import { Read, ApplicationAdmin } from "@auth/roles.decorator";
import { ApplicationAdmin, Read } from "@auth/roles.decorator";
import { RolesGuard } from "@auth/roles.guard";
import { CreateApplicationDto } from "@dto/create-application.dto";
import { DeleteResponseDto } from "@dto/delete-application-response.dto";
Expand All @@ -49,11 +48,12 @@ import { ActionType } from "@entities/audit-log-entry";
import { ListAllEntitiesDto } from "@dto/list-all-entities.dto";
import { ListAllIoTDevicesResponseDto } from "@dto/list-all-iot-devices-response.dto";
import { ComposeAuthGuard } from "@auth/compose-auth.guard";
import { ApiAuth } from "@auth/swagger-auth-decorator";

@ApiTags("Application")
@Controller("application")
@UseGuards(ComposeAuthGuard, RolesGuard)
@ApiBearerAuth()
@ApiAuth()
@Read()
@ApiForbiddenResponse()
@ApiUnauthorizedResponse()
Expand Down Expand Up @@ -85,10 +85,7 @@ export class ApplicationController {
return await this.getApplicationsForNonGlobalAdmin(req, query);
}

private async getApplicationsForNonGlobalAdmin(
req: AuthenticatedRequest,
query: ListAllApplicationsDto
) {
private async getApplicationsForNonGlobalAdmin(req: AuthenticatedRequest, query: ListAllApplicationsDto) {
if (query?.organizationId) {
checkIfUserHasAccessToOrganization(req, query.organizationId, OrganizationAccessScope.ApplicationRead);
return await this.getApplicationsInOrganization(req, query);
Expand All @@ -104,34 +101,22 @@ export class ApplicationController {
return applications;
}

private async getApplicationsInOrganization(
req: AuthenticatedRequest,
query: ListAllApplicationsDto
) {
private async getApplicationsInOrganization(req: AuthenticatedRequest, query: ListAllApplicationsDto) {
// User admins have access to all applications in the organization
const allFromOrg = req.user.permissions.getAllOrganizationsWithUserAdmin();
if (allFromOrg.some(x => x === query?.organizationId)) {
return await this.applicationService.findAndCountWithPagination(query, [
query.organizationId,
]);
return await this.applicationService.findAndCountWithPagination(query, [query.organizationId]);
}

const allowedApplications = req.user.permissions.getAllApplicationsWithAtLeastRead();
return await this.applicationService.findAndCountInList(
query,
allowedApplications,
[query.organizationId]
);
return await this.applicationService.findAndCountInList(query, allowedApplications, [query.organizationId]);
}

@Read()
@Get(":id")
@ApiOperation({ summary: "Find one Application by id" })
@ApiNotFoundResponse()
async findOne(
@Req() req: AuthenticatedRequest,
@Param("id", new ParseIntPipe()) id: number
): Promise<Application> {
async findOne(@Req() req: AuthenticatedRequest, @Param("id", new ParseIntPipe()) id: number): Promise<Application> {
checkIfUserHasAccessToApplication(req, id, ApplicationAccessScope.Read);

try {
Expand All @@ -153,10 +138,7 @@ export class ApplicationController {
checkIfUserHasAccessToApplication(req, applicationId, ApplicationAccessScope.Read);

try {
return await this.applicationService.findDevicesForApplication(
applicationId,
query
);
return await this.applicationService.findDevicesForApplication(applicationId, query);
} catch (err) {
throw new NotFoundException(ErrorCodes.IdDoesNotExists);
}
Expand All @@ -177,29 +159,16 @@ export class ApplicationController {
OrganizationAccessScope.ApplicationWrite
);

const isValid = await this.applicationService.isNameValidAndNotUsed(
createApplicationDto?.name
);
const isValid = await this.applicationService.isNameValidAndNotUsed(createApplicationDto?.name);

if (!isValid) {
this.logger.error(
`Tried to create an application with name: '${createApplicationDto.name}'`
);
this.logger.error(`Tried to create an application with name: '${createApplicationDto.name}'`);
AuditLog.fail(ActionType.CREATE, Application.name, req.user.userId);
throw new BadRequestException(ErrorCodes.NameInvalidOrAlreadyInUse);
}

const application = await this.applicationService.create(
createApplicationDto,
req.user.userId
);
AuditLog.success(
ActionType.CREATE,
Application.name,
req.user.userId,
application.id,
application.name
);
const application = await this.applicationService.create(createApplicationDto, req.user.userId);
AuditLog.success(ActionType.CREATE, Application.name, req.user.userId, application.id, application.name);
return application;
}

Expand All @@ -214,32 +183,15 @@ export class ApplicationController {
@Body() updateApplicationDto: UpdateApplicationDto
): Promise<Application> {
checkIfUserHasAccessToApplication(req, id, ApplicationAccessScope.Write);
if (
!(await this.applicationService.isNameValidAndNotUsed(
updateApplicationDto?.name,
id
))
) {
this.logger.error(
`Tried to change an application with name: '${updateApplicationDto.name}'`
);
if (!(await this.applicationService.isNameValidAndNotUsed(updateApplicationDto?.name, id))) {
this.logger.error(`Tried to change an application with name: '${updateApplicationDto.name}'`);
AuditLog.fail(ActionType.UPDATE, Application.name, req.user.userId);
throw new BadRequestException(ErrorCodes.NameInvalidOrAlreadyInUse);
}

const application = await this.applicationService.update(
id,
updateApplicationDto,
req.user.userId
);
const application = await this.applicationService.update(id, updateApplicationDto, req.user.userId);

AuditLog.success(
ActionType.UPDATE,
Application.name,
req.user.userId,
application.id,
application.name
);
AuditLog.success(ActionType.UPDATE, Application.name, req.user.userId, application.id, application.name);
return application;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import {
Req,
UseGuards,
} from "@nestjs/common";
import { ApiBadRequestResponse, ApiBearerAuth, ApiOperation, ApiProduces, ApiTags } from "@nestjs/swagger";
import { ApiBadRequestResponse, ApiOperation, ApiProduces, ApiTags } from "@nestjs/swagger";

import { Read, GatewayAdmin } from "@auth/roles.decorator";
import { GatewayAdmin, Read } from "@auth/roles.decorator";
import { RolesGuard } from "@auth/roles.guard";
import { ChirpstackResponseStatus } from "@dto/chirpstack/chirpstack-response.dto";
import { CreateGatewayDto } from "@dto/chirpstack/create-gateway.dto";
Expand All @@ -29,11 +29,12 @@ import { AuditLog } from "@services/audit-log.service";
import { ActionType } from "@entities/audit-log-entry";
import { ChirpstackGetAll } from "@dto/chirpstack/chirpstack-get-all.dto";
import { ComposeAuthGuard } from "@auth/compose-auth.guard";
import { ApiAuth } from "@auth/swagger-auth-decorator";

@ApiTags("Chirpstack")
@Controller("chirpstack/gateway")
@UseGuards(ComposeAuthGuard, RolesGuard)
@ApiBearerAuth()
@ApiAuth()
export class ChirpstackGatewayController {
constructor(private chirpstackGatewayService: ChirpstackGatewayService) {}

Expand Down
Loading

0 comments on commit 070e174

Please sign in to comment.