corgi/src/admin.server.ts
2021-05-08 11:40:09 +08:00

153 lines
5.0 KiB
TypeScript

import fastify, { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'
import helmet from 'fastify-helmet'
import { IncomingMessage, Server, ServerResponse } from 'http'
import { RouterMap } from 'decorators/router'
import { mongoose } from '@typegoose/typegoose'
import logger from 'logger/logger'
import config from 'config/config'
import { AdminRole } from 'models/admin/AdminRole'
const rbacPlugin = require('plugins/zrbac');
const zAuthPlugin = require('plugins/zauth');
const zReqParserPlugin = require('plugins/zReqParser');
const fs = require('fs');
const join = require('path').join;
require('./common/Extend');
export class AdminServer {
server: FastifyInstance<Server, IncomingMessage, ServerResponse>;
public constructor() {
this.server = fastify({logger: true});
// @ts-ignore
this.server['jcname'] = '222';
this.registerPlugins();
}
private registerPlugins() {
this.server.register(require('fastify-formbody'))
this.server.register(zReqParserPlugin)
this.server.register(
helmet,
{ hidePoweredBy: false }
)
this.server.register(zAuthPlugin, {
secret: config.admin.token_secret,
expiresIn: config.admin.token_expiresIn
})
this.server.register(require('fastify-cors'), {});
}
private async registerRbac() {
let roles = await AdminRole.allRbacJson();
this.server.register(rbacPlugin, { roles: roles });
}
private registerRouter() {
logger.log('register api routers');
let self = this;
for (let [controller, config] of RouterMap.decoratedRouters) {
for(let data of config.data) {
logger.info('find admin router', data.method || 'all',
data.path, controller.name);
// @ts-ignore
self.server[data.method || 'all'](data.path, {
preValidation: async function (request: FastifyRequest, reply: FastifyReply) {
request.roles = config.roles;
request.permissions = config.permissions;
request.depts = config.depts;
await this.zAuth(request, reply);
}
}, controller);
}
}
}
/**
* 加载所有的controller
*/
initControllers() {
logger.info('Bootstrap controllers...');
const controllers = join(__dirname, 'admin/controllers');
fs.readdirSync(controllers)
.filter((file: string) => ~file.search(/^[^.].*\.(ts|js)$/))
.forEach((file: any) => {
logger.log(file);
return require(join(controllers, file))});
}
async connectDB() {
const options = {useNewUrlParser: true,
poolSize: 5,
keepAlive: true,
keepAliveInitialDelay: 300000,
useUnifiedTopology: true};
const uri = config.db_main;
logger.info(`connect to ${uri} ...`);
try {
// await mongoose.createConnection(uri, options)
await mongoose.connect(uri, options)
logger.log('DB Connected');
} catch (err) {
logger.log(`DB Connection Error: ${err.message}`);
}
}
private setErrHandler() {
this.server.setNotFoundHandler(function(request, reply){
reply.send({code: 404, msg: 'page not found'})
});
this.server.setErrorHandler(function (error, request, reply) {
let statusCode = error.statusCode || 100;
if (statusCode >= 500) {
logger.error(error)
} else if (statusCode >= 400) {
logger.info(error)
} else {
logger.error(error)
}
reply.code(200).send({code: statusCode, msg: error.message})
})
}
/**
* 格式化接口返回数据, 统一封装成如下格式
* {
* code: 0,
* msg?: '',
* data: any
* }
* @private
*/
private setFormatSend() {
this.server.addHook('preSerialization', async (request: FastifyRequest, reply: FastifyReply, payload) => {
reply.header('X-Powered-By', 'PHP/5.4.16')
// @ts-ignore
if (!payload.code) {
payload = {
code: 0,
data: payload
}
}
return payload
})
}
public async start() {
let self = this;
return new Promise(async (resolve, reject) => {
await self.connectDB();
await self.registerRbac();
self.initControllers();
self.registerRouter();
self.setErrHandler();
self.setFormatSend();
this.server.listen({port: config.admin.port}, (err: any, address: any) => {
if (err) {
logger.log(err)
process.exit(0)
}
resolve && resolve(address);
})
});
}
}