diff --git a/back/api/config.ts b/back/api/config.ts index c86bde56..8e412b8b 100644 --- a/back/api/config.ts +++ b/back/api/config.ts @@ -8,10 +8,10 @@ import { celebrate, Joi } from 'celebrate'; const route = Router(); export default (app: Router) => { - app.use('/', route); + app.use('/configs', route); route.get( - '/configs/files', + '/files', async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger'); try { @@ -32,7 +32,7 @@ export default (app: Router) => { ); route.get( - '/configs/:file', + '/:file', async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger'); try { @@ -58,7 +58,7 @@ export default (app: Router) => { ); route.post( - '/configs/save', + '/save', celebrate({ body: Joi.object({ name: Joi.string().required(), diff --git a/back/api/cron.ts b/back/api/cron.ts index dd0b6690..ff2600a0 100644 --- a/back/api/cron.ts +++ b/back/api/cron.ts @@ -7,26 +7,22 @@ import cron_parser from 'cron-parser'; const route = Router(); export default (app: Router) => { - app.use('/', route); - route.get( - '/crons', - async (req: Request, res: Response, next: NextFunction) => { - const logger: Logger = Container.get('logger'); - try { - const cronService = Container.get(CronService); - const data = await cronService.crontabs( - req.query.searchValue as string, - ); - return res.send({ code: 200, data }); - } catch (e) { - logger.error('🔥 error: %o', e); - return next(e); - } - }, - ); + app.use('/crons', route); + + route.get('/', async (req: Request, res: Response, next: NextFunction) => { + const logger: Logger = Container.get('logger'); + try { + const cronService = Container.get(CronService); + const data = await cronService.crontabs(req.query.searchValue as string); + return res.send({ code: 200, data }); + } catch (e) { + logger.error('🔥 error: %o', e); + return next(e); + } + }); route.post( - '/crons', + '/', celebrate({ body: Joi.object({ command: Joi.string().required(), @@ -52,7 +48,7 @@ export default (app: Router) => { ); route.put( - '/crons/run', + '/run', celebrate({ body: Joi.array().items(Joi.string().required()), }), @@ -70,7 +66,7 @@ export default (app: Router) => { ); route.put( - '/crons/stop', + '/stop', celebrate({ body: Joi.array().items(Joi.string().required()), }), @@ -88,7 +84,7 @@ export default (app: Router) => { ); route.put( - '/crons/disable', + '/disable', celebrate({ body: Joi.array().items(Joi.string().required()), }), @@ -106,7 +102,7 @@ export default (app: Router) => { ); route.put( - '/crons/enable', + '/enable', celebrate({ body: Joi.array().items(Joi.string().required()), }), @@ -124,7 +120,7 @@ export default (app: Router) => { ); route.get( - '/crons/:id/log', + '/:id/log', celebrate({ params: Joi.object({ id: Joi.string().required(), @@ -144,7 +140,7 @@ export default (app: Router) => { ); route.put( - '/crons', + '', celebrate({ body: Joi.object({ command: Joi.string().optional(), @@ -174,7 +170,7 @@ export default (app: Router) => { ); route.delete( - '/crons', + '/', celebrate({ body: Joi.array().items(Joi.string().required()), }), @@ -192,7 +188,7 @@ export default (app: Router) => { ); route.put( - '/crons/pin', + '/pin', celebrate({ body: Joi.array().items(Joi.string().required()), }), @@ -210,7 +206,7 @@ export default (app: Router) => { ); route.put( - '/crons/unpin', + '/unpin', celebrate({ body: Joi.array().items(Joi.string().required()), }), @@ -228,7 +224,7 @@ export default (app: Router) => { ); route.get( - '/crons/import', + '/import', async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger'); try { @@ -243,7 +239,7 @@ export default (app: Router) => { ); route.get( - '/crons/:id', + '/:id', celebrate({ params: Joi.object({ id: Joi.string().required(), @@ -263,7 +259,7 @@ export default (app: Router) => { ); route.put( - '/crons/status', + '/status', celebrate({ body: Joi.object({ ids: Joi.array().items(Joi.string().required()), diff --git a/back/api/dependence.ts b/back/api/dependence.ts index 9d4d5bc1..3e805905 100644 --- a/back/api/dependence.ts +++ b/back/api/dependence.ts @@ -6,24 +6,22 @@ import { celebrate, Joi } from 'celebrate'; const route = Router(); export default (app: Router) => { - app.use('/', route); - route.get( - '/dependencies', - async (req: Request, res: Response, next: NextFunction) => { - const logger: Logger = Container.get('logger'); - try { - const dependenceService = Container.get(DependenceService); - const data = await dependenceService.dependencies(req.query as any); - return res.send({ code: 200, data }); - } catch (e) { - logger.error('🔥 error: %o', e); - return next(e); - } - }, - ); + app.use('/dependencies', route); + + route.get('/', async (req: Request, res: Response, next: NextFunction) => { + const logger: Logger = Container.get('logger'); + try { + const dependenceService = Container.get(DependenceService); + const data = await dependenceService.dependencies(req.query as any); + return res.send({ code: 200, data }); + } catch (e) { + logger.error('🔥 error: %o', e); + return next(e); + } + }); route.post( - '/dependencies', + '/', celebrate({ body: Joi.array().items( Joi.object({ @@ -47,7 +45,7 @@ export default (app: Router) => { ); route.put( - '/dependencies', + '/', celebrate({ body: Joi.object({ name: Joi.string().required(), @@ -70,7 +68,7 @@ export default (app: Router) => { ); route.delete( - '/dependencies', + '/', celebrate({ body: Joi.array().items(Joi.string().required()), }), @@ -88,7 +86,7 @@ export default (app: Router) => { ); route.delete( - '/dependencies/force', + '/force', celebrate({ body: Joi.array().items(Joi.string().required()), }), @@ -106,7 +104,7 @@ export default (app: Router) => { ); route.get( - '/dependencies/:id', + '/:id', celebrate({ params: Joi.object({ id: Joi.string().required(), @@ -126,7 +124,7 @@ export default (app: Router) => { ); route.put( - '/dependencies/reinstall', + '/reinstall', celebrate({ body: Joi.array().items(Joi.string().required()), }), diff --git a/back/api/env.ts b/back/api/env.ts index 1b2fbec8..9297cf23 100644 --- a/back/api/env.ts +++ b/back/api/env.ts @@ -6,24 +6,22 @@ import { celebrate, Joi } from 'celebrate'; const route = Router(); export default (app: Router) => { - app.use('/', route); - route.get( - '/envs', - async (req: Request, res: Response, next: NextFunction) => { - const logger: Logger = Container.get('logger'); - try { - const envService = Container.get(EnvService); - const data = await envService.envs(req.query.searchValue as string); - return res.send({ code: 200, data }); - } catch (e) { - logger.error('🔥 error: %o', e); - return next(e); - } - }, - ); + app.use('/envs', route); + + route.get('/', async (req: Request, res: Response, next: NextFunction) => { + const logger: Logger = Container.get('logger'); + try { + const envService = Container.get(EnvService); + const data = await envService.envs(req.query.searchValue as string); + return res.send({ code: 200, data }); + } catch (e) { + logger.error('🔥 error: %o', e); + return next(e); + } + }); route.post( - '/envs', + '/', celebrate({ body: Joi.array().items( Joi.object({ @@ -47,7 +45,7 @@ export default (app: Router) => { ); route.put( - '/envs', + '/', celebrate({ body: Joi.object({ value: Joi.string().required(), @@ -70,7 +68,7 @@ export default (app: Router) => { ); route.delete( - '/envs', + '/', celebrate({ body: Joi.array().items(Joi.string().required()), }), @@ -88,7 +86,7 @@ export default (app: Router) => { ); route.put( - '/envs/:id/move', + '/:id/move', celebrate({ params: Joi.object({ id: Joi.string().required(), @@ -112,7 +110,7 @@ export default (app: Router) => { ); route.put( - '/envs/disable', + '/disable', celebrate({ body: Joi.array().items(Joi.string().required()), }), @@ -130,7 +128,7 @@ export default (app: Router) => { ); route.put( - '/envs/enable', + '/enable', celebrate({ body: Joi.array().items(Joi.string().required()), }), @@ -148,7 +146,7 @@ export default (app: Router) => { ); route.put( - '/envs/name', + '/name', celebrate({ body: Joi.object({ ids: Joi.array().items(Joi.string().required()), @@ -169,7 +167,7 @@ export default (app: Router) => { ); route.get( - '/envs/:id', + '/:id', celebrate({ params: Joi.object({ id: Joi.string().required(), diff --git a/back/api/index.ts b/back/api/index.ts index 0921a955..f616b91a 100644 --- a/back/api/index.ts +++ b/back/api/index.ts @@ -7,6 +7,7 @@ import cron from './cron'; import script from './script'; import open from './open'; import dependence from './dependence'; +import system from './system'; export default () => { const app = Router(); @@ -18,6 +19,7 @@ export default () => { script(app); open(app); dependence(app); + system(app); return app; }; diff --git a/back/api/log.ts b/back/api/log.ts index 6d9feb8b..e6e1af94 100644 --- a/back/api/log.ts +++ b/back/api/log.ts @@ -7,44 +7,42 @@ import { getFileContentByName } from '../config/util'; const route = Router(); export default (app: Router) => { - app.use('/', route); - route.get( - '/logs', - async (req: Request, res: Response, next: NextFunction) => { - const logger: Logger = Container.get('logger'); - try { - const fileList = fs.readdirSync(config.logPath, 'utf-8'); - const dirs = []; - for (let i = 0; i < fileList.length; i++) { - const stat = fs.lstatSync(config.logPath + fileList[i]); - if (stat.isDirectory()) { - const fileListTmp = fs.readdirSync( - `${config.logPath}/${fileList[i]}`, - 'utf-8', - ); - dirs.push({ - name: fileList[i], - isDir: true, - files: fileListTmp.reverse(), - }); - } else { - dirs.push({ - name: fileList[i], - isDir: false, - files: [], - }); - } + app.use('/logs', route); + + route.get('/', async (req: Request, res: Response, next: NextFunction) => { + const logger: Logger = Container.get('logger'); + try { + const fileList = fs.readdirSync(config.logPath, 'utf-8'); + const dirs = []; + for (let i = 0; i < fileList.length; i++) { + const stat = fs.lstatSync(config.logPath + fileList[i]); + if (stat.isDirectory()) { + const fileListTmp = fs.readdirSync( + `${config.logPath}/${fileList[i]}`, + 'utf-8', + ); + dirs.push({ + name: fileList[i], + isDir: true, + files: fileListTmp.reverse(), + }); + } else { + dirs.push({ + name: fileList[i], + isDir: false, + 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( - '/logs/:dir/:file', + '/:dir/:file', async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger'); try { @@ -61,7 +59,7 @@ export default (app: Router) => { ); route.get( - '/logs/:file', + '/:file', async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger'); try { diff --git a/back/api/script.ts b/back/api/script.ts index 0fdc5654..bd2805bf 100644 --- a/back/api/script.ts +++ b/back/api/script.ts @@ -14,10 +14,10 @@ import ScriptService from '../services/script'; const route = Router(); export default (app: Router) => { - app.use('/', route); + app.use('/scripts', route); route.get( - '/scripts/files', + '/files', async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger'); try { @@ -80,7 +80,7 @@ export default (app: Router) => { ); route.get( - '/scripts/:file', + '/:file', async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger'); try { @@ -99,7 +99,7 @@ export default (app: Router) => { ); route.post( - '/scripts', + '/', celebrate({ body: Joi.object({ filename: Joi.string().required(), @@ -159,7 +159,7 @@ export default (app: Router) => { ); route.put( - '/scripts', + '/', celebrate({ body: Joi.object({ filename: Joi.string().required(), @@ -186,7 +186,7 @@ export default (app: Router) => { ); route.delete( - '/scripts', + '/', celebrate({ body: Joi.object({ filename: Joi.string().required(), @@ -211,7 +211,7 @@ export default (app: Router) => { ); route.post( - '/scripts/download', + '/download', celebrate({ body: Joi.object({ filename: Joi.string().required(), @@ -242,7 +242,7 @@ export default (app: Router) => { ); route.put( - '/scripts/run', + '/run', celebrate({ body: Joi.object({ filename: Joi.string().required(), diff --git a/back/api/system.ts b/back/api/system.ts new file mode 100644 index 00000000..8aba494e --- /dev/null +++ b/back/api/system.ts @@ -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); + } + }, + ); +}; diff --git a/back/api/user.ts b/back/api/user.ts index 4a87ff81..9cfd47a8 100644 --- a/back/api/user.ts +++ b/back/api/user.ts @@ -9,7 +9,8 @@ import { getFileContentByName } from '../config/util'; const route = Router(); export default (app: Router) => { - app.use('/', route); + app.use('/user', route); + route.post( '/login', celebrate({ @@ -47,7 +48,7 @@ export default (app: Router) => { ); route.put( - '/user', + '/', celebrate({ body: Joi.object({ username: Joi.string().required(), @@ -67,29 +68,26 @@ export default (app: Router) => { }, ); - route.get( - '/user', - async (req: Request, res: Response, next: NextFunction) => { - const logger: Logger = Container.get('logger'); - try { - const userService = Container.get(UserService); - const authInfo = await userService.getUserInfo(); - res.send({ - code: 200, - data: { - username: authInfo.username, - twoFactorActivated: authInfo.twoFactorActivated, - }, - }); - } catch (e) { - logger.error('🔥 error: %o', e); - return next(e); - } - }, - ); + 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(); + res.send({ + code: 200, + data: { + username: authInfo.username, + twoFactorActivated: authInfo.twoFactorActivated, + }, + }); + } catch (e) { + logger.error('🔥 error: %o', e); + return next(e); + } + }); route.get( - '/user/two-factor/init', + '/two-factor/init', async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger'); try { @@ -104,7 +102,7 @@ export default (app: Router) => { ); route.put( - '/user/two-factor/active', + '/two-factor/active', celebrate({ body: Joi.object({ code: Joi.string().required(), @@ -124,7 +122,7 @@ export default (app: Router) => { ); route.put( - '/user/two-factor/deactive', + '/two-factor/deactive', async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger'); try { @@ -139,7 +137,7 @@ export default (app: Router) => { ); route.put( - '/user/two-factor/login', + '/two-factor/login', celebrate({ body: Joi.object({ code: Joi.string().required(), @@ -161,7 +159,7 @@ export default (app: Router) => { ); route.get( - '/user/login-log', + '/login-log', async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger'); try { @@ -176,7 +174,7 @@ export default (app: Router) => { ); route.get( - '/user/notification', + '/notification', async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger'); try { @@ -191,7 +189,7 @@ export default (app: Router) => { ); route.put( - '/user/notification', + '/notification', async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger'); 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( - '/init/user', + '/init', celebrate({ body: Joi.object({ username: Joi.string().required(), @@ -261,7 +225,7 @@ export default (app: Router) => { ); route.put( - '/init/notification', + '/notification/init', async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger'); 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); - } - }, - ); }; diff --git a/back/config/index.ts b/back/config/index.ts index e5ac7562..0e525291 100644 --- a/back/config/index.ts +++ b/back/config/index.ts @@ -81,8 +81,8 @@ export default { '/open/auth/token', '/api/user/two-factor/login', '/api/system', - '/api/init/user', - '/api/init/notification', + '/api/user/init', + '/api/user/notification/init', ], versionFile, lastVersionFile, diff --git a/back/loaders/express.ts b/back/loaders/express.ts index f76ec5a0..0541cd3e 100644 --- a/back/loaders/express.ts +++ b/back/loaders/express.ts @@ -98,7 +98,7 @@ export default ({ app }: { app: Application }) => { }); 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(); } const userService = Container.get(UserService); diff --git a/back/services/system.ts b/back/services/system.ts new file mode 100644 index 00000000..93a884e9 --- /dev/null +++ b/back/services/system.ts @@ -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 { + 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 }; + } +} diff --git a/src/pages/initialization/index.tsx b/src/pages/initialization/index.tsx index 2a66989c..05086833 100644 --- a/src/pages/initialization/index.tsx +++ b/src/pages/initialization/index.tsx @@ -35,7 +35,7 @@ const Initialization = () => { const submitAccountSetting = (values: any) => { setLoading(true); request - .put(`${config.apiPrefix}init/user`, { + .put(`${config.apiPrefix}user/init`, { data: { username: values.username, password: values.password, @@ -53,7 +53,7 @@ const Initialization = () => { const submitNotification = (values: any) => { request - .put(`${config.apiPrefix}init/notification`, { + .put(`${config.apiPrefix}user/notification/init`, { data: { ...values, }, diff --git a/src/utils/config.ts b/src/utils/config.ts index 9d5c7e92..11c72dad 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -59,6 +59,10 @@ export default { name: '依赖管理', value: 'dependencies', }, + { + name: '系统信息', + value: 'system', + }, ], scopesMap: { crons: '定时任务', diff --git a/src/utils/http.ts b/src/utils/http.ts index bf2c93d1..f85f5b0f 100644 --- a/src/utils/http.ts +++ b/src/utils/http.ts @@ -38,8 +38,8 @@ const apiWhiteList = [ '/open/auth/token', '/api/user/two-factor/login', '/api/system', - '/api/init/user', - '/api/init/notification', + '/api/user/init', + '/api/user/notification/init', ]; _request.interceptors.request.use((url, options) => {