Skip to content

Commit

Permalink
✨ plus&功能重构
Browse files Browse the repository at this point in the history
  • Loading branch information
chaos-zhu committed Nov 9, 2024
1 parent 1fdf8c6 commit 6dce6fe
Show file tree
Hide file tree
Showing 47 changed files with 1,431 additions and 372 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ server/app/db/*
plan.md
.env
.env.local
.env-encrypt-key
*clear.js
local-script
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## [3.0.0](https://github.com/chaos-zhu/easynode/releases) (2024-11-09)

* 新增跳板机功能,支持选择多台机器跳转
* 脚本库批量导出导入
* 本地socket断开自动重连,无需手动重新连接
* 支持脚本库模糊搜索功能
* 分组添加实例数量标识
* 优化登录逻辑
* 默认登录有效期更改为当天有效
* 修复一些小bug

## [2.3.0](https://github.com/chaos-zhu/easynode/releases) (2024-10-24)

* 重构本地数据库存储方式(性能提升一个level~)
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
docker run -d -p 8082:8082 --name=easynode --restart=always -v /root/easynode/db:/easynode/app/db chaoszhu/easynode
```
环境变量:
- `PLUS_KEY`: 激活PLUS功能的授权码
- `DEBUG`: 启动debug日志 0:关闭 1:开启, 默认关闭
- `ALLOWED_IPS`: 可以访问服务的IP白名单, 多个使用逗号分隔, 支持填写部分ip前缀, 例如: `-e ALLOWED_IPS=127.0.0.1,196.168`

Expand Down Expand Up @@ -119,3 +120,5 @@ webssh与监控服务都将以`该服务器作为中转`。中国大陆用户建
## License

[MIT](LICENSE). Copyright (c).

![访问数](https://profile-counter.glitch.me/easynode/count.svg)
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"license": "ISC",
"scripts": {
"dev": "concurrently \"yarn workspace web run dev\" \"yarn workspace server run local\"",
"clean": "rimraf web/node_modules server/node_modules client/node_modules node_modules"
"clean": "rimraf web/node_modules server/node_modules client/node_modules node_modules",
"encrypt": "node ./local-script/encrypt-file.js"
},
"bugs": {
"url": "https://github.com/chaos-zhu/easynode/issues"
Expand Down
5 changes: 4 additions & 1 deletion server/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@
DEBUG=1

# 访问IP限制
allowedIPs=['127.0.0.1']
allowedIPs=['127.0.0.1']

# 激活PLUS功能的授权码
PLUS_KEY=
1 change: 1 addition & 0 deletions server/app/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module.exports = {
notifyConfigDBPath: path.join(process.cwd(),'app/db/notify-config.db'),
onekeyDBPath: path.join(process.cwd(),'app/db/onekey.db'),
logDBPath: path.join(process.cwd(),'app/db/log.db'),
plusDBPath: path.join(process.cwd(),'app/db/plus.db'),
apiPrefix: '/api/v1',
logConfig: {
outDir: path.join(process.cwd(),'./app/logs'),
Expand Down
6 changes: 2 additions & 4 deletions server/app/controller/host.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ async function updateHost({ res, request }) {
hosts,
id,
host: newHost, name: newName, index, oldHost, expired, expiredNotify, group, consoleUrl, remark,
port, clientPort, username, authType, password, privateKey, credential, command, tempKey
port, clientPort, username, authType, password, privateKey, credential, command, tempKey, jumpHosts = []
}
} = request
let isBatch = Array.isArray(hosts)
Expand All @@ -73,7 +73,6 @@ async function updateHost({ res, request }) {
target[authType] = await AESEncryptAsync(clearSSHKey)
// console.log(`${ authType }__commonKey加密存储: `, target[authType])
}
delete target._id
delete target.monitorData
delete target.tempKey
Object.assign(oldRecord, target)
Expand All @@ -85,7 +84,7 @@ async function updateHost({ res, request }) {

let updateRecord = {
name: newName, host: newHost, index, expired, expiredNotify, group, consoleUrl, remark,
port, clientPort, username, authType, password, privateKey, credential, command
port, clientPort, username, authType, password, privateKey, credential, command, jumpHosts
}

let oldRecord = await hostListDB.findOneAsync({ _id: id })
Expand All @@ -108,7 +107,6 @@ async function removeHost({ res, request }) {
let { body: { ids } } = request
if (!Array.isArray(ids)) return res.fail({ msg: '参数错误' })
const numRemoved = await hostListDB.removeAsync({ _id: { $in: ids } }, { multi: true })
// console.log('numRemoved: ', numRemoved)
res.success({ data: `已移除,数量: ${ numRemoved }` })
}

Expand Down
1 change: 1 addition & 0 deletions server/app/controller/plus.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 21 additions & 1 deletion server/app/controller/scripts.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const path = require('path')
const localShellJson = require('../config/shell.json')
const { randomStr } = require('../utils/tools')
const { ScriptsDB } = require('../utils/db-class')
const decryptAndExecuteAsync = require('../utils/decrypt-file')
const scriptsDB = new ScriptsDB().getInstance()

let localShell = JSON.parse(JSON.stringify(localShellJson)).map((item) => {
Expand Down Expand Up @@ -44,10 +46,28 @@ const removeScript = async ({ res, request }) => {
res.success({ data: '移除成功' })
}

const batchRemoveScript = async ({ res, request }) => {
let { body: { ids } } = request
if (!Array.isArray(ids)) return res.fail({ msg: '参数错误' })
const numRemoved = await scriptsDB.removeAsync({ _id: { $in: ids } }, { multi: true })
res.success({ data: `批量移除成功,数量: ${ numRemoved }` })
}

const importScript = async ({ res, request }) => {
let { impScript } = (await decryptAndExecuteAsync(path.join(__dirname, 'plus.js'))) || {}
if (impScript) {
await impScript({ res, request })
} else {
return res.fail({ data: false, msg: 'Plus专属功能,无法导入脚本!' })
}
}

module.exports = {
addScript,
getScriptList,
getLocalScriptList,
updateScriptList,
removeScript
removeScript,
batchRemoveScript,
importScript
}
21 changes: 16 additions & 5 deletions server/app/controller/ssh.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
const path = require('path')
const { RSADecryptAsync, AESEncryptAsync, AESDecryptAsync } = require('../utils/encrypt')
const { HostListDB, CredentialsDB } = require('../utils/db-class')
const decryptAndExecuteAsync = require('../utils/decrypt-file')
const hostListDB = new HostListDB().getInstance()
const credentialsDB = new CredentialsDB().getInstance()

async function getSSHList({ res }) {
// console.log('get-host-list')
let data = await credentialsDB.findAsync({})
data = data?.map(item => {
const { name, authType, _id: id, date } = item
Expand Down Expand Up @@ -83,16 +84,26 @@ const getCommand = async ({ res, request }) => {
let hostInfo = await hostListDB.findAsync({})
let record = hostInfo?.find(item => item._id === hostId)
consola.info('查询登录后执行的指令:', hostId)
if (!record) return res.fail({ data: false, msg: 'host not found' }) // host不存在
if (!record) return res.fail({ data: false, msg: 'host not found' })
const { command } = record
if (!command) return res.success({ data: false }) // command不存在
res.success({ data: command }) // 存在
if (!command) return res.success({ data: false })
res.success({ data: command })
}

const decryptPrivateKey = async ({ res, request }) => {
let { dePrivateKey } = (await decryptAndExecuteAsync(path.join(__dirname, 'plus.js'))) || {}
if (dePrivateKey) {
await dePrivateKey({ res, request })
} else {
return res.fail({ data: false, msg: 'Plus专属功能,无法解密私钥!' })
}
}

module.exports = {
getSSHList,
addSSH,
updateSSH,
removeSSH,
getCommand
getCommand,
decryptPrivateKey
}
13 changes: 11 additions & 2 deletions server/app/controller/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ const QRCode = require('qrcode')
const { sendNoticeAsync } = require('../utils/notify')
const { RSADecryptAsync, AESEncryptAsync, SHA1Encrypt } = require('../utils/encrypt')
const { getNetIPInfo } = require('../utils/tools')
const { KeyDB, LogDB } = require('../utils/db-class')
const { KeyDB, LogDB, PlusDB } = require('../utils/db-class')
const keyDB = new KeyDB().getInstance()
const logDB = new LogDB().getInstance()
const plusDB = new PlusDB().getInstance()

const getpublicKey = async ({ res }) => {
let { publicKey: data } = await keyDB.findOneAsync({})
Expand Down Expand Up @@ -164,6 +165,13 @@ const disableMFA2 = async ({ res }) => {
res.success({ msg: 'success' })
}

const getPlusInfo = async ({ res }) => {
let data = await plusDB.findOneAsync({})
delete data?._id
delete data?.decryptKey
res.success({ data, msg: 'success' })
}

module.exports = {
login,
getpublicKey,
Expand All @@ -172,5 +180,6 @@ module.exports = {
getMFA2Status,
getMFA2Code,
enableMFA2,
disableMFA2
disableMFA2,
getPlusInfo
}
4 changes: 2 additions & 2 deletions server/app/main.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
const consola = require('consola')
global.consola = consola
const { httpServer } = require('./server')
const initDB = require('./db')
const scheduleJob = require('./schedule')
const getLicenseInfo = require('./utils/get-plus')

async function main() {
await initDB()
httpServer()
scheduleJob()
getLicenseInfo()
}

main()
24 changes: 14 additions & 10 deletions server/app/middlewares/log4.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,28 @@ const { outDir, recordLog } = require('../config').logConfig

log4js.configure({
appenders: {
// 控制台输出
out: {
console: {
type: 'stdout',
layout: {
type: 'colored'
type: 'pattern',
pattern: '%[%d{yyyy-MM-dd hh:mm:ss.SSS} [%p] -%] %m'
}
},
// 保存日志文件
cheese: {
type: 'file',
maxLogSize: 512*1024, // unit: bytes 1KB = 1024bytes
filename: `${ outDir }/receive.log`
maxLogSize: 10 * 1024 * 1024, // unit: bytes 1KB = 1024bytes
filename: `${ outDir }/receive.log`,
backups: 10,
compress: true,
keepFileExt: true
}
},
categories: {
default: {
appenders: [ 'out', 'cheese' ], // 配置
level: 'info' // 只输出info以上级别的日志
appenders: ['console', 'cheese'],
level: 'debug'
}
}
// pm2: true
})

const logger = log4js.getLogger()
Expand Down Expand Up @@ -55,4 +56,7 @@ const useLog = () => {
}
}

module.exports = useLog()
module.exports = useLog()

// 可以先测试一下日志是否正常工作
logger.info('日志系统启动')
26 changes: 23 additions & 3 deletions server/app/router/routes.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const { getSSHList, addSSH, updateSSH, removeSSH, getCommand } = require('../controller/ssh')
const { getSSHList, addSSH, updateSSH, removeSSH, getCommand, decryptPrivateKey } = require('../controller/ssh')
const { getHostList, addHost, updateHost, removeHost, importHost } = require('../controller/host')
const { login, getpublicKey, updatePwd, getEasynodeVersion, getMFA2Status, getMFA2Code, enableMFA2, disableMFA2 } = require('../controller/user')
const { login, getpublicKey, updatePwd, getEasynodeVersion, getMFA2Status, getMFA2Code, enableMFA2, disableMFA2, getPlusInfo } = require('../controller/user')
const { getNotifyConfig, updateNotifyConfig, getNotifyList, updateNotifyList } = require('../controller/notify')
const { getGroupList, addGroupList, updateGroupList, removeGroup } = require('../controller/group')
const { getScriptList, getLocalScriptList, addScript, updateScriptList, removeScript } = require('../controller/scripts')
const { getScriptList, getLocalScriptList, addScript, updateScriptList, removeScript, batchRemoveScript, importScript } = require('../controller/scripts')
const { getOnekeyRecord, removeOnekeyRecord } = require('../controller/onekey')
const { getLog } = require('../controller/log')

Expand Down Expand Up @@ -32,6 +32,11 @@ const ssh = [
method: 'get',
path: '/command',
controller: getCommand
},
{
method: 'post',
path: '/decrypt-private-key',
controller: decryptPrivateKey
}
]
const host = [
Expand Down Expand Up @@ -101,6 +106,11 @@ const user = [
method: 'post',
path: '/mfa2-disable',
controller: disableMFA2
},
{
method: 'get',
path: '/plus-info',
controller: getPlusInfo
}
]
const notify = [
Expand Down Expand Up @@ -170,10 +180,20 @@ const scripts = [
path: '/script/:id',
controller: removeScript
},
{
method: 'post',
path: '/batch-remove-script',
controller: batchRemoveScript
},
{
method: 'put',
path: '/script/:id',
controller: updateScriptList
},
{
method: 'post',
path: '/import-script',
controller: importScript
}
]

Expand Down
33 changes: 0 additions & 33 deletions server/app/schedule/expired-notify.js

This file was deleted.

Loading

0 comments on commit 6dce6fe

Please sign in to comment.