优化错误提示,抽离中间件
This commit is contained in:
parent
9c945a03be
commit
415a463027
@ -19,9 +19,6 @@ import KoaBodyMiddleware from 'koa-body';
|
||||
import KoaSessionMilddleware from 'koa-session';
|
||||
import KoaLogMiddleware from 'koa-logger';
|
||||
import MysqlSessionStore from '~/store/mysql-session';
|
||||
import Knex from 'knex';
|
||||
import WebSocket from 'ws';
|
||||
import * as redisService from '~/service/redis';
|
||||
import http from 'http';
|
||||
import cwlog from 'chowa-log';
|
||||
import config from '~/config';
|
||||
@ -30,8 +27,11 @@ import MpModule from '~/module/mp';
|
||||
import PcModule from '~/module/pc';
|
||||
import NotifyModule from '~/module/notify';
|
||||
import OaModule from '~/module/oa';
|
||||
import utils from '~/utils';
|
||||
import { SYSTEMT_NOT_INIT } from '~/constant/code';
|
||||
import wss from '~/wss';
|
||||
import * as redisService from '~/service/redis';
|
||||
import ModelMiddleware from '~/middleware/model';
|
||||
import IpMiddleware from '~/middleware/ip';
|
||||
import HeaderMiddleware from '~/middleware/header';
|
||||
|
||||
if (cluster.isMaster) {
|
||||
cwlog.success(`main process ${process.pid}`);
|
||||
@ -43,16 +43,7 @@ if (cluster.isMaster) {
|
||||
const app = new Koa();
|
||||
const router = new KoaRouter();
|
||||
const server = http.createServer(app.callback());
|
||||
const wss = new WebSocket.Server({ server, path: '/cws' });
|
||||
const model = Knex({
|
||||
client: 'mysql',
|
||||
connection: config.mysqlConfig,
|
||||
pool: {
|
||||
min: 0,
|
||||
max: 200
|
||||
}
|
||||
});
|
||||
console.log(config);
|
||||
|
||||
cwlog.setProject(`${config.name}-${process.pid}`);
|
||||
cwlog.displayDate();
|
||||
|
||||
@ -65,87 +56,33 @@ if (cluster.isMaster) {
|
||||
NotifyModule(router);
|
||||
OaModule(router);
|
||||
|
||||
// for socket
|
||||
redisService.subscribe(model, wss);
|
||||
|
||||
app.use(KoaBodyMiddleware({ multipart: true }));
|
||||
app.use(
|
||||
KoaLogMiddleware({
|
||||
transporter: str => {
|
||||
cwlog.log(`${str}`);
|
||||
}
|
||||
})
|
||||
);
|
||||
app.use(
|
||||
KoaSessionMilddleware(
|
||||
{
|
||||
store: new MysqlSessionStore(model),
|
||||
...config.session
|
||||
},
|
||||
app
|
||||
app.use(KoaBodyMiddleware({ multipart: true }))
|
||||
.use(
|
||||
KoaLogMiddleware({
|
||||
transporter: str => {
|
||||
cwlog.log(`${str}`);
|
||||
}
|
||||
})
|
||||
)
|
||||
);
|
||||
app.use(async (ctx, next) => {
|
||||
ctx.model = model;
|
||||
ctx.request.ip = (ctx.request.header['x-real-ip'] as string) || ctx.request.ip;
|
||||
.use(
|
||||
KoaSessionMilddleware(
|
||||
{
|
||||
store: new MysqlSessionStore(),
|
||||
...config.session
|
||||
},
|
||||
app
|
||||
)
|
||||
)
|
||||
.use(ModelMiddleware())
|
||||
.use(IpMiddleware())
|
||||
.use(HeaderMiddleware())
|
||||
.use(router.routes());
|
||||
|
||||
ctx.set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');
|
||||
// WebSocket
|
||||
wss.init(server);
|
||||
|
||||
if (ctx.method == 'OPTIONS') {
|
||||
ctx.body = '';
|
||||
ctx.status = 204;
|
||||
} else {
|
||||
const isInitAction = /^\/pc\/init\/\w+$/.test(ctx.request.path);
|
||||
|
||||
if (!config.inited && !/^\/pc\/upload\/sign$/.test(ctx.request.path)) {
|
||||
const total = utils.sql.countReader(await ctx.model.from('ejyy_property_company_admin').count());
|
||||
|
||||
if (total === 0) {
|
||||
if (!isInitAction) {
|
||||
return (ctx.body = {
|
||||
code: SYSTEMT_NOT_INIT,
|
||||
message: '系统未初始化'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
config.inited = true;
|
||||
}
|
||||
} else {
|
||||
if (isInitAction) {
|
||||
ctx.redirect('https://www.chowa.cn');
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await next();
|
||||
} catch (error) {
|
||||
ctx.status = 500;
|
||||
|
||||
if (config.debug) {
|
||||
cwlog.error('===============错误捕捉开始=================');
|
||||
console.log(error);
|
||||
cwlog.error('===============错误捕捉结束=================');
|
||||
} else {
|
||||
utils.mail.send({
|
||||
subject: `错误捕获`,
|
||||
content: [
|
||||
`访问地址:${ctx.request.path}`,
|
||||
`进程号:${process.pid}`,
|
||||
`body参数: ${JSON.stringify(ctx.request.body)}`,
|
||||
`params参数: ${JSON.stringify(ctx.params)}`,
|
||||
`进程号:${process.pid}`,
|
||||
`错误原因:${error}`
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.status === 404) {
|
||||
ctx.redirect('https://www.chowa.cn');
|
||||
}
|
||||
});
|
||||
app.use(router.routes());
|
||||
// for socket
|
||||
redisService.subscribe();
|
||||
|
||||
const port = process.env.port ? parseInt(process.env.port, 10) : config.server.port;
|
||||
|
||||
|
28
server/src/middleware/header.ts
Normal file
28
server/src/middleware/header.ts
Normal file
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* +----------------------------------------------------------------------
|
||||
* | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主
|
||||
* +----------------------------------------------------------------------
|
||||
* | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved.
|
||||
* +----------------------------------------------------------------------
|
||||
* | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权
|
||||
* +----------------------------------------------------------------------
|
||||
* | Author: jixuecong@chowa.cn
|
||||
* +----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { Middleware, DefaultState, DefaultContext } from 'koa';
|
||||
|
||||
function HeaderMiddleware(): Middleware<DefaultState, DefaultContext> {
|
||||
return async (ctx: DefaultContext, next) => {
|
||||
ctx.set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');
|
||||
|
||||
if (ctx.method == 'OPTIONS') {
|
||||
ctx.body = '';
|
||||
return (ctx.status = 204);
|
||||
}
|
||||
|
||||
await next();
|
||||
};
|
||||
}
|
||||
|
||||
export default HeaderMiddleware;
|
23
server/src/middleware/ip.ts
Normal file
23
server/src/middleware/ip.ts
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* +----------------------------------------------------------------------
|
||||
* | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主
|
||||
* +----------------------------------------------------------------------
|
||||
* | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved.
|
||||
* +----------------------------------------------------------------------
|
||||
* | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权
|
||||
* +----------------------------------------------------------------------
|
||||
* | Author: jixuecong@chowa.cn
|
||||
* +----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { Middleware, DefaultState, DefaultContext } from 'koa';
|
||||
|
||||
function IpMiddleware(): Middleware<DefaultState, DefaultContext> {
|
||||
return async (ctx, next) => {
|
||||
ctx.request.ip = (ctx.request.header['x-real-ip'] as string) || ctx.request.ip;
|
||||
|
||||
await next();
|
||||
};
|
||||
}
|
||||
|
||||
export default IpMiddleware;
|
31
server/src/middleware/model.ts
Normal file
31
server/src/middleware/model.ts
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* +----------------------------------------------------------------------
|
||||
* | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主
|
||||
* +----------------------------------------------------------------------
|
||||
* | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved.
|
||||
* +----------------------------------------------------------------------
|
||||
* | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权
|
||||
* +----------------------------------------------------------------------
|
||||
* | Author: jixuecong@chowa.cn
|
||||
* +----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { Middleware, DefaultState, DefaultContext } from 'koa';
|
||||
import Knex from 'knex';
|
||||
import model from '~/model';
|
||||
|
||||
declare module 'koa' {
|
||||
interface BaseContext {
|
||||
model: Knex;
|
||||
}
|
||||
}
|
||||
|
||||
function ModelMiddleware(): Middleware<DefaultState, DefaultContext> {
|
||||
return async (ctx, next) => {
|
||||
ctx.model = model;
|
||||
|
||||
await next();
|
||||
};
|
||||
}
|
||||
|
||||
export default ModelMiddleware;
|
51
server/src/middleware/watcher.ts
Normal file
51
server/src/middleware/watcher.ts
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* +----------------------------------------------------------------------
|
||||
* | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主
|
||||
* +----------------------------------------------------------------------
|
||||
* | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved.
|
||||
* +----------------------------------------------------------------------
|
||||
* | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权
|
||||
* +----------------------------------------------------------------------
|
||||
* | Author: jixuecong@chowa.cn
|
||||
* +----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import { Middleware, DefaultState, DefaultContext } from 'koa';
|
||||
import utils from '~/utils';
|
||||
import cwlog from 'chowa-log';
|
||||
import config from '~/config';
|
||||
|
||||
function WatcherMiddleware(): Middleware<DefaultState, DefaultContext> {
|
||||
return async (ctx, next) => {
|
||||
try {
|
||||
await next();
|
||||
} catch (error) {
|
||||
ctx.status = 500;
|
||||
|
||||
if (config.debug) {
|
||||
cwlog.error('===============错误捕捉开始=================');
|
||||
console.log(error);
|
||||
cwlog.error('===============错误捕捉结束=================');
|
||||
} else {
|
||||
utils.mail.send({
|
||||
to: config.smtp.to,
|
||||
subject: `${config.name}异常捕获`,
|
||||
content: [
|
||||
`访问地址:${ctx.request.path}`,
|
||||
`进程号:${process.pid}`,
|
||||
`body参数: ${JSON.stringify(ctx.request.body)}`,
|
||||
`params参数: ${JSON.stringify(ctx.params)}`,
|
||||
`进程号:${process.pid}`,
|
||||
`错误原因:${error}`
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.status === 404) {
|
||||
ctx.redirect('https://www.chowa.cn');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default WatcherMiddleware;
|
25
server/src/model/index.ts
Normal file
25
server/src/model/index.ts
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* +----------------------------------------------------------------------
|
||||
* | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主
|
||||
* +----------------------------------------------------------------------
|
||||
* | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved.
|
||||
* +----------------------------------------------------------------------
|
||||
* | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权
|
||||
* +----------------------------------------------------------------------
|
||||
* | Author: jixuecong@chowa.cn
|
||||
* +----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import Knex from 'knex';
|
||||
import config from '~/config';
|
||||
|
||||
const model = Knex({
|
||||
client: 'mysql',
|
||||
connection: config.mysqlConfig,
|
||||
pool: {
|
||||
min: 0,
|
||||
max: 200
|
||||
}
|
||||
});
|
||||
|
||||
export default model;
|
@ -49,7 +49,8 @@ const MpUserSupplementAction = <Action>{
|
||||
{
|
||||
name: 'idcard',
|
||||
required: true,
|
||||
validator: val => utils.idcard.verify(val)
|
||||
validator: val => utils.idcard.verify(val),
|
||||
message: '身份证号码验证失败'
|
||||
},
|
||||
{
|
||||
name: 'avatar_url',
|
||||
|
@ -70,17 +70,19 @@ function MpModule(appRouter: KoaRouter) {
|
||||
}
|
||||
}
|
||||
|
||||
if (validatorService(ctx, validator)) {
|
||||
const vs = validatorService(ctx, validator);
|
||||
|
||||
if (!vs.success) {
|
||||
return (ctx.body = {
|
||||
code: PARAMS_ERROR,
|
||||
message: '参数错误'
|
||||
message: vs.message
|
||||
});
|
||||
}
|
||||
|
||||
await response.apply(this, [ctx, next]);
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (config.debug) {
|
||||
cwlog.info(`${name} mounted and request from ${path.posix.join('/mp', router.path)} by ${router.method}`);
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import { NotifyAction } from '~/types/action';
|
||||
import KoaRouter from 'koa-router';
|
||||
import * as NotifyModuleRouter from './router';
|
||||
import cwlog from 'chowa-log';
|
||||
import config from '~/config';
|
||||
|
||||
function MpModule(appRouter: KoaRouter) {
|
||||
for (const name in NotifyModuleRouter) {
|
||||
@ -25,7 +26,7 @@ function MpModule(appRouter: KoaRouter) {
|
||||
await response.apply(this, [ctx, next]);
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (config.debug) {
|
||||
cwlog.info(
|
||||
`${name} mounted and request from ${path.posix.join('/notify', router.path)} by ${router.method}`
|
||||
);
|
||||
|
@ -18,6 +18,7 @@ import * as OaModuleRouter from './router';
|
||||
import cwlog from 'chowa-log';
|
||||
import * as wechatService from '~/service/wechat';
|
||||
import menu from './menu';
|
||||
import config from '~/config';
|
||||
|
||||
async function OaModule(appRouter: KoaRouter) {
|
||||
for (const name in OaModuleRouter) {
|
||||
@ -27,7 +28,7 @@ async function OaModule(appRouter: KoaRouter) {
|
||||
await response.apply(this, [ctx, next]);
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (config.debug) {
|
||||
cwlog.info(`${name} mounted and request from ${path.posix.join('/oa', router.path)} by ${router.method}`);
|
||||
}
|
||||
}
|
||||
|
@ -115,17 +115,19 @@ function PcModule(appRouter: KoaRouter) {
|
||||
}
|
||||
}
|
||||
|
||||
if (validatorService(ctx, validator)) {
|
||||
const vs = validatorService(ctx, validator);
|
||||
|
||||
if (!vs.success) {
|
||||
return (ctx.body = {
|
||||
code: PARAMS_ERROR,
|
||||
message: '参数错误'
|
||||
message: vs.message
|
||||
});
|
||||
}
|
||||
|
||||
await response.apply(this, [ctx, next]);
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (config.debug) {
|
||||
cwlog.info(`${name} mounted and request from ${path.posix.join('/pc', router.path)} by ${router.method}`);
|
||||
}
|
||||
}
|
||||
|
@ -11,40 +11,16 @@
|
||||
*/
|
||||
|
||||
import redis from 'redis';
|
||||
import Knex from 'knex';
|
||||
import WebSocket from 'ws';
|
||||
import http from 'http';
|
||||
import quertString from 'query-string';
|
||||
import { CwWebSocket } from '~/types/ws';
|
||||
import wss, { PcData } from '~/wss';
|
||||
import config from '~/config';
|
||||
import { Role } from '~/constant/role_access';
|
||||
|
||||
const pub = process.env.NODE_ENV === 'production' ? redis.createClient(config.redis) : null;
|
||||
const sub = process.env.NODE_ENV === 'production' ? redis.createClient(config.redis) : null;
|
||||
|
||||
let wss = null;
|
||||
const pub = config.debug ? null : redis.createClient(config.redis);
|
||||
const sub = config.debug ? null : redis.createClient(config.redis);
|
||||
|
||||
export const WS_NOTICE_TO_PROPERTY_COMPANY = 'WS_NOTICE_TO_PROPERTY_COMPANY';
|
||||
export const WS_NOTICE_TO_REMOTE_SERVER = 'WS_NOTICE_TO_REMOTE_SERVER';
|
||||
|
||||
interface PcData {
|
||||
id: number;
|
||||
community_id: number;
|
||||
type: Role;
|
||||
urge: boolean;
|
||||
}
|
||||
|
||||
function sendToPc(data: PcData) {
|
||||
if (!(wss instanceof WebSocket.Server)) {
|
||||
return;
|
||||
}
|
||||
wss.clients.forEach((client: CwWebSocket) => {
|
||||
if (client.readyState === WebSocket.OPEN && client.access.includes(data.type)) {
|
||||
client.send(JSON.stringify(data));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// todo
|
||||
interface RsData {
|
||||
remote_id: number;
|
||||
door_id: number;
|
||||
@ -57,7 +33,7 @@ function sendToRs(data: RsData) {
|
||||
function dispatch(channel: string, data: Object) {
|
||||
switch (channel) {
|
||||
case WS_NOTICE_TO_PROPERTY_COMPANY:
|
||||
return sendToPc(data as PcData);
|
||||
return wss.sendToPc(data as PcData);
|
||||
|
||||
case WS_NOTICE_TO_REMOTE_SERVER:
|
||||
return sendToRs(data as RsData);
|
||||
@ -65,50 +41,15 @@ function dispatch(channel: string, data: Object) {
|
||||
}
|
||||
|
||||
export function pubish(channel: string, data: Object) {
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
if (!config.debug) {
|
||||
pub.publish(channel, JSON.stringify(data));
|
||||
} else {
|
||||
dispatch(channel, data);
|
||||
}
|
||||
}
|
||||
|
||||
export function subscribe(model: Knex, w: WebSocket.Server) {
|
||||
wss = w;
|
||||
|
||||
wss.on('connection', async (ws: CwWebSocket, request: http.IncomingMessage) => {
|
||||
const {
|
||||
query: { token }
|
||||
} = quertString.parseUrl(request.url);
|
||||
|
||||
if (!token) {
|
||||
return ws.close();
|
||||
}
|
||||
|
||||
const pcUserInfo = await model
|
||||
.table('ejyy_property_company_auth')
|
||||
.leftJoin(
|
||||
'ejyy_property_company_user',
|
||||
'ejyy_property_company_user.id',
|
||||
'ejyy_property_company_auth.property_company_user_id'
|
||||
)
|
||||
.leftJoin(
|
||||
'ejyy_property_company_access',
|
||||
'ejyy_property_company_access.id',
|
||||
'ejyy_property_company_user.access_id'
|
||||
)
|
||||
.where('ejyy_property_company_auth.token', token)
|
||||
.select('ejyy_property_company_user.id', 'ejyy_property_company_access.content as access')
|
||||
.first();
|
||||
|
||||
if (!pcUserInfo) {
|
||||
return ws.close();
|
||||
}
|
||||
|
||||
ws.user_id = pcUserInfo.id;
|
||||
ws.access = pcUserInfo.access;
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
export async function subscribe() {
|
||||
if (!config.debug) {
|
||||
sub.subscribe(WS_NOTICE_TO_PROPERTY_COMPANY);
|
||||
sub.subscribe(WS_NOTICE_TO_REMOTE_SERVER);
|
||||
|
||||
|
@ -11,80 +11,88 @@
|
||||
*/
|
||||
|
||||
import { Context } from 'koa';
|
||||
import { ValidatorDeclare } from '~/types/action';
|
||||
import config from '~/config';
|
||||
import cwlog from 'chowa-log';
|
||||
import { ValidatorDeclare, FieldVerifyDeclare } from '~/types/action';
|
||||
|
||||
function validatorService(ctx: Context, validator: ValidatorDeclare): boolean {
|
||||
if (!validator) {
|
||||
return false;
|
||||
interface ValidatorResult {
|
||||
success: boolean;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
interface FieldVeirfy extends FieldVerifyDeclare {
|
||||
value: any;
|
||||
}
|
||||
|
||||
function validatorService(ctx: Context, validatorDeclare: ValidatorDeclare): ValidatorResult {
|
||||
if (!validatorDeclare) {
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
return !['body', 'params', 'query', 'files'].every(refer => {
|
||||
const origin = validator[refer];
|
||||
const fileds: FieldVeirfy[] = [];
|
||||
|
||||
if (!Array.isArray(origin)) {
|
||||
return true;
|
||||
['body', 'params', 'query', 'files'].forEach((refer: 'body' | 'params' | 'query' | 'files') => {
|
||||
if (!Array.isArray(validatorDeclare[refer])) {
|
||||
return;
|
||||
}
|
||||
|
||||
return origin.every(({ name, required, length, min, max, regex, validator }) => {
|
||||
let value = undefined;
|
||||
|
||||
if (refer === 'params') {
|
||||
value = ctx.params[name];
|
||||
} else {
|
||||
value = ctx.request[refer][name];
|
||||
}
|
||||
|
||||
if (
|
||||
required === true &&
|
||||
((Array.isArray(value) && value.length === 0) ||
|
||||
(!Array.isArray(value) && (value == undefined || value === '')))
|
||||
) {
|
||||
if (config.debug) {
|
||||
cwlog.warning(`${name} 字段必须`);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (length && value && value.length !== length) {
|
||||
if (config.debug) {
|
||||
cwlog.warning(`${name} 长度必须等于 ${length},当前值:${value}`);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (min && value && value.length < min) {
|
||||
if (config.debug) {
|
||||
cwlog.warning(`${name} 长度必须小于 ${min},当前值:${value}`);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (max && value && value.length > max) {
|
||||
if (config.debug) {
|
||||
cwlog.warning(`${name} 长度必须大于 ${max},当前值:${value}`);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (regex && value && !regex.test(value)) {
|
||||
if (config.debug) {
|
||||
cwlog.warning(`${name} 必须满足正则 ${regex},当前值:${value}`);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (validator && value && !validator(value)) {
|
||||
if (config.debug) {
|
||||
cwlog.warning(`${name} 自定义验证未通过,当前值:${value}`);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
validatorDeclare[refer].forEach(declare => {
|
||||
fileds.push({
|
||||
value: refer === 'params' ? ctx.params[declare.name] : ctx.request[refer][declare.name],
|
||||
...declare
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
for (let i = 0; i < fileds.length; i++) {
|
||||
const { name, required, length, min, max, regex, validator, value, message } = fileds[i];
|
||||
|
||||
if (
|
||||
required === true &&
|
||||
((Array.isArray(value) && value.length === 0) ||
|
||||
(!Array.isArray(value) && (value == undefined || value === '')))
|
||||
) {
|
||||
return {
|
||||
success: false,
|
||||
message: message ? message : `参数错误,${name}字段是必填字段`
|
||||
};
|
||||
}
|
||||
|
||||
if (length && value && value.length !== length) {
|
||||
return {
|
||||
success: false,
|
||||
message: message ? message : `参数错误,${name}字段长度必须等于 ${length}`
|
||||
};
|
||||
}
|
||||
|
||||
if (min && value && value.length < min) {
|
||||
return {
|
||||
success: false,
|
||||
message: message ? message : `参数错误,${name}字段长度必须大于 ${min}`
|
||||
};
|
||||
}
|
||||
|
||||
if (max && value && value.length > max) {
|
||||
return {
|
||||
success: false,
|
||||
message: message ? message : `参数错误,${name}字段长度必须小于 ${max}`
|
||||
};
|
||||
}
|
||||
|
||||
if (regex && value && !regex.test(value)) {
|
||||
return {
|
||||
success: false,
|
||||
message: message ? message : `参数错误,${name}字段必须满足正则 ${regex}`
|
||||
};
|
||||
}
|
||||
|
||||
if (validator && value && !validator(value)) {
|
||||
return {
|
||||
success: false,
|
||||
message: message ? message : `参数错误,${name}字段验证未通过`
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
export default validatorService;
|
||||
|
@ -10,7 +10,7 @@
|
||||
* +----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import Knex from 'knex';
|
||||
import model from '~/model';
|
||||
import { Session } from 'koa-session';
|
||||
|
||||
const FORTY_FIVE_MINUTES = 45 * 60 * 1000;
|
||||
@ -34,14 +34,8 @@ function getExpiresOn(session: Session, ttl: number): number {
|
||||
}
|
||||
|
||||
class MysqlSessionStore {
|
||||
constructor(model: Knex) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
model = <Knex>null;
|
||||
|
||||
async get(sid: string): Promise<Session> {
|
||||
const row = await this.model
|
||||
const row = await model
|
||||
.from('ejyy_session_store')
|
||||
.where('id', sid)
|
||||
.where('expire', '>', Date.now())
|
||||
@ -60,14 +54,14 @@ class MysqlSessionStore {
|
||||
let expire = getExpiresOn(session, ttl).valueOf();
|
||||
let data = JSON.stringify(session);
|
||||
|
||||
await this.model.raw(
|
||||
await model.raw(
|
||||
'INSERT INTO ejyy_session_store (id, expire, data) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE expire=?, data =?',
|
||||
[sid, expire, data, expire, data]
|
||||
);
|
||||
}
|
||||
|
||||
async destroy(sid: string) {
|
||||
await this.model
|
||||
await model
|
||||
.from('ejyy_session_store')
|
||||
.where('id', sid)
|
||||
.delete();
|
||||
|
1
server/src/types/action.d.ts
vendored
1
server/src/types/action.d.ts
vendored
@ -32,6 +32,7 @@ declare namespace Action {
|
||||
min?: number;
|
||||
max?: number;
|
||||
regex?: RegExp;
|
||||
message?: string;
|
||||
validator?: (value: any) => boolean;
|
||||
}
|
||||
|
||||
|
3
server/src/types/koa.d.ts
vendored
3
server/src/types/koa.d.ts
vendored
@ -9,8 +9,6 @@
|
||||
* | Author: jixuecong@chowa.cn
|
||||
* +----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import Knex from 'knex';
|
||||
import { MpUserInfo, PcUserInfo, OaUserInfo } from './user-info';
|
||||
|
||||
interface InterfaceBody {
|
||||
@ -24,7 +22,6 @@ declare module 'koa' {
|
||||
mpUserInfo: MpUserInfo;
|
||||
pcUserInfo: PcUserInfo;
|
||||
OaUserInfo: OaUserInfo;
|
||||
model: Knex;
|
||||
}
|
||||
|
||||
interface ContextDelegatedResponse {
|
||||
|
84
server/src/wss/index.ts
Normal file
84
server/src/wss/index.ts
Normal file
@ -0,0 +1,84 @@
|
||||
/**
|
||||
* +----------------------------------------------------------------------
|
||||
* | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主
|
||||
* +----------------------------------------------------------------------
|
||||
* | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved.
|
||||
* +----------------------------------------------------------------------
|
||||
* | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权
|
||||
* +----------------------------------------------------------------------
|
||||
* | Author: jixuecong@chowa.cn
|
||||
* +----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import WebSocket from 'ws';
|
||||
import http from 'http';
|
||||
import quertString from 'query-string';
|
||||
import model from '~/model';
|
||||
import { Role } from '~/constant/role_access';
|
||||
|
||||
export interface CwWebSocket extends WebSocket {
|
||||
access?: Role[];
|
||||
user_id?: number;
|
||||
}
|
||||
|
||||
export interface PcData {
|
||||
id: number;
|
||||
community_id: number;
|
||||
type: Role;
|
||||
urge: boolean;
|
||||
}
|
||||
|
||||
class ws {
|
||||
static ws: WebSocket.Server;
|
||||
|
||||
static init(server: http.Server) {
|
||||
this.ws = new WebSocket.Server({ server, path: '/cws' });
|
||||
|
||||
this.ws.on('connection', async (ws: CwWebSocket, request: http.IncomingMessage) => {
|
||||
const {
|
||||
query: { token }
|
||||
} = quertString.parseUrl(request.url);
|
||||
|
||||
if (!token) {
|
||||
return ws.close();
|
||||
}
|
||||
|
||||
const userInfo = await model
|
||||
.table('ejyy_property_company_auth')
|
||||
.leftJoin(
|
||||
'ejyy_property_company_user',
|
||||
'ejyy_property_company_user.id',
|
||||
'ejyy_property_company_auth.property_company_user_id'
|
||||
)
|
||||
.leftJoin(
|
||||
'ejyy_property_company_access',
|
||||
'ejyy_property_company_access.id',
|
||||
'ejyy_property_company_user.access_id'
|
||||
)
|
||||
.where('ejyy_property_company_auth.token', token)
|
||||
.select('ejyy_property_company_user.id', 'ejyy_property_company_access.content')
|
||||
.first();
|
||||
|
||||
if (!userInfo) {
|
||||
return ws.close();
|
||||
}
|
||||
|
||||
ws.user_id = userInfo.id;
|
||||
ws.access = userInfo.content;
|
||||
});
|
||||
}
|
||||
|
||||
static sendToPc(data: PcData) {
|
||||
if (!(this.ws instanceof WebSocket.Server)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.ws.clients.forEach((client: CwWebSocket) => {
|
||||
if (client.readyState === WebSocket.OPEN && client.access.includes(data.type)) {
|
||||
client.send(JSON.stringify(data));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default ws;
|
Loading…
x
Reference in New Issue
Block a user