添加分页功能、打包优化、ts编译优化
This commit is contained in:
parent
fd85fcef74
commit
6a1f9a3f6b
|
@ -62,6 +62,4 @@ typings/
|
||||||
|
|
||||||
dist
|
dist
|
||||||
|
|
||||||
entity/**/*.js
|
|
||||||
|
|
||||||
ormconfig.json
|
ormconfig.json
|
|
@ -1,11 +1,17 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 错误响应
|
* 错误响应
|
||||||
*/
|
*/
|
||||||
interface ExpressResponseError extends Record<string,unknown>{
|
interface ExpressResponseError extends Record<string,unknown>{
|
||||||
error:string
|
error:string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 成功响应
|
||||||
|
*/
|
||||||
|
interface ExpressResponseSuccess extends Record<string,unknown>{
|
||||||
|
message:string
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 响应列表
|
* 响应列表
|
||||||
*/
|
*/
|
||||||
|
@ -17,10 +23,17 @@ interface ExpressResponseDetail<T=Record<string,unknown>> extends Record<string,
|
||||||
detail:T
|
detail:T
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SSEPayload = Record<string|number,SSEPayload>|string|number
|
||||||
|
|
||||||
declare namespace Express {
|
declare namespace Express {
|
||||||
export interface Response {
|
export interface Response {
|
||||||
error(error:string,statusCode:number,errObj:Record<string,unknown>):ExpressResponseError
|
error(error:string,statusCode:number,errObj?:Record<string,unknown>):ExpressResponseError
|
||||||
list<T=Record<string,unknown>>(list:T,resObj:Record<string,unknown>):ExpressResponseList<T>
|
list<T=Record<string,unknown>>(list:T,resObj?:Record<string,unknown>):ExpressResponseList<T>
|
||||||
detail<T=Record<string,unknown>>(detail:T,resObj:Record<string,unknown>):ExpressResponseDetail<T>
|
detail<T=Record<string,unknown>>(detail:T,resObj?:Record<string,unknown>):ExpressResponseDetail<T>
|
||||||
|
success(message:string,resObj?:Record<string,unknown>):ExpressResponseSuccess
|
||||||
|
|
||||||
|
enable_sse():this
|
||||||
|
|
||||||
|
sse(data:SSEPayload,event:string):this
|
||||||
}
|
}
|
||||||
}
|
}
|
12
app.js
12
app.js
|
@ -42,6 +42,18 @@ Object.defineProperty(express.response,'detail',{
|
||||||
configurable:false
|
configurable:false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Object.defineProperty(express.response,'success',{
|
||||||
|
value:function (msg,resObj = {}) {
|
||||||
|
|
||||||
|
resObj.message = msg
|
||||||
|
|
||||||
|
this.status(200).send(resObj)
|
||||||
|
},
|
||||||
|
enumerable:false,
|
||||||
|
writable:false,
|
||||||
|
configurable:false
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 连接数据库
|
* 连接数据库
|
||||||
*/
|
*/
|
||||||
|
|
87
bin/www
87
bin/www
|
@ -3,94 +3,95 @@
|
||||||
/**
|
/**
|
||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
*/
|
*/
|
||||||
require('dotenv').config({path:'./config/.env'})
|
const {resolve} = require('path')
|
||||||
var app = require('../app');
|
require('dotenv').config({ path:resolve(__dirname,'../.env') })
|
||||||
var debug = require('debug')('express-my-admin:server');
|
var app = require(resolve(__dirname,'../app'))
|
||||||
var http = require('http');
|
var debug = require('debug')('express-im:server')
|
||||||
const event = require('../event')
|
var http = require('http')
|
||||||
|
const event = require(resolve(__dirname,'../event'))
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
|
||||||
* Get port from environment and store in Express.
|
* Get port from environment and store in Express.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var port = normalizePort(process.env.PORT || '3000');
|
var port = normalizePort(process.env.PORT || '3000')
|
||||||
app.set('port', port);
|
app.set('port', port)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create HTTP server.
|
* Create HTTP server.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var server = http.createServer(app);
|
var server = http.createServer(app)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listen on provided port, on all network interfaces.
|
* Listen on provided port, on all network interfaces.
|
||||||
*/
|
*/
|
||||||
event.on('typeorm-connection',()=>{
|
event.on('typeorm-connection',()=>{
|
||||||
server.listen(port,()=>{
|
server.listen(port,()=>{
|
||||||
console.log(`Admin服务启动成功,监听端口${port}`);
|
console.log(`服务启动成功,监听端口${port}`)
|
||||||
});
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
server.on('error', onError);
|
server.on('error', onError)
|
||||||
server.on('listening', onListening);
|
server.on('listening', onListening)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize a port into a number, string, or false.
|
* Normalize a port into a number, string, or false.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function normalizePort(val) {
|
function normalizePort (val) {
|
||||||
var port = parseInt(val, 10);
|
var port = parseInt(val, 10)
|
||||||
|
|
||||||
if (isNaN(port)) {
|
if (isNaN(port)) {
|
||||||
// named pipe
|
// named pipe
|
||||||
return val;
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port >= 0) {
|
if (port >= 0) {
|
||||||
// port number
|
// port number
|
||||||
return port;
|
return port
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event listener for HTTP server "error" event.
|
* Event listener for HTTP server "error" event.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function onError(error) {
|
function onError (error) {
|
||||||
if (error.syscall !== 'listen') {
|
if (error.syscall !== 'listen') {
|
||||||
throw error;
|
throw error
|
||||||
}
|
}
|
||||||
|
|
||||||
var bind = typeof port === 'string'
|
var bind = typeof port === 'string'
|
||||||
? 'Pipe ' + port
|
? 'Pipe ' + port
|
||||||
: 'Port ' + port;
|
: 'Port ' + port
|
||||||
|
|
||||||
// handle specific listen errors with friendly messages
|
// handle specific listen errors with friendly messages
|
||||||
switch (error.code) {
|
switch (error.code) {
|
||||||
case 'EACCES':
|
case 'EACCES':
|
||||||
console.error(bind + ' requires elevated privileges');
|
console.error(bind + ' requires elevated privileges')
|
||||||
process.exit(1);
|
process.exit(1)
|
||||||
break;
|
break
|
||||||
case 'EADDRINUSE':
|
case 'EADDRINUSE':
|
||||||
console.error(bind + ' is already in use');
|
console.error(bind + ' is already in use')
|
||||||
process.exit(1);
|
process.exit(1)
|
||||||
break;
|
break
|
||||||
default:
|
default:
|
||||||
throw error;
|
throw error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event listener for HTTP server "listening" event.
|
* Event listener for HTTP server "listening" event.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function onListening() {
|
function onListening () {
|
||||||
var addr = server.address();
|
var addr = server.address()
|
||||||
var bind = typeof addr === 'string'
|
var bind = typeof addr === 'string'
|
||||||
? 'pipe ' + addr
|
? 'pipe ' + addr
|
||||||
: 'port ' + addr.port;
|
: 'port ' + addr.port
|
||||||
debug('Listening on ' + bind);
|
debug('Listening on ' + bind)
|
||||||
}
|
}
|
||||||
|
|
30
dto/admin.js
30
dto/admin.js
|
@ -1,30 +0,0 @@
|
||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.PostAdminMemberDto = void 0;
|
|
||||||
var class_transformer_1 = require("class-transformer");
|
|
||||||
var class_validator_1 = require("class-validator");
|
|
||||||
var PostAdminMemberDto = /** @class */ (function () {
|
|
||||||
function PostAdminMemberDto() {
|
|
||||||
}
|
|
||||||
__decorate([
|
|
||||||
class_transformer_1.Expose(),
|
|
||||||
class_validator_1.IsNotEmpty({ message: '登录用户名不能为空' }),
|
|
||||||
__metadata("design:type", String)
|
|
||||||
], PostAdminMemberDto.prototype, "username", void 0);
|
|
||||||
__decorate([
|
|
||||||
class_transformer_1.Expose(),
|
|
||||||
class_validator_1.IsNotEmpty({ message: '登录密码不能为空' }),
|
|
||||||
__metadata("design:type", String)
|
|
||||||
], PostAdminMemberDto.prototype, "password", void 0);
|
|
||||||
return PostAdminMemberDto;
|
|
||||||
}());
|
|
||||||
exports.PostAdminMemberDto = PostAdminMemberDto;
|
|
|
@ -1,4 +0,0 @@
|
||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
require("reflect-metadata");
|
|
||||||
require("es6-shim");
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
PORT=5500
|
||||||
|
GITHUB_CLIENTID=xxx
|
||||||
|
GITHUB_SECRET=xxx
|
||||||
|
AES=xxx
|
|
@ -0,0 +1,34 @@
|
||||||
|
const AuthUtils = require('../utils/auth')
|
||||||
|
const { Account } = require('../entity/account')
|
||||||
|
const { getManager } = require('typeorm')
|
||||||
|
|
||||||
|
module.exports = async function (req,res,next) {
|
||||||
|
|
||||||
|
try{
|
||||||
|
const session = req.cookies.IM_SESS
|
||||||
|
|
||||||
|
if(!session) return res.error('未登录',401)
|
||||||
|
|
||||||
|
try{
|
||||||
|
var payload = AuthUtils.decode(session)
|
||||||
|
}catch(err) {
|
||||||
|
return res.error(err.message,401)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.auth_session = payload
|
||||||
|
|
||||||
|
const manager = getManager()
|
||||||
|
|
||||||
|
const detail = await manager.findOne(Account,{ aid:payload.aid })
|
||||||
|
|
||||||
|
if(!detail.isActive) return res.error('账号不可用',403)
|
||||||
|
|
||||||
|
req.account_detail = detail
|
||||||
|
}catch(err) {
|
||||||
|
console.error('登录认证中间件报错:',err);
|
||||||
|
return res.error('登录凭证已过期',401)
|
||||||
|
}
|
||||||
|
|
||||||
|
next()
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
const AuthUtils = require('../utils/auth')
|
||||||
|
const { Account } = require('../entity/account')
|
||||||
|
const { getManager } = require('typeorm')
|
||||||
|
|
||||||
|
module.exports = async function (req,res,next) {
|
||||||
|
|
||||||
|
const session = req.cookies.IM_SESS
|
||||||
|
|
||||||
|
if(!session) return res.redirect('/oauth/login')
|
||||||
|
|
||||||
|
try{
|
||||||
|
var payload = AuthUtils.decode(session)
|
||||||
|
}catch(err) {
|
||||||
|
return res.redirect('/oauth/login')
|
||||||
|
}
|
||||||
|
|
||||||
|
req.auth_session = payload
|
||||||
|
|
||||||
|
const manager = getManager()
|
||||||
|
|
||||||
|
const detail = await manager.findOne(Account,{ aid:payload.aid })
|
||||||
|
|
||||||
|
req.account_detail = detail
|
||||||
|
|
||||||
|
next()
|
||||||
|
|
||||||
|
}
|
|
@ -4,16 +4,14 @@
|
||||||
".vscode",
|
".vscode",
|
||||||
".git",
|
".git",
|
||||||
"node_modules/*",
|
"node_modules/*",
|
||||||
"views/*",
|
|
||||||
"entity/**/*.js",
|
|
||||||
"dto/**/*.js",
|
|
||||||
".gitignore",
|
".gitignore",
|
||||||
"ormconfig.example.json",
|
"ormconfig.example.json",
|
||||||
"package.json"
|
"dist/*",
|
||||||
|
"bin/*"
|
||||||
],
|
],
|
||||||
"env": {
|
"env": {
|
||||||
"NODE_ENV": "development"
|
"NODE_ENV": "development"
|
||||||
},
|
},
|
||||||
"ext":"js,json,ts",
|
"ext":"js,json,ts",
|
||||||
"exec":"tsc && node ./bin/www"
|
"exec":"ts-node ./bin/www"
|
||||||
}
|
}
|
|
@ -4,8 +4,8 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"repository": "git@git.zcj.plus:zhouchijian/express-my-admin.git",
|
"repository": "git@git.zcj.plus:zhouchijian/express-my-admin.git",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "rm -rf dist && tsc && cp .env dist/.env && cp ormconfig.json dist/ormconfig.json && cp -r bin dist/bin && cp -r views ./dist/views",
|
||||||
"start": "node ./bin/www",
|
"start:prod": "cd dist && node ./bin/www",
|
||||||
"dev": "nodemon"
|
"dev": "nodemon"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
"mysql": "^2.18.1",
|
"mysql": "^2.18.1",
|
||||||
"mysql2": "^2.2.5",
|
"mysql2": "^2.2.5",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"ts-node": "^10.1.0",
|
||||||
"typeorm": "^0.2.34"
|
"typeorm": "^0.2.34"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -7,14 +7,14 @@
|
||||||
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
|
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
|
||||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
||||||
"lib": ["es5","es6"], /* Specify library files to be included in the compilation. */
|
"lib": ["es5","es6"], /* Specify library files to be included in the compilation. */
|
||||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
"allowJs": true, /* Allow javascript files to be compiled. */
|
||||||
// "checkJs": true, /* Report errors in .js files. */
|
// "checkJs": true, /* Report errors in .js files. */
|
||||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||||
// "outDir": "dist", /* Redirect output structure to the directory. */
|
"outDir": "dist", /* Redirect output structure to the directory. */
|
||||||
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||||
// "composite": true, /* Enable project compilation */
|
// "composite": true, /* Enable project compilation */
|
||||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
const isJSON = require('is-json')
|
||||||
|
const CryptoJS = require('crypto-js')
|
||||||
|
|
||||||
|
const keyHex = process.env.AES
|
||||||
|
|
||||||
|
function encode (payload, timestamp = 0) {
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
payload,
|
||||||
|
expired_timestamp: timestamp ? timestamp + Date.now() : 0,
|
||||||
|
}
|
||||||
|
const messageHex = CryptoJS.enc.Utf8.parse(JSON.stringify(data))
|
||||||
|
var encrypted = CryptoJS.AES.encrypt(messageHex, keyHex, {
|
||||||
|
mode: CryptoJS.mode.ECB,
|
||||||
|
padding: CryptoJS.pad.Pkcs7,
|
||||||
|
})
|
||||||
|
|
||||||
|
return encrypted.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
function decode (encrypted) {
|
||||||
|
|
||||||
|
const errmsg = '登录凭证无效'
|
||||||
|
|
||||||
|
try{
|
||||||
|
var decrypt = CryptoJS.enc.Utf8.stringify(
|
||||||
|
CryptoJS.AES.decrypt(encrypted, keyHex, {
|
||||||
|
mode: CryptoJS.mode.ECB,
|
||||||
|
padding: CryptoJS.pad.Pkcs7,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
}catch(err) {
|
||||||
|
throw new Error(errmsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isJSON(decrypt)) {
|
||||||
|
throw new Error(errmsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
var payload = JSON.parse(decrypt)
|
||||||
|
|
||||||
|
if (!payload.payload) {
|
||||||
|
throw new Error(errmsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Date.now() >= payload.expired_timestamp) {
|
||||||
|
throw new Error('登录凭证已过期')
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload.payload
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
encode,
|
||||||
|
decode
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { v4 as uuid } from 'uuid'
|
||||||
|
import md5 from 'md5'
|
||||||
|
|
||||||
|
export function md5_uuid ():string {
|
||||||
|
return md5(uuid())
|
||||||
|
}
|
Loading…
Reference in New Issue