diff --git a/.gitignore b/.gitignore
index 70e3ed3..4790d71 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,5 @@ server/app/logs/*
server/app/db/*
!server/app/db/README.md
plan.md
+.env
+.env.local
diff --git a/README.md b/README.md
index b1c4f04..72b8076 100644
--- a/README.md
+++ b/README.md
@@ -167,10 +167,10 @@ wget -qO- --no-check-certificate https://ghproxy.com/https://raw.githubuserconte
## 开发
-1. 拉取代码,准备nodejs环境>=16
-2. cd到项目根目录,yarn执行安装依赖
-3. cd web 启动前端 npm run dev
-4. cd server 启动服务端 npm run local
+1. 拉取代码,环境 `nodejs``>=20`
+2. cd到项目根目录,`yarn install` 执行安装依赖
+3. `yarn dev`启动项目
+4. web: `http://localhost:18090/`
## Q&A
diff --git a/client/package.json b/client/package.json
index 369ca5f..f6dd716 100644
--- a/client/package.json
+++ b/client/package.json
@@ -21,15 +21,15 @@
]
},
"dependencies": {
- "axios": "^0.21.4",
- "koa": "^2.13.1",
- "node-os-utils": "^1.3.6",
- "node-schedule": "^2.1.0",
- "socket.io": "^4.4.1"
+ "axios": "^1.7.2",
+ "koa": "^2.15.3",
+ "node-os-utils": "^1.3.7",
+ "node-schedule": "^2.1.1",
+ "socket.io": "^4.7.5"
},
"devDependencies": {
- "eslint": "^7.32.0",
- "nodemon": "^2.0.15",
- "pkg": "5.6"
+ "eslint": "^9.6.0",
+ "nodemon": "^3.1.4",
+ "pkg": "5.8"
}
}
diff --git a/package.json b/package.json
index 592f018..79f6b10 100644
--- a/package.json
+++ b/package.json
@@ -22,13 +22,15 @@
"author": "chaoszhu",
"license": "ISC",
"scripts": {
- "dev": "concurrently \"yarn workspace web run dev\" \"yarn workspace server run local\""
+ "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"
},
"bugs": {
"url": "https://github.com/chaos-zhu/easynode/issues"
},
"homepage": "https://github.com/chaos-zhu/easynode#readme",
- "dependencies": {
- "concurrently": "^8.2.2"
+ "devDependencies": {
+ "concurrently": "^8.2.2",
+ "rimraf": "^6.0.1"
}
}
diff --git a/server/.env.template b/server/.env.template
new file mode 100644
index 0000000..03c8c62
--- /dev/null
+++ b/server/.env.template
@@ -0,0 +1,2 @@
+# 启动debug日志 0:关闭 1:开启
+DEBUG=1
diff --git a/server/app/config/index.js b/server/app/config/index.js
index 77bafc4..f998840 100644
--- a/server/app/config/index.js
+++ b/server/app/config/index.js
@@ -1,5 +1,7 @@
const path = require('path')
+consola.info('debug日志:', process.env.DEBUG === '1' ? '开启' : '关闭')
+
module.exports = {
httpPort: 8082,
clientPort: 22022, // 暂不支持更改
@@ -15,6 +17,6 @@ module.exports = {
apiPrefix: '/api/v1',
logConfig: {
outDir: path.join(process.cwd(),'./app/logs'),
- recordLog: true // 是否记录日志
+ recordLog: process.env.DEBUG === '1' // 是否记录日志
}
}
diff --git a/server/app/controller/user.js b/server/app/controller/user.js
index 7ba12a5..469305b 100644
--- a/server/app/controller/user.js
+++ b/server/app/controller/user.js
@@ -51,7 +51,7 @@ const login = async ({ res, request }) => {
try {
// console.log('ciphertext', ciphertext)
let password = await RSADecryptSync(ciphertext)
- // console.log('Decrypt解密password:', password)
+ console.log('Decrypt解密password:', password)
let { pwd } = await readKey()
if(password === 'admin' && pwd === 'admin') {
const token = await beforeLoginHandler(clientIp, jwtExpires)
diff --git a/server/app/init.js b/server/app/init.js
index d560706..b598f5b 100644
--- a/server/app/init.js
+++ b/server/app/init.js
@@ -20,7 +20,7 @@ async function initRsa() {
let keyObj = await readKey()
if(keyObj.privateKey && keyObj.publicKey) return consola.info('公私钥已存在[重新生成会导致已保存的ssh密钥信息失效]')
let key = new NodeRSA({ b: 1024 })
- key.setOptions({ encryptionScheme: 'pkcs1' })
+ key.setOptions({ encryptionScheme: 'pkcs1', environment: "browser" })
let privateKey = key.exportKey('pkcs1-private-pem')
let publicKey = key.exportKey('pkcs8-public-pem')
keyObj.privateKey = await AESEncryptSync(privateKey) // 加密私钥
diff --git a/server/app/middlewares/body.js b/server/app/middlewares/body.js
index 382cccb..fe1bb9c 100644
--- a/server/app/middlewares/body.js
+++ b/server/app/middlewares/body.js
@@ -1,4 +1,4 @@
-const koaBody = require('koa-body')
+const { koaBody } = require('koa-body')
const { uploadDir } = require('../config')
module.exports = koaBody({
diff --git a/server/app/middlewares/response.js b/server/app/middlewares/response.js
index 50c9b60..67f2091 100644
--- a/server/app/middlewares/response.js
+++ b/server/app/middlewares/response.js
@@ -22,6 +22,7 @@ const responseHandler = async (ctx, next) => {
try {
await next() // 每个中间件都需等待next完成调用,不然会返回404给前端!!!
} catch (err) {
+ console.dir(err)
consola.error('中间件错误:', err)
if (err.status)
ctx.res.fail({ status: err.status, msg: err.message }) // 自己主动抛出的错误 throwError
diff --git a/server/app/socket/clients.js b/server/app/socket/clients.js
index ddd3e29..326dd3b 100644
--- a/server/app/socket/clients.js
+++ b/server/app/socket/clients.js
@@ -15,7 +15,7 @@ async function getClientsInfo(socketId) {
forceNew: true,
timeout: 5000,
reconnectionDelay: 3000,
- reconnectionAttempts: 100
+ reconnectionAttempts: 3
})
// 将与客户端连接的socket实例保存起来,web端断开时关闭这些连接
clientSockets[socketId].push(clientSocket)
diff --git a/server/app/socket/monitor.js b/server/app/socket/monitor.js
index 5a45a89..cddab63 100644
--- a/server/app/socket/monitor.js
+++ b/server/app/socket/monitor.js
@@ -18,7 +18,7 @@ async function getIpInfo() {
function ipSchedule() {
let rule1 = new schedule.RecurrenceRule()
- rule1.second = [0, 30]
+ rule1.second = [0]
schedule.scheduleJob(rule1, () => {
let { query, country, city } = ipInfo || {}
if(query && country && city) return
diff --git a/server/app/utils/encrypt.js b/server/app/utils/encrypt.js
index ac601cd..f2501e7 100644
--- a/server/app/utils/encrypt.js
+++ b/server/app/utils/encrypt.js
@@ -9,7 +9,7 @@ const RSADecryptSync = async (ciphertext) => {
let { privateKey } = await readKey()
privateKey = await AESDecryptSync(privateKey) // 先解密私钥
const rsakey = new NodeRSA(privateKey)
- rsakey.setOptions({ encryptionScheme: 'pkcs1' }) // Must Set It When Frontend Use jsencrypt
+ rsakey.setOptions({ encryptionScheme: 'pkcs1', environment: "browser" }) // Must Set It When Frontend Use jsencrypt
const plaintext = rsakey.decrypt(ciphertext, 'utf8')
return plaintext
}
diff --git a/server/app/utils/verify-auth.js b/server/app/utils/verify-auth.js
index 56da11e..6304400 100644
--- a/server/app/utils/verify-auth.js
+++ b/server/app/utils/verify-auth.js
@@ -12,9 +12,9 @@ const enumLoginCode = {
// 校验token与登录IP
const verifyAuthSync = async (token, clientIp) => {
consola.info('verifyAuthSync IP:', clientIp)
- token = await AESDecryptSync(token) // 先aes解密
- const { commonKey } = await readKey()
try {
+ token = await AESDecryptSync(token) // 先aes解密
+ const { commonKey } = await readKey()
const { exp } = jwt.verify(token, commonKey)
if (Date.now() > (exp * 1000)) return { code: -1, msg: 'token expires' } // 过期
return { code: enumLoginCode.SUCCESS, msg: 'success' } // 验证成功
diff --git a/server/bin/www b/server/bin/www
index a8611d0..be8f123 100755
--- a/server/bin/www
+++ b/server/bin/www
@@ -1,3 +1,3 @@
#!/usr/bin/env node
console.log('start time', new Date())
-require('../app/main.js')
+require('../index.js')
diff --git a/server/index.js b/server/index.js
index e455fee..110576d 100644
--- a/server/index.js
+++ b/server/index.js
@@ -1 +1,2 @@
+require('dotenv').config()
require('./app/main.js')
diff --git a/server/package.json b/server/package.json
index 0711d3f..abd2287 100644
--- a/server/package.json
+++ b/server/package.json
@@ -9,12 +9,12 @@
"assets": "./*"
},
"scripts": {
- "local": "cross-env EXEC_ENV=local nodemon ./app/main.js",
- "server": "cross-env EXEC_ENV=production nodemon ./app/main.js",
- "start": "node ./app/main.js",
- "pkgwin": "pkg . -t node16-win-x64",
- "pkglinux:x86": "pkg . -t node16-linux-x64",
- "pkglinux:arm": "pkg . -t node16-linux-arm64"
+ "local": "cross-env EXEC_ENV=local nodemon ./app/index.js",
+ "prod": "cross-env EXEC_ENV=production nodemon ./app/index.js",
+ "start": "node ./app/index.js",
+ "pkgwin": "pkg . -t node20-win-x64",
+ "pkglinux:x86": "pkg . -t node20-linux-x64",
+ "pkglinux:arm": "pkg . -t node20-linux-arm64"
},
"keywords": [],
"author": "",
@@ -27,34 +27,35 @@
"dependencies": {
"@koa/cors": "^5.0.0",
"@seald-io/nedb": "^4.0.4",
- "axios": "^0.21.4",
- "consola": "^2.15.3",
+ "axios": "^1.7.2",
+ "consola": "^3.2.3",
"cross-env": "^7.0.3",
"crypto-js": "^4.2.0",
+ "dotenv": "^16.4.5",
"global": "^4.4.0",
- "jsonwebtoken": "^9.0.0",
- "koa": "^2.13.1",
- "koa-body": "^4.2.0",
+ "jsonwebtoken": "^9.0.2",
+ "koa": "^2.15.3",
+ "koa-body": "^6.0.1",
"koa-compose": "^4.1.0",
- "koa-compress": "^5.1.0",
- "koa-jwt": "^4.0.3",
- "koa-router": "^10.0.0",
- "koa-sslify": "^5.0.0",
+ "koa-compress": "^5.1.1",
+ "koa-jwt": "^4.0.4",
+ "koa-router": "^12.0.1",
+ "koa-sslify": "^5.0.1",
"koa-static": "^5.0.0",
"koa2-connect-history-api-fallback": "^0.1.3",
- "log4js": "^6.4.4",
- "node-os-utils": "^1.3.6",
+ "log4js": "^6.9.1",
+ "node-os-utils": "^1.3.7",
"node-rsa": "^1.1.1",
- "node-schedule": "^2.1.0",
- "nodemailer": "^6.7.5",
- "socket.io": "^4.4.1",
- "socket.io-client": "^4.5.1",
- "ssh2": "^1.10.0",
- "ssh2-sftp-client": "^9.0.1"
+ "node-schedule": "^2.1.1",
+ "nodemailer": "^6.9.14",
+ "socket.io": "^4.7.5",
+ "socket.io-client": "^4.7.5",
+ "ssh2": "^1.15.0",
+ "ssh2-sftp-client": "^10.0.3"
},
"devDependencies": {
- "eslint": "^7.32.0",
- "nodemon": "^2.0.15",
- "pkg": "5.6"
+ "eslint": "^9.6.0",
+ "nodemon": "^3.1.4",
+ "pkg": "5.8"
}
}
diff --git a/web/package.json b/web/package.json
index 8c29bc6..459c066 100644
--- a/web/package.json
+++ b/web/package.json
@@ -10,30 +10,30 @@
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
},
"dependencies": {
- "@codemirror/lang-cpp": "^6.0.1",
- "@codemirror/lang-css": "^6.0.0",
- "@codemirror/lang-html": "^6.1.0",
- "@codemirror/lang-java": "^6.0.0",
- "@codemirror/lang-javascript": "^6.0.1",
- "@codemirror/lang-json": "^6.0.0",
- "@codemirror/lang-markdown": "^6.0.0",
- "@codemirror/lang-php": "^6.0.0",
- "@codemirror/lang-python": "^6.0.0",
- "@codemirror/lang-sql": "^6.0.0",
- "@codemirror/lang-xml": "^6.0.0",
- "@codemirror/language": "^6.2.0",
- "@codemirror/legacy-modes": "^6.1.0",
- "@codemirror/theme-one-dark": "^6.0.0",
- "axios": "^0.26.1",
+ "@codemirror/lang-cpp": "^6.0.2",
+ "@codemirror/lang-css": "^6.2.1",
+ "@codemirror/lang-html": "^6.4.9",
+ "@codemirror/lang-java": "^6.0.1",
+ "@codemirror/lang-javascript": "^6.2.2",
+ "@codemirror/lang-json": "^6.0.1",
+ "@codemirror/lang-markdown": "^6.2.5",
+ "@codemirror/lang-php": "^6.0.1",
+ "@codemirror/lang-python": "^6.1.6",
+ "@codemirror/lang-sql": "^6.7.0",
+ "@codemirror/lang-xml": "^6.1.0",
+ "@codemirror/language": "^6.10.2",
+ "@codemirror/legacy-modes": "^6.4.0",
+ "@codemirror/theme-one-dark": "^6.1.2",
+ "axios": "^1.7.2",
"codemirror": "^6.0.1",
- "crypto-js": "^4.1.1",
- "element-plus": "^2.1.7",
- "jsencrypt": "^3.0.0-rc.1",
- "pinia": "^2.0.16",
- "socket.io-client": "^4.4.1",
- "vue": "^3.2.31",
- "vue-codemirror": "^6.0.0",
- "vue-router": "^4.0.14",
+ "crypto-js": "^4.2.0",
+ "element-plus": "^2.7.6",
+ "jsencrypt": "^3.3.2",
+ "pinia": "^2.1.7",
+ "socket.io-client": "^4.7.5",
+ "vue": "^3.4.31",
+ "vue-codemirror": "^6.1.1",
+ "vue-router": "^4.4.0",
"xterm": "^4.19.0",
"xterm-addon-fit": "^0.5.0",
"xterm-addon-search": "^0.9.0",
@@ -41,16 +41,15 @@
"xterm-addon-web-links": "^0.6.0"
},
"devDependencies": {
- "@vitejs/plugin-vue": "^2.3.1",
- "@vitejs/plugin-vue-jsx": "^1.3.9",
- "eslint": "^8.5.0",
- "eslint-plugin-vue": "^8.2.0",
- "sass": "^1.49.11",
- "unplugin-auto-import": "^0.6.9",
- "unplugin-vue-components": "^0.18.5",
- "vite": "^2.9.1",
+ "@vitejs/plugin-vue": "^5.0.5",
+ "@vitejs/plugin-vue-jsx": "^4.0.0",
+ "eslint": "^9.6.0",
+ "eslint-plugin-vue": "^9.27.0",
+ "sass": "^1.77.7",
+ "unplugin-auto-import": "^0.17.6",
+ "unplugin-vue-components": "^0.27.2",
+ "vite": "^5.3.3",
"vite-plugin-compression": "^0.5.1",
- "vite-plugin-style-import": "^1.4.1",
- "vue-eslint-parser": "^9.0.2"
+ "vue-eslint-parser": "^9.4.3"
}
}
diff --git a/web/src/App.vue b/web/src/App.vue
index af50110..358d39d 100644
--- a/web/src/App.vue
+++ b/web/src/App.vue
@@ -4,17 +4,11 @@
-