✨ test plus
This commit is contained in:
parent
1171d6e6cc
commit
1b3b2892d0
@ -2,4 +2,7 @@
|
||||
DEBUG=1
|
||||
|
||||
# 访问IP限制
|
||||
allowedIPs=['127.0.0.1']
|
||||
allowedIPs=['127.0.0.1']
|
||||
|
||||
# 激活PLUS功能的授权码
|
||||
PLUS_KEY=
|
||||
|
@ -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'),
|
||||
|
@ -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)
|
||||
@ -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)
|
||||
@ -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 })
|
||||
|
@ -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({})
|
||||
@ -164,6 +165,11 @@ const disableMFA2 = async ({ res }) => {
|
||||
res.success({ msg: 'success' })
|
||||
}
|
||||
|
||||
const getPlusInfo = async ({ res }) => {
|
||||
const data = await plusDB.findOneAsync({})
|
||||
res.success({ data, msg: 'success' })
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
login,
|
||||
getpublicKey,
|
||||
@ -172,5 +178,6 @@ module.exports = {
|
||||
getMFA2Status,
|
||||
getMFA2Code,
|
||||
enableMFA2,
|
||||
disableMFA2
|
||||
disableMFA2,
|
||||
getPlusInfo
|
||||
}
|
||||
|
44
server/app/encrypt-file.js
Normal file
44
server/app/encrypt-file.js
Normal file
@ -0,0 +1,44 @@
|
||||
const fs = require('fs-extra')
|
||||
const path = require('path')
|
||||
const CryptoJS = require('crypto-js')
|
||||
require('dotenv').config()
|
||||
console.log(process.env.PLUS_DECRYPT_KEY)
|
||||
|
||||
async function encryptPlusClearFiles(dir) {
|
||||
try {
|
||||
const files = await fs.readdir(dir)
|
||||
|
||||
for (const file of files) {
|
||||
const fullPath = path.join(dir, file)
|
||||
const stat = await fs.stat(fullPath)
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
await encryptPlusClearFiles(fullPath)
|
||||
} else if (file === 'plus-clear.js') {
|
||||
const content = await fs.readFile(fullPath, 'utf-8')
|
||||
|
||||
// global.PLUS_DECRYPT_KEY
|
||||
const encryptedContent = CryptoJS.AES.encrypt(content, process.env.PLUS_DECRYPT_KEY).toString()
|
||||
|
||||
const newPath = path.join(path.dirname(fullPath), 'plus.js')
|
||||
|
||||
await fs.writeFile(newPath, encryptedContent)
|
||||
|
||||
console.log(`已加密文件: ${fullPath}`)
|
||||
console.log(`生成加密文件: ${newPath}`)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加密过程出错:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const appDir = path.join(__dirname)
|
||||
console.log(appDir)
|
||||
// encryptPlusClearFiles(appDir)
|
||||
// .then(() => {
|
||||
// console.log('加密完成!')
|
||||
// })
|
||||
// .catch(error => {
|
||||
// console.error('程序执行出错:', error)
|
||||
// })
|
@ -1,8 +1,7 @@
|
||||
const consola = require('consola')
|
||||
global.consola = consola
|
||||
const { httpServer } = require('./server')
|
||||
const initDB = require('./db')
|
||||
const scheduleJob = require('./schedule')
|
||||
require(process.env.NODE_ENV === 'dev' ? './utils/plus-clear' : './utils/plus')()
|
||||
|
||||
async function main() {
|
||||
await initDB()
|
||||
|
@ -1,6 +1,6 @@
|
||||
const { getSSHList, addSSH, updateSSH, removeSSH, getCommand } = 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')
|
||||
@ -101,6 +101,11 @@ const user = [
|
||||
method: 'post',
|
||||
path: '/mfa2-disable',
|
||||
controller: disableMFA2
|
||||
},
|
||||
{
|
||||
method: 'get',
|
||||
path: '/plus-info',
|
||||
controller: getPlusInfo
|
||||
}
|
||||
]
|
||||
const notify = [
|
||||
|
@ -1,33 +0,0 @@
|
||||
const schedule = require('node-schedule')
|
||||
const { sendNoticeAsync } = require('../utils/notify')
|
||||
const { formatTimestamp } = require('../utils/tools')
|
||||
const { HostListDB } = require('../utils/db-class')
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
|
||||
const expiredNotifyJob = async () => {
|
||||
consola.info('=====开始检测服务器到期时间=====', new Date())
|
||||
const hostList = await hostListDB.findAsync({})
|
||||
for (const item of hostList) {
|
||||
if (!item.expiredNotify) continue
|
||||
const { host, name, expired, consoleUrl } = item
|
||||
const restDay = Number(((expired - Date.now()) / (1000 * 60 * 60 * 24)).toFixed(1))
|
||||
console.log(Date.now(), restDay)
|
||||
let title = '服务器到期提醒'
|
||||
let content = `别名: ${ name }\nIP: ${ host }\n到期时间:${ formatTimestamp(expired, 'week') }\n控制台: ${ consoleUrl || '未填写' }`
|
||||
if (0 <= restDay && restDay <= 1) {
|
||||
let temp = '有服务器将在一天后到期,请关注\n'
|
||||
sendNoticeAsync('host_expired', title, temp + content)
|
||||
} else if (3 <= restDay && restDay < 4) {
|
||||
let temp = '有服务器将在三天后到期,请关注\n'
|
||||
sendNoticeAsync('host_expired', title, temp + content)
|
||||
} else if (7 <= restDay && restDay < 8) {
|
||||
let temp = '有服务器将在七天后到期,请关注\n'
|
||||
sendNoticeAsync('host_expired', title, temp + content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = () => {
|
||||
// 每天中午12点执行一次。
|
||||
schedule.scheduleJob('0 0 12 1/1 * ?', expiredNotifyJob)
|
||||
}
|
@ -1,5 +1,32 @@
|
||||
const expiredNotify = require('./expired-notify')
|
||||
const schedule = require('node-schedule')
|
||||
const { sendNoticeAsync } = require('../utils/notify')
|
||||
const { formatTimestamp } = require('../utils/tools')
|
||||
const { HostListDB } = require('../utils/db-class')
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
|
||||
const expiredNotifyJob = async () => {
|
||||
consola.info('=====开始检测服务器到期时间=====', new Date())
|
||||
const hostList = await hostListDB.findAsync({})
|
||||
for (const item of hostList) {
|
||||
if (!item.expiredNotify) continue
|
||||
const { host, name, expired, consoleUrl } = item
|
||||
const restDay = Number(((expired - Date.now()) / (1000 * 60 * 60 * 24)).toFixed(1))
|
||||
console.log(Date.now(), restDay)
|
||||
let title = '服务器到期提醒'
|
||||
let content = `别名: ${ name }\nIP: ${ host }\n到期时间:${ formatTimestamp(expired, 'week') }\n控制台: ${ consoleUrl || '未填写' }`
|
||||
if (0 <= restDay && restDay <= 1) {
|
||||
let temp = '有服务器将在一天后到期,请关注\n'
|
||||
sendNoticeAsync('host_expired', title, temp + content)
|
||||
} else if (3 <= restDay && restDay < 4) {
|
||||
let temp = '有服务器将在三天后到期,请关注\n'
|
||||
sendNoticeAsync('host_expired', title, temp + content)
|
||||
} else if (7 <= restDay && restDay < 8) {
|
||||
let temp = '有服务器将在七天后到期,请关注\n'
|
||||
sendNoticeAsync('host_expired', title, temp + content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = () => {
|
||||
expiredNotify()
|
||||
schedule.scheduleJob('0 0 12 1/1 * ?', expiredNotifyJob)
|
||||
}
|
||||
|
0
server/app/socket/plus.js
Normal file
0
server/app/socket/plus.js
Normal file
@ -1,16 +1,15 @@
|
||||
const { Server } = require('socket.io')
|
||||
const { Client: SSHClient } = require('ssh2')
|
||||
const { verifyAuthSync } = require('../utils/verify-auth')
|
||||
const { AESDecryptAsync } = require('../utils/encrypt')
|
||||
const { sendNoticeAsync } = require('../utils/notify')
|
||||
const { isAllowedIp, ping } = require('../utils/tools')
|
||||
const { HostListDB, CredentialsDB } = require('../utils/db-class')
|
||||
const { HostListDB } = require('../utils/db-class')
|
||||
const { getConnectionOptions, connectByJumpHosts } = require(process.env.NODE_ENV === 'dev' ? './plus-clear' : './plus')
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
const credentialsDB = new CredentialsDB().getInstance()
|
||||
|
||||
function createInteractiveShell(socket, sshClient) {
|
||||
function createInteractiveShell(socket, targetSSHClient) {
|
||||
return new Promise((resolve) => {
|
||||
sshClient.shell({ term: 'xterm-color' }, (err, stream) => {
|
||||
targetSSHClient.shell({ term: 'xterm-color' }, (err, stream) => {
|
||||
resolve(stream)
|
||||
if (err) return socket.emit('output', err.toString())
|
||||
// 终端输出
|
||||
@ -20,70 +19,38 @@ function createInteractiveShell(socket, sshClient) {
|
||||
})
|
||||
.on('close', () => {
|
||||
consola.info('交互终端已关闭')
|
||||
sshClient.end()
|
||||
targetSSHClient.end()
|
||||
})
|
||||
socket.emit('connect_shell_success') // 已连接终端,web端可以执行指令了
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// function execShell(sshClient, command = '', callback) {
|
||||
// if (!command) return
|
||||
// let result = ''
|
||||
// sshClient.exec(`source ~/.bashrc && ${ command }`, (err, stream) => {
|
||||
// if (err) return callback(err.toString())
|
||||
// stream
|
||||
// .on('data', (data) => {
|
||||
// result += data.toString()
|
||||
// })
|
||||
// .stderr
|
||||
// .on('data', (data) => {
|
||||
// result += data.toString()
|
||||
// })
|
||||
// .on('close', () => {
|
||||
// consola.info('一次性指令执行完成:', command)
|
||||
// callback(result)
|
||||
// })
|
||||
// .on('error', (error) => {
|
||||
// console.log('Error:', error.toString())
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
|
||||
async function createTerminal(hostId, socket, sshClient) {
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
async function createTerminal(hostId, socket, targetSSHClient) {
|
||||
return new Promise(async (resolve) => {
|
||||
const hostList = await hostListDB.findAsync({})
|
||||
const targetHostInfo = hostList.find(item => item._id === hostId) || {}
|
||||
let { authType, host, port, username, name } = targetHostInfo
|
||||
if (!host) return socket.emit('create_fail', `查找hostId【${ hostId }】凭证信息失败`)
|
||||
let authInfo = { host, port, username }
|
||||
// 统一使用commonKey解密
|
||||
const targetHostInfo = await hostListDB.findOneAsync({ _id: hostId })
|
||||
if (!targetHostInfo) return socket.emit('create_fail', `查找hostId【${ hostId }】凭证信息失败`)
|
||||
let { authType, host, port, username, name, jumpHosts } = targetHostInfo
|
||||
try {
|
||||
// 解密放到try里面,防止报错【commonKey必须配对, 否则需要重新添加服务器密钥】
|
||||
if (authType === 'credential') {
|
||||
let credentialId = await AESDecryptAsync(targetHostInfo[authType])
|
||||
const sshRecord = await credentialsDB.findOneAsync({ _id: credentialId })
|
||||
authInfo.authType = sshRecord.authType
|
||||
authInfo[authInfo.authType] = await AESDecryptAsync(sshRecord[authInfo.authType])
|
||||
} else {
|
||||
authInfo[authType] = await AESDecryptAsync(targetHostInfo[authType])
|
||||
let { authInfo: targetConnectionOptions } = await getConnectionOptions(hostId)
|
||||
let jumpHostResult = await connectByJumpHosts(jumpHosts, targetConnectionOptions.host, targetConnectionOptions.port, socket)
|
||||
if (jumpHostResult) {
|
||||
targetConnectionOptions.sock = jumpHostResult.sock
|
||||
}
|
||||
consola.info('准备连接终端:', host)
|
||||
// targetHostInfo[targetHostInfo.authType] = await AESDecryptAsync(targetHostInfo[targetHostInfo.authType])
|
||||
|
||||
socket.emit('terminal_print_info', `准备连接目标终端: ${ name } - ${ host }`)
|
||||
socket.emit('terminal_print_info', `连接信息: ssh ${ username }@${ host } -p ${ port } -> ${ authType }`)
|
||||
|
||||
consola.info('准备连接目标终端:', host)
|
||||
consola.log('连接信息', { username, port, authType })
|
||||
sshClient
|
||||
targetSSHClient
|
||||
.on('ready', async() => {
|
||||
sendNoticeAsync('host_login', '终端登录', `别名: ${ name } \n IP:${ host } \n 端口:${ port } \n 状态: 登录成功`)
|
||||
socket.emit('terminal_print_info', `终端连接成功: ${ name } - ${ host }`)
|
||||
consola.success('终端连接成功:', host)
|
||||
socket.emit('connect_terminal_success', `终端连接成功:${ host }`)
|
||||
let stream = await createInteractiveShell(socket, sshClient)
|
||||
let stream = await createInteractiveShell(socket, targetSSHClient)
|
||||
resolve(stream)
|
||||
// execShell(sshClient, 'history', (data) => {
|
||||
// data = data.split('\n').filter(item => item)
|
||||
// console.log(data)
|
||||
// socket.emit('terminal_command_history', data)
|
||||
// })
|
||||
})
|
||||
.on('close', () => {
|
||||
consola.info('终端连接断开close: ', host)
|
||||
@ -96,7 +63,7 @@ async function createTerminal(hostId, socket, sshClient) {
|
||||
socket.emit('connect_fail', err.message)
|
||||
})
|
||||
.connect({
|
||||
...authInfo
|
||||
...targetConnectionOptions
|
||||
// debug: (info) => console.log(info)
|
||||
})
|
||||
|
||||
@ -123,7 +90,7 @@ module.exports = (httpServer) => {
|
||||
return
|
||||
}
|
||||
consola.success('terminal websocket 已连接')
|
||||
let sshClient = null
|
||||
let targetSSHClient = null
|
||||
socket.on('create', async ({ hostId, token }) => {
|
||||
const { code } = await verifyAuthSync(token, requestIP)
|
||||
if (code !== 1) {
|
||||
@ -131,16 +98,10 @@ module.exports = (httpServer) => {
|
||||
socket.disconnect()
|
||||
return
|
||||
}
|
||||
sshClient = new SSHClient()
|
||||
|
||||
// 尝试手动断开调试,再次连接后终端输出内容为4份相同的输出,导致异常
|
||||
// setTimeout(() => {
|
||||
// sshClient.end()
|
||||
// }, 3000)
|
||||
targetSSHClient = new SSHClient()
|
||||
let stream = null
|
||||
|
||||
function listenerInput(key) {
|
||||
if (sshClient._sock.writable === false) return consola.info('终端连接已关闭,禁止输入')
|
||||
if (targetSSHClient._sock.writable === false) return consola.info('终端连接已关闭,禁止输入')
|
||||
stream && stream.write(key)
|
||||
}
|
||||
function resizeShell({ rows, cols }) {
|
||||
@ -155,20 +116,20 @@ module.exports = (httpServer) => {
|
||||
consola.info('重连终端: ', hostId)
|
||||
socket.off('input', listenerInput) // 取消监听,重新注册监听,操作新的stream
|
||||
socket.off('resize', resizeShell)
|
||||
sshClient?.end()
|
||||
sshClient?.destroy()
|
||||
sshClient = null
|
||||
targetSSHClient?.end()
|
||||
targetSSHClient?.destroy()
|
||||
targetSSHClient = null
|
||||
stream = null
|
||||
setTimeout(async () => {
|
||||
// 初始化新的SSH客户端对象
|
||||
sshClient = new SSHClient()
|
||||
stream = await createTerminal(hostId, socket, sshClient)
|
||||
targetSSHClient = new SSHClient()
|
||||
stream = await createTerminal(hostId, socket, targetSSHClient)
|
||||
socket.emit('reconnect_terminal_success')
|
||||
socket.on('input', listenerInput)
|
||||
socket.on('resize', resizeShell)
|
||||
}, 3000)
|
||||
})
|
||||
stream = await createTerminal(hostId, socket, sshClient)
|
||||
stream = await createTerminal(hostId, socket, targetSSHClient)
|
||||
})
|
||||
|
||||
socket.on('get_ping',async (ip) => {
|
||||
|
@ -8,7 +8,8 @@ const {
|
||||
groupConfDBPath,
|
||||
scriptsDBPath,
|
||||
onekeyDBPath,
|
||||
logDBPath
|
||||
logDBPath,
|
||||
plusDBPath
|
||||
} = require('../config')
|
||||
|
||||
module.exports.KeyDB = class KeyDB {
|
||||
@ -117,4 +118,15 @@ module.exports.LogDB = class LogDB {
|
||||
getInstance() {
|
||||
return LogDB.instance
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.PlusDB = class PlusDB {
|
||||
constructor() {
|
||||
if (!PlusDB.instance) {
|
||||
PlusDB.instance = new Datastore({ filename: plusDBPath, autoload: true })
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
return PlusDB.instance
|
||||
}
|
||||
}
|
0
server/app/utils/plus.js
Normal file
0
server/app/utils/plus.js
Normal file
@ -89,6 +89,35 @@ const getNetIPInfo = async (searchIp = '') => {
|
||||
}
|
||||
}
|
||||
|
||||
const getLocalNetIP = async () => {
|
||||
try {
|
||||
let ipUrls = [
|
||||
'http://whois.pconline.com.cn/ipJson.jsp?json=true',
|
||||
'https://www.ip.cn/api/index?ip=&type=0',
|
||||
'https://freeipapi.com/api/json'
|
||||
]
|
||||
let result = await Promise.allSettled(ipUrls.map(url => axios.get(url)))
|
||||
let [pconline, ipCN, freeipapi] = result
|
||||
if (pconline.status === 'fulfilled') {
|
||||
let ip = pconline.value?.data?.ip
|
||||
if (ip) return ip
|
||||
}
|
||||
if (ipCN.status === 'fulfilled') {
|
||||
let ip = ipCN.value?.data?.ip
|
||||
consola.log('ipCN:', ip)
|
||||
if (ip) return ip
|
||||
}
|
||||
if (freeipapi.status === 'fulfilled') {
|
||||
let ip = pconline.value?.data?.ipAddress
|
||||
if (ip) return ip
|
||||
}
|
||||
return null
|
||||
} catch (error) {
|
||||
console.error('getIpInfo Error: ', error?.message || error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function isLocalIP(ip) {
|
||||
// Check if IPv4 or IPv6 address
|
||||
const isIPv4 = net.isIPv4(ip)
|
||||
@ -159,7 +188,7 @@ const isIP = (ip = '') => {
|
||||
return isIPv4.test(ip) || isIPv6.test(ip)
|
||||
}
|
||||
|
||||
const randomStr = (len) =>{
|
||||
const randomStr = (len) => {
|
||||
len = len || 16
|
||||
let str = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678',
|
||||
a = str.length,
|
||||
@ -178,7 +207,7 @@ const getUTCDate = (num = 8) => {
|
||||
}
|
||||
|
||||
const formatTimestamp = (timestamp = Date.now(), format = 'time') => {
|
||||
if (typeof(timestamp) !== 'number') return '--'
|
||||
if (typeof (timestamp) !== 'number') return '--'
|
||||
let date = new Date(timestamp)
|
||||
let padZero = (num) => String(num).padStart(2, '0')
|
||||
let year = date.getFullYear()
|
||||
@ -187,7 +216,7 @@ const formatTimestamp = (timestamp = Date.now(), format = 'time') => {
|
||||
let hours = padZero(date.getHours())
|
||||
let minute = padZero(date.getMinutes())
|
||||
let second = padZero(date.getSeconds())
|
||||
let weekday = ['周日', '周一', '周二', '周三', '周四', '周五', '周六' ]
|
||||
let weekday = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
|
||||
let week = weekday[date.getDay()]
|
||||
switch (format) {
|
||||
case 'date':
|
||||
@ -284,6 +313,7 @@ const ping = (ip, timeout = 5000) => {
|
||||
|
||||
module.exports = {
|
||||
getNetIPInfo,
|
||||
getLocalNetIP,
|
||||
throwError,
|
||||
isIP,
|
||||
randomStr,
|
||||
|
@ -1,2 +1,4 @@
|
||||
const consola = require('consola')
|
||||
global.consola = consola
|
||||
require('dotenv').config()
|
||||
require('./app/main.js')
|
||||
|
@ -1,58 +1,59 @@
|
||||
{
|
||||
"name": "server",
|
||||
"version": "1.0.0",
|
||||
"description": "easynode-server",
|
||||
"bin": "./bin/www",
|
||||
"scripts": {
|
||||
"local": "cross-env EXEC_ENV=local nodemon index.js",
|
||||
"prod": "cross-env EXEC_ENV=production nodemon index.js",
|
||||
"start": "node ./index.js",
|
||||
"lint": "eslint . --ext .js,.vue",
|
||||
"lint:fix": "eslint . --ext .js,.jsx,.cjs,.mjs --fix"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"nodemonConfig": {
|
||||
"ignore": [
|
||||
"*.json"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@koa/cors": "^5.0.0",
|
||||
"@seald-io/nedb": "^4.0.4",
|
||||
"axios": "^1.7.4",
|
||||
"consola": "^3.2.3",
|
||||
"cross-env": "^7.0.3",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"fs-extra": "^11.2.0",
|
||||
"global": "^4.4.0",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"koa": "^2.15.3",
|
||||
"koa-body": "^6.0.1",
|
||||
"koa-compose": "^4.1.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.9.1",
|
||||
"node-os-utils": "^1.3.7",
|
||||
"node-rsa": "^1.1.1",
|
||||
"node-schedule": "^2.1.1",
|
||||
"nodemailer": "^6.9.14",
|
||||
"qrcode": "^1.5.4",
|
||||
"socket.io": "^4.7.5",
|
||||
"socket.io-client": "^4.7.5",
|
||||
"speakeasy": "^2.0.0",
|
||||
"ssh2": "^1.15.0",
|
||||
"ssh2-sftp-client": "^10.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.56.0",
|
||||
"nodemon": "^3.1.4"
|
||||
}
|
||||
}
|
||||
{
|
||||
"name": "server",
|
||||
"version": "3.0.0",
|
||||
"description": "easynode-server",
|
||||
"bin": "./bin/www",
|
||||
"scripts": {
|
||||
"local": "cross-env EXEC_ENV=local nodemon index.js",
|
||||
"prod": "cross-env EXEC_ENV=production nodemon index.js",
|
||||
"start": "node ./index.js",
|
||||
"lint": "eslint . --ext .js,.vue",
|
||||
"lint:fix": "eslint . --ext .js,.jsx,.cjs,.mjs --fix",
|
||||
"encrypt": "node ./app/encrypt-file.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"nodemonConfig": {
|
||||
"ignore": [
|
||||
"*.json"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@koa/cors": "^5.0.0",
|
||||
"@seald-io/nedb": "^4.0.4",
|
||||
"axios": "^1.7.4",
|
||||
"consola": "^3.2.3",
|
||||
"cross-env": "^7.0.3",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"fs-extra": "^11.2.0",
|
||||
"global": "^4.4.0",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"koa": "^2.15.3",
|
||||
"koa-body": "^6.0.1",
|
||||
"koa-compose": "^4.1.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.9.1",
|
||||
"node-os-utils": "^1.3.7",
|
||||
"node-rsa": "^1.1.1",
|
||||
"node-schedule": "^2.1.1",
|
||||
"nodemailer": "^6.9.14",
|
||||
"qrcode": "^1.5.4",
|
||||
"socket.io": "^4.7.5",
|
||||
"socket.io-client": "^4.7.5",
|
||||
"speakeasy": "^2.0.0",
|
||||
"ssh2": "^1.15.0",
|
||||
"ssh2-sftp-client": "^10.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.56.0",
|
||||
"nodemon": "^3.1.4"
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user