✨ 支持MFA2二次验证
This commit is contained in:
parent
70bdaa5b69
commit
f0b492da26
@ -1,3 +1,11 @@
|
||||
## [2.3.0](https://github.com/chaos-zhu/easynode/releases) (2024-10-xx)
|
||||
|
||||
* 重构本地数据库存储方式(性能提升一个level~)
|
||||
* 支持MFA2二次验证
|
||||
* 优化了一些页面在移动端的展示
|
||||
* 修复偶现刷新页面需重新登录的bug
|
||||
|
||||
|
||||
## [2.2.8](https://github.com/chaos-zhu/easynode/releases) (2024-10-20)
|
||||
|
||||
### Features
|
||||
|
@ -1,5 +1,7 @@
|
||||
const jwt = require('jsonwebtoken')
|
||||
const axios = require('axios')
|
||||
const speakeasy = require('speakeasy')
|
||||
const QRCode = require('qrcode')
|
||||
const { sendNoticeAsync } = require('../utils/notify')
|
||||
const { RSADecryptAsync, AESEncryptAsync, SHA1Encrypt } = require('../utils/encrypt')
|
||||
const { getNetIPInfo } = require('../utils/tools')
|
||||
@ -112,7 +114,6 @@ const getEasynodeVersion = async ({ res }) => {
|
||||
try {
|
||||
// const { data } = await axios.get('https://api.github.com/repos/chaos-zhu/easynode/releases/latest')
|
||||
const { data } = await axios.get('https://get-easynode-latest-version.chaoszhu.workers.dev/version')
|
||||
console.log(data)
|
||||
res.success({ data, msg: 'success' })
|
||||
} catch (error) {
|
||||
consola.error('Failed to fetch Easynode latest version:', error)
|
||||
@ -120,9 +121,58 @@ const getEasynodeVersion = async ({ res }) => {
|
||||
}
|
||||
}
|
||||
|
||||
let tempSecret = null
|
||||
const getMFA2Status = async ({ res }) => {
|
||||
const { enableMFA2 = false } = await keyDB.findOneAsync({})
|
||||
res.success({ data: enableMFA2, msg: 'success' })
|
||||
}
|
||||
const getMFA2Code = async ({ res }) => {
|
||||
const { user } = await keyDB.findOneAsync({})
|
||||
let { otpauth_url, base32 } = speakeasy.generateSecret({ name: `EasyNode-${ user }`, length: 20 })
|
||||
tempSecret = base32
|
||||
const qrImage = await QRCode.toDataURL(otpauth_url)
|
||||
const data = { qrImage, secret: tempSecret }
|
||||
res.success({ data, msg: 'success' })
|
||||
}
|
||||
|
||||
const enableMFA2 = async ({ res, request }) => {
|
||||
const { body: { token } } = request
|
||||
if (!token) return res.fail({ data: false, msg: '参数错误' })
|
||||
try {
|
||||
// const isValid = authenticator.verify({ token, secret: tempSecret })
|
||||
const isValid = speakeasy.totp.verify({
|
||||
secret: tempSecret,
|
||||
encoding: 'base32',
|
||||
token,
|
||||
window: 1
|
||||
})
|
||||
if (!isValid) return res.fail({ msg: '验证失败' })
|
||||
const keyConfig = await keyDB.findOneAsync({})
|
||||
keyConfig.enableMFA2 = true
|
||||
keyConfig.secret = tempSecret
|
||||
tempSecret = null
|
||||
await keyDB.updateAsync({}, keyConfig)
|
||||
res.success({ msg: '验证成功' })
|
||||
} catch (error) {
|
||||
res.fail({ msg: `验证失败: ${ error.message }` })
|
||||
}
|
||||
}
|
||||
|
||||
const disableMFA2 = async ({ res }) => {
|
||||
const keyConfig = await keyDB.findOneAsync({})
|
||||
keyConfig.enableMFA2 = false
|
||||
keyConfig.secret = null
|
||||
await keyDB.updateAsync({}, keyConfig)
|
||||
res.success({ msg: 'success' })
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
login,
|
||||
getpublicKey,
|
||||
updatePwd,
|
||||
getEasynodeVersion
|
||||
getEasynodeVersion,
|
||||
getMFA2Status,
|
||||
getMFA2Code,
|
||||
enableMFA2,
|
||||
disableMFA2
|
||||
}
|
||||
|
@ -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 } = require('../controller/user')
|
||||
const { login, getpublicKey, updatePwd, getEasynodeVersion, getMFA2Status, getMFA2Code, enableMFA2, disableMFA2 } = 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')
|
||||
@ -81,6 +81,26 @@ const user = [
|
||||
method: 'get',
|
||||
path: '/version',
|
||||
controller: getEasynodeVersion
|
||||
},
|
||||
{
|
||||
method: 'get',
|
||||
path: '/mfa2-status',
|
||||
controller: getMFA2Status
|
||||
},
|
||||
{
|
||||
method: 'post',
|
||||
path: '/mfa2-code',
|
||||
controller: getMFA2Code
|
||||
},
|
||||
{
|
||||
method: 'post',
|
||||
path: '/mfa2-enable',
|
||||
controller: enableMFA2
|
||||
},
|
||||
{
|
||||
method: 'post',
|
||||
path: '/mfa2-disable',
|
||||
controller: disableMFA2
|
||||
}
|
||||
]
|
||||
const notify = [
|
||||
|
@ -44,8 +44,10 @@
|
||||
"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"
|
||||
},
|
||||
|
@ -52,24 +52,18 @@ export default {
|
||||
updatePwd(data) {
|
||||
return axios({ url: '/pwd', method: 'put', data })
|
||||
},
|
||||
// updateHostSort(data) {
|
||||
// return axios({ url: '/host-sort', method: 'put', data })
|
||||
// },
|
||||
// getUserEmailList() {
|
||||
// return axios({ url: '/user-email', method: 'get' })
|
||||
// },
|
||||
// getSupportEmailList() {
|
||||
// return axios({ url: '/support-email', method: 'get' })
|
||||
// },
|
||||
// updateUserEmailList(data) {
|
||||
// return axios({ url: '/user-email', method: 'post', data })
|
||||
// },
|
||||
// deleteUserEmail(email) {
|
||||
// return axios({ url: `/user-email/${ email }`, method: 'delete' })
|
||||
// },
|
||||
// pushTestEmail(data) {
|
||||
// return axios({ url: '/push-email', method: 'post', data })
|
||||
// },
|
||||
getMFA2QR() {
|
||||
return axios({ url: '/mfa2-code', method: 'post' })
|
||||
},
|
||||
getMFA2Status() {
|
||||
return axios({ url: '/mfa2-status', method: 'get' })
|
||||
},
|
||||
enableMFA2(data) {
|
||||
return axios({ url: '/mfa2-enable', method: 'post', data })
|
||||
},
|
||||
disableMFA2() {
|
||||
return axios({ url: '/mfa2-disable', method: 'post' })
|
||||
},
|
||||
getNotifyConfig() {
|
||||
return axios({ url: '/notify-config', method: 'get' })
|
||||
},
|
||||
|
@ -6,7 +6,7 @@
|
||||
:rules="rules"
|
||||
:hide-required-asterisk="true"
|
||||
label-suffix=":"
|
||||
label-width="90px"
|
||||
label-width="86px"
|
||||
:show-message="false"
|
||||
>
|
||||
<el-form-item label="原用户名" prop="oldLoginName">
|
||||
@ -50,13 +50,37 @@
|
||||
<el-button type="primary" :loading="loading" @click="handleUpdate">确认</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<h2 class="mfa2_title">两步验证(MFA2)</h2>
|
||||
<div v-if="isEnableMFA2">
|
||||
<span class="enable_text">已启用</span>
|
||||
<el-button class="disable_btn" type="danger" @click="handleDisableMFA2">禁用</el-button>
|
||||
</div>
|
||||
<template v-else>
|
||||
<el-button v-if="startEnableMFA2" type="primary" @click="handleMFA2">启用</el-button>
|
||||
<template v-else>
|
||||
<div class="mfa2_container">
|
||||
<!-- https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2 -->
|
||||
<p>1. 使用MFA2应用(<a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2" target="_blank" class="link">Google Authenticator</a> )扫描下面二维码,或者输入秘钥 <span class="secret">{{ MFA2Data.secret }}</span></p>
|
||||
<img :src="MFA2Data.qrImage" :alt="MFA2Data.secret">
|
||||
<p>2. 输入MFA2应用上的6位数字</p>
|
||||
<el-input
|
||||
v-model="mfa2Token"
|
||||
class="mfa2_input"
|
||||
clearable
|
||||
placeholder=""
|
||||
@keyup.enter="handleEnableMFA2"
|
||||
/>
|
||||
<el-button type="primary" @click="handleEnableMFA2">保存</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, getCurrentInstance } from 'vue'
|
||||
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
|
||||
import { RSAEncrypt } from '@utils/index.js'
|
||||
|
||||
const { proxy: { $api, $message, $store } } = getCurrentInstance()
|
||||
const { proxy: { $api, $message, $messageBox, $store } } = getCurrentInstance()
|
||||
|
||||
const loading = ref(false)
|
||||
const formRef = ref(null)
|
||||
@ -73,6 +97,14 @@ const rules = reactive({
|
||||
newPwd: { required: true, message: '输入新密码', trigger: 'change' }
|
||||
})
|
||||
|
||||
const startEnableMFA2 = ref(true)
|
||||
const isEnableMFA2 = ref(false)
|
||||
const MFA2Data = ref({
|
||||
qrImage: '',
|
||||
secret: ''
|
||||
})
|
||||
const mfa2Token = ref('')
|
||||
|
||||
const handleUpdate = () => {
|
||||
formRef.value.validate()
|
||||
.then(async () => {
|
||||
@ -89,10 +121,73 @@ const handleUpdate = () => {
|
||||
formRef.value.resetFields()
|
||||
})
|
||||
}
|
||||
|
||||
const getMFA2Status = async () => {
|
||||
let { data } = await $api.getMFA2Status()
|
||||
isEnableMFA2.value = data
|
||||
}
|
||||
const handleMFA2 = async () => {
|
||||
startEnableMFA2.value = false
|
||||
let { data } = await $api.getMFA2QR()
|
||||
MFA2Data.value = data
|
||||
console.log(data)
|
||||
}
|
||||
|
||||
const handleEnableMFA2 = async () => {
|
||||
if (!mfa2Token.value) return $message({ type: 'error', center: true, message: '请输入MFA2应用上的6位数字' })
|
||||
let { msg } = await $api.enableMFA2({ token: mfa2Token.value })
|
||||
$message({ type: 'success', center: true, message: msg })
|
||||
getMFA2Status()
|
||||
}
|
||||
const handleDisableMFA2 = async () => {
|
||||
$messageBox.confirm('确认禁用MFA2', 'Warning', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
let { msg } = await $api.disableMFA2()
|
||||
$message({ type: 'success', center: true, message: msg })
|
||||
getMFA2Status()
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getMFA2Status()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.password-form {
|
||||
width: 500px;
|
||||
}
|
||||
.mfa2_title {
|
||||
font-size: 18px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.mfa2_container {
|
||||
align-items: flex-start;
|
||||
color: var(--el-text-color-regular);
|
||||
font-size: var(--el-form-label-font-size);
|
||||
line-height: 32px;
|
||||
.secret {
|
||||
color: var(--el-color-primary);
|
||||
text-decoration: underline;
|
||||
}
|
||||
img {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.mfa2_input {
|
||||
width: 150px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
}
|
||||
.enable_text {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
.disable_btn {
|
||||
margin: 0 15px;
|
||||
}
|
||||
</style>
|
140
yarn.lock
140
yarn.lock
@ -1593,6 +1593,11 @@ balanced-match@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||
|
||||
base32.js@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/base32.js/-/base32.js-0.0.1.tgz#d045736a57b1f6c139f0c7df42518a84e91bb2ba"
|
||||
integrity sha512-EGHIRiegFa62/SsA1J+Xs2tIzludPdzM064N9wjbiEgHnGnJ1V0WEpA4pEwCYT5nDvZk3ubf0shqaCS7k6xeUQ==
|
||||
|
||||
base64-js@^1.3.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||
@ -1713,6 +1718,11 @@ callsites@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
||||
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
|
||||
|
||||
camelcase@^5.0.0:
|
||||
version "5.3.1"
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
||||
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
||||
|
||||
camelcase@^6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
|
||||
@ -1773,6 +1783,15 @@ clean-stack@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
|
||||
integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
|
||||
|
||||
cliui@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
|
||||
integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
|
||||
dependencies:
|
||||
string-width "^4.2.0"
|
||||
strip-ansi "^6.0.0"
|
||||
wrap-ansi "^6.2.0"
|
||||
|
||||
cliui@^7.0.2:
|
||||
version "7.0.4"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
|
||||
@ -2053,6 +2072,11 @@ debug@^3.1.0, debug@^3.2.7:
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
decamelize@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
||||
integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==
|
||||
|
||||
decompress-response@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc"
|
||||
@ -2122,6 +2146,11 @@ dezalgo@^1.0.4:
|
||||
asap "^2.0.0"
|
||||
wrappy "1"
|
||||
|
||||
dijkstrajs@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz#4c8dbdea1f0f6478bff94d9c49c784d623e4fc23"
|
||||
integrity sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==
|
||||
|
||||
dir-glob@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
|
||||
@ -2538,6 +2567,14 @@ fill-range@^7.1.1:
|
||||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
find-up@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
|
||||
integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
|
||||
dependencies:
|
||||
locate-path "^5.0.0"
|
||||
path-exists "^4.0.0"
|
||||
|
||||
find-up@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
|
||||
@ -2674,7 +2711,7 @@ gensync@^1.0.0-beta.2:
|
||||
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
|
||||
|
||||
get-caller-file@^2.0.5:
|
||||
get-caller-file@^2.0.1, get-caller-file@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
@ -3334,6 +3371,13 @@ localforage@^1.9.0:
|
||||
dependencies:
|
||||
lie "3.1.1"
|
||||
|
||||
locate-path@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
|
||||
integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
|
||||
dependencies:
|
||||
p-locate "^4.1.0"
|
||||
|
||||
locate-path@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
|
||||
@ -3727,6 +3771,13 @@ p-is-promise@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-3.0.0.tgz#58e78c7dfe2e163cf2a04ff869e7c1dba64a5971"
|
||||
integrity sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==
|
||||
|
||||
p-limit@^2.2.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
|
||||
integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
|
||||
dependencies:
|
||||
p-try "^2.0.0"
|
||||
|
||||
p-limit@^3.0.2:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
|
||||
@ -3734,6 +3785,13 @@ p-limit@^3.0.2:
|
||||
dependencies:
|
||||
yocto-queue "^0.1.0"
|
||||
|
||||
p-locate@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
|
||||
integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
|
||||
dependencies:
|
||||
p-limit "^2.2.0"
|
||||
|
||||
p-locate@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
|
||||
@ -3749,6 +3807,11 @@ p-some@^4.0.0:
|
||||
aggregate-error "^3.0.0"
|
||||
p-cancelable "^2.0.0"
|
||||
|
||||
p-try@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
|
||||
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
|
||||
|
||||
package-json-from-dist@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz#e501cd3094b278495eb4258d4c9f6d5ac3019f00"
|
||||
@ -3870,6 +3933,11 @@ pkg@5.8:
|
||||
resolve "^1.22.0"
|
||||
stream-meter "^1.0.4"
|
||||
|
||||
pngjs@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb"
|
||||
integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==
|
||||
|
||||
portfinder@^1.0.28:
|
||||
version "1.0.32"
|
||||
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.32.tgz#2fe1b9e58389712429dc2bea5beb2146146c7f81"
|
||||
@ -3970,6 +4038,15 @@ punycode@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
|
||||
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
|
||||
|
||||
qrcode@^1.5.4:
|
||||
version "1.5.4"
|
||||
resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.5.4.tgz#5cb81d86eb57c675febb08cf007fff963405da88"
|
||||
integrity sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==
|
||||
dependencies:
|
||||
dijkstrajs "^1.0.1"
|
||||
pngjs "^5.0.0"
|
||||
yargs "^15.3.1"
|
||||
|
||||
qs@^6.11.0, qs@^6.5.2:
|
||||
version "6.12.3"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.3.tgz#e43ce03c8521b9c7fd7f1f13e514e5ca37727754"
|
||||
@ -4041,6 +4118,11 @@ require-directory@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
|
||||
integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
|
||||
|
||||
require-main-filename@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
|
||||
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
|
||||
|
||||
resolve-from@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
||||
@ -4171,6 +4253,11 @@ semver@^7.3.5, semver@^7.3.6, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
|
||||
integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
|
||||
|
||||
set-blocking@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||
integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==
|
||||
|
||||
set-function-length@^1.2.1:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449"
|
||||
@ -4305,6 +4392,13 @@ spawn-command@0.0.2:
|
||||
resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2.tgz#9544e1a43ca045f8531aac1a48cb29bdae62338e"
|
||||
integrity sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==
|
||||
|
||||
speakeasy@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/speakeasy/-/speakeasy-2.0.0.tgz#85c91a071b09a5cb8642590d983566165f57613a"
|
||||
integrity sha512-lW2A2s5LKi8rwu77ewisuUOtlCydF/hmQSOJjpTqTj1gZLkNgTaYnyvfxy2WBr4T/h+9c4g8HIITfj83OkFQFw==
|
||||
dependencies:
|
||||
base32.js "0.0.1"
|
||||
|
||||
ssh2-sftp-client@^10.0.3:
|
||||
version "10.0.3"
|
||||
resolved "https://registry.yarnpkg.com/ssh2-sftp-client/-/ssh2-sftp-client-10.0.3.tgz#aa8f9b875b745a0b6108692f576343437e428a86"
|
||||
@ -4809,6 +4903,11 @@ whatwg-url@^5.0.0:
|
||||
tr46 "~0.0.3"
|
||||
webidl-conversions "^3.0.0"
|
||||
|
||||
which-module@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409"
|
||||
integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==
|
||||
|
||||
which-typed-array@^1.1.14, which-typed-array@^1.1.2:
|
||||
version "1.1.15"
|
||||
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d"
|
||||
@ -4841,6 +4940,15 @@ word-wrap@^1.2.5:
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
wrap-ansi@^6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
|
||||
integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
|
||||
dependencies:
|
||||
ansi-styles "^4.0.0"
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
wrap-ansi@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||
@ -4884,6 +4992,11 @@ xterm-theme@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/xterm-theme/-/xterm-theme-1.1.0.tgz#2e499c4dd6d2cf592c90389022095e1ce509bbbe"
|
||||
integrity sha512-n2GocBEbqcz4vEl4OYkU93hEVia8GWdnqchiz/0nQ/olRUyhulGf4wfha23x/D2m0imWaIavRZtt8c6kWZXdsA==
|
||||
|
||||
y18n@^4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
|
||||
integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
|
||||
|
||||
y18n@^5.0.5:
|
||||
version "5.0.8"
|
||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
|
||||
@ -4894,6 +5007,14 @@ yallist@^3.0.2:
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
||||
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
||||
|
||||
yargs-parser@^18.1.2:
|
||||
version "18.1.3"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
|
||||
integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
|
||||
dependencies:
|
||||
camelcase "^5.0.0"
|
||||
decamelize "^1.2.0"
|
||||
|
||||
yargs-parser@^20.2.2:
|
||||
version "20.2.9"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
|
||||
@ -4904,6 +5025,23 @@ yargs-parser@^21.1.1:
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
|
||||
integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
|
||||
|
||||
yargs@^15.3.1:
|
||||
version "15.4.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
|
||||
integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
|
||||
dependencies:
|
||||
cliui "^6.0.0"
|
||||
decamelize "^1.2.0"
|
||||
find-up "^4.1.0"
|
||||
get-caller-file "^2.0.1"
|
||||
require-directory "^2.1.1"
|
||||
require-main-filename "^2.0.0"
|
||||
set-blocking "^2.0.0"
|
||||
string-width "^4.2.0"
|
||||
which-module "^2.0.0"
|
||||
y18n "^4.0.0"
|
||||
yargs-parser "^18.1.2"
|
||||
|
||||
yargs@^16.2.0:
|
||||
version "16.2.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
|
||||
|
Loading…
x
Reference in New Issue
Block a user