增加系统openapi

This commit is contained in:
whyour 2021-12-21 23:22:34 +08:00
parent 3eaf0b4856
commit 0c840095d1
15 changed files with 451 additions and 260 deletions

View File

@ -8,10 +8,10 @@ import { celebrate, Joi } from 'celebrate';
const route = Router(); const route = Router();
export default (app: Router) => { export default (app: Router) => {
app.use('/', route); app.use('/configs', route);
route.get( route.get(
'/configs/files', '/files',
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
@ -32,7 +32,7 @@ export default (app: Router) => {
); );
route.get( route.get(
'/configs/:file', '/:file',
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
@ -58,7 +58,7 @@ export default (app: Router) => {
); );
route.post( route.post(
'/configs/save', '/save',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
name: Joi.string().required(), name: Joi.string().required(),

View File

@ -7,26 +7,22 @@ import cron_parser from 'cron-parser';
const route = Router(); const route = Router();
export default (app: Router) => { export default (app: Router) => {
app.use('/', route); app.use('/crons', route);
route.get(
'/crons', route.get('/', async (req: Request, res: Response, next: NextFunction) => {
async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger');
const logger: Logger = Container.get('logger'); try {
try { const cronService = Container.get(CronService);
const cronService = Container.get(CronService); const data = await cronService.crontabs(req.query.searchValue as string);
const data = await cronService.crontabs( return res.send({ code: 200, data });
req.query.searchValue as string, } catch (e) {
); logger.error('🔥 error: %o', e);
return res.send({ code: 200, data }); return next(e);
} catch (e) { }
logger.error('🔥 error: %o', e); });
return next(e);
}
},
);
route.post( route.post(
'/crons', '/',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
command: Joi.string().required(), command: Joi.string().required(),
@ -52,7 +48,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/crons/run', '/run',
celebrate({ celebrate({
body: Joi.array().items(Joi.string().required()), body: Joi.array().items(Joi.string().required()),
}), }),
@ -70,7 +66,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/crons/stop', '/stop',
celebrate({ celebrate({
body: Joi.array().items(Joi.string().required()), body: Joi.array().items(Joi.string().required()),
}), }),
@ -88,7 +84,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/crons/disable', '/disable',
celebrate({ celebrate({
body: Joi.array().items(Joi.string().required()), body: Joi.array().items(Joi.string().required()),
}), }),
@ -106,7 +102,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/crons/enable', '/enable',
celebrate({ celebrate({
body: Joi.array().items(Joi.string().required()), body: Joi.array().items(Joi.string().required()),
}), }),
@ -124,7 +120,7 @@ export default (app: Router) => {
); );
route.get( route.get(
'/crons/:id/log', '/:id/log',
celebrate({ celebrate({
params: Joi.object({ params: Joi.object({
id: Joi.string().required(), id: Joi.string().required(),
@ -144,7 +140,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/crons', '',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
command: Joi.string().optional(), command: Joi.string().optional(),
@ -174,7 +170,7 @@ export default (app: Router) => {
); );
route.delete( route.delete(
'/crons', '/',
celebrate({ celebrate({
body: Joi.array().items(Joi.string().required()), body: Joi.array().items(Joi.string().required()),
}), }),
@ -192,7 +188,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/crons/pin', '/pin',
celebrate({ celebrate({
body: Joi.array().items(Joi.string().required()), body: Joi.array().items(Joi.string().required()),
}), }),
@ -210,7 +206,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/crons/unpin', '/unpin',
celebrate({ celebrate({
body: Joi.array().items(Joi.string().required()), body: Joi.array().items(Joi.string().required()),
}), }),
@ -228,7 +224,7 @@ export default (app: Router) => {
); );
route.get( route.get(
'/crons/import', '/import',
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
@ -243,7 +239,7 @@ export default (app: Router) => {
); );
route.get( route.get(
'/crons/:id', '/:id',
celebrate({ celebrate({
params: Joi.object({ params: Joi.object({
id: Joi.string().required(), id: Joi.string().required(),
@ -263,7 +259,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/crons/status', '/status',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
ids: Joi.array().items(Joi.string().required()), ids: Joi.array().items(Joi.string().required()),

View File

@ -6,24 +6,22 @@ import { celebrate, Joi } from 'celebrate';
const route = Router(); const route = Router();
export default (app: Router) => { export default (app: Router) => {
app.use('/', route); app.use('/dependencies', route);
route.get(
'/dependencies', route.get('/', async (req: Request, res: Response, next: NextFunction) => {
async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger');
const logger: Logger = Container.get('logger'); try {
try { const dependenceService = Container.get(DependenceService);
const dependenceService = Container.get(DependenceService); const data = await dependenceService.dependencies(req.query as any);
const data = await dependenceService.dependencies(req.query as any); return res.send({ code: 200, data });
return res.send({ code: 200, data }); } catch (e) {
} catch (e) { logger.error('🔥 error: %o', e);
logger.error('🔥 error: %o', e); return next(e);
return next(e); }
} });
},
);
route.post( route.post(
'/dependencies', '/',
celebrate({ celebrate({
body: Joi.array().items( body: Joi.array().items(
Joi.object({ Joi.object({
@ -47,7 +45,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/dependencies', '/',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
name: Joi.string().required(), name: Joi.string().required(),
@ -70,7 +68,7 @@ export default (app: Router) => {
); );
route.delete( route.delete(
'/dependencies', '/',
celebrate({ celebrate({
body: Joi.array().items(Joi.string().required()), body: Joi.array().items(Joi.string().required()),
}), }),
@ -88,7 +86,7 @@ export default (app: Router) => {
); );
route.delete( route.delete(
'/dependencies/force', '/force',
celebrate({ celebrate({
body: Joi.array().items(Joi.string().required()), body: Joi.array().items(Joi.string().required()),
}), }),
@ -106,7 +104,7 @@ export default (app: Router) => {
); );
route.get( route.get(
'/dependencies/:id', '/:id',
celebrate({ celebrate({
params: Joi.object({ params: Joi.object({
id: Joi.string().required(), id: Joi.string().required(),
@ -126,7 +124,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/dependencies/reinstall', '/reinstall',
celebrate({ celebrate({
body: Joi.array().items(Joi.string().required()), body: Joi.array().items(Joi.string().required()),
}), }),

View File

@ -6,24 +6,22 @@ import { celebrate, Joi } from 'celebrate';
const route = Router(); const route = Router();
export default (app: Router) => { export default (app: Router) => {
app.use('/', route); app.use('/envs', route);
route.get(
'/envs', route.get('/', async (req: Request, res: Response, next: NextFunction) => {
async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger');
const logger: Logger = Container.get('logger'); try {
try { const envService = Container.get(EnvService);
const envService = Container.get(EnvService); const data = await envService.envs(req.query.searchValue as string);
const data = await envService.envs(req.query.searchValue as string); return res.send({ code: 200, data });
return res.send({ code: 200, data }); } catch (e) {
} catch (e) { logger.error('🔥 error: %o', e);
logger.error('🔥 error: %o', e); return next(e);
return next(e); }
} });
},
);
route.post( route.post(
'/envs', '/',
celebrate({ celebrate({
body: Joi.array().items( body: Joi.array().items(
Joi.object({ Joi.object({
@ -47,7 +45,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/envs', '/',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
value: Joi.string().required(), value: Joi.string().required(),
@ -70,7 +68,7 @@ export default (app: Router) => {
); );
route.delete( route.delete(
'/envs', '/',
celebrate({ celebrate({
body: Joi.array().items(Joi.string().required()), body: Joi.array().items(Joi.string().required()),
}), }),
@ -88,7 +86,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/envs/:id/move', '/:id/move',
celebrate({ celebrate({
params: Joi.object({ params: Joi.object({
id: Joi.string().required(), id: Joi.string().required(),
@ -112,7 +110,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/envs/disable', '/disable',
celebrate({ celebrate({
body: Joi.array().items(Joi.string().required()), body: Joi.array().items(Joi.string().required()),
}), }),
@ -130,7 +128,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/envs/enable', '/enable',
celebrate({ celebrate({
body: Joi.array().items(Joi.string().required()), body: Joi.array().items(Joi.string().required()),
}), }),
@ -148,7 +146,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/envs/name', '/name',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
ids: Joi.array().items(Joi.string().required()), ids: Joi.array().items(Joi.string().required()),
@ -169,7 +167,7 @@ export default (app: Router) => {
); );
route.get( route.get(
'/envs/:id', '/:id',
celebrate({ celebrate({
params: Joi.object({ params: Joi.object({
id: Joi.string().required(), id: Joi.string().required(),

View File

@ -7,6 +7,7 @@ import cron from './cron';
import script from './script'; import script from './script';
import open from './open'; import open from './open';
import dependence from './dependence'; import dependence from './dependence';
import system from './system';
export default () => { export default () => {
const app = Router(); const app = Router();
@ -18,6 +19,7 @@ export default () => {
script(app); script(app);
open(app); open(app);
dependence(app); dependence(app);
system(app);
return app; return app;
}; };

View File

@ -7,44 +7,42 @@ import { getFileContentByName } from '../config/util';
const route = Router(); const route = Router();
export default (app: Router) => { export default (app: Router) => {
app.use('/', route); app.use('/logs', route);
route.get(
'/logs', route.get('/', async (req: Request, res: Response, next: NextFunction) => {
async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger');
const logger: Logger = Container.get('logger'); try {
try { const fileList = fs.readdirSync(config.logPath, 'utf-8');
const fileList = fs.readdirSync(config.logPath, 'utf-8'); const dirs = [];
const dirs = []; for (let i = 0; i < fileList.length; i++) {
for (let i = 0; i < fileList.length; i++) { const stat = fs.lstatSync(config.logPath + fileList[i]);
const stat = fs.lstatSync(config.logPath + fileList[i]); if (stat.isDirectory()) {
if (stat.isDirectory()) { const fileListTmp = fs.readdirSync(
const fileListTmp = fs.readdirSync( `${config.logPath}/${fileList[i]}`,
`${config.logPath}/${fileList[i]}`, 'utf-8',
'utf-8', );
); dirs.push({
dirs.push({ name: fileList[i],
name: fileList[i], isDir: true,
isDir: true, files: fileListTmp.reverse(),
files: fileListTmp.reverse(), });
}); } else {
} else { dirs.push({
dirs.push({ name: fileList[i],
name: fileList[i], isDir: false,
isDir: false, files: [],
files: [], });
});
}
} }
res.send({ code: 200, dirs });
} catch (e) {
logger.error('🔥 error: %o', e);
return next(e);
} }
}, res.send({ code: 200, dirs });
); } catch (e) {
logger.error('🔥 error: %o', e);
return next(e);
}
});
route.get( route.get(
'/logs/:dir/:file', '/:dir/:file',
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
@ -61,7 +59,7 @@ export default (app: Router) => {
); );
route.get( route.get(
'/logs/:file', '/:file',
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {

View File

@ -14,10 +14,10 @@ import ScriptService from '../services/script';
const route = Router(); const route = Router();
export default (app: Router) => { export default (app: Router) => {
app.use('/', route); app.use('/scripts', route);
route.get( route.get(
'/scripts/files', '/files',
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
@ -80,7 +80,7 @@ export default (app: Router) => {
); );
route.get( route.get(
'/scripts/:file', '/:file',
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
@ -99,7 +99,7 @@ export default (app: Router) => {
); );
route.post( route.post(
'/scripts', '/',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
filename: Joi.string().required(), filename: Joi.string().required(),
@ -159,7 +159,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/scripts', '/',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
filename: Joi.string().required(), filename: Joi.string().required(),
@ -186,7 +186,7 @@ export default (app: Router) => {
); );
route.delete( route.delete(
'/scripts', '/',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
filename: Joi.string().required(), filename: Joi.string().required(),
@ -211,7 +211,7 @@ export default (app: Router) => {
); );
route.post( route.post(
'/scripts/download', '/download',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
filename: Joi.string().required(), filename: Joi.string().required(),
@ -242,7 +242,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/scripts/run', '/run',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
filename: Joi.string().required(), filename: Joi.string().required(),

114
back/api/system.ts Normal file
View File

@ -0,0 +1,114 @@
import { Router, Request, Response, NextFunction } from 'express';
import { Container } from 'typedi';
import { Logger } from 'winston';
import * as fs from 'fs';
import config from '../config';
import SystemService from '../services/system';
import { celebrate, Joi } from 'celebrate';
import { getFileContentByName } from '../config/util';
import UserService from '../services/user';
const route = Router();
export default (app: Router) => {
app.use('/system', route);
route.get('/', async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
const userService = Container.get(UserService);
const authInfo = await userService.getUserInfo();
const envDbContent = getFileContentByName(config.envDbFile);
const versionRegx = /.*export const version = \'(.*)\'\;/;
const currentVersionFile = fs.readFileSync(config.versionFile, 'utf8');
const version = currentVersionFile.match(versionRegx)![1];
let isInitialized = true;
if (
Object.keys(authInfo).length === 2 &&
authInfo.username === 'admin' &&
authInfo.password === 'admin' &&
envDbContent.length === 0
) {
isInitialized = false;
}
res.send({
code: 200,
data: {
isInitialized,
version,
},
});
} catch (e) {
logger.error('🔥 error: %o', e);
return next(e);
}
});
route.get(
'/log/remove',
async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
const systemService = Container.get(SystemService);
const data = await systemService.getLogRemoveFrequency();
res.send({ code: 200, data });
} catch (e) {
logger.error('🔥 error: %o', e);
return next(e);
}
},
);
route.put(
'/log/remove',
celebrate({
body: Joi.object({
frequency: Joi.number().required(),
}),
}),
async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
const systemService = Container.get(SystemService);
const result = await systemService.updateLogRemoveFrequency(
req.body.frequency,
);
res.send(result);
} catch (e) {
logger.error('🔥 error: %o', e);
return next(e);
}
},
);
route.put(
'/update-check',
async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
const systemService = Container.get(SystemService);
const result = await systemService.checkUpdate();
res.send(result);
} catch (e) {
logger.error('🔥 error: %o', e);
return next(e);
}
},
);
route.put(
'/update',
async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
const systemService = Container.get(SystemService);
const result = await systemService.updateSystem();
res.send(result);
} catch (e) {
logger.error('🔥 error: %o', e);
return next(e);
}
},
);
};

View File

@ -9,7 +9,8 @@ import { getFileContentByName } from '../config/util';
const route = Router(); const route = Router();
export default (app: Router) => { export default (app: Router) => {
app.use('/', route); app.use('/user', route);
route.post( route.post(
'/login', '/login',
celebrate({ celebrate({
@ -47,7 +48,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/user', '/',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
username: Joi.string().required(), username: Joi.string().required(),
@ -67,29 +68,26 @@ export default (app: Router) => {
}, },
); );
route.get( route.get('/', async (req: Request, res: Response, next: NextFunction) => {
'/user', const logger: Logger = Container.get('logger');
async (req: Request, res: Response, next: NextFunction) => { try {
const logger: Logger = Container.get('logger'); const userService = Container.get(UserService);
try { const authInfo = await userService.getUserInfo();
const userService = Container.get(UserService); res.send({
const authInfo = await userService.getUserInfo(); code: 200,
res.send({ data: {
code: 200, username: authInfo.username,
data: { twoFactorActivated: authInfo.twoFactorActivated,
username: authInfo.username, },
twoFactorActivated: authInfo.twoFactorActivated, });
}, } catch (e) {
}); logger.error('🔥 error: %o', e);
} catch (e) { return next(e);
logger.error('🔥 error: %o', e); }
return next(e); });
}
},
);
route.get( route.get(
'/user/two-factor/init', '/two-factor/init',
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
@ -104,7 +102,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/user/two-factor/active', '/two-factor/active',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
code: Joi.string().required(), code: Joi.string().required(),
@ -124,7 +122,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/user/two-factor/deactive', '/two-factor/deactive',
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
@ -139,7 +137,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/user/two-factor/login', '/two-factor/login',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
code: Joi.string().required(), code: Joi.string().required(),
@ -161,7 +159,7 @@ export default (app: Router) => {
); );
route.get( route.get(
'/user/login-log', '/login-log',
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
@ -176,7 +174,7 @@ export default (app: Router) => {
); );
route.get( route.get(
'/user/notification', '/notification',
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
@ -191,7 +189,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/user/notification', '/notification',
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
@ -205,42 +203,8 @@ export default (app: Router) => {
}, },
); );
route.get(
'/system',
async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
const userService = Container.get(UserService);
const authInfo = await userService.getUserInfo();
const envDbContent = getFileContentByName(config.envDbFile);
const { version } = await import(config.versionFile);
let isInitialized = true;
if (
Object.keys(authInfo).length === 2 &&
authInfo.username === 'admin' &&
authInfo.password === 'admin' &&
envDbContent.length === 0
) {
isInitialized = false;
}
res.send({
code: 200,
data: {
isInitialized,
version,
},
});
} catch (e) {
logger.error('🔥 error: %o', e);
return next(e);
}
},
);
// 初始化api
route.put( route.put(
'/init/user', '/init',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
username: Joi.string().required(), username: Joi.string().required(),
@ -261,7 +225,7 @@ export default (app: Router) => {
); );
route.put( route.put(
'/init/notification', '/notification/init',
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
@ -274,71 +238,4 @@ export default (app: Router) => {
} }
}, },
); );
route.get(
'/system/log/remove',
async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
const userService = Container.get(UserService);
const data = await userService.getLogRemoveFrequency();
res.send({ code: 200, data });
} catch (e) {
logger.error('🔥 error: %o', e);
return next(e);
}
},
);
route.put(
'/system/log/remove',
celebrate({
body: Joi.object({
frequency: Joi.number().required(),
}),
}),
async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
const userService = Container.get(UserService);
const result = await userService.updateLogRemoveFrequency(
req.body.frequency,
);
res.send(result);
} catch (e) {
logger.error('🔥 error: %o', e);
return next(e);
}
},
);
route.put(
'/system/update-check',
async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
const userService = Container.get(UserService);
const result = await userService.checkUpdate();
res.send(result);
} catch (e) {
logger.error('🔥 error: %o', e);
return next(e);
}
},
);
route.put(
'/system/update',
async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
const userService = Container.get(UserService);
const result = await userService.updateSystem();
res.send(result);
} catch (e) {
logger.error('🔥 error: %o', e);
return next(e);
}
},
);
}; };

View File

@ -81,8 +81,8 @@ export default {
'/open/auth/token', '/open/auth/token',
'/api/user/two-factor/login', '/api/user/two-factor/login',
'/api/system', '/api/system',
'/api/init/user', '/api/user/init',
'/api/init/notification', '/api/user/notification/init',
], ],
versionFile, versionFile,
lastVersionFile, lastVersionFile,

View File

@ -98,7 +98,7 @@ export default ({ app }: { app: Application }) => {
}); });
app.use(async (req, res, next) => { app.use(async (req, res, next) => {
if (!['/api/init/user', '/api/init/notification'].includes(req.path)) { if (!['/api/user/init', '/api/user/notification/init'].includes(req.path)) {
return next(); return next();
} }
const userService = Container.get(UserService); const userService = Container.get(UserService);

184
back/services/system.ts Normal file
View File

@ -0,0 +1,184 @@
import { Service, Inject } from 'typedi';
import winston from 'winston';
import config from '../config';
import * as fs from 'fs';
import _ from 'lodash';
import { AuthDataType, AuthInfo, LoginStatus } from '../data/auth';
import { NotificationInfo } from '../data/notify';
import NotificationService from './notify';
import ScheduleService from './schedule';
import { spawn } from 'child_process';
import SockService from './sock';
import got from 'got';
import { dbs } from '../loaders/db';
@Service()
export default class SystemService {
@Inject((type) => NotificationService)
private notificationService!: NotificationService;
private authDb = dbs.authDb;
constructor(
@Inject('logger') private logger: winston.Logger,
private scheduleService: ScheduleService,
private sockService: SockService,
) {}
public async getLogRemoveFrequency() {
return new Promise((resolve) => {
this.authDb
.find({ type: AuthDataType.removeLogFrequency })
.exec((err, docs) => {
if (err || docs.length === 0) {
resolve({});
} else {
resolve(docs[0].info);
}
});
});
}
private async updateAuthDb(payload: AuthInfo): Promise<any> {
return new Promise((resolve) => {
this.authDb.update(
{ type: payload.type },
{ ...payload },
{ upsert: true, returnUpdatedDocs: true },
(err, num, doc: any) => {
if (err) {
resolve({} as NotificationInfo);
} else {
resolve({ ...doc.info, _id: doc._id });
}
},
);
});
}
public async updateNotificationMode(notificationInfo: NotificationInfo) {
const code = Math.random().toString().slice(-6);
const isSuccess = await this.notificationService.testNotify(
notificationInfo,
'青龙',
`【蛟龙】测试通知 https://t.me/jiao_long`,
);
if (isSuccess) {
const result = await this.updateAuthDb({
type: AuthDataType.notification,
info: { ...notificationInfo },
});
return { code: 200, data: { ...result, code } };
} else {
return { code: 400, data: '通知发送失败,请检查参数' };
}
}
public async updateLogRemoveFrequency(frequency: number) {
const result = await this.updateAuthDb({
type: AuthDataType.removeLogFrequency,
info: { frequency },
});
const cron = {
_id: result._id,
name: '删除日志',
command: `ql rmlog ${frequency}`,
schedule: `5 23 */${frequency} * *`,
};
await this.scheduleService.cancelSchedule(cron);
if (frequency > 0) {
await this.scheduleService.generateSchedule(cron);
}
return { code: 200, data: { ...cron } };
}
public async checkUpdate() {
try {
const versionRegx = /.*export const version = \'(.*)\'\;/;
const logRegx = /.*export const changeLog = \`((.*\n.*)+)\`;/;
const currentVersionFile = fs.readFileSync(config.versionFile, 'utf8');
const currentVersion = currentVersionFile.match(versionRegx)![1];
let lastVersion = '';
let lastLog = '';
try {
const result = await Promise.race([
got.get(config.lastVersionFile, { timeout: 1000, retry: 0 }),
got.get(`https://ghproxy.com/${config.lastVersionFile}`, {
timeout: 5000,
retry: 0,
}),
]);
const lastVersionFileContent = result.body;
lastVersion = lastVersionFileContent.match(versionRegx)![1];
lastLog = lastVersionFileContent.match(logRegx)
? lastVersionFileContent.match(logRegx)![1]
: '';
} catch (error) {}
return {
code: 200,
data: {
hasNewVersion: this.checkHasNewVersion(currentVersion, lastVersion),
lastVersion,
lastLog,
},
};
} catch (error: any) {
return {
code: 400,
data: error.message,
};
}
}
private checkHasNewVersion(curVersion: string, lastVersion: string) {
const curArr = curVersion.split('.').map((x) => parseInt(x, 10));
const lastArr = lastVersion.split('.').map((x) => parseInt(x, 10));
if (curArr[0] < lastArr[0]) {
return true;
}
if (curArr[0] === lastArr[0] && curArr[1] < lastArr[1]) {
return true;
}
if (
curArr[0] === lastArr[0] &&
curArr[1] === lastArr[1] &&
curArr[2] < lastArr[2]
) {
return true;
}
return false;
}
public async updateSystem() {
const cp = spawn('ql -l update', { shell: '/bin/bash' });
this.sockService.sendMessage({
type: 'updateSystemVersion',
message: `开始更新系统`,
});
cp.stdout.on('data', (data) => {
this.sockService.sendMessage({
type: 'updateSystemVersion',
message: data.toString(),
});
});
cp.stderr.on('data', (data) => {
this.sockService.sendMessage({
type: 'updateSystemVersion',
message: data.toString(),
});
});
cp.on('error', (err) => {
this.sockService.sendMessage({
type: 'updateSystemVersion',
message: JSON.stringify(err),
});
});
return { code: 200 };
}
}

View File

@ -35,7 +35,7 @@ const Initialization = () => {
const submitAccountSetting = (values: any) => { const submitAccountSetting = (values: any) => {
setLoading(true); setLoading(true);
request request
.put(`${config.apiPrefix}init/user`, { .put(`${config.apiPrefix}user/init`, {
data: { data: {
username: values.username, username: values.username,
password: values.password, password: values.password,
@ -53,7 +53,7 @@ const Initialization = () => {
const submitNotification = (values: any) => { const submitNotification = (values: any) => {
request request
.put(`${config.apiPrefix}init/notification`, { .put(`${config.apiPrefix}user/notification/init`, {
data: { data: {
...values, ...values,
}, },

View File

@ -59,6 +59,10 @@ export default {
name: '依赖管理', name: '依赖管理',
value: 'dependencies', value: 'dependencies',
}, },
{
name: '系统信息',
value: 'system',
},
], ],
scopesMap: { scopesMap: {
crons: '定时任务', crons: '定时任务',

View File

@ -38,8 +38,8 @@ const apiWhiteList = [
'/open/auth/token', '/open/auth/token',
'/api/user/two-factor/login', '/api/user/two-factor/login',
'/api/system', '/api/system',
'/api/init/user', '/api/user/init',
'/api/init/notification', '/api/user/notification/init',
]; ];
_request.interceptors.request.use((url, options) => { _request.interceptors.request.use((url, options) => {