-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: 重构 CRUD 相关逻辑;修改错误处理中间件;增加规则实体类
- Loading branch information
1 parent
9f0ba96
commit a331d84
Showing
10 changed files
with
255 additions
and
221 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { Column, Entity } from 'typeorm' | ||
import { Base } from './base' | ||
|
||
/** | ||
* 规则实体类 | ||
* 用于配置接收到用户消息时,需要执行的操作 | ||
* | ||
* @author CaoMeiYouRen | ||
* @date 2024-10-01 | ||
* @export | ||
* @class Rule | ||
*/ | ||
@Entity() | ||
export class Rule extends Base { | ||
|
||
// 规则名称 | ||
@Column({ type: 'varchar', length: 255, nullable: false }) | ||
name: string | ||
|
||
// 规则描述 | ||
@Column({ type: 'varchar', length: 1024, nullable: true }) | ||
description?: string | ||
|
||
// 规则是否启用 | ||
@Column({ type: 'boolean', default: true }) | ||
enabled: boolean | ||
|
||
// 规则优先级 | ||
@Column({ type: 'int', default: 0 }) | ||
priority: number | ||
|
||
// 规则类型,文本或正则 | ||
@Column({ type: 'varchar', length: 50, nullable: false }) | ||
type: 'text' | 'regex' | ||
|
||
// 规则匹配的文本或正则 | ||
@Column({ type: 'varchar', length: 1024, nullable: true }) | ||
match?: string | ||
|
||
// 规则执行的操作,回复文本/转发/屏蔽/验证码/登录链接(OAuth2) | ||
@Column({ type: 'varchar', length: 50, nullable: false }) | ||
action: 'reply' | 'forward' | 'block' | 'verify' | 'login' | ||
|
||
// 回复内容,如果是回复,则需要填写 | ||
@Column({ type: 'varchar', length: 1024, nullable: true }) | ||
content?: string | ||
|
||
// 转发的目标,如果是转发,则需要填写 | ||
@Column({ type: 'varchar', length: 255, nullable: true }) | ||
target?: string | ||
|
||
// OAuth2 登录的 url,会用 POST 方法请求该地址,提交内容为 appId、token、timestamp、sign | ||
// token 为用户的 jwtToken,timestamp 为当前时间戳,sign 为 appId + appSecret + token + timeStamp 的 sha256 哈希值 | ||
@Column({ type: 'varchar', length: 1024, nullable: true }) | ||
url?: string | ||
|
||
// OAuth2 登录的目标 AppId,用于区分要登录哪个 App | ||
@Column({ type: 'varchar', length: 255, nullable: true }) | ||
appId?: string | ||
|
||
// OAuth2 登录的目标 AppSecret,用于请求签名 | ||
@Column({ type: 'varchar', length: 255, nullable: true }) | ||
appSecret?: string | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { Context } from 'hono' | ||
import { HTTPException } from 'hono/http-exception' | ||
import { ErrorHandler, HTTPResponseError, NotFoundHandler } from 'hono/types' | ||
import { StatusCode } from 'hono/utils/http-status' | ||
import winstonLogger from '@/utils/logger' | ||
|
||
export const errorhandler: ErrorHandler = (error: HTTPResponseError, c: Context) => { | ||
const message = process.env.NODE_ENV === 'production' ? `${error.name}: ${error.message}` : error.stack | ||
let status = 500 | ||
if (error instanceof HTTPException) { | ||
const response = error.getResponse() | ||
status = response.status | ||
} | ||
const method = c.req.method | ||
const requestPath = c.req.path | ||
winstonLogger.error(`Error in ${method} ${requestPath}: \n${message}`) | ||
return c.json({ | ||
status, | ||
message, | ||
}, status as StatusCode) | ||
} | ||
|
||
export const notFoundHandler: NotFoundHandler = (c: Context) => { | ||
const method = c.req.method | ||
const requestPath = c.req.path | ||
const message = `Cannot ${method} ${requestPath}` | ||
winstonLogger.warn(message) | ||
return c.json({ | ||
status: 404, | ||
message, | ||
}, 404) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,63 +1,17 @@ | ||
import { Hono } from 'hono' | ||
import { HTTPException } from 'hono/http-exception' | ||
import { merge, uniq } from 'lodash-es' | ||
import { getDataSource } from '@/db' | ||
import { VerifyCode } from '@/db/models/verify-code' | ||
import { adminAuth } from '@/middlewares/auth' | ||
import { CrudQuery } from '@/interfaces/crud-query' | ||
import { transformQueryOperator } from '@/utils/helper' | ||
import { createCrudRoute } from '@/utils/route-helper' | ||
// 验证码路由 | ||
const app = new Hono() | ||
|
||
app.use('/*', adminAuth) | ||
|
||
// 获取所有验证码 | ||
app.get('/', async (c) => { | ||
const query = c.req.query() as CrudQuery | ||
const limit = Number(query.limit) || 10 | ||
const page = Number(query.page) || 1 | ||
const skip = Number(query.skip) || (page - 1) * limit | ||
const { where = {}, sort = {}, select = [], relations = [] } = query | ||
const repository = (await getDataSource()).getRepository(VerifyCode) | ||
const [data, total] = await repository.findAndCount({ | ||
where: { | ||
...transformQueryOperator(where), | ||
}, | ||
skip, | ||
take: limit, | ||
order: merge({ | ||
createdAt: 'DESC', | ||
}, sort), | ||
relations: uniq([...relations]), | ||
select: uniq([...select || []]) as any, | ||
}) | ||
|
||
return c.json({ | ||
data, | ||
total, | ||
lastPage: Math.ceil(total / limit), | ||
currentPage: page, | ||
}) | ||
}) | ||
|
||
// 获取单个验证码 | ||
app.get('/:id', async (c) => { | ||
const id = parseInt(c.req.param('id')) | ||
const repository = (await getDataSource()).getRepository(VerifyCode) | ||
const message = await repository.findOne({ where: { id } }) | ||
return c.json(message) | ||
}) | ||
|
||
// 删除单个验证码 | ||
app.delete('/:id', async (c) => { | ||
const id = parseInt(c.req.param('id')) | ||
const repository = (await getDataSource()).getRepository(VerifyCode) | ||
const message = await repository.findOne({ where: { id } }) | ||
if (!message) { | ||
throw new HTTPException(404, { message: '验证码不存在' }) | ||
} | ||
await repository.delete({ id }) | ||
return c.json({ message: '删除成功' }) | ||
const app = createCrudRoute({ | ||
name: '验证码', | ||
model: VerifyCode, | ||
methods: { | ||
find: true, | ||
findOne: true, | ||
create: false, | ||
update: false, | ||
delete: true, | ||
}, | ||
admin: true, | ||
}) | ||
|
||
export default app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,18 @@ | ||
import { Hono } from 'hono' | ||
import { HTTPException } from 'hono/http-exception' | ||
import { merge, uniq } from 'lodash-es' | ||
import { getDataSource } from '@/db' | ||
import { BaseMessage } from '@/db/models/wechat-base' | ||
import { adminAuth } from '@/middlewares/auth' | ||
import { CrudQuery } from '@/interfaces/crud-query' | ||
import { transformQueryOperator } from '@/utils/helper' | ||
import { createCrudRoute } from '@/utils/route-helper' | ||
|
||
// message 接口需要 admin 权限 | ||
const app = new Hono() | ||
|
||
app.use('/*', adminAuth) | ||
|
||
// 获取所有消息 | ||
app.get('/', async (c) => { | ||
const query = c.req.query() as CrudQuery | ||
const limit = Number(query.limit) || 10 | ||
const page = Number(query.page) || 1 | ||
const skip = Number(query.skip) || (page - 1) * limit | ||
const { where = {}, sort = {}, select = [], relations = [] } = query | ||
const repository = (await getDataSource()).getRepository(BaseMessage) | ||
const [data, total] = await repository.findAndCount({ | ||
where: { | ||
...transformQueryOperator(where), | ||
}, | ||
skip, | ||
take: limit, | ||
order: merge({ | ||
createdAt: 'DESC', | ||
}, sort), | ||
relations: uniq([...relations]), | ||
select: uniq([...select || []]) as any, | ||
}) | ||
|
||
return c.json({ | ||
data, | ||
total, | ||
lastPage: Math.ceil(total / limit), | ||
currentPage: page, | ||
}) | ||
}) | ||
|
||
// 获取单个消息 | ||
app.get('/:id', async (c) => { | ||
const id = parseInt(c.req.param('id')) | ||
const repository = (await getDataSource()).getRepository(BaseMessage) | ||
const message = await repository.findOne({ where: { id } }) | ||
return c.json(message) | ||
}) | ||
|
||
// 删除单个消息 | ||
app.delete('/:id', async (c) => { | ||
const id = parseInt(c.req.param('id')) | ||
const repository = (await getDataSource()).getRepository(BaseMessage) | ||
const message = await repository.findOne({ where: { id } }) | ||
if (!message) { | ||
throw new HTTPException(404, { message: '消息不存在' }) | ||
} | ||
await repository.delete({ id }) | ||
return c.json({ message: '删除成功' }) | ||
const app = createCrudRoute({ | ||
name: '消息', | ||
model: BaseMessage, | ||
methods: { | ||
find: true, | ||
findOne: true, | ||
create: false, | ||
update: false, | ||
delete: true, | ||
}, | ||
admin: true, | ||
}) | ||
|
||
export default app |
Oops, something went wrong.