diff --git a/src/modules/option/controllers/base.option.controller.ts b/src/modules/option/controllers/base.option.controller.ts new file mode 100644 index 00000000..1d08c25b --- /dev/null +++ b/src/modules/option/controllers/base.option.controller.ts @@ -0,0 +1,56 @@ +import { + BadRequestException, + Body, + Get, + Param, + Patch, + UnprocessableEntityException, +} from '@nestjs/common' +import { instanceToPlain } from 'class-transformer' +import { HTTPDecorators } from '~/common/decorator/http.decorator' +import { IConfig } from '~/modules/configs/configs.interface' +import { ConfigsService } from '~/modules/configs/configs.service' +import { classToJsonSchema } from '~/utils/jsonschema.util' +import { ConfigKeyDto } from '../dtos/config.dto' +import { OptionController } from '../option.decorator' + +@OptionController() +export class BaseOptionController { + constructor( + private readonly configsService: ConfigsService, + private readonly configs: ConfigsService, + ) {} + + @Get('/') + getOption() { + return instanceToPlain(this.configs.getConfig()) + } + + @HTTPDecorators.Bypass + @Get('/jsonschema') + getJsonSchema() { + return classToJsonSchema(IConfig) + } + + @Get('/:key') + async getOptionKey(@Param('key') key: keyof IConfig) { + if (typeof key !== 'string' && !key) { + throw new UnprocessableEntityException( + 'key must be IConfigKeys, got ' + key, + ) + } + const value = await this.configs.get(key) + if (!value) { + throw new BadRequestException('key is not exists.') + } + return { data: instanceToPlain(value) } + } + + @Patch('/:key') + patch(@Param() params: ConfigKeyDto, @Body() body: Record) { + if (typeof body !== 'object') { + throw new UnprocessableEntityException('body must be object') + } + return this.configsService.patchAndValid(params.key, body) + } +} diff --git a/src/modules/option/controllers/email.option.controller.ts b/src/modules/option/controllers/email.option.controller.ts new file mode 100644 index 00000000..c0334ff8 --- /dev/null +++ b/src/modules/option/controllers/email.option.controller.ts @@ -0,0 +1,52 @@ +import { Body, Delete, Get, Put, Query } from '@nestjs/common' +import { + EmailService, + EmailTemplateRenderProps, + ReplyMailType, +} from '~/processors/helper/helper.email.service' +import { ReplyEmailBodyDto, ReplyEmailTypeDto } from '../dtos/email.dto' +import { OptionController } from '../option.decorator' + +@OptionController('Email', 'email') +export class EmailOptionController { + constructor(private readonly emailService: EmailService) {} + @Get('/template/reply') + async getEmailReplyTemplate(@Query() { type }: ReplyEmailTypeDto) { + const template = await this.emailService.readTemplate( + type === 'guest' ? ReplyMailType.Guest : ReplyMailType.Owner, + ) + return { + template, + props: { + author: '评论人Kemmer', + link: 'https://example.com', + mail: 'example@example.com', + text: '这是一段回复评论', + title: '文章的标题', + time: '2020/01/01', + master: '你的名字', + ip: '0.0.0.0', + } as EmailTemplateRenderProps, + } + } + + @Put('/template/reply') + writeEmailReplyTemplate( + @Query() { type }: ReplyEmailTypeDto, + @Body() body: ReplyEmailBodyDto, + ) { + this.emailService.writeTemplate( + type === 'guest' ? ReplyMailType.Guest : ReplyMailType.Owner, + body.source, + ) + return { + source: body.source, + } + } + + @Delete('/template/reply') + async deleteEmailReplyTemplate(@Query() { type }: ReplyEmailTypeDto) { + await this.emailService.deleteTemplate(type) + return + } +} diff --git a/src/modules/option/option.controller.ts b/src/modules/option/option.controller.ts deleted file mode 100644 index 11de4638..00000000 --- a/src/modules/option/option.controller.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { - BadRequestException, - Body, - Controller, - Delete, - Get, - Param, - Patch, - Put, - Query, - UnprocessableEntityException, -} from '@nestjs/common' -import { ApiTags } from '@nestjs/swagger' -import { instanceToPlain } from 'class-transformer' -import { Auth } from '~/common/decorator/auth.decorator' -import { - EmailService, - EmailTemplateRenderProps, - ReplyMailType, -} from '~/processors/helper/helper.email.service' -import { IConfig } from '../configs/configs.interface' -import { ConfigsService } from '../configs/configs.service' -import { ConfigKeyDto } from './dtos/config.dto' -import { ReplyEmailBodyDto, ReplyEmailTypeDto } from './dtos/email.dto' - -@Controller(['options', 'config', 'setting', 'configs', 'option']) -@ApiTags('Option Routes') -@Auth() -export class OptionController { - constructor( - private readonly configsService: ConfigsService, - private readonly configs: ConfigsService, - private readonly emailService: EmailService, - ) {} - - @Get('/') - getOption() { - return instanceToPlain(this.configs.getConfig()) - } - - @Get('/:key') - async getOptionKey(@Param('key') key: keyof IConfig) { - if (typeof key !== 'string' && !key) { - throw new UnprocessableEntityException( - 'key must be IConfigKeys, got ' + key, - ) - } - const value = await this.configs.get(key) - if (!value) { - throw new BadRequestException('key is not exists.') - } - return { data: instanceToPlain(value) } - } - - @Patch('/:key') - patch(@Param() params: ConfigKeyDto, @Body() body: Record) { - if (typeof body !== 'object') { - throw new UnprocessableEntityException('body must be object') - } - return this.configsService.patchAndValid(params.key, body) - } - - @Get('/email/template/reply') - async getEmailReplyTemplate(@Query() { type }: ReplyEmailTypeDto) { - const template = await this.emailService.readTemplate( - type === 'guest' ? ReplyMailType.Guest : ReplyMailType.Owner, - ) - return { - template, - props: { - author: '评论人Kemmer', - link: 'https://example.com', - mail: 'example@example.com', - text: '这是一段回复评论', - title: '文章的标题', - time: '2020/01/01', - master: '你的名字', - ip: '0.0.0.0', - } as EmailTemplateRenderProps, - } - } - - @Put('/email/template/reply') - writeEmailReplyTemplate( - @Query() { type }: ReplyEmailTypeDto, - @Body() body: ReplyEmailBodyDto, - ) { - this.emailService.writeTemplate( - type === 'guest' ? ReplyMailType.Guest : ReplyMailType.Owner, - body.source, - ) - return { - source: body.source, - } - } - - @Delete('/email/template/reply') - async deleteEmailReplyTemplate(@Query() { type }: ReplyEmailTypeDto) { - await this.emailService.deleteTemplate(type) - return - } -} diff --git a/src/modules/option/option.decorator.ts b/src/modules/option/option.decorator.ts new file mode 100644 index 00000000..f9e7058e --- /dev/null +++ b/src/modules/option/option.decorator.ts @@ -0,0 +1,14 @@ +import { applyDecorators, Controller } from '@nestjs/common' +import { ApiTags } from '@nestjs/swagger' +import { Auth } from '~/common/decorator/auth.decorator' + +export function OptionController(name?: string, postfixRoute?: string) { + const routes = ['options', 'config', 'setting', 'configs', 'option'] + return applyDecorators( + Auth(), + Controller( + postfixRoute ? routes.map((route) => route + '/' + postfixRoute) : routes, + ), + ApiTags(`${name ? name + ' ' : ''}Option Routes`), + ) +} diff --git a/src/modules/option/option.module.ts b/src/modules/option/option.module.ts index e286d141..6060621a 100644 --- a/src/modules/option/option.module.ts +++ b/src/modules/option/option.module.ts @@ -1,9 +1,10 @@ import { Module } from '@nestjs/common' import { GatewayModule } from '~/processors/gateway/gateway.module' -import { OptionController } from './option.controller' +import { BaseOptionController } from './controllers/base.option.controller' +import { EmailOptionController } from './controllers/email.option.controller' @Module({ imports: [GatewayModule], - controllers: [OptionController], + controllers: [BaseOptionController, EmailOptionController], }) export class OptionModule {}