⬆️ 升级依赖
This commit is contained in:
parent
8d52e34d6f
commit
644b9f1de2
2
.gitignore
vendored
2
.gitignore
vendored
@ -9,3 +9,5 @@ server/app/logs/*
|
||||
server/app/db/*
|
||||
!server/app/db/README.md
|
||||
plan.md
|
||||
.env
|
||||
.env.local
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
2
server/.env.template
Normal file
2
server/.env.template
Normal file
@ -0,0 +1,2 @@
|
||||
# 启动debug日志 0:关闭 1:开启
|
||||
DEBUG=1
|
@ -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' // 是否记录日志
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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) // 加密私钥
|
||||
|
@ -1,4 +1,4 @@
|
||||
const koaBody = require('koa-body')
|
||||
const { koaBody } = require('koa-body')
|
||||
const { uploadDir } = require('../config')
|
||||
|
||||
module.exports = koaBody({
|
||||
|
@ -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
|
||||
|
@ -15,7 +15,7 @@ async function getClientsInfo(socketId) {
|
||||
forceNew: true,
|
||||
timeout: 5000,
|
||||
reconnectionDelay: 3000,
|
||||
reconnectionAttempts: 100
|
||||
reconnectionAttempts: 3
|
||||
})
|
||||
// 将与客户端连接的socket实例保存起来,web端断开时关闭这些连接
|
||||
clientSockets[socketId].push(clientSocket)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -12,9 +12,9 @@ const enumLoginCode = {
|
||||
// 校验token与登录IP
|
||||
const verifyAuthSync = async (token, clientIp) => {
|
||||
consola.info('verifyAuthSync IP:', clientIp)
|
||||
try {
|
||||
token = await AESDecryptSync(token) // 先aes解密
|
||||
const { commonKey } = await readKey()
|
||||
try {
|
||||
const { exp } = jwt.verify(token, commonKey)
|
||||
if (Date.now() > (exp * 1000)) return { code: -1, msg: 'token expires' } // 过期
|
||||
return { code: enumLoginCode.SUCCESS, msg: 'success' } // 验证成功
|
||||
|
@ -1,3 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
console.log('start time', new Date())
|
||||
require('../app/main.js')
|
||||
require('../index.js')
|
||||
|
@ -1 +1,2 @@
|
||||
require('dotenv').config()
|
||||
require('./app/main.js')
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -4,17 +4,11 @@
|
||||
</el-config-provider>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
data() {
|
||||
return {
|
||||
locale: zhCn
|
||||
}
|
||||
}
|
||||
}
|
||||
const locale = ref(zhCn)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -1,5 +1,10 @@
|
||||
import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'
|
||||
import 'element-plus/es/components/message/style/css'
|
||||
import 'element-plus/es/components/message-box/style/css'
|
||||
import 'element-plus/es/components/notification/style/css'
|
||||
|
||||
// 如果使用 unplugin-element-plus 并且只使用组件 API,需要手动导入样式
|
||||
// https://element-plus.org/zh-CN/guide/quickstart.html#%E6%89%8B%E5%8A%A8%E5%AF%BC%E5%85%A5
|
||||
export default (app) => {
|
||||
app.config.globalProperties.$ELEMENT = { size: 'default' }
|
||||
app.config.globalProperties.$message = ElMessage
|
||||
|
@ -34,7 +34,7 @@ const useStore = defineStore({
|
||||
item.ping = res
|
||||
})
|
||||
})
|
||||
console.clear()
|
||||
// console.clear()
|
||||
// console.warn('Please tick \'Preserve Log\'')
|
||||
}, 1500)
|
||||
},
|
||||
|
@ -37,8 +37,8 @@
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
<el-form-item label="认证方式" prop="type">
|
||||
<el-radio v-model.trim="sshForm.type" label="privateKey">密钥</el-radio>
|
||||
<el-radio v-model.trim="sshForm.type" label="password">密码</el-radio>
|
||||
<el-radio v-model.trim="sshForm.type" value="privateKey">密钥</el-radio>
|
||||
<el-radio v-model.trim="sshForm.type" value="password">密码</el-radio>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="sshForm.type === 'password'" prop="password" label="密码">
|
||||
<el-input
|
||||
|
@ -9,7 +9,7 @@
|
||||
:show-close="false"
|
||||
center
|
||||
>
|
||||
<template #title>
|
||||
<template #header>
|
||||
<h2 v-if="notKey" style="color: #f56c6c;"> Error </h2>
|
||||
<h2 v-else style="color: #409eff;"> LOGIN </h2>
|
||||
</template>
|
||||
@ -53,8 +53,8 @@
|
||||
label="有效期"
|
||||
>
|
||||
<el-radio-group v-model="isSession" class="login-indate">
|
||||
<el-radio :label="true">一次性会话</el-radio>
|
||||
<el-radio :label="false">自定义(小时)</el-radio>
|
||||
<el-radio :value="true">一次性会话</el-radio>
|
||||
<el-radio :value="false">自定义(小时)</el-radio>
|
||||
<el-input-number
|
||||
v-model="loginForm.jwtExpires"
|
||||
:disabled="isSession"
|
||||
|
@ -353,7 +353,7 @@ export default {
|
||||
.then(res => {
|
||||
this.ping = res
|
||||
if(!import.meta.env.DEV) {
|
||||
console.clear()
|
||||
// console.clear()
|
||||
console.warn('Please tick \'Preserve Log\'')
|
||||
}
|
||||
})
|
||||
|
@ -6,7 +6,6 @@ import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||
import AutoImport from 'unplugin-auto-import/vite'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
||||
import styleImport from 'vite-plugin-style-import'
|
||||
import viteCompression from 'vite-plugin-compression'
|
||||
|
||||
const serviceURI = 'http://localhost:8082/'
|
||||
@ -55,19 +54,6 @@ export default defineConfig({
|
||||
ElementPlusResolver(),
|
||||
]
|
||||
}),
|
||||
styleImport({
|
||||
libs: [
|
||||
{
|
||||
libraryName: 'element-plus',
|
||||
esModule: true,
|
||||
resolveStyle: (name) => {
|
||||
if (name.includes('el-')) name = name.replace('el-', '')
|
||||
return `element-plus/theme-chalk/src/${ name }.scss` // 按需引入样式
|
||||
// return `element-plus/theme-chalk/${ name }.css`
|
||||
}
|
||||
},
|
||||
]
|
||||
}),
|
||||
viteCompression({
|
||||
algorithm: 'gzip',
|
||||
deleteOriginFile: false
|
||||
|
Loading…
x
Reference in New Issue
Block a user