Skip to content

Commit

Permalink
fix(server): fix dto validation method, fix cors config (#446)
Browse files Browse the repository at this point in the history
Signed-off-by: maslow <wangfugen@126.com>

Signed-off-by: maslow <wangfugen@126.com>
  • Loading branch information
maslow authored Nov 29, 2022
1 parent f5cea5c commit d147a73
Show file tree
Hide file tree
Showing 14 changed files with 25,087 additions and 75 deletions.
25,011 changes: 25,011 additions & 0 deletions server/package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
"@nestjs/throttler": "^3.1.0",
"@prisma/client": "^4.6.1",
"casdoor-nodejs-sdk": "^1.3.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.13.2",
"dotenv": "^16.0.3",
"fast-json-patch": "^3.1.1",
"mongodb": "^4.12.1",
Expand Down
4 changes: 2 additions & 2 deletions server/src/applications/applications.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class ApplicationsController {
@Post()
async create(@Body() dto: CreateApplicationDto, @Req() req: IRequest) {
const user = req.user
const error = CreateApplicationDto.validate(dto)
const error = dto.validate()
if (error) {
return ResponseUtil.error(error)
}
Expand Down Expand Up @@ -107,7 +107,7 @@ export class ApplicationsController {
@Req() req: IRequest,
) {
// check dto
const error = UpdateApplicationDto.validate(dto)
const error = dto.validate()
if (error) {
return ResponseUtil.error(error)
}
Expand Down
2 changes: 1 addition & 1 deletion server/src/applications/applications.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export class ApplicationsService {

try {
const res = await this.k8sClient.objectApi.create(app)
return res.body
return Application.fromObject(res.body)
} catch (error) {
this.logger.error(error, error?.response.body)
return null
Expand Down
28 changes: 11 additions & 17 deletions server/src/applications/dto/create-application.dto.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,34 @@
import { ApiProperty } from '@nestjs/swagger'
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'
import { IsEnum, IsNotEmpty, Length } from 'class-validator'
import { ApplicationState } from '../entities/application.entity'

export class CreateApplicationDto {
@ApiProperty({ required: true })
@Length(1, 64)
@IsNotEmpty()
displayName: string

@ApiProperty({
@ApiPropertyOptional({
default: ApplicationState.ApplicationStateRunning,
required: false,
enum: ApplicationState,
})
@IsNotEmpty()
@IsEnum(ApplicationState)
state: ApplicationState

@ApiProperty()
@IsNotEmpty()
region: string

@ApiProperty()
@IsNotEmpty()
bundleName: string

@ApiProperty()
@IsNotEmpty()
runtimeName: string

static validate(dto: CreateApplicationDto): string | null {
if (!dto.displayName) {
return 'name is required'
}
if (!dto.state) {
return 'state is required'
}
if (!dto.region) {
return 'region is required'
}
if (!dto.bundleName) {
return 'bundleName is required'
}

validate(): string | null {
return null
}
}
10 changes: 3 additions & 7 deletions server/src/applications/dto/update-application.dto.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ApiPropertyOptional } from '@nestjs/swagger'
import { IsIn } from 'class-validator'
import { ApplicationState } from '../entities/application.entity'

const STATES = ['Running', 'Stopped']
Expand All @@ -12,15 +13,10 @@ export class UpdateApplicationDto {
@ApiPropertyOptional({
enum: STATES,
})
@IsIn(STATES)
state?: ApplicationState

static validate(dto: UpdateApplicationDto) {
if (dto.state) {
if (!STATES.includes(dto.state)) {
return 'state must be running or stopped'
}
}

validate() {
return null
}
}
17 changes: 9 additions & 8 deletions server/src/buckets/buckets.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'
import { ApplicationAuthGuard } from 'src/applications/application.auth.guard'
import { IRequest } from 'src/common/types'
import { ApplicationsService } from '../applications/applications.service'
import { JwtAuthGuard } from '../auth/jwt-auth.guard'
import { ApiResponseUtil, ResponseUtil } from '../common/response'
import { BucketsService } from './buckets.service'
Expand All @@ -28,10 +27,7 @@ import { Bucket, BucketList } from './entities/bucket.entity'
@Controller('apps/:appid/buckets')
export class BucketsController {
logger = new Logger(BucketsController.name)
constructor(
private readonly bucketsService: BucketsService,
private readonly appService: ApplicationsService,
) {}
constructor(private readonly bucketsService: BucketsService) {}

/**
* Create a new bucket
Expand All @@ -43,9 +39,14 @@ export class BucketsController {
@ApiOperation({ summary: 'Create a new bucket' })
@UseGuards(JwtAuthGuard, ApplicationAuthGuard)
@Post()
async create(@Body() dto: CreateBucketDto, @Req() req: IRequest) {
async create(
@Param('appid') appid: string,
@Body() dto: CreateBucketDto,
@Req() req: IRequest,
) {
// check if the bucket name is unique
const found = await this.bucketsService.findOne(dto.appid, dto.name)

const found = await this.bucketsService.findOne(appid, dto.fullname(appid))
if (found) {
return ResponseUtil.error('bucket name is already existed')
}
Expand All @@ -58,7 +59,7 @@ export class BucketsController {
)

// create bucket
const bucket = await this.bucketsService.create(dto)
const bucket = await this.bucketsService.create(appid, dto)
if (!bucket) {
return ResponseUtil.error('create bucket failed')
}
Expand Down
6 changes: 3 additions & 3 deletions server/src/buckets/buckets.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ export class BucketsService {
logger: Logger = new Logger(BucketsService.name)
constructor(private readonly k8sClient: KubernetesService) {}

async create(dto: CreateBucketDto) {
const namespace = GetApplicationNamespaceById(dto.appid)
const bucket = new Bucket(dto.name, namespace)
async create(appid: string, dto: CreateBucketDto) {
const namespace = GetApplicationNamespaceById(appid)
const bucket = new Bucket(dto.fullname(appid), namespace)
bucket.spec = {
policy: dto.policy,
storage: dto.storage,
Expand Down
14 changes: 9 additions & 5 deletions server/src/buckets/dto/create-bucket.dto.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
import { ApiProperty } from '@nestjs/swagger'
import { IsEnum, IsNotEmpty, IsString, Length } from 'class-validator'
import { BucketPolicy } from '../entities/bucket.entity'

export class CreateBucketDto {
@ApiProperty({
description: 'The short name of the bucket which not contain the appid',
})
@IsNotEmpty()
@Length(3, 32)
shortName: string

@ApiProperty()
appid: string

@ApiProperty({
enum: BucketPolicy,
})
@IsEnum(BucketPolicy)
@IsNotEmpty()
policy: BucketPolicy

@ApiProperty({
description: 'The storage capacity of the bucket: "1Gi", "0.5Gi", "100Gi"',
})
@IsNotEmpty()
@IsString()
storage: string

get name() {
return `${this.appid}-${this.shortName}`
fullname(appid: string) {
return `${appid}-${this.shortName}`
}
}
7 changes: 3 additions & 4 deletions server/src/collections/dto/create-collection.dto.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { ApiProperty } from '@nestjs/swagger'
import { IsNotEmpty, Length } from 'class-validator'

export class CreateCollectionDto {
@ApiProperty()
@IsNotEmpty()
@Length(3, 32)
name: string

async validate() {
if (!this.name) {
return 'Collection name is required'
}

return null
}
}
2 changes: 2 additions & 0 deletions server/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,5 @@ export class ResourceLabels {
return 'laf.dev/namespace.type'
}
}

export const HTTP_METHODS = ['HEAD', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH']
37 changes: 17 additions & 20 deletions server/src/functions/dto/create-function.dto.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,37 @@
import { ApiProperty } from '@nestjs/swagger'
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'
import { IsIn, IsNotEmpty, IsString, Length, MaxLength } from 'class-validator'
import { HTTP_METHODS } from 'src/constants'

export class CreateFunctionDto {
@ApiProperty({
description: 'Function name is unique in the application',
})
@IsNotEmpty()
@Length(1, 128)
name: string

@ApiProperty()
@ApiPropertyOptional()
@MaxLength(256)
description: string

@ApiProperty()
websocket: boolean

@ApiProperty({
type: [String],
enum: ['HEAD', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
})
@ApiProperty({ type: [String], enum: HTTP_METHODS })
@IsIn(HTTP_METHODS)
methods: string[] = []

@ApiProperty({
description: 'The source code of the function',
})
@ApiProperty({ description: 'The source code of the function' })
@IsNotEmpty()
@IsString()
@MaxLength(1024 * 512)
codes: string

static validate(dto: CreateFunctionDto) {
if (!dto.name) {
return 'name is required'
}

if (!dto.methods) {
dto.methods = []
validate() {
if (!this.methods) {
this.methods = []
}

const valid = dto.methods.every((method) => {
return ['HEAD', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH'].includes(method)
})
const valid = this.methods.every((method) => HTTP_METHODS.includes(method))
if (!valid) {
return 'methods is invalid'
}
Expand Down
2 changes: 1 addition & 1 deletion server/src/functions/functions.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class FunctionsController {
@UseGuards(JwtAuthGuard, ApplicationAuthGuard)
@Post()
async create(@Param('appid') appid: string, @Body() dto: CreateFunctionDto) {
const error = CreateFunctionDto.validate(dto)
const error = dto.validate()
if (error) {
return ResponseUtil.error(error)
}
Expand Down
20 changes: 13 additions & 7 deletions server/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,35 @@
import { NestFactory } from '@nestjs/core'
import { AppModule } from './app.module'
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'
import { ValidationPipe } from '@nestjs/common'
import { HTTP_METHODS } from './constants'

async function bootstrap() {
const app = await NestFactory.create(AppModule, {
cors: {
// TODO: only allow localhost:3000
origin: 'http://localhost:3001',
credentials: true,
},
const app = await NestFactory.create(AppModule)

app.enableCors({
origin: '*',
methods: HTTP_METHODS,
credentials: true,
allowedHeaders: ['Content-Type', 'Authorization'],
})

app.setGlobalPrefix('v1')
app.useGlobalPipes(new ValidationPipe({ transform: true }))

// for swagger api
const config = new DocumentBuilder()
.setTitle('Open API Documentation of laf')
.setDescription('`The APIs of laf server`')
.setVersion('1.0.alpha')
.addServer('http://localhost:3000')
.addServer('http://localhost:3000', 'local server')
.addServer('http://dev.server:3000', 'dev server')
.addBearerAuth(
{ type: 'http', scheme: 'bearer', bearerFormat: 'JWT', in: 'header' },
'Authorization',
)
.build()

const document = SwaggerModule.createDocument(app, config)
SwaggerModule.setup('api', app, document, {
swaggerOptions: {
Expand Down

0 comments on commit d147a73

Please sign in to comment.