mirror of
https://github.com/chaos-zhu/easynode.git
synced 2026-10-07 12:48:28 +08:00
feat: 转为esm规范&升级koa2 latest
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
const path = require('path')
|
||||
import path from 'node:path'
|
||||
|
||||
module.exports = {
|
||||
const config = {
|
||||
httpPort: process.env.HTTP_PORT ? parseInt(process.env.HTTP_PORT) : 8082,
|
||||
httpsPort: process.env.HTTPS_PORT ? parseInt(process.env.HTTPS_PORT) : 8092,
|
||||
enableHttps: process.env.ENABLE_HTTPS ? parseInt(process.env.ENABLE_HTTPS) : 0, // 0:关闭 1:自签证书 2:传入证书路径
|
||||
@@ -32,5 +32,39 @@ module.exports = {
|
||||
logConfig: {
|
||||
outDir: path.join(process.cwd(),'./app/db/logs'),
|
||||
DEBUG: process.env.DEBUG !== 'false'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const {
|
||||
httpPort,
|
||||
httpsPort,
|
||||
enableHttps,
|
||||
sslCertPath,
|
||||
sslKeyPath,
|
||||
uploadDir,
|
||||
staticDir,
|
||||
sftpCacheDir,
|
||||
credentialsDBPath,
|
||||
keyDBPath,
|
||||
hostListDBPath,
|
||||
groupConfDBPath,
|
||||
scriptsDBPath,
|
||||
scriptGroupDBPath,
|
||||
notifyDBPath,
|
||||
notifyConfigDBPath,
|
||||
onekeyDBPath,
|
||||
plusDBPath,
|
||||
aiConfigDBPath,
|
||||
chatHistoryDBPath,
|
||||
favoriteSftpDBPath,
|
||||
proxyDBPath,
|
||||
fileTransferDBPath,
|
||||
terminalConfigDBPath,
|
||||
serverListDBPath,
|
||||
sessionDBPath,
|
||||
terminalSessionDBPath,
|
||||
apiPrefix,
|
||||
logConfig
|
||||
} = config
|
||||
|
||||
export default config
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
const path = require('path')
|
||||
const decryptAndExecuteAsync = require('../utils/decrypt-file')
|
||||
const { AIConfigDB, ChatHistoryDB } = require('../utils/db-class')
|
||||
import path, { dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import decryptAndExecuteAsync from '../utils/decrypt-file.js'
|
||||
import { AIConfigDB, ChatHistoryDB } from '../utils/db-class.js'
|
||||
|
||||
const aiConfigDB = new AIConfigDB().getInstance()
|
||||
const chatHistoryDB = new ChatHistoryDB().getInstance()
|
||||
const currentDir = dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
async function getAIConfig({ res }) {
|
||||
try {
|
||||
@@ -18,7 +20,7 @@ async function getAIConfig({ res }) {
|
||||
}
|
||||
|
||||
async function getAIModels({ res, request }) {
|
||||
let { getAIModels } = (await decryptAndExecuteAsync(path.join(__dirname, 'plus.js'))) || {}
|
||||
let { getAIModels } = (await decryptAndExecuteAsync(path.join(currentDir, 'plus.js'))) || {}
|
||||
if (getAIModels) {
|
||||
await getAIModels({ res, request })
|
||||
} else {
|
||||
@@ -27,7 +29,7 @@ async function getAIModels({ res, request }) {
|
||||
}
|
||||
|
||||
async function saveAIConfig({ res, request }) {
|
||||
let { saveAIConfig } = (await decryptAndExecuteAsync(path.join(__dirname, 'plus.js'))) || {}
|
||||
let { saveAIConfig } = (await decryptAndExecuteAsync(path.join(currentDir, 'plus.js'))) || {}
|
||||
if (saveAIConfig) {
|
||||
await saveAIConfig({ res, request })
|
||||
} else {
|
||||
@@ -71,7 +73,7 @@ async function removeChatHistory({ res, request }) {
|
||||
res.success({ data: true })
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
getAIConfig,
|
||||
saveAIConfig,
|
||||
getAIModels,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { HostListDB, GroupDB } = require('../utils/db-class')
|
||||
import { HostListDB, GroupDB } from '../utils/db-class.js'
|
||||
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
const groupDB = new GroupDB().getInstance()
|
||||
@@ -45,7 +45,7 @@ const removeGroup = async ({ res, request }) => {
|
||||
res.success({ data: '移除成功' })
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
addGroupList,
|
||||
getGroupList,
|
||||
updateGroupList,
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
const path = require('path')
|
||||
const decryptAndExecuteAsync = require('../utils/decrypt-file')
|
||||
const { RSADecryptAsync, AESEncryptAsync, AESDecryptAsync } = require('../utils/encrypt')
|
||||
const { HostListDB } = require('../utils/db-class')
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
import path, { dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import decryptAndExecuteAsync from '../utils/decrypt-file.js'
|
||||
import { RSADecryptAsync, AESEncryptAsync, AESDecryptAsync } from '../utils/encrypt.js'
|
||||
import { HostListDB } from '../utils/db-class.js'
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
const currentDir = dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
async function getHostList({ res }) {
|
||||
let data = await hostListDB.findAsync({})
|
||||
@@ -58,7 +60,7 @@ async function updateHost({ res, request }) {
|
||||
}
|
||||
|
||||
async function batchUpdateHost({ res, request }) {
|
||||
let { updateHosts } = (await decryptAndExecuteAsync(path.join(__dirname, 'plus.js'))) || {}
|
||||
let { updateHosts } = (await decryptAndExecuteAsync(path.join(currentDir, 'plus.js'))) || {}
|
||||
if (updateHosts) {
|
||||
await updateHosts({ res, request })
|
||||
} else {
|
||||
@@ -121,7 +123,7 @@ async function updateLastConnectTime({ res, request }) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
getHostList,
|
||||
addHost,
|
||||
updateHost,
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
const crypto = require('crypto')
|
||||
const path = require('path')
|
||||
const { RSADecryptAsync } = require('../utils/encrypt')
|
||||
const decryptAndExecuteAsync = require('../utils/decrypt-file')
|
||||
import crypto from 'node:crypto'
|
||||
import path, { dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { RSADecryptAsync } from '../utils/encrypt.js'
|
||||
import decryptAndExecuteAsync from '../utils/decrypt-file.js'
|
||||
|
||||
const currentDir = dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
function encryptJsonForNative(payload, key) {
|
||||
if (!Buffer.isBuffer(key) || key.length !== 32) {
|
||||
@@ -46,13 +49,12 @@ async function buildNativeTopology(hostInfo = {}) {
|
||||
return { proxyType: '', proxy: null, jumpHosts: [] }
|
||||
}
|
||||
|
||||
let { getConnectionHelper } = (await decryptAndExecuteAsync(path.join(__dirname, 'plus.js'))) || {}
|
||||
let { getConnectionHelper } = (await decryptAndExecuteAsync(path.join(currentDir, 'plus.js'))) || {}
|
||||
if (getConnectionHelper) {
|
||||
const config = await getConnectionHelper(proxyType, hostInfo, normalizeNativeAuthPayload)
|
||||
return config
|
||||
} else {
|
||||
throw new Error('跳板机&代理服务为Plus功能')
|
||||
}
|
||||
throw new Error('跳板机&代理服务为Plus功能')
|
||||
}
|
||||
|
||||
async function getNativeSshConnection({ request, res }) {
|
||||
@@ -64,7 +66,7 @@ async function getNativeSshConnection({ request, res }) {
|
||||
|
||||
const tempKeyText = await RSADecryptAsync(encryptedKey)
|
||||
const tempKey = Buffer.from(tempKeyText, 'base64')
|
||||
const { getConnectionOptions } = require('../socket/terminal')
|
||||
const { getConnectionOptions } = await import('../socket/terminal.js')
|
||||
const { authInfo, name, hostInfo } = await getConnectionOptions(hostId)
|
||||
const payload = {
|
||||
...normalizeNativeAuthPayload(hostId, name, authInfo),
|
||||
@@ -79,6 +81,6 @@ async function getNativeSshConnection({ request, res }) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
getNativeSshConnection
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const { sendServerChan, sendEmail, sendTg, sendWebhook } = require('../utils/notify')
|
||||
const { NotifyConfigDB, NotifyDB } = require('../utils/db-class')
|
||||
import { sendServerChan, sendEmail, sendTg, sendWebhook } from '../utils/notify.js'
|
||||
import { NotifyConfigDB, NotifyDB } from '../utils/db-class.js'
|
||||
const notifyDB = new NotifyDB().getInstance()
|
||||
const notifyConfigDB = new NotifyConfigDB().getInstance()
|
||||
|
||||
@@ -46,7 +46,7 @@ async function updateNotifyList({ res, request }) {
|
||||
res.success()
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
getNotifyConfig,
|
||||
updateNotifyConfig,
|
||||
getNotifyList,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { OnekeyDB } = require('../utils/db-class')
|
||||
import { OnekeyDB } from '../utils/db-class.js'
|
||||
const onekeyDB = new OnekeyDB().getInstance()
|
||||
|
||||
async function getOnekeyRecord({ res }) {
|
||||
@@ -21,7 +21,7 @@ const removeOnekeyRecord = async ({ res, request }) => {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
getOnekeyRecord,
|
||||
removeOnekeyRecord
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
||||
const { ProxyDB, HostListDB } = require('../utils/db-class')
|
||||
import { ProxyDB, HostListDB } from '../utils/db-class.js'
|
||||
|
||||
const proxyDB = new ProxyDB().getInstance()
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
@@ -109,7 +109,7 @@ const removeProxy = async ({ res, request }) => {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
getProxyList,
|
||||
addProxy,
|
||||
updateProxy,
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
const path = require('path')
|
||||
const { ScriptGroupDB } = require('../utils/db-class')
|
||||
const decryptAndExecuteAsync = require('../utils/decrypt-file')
|
||||
import path, { dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { ScriptGroupDB } from '../utils/db-class.js'
|
||||
import decryptAndExecuteAsync from '../utils/decrypt-file.js'
|
||||
|
||||
const currentDir = dirname(fileURLToPath(import.meta.url))
|
||||
const scriptGroupDB = new ScriptGroupDB().getInstance()
|
||||
|
||||
async function getScriptGroupList({ res }) {
|
||||
@@ -11,7 +14,7 @@ async function getScriptGroupList({ res }) {
|
||||
}
|
||||
|
||||
const addScriptGroup = async ({ res, request }) => {
|
||||
let { addScriptGroup } = (await decryptAndExecuteAsync(path.join(__dirname, 'plus.js'))) || {}
|
||||
let { addScriptGroup } = (await decryptAndExecuteAsync(path.join(currentDir, 'plus.js'))) || {}
|
||||
if (addScriptGroup) {
|
||||
await addScriptGroup({ res, request })
|
||||
} else {
|
||||
@@ -20,7 +23,7 @@ const addScriptGroup = async ({ res, request }) => {
|
||||
}
|
||||
|
||||
const updateScriptGroup = async ({ res, request }) => {
|
||||
let { updateScriptGroup } = (await decryptAndExecuteAsync(path.join(__dirname, 'plus.js'))) || {}
|
||||
let { updateScriptGroup } = (await decryptAndExecuteAsync(path.join(currentDir, 'plus.js'))) || {}
|
||||
if (updateScriptGroup) {
|
||||
await updateScriptGroup({ res, request })
|
||||
} else {
|
||||
@@ -29,7 +32,7 @@ const updateScriptGroup = async ({ res, request }) => {
|
||||
}
|
||||
|
||||
const removeScriptGroup = async ({ res, request }) => {
|
||||
let { removeScriptGroup } = (await decryptAndExecuteAsync(path.join(__dirname, 'plus.js'))) || {}
|
||||
let { removeScriptGroup } = (await decryptAndExecuteAsync(path.join(currentDir, 'plus.js'))) || {}
|
||||
if (removeScriptGroup) {
|
||||
await removeScriptGroup({ res, request })
|
||||
} else {
|
||||
@@ -37,9 +40,9 @@ const removeScriptGroup = async ({ res, request }) => {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
addScriptGroup,
|
||||
getScriptGroupList,
|
||||
updateScriptGroup,
|
||||
removeScriptGroup
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
const path = require('path')
|
||||
const decryptAndExecuteAsync = require('../utils/decrypt-file')
|
||||
const { randomStr } = require('../utils/tools')
|
||||
const { ScriptsDB } = require('../utils/db-class')
|
||||
const localShellJson = require('../config/shell.json')
|
||||
import path, { dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import decryptAndExecuteAsync from '../utils/decrypt-file.js'
|
||||
import { randomStr } from '../utils/tools.js'
|
||||
import { ScriptsDB } from '../utils/db-class.js'
|
||||
import localShellJson from '../config/shell.json' with { type: 'json' }
|
||||
const scriptsDB = new ScriptsDB().getInstance()
|
||||
const currentDir = dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
let localShell = JSON.parse(JSON.stringify(localShellJson)).map((item) => {
|
||||
return { ...item, id: randomStr(10), index: '--', description: item.description, group: 'builtin' }
|
||||
@@ -56,7 +58,7 @@ const batchRemoveScript = async ({ res, request }) => {
|
||||
}
|
||||
|
||||
const importScript = async ({ res, request }) => {
|
||||
let { impScript } = (await decryptAndExecuteAsync(path.join(__dirname, 'plus.js'))) || {}
|
||||
let { impScript } = (await decryptAndExecuteAsync(path.join(currentDir, 'plus.js'))) || {}
|
||||
if (impScript) {
|
||||
await impScript({ res, request })
|
||||
} else {
|
||||
@@ -64,7 +66,7 @@ const importScript = async ({ res, request }) => {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
addScript,
|
||||
getScriptList,
|
||||
getLocalScriptList,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { ServerListDB } = require('../utils/db-class')
|
||||
import { ServerListDB } from '../utils/db-class.js'
|
||||
const serverListDB = new ServerListDB().getInstance()
|
||||
|
||||
// 获取服务器列表配置
|
||||
@@ -63,7 +63,7 @@ async function saveServerListConfig({ res, request }) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
getServerListConfig,
|
||||
saveServerListConfig
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { KeyDB, SessionDB } = require('../utils/db-class')
|
||||
import { KeyDB, SessionDB } from '../utils/db-class.js'
|
||||
const keyDB = new KeyDB().getInstance()
|
||||
const sessionDB = new SessionDB().getInstance()
|
||||
|
||||
@@ -50,7 +50,7 @@ const revokeLoginSid = async (ctx) => {
|
||||
res.success({ msg: '注销凭证成功' })
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
getLog,
|
||||
saveIpWhiteList,
|
||||
removeSomeLoginRecords,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { HostListDB, CredentialsDB, FavoriteSftpDB } = require('../utils/db-class')
|
||||
import { HostListDB, CredentialsDB, FavoriteSftpDB } from '../utils/db-class.js'
|
||||
|
||||
const favoriteSftpDB = new FavoriteSftpDB().getInstance()
|
||||
|
||||
@@ -19,6 +19,6 @@ async function getSftpFavorites({ params, request, res }) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
getSftpFavorites
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
const path = require('path')
|
||||
const crypto = require('crypto')
|
||||
const { RSADecryptAsync, AESEncryptAsync, AESDecryptAsync } = require('../utils/encrypt')
|
||||
const { HostListDB, CredentialsDB } = require('../utils/db-class')
|
||||
const decryptAndExecuteAsync = require('../utils/decrypt-file')
|
||||
import path, { dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import crypto from 'node:crypto'
|
||||
import { RSADecryptAsync, AESEncryptAsync, AESDecryptAsync } from '../utils/encrypt.js'
|
||||
import { HostListDB, CredentialsDB } from '../utils/db-class.js'
|
||||
import decryptAndExecuteAsync from '../utils/decrypt-file.js'
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
const credentialsDB = new CredentialsDB().getInstance()
|
||||
const credentialsDB = new CredentialsDB().getInstance()
|
||||
const currentDir = dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
async function getSSHList({ res }) {
|
||||
let data = await credentialsDB.findAsync({})
|
||||
@@ -118,7 +120,7 @@ const decryptPrivateKey = async ({ res, request }) => {
|
||||
}
|
||||
|
||||
const getRdpToken = async ({ res, request }) => {
|
||||
let { genRdpToken } = (await decryptAndExecuteAsync(path.join(__dirname, 'plus.js'))) || {}
|
||||
let { genRdpToken } = (await decryptAndExecuteAsync(path.join(currentDir, 'plus.js'))) || {}
|
||||
if (genRdpToken) {
|
||||
await genRdpToken({ res, request })
|
||||
} else {
|
||||
@@ -126,7 +128,7 @@ const getRdpToken = async ({ res, request }) => {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
getSSHList,
|
||||
addSSH,
|
||||
updateSSH,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { TerminalConfigDB } = require('../utils/db-class')
|
||||
import { TerminalConfigDB } from '../utils/db-class.js'
|
||||
|
||||
// 终端默认配置
|
||||
const DEFAULT_TERMINAL_CONFIG = {
|
||||
@@ -74,7 +74,7 @@ async function saveTerminalConfig({ res, request }) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
getTerminalConfig,
|
||||
saveTerminalConfig
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
const { sessionManager, getDefaultSessionConfig } = require('../utils/terminal-session')
|
||||
const { KeyDB, HostListDB, TerminalSessionDB } = require('../utils/db-class')
|
||||
import { sessionManager, getDefaultSessionConfig } from '../utils/terminal-session.js'
|
||||
import { KeyDB, HostListDB, TerminalSessionDB } from '../utils/db-class.js'
|
||||
|
||||
const keyDB = new KeyDB().getInstance()
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
@@ -101,7 +101,7 @@ async function updateTerminalSessionConfig({ request, res }) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
getSuspendedSessions,
|
||||
getTerminalSessionConfig,
|
||||
updateTerminalSessionConfig
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
const jwt = require('jsonwebtoken')
|
||||
const axios = require('axios')
|
||||
const speakeasy = require('speakeasy')
|
||||
const QRCode = require('qrcode')
|
||||
const uap = require('ua-parser-js')
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
const version = require('../../package.json').version
|
||||
const getLicenseInfo = require('../utils/get-plus')
|
||||
const { sendNoticeAsync } = require('../utils/notify')
|
||||
const { RSADecryptAsync, AESEncryptAsync, SHA1Encrypt, SHA256Encrypt } = require('../utils/encrypt')
|
||||
const { getNetIPInfo, requestWithFailover, timingSafeEqual } = require('../utils/tools')
|
||||
const { KeyDB, PlusDB, SessionDB } = require('../utils/db-class')
|
||||
const { RuntimeState } = require('../utils/runtime-state')
|
||||
import jwt from 'jsonwebtoken'
|
||||
import axios from 'axios'
|
||||
import speakeasy from 'speakeasy'
|
||||
import QRCode from 'qrcode'
|
||||
import { UAParser as uap } from 'ua-parser-js'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import PackageJsonModule from '../../package.json' with { type: 'json' }
|
||||
const version = PackageJsonModule.version
|
||||
import getLicenseInfo from '../utils/get-plus.js'
|
||||
import { sendNoticeAsync } from '../utils/notify.js'
|
||||
import { RSADecryptAsync, AESEncryptAsync, SHA1Encrypt, SHA256Encrypt } from '../utils/encrypt.js'
|
||||
import { getNetIPInfo, requestWithFailover, timingSafeEqual } from '../utils/tools.js'
|
||||
import { KeyDB, PlusDB, SessionDB } from '../utils/db-class.js'
|
||||
import { RuntimeState } from '../utils/runtime-state.js'
|
||||
|
||||
const keyDB = new KeyDB().getInstance()
|
||||
const sessionDB = new SessionDB().getInstance()
|
||||
@@ -320,7 +321,7 @@ const releasePlusDevice = async ({ res, request }) => {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
login,
|
||||
getpublicKey,
|
||||
updatePwd,
|
||||
|
||||
+5
-5
@@ -1,7 +1,7 @@
|
||||
const NodeRSA = require('node-rsa')
|
||||
const { randomStr } = require('./utils/tools')
|
||||
const { AESEncryptAsync, SHA1Encrypt } = require('./utils/encrypt')
|
||||
const { KeyDB, GroupDB, NotifyDB, NotifyConfigDB, ScriptGroupDB } = require('./utils/db-class')
|
||||
import NodeRSA from 'node-rsa'
|
||||
import { randomStr } from './utils/tools.js'
|
||||
import { AESEncryptAsync, SHA1Encrypt } from './utils/encrypt.js'
|
||||
import { KeyDB, GroupDB, NotifyDB, NotifyConfigDB, ScriptGroupDB } from './utils/db-class.js'
|
||||
|
||||
async function initKeyDB() {
|
||||
const keyDB = new KeyDB().getInstance()
|
||||
@@ -153,7 +153,7 @@ async function initScriptGroupDB() {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
module.exports = async () => {
|
||||
export default async () => {
|
||||
await initKeyDB()
|
||||
await initNotifyDB()
|
||||
await initGroupDB()
|
||||
|
||||
+5
-3
@@ -1,5 +1,7 @@
|
||||
const log4js = require('log4js')
|
||||
const { outDir } = require('./config').logConfig
|
||||
import log4js from 'log4js'
|
||||
import { logConfig } from './config/index.js'
|
||||
|
||||
const { outDir } = logConfig
|
||||
log4js.configure({
|
||||
appenders: {
|
||||
console: {
|
||||
@@ -26,4 +28,4 @@ log4js.configure({
|
||||
}
|
||||
})
|
||||
const logger = log4js.getLogger()
|
||||
global.logger = logger
|
||||
global.logger = logger
|
||||
|
||||
+5
-5
@@ -1,8 +1,8 @@
|
||||
require('./logs')
|
||||
const { createServer } = require('./server')
|
||||
const initDB = require('./db')
|
||||
const scheduleJob = require('./schedule')
|
||||
const { startActivation } = require('./utils/get-plus')
|
||||
import './logs.js'
|
||||
import { createServer } from './server.js'
|
||||
import initDB from './db.js'
|
||||
import scheduleJob from './schedule/index.js'
|
||||
import { startActivation } from './utils/get-plus.js'
|
||||
|
||||
async function main() {
|
||||
await initDB()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const { apiPrefix } = require('../config')
|
||||
const { verifyAuthSync, enumLoginCode } = require('../utils/verify-auth')
|
||||
import { apiPrefix } from '../config/index.js'
|
||||
import { verifyAuthSync, enumLoginCode } from '../utils/verify-auth.js'
|
||||
|
||||
let whitePath = [
|
||||
'/login',
|
||||
@@ -48,4 +48,4 @@ const useAuth = async (ctx, next) => {
|
||||
return res.fail({ msg: failMsg || '身份验证失败(未知错误!)', status: 403 })
|
||||
}
|
||||
|
||||
module.exports = useAuth
|
||||
export default useAuth
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
const { koaBody } = require('koa-body')
|
||||
import koaBodyModule from 'koa-body'
|
||||
|
||||
module.exports = koaBody({
|
||||
const { koaBody } = koaBodyModule
|
||||
|
||||
export default koaBody({
|
||||
multipart: false
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// 响应压缩模块,自适应头部压缩方式
|
||||
const compress = require('koa-compress')
|
||||
import compress from 'koa-compress'
|
||||
|
||||
const options = { threshold: 2048 }
|
||||
|
||||
module.exports = compress(options)
|
||||
export default compress(options)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const cors = require('@koa/cors')
|
||||
import cors from '@koa/cors'
|
||||
|
||||
// 跨域处理
|
||||
const useCors = cors({
|
||||
@@ -9,4 +9,4 @@ const useCors = cors({
|
||||
allowMethods: [ 'GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH' ]
|
||||
})
|
||||
|
||||
module.exports = useCors
|
||||
export default useCors
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
const { historyApiFallback } = require('koa2-connect-history-api-fallback')
|
||||
import koa2ConnectHistoryApiFallbackModule from 'koa2-connect-history-api-fallback'
|
||||
const { historyApiFallback } = koa2ConnectHistoryApiFallbackModule
|
||||
|
||||
module.exports = historyApiFallback({ whiteList: ['/api'] })
|
||||
export default historyApiFallback({ whiteList: ['/api'] })
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
const ipFilter = require('./ipFilter') // IP过滤
|
||||
const responseHandler = require('./response') // 统一返回格式, 错误捕获
|
||||
const useAuth = require('./auth') // 鉴权
|
||||
// const useCors = require('./cors') // 处理跨域[暂时禁止]
|
||||
const useLog = require('./useLog') // 记录日志,需要等待路由处理完成,所以得放路由前
|
||||
const useKoaBody = require('./body') // 处理body参数 【请求需先走该中间件】
|
||||
const { useRoutes, useAllowedMethods } = require('./router') // 路由管理
|
||||
const useStatic = require('./static') // 静态目录
|
||||
const useSftpCacheStatic = require('./sftp-cache') // SFTP缓存文件服务
|
||||
const compress = require('./compress') // br/gzip压缩
|
||||
const history = require('./history') // vue-router的history模式
|
||||
import ipFilter from './ipFilter.js' // IP过滤
|
||||
import responseHandler from './response.js' // 统一返回格式, 错误捕获
|
||||
import useAuth from './auth.js' // 鉴权
|
||||
// import useCors from './cors.js' // 处理跨域[暂时禁止]
|
||||
import useLog from './useLog.js' // 记录日志,需要等待路由处理完成,所以得放路由前
|
||||
import useKoaBody from './body.js' // 处理body参数 【请求需先走该中间件】
|
||||
import { useRoutes, useAllowedMethods } from './router.js' // 路由管理
|
||||
import useStatic from './static.js' // 静态目录
|
||||
import useSftpCacheStatic from './sftp-cache.js' // SFTP缓存文件服务
|
||||
import compress from './compress.js' // br/gzip压缩
|
||||
import history from './history.js' // vue-router的history模式
|
||||
|
||||
module.exports = [
|
||||
export default [
|
||||
ipFilter,
|
||||
useSftpCacheStatic, // SFTP缓存文件服务
|
||||
compress,
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
// 白名单IP
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const { isAllowedIp, getClientIP } = require('../utils/tools')
|
||||
import fs from 'node:fs'
|
||||
import path, { dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { isAllowedIp, getClientIP } from '../utils/tools.js'
|
||||
|
||||
const htmlPath = path.join(__dirname, '../template/ipForbidden.html')
|
||||
const currentDir = dirname(fileURLToPath(import.meta.url))
|
||||
const htmlPath = path.join(currentDir, '../template/ipForbidden.html')
|
||||
const ipForbiddenHtml = fs.readFileSync(htmlPath, 'utf8')
|
||||
|
||||
const ipFilter = async (ctx, next) => {
|
||||
@@ -13,4 +15,4 @@ const ipFilter = async (ctx, next) => {
|
||||
ctx.body = ipForbiddenHtml
|
||||
}
|
||||
|
||||
module.exports = ipFilter
|
||||
export default ipFilter
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const { createProxyMiddleware } = require('http-proxy-middleware')
|
||||
import httpProxyMiddlewareModule from 'http-proxy-middleware'
|
||||
const { createProxyMiddleware } = httpProxyMiddlewareModule
|
||||
|
||||
/**
|
||||
* RDP代理中间件
|
||||
@@ -25,4 +26,4 @@ const createRdpProxyMiddleware = () => {
|
||||
return wsProxy
|
||||
}
|
||||
|
||||
module.exports = createRdpProxyMiddleware
|
||||
export default createRdpProxyMiddleware
|
||||
@@ -31,4 +31,4 @@ const responseHandler = async (ctx, next) => {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = responseHandler
|
||||
export default responseHandler
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const router = require('../router')
|
||||
import router from '../router/index.js'
|
||||
|
||||
// 路由中间件
|
||||
const useRoutes = router.routes()
|
||||
@@ -7,7 +7,7 @@ const useRoutes = router.routes()
|
||||
// 使用该中间件后请求方法错误会提示405 Method Not Allowed【get list ✔200 post /list ❌405】
|
||||
const useAllowedMethods = router.allowedMethods()
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
useRoutes,
|
||||
useAllowedMethods
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const koaStatic = require('koa-static')
|
||||
const path = require('path')
|
||||
const { sftpCacheDir } = require('../config')
|
||||
import koaStatic from 'koa-static'
|
||||
import path from 'node:path'
|
||||
import { sftpCacheDir } from '../config/index.js'
|
||||
|
||||
const useSftpCacheStatic = async (ctx, next) => {
|
||||
// 只处理 /sftp-cache 路径
|
||||
@@ -29,4 +29,4 @@ const useSftpCacheStatic = async (ctx, next) => {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = useSftpCacheStatic
|
||||
export default useSftpCacheStatic
|
||||
@@ -1,5 +1,5 @@
|
||||
const koaStatic = require('koa-static')
|
||||
const { staticDir } = require('../config')
|
||||
import koaStatic from 'koa-static'
|
||||
import { staticDir } from '../config/index.js'
|
||||
|
||||
const useStatic = koaStatic(staticDir, {
|
||||
maxage: 1000 * 60 * 60 * 24 * 30,
|
||||
@@ -11,4 +11,4 @@ const useStatic = koaStatic(staticDir, {
|
||||
}
|
||||
})
|
||||
|
||||
module.exports = useStatic
|
||||
export default useStatic
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
const { DEBUG } = require('../config').logConfig
|
||||
const { getClientIP } = require('../utils/tools')
|
||||
import { logConfig } from '../config/index.js'
|
||||
import { getClientIP } from '../utils/tools.js'
|
||||
|
||||
const { DEBUG } = logConfig
|
||||
|
||||
// ------------------ 脱敏 ------------------
|
||||
// 可能包含敏感信息的 header key(小写比较)
|
||||
@@ -109,7 +111,7 @@ const useLog = () => {
|
||||
origin,
|
||||
query,
|
||||
body,
|
||||
headers,
|
||||
headers
|
||||
} = ctx.request
|
||||
|
||||
const ip = getClientIP(ctx.socket.remoteAddress, ctx.get('x-forwarded-for'))
|
||||
@@ -169,4 +171,4 @@ const useLog = () => {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = useLog()
|
||||
export default useLog()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const http = require('http')
|
||||
const GuacamoleLite = require('guacamole-lite')
|
||||
import http from 'node:http'
|
||||
import GuacamoleLite from 'guacamole-lite'
|
||||
|
||||
const RDP_PORT = process.env.RDP_PORT || 8083 // 使用独立端口
|
||||
const GUACD_HOST = process.env.GUACD_HOST || 'guacd'
|
||||
@@ -45,4 +45,4 @@ const startRdpServer = () => {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { startRdpServer }
|
||||
export { startRdpServer }
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const { apiPrefix } = require('../config')
|
||||
const koaRouter = require('koa-router')
|
||||
import { apiPrefix } from '../config/index.js'
|
||||
import koaRouter from 'koa-router'
|
||||
const router = new koaRouter({ prefix: apiPrefix })
|
||||
|
||||
const routeList = require('./routes')
|
||||
import routeList from './routes.js'
|
||||
|
||||
// 统一注册路由
|
||||
routeList.forEach(item => {
|
||||
@@ -10,4 +10,4 @@ routeList.forEach(item => {
|
||||
router[method](path, controller)
|
||||
})
|
||||
|
||||
module.exports = router
|
||||
export default router
|
||||
|
||||
+17
-17
@@ -1,19 +1,19 @@
|
||||
const { getSSHList, addSSH, updateSSH, removeSSH, getCommand, decryptPrivateKey, getRdpToken } = require('../controller/ssh')
|
||||
const { getSftpFavorites } = require('../controller/sftp')
|
||||
const { getHostList, addHost, updateHost, batchUpdateHost, removeHost, importHost, updateLastConnectTime } = require('../controller/host')
|
||||
const { login, getpublicKey, updatePwd, getEasynodeVersion, getMFA2Status, getMFA2Code, enableMFA2, disableMFA2, getPlusInfo, getPlusDiscount, getPlusConf, updatePlusKey, getPlusDevices, releasePlusDevice } = 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, batchRemoveScript, importScript } = require('../controller/scripts')
|
||||
const { getScriptGroupList, addScriptGroup, removeScriptGroup, updateScriptGroup } = require('../controller/script-group')
|
||||
const { getOnekeyRecord, removeOnekeyRecord } = require('../controller/onekey')
|
||||
const { getLog, saveIpWhiteList, removeSomeLoginRecords, revokeLoginSid } = require('../controller/sessionLog')
|
||||
const { getAIConfig, saveAIConfig, getAIModels, getChatHistory, saveChatHistory, removeChatHistory } = require('../controller/chat')
|
||||
const { getProxyList, addProxy, updateProxy, removeProxy } = require('../controller/proxy')
|
||||
const { getTerminalConfig, saveTerminalConfig } = require('../controller/terminal-config')
|
||||
const { getServerListConfig, saveServerListConfig } = require('../controller/server-list-config')
|
||||
const { getSuspendedSessions, getTerminalSessionConfig, updateTerminalSessionConfig } = require('../controller/terminal')
|
||||
const { getNativeSshConnection } = require('../controller/native')
|
||||
import { getSSHList, addSSH, updateSSH, removeSSH, getCommand, decryptPrivateKey, getRdpToken } from '../controller/ssh.js'
|
||||
import { getSftpFavorites } from '../controller/sftp.js'
|
||||
import { getHostList, addHost, updateHost, batchUpdateHost, removeHost, importHost, updateLastConnectTime } from '../controller/host.js'
|
||||
import { login, getpublicKey, updatePwd, getEasynodeVersion, getMFA2Status, getMFA2Code, enableMFA2, disableMFA2, getPlusInfo, getPlusDiscount, getPlusConf, updatePlusKey, getPlusDevices, releasePlusDevice } from '../controller/user.js'
|
||||
import { getNotifyConfig, updateNotifyConfig, getNotifyList, updateNotifyList } from '../controller/notify.js'
|
||||
import { getGroupList, addGroupList, updateGroupList, removeGroup } from '../controller/group.js'
|
||||
import { getScriptList, getLocalScriptList, addScript, updateScriptList, removeScript, batchRemoveScript, importScript } from '../controller/scripts.js'
|
||||
import { getScriptGroupList, addScriptGroup, removeScriptGroup, updateScriptGroup } from '../controller/script-group.js'
|
||||
import { getOnekeyRecord, removeOnekeyRecord } from '../controller/onekey.js'
|
||||
import { getLog, saveIpWhiteList, removeSomeLoginRecords, revokeLoginSid } from '../controller/sessionLog.js'
|
||||
import { getAIConfig, saveAIConfig, getAIModels, getChatHistory, saveChatHistory, removeChatHistory } from '../controller/chat.js'
|
||||
import { getProxyList, addProxy, updateProxy, removeProxy } from '../controller/proxy.js'
|
||||
import { getTerminalConfig, saveTerminalConfig } from '../controller/terminal-config.js'
|
||||
import { getServerListConfig, saveServerListConfig } from '../controller/server-list-config.js'
|
||||
import { getSuspendedSessions, getTerminalSessionConfig, updateTerminalSessionConfig } from '../controller/terminal.js'
|
||||
import { getNativeSshConnection } from '../controller/native.js'
|
||||
|
||||
const ssh = [
|
||||
{
|
||||
@@ -420,7 +420,7 @@ const sftp = [
|
||||
}
|
||||
]
|
||||
|
||||
module.exports = [].concat(
|
||||
export default [].concat(
|
||||
ssh,
|
||||
host,
|
||||
user,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const schedule = require('node-schedule')
|
||||
const { sendNoticeAsync } = require('../utils/notify')
|
||||
const { formatTimestamp } = require('../utils/tools')
|
||||
const { HostListDB } = require('../utils/db-class')
|
||||
import schedule from 'node-schedule'
|
||||
import { sendNoticeAsync } from '../utils/notify.js'
|
||||
import { formatTimestamp } from '../utils/tools.js'
|
||||
import { HostListDB } from '../utils/db-class.js'
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
|
||||
const expiredNotifyJob = async () => {
|
||||
@@ -27,6 +27,6 @@ const expiredNotifyJob = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = () => {
|
||||
export default () => {
|
||||
schedule.scheduleJob('0 0 12 1/1 * ?', expiredNotifyJob)
|
||||
}
|
||||
|
||||
+20
-20
@@ -1,22 +1,22 @@
|
||||
const Koa = require('koa')
|
||||
const compose = require('koa-compose') // 组合中间件,简化写法
|
||||
const http = require('http')
|
||||
const https = require('https')
|
||||
const fs = require('fs')
|
||||
const { httpPort, httpsPort, enableHttps, sslCertPath, sslKeyPath } = require('./config')
|
||||
const middlewares = require('./middlewares')
|
||||
const { startRdpServer } = require('./rdp-server')
|
||||
const wsTerminal = require('./socket/terminal')
|
||||
const wsSftpV2 = require('./socket/sftp-v2')
|
||||
const wsDocker = require('./socket/docker')
|
||||
const wsOnekey = require('./socket/onekey')
|
||||
const wsServerStatus = require('./socket/server-status')
|
||||
const wsFileTransfer = require('./socket/file-transfer')
|
||||
const { throwError, isAllowedIp, getClientIP } = require('./utils/tools')
|
||||
const { SessionDB } = require('./utils/db-class')
|
||||
const { parseCookies } = require('./utils/verify-auth')
|
||||
const { generateSelfSignedCert } = require('./utils/ssl-cert')
|
||||
const createRdpProxyMiddleware = require('./middlewares/rdp-proxy')
|
||||
import Koa from 'koa'
|
||||
import compose from 'koa-compose' // 组合中间件,简化写法
|
||||
import http from 'node:http'
|
||||
import https from 'node:https'
|
||||
import fs from 'node:fs'
|
||||
import { httpPort, httpsPort, enableHttps, sslCertPath, sslKeyPath } from './config/index.js'
|
||||
import middlewares from './middlewares/index.js'
|
||||
import { startRdpServer } from './rdp-server.js'
|
||||
import wsTerminal from './socket/terminal.js'
|
||||
import wsSftpV2 from './socket/sftp-v2.js'
|
||||
import wsDocker from './socket/docker.js'
|
||||
import wsOnekey from './socket/onekey.js'
|
||||
import wsServerStatus from './socket/server-status.js'
|
||||
import wsFileTransfer from './socket/file-transfer.js'
|
||||
import { throwError, isAllowedIp, getClientIP } from './utils/tools.js'
|
||||
import { SessionDB } from './utils/db-class.js'
|
||||
import { parseCookies } from './utils/verify-auth.js'
|
||||
import { generateSelfSignedCert } from './utils/ssl-cert.js'
|
||||
import createRdpProxyMiddleware from './middlewares/rdp-proxy.js'
|
||||
|
||||
const sessionDB = new SessionDB().getInstance()
|
||||
|
||||
@@ -177,6 +177,6 @@ function serverHandler(app, server, httpsServer) {
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
createServer
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
const path = require('path')
|
||||
const { Client: SSHClient } = require('ssh2')
|
||||
const { createTerminal } = require('./terminal')
|
||||
const decryptAndExecuteAsync = require('../utils/decrypt-file')
|
||||
const { createSecureWs } = require('../utils/ws-tool')
|
||||
import path, { dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import ssh2Module from 'ssh2'
|
||||
const { Client: SSHClient } = ssh2Module
|
||||
import { createTerminal } from './terminal.js'
|
||||
import decryptAndExecuteAsync from '../utils/decrypt-file.js'
|
||||
import { createSecureWs } from '../utils/ws-tool.js'
|
||||
|
||||
const currentDir = dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
let executeCommand = () => {
|
||||
return new Promise((resolve) => {
|
||||
@@ -129,7 +133,7 @@ async function deleteDockerContainer(targetSSHClient, containerId) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = (httpServer) => {
|
||||
export default (httpServer) => {
|
||||
const serverIo = createSecureWs(httpServer, '/docker')
|
||||
|
||||
let connectionCount = 0
|
||||
@@ -144,7 +148,7 @@ module.exports = (httpServer) => {
|
||||
targetSSHClient = new SSHClient()
|
||||
let { jumpSshClients: dockerJumpSshClients } = await createTerminal(hostId, socket, targetSSHClient, false)
|
||||
jumpSshClients.push(...dockerJumpSshClients)
|
||||
let { getDockerContainers = null, executeCommand: dockerExecuteCommand } = (await decryptAndExecuteAsync(path.join(__dirname, 'plus.js'))) || {}
|
||||
let { getDockerContainers = null, executeCommand: dockerExecuteCommand } = (await decryptAndExecuteAsync(path.join(currentDir, 'plus.js'))) || {}
|
||||
executeCommand = dockerExecuteCommand
|
||||
if (!getDockerContainers) {
|
||||
socket.emit('docker_not_plus')
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
const path = require('path')
|
||||
const { Client: SSHClient } = require('ssh2')
|
||||
const { fileTransferThrottle } = require('../utils/tools')
|
||||
const { createSecureWs } = require('../utils/ws-tool')
|
||||
const { getConnectionOptions } = require('./terminal')
|
||||
const { FileTransferDB, HostListDB } = require('../utils/db-class')
|
||||
const decryptAndExecuteAsync = require('../utils/decrypt-file')
|
||||
import path, { dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import ssh2Module from 'ssh2'
|
||||
const { Client: SSHClient } = ssh2Module
|
||||
import { fileTransferThrottle } from '../utils/tools.js'
|
||||
import { createSecureWs } from '../utils/ws-tool.js'
|
||||
import { getConnectionOptions } from './terminal.js'
|
||||
import { FileTransferDB, HostListDB } from '../utils/db-class.js'
|
||||
import decryptAndExecuteAsync from '../utils/decrypt-file.js'
|
||||
|
||||
const fileTransferDB = new FileTransferDB().getInstance()
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
const currentDir = dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
// 全局传输任务管理
|
||||
const activeTasks = new Map() // taskId -> { process, sshClient, status, ... }
|
||||
@@ -53,7 +56,7 @@ async function getSortedTasksList() {
|
||||
return sortTasks(tasksWithStatus)
|
||||
}
|
||||
|
||||
module.exports = (httpServer) => {
|
||||
export default (httpServer) => {
|
||||
const serverIo = createSecureWs(httpServer, '/file-transfer')
|
||||
|
||||
let connectionCount = 0
|
||||
@@ -83,7 +86,7 @@ module.exports = (httpServer) => {
|
||||
// 启动传输任务
|
||||
socket.on('start_transfer', async (transferConfig) => {
|
||||
try {
|
||||
const { createTransferTask = null } = (await decryptAndExecuteAsync(path.join(__dirname, 'plus.js'))) || {}
|
||||
const { createTransferTask = null } = (await decryptAndExecuteAsync(path.join(currentDir, 'plus.js'))) || {}
|
||||
if (!createTransferTask) throw new Error('Plus功能解锁失败: createTransferTask')
|
||||
const task = await createTransferTask(transferConfig, socket, hostListDB, fileTransferDB, executeTransfer)
|
||||
socket.emit('task_started', { taskId: task.taskId, message: '传输任务已启动' })
|
||||
@@ -926,4 +929,3 @@ function stopProgressBroadcast(socket) {
|
||||
logger.info('已停止进度广播定时器')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
const { Server } = require('socket.io')
|
||||
const { Client: SSHClient } = require('ssh2')
|
||||
const { sendNoticeAsync } = require('../utils/notify')
|
||||
const { shellThrottle } = require('../utils/tools')
|
||||
const { createSecureWs } = require('../utils/ws-tool')
|
||||
const { HostListDB, OnekeyDB } = require('../utils/db-class')
|
||||
const { getConnectionOptions, handleProxyAndJumpHostConnection } = require('./terminal')
|
||||
import { Server } from 'socket.io'
|
||||
import ssh2Module from 'ssh2'
|
||||
const { Client: SSHClient } = ssh2Module
|
||||
import { sendNoticeAsync } from '../utils/notify.js'
|
||||
import { shellThrottle } from '../utils/tools.js'
|
||||
import { createSecureWs } from '../utils/ws-tool.js'
|
||||
import { HostListDB, OnekeyDB } from '../utils/db-class.js'
|
||||
import { getConnectionOptions, handleProxyAndJumpHostConnection } from './terminal.js'
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
const onekeyDB = new OnekeyDB().getInstance()
|
||||
|
||||
@@ -88,7 +89,7 @@ function execShell(socket, sshClient, curRes, resolve) {
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = (httpServer) => {
|
||||
export default (httpServer) => {
|
||||
const serverIo = createSecureWs(httpServer, '/onekey')
|
||||
|
||||
serverIo.on('connection', async (socket) => {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,12 +1,12 @@
|
||||
const { Client: SSHClient } = require('ssh2')
|
||||
const { createTerminal } = require('./terminal')
|
||||
const { createSecureWs } = require('../utils/ws-tool')
|
||||
import ssh2Module from 'ssh2'
|
||||
const { Client: SSHClient } = ssh2Module
|
||||
import { createTerminal } from './terminal.js'
|
||||
import { createSecureWs } from '../utils/ws-tool.js'
|
||||
const monitorMap = new Map() // key -> { sockets: Set, statusData, stop }
|
||||
const pendingConnections = new Map() // key -> Promise,跟踪正在创建的连接
|
||||
const { HostListDB } = require('../utils/db-class')
|
||||
import { HostListDB } from '../utils/db-class.js'
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
|
||||
/* eslint-disable no-control-regex */
|
||||
function stripAnsi(s = '') {
|
||||
return s
|
||||
.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, '') // CSI
|
||||
@@ -16,7 +16,7 @@ function stripAnsi(s = '') {
|
||||
|
||||
const safeDelta = (curr, prev) => (curr >= prev ? curr - prev : 0)
|
||||
|
||||
module.exports = (httpServer) => {
|
||||
export default (httpServer) => {
|
||||
const serverIo = createSecureWs(httpServer, '/server-status')
|
||||
|
||||
let connectionCount = 0
|
||||
@@ -593,7 +593,7 @@ module.exports = (httpServer) => {
|
||||
try {
|
||||
const cgroupMem = await getCgroupMemoryInfo()
|
||||
if (cgroupMem) {
|
||||
if (cgroupMem.memTotalBytes != null) {
|
||||
if (cgroupMem.memTotalBytes !== null) {
|
||||
const cgroupTotalMb = Math.round(cgroupMem.memTotalBytes / 1024 / 1024)
|
||||
if (cgroupTotalMb > 0 && cgroupTotalMb < memInfo.totalMemMb) {
|
||||
const cgroupUsedMb = Math.max(0, Math.min(Math.round(cgroupMem.memUsedBytes / 1024 / 1024), cgroupTotalMb))
|
||||
@@ -607,7 +607,7 @@ module.exports = (httpServer) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cgroupMem.swapTotalBytes != null) {
|
||||
if (cgroupMem.swapTotalBytes !== null) {
|
||||
const cgroupSwapTotalMb = Math.round(cgroupMem.swapTotalBytes / 1024 / 1024)
|
||||
if (cgroupSwapTotalMb > 0 && (swapInfo.swapTotal === 0 || cgroupSwapTotalMb < swapInfo.swapTotal)) {
|
||||
const cgroupSwapUsedMb = Math.max(0, Math.min(Math.round(cgroupMem.swapUsedBytes / 1024 / 1024), cgroupSwapTotalMb))
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
const rawPath = require('path')
|
||||
const fs = require('fs-extra')
|
||||
const SFTPClient = require('ssh2-sftp-client')
|
||||
const iconv = require('iconv-lite')
|
||||
const chardet = require('chardet')
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
const { sftpCacheDir } = require('../config')
|
||||
const { createSecureWs } = require('../utils/ws-tool')
|
||||
const { HostListDB, FavoriteSftpDB } = require('../utils/db-class')
|
||||
const { getConnectionOptions, handleProxyAndJumpHostConnection } = require('./terminal')
|
||||
import rawPath from 'node:path'
|
||||
import fs from 'fs-extra'
|
||||
import SFTPClient from 'ssh2-sftp-client'
|
||||
import iconv from 'iconv-lite'
|
||||
import chardet from 'chardet'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { sftpCacheDir } from '../config/index.js'
|
||||
import { createSecureWs } from '../utils/ws-tool.js'
|
||||
import { HostListDB, FavoriteSftpDB } from '../utils/db-class.js'
|
||||
import { getConnectionOptions, handleProxyAndJumpHostConnection } from './terminal.js'
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
const favoriteSftpDB = new FavoriteSftpDB().getInstance()
|
||||
const { Client: SSHClient } = require('ssh2')
|
||||
import ssh2Module from 'ssh2'
|
||||
const { Client: SSHClient } = ssh2Module
|
||||
|
||||
function shellEscape(s) {
|
||||
// eslint-disable-next-line quotes
|
||||
@@ -1559,7 +1560,7 @@ const listenAction = (sftpClient, socket) => {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = (httpServer) => {
|
||||
export default (httpServer) => {
|
||||
const serverIo = createSecureWs(httpServer, '/sftp-v2', {
|
||||
// 增加消息大小限制,支持大文件上传(默认1MB)
|
||||
maxHttpBufferSize: 10 * 1024 * 1024, // 10MB
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
const path = require('path')
|
||||
const { Client: SSHClient } = require('ssh2')
|
||||
const { sendNoticeAsync } = require('../utils/notify')
|
||||
const { ping } = require('../utils/tools')
|
||||
const { AESDecryptAsync } = require('../utils/encrypt')
|
||||
const { KeyDB, HostListDB, CredentialsDB, ProxyDB } = require('../utils/db-class')
|
||||
const decryptAndExecuteAsync = require('../utils/decrypt-file')
|
||||
const { sessionManager, SessionStatus } = require('../utils/terminal-session')
|
||||
const { createSecureWs } = require('../utils/ws-tool')
|
||||
import path, { dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import ssh2Module from 'ssh2'
|
||||
const { Client: SSHClient } = ssh2Module
|
||||
import { sendNoticeAsync } from '../utils/notify.js'
|
||||
import { ping } from '../utils/tools.js'
|
||||
import { AESDecryptAsync } from '../utils/encrypt.js'
|
||||
import { KeyDB, HostListDB, CredentialsDB, ProxyDB } from '../utils/db-class.js'
|
||||
import decryptAndExecuteAsync from '../utils/decrypt-file.js'
|
||||
import { sessionManager, SessionStatus } from '../utils/terminal-session.js'
|
||||
import { createSecureWs } from '../utils/ws-tool.js'
|
||||
|
||||
const hostListDB = new HostListDB().getInstance()
|
||||
const credentialsDB = new CredentialsDB().getInstance()
|
||||
const proxyDB = new ProxyDB().getInstance()
|
||||
const keyDB = new KeyDB().getInstance()
|
||||
const currentDir = dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
async function getConnectionOptions(hostId) {
|
||||
const hostInfo = await hostListDB.findOneAsync({ _id: hostId })
|
||||
@@ -137,11 +140,11 @@ async function handleProxyAndJumpHostConnection(options) {
|
||||
|
||||
let proxySocket
|
||||
if (proxyConfig.type === 'socks5') {
|
||||
const { createSocks5Connection = null } = (await decryptAndExecuteAsync(path.join(__dirname, 'plus.js'))) || {}
|
||||
const { createSocks5Connection = null } = (await decryptAndExecuteAsync(path.join(currentDir, 'plus.js'))) || {}
|
||||
if (!createSocks5Connection) throw new Error('Plus功能解锁失败: createSocks5Connection')
|
||||
proxySocket = await createSocks5Connection(proxyConfig, targetConnectionOptions.host, targetConnectionOptions.port)
|
||||
} else if (proxyConfig.type === 'http') {
|
||||
const { createHttpConnection = null } = (await decryptAndExecuteAsync(path.join(__dirname, 'plus.js'))) || {}
|
||||
const { createHttpConnection = null } = (await decryptAndExecuteAsync(path.join(currentDir, 'plus.js'))) || {}
|
||||
if (!createHttpConnection) throw new Error('Plus功能解锁失败: createHttpConnection')
|
||||
proxySocket = await createHttpConnection(proxyConfig, targetConnectionOptions.host, targetConnectionOptions.port)
|
||||
} else {
|
||||
@@ -163,7 +166,7 @@ async function handleProxyAndJumpHostConnection(options) {
|
||||
}
|
||||
// 跳板机连接
|
||||
else if (proxyType === 'jumpHosts' && Array.isArray(jumpHosts) && jumpHosts.length > 0) {
|
||||
const { connectByJumpHosts = null } = (await decryptAndExecuteAsync(path.join(__dirname, 'plus.js'))) || {}
|
||||
const { connectByJumpHosts = null } = (await decryptAndExecuteAsync(path.join(currentDir, 'plus.js'))) || {}
|
||||
if (!connectByJumpHosts) throw new Error('Plus功能解锁失败: connectByJumpHosts')
|
||||
const jumpHostResult = await connectByJumpHosts(jumpHosts, targetConnectionOptions.host, targetConnectionOptions.port, socket)
|
||||
if (jumpHostResult) {
|
||||
@@ -538,13 +541,15 @@ function createServerIo(serverIo) {
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = (httpServer) => {
|
||||
export default (httpServer) => {
|
||||
const serverIo = createSecureWs(httpServer, '/terminal')
|
||||
createServerIo(serverIo)
|
||||
}
|
||||
|
||||
module.exports.getConnectionOptions = getConnectionOptions
|
||||
module.exports.createTerminal = createTerminal
|
||||
module.exports.createServerIo = createServerIo
|
||||
module.exports.getProxyConfig = getProxyConfig
|
||||
module.exports.handleProxyAndJumpHostConnection = handleProxyAndJumpHostConnection
|
||||
export {
|
||||
getConnectionOptions,
|
||||
createTerminal,
|
||||
createServerIo,
|
||||
getProxyConfig,
|
||||
handleProxyAndJumpHostConnection
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module.exports = (content) => {
|
||||
export default (content) => {
|
||||
return `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const Datastore = require('@seald-io/nedb')
|
||||
const {
|
||||
import Datastore from '@seald-io/nedb'
|
||||
import {
|
||||
credentialsDBPath,
|
||||
hostListDBPath,
|
||||
keyDBPath,
|
||||
@@ -19,9 +19,9 @@ const {
|
||||
serverListDBPath,
|
||||
sessionDBPath,
|
||||
terminalSessionDBPath
|
||||
} = require('../config')
|
||||
} from '../config/index.js'
|
||||
|
||||
module.exports.KeyDB = class KeyDB {
|
||||
export class KeyDB {
|
||||
constructor() {
|
||||
if (!KeyDB.instance) {
|
||||
KeyDB.instance = new Datastore({ filename: keyDBPath, autoload: true })
|
||||
@@ -33,7 +33,7 @@ module.exports.KeyDB = class KeyDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.HostListDB = class HostListDB {
|
||||
export class HostListDB {
|
||||
constructor() {
|
||||
if (!HostListDB.instance) {
|
||||
HostListDB.instance = new Datastore({ filename: hostListDBPath, autoload: true })
|
||||
@@ -45,7 +45,7 @@ module.exports.HostListDB = class HostListDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.CredentialsDB = class CredentialsDB {
|
||||
export class CredentialsDB {
|
||||
constructor() {
|
||||
if (!CredentialsDB.instance) {
|
||||
CredentialsDB.instance = new Datastore({ filename: credentialsDBPath, autoload: true })
|
||||
@@ -57,7 +57,7 @@ module.exports.CredentialsDB = class CredentialsDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.NotifyDB = class NotifyDB {
|
||||
export class NotifyDB {
|
||||
constructor() {
|
||||
if (!NotifyDB.instance) {
|
||||
NotifyDB.instance = new Datastore({ filename: notifyDBPath, autoload: true })
|
||||
@@ -69,7 +69,7 @@ module.exports.NotifyDB = class NotifyDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.NotifyConfigDB = class NotifyConfigDB {
|
||||
export class NotifyConfigDB {
|
||||
constructor() {
|
||||
if (!NotifyConfigDB.instance) {
|
||||
NotifyConfigDB.instance = new Datastore({ filename: notifyConfigDBPath, autoload: true })
|
||||
@@ -81,7 +81,7 @@ module.exports.NotifyConfigDB = class NotifyConfigDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.GroupDB = class GroupDB {
|
||||
export class GroupDB {
|
||||
constructor() {
|
||||
if (!GroupDB.instance) {
|
||||
GroupDB.instance = new Datastore({ filename: groupConfDBPath, autoload: true })
|
||||
@@ -93,7 +93,7 @@ module.exports.GroupDB = class GroupDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.ScriptsDB = class ScriptsDB {
|
||||
export class ScriptsDB {
|
||||
constructor() {
|
||||
if (!ScriptsDB.instance) {
|
||||
ScriptsDB.instance = new Datastore({ filename: scriptsDBPath, autoload: true })
|
||||
@@ -105,7 +105,7 @@ module.exports.ScriptsDB = class ScriptsDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.ScriptGroupDB = class ScriptGroupDB {
|
||||
export class ScriptGroupDB {
|
||||
constructor() {
|
||||
if (!ScriptGroupDB.instance) {
|
||||
ScriptGroupDB.instance = new Datastore({ filename: scriptGroupDBPath, autoload: true })
|
||||
@@ -116,7 +116,7 @@ module.exports.ScriptGroupDB = class ScriptGroupDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.OnekeyDB = class OnekeyDB {
|
||||
export class OnekeyDB {
|
||||
constructor() {
|
||||
if (!OnekeyDB.instance) {
|
||||
OnekeyDB.instance = new Datastore({ filename: onekeyDBPath, autoload: true })
|
||||
@@ -128,7 +128,7 @@ module.exports.OnekeyDB = class OnekeyDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.PlusDB = class PlusDB {
|
||||
export class PlusDB {
|
||||
constructor() {
|
||||
if (!PlusDB.instance) {
|
||||
PlusDB.instance = new Datastore({ filename: plusDBPath, autoload: true })
|
||||
@@ -139,7 +139,7 @@ module.exports.PlusDB = class PlusDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.AIConfigDB = class AIConfigDB {
|
||||
export class AIConfigDB {
|
||||
constructor() {
|
||||
if (!AIConfigDB.instance) {
|
||||
AIConfigDB.instance = new Datastore({ filename: aiConfigDBPath, autoload: true })
|
||||
@@ -150,7 +150,7 @@ module.exports.AIConfigDB = class AIConfigDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.ChatHistoryDB = class ChatHistoryDB {
|
||||
export class ChatHistoryDB {
|
||||
constructor() {
|
||||
if (!ChatHistoryDB.instance) {
|
||||
ChatHistoryDB.instance = new Datastore({ filename: chatHistoryDBPath, autoload: true })
|
||||
@@ -161,7 +161,7 @@ module.exports.ChatHistoryDB = class ChatHistoryDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.FavoriteSftpDB = class FavoriteSftpDB {
|
||||
export class FavoriteSftpDB {
|
||||
constructor() {
|
||||
if (!FavoriteSftpDB.instance) {
|
||||
FavoriteSftpDB.instance = new Datastore({ filename: favoriteSftpDBPath, autoload: true })
|
||||
@@ -172,7 +172,7 @@ module.exports.FavoriteSftpDB = class FavoriteSftpDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.ProxyDB = class ProxyDB {
|
||||
export class ProxyDB {
|
||||
constructor() {
|
||||
if (!ProxyDB.instance) {
|
||||
ProxyDB.instance = new Datastore({ filename: proxyDBPath, autoload: true })
|
||||
@@ -183,7 +183,7 @@ module.exports.ProxyDB = class ProxyDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.FileTransferDB = class FileTransferDB {
|
||||
export class FileTransferDB {
|
||||
constructor() {
|
||||
if (!FileTransferDB.instance) {
|
||||
FileTransferDB.instance = new Datastore({ filename: fileTransferDBPath, autoload: true })
|
||||
@@ -194,7 +194,7 @@ module.exports.FileTransferDB = class FileTransferDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.TerminalConfigDB = class TerminalConfigDB {
|
||||
export class TerminalConfigDB {
|
||||
constructor() {
|
||||
if (!TerminalConfigDB.instance) {
|
||||
TerminalConfigDB.instance = new Datastore({ filename: terminalConfigDBPath, autoload: true })
|
||||
@@ -205,7 +205,7 @@ module.exports.TerminalConfigDB = class TerminalConfigDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.ServerListDB = class ServerListDB {
|
||||
export class ServerListDB {
|
||||
constructor() {
|
||||
if (!ServerListDB.instance) {
|
||||
ServerListDB.instance = new Datastore({ filename: serverListDBPath, autoload: true })
|
||||
@@ -216,7 +216,7 @@ module.exports.ServerListDB = class ServerListDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.SessionDB = class SessionDB {
|
||||
export class SessionDB {
|
||||
constructor() {
|
||||
if (!SessionDB.instance) {
|
||||
SessionDB.instance = new Datastore({ filename: sessionDBPath, autoload: true })
|
||||
@@ -227,7 +227,7 @@ module.exports.SessionDB = class SessionDB {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.TerminalSessionDB = class TerminalSessionDB {
|
||||
export class TerminalSessionDB {
|
||||
constructor() {
|
||||
if (!TerminalSessionDB.instance) {
|
||||
TerminalSessionDB.instance = new Datastore({ filename: terminalSessionDBPath, autoload: true })
|
||||
|
||||
@@ -1,56 +1,143 @@
|
||||
const fs = require('fs-extra')
|
||||
const path = require('path')
|
||||
const CryptoJS = require('crypto-js')
|
||||
const { AESDecryptAsync } = require('./encrypt')
|
||||
const { RuntimeState } = require('./runtime-state')
|
||||
import fs from 'fs-extra'
|
||||
import { createRequire } from 'node:module'
|
||||
import path from 'node:path'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import CryptoJS from 'crypto-js'
|
||||
import { init, parse } from 'es-module-lexer'
|
||||
import { AESDecryptAsync, SHA256Encrypt } from './encrypt.js'
|
||||
import { RuntimeState } from './runtime-state.js'
|
||||
const runtimeState = new RuntimeState().getInstance()
|
||||
const plusModuleCache = new Map()
|
||||
const dataModuleUrlPattern = /data:text\/javascript;base64,[A-Za-z0-9+/]+={0,2}(?:#[A-Za-z0-9._-]+)?/g
|
||||
const moduleLexerReady = init
|
||||
|
||||
function decryptAndExecuteAsync(plusPath) {
|
||||
return new Promise(async (resolve) => {
|
||||
try {
|
||||
const decryptKeyCipher = runtimeState.getDecryptKey()
|
||||
if (!decryptKeyCipher) {
|
||||
throw new Error('缺少解密密钥')
|
||||
}
|
||||
const decryptKey = await AESDecryptAsync(decryptKeyCipher)
|
||||
if (!decryptKey) {
|
||||
throw new Error('解密密钥解析失败')
|
||||
}
|
||||
const encryptedContent = fs.readFileSync(plusPath, 'utf-8')
|
||||
const bytes = CryptoJS.AES.decrypt(encryptedContent, decryptKey)
|
||||
const decryptedContent = bytes.toString(CryptoJS.enc.Utf8)
|
||||
if (!decryptedContent) {
|
||||
throw new Error('解密失败,请检查密钥是否正确')
|
||||
}
|
||||
const customRequire = (modulePath) => {
|
||||
if (modulePath.startsWith('.')) {
|
||||
const absolutePath = path.resolve(path.dirname(plusPath), modulePath)
|
||||
return require(absolutePath)
|
||||
}
|
||||
return require(modulePath)
|
||||
}
|
||||
const module = {
|
||||
exports: {},
|
||||
require: customRequire,
|
||||
__filename: plusPath,
|
||||
__dirname: path.dirname(plusPath)
|
||||
}
|
||||
const wrapper = Function('module', 'exports', 'require', '__filename', '__dirname',
|
||||
decryptedContent + '\n return module.exports;'
|
||||
)
|
||||
const exports = wrapper(
|
||||
module,
|
||||
module.exports,
|
||||
customRequire,
|
||||
module.__filename,
|
||||
module.__dirname
|
||||
)
|
||||
resolve(exports)
|
||||
} catch (error) {
|
||||
logger.info('解锁plus功能失败: ', error.message)
|
||||
resolve(null)
|
||||
}
|
||||
})
|
||||
function isPlusAvailable() {
|
||||
return Boolean(runtimeState.getDecryptKey()) && !runtimeState.getPlusKicked()
|
||||
}
|
||||
|
||||
module.exports = decryptAndExecuteAsync
|
||||
function sanitizeLoaderError(error) {
|
||||
const message = error?.message || String(error)
|
||||
return message.replace(dataModuleUrlPattern, '[Plus ESM module]')
|
||||
}
|
||||
|
||||
async function resolveImportSpecifiers(source, plusPath) {
|
||||
await moduleLexerReady
|
||||
const moduleUrl = pathToFileURL(path.resolve(plusPath))
|
||||
const resolver = createRequire(moduleUrl)
|
||||
const resolveSpecifier = (specifier) => {
|
||||
if (specifier.startsWith('node:')) return specifier
|
||||
if (specifier.startsWith('.') || specifier.startsWith('/')) {
|
||||
return new URL(specifier, moduleUrl).href
|
||||
}
|
||||
const resolvedPath = resolver.resolve(specifier)
|
||||
return resolvedPath.startsWith('node:') ? resolvedPath : pathToFileURL(resolvedPath).href
|
||||
}
|
||||
|
||||
const [imports] = parse(source)
|
||||
let resolvedSource = source
|
||||
// 从后向前替换,保证 lexer 返回的源码下标不会因前面的替换而偏移。
|
||||
for (let index = imports.length - 1; index >= 0; index -= 1) {
|
||||
const importRecord = imports[index]
|
||||
// 非字面量动态导入(如 import(moduleName))在运行时才能确定,保持原样。
|
||||
if (typeof importRecord.n !== 'string') continue
|
||||
const resolvedSpecifier = resolveSpecifier(importRecord.n)
|
||||
const quote = importRecord.d >= 0 ? source[importRecord.s] : ''
|
||||
const replacement = quote === '\'' || quote === '"' || quote === '`'
|
||||
? `${ quote }${ resolvedSpecifier }${ quote }`
|
||||
: resolvedSpecifier
|
||||
resolvedSource = `${ resolvedSource.slice(0, importRecord.s) }${ replacement }${ resolvedSource.slice(importRecord.e) }`
|
||||
}
|
||||
return resolvedSource
|
||||
}
|
||||
|
||||
async function resolveDecryptKey(decryptKeyCipher) {
|
||||
const decryptKey = await AESDecryptAsync(decryptKeyCipher)
|
||||
if (!decryptKey) {
|
||||
throw new Error('解密密钥解析失败')
|
||||
}
|
||||
return {
|
||||
decryptKey,
|
||||
fingerprint: SHA256Encrypt(decryptKey)
|
||||
}
|
||||
}
|
||||
|
||||
async function decryptAndImportOnce(plusPath, decryptKey) {
|
||||
const encryptedContent = await fs.readFile(plusPath, 'utf-8')
|
||||
const bytes = CryptoJS.AES.decrypt(encryptedContent, decryptKey)
|
||||
const decryptedContent = bytes.toString(CryptoJS.enc.Utf8)
|
||||
if (!decryptedContent) {
|
||||
throw new Error('解密失败,请检查密钥是否正确')
|
||||
}
|
||||
const esmContent = await resolveImportSpecifiers(decryptedContent, plusPath)
|
||||
const moduleId = path.basename(path.dirname(plusPath))
|
||||
const sourceLabel = `easynode-plus-${ moduleId }.mjs`
|
||||
const encodedContent = Buffer.from(`${ esmContent }\n//# sourceURL=${ sourceLabel }\n`).toString('base64')
|
||||
return import(`data:text/javascript;base64,${ encodedContent }#plus-${ moduleId }`)
|
||||
}
|
||||
|
||||
function createCacheEntry(absolutePath, decryptKeyCipher) {
|
||||
const entry = {
|
||||
keyFingerprint: null,
|
||||
validatedCipher: decryptKeyCipher,
|
||||
modulePromise: null
|
||||
}
|
||||
|
||||
entry.modulePromise = resolveDecryptKey(decryptKeyCipher)
|
||||
.then(({ decryptKey, fingerprint }) => {
|
||||
entry.keyFingerprint = fingerprint
|
||||
return decryptAndImportOnce(absolutePath, decryptKey)
|
||||
})
|
||||
.catch((error) => {
|
||||
if (plusModuleCache.get(absolutePath) === entry) {
|
||||
plusModuleCache.delete(absolutePath)
|
||||
}
|
||||
throw error
|
||||
})
|
||||
plusModuleCache.set(absolutePath, entry)
|
||||
return entry
|
||||
}
|
||||
|
||||
async function validateCachedAuthorization(entry, decryptKeyCipher) {
|
||||
if (entry.validatedCipher === decryptKeyCipher) return
|
||||
|
||||
const [, currentAuth] = await Promise.all([
|
||||
entry.modulePromise,
|
||||
resolveDecryptKey(decryptKeyCipher)
|
||||
])
|
||||
if (entry.keyFingerprint !== currentAuth.fingerprint) {
|
||||
throw new Error('Plus解密密钥已变化')
|
||||
}
|
||||
|
||||
// 同一明文密钥重新激活时密文会变化,仅在状态仍有效时记录本次校验结果。
|
||||
if (isPlusAvailable() && runtimeState.getDecryptKey() === decryptKeyCipher) {
|
||||
entry.validatedCipher = decryptKeyCipher
|
||||
}
|
||||
}
|
||||
|
||||
async function decryptAndExecuteAsync(plusPath) {
|
||||
try {
|
||||
if (!isPlusAvailable()) {
|
||||
throw new Error(runtimeState.getPlusKicked() ? 'Plus授权已失效' : '缺少解密密钥')
|
||||
}
|
||||
|
||||
const absolutePath = path.resolve(plusPath)
|
||||
const decryptKeyCipher = runtimeState.getDecryptKey()
|
||||
const entry = plusModuleCache.get(absolutePath)
|
||||
|| createCacheEntry(absolutePath, decryptKeyCipher)
|
||||
|
||||
await validateCachedAuthorization(entry, decryptKeyCipher)
|
||||
const plusModule = await entry.modulePromise
|
||||
|
||||
// 加载过程中授权可能被清除,返回模块前再次校验。
|
||||
if (!isPlusAvailable() || runtimeState.getDecryptKey() !== decryptKeyCipher) {
|
||||
throw new Error('Plus授权状态已变化')
|
||||
}
|
||||
|
||||
return plusModule
|
||||
} catch (error) {
|
||||
logger.info('解锁plus功能失败: ', sanitizeLoaderError(error))
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export default decryptAndExecuteAsync
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const CryptoJS = require('crypto-js')
|
||||
const rawCrypto = require('crypto')
|
||||
const NodeRSA = require('node-rsa')
|
||||
const { KeyDB } = require('./db-class')
|
||||
import CryptoJS from 'crypto-js'
|
||||
import rawCrypto from 'node:crypto'
|
||||
import NodeRSA from 'node-rsa'
|
||||
import { KeyDB } from './db-class.js'
|
||||
const keyDB = new KeyDB().getInstance()
|
||||
|
||||
// rsa非对称 私钥解密
|
||||
@@ -41,7 +41,7 @@ const SHA256Encrypt = (clearText) => {
|
||||
return rawCrypto.createHash('sha256').update(clearText).digest('hex')
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
RSADecryptAsync,
|
||||
AESEncryptAsync,
|
||||
AESDecryptAsync,
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
const crypto = require('crypto')
|
||||
const path = require('path')
|
||||
const { requestWithFailover } = require('./tools')
|
||||
const { AESEncryptAsync } = require('./encrypt')
|
||||
const decryptAndExecuteAsync = require('./decrypt-file')
|
||||
const version = require('../../package.json').version
|
||||
const { PlusDB } = require('./db-class')
|
||||
const { RuntimeState } = require('./runtime-state')
|
||||
import crypto from 'node:crypto'
|
||||
import path, { dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { requestWithFailover } from './tools.js'
|
||||
import { AESEncryptAsync } from './encrypt.js'
|
||||
import decryptAndExecuteAsync from './decrypt-file.js'
|
||||
import PackageJsonModule from '../../package.json' with { type: 'json' }
|
||||
const version = PackageJsonModule.version
|
||||
import { PlusDB } from './db-class.js'
|
||||
import { RuntimeState } from './runtime-state.js'
|
||||
const plusDB = new PlusDB().getInstance()
|
||||
const runtimeState = new RuntimeState().getInstance()
|
||||
const currentDir = dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
const RETRY_INTERVAL_MS = 30 * 1000
|
||||
let maxRetryCount = 3
|
||||
let retryTimer = null
|
||||
|
||||
async function startHeartbeatIfAvailable() {
|
||||
const plusModule = await decryptAndExecuteAsync(path.join(__dirname, '../controller/plus.js'))
|
||||
const plusModule = await decryptAndExecuteAsync(path.join(currentDir, '../controller/plus.js'))
|
||||
if (typeof plusModule?.startHeartbeat === 'function') {
|
||||
plusModule.startHeartbeat()
|
||||
} else {
|
||||
@@ -102,5 +105,5 @@ function scheduleNextActivation() {
|
||||
if (retryTimer.unref) retryTimer.unref()
|
||||
}
|
||||
|
||||
module.exports = getLicenseInfo
|
||||
module.exports.startActivation = activateOrRetry
|
||||
export default getLicenseInfo
|
||||
export { activateOrRetry as startActivation }
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
const nodemailer = require('nodemailer')
|
||||
const TelegramBot = require('node-telegram-bot-api')
|
||||
const axios = require('axios')
|
||||
const FormData = require('form-data')
|
||||
const commonTemp = require('../template/commonTemp')
|
||||
const { NotifyDB, NotifyConfigDB } = require('./db-class')
|
||||
import nodemailer from 'nodemailer'
|
||||
import TelegramBot from 'node-telegram-bot-api'
|
||||
import axios from 'axios'
|
||||
import FormData from 'form-data'
|
||||
import commonTemp from '../template/commonTemp.js'
|
||||
import { NotifyDB, NotifyConfigDB } from './db-class.js'
|
||||
const notifyConfigDB = new NotifyConfigDB().getInstance()
|
||||
const notifyDB = new NotifyDB().getInstance()
|
||||
|
||||
@@ -251,7 +251,7 @@ async function sendNoticeAsync(noticeAction, title, content) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
sendNoticeAsync,
|
||||
sendServerChan,
|
||||
sendEmail,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module.exports = {
|
||||
plusServers: [
|
||||
'https://easynode-auth1.chaoszhu.com',
|
||||
'https://easynode-auth2.chaoszhu.com'
|
||||
]
|
||||
}
|
||||
const plusServers = [
|
||||
'https://easynode-auth1.chaoszhu.com',
|
||||
'https://easynode-auth2.chaoszhu.com'
|
||||
]
|
||||
|
||||
export { plusServers }
|
||||
|
||||
@@ -70,4 +70,4 @@ class RuntimeState {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { RuntimeState }
|
||||
export { RuntimeState }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const selfsigned = require('selfsigned')
|
||||
import selfsigned from 'selfsigned'
|
||||
|
||||
/**
|
||||
* 生成自签名证书
|
||||
@@ -53,6 +53,6 @@ function generateSelfSignedCert() {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
generateSelfSignedCert
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ class TerminalSession {
|
||||
}
|
||||
|
||||
// 创建新的SSH连接
|
||||
const { Client: SSHClient } = require('ssh2')
|
||||
const { Client: SSHClient } = (await import('ssh2')).default
|
||||
const newClient = new SSHClient()
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
@@ -299,7 +299,7 @@ class SessionManager {
|
||||
*/
|
||||
async loadConfigFromDB() {
|
||||
try {
|
||||
const { TerminalSessionDB } = require('./db-class')
|
||||
const { TerminalSessionDB } = await import('./db-class.js')
|
||||
const terminalSessionDB = new TerminalSessionDB().getInstance()
|
||||
const config = await terminalSessionDB.findOneAsync({})
|
||||
|
||||
@@ -327,7 +327,7 @@ class SessionManager {
|
||||
// 数据库中存储的是KB,需要转换为字节
|
||||
this.maxBufferSize = config.maxBufferSize * 1024
|
||||
}
|
||||
logger.info(`已从数据库加载终端会话配置: maxSuspendedPerUser=${this.maxSuspendedPerUser}, maxSuspendTime=${this.maxSuspendTime / 1000 / 60 / 60}小时`)
|
||||
logger.info(`已从数据库加载终端会话配置: maxSuspendedPerUser=${ this.maxSuspendedPerUser }, maxSuspendTime=${ this.maxSuspendTime / 1000 / 60 / 60 }小时`)
|
||||
} else {
|
||||
logger.info('数据库中无终端会话配置,使用默认配置')
|
||||
}
|
||||
@@ -644,7 +644,7 @@ class SessionManager {
|
||||
// 导出单例
|
||||
const sessionManager = new SessionManager()
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
SessionStatus,
|
||||
TerminalSession,
|
||||
sessionManager,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
const { exec } = require('child_process')
|
||||
const crypto = require('crypto')
|
||||
const os = require('os')
|
||||
const net = require('net')
|
||||
const iconv = require('iconv-lite')
|
||||
const axios = require('axios')
|
||||
import { exec } from 'node:child_process'
|
||||
import crypto from 'node:crypto'
|
||||
import os from 'node:os'
|
||||
import net from 'node:net'
|
||||
import iconv from 'iconv-lite'
|
||||
import axios from 'axios'
|
||||
const request = axios.create({ timeout: 3000 })
|
||||
const { plusServers } = require('./plus-server')
|
||||
import { plusServers } from './plus-server.js'
|
||||
|
||||
// 为空时请求本地IP
|
||||
const getNetIPInfo = async (searchIp = '') => {
|
||||
@@ -438,7 +438,7 @@ const timingSafeEqual = (a, b) => {
|
||||
return crypto.timingSafeEqual(bufA, bufB)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
getNetIPInfo,
|
||||
getLocalNetIP,
|
||||
throwError,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const jwt = require('jsonwebtoken')
|
||||
const { AESDecryptAsync } = require('./encrypt')
|
||||
const { isAllowedIp, getClientIP } = require('../utils/tools')
|
||||
const { SHA256Encrypt } = require('../utils/encrypt')
|
||||
const { KeyDB, SessionDB } = require('./db-class')
|
||||
import jwt from 'jsonwebtoken'
|
||||
import { AESDecryptAsync } from './encrypt.js'
|
||||
import { isAllowedIp, getClientIP } from '../utils/tools.js'
|
||||
import { SHA256Encrypt } from '../utils/encrypt.js'
|
||||
import { KeyDB, SessionDB } from './db-class.js'
|
||||
const keyDB = new KeyDB().getInstance()
|
||||
const sessionDB = new SessionDB().getInstance()
|
||||
|
||||
@@ -95,7 +95,7 @@ const verifyWsAuthSync = async (socket, next) => {
|
||||
next()
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
enumLoginCode,
|
||||
verifyAuthSync,
|
||||
verifyWsAuthSync,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const { Server } = require('socket.io')
|
||||
const { verifyWsAuthSync } = require('./verify-auth')
|
||||
import { Server } from 'socket.io'
|
||||
import { verifyWsAuthSync } from './verify-auth.js'
|
||||
|
||||
const createSecureWs = (httpServer, path, otherConfig = {}) => {
|
||||
const serverIo = new Server(httpServer, {
|
||||
@@ -16,6 +16,6 @@ const createSecureWs = (httpServer, path, otherConfig = {}) => {
|
||||
return serverIo
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
createSecureWs
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,3 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
console.log('start time', new Date())
|
||||
require('../index.js')
|
||||
#!/usr/bin/env node
|
||||
console.log('start time', new Date())
|
||||
await import('../index.js')
|
||||
|
||||
+7
-3
@@ -1,7 +1,11 @@
|
||||
const { spawn } = require('child_process')
|
||||
const treeKill = require('tree-kill')
|
||||
import { spawn } from 'node:child_process'
|
||||
import { createRequire } from 'node:module'
|
||||
import { dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import treeKill from 'tree-kill'
|
||||
|
||||
const serverRoot = __dirname
|
||||
const serverRoot = dirname(fileURLToPath(import.meta.url))
|
||||
const require = createRequire(import.meta.url)
|
||||
const nodemonBin = require.resolve('nodemon/bin/nodemon.js')
|
||||
const child = spawn(process.execPath, [nodemonBin, 'index.js'], {
|
||||
cwd: serverRoot,
|
||||
|
||||
+6
-3
@@ -1,5 +1,8 @@
|
||||
// AES-256-CBC requires a 32-byte key. Keep the random bytes as a Buffer;
|
||||
// converting them to hex produces a 64-character value and breaks RDP token encryption.
|
||||
global.rpdToken = require('crypto').randomBytes(32)
|
||||
require('dotenv').config()
|
||||
require('./app/main.js')
|
||||
import crypto from 'node:crypto'
|
||||
import dotenv from 'dotenv'
|
||||
|
||||
global.rpdToken = crypto.randomBytes(32)
|
||||
dotenv.config()
|
||||
await import('./app/main.js')
|
||||
|
||||
+3
-1
@@ -2,6 +2,7 @@
|
||||
"name": "server",
|
||||
"version": "3.7.1",
|
||||
"description": "easynode-server",
|
||||
"type": "module",
|
||||
"bin": "./bin/www",
|
||||
"scripts": {
|
||||
"local": "cross-env EXEC_ENV=local node dev-local.js",
|
||||
@@ -30,6 +31,7 @@
|
||||
"cross-env": "^7.0.3",
|
||||
"crypto-js": "4.2.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"es-module-lexer": "^2.3.1",
|
||||
"eslint": "^10.4.1",
|
||||
"fs-extra": "^11.2.0",
|
||||
"global": "^4.4.0",
|
||||
@@ -37,7 +39,7 @@
|
||||
"http-proxy-middleware": "^3.0.5",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"jsonwebtoken": "9.0.2",
|
||||
"koa": "2.16.2",
|
||||
"koa": "2.16.4",
|
||||
"koa-body": "^6.0.1",
|
||||
"koa-compose": "^4.1.0",
|
||||
"koa-compress": "^5.1.1",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const axios = require('axios')
|
||||
import axios from 'axios'
|
||||
|
||||
const BASE_URL = 'http://localhost:8082/api/v1'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const io = require('socket.io-client')
|
||||
import io from 'socket.io-client'
|
||||
|
||||
const SERVER_URL = 'http://localhost:8082'
|
||||
const VALID_TOKEN = 'U2FsdGVkX1+26QCTo4JlGxKnQFcDjOxHyZthx/zucoUMh4CVGc3d4DdBPG2LK52gLuO5RRtmnclYoZESSyQrP7RDoJxh4PLkF6Dm7m3PiO112i1DWxp/xANsRQBzotJ1soPa1ym82BNQRNoziZHbG2RmC/wM953x1zEBgK0wD6LW0I9cQMNIaiO+TV8f/qYt9m4QEoG3UBnLWCN5+oHU0DTOMJQgXBl7zFVwj/9YENt0rN5tBLZSSZv6krM94lmTO7V/mXycUqa/fWJuz7+B0ThlxFNFwzHdizGB+iqTHLoFrDL9Nw0d4oHnBOEkzSmwjIzNysVttfESpjAjNZ6gfmpV7+qERGxt9VHTogWP2cIaT5Dqjkc1ldG63yfYzXCx'
|
||||
|
||||
@@ -2706,6 +2706,11 @@ es-errors@^1.3.0:
|
||||
resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
|
||||
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
|
||||
|
||||
es-module-lexer@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-2.3.1.tgz#5bf2df06999dbbe5f006a5f46a11fb9f5b7b391b"
|
||||
integrity sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==
|
||||
|
||||
es-object-atoms@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941"
|
||||
@@ -4053,10 +4058,10 @@ koa2-connect-history-api-fallback@^0.1.3:
|
||||
resolved "https://registry.yarnpkg.com/koa2-connect-history-api-fallback/-/koa2-connect-history-api-fallback-0.1.3.tgz#dd07b6183ab111d48a6e14f0896d39397c2b879b"
|
||||
integrity sha512-6SucVC8sn7ffaAKOhpNn1OJUqZDK37Jg/PSBAGSribQIikU/Et1aOkUcPH34dm55Kl94RrH4d1snOG6EErzE1Q==
|
||||
|
||||
koa@2.16.2:
|
||||
version "2.16.2"
|
||||
resolved "https://registry.yarnpkg.com/koa/-/koa-2.16.2.tgz#1292a3b415a9b9f3dd6872c1835229630a4ecae3"
|
||||
integrity sha512-+CCssgnrWKx9aI3OeZwroa/ckG4JICxvIFnSiOUyl2Uv+UTI+xIw0FfFrWS7cQFpoePpr9o8csss7KzsTzNL8Q==
|
||||
koa@2.16.4:
|
||||
version "2.16.4"
|
||||
resolved "https://registry.yarnpkg.com/koa/-/koa-2.16.4.tgz#303b996f5c3f2a3bb771c7db5e4303ee05f2265f"
|
||||
integrity sha512-3An0GCLDSR34tsCO4H8Tef8Pp2ngtaZDAZnsWJYelqXUK5wyiHvGItgK/xcSkmHLSTn1Jcho1mRQs2ehRzvKKw==
|
||||
dependencies:
|
||||
accepts "^1.3.5"
|
||||
cache-content-type "^1.0.0"
|
||||
@@ -4547,6 +4552,11 @@ object-inspect@^1.13.3:
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.3.tgz#f14c183de51130243d6d18ae149375ff50ea488a"
|
||||
integrity sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==
|
||||
|
||||
object-inspect@^1.13.4:
|
||||
version "1.13.4"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213"
|
||||
integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==
|
||||
|
||||
object-keys@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
|
||||
@@ -4858,7 +4868,14 @@ qrcode@^1.5.4:
|
||||
pngjs "^5.0.0"
|
||||
yargs "^15.3.1"
|
||||
|
||||
qs@6.13.1, qs@^6.11.0, qs@^6.14.1, qs@^6.5.2:
|
||||
qs@6.13.1:
|
||||
version "6.13.1"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.1.tgz#3ce5fc72bd3a8171b85c99b93c65dd20b7d1b16e"
|
||||
integrity sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==
|
||||
dependencies:
|
||||
side-channel "^1.0.6"
|
||||
|
||||
qs@^6.11.0, qs@^6.5.2:
|
||||
version "6.15.2"
|
||||
resolved "https://registry.npmmirror.com/qs/-/qs-6.15.2.tgz#fd55426d710403ddccc45e0f9eab16db7727ece9"
|
||||
integrity sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==
|
||||
@@ -5178,6 +5195,14 @@ side-channel-list@^1.0.0:
|
||||
es-errors "^1.3.0"
|
||||
object-inspect "^1.13.3"
|
||||
|
||||
side-channel-list@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.1.tgz#c2e0b5a14a540aebee3bbc6c3f8666cc9b509127"
|
||||
integrity sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
object-inspect "^1.13.4"
|
||||
|
||||
side-channel-map@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42"
|
||||
@@ -5199,6 +5224,17 @@ side-channel-weakmap@^1.0.2:
|
||||
object-inspect "^1.13.3"
|
||||
side-channel-map "^1.0.1"
|
||||
|
||||
side-channel@^1.0.6:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.1.tgz#ea02c62e05dc4bea67d4442f0fb71ee192f8e0ab"
|
||||
integrity sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
object-inspect "^1.13.4"
|
||||
side-channel-list "^1.0.1"
|
||||
side-channel-map "^1.0.1"
|
||||
side-channel-weakmap "^1.0.2"
|
||||
|
||||
side-channel@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9"
|
||||
|
||||
Reference in New Issue
Block a user