Skip to content

Commit

Permalink
feat(api): Added validation for reason field (#190)
Browse files Browse the repository at this point in the history
  • Loading branch information
JosephFak authored Apr 24, 2024
1 parent b38d45a commit 90b8ff2
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 21 deletions.
3 changes: 2 additions & 1 deletion apps/api/src/approval/controller/approval.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from '@prisma/client'
import { CurrentUser } from '../../decorators/user.decorator'
import { RequiredApiKeyAuthorities } from '../../decorators/required-api-key-authorities.decorator'
import { AlphanumericReasonValidationPipe } from '../../common/alphanumeric-reason-pipe'

@Controller('approval')
export class ApprovalController {
Expand All @@ -20,7 +21,7 @@ export class ApprovalController {
async updateApproval(
@CurrentUser() user: User,
@Param('approvalId') approvalId: Approval['id'],
@Query('reason') reason: string
@Query('reason', AlphanumericReasonValidationPipe) reason: string
) {
return this.approvalService.updateApproval(user, reason, approvalId)
}
Expand Down
29 changes: 29 additions & 0 deletions apps/api/src/common/alphanumeric-reason-pipe.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { AlphanumericReasonValidationPipe } from './alphanumeric-reason-pipe';
import { BadRequestException } from '@nestjs/common';

describe('AlphanumericReasonValidationPipe', () => {
let pipe: AlphanumericReasonValidationPipe;

beforeEach(() => {
pipe = new AlphanumericReasonValidationPipe();
});

it('should allow alphanumeric string', () => {
const validInput = 'Test123';
expect(pipe.transform(validInput)).toBe(validInput);
});

it('should not allow strings with only spaces', () => {
expect(() => pipe.transform(' ')).toThrow(BadRequestException);
});

it('should throw BadRequestException for non-alphanumeric string', () => {
const invalidInput = 'Test123$%^';
try {
pipe.transform(invalidInput);
} catch (e) {
expect(e).toBeInstanceOf(BadRequestException);
expect(e.message).toBe('Reason must contain only alphanumeric characters and no leading or trailing spaces.');
}
});
});
12 changes: 12 additions & 0 deletions apps/api/src/common/alphanumeric-reason-pipe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common';

@Injectable()
export class AlphanumericReasonValidationPipe implements PipeTransform {
transform(value: string) {
if (/^[a-zA-Z0-9]+(?: [a-zA-Z0-9]+)*$/.test(value)) {
return value;
} else {
throw new BadRequestException('Reason must contain only alphanumeric characters and no leading or trailing spaces.');
}
}
}
7 changes: 4 additions & 3 deletions apps/api/src/environment/controller/environment.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Authority, User } from '@prisma/client'
import { UpdateEnvironment } from '../dto/update.environment/update.environment'
import { ApiTags } from '@nestjs/swagger'
import { RequiredApiKeyAuthorities } from '../../decorators/required-api-key-authorities.decorator'
import { AlphanumericReasonValidationPipe } from '../../common/alphanumeric-reason-pipe'

@ApiTags('Environment Controller')
@Controller('environment')
Expand All @@ -27,7 +28,7 @@ export class EnvironmentController {
@CurrentUser() user: User,
@Body() dto: CreateEnvironment,
@Param('projectId') projectId: string,
@Query('reason') reason: string
@Query('reason', AlphanumericReasonValidationPipe) reason: string
) {
return await this.environmentService.createEnvironment(
user,
Expand All @@ -43,7 +44,7 @@ export class EnvironmentController {
@CurrentUser() user: User,
@Body() dto: UpdateEnvironment,
@Param('environmentId') environmentId: string,
@Query('reason') reason: string
@Query('reason', AlphanumericReasonValidationPipe) reason: string
) {
return await this.environmentService.updateEnvironment(
user,
Expand Down Expand Up @@ -89,7 +90,7 @@ export class EnvironmentController {
async deleteEnvironment(
@CurrentUser() user: User,
@Param('environmentId') environmentId: string,
@Query('reason') reason: string
@Query('reason', AlphanumericReasonValidationPipe) reason: string
) {
return await this.environmentService.deleteEnvironment(
user,
Expand Down
7 changes: 4 additions & 3 deletions apps/api/src/project/controller/project.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { CreateProject } from '../dto/create.project/create.project'
import { UpdateProject } from '../dto/update.project/update.project'
import { ApiTags } from '@nestjs/swagger'
import { RequiredApiKeyAuthorities } from '../../decorators/required-api-key-authorities.decorator'
import { AlphanumericReasonValidationPipe } from '../../common/alphanumeric-reason-pipe'

@ApiTags('Project Controller')
@Controller('project')
Expand All @@ -27,7 +28,7 @@ export class ProjectController {
@CurrentUser() user: User,
@Param('workspaceId') workspaceId: Workspace['id'],
@Body() dto: CreateProject,
@Query('reason') reason: string
@Query('reason', AlphanumericReasonValidationPipe) reason: string
) {
return await this.service.createProject(user, workspaceId, dto, reason)
}
Expand All @@ -38,7 +39,7 @@ export class ProjectController {
@CurrentUser() user: User,
@Param('projectId') projectId: Project['id'],
@Body() dto: UpdateProject,
@Query('reason') reason: string
@Query('reason', AlphanumericReasonValidationPipe) reason: string
) {
return await this.service.updateProject(user, projectId, dto, reason)
}
Expand All @@ -48,7 +49,7 @@ export class ProjectController {
async deleteProject(
@CurrentUser() user: User,
@Param('projectId') projectId: Project['id'],
@Query('reason') reason: string
@Query('reason', AlphanumericReasonValidationPipe) reason: string
) {
return await this.service.deleteProject(user, projectId, reason)
}
Expand Down
11 changes: 6 additions & 5 deletions apps/api/src/secret/controller/secret.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { CreateSecret } from '../dto/create.secret/create.secret'
import { UpdateSecret } from '../dto/update.secret/update.secret'
import { ApiTags } from '@nestjs/swagger'
import { RequiredApiKeyAuthorities } from '../../decorators/required-api-key-authorities.decorator'
import { AlphanumericReasonValidationPipe } from '../../common/alphanumeric-reason-pipe'

@ApiTags('Secret Controller')
@Controller('secret')
Expand All @@ -27,7 +28,7 @@ export class SecretController {
@CurrentUser() user: User,
@Param('projectId') projectId: string,
@Body() dto: CreateSecret,
@Query('reason') reason: string
@Query('reason', AlphanumericReasonValidationPipe) reason: string
) {
return await this.secretService.createSecret(user, dto, projectId, reason)
}
Expand All @@ -38,7 +39,7 @@ export class SecretController {
@CurrentUser() user: User,
@Param('secretId') secretId: string,
@Body() dto: UpdateSecret,
@Query('reason') reason: string
@Query('reason', AlphanumericReasonValidationPipe) reason: string
) {
return await this.secretService.updateSecret(user, secretId, dto, reason)
}
Expand All @@ -52,7 +53,7 @@ export class SecretController {
@CurrentUser() user: User,
@Param('secretId') secretId: string,
@Param('environmentId') environmentId: string,
@Query('reason') reason: string
@Query('reason', AlphanumericReasonValidationPipe) reason: string
) {
return await this.secretService.updateSecretEnvironment(
user,
Expand All @@ -68,7 +69,7 @@ export class SecretController {
@CurrentUser() user: User,
@Param('secretId') secretId: string,
@Param('rollbackVersion') rollbackVersion: number,
@Query('reason') reason: string
@Query('reason', AlphanumericReasonValidationPipe) reason: string
) {
return await this.secretService.rollbackSecret(
user,
Expand All @@ -83,7 +84,7 @@ export class SecretController {
async deleteSecret(
@CurrentUser() user: User,
@Param('secretId') secretId: string,
@Query('reason') reason: string
@Query('reason', AlphanumericReasonValidationPipe) reason: string
) {
return await this.secretService.deleteSecret(user, secretId, reason)
}
Expand Down
14 changes: 7 additions & 7 deletions apps/api/src/variable/controller/variable.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import { ApiTags } from '@nestjs/swagger'
import { VariableService } from '../service/variable.service'
import { RequiredApiKeyAuthorities } from '../../decorators/required-api-key-authorities.decorator'
import { Authority, User } from '@prisma/client'
import { AlphanumericReasonValidationPipe } from '../../common/alphanumeric-reason-pipe'
import { CurrentUser } from '../../decorators/user.decorator'
import { CreateVariable } from '../dto/create.variable/create.variable'
import { UpdateVariable } from '../dto/update.variable/update.variable'

@ApiTags('Variable Controller')
@Controller('variable')
Expand All @@ -27,7 +27,7 @@ export class VariableController {
@CurrentUser() user: User,
@Param('projectId') projectId: string,
@Body() dto: CreateVariable,
@Query('reason') reason: string
@Query('reason', AlphanumericReasonValidationPipe ) reason: string
) {
return await this.variableService.createVariable(
user,
Expand All @@ -42,8 +42,8 @@ export class VariableController {
async updateVariable(
@CurrentUser() user: User,
@Param('variableId') variableId: string,
@Body() dto: UpdateVariable,
@Query('reason') reason: string
@Body() dto: CreateVariable,
@Query('reason', AlphanumericReasonValidationPipe) reason: string
) {
return await this.variableService.updateVariable(
user,
Expand All @@ -62,7 +62,7 @@ export class VariableController {
@CurrentUser() user: User,
@Param('variableId') variableId: string,
@Param('environmentId') environmentId: string,
@Query('reason') reason: string
@Query('reason', AlphanumericReasonValidationPipe) reason: string
) {
return await this.variableService.updateVariableEnvironment(
user,
Expand All @@ -78,7 +78,7 @@ export class VariableController {
@CurrentUser() user: User,
@Param('variableId') variableId: string,
@Param('rollbackVersion') rollbackVersion: number,
@Query('reason') reason: string
@Query('reason', AlphanumericReasonValidationPipe) reason: string
) {
return await this.variableService.rollbackVariable(
user,
Expand All @@ -93,7 +93,7 @@ export class VariableController {
async deleteVariable(
@CurrentUser() user: User,
@Param('variableId') variableId: string,
@Query('reason') reason: string
@Query('reason', AlphanumericReasonValidationPipe) reason: string
) {
return await this.variableService.deleteVariable(user, variableId, reason)
}
Expand Down
5 changes: 3 additions & 2 deletions apps/api/src/workspace/controller/workspace.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
import { WorkspaceService } from '../service/workspace.service'
import { CurrentUser } from '../../decorators/user.decorator'
import { Authority, User, Workspace, WorkspaceRole } from '@prisma/client'
import {
import { AlphanumericReasonValidationPipe } from '../../common/alphanumeric-reason-pipe'
import{
CreateWorkspace,
WorkspaceMemberDTO
} from '../dto/create.workspace/create.workspace'
Expand All @@ -34,7 +35,7 @@ export class WorkspaceController {
@CurrentUser() user: User,
@Param('workspaceId') workspaceId: Workspace['id'],
@Body() dto: UpdateWorkspace,
@Query('reason') reason: string
@Query('reason', AlphanumericReasonValidationPipe) reason: string
) {
return this.workspaceService.updateWorkspace(user, workspaceId, dto, reason)
}
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,13 @@
"husky": "^9.0.11",
"prettier": "^3.0.0",
"prettier-plugin-tailwindcss": "^0.5.11",
"prisma": "5.12.1",
"tsconfig": "workspace:*",
"turbo": "^1.12.4"
},
"dependencies": {
"@million/lint": "^0.0.73",
"@prisma/client": "5.12.1",
"@sentry/node": "^7.102.0",
"@sentry/profiling-node": "^7.102.0",
"million": "^3.0.5",
Expand Down
54 changes: 54 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 90b8ff2

Please sign in to comment.