mirror of
https://github.com/fatedier/frp.git
synced 2026-09-12 05:55:56 +08:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ac3d6545a |
+1
-3
@@ -1,3 +1 @@
|
|||||||
## Fixes
|
## Features
|
||||||
|
|
||||||
* Fixed a configuration-dependent authentication bypass in `type = "http"` proxies when `routeByHTTPUser` is used together with `httpUser` / `httpPassword`. This affected proxy-style requests. Proxy-style authentication failures now return `407 Proxy Authentication Required`.
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
package version
|
package version
|
||||||
|
|
||||||
var version = "0.68.1"
|
var version = "0.68.0"
|
||||||
|
|
||||||
func Full() string {
|
func Full() string {
|
||||||
return version
|
return version
|
||||||
|
|||||||
+20
-39
@@ -187,25 +187,16 @@ func (rp *HTTPReverseProxy) CreateConnection(reqRouteInfo *RequestRouteInfo, byE
|
|||||||
return nil, fmt.Errorf("%v: %s %s %s", ErrNoRouteFound, host, reqRouteInfo.URL, reqRouteInfo.HTTPUser)
|
return nil, fmt.Errorf("%v: %s %s %s", ErrNoRouteFound, host, reqRouteInfo.URL, reqRouteInfo.HTTPUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkRouteAuthByRequest(req *http.Request, rc *RouteConfig) bool {
|
func (rp *HTTPReverseProxy) CheckAuth(domain, location, routeByHTTPUser, user, passwd string) bool {
|
||||||
if rc == nil {
|
vr, ok := rp.getVhost(domain, location, routeByHTTPUser)
|
||||||
return true
|
if ok {
|
||||||
}
|
checkUser := vr.payload.(*RouteConfig).Username
|
||||||
if rc.Username == "" && rc.Password == "" {
|
checkPasswd := vr.payload.(*RouteConfig).Password
|
||||||
return true
|
if (checkUser != "" || checkPasswd != "") && (checkUser != user || checkPasswd != passwd) {
|
||||||
}
|
|
||||||
|
|
||||||
if req.URL.Host != "" {
|
|
||||||
proxyAuth := req.Header.Get("Proxy-Authorization")
|
|
||||||
if proxyAuth == "" {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
user, passwd, ok := httppkg.ParseBasicAuth(proxyAuth)
|
|
||||||
return ok && user == rc.Username && passwd == rc.Password
|
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
user, passwd, ok := req.BasicAuth()
|
|
||||||
return ok && user == rc.Username && passwd == rc.Password
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getVhost tries to get vhost router by route policy.
|
// getVhost tries to get vhost router by route policy.
|
||||||
@@ -275,25 +266,18 @@ func (rp *HTTPReverseProxy) connectHandler(rw http.ResponseWriter, req *http.Req
|
|||||||
go libio.Join(remote, client)
|
go libio.Join(remote, client)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRequestRouteUser(req *http.Request) string {
|
func (rp *HTTPReverseProxy) injectRequestInfoToCtx(req *http.Request) *http.Request {
|
||||||
|
user := ""
|
||||||
|
// If url host isn't empty, it's a proxy request. Get http user from Proxy-Authorization header.
|
||||||
if req.URL.Host != "" {
|
if req.URL.Host != "" {
|
||||||
proxyAuth := req.Header.Get("Proxy-Authorization")
|
proxyAuth := req.Header.Get("Proxy-Authorization")
|
||||||
if proxyAuth == "" {
|
if proxyAuth != "" {
|
||||||
// Preserve legacy proxy-mode routing when clients send only Authorization,
|
user, _, _ = httppkg.ParseBasicAuth(proxyAuth)
|
||||||
// so requests still hit the matched route and return 407 instead of 404.
|
|
||||||
// Auth validation intentionally does not share this fallback.
|
|
||||||
user, _, _ := req.BasicAuth()
|
|
||||||
return user
|
|
||||||
}
|
}
|
||||||
user, _, _ := httppkg.ParseBasicAuth(proxyAuth)
|
|
||||||
return user
|
|
||||||
}
|
}
|
||||||
user, _, _ := req.BasicAuth()
|
if user == "" {
|
||||||
return user
|
user, _, _ = req.BasicAuth()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rp *HTTPReverseProxy) injectRequestInfoToCtx(req *http.Request) *http.Request {
|
|
||||||
user := getRequestRouteUser(req)
|
|
||||||
|
|
||||||
reqRouteInfo := &RequestRouteInfo{
|
reqRouteInfo := &RequestRouteInfo{
|
||||||
URL: req.URL.Path,
|
URL: req.URL.Path,
|
||||||
@@ -313,19 +297,16 @@ func (rp *HTTPReverseProxy) injectRequestInfoToCtx(req *http.Request) *http.Requ
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (rp *HTTPReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
func (rp *HTTPReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
newreq := rp.injectRequestInfoToCtx(req)
|
domain, _ := httppkg.CanonicalHost(req.Host)
|
||||||
rc := newreq.Context().Value(RouteConfigKey).(*RouteConfig)
|
location := req.URL.Path
|
||||||
if !checkRouteAuthByRequest(req, rc) {
|
user, passwd, _ := req.BasicAuth()
|
||||||
if req.URL.Host != "" {
|
if !rp.CheckAuth(domain, location, user, user, passwd) {
|
||||||
rw.Header().Set("Proxy-Authenticate", `Basic realm="Restricted"`)
|
|
||||||
http.Error(rw, http.StatusText(http.StatusProxyAuthRequired), http.StatusProxyAuthRequired)
|
|
||||||
} else {
|
|
||||||
rw.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
|
rw.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
|
||||||
http.Error(rw, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
http.Error(rw, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newreq := rp.injectRequestInfoToCtx(req)
|
||||||
if req.Method == http.MethodConnect {
|
if req.Method == http.MethodConnect {
|
||||||
rp.connectHandler(rw, newreq)
|
rp.connectHandler(rw, newreq)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,102 +0,0 @@
|
|||||||
package vhost
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http/httptest"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
httppkg "github.com/fatedier/frp/pkg/util/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCheckRouteAuthByRequest(t *testing.T) {
|
|
||||||
rc := &RouteConfig{
|
|
||||||
Username: "alice",
|
|
||||||
Password: "secret",
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Run("accepts nil route config", func(t *testing.T) {
|
|
||||||
req := httptest.NewRequest("GET", "/", nil)
|
|
||||||
require.True(t, checkRouteAuthByRequest(req, nil))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("accepts route without credentials", func(t *testing.T) {
|
|
||||||
req := httptest.NewRequest("GET", "/", nil)
|
|
||||||
require.True(t, checkRouteAuthByRequest(req, &RouteConfig{}))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("accepts authorization header", func(t *testing.T) {
|
|
||||||
req := httptest.NewRequest("GET", "/", nil)
|
|
||||||
req.SetBasicAuth("alice", "secret")
|
|
||||||
require.True(t, checkRouteAuthByRequest(req, rc))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("accepts proxy authorization header", func(t *testing.T) {
|
|
||||||
req := httptest.NewRequest("GET", "http://target.example.com/", nil)
|
|
||||||
req.Header.Set("Proxy-Authorization", httppkg.BasicAuth("alice", "secret"))
|
|
||||||
require.True(t, checkRouteAuthByRequest(req, rc))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("rejects authorization fallback for proxy request", func(t *testing.T) {
|
|
||||||
req := httptest.NewRequest("GET", "http://target.example.com/", nil)
|
|
||||||
req.SetBasicAuth("alice", "secret")
|
|
||||||
require.False(t, checkRouteAuthByRequest(req, rc))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("rejects wrong proxy authorization even when authorization matches", func(t *testing.T) {
|
|
||||||
req := httptest.NewRequest("GET", "http://target.example.com/", nil)
|
|
||||||
req.SetBasicAuth("alice", "secret")
|
|
||||||
req.Header.Set("Proxy-Authorization", httppkg.BasicAuth("alice", "wrong"))
|
|
||||||
require.False(t, checkRouteAuthByRequest(req, rc))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("rejects when neither header matches", func(t *testing.T) {
|
|
||||||
req := httptest.NewRequest("GET", "http://target.example.com/", nil)
|
|
||||||
req.SetBasicAuth("alice", "wrong")
|
|
||||||
req.Header.Set("Proxy-Authorization", httppkg.BasicAuth("alice", "wrong"))
|
|
||||||
require.False(t, checkRouteAuthByRequest(req, rc))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("rejects proxy authorization on direct request", func(t *testing.T) {
|
|
||||||
req := httptest.NewRequest("GET", "/", nil)
|
|
||||||
req.Header.Set("Proxy-Authorization", httppkg.BasicAuth("alice", "secret"))
|
|
||||||
require.False(t, checkRouteAuthByRequest(req, rc))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetRequestRouteUser(t *testing.T) {
|
|
||||||
t.Run("proxy request uses proxy authorization username", func(t *testing.T) {
|
|
||||||
req := httptest.NewRequest("GET", "http://target.example.com/", nil)
|
|
||||||
req.Host = "target.example.com"
|
|
||||||
req.Header.Set("Proxy-Authorization", httppkg.BasicAuth("proxy-user", "proxy-pass"))
|
|
||||||
req.SetBasicAuth("direct-user", "direct-pass")
|
|
||||||
|
|
||||||
require.Equal(t, "proxy-user", getRequestRouteUser(req))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("connect request keeps proxy authorization routing", func(t *testing.T) {
|
|
||||||
req := httptest.NewRequest("CONNECT", "http://target.example.com:443", nil)
|
|
||||||
req.Host = "target.example.com:443"
|
|
||||||
req.Header.Set("Proxy-Authorization", httppkg.BasicAuth("proxy-user", "proxy-pass"))
|
|
||||||
req.SetBasicAuth("direct-user", "direct-pass")
|
|
||||||
|
|
||||||
require.Equal(t, "proxy-user", getRequestRouteUser(req))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("direct request uses authorization username", func(t *testing.T) {
|
|
||||||
req := httptest.NewRequest("GET", "/", nil)
|
|
||||||
req.Host = "example.com"
|
|
||||||
req.SetBasicAuth("direct-user", "direct-pass")
|
|
||||||
|
|
||||||
require.Equal(t, "direct-user", getRequestRouteUser(req))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("proxy request does not fall back when proxy authorization is invalid", func(t *testing.T) {
|
|
||||||
req := httptest.NewRequest("GET", "http://target.example.com/", nil)
|
|
||||||
req.Host = "target.example.com"
|
|
||||||
req.Header.Set("Proxy-Authorization", "Basic !!!")
|
|
||||||
req.SetBasicAuth("direct-user", "direct-pass")
|
|
||||||
|
|
||||||
require.Empty(t, getRequestRouteUser(req))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -144,79 +144,6 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
|
|||||||
Ensure()
|
Ensure()
|
||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("HTTP proxy mode uses proxy auth consistently", func() {
|
|
||||||
vhostHTTPPort := f.AllocPort()
|
|
||||||
serverConf := getDefaultServerConf(vhostHTTPPort)
|
|
||||||
|
|
||||||
backendPort := f.AllocPort()
|
|
||||||
f.RunServer("", newHTTPServer(backendPort, "PRIVATE"))
|
|
||||||
|
|
||||||
clientConf := consts.DefaultClientConfig
|
|
||||||
clientConf += fmt.Sprintf(`
|
|
||||||
[[proxies]]
|
|
||||||
name = "protected"
|
|
||||||
type = "http"
|
|
||||||
localPort = %d
|
|
||||||
customDomains = ["normal.example.com"]
|
|
||||||
routeByHTTPUser = "alice"
|
|
||||||
httpUser = "alice"
|
|
||||||
httpPassword = "secret"
|
|
||||||
`, backendPort)
|
|
||||||
|
|
||||||
f.RunProcesses(serverConf, []string{clientConf})
|
|
||||||
|
|
||||||
proxyURLWithAuth := func(username, password string) string {
|
|
||||||
if username == "" {
|
|
||||||
return fmt.Sprintf("http://127.0.0.1:%d", vhostHTTPPort)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("http://%s:%s@127.0.0.1:%d", username, password, vhostHTTPPort)
|
|
||||||
}
|
|
||||||
|
|
||||||
framework.NewRequestExpect(f).Explain("direct no auth").Port(vhostHTTPPort).
|
|
||||||
RequestModify(func(r *request.Request) {
|
|
||||||
r.HTTP().HTTPHost("normal.example.com")
|
|
||||||
}).
|
|
||||||
Ensure(framework.ExpectResponseCode(http.StatusNotFound))
|
|
||||||
|
|
||||||
framework.NewRequestExpect(f).Explain("direct correct auth").Port(vhostHTTPPort).
|
|
||||||
RequestModify(func(r *request.Request) {
|
|
||||||
r.HTTP().HTTPHost("normal.example.com").HTTPAuth("alice", "secret")
|
|
||||||
}).
|
|
||||||
ExpectResp([]byte("PRIVATE")).
|
|
||||||
Ensure()
|
|
||||||
|
|
||||||
framework.NewRequestExpect(f).Explain("direct wrong auth").Port(vhostHTTPPort).
|
|
||||||
RequestModify(func(r *request.Request) {
|
|
||||||
r.HTTP().HTTPHost("normal.example.com").HTTPAuth("alice", "wrong")
|
|
||||||
}).
|
|
||||||
Ensure(framework.ExpectResponseCode(http.StatusUnauthorized))
|
|
||||||
|
|
||||||
framework.NewRequestExpect(f).Explain("proxy correct proxy auth").
|
|
||||||
RequestModify(func(r *request.Request) {
|
|
||||||
r.HTTP().Addr("normal.example.com").Proxy(proxyURLWithAuth("alice", "secret"))
|
|
||||||
}).
|
|
||||||
ExpectResp([]byte("PRIVATE")).
|
|
||||||
Ensure()
|
|
||||||
|
|
||||||
framework.NewRequestExpect(f).Explain("proxy wrong proxy auth").
|
|
||||||
RequestModify(func(r *request.Request) {
|
|
||||||
r.HTTP().Addr("normal.example.com").Proxy(proxyURLWithAuth("alice", "wrong"))
|
|
||||||
}).
|
|
||||||
Ensure(framework.ExpectResponseCode(http.StatusProxyAuthRequired))
|
|
||||||
|
|
||||||
framework.NewRequestExpect(f).Explain("proxy request ignores authorization header").
|
|
||||||
RequestModify(func(r *request.Request) {
|
|
||||||
r.HTTP().Addr("normal.example.com").Proxy(proxyURLWithAuth("", "")).HTTPAuth("alice", "secret")
|
|
||||||
}).
|
|
||||||
Ensure(framework.ExpectResponseCode(http.StatusProxyAuthRequired))
|
|
||||||
|
|
||||||
framework.NewRequestExpect(f).Explain("proxy wrong proxy auth with correct authorization").
|
|
||||||
RequestModify(func(r *request.Request) {
|
|
||||||
r.HTTP().Addr("normal.example.com").Proxy(proxyURLWithAuth("alice", "wrong")).HTTPAuth("alice", "secret")
|
|
||||||
}).
|
|
||||||
Ensure(framework.ExpectResponseCode(http.StatusProxyAuthRequired))
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("HTTP Basic Auth", func() {
|
ginkgo.It("HTTP Basic Auth", func() {
|
||||||
vhostHTTPPort := f.AllocPort()
|
vhostHTTPPort := f.AllocPort()
|
||||||
serverConf := getDefaultServerConf(vhostHTTPPort)
|
serverConf := getDefaultServerConf(vhostHTTPPort)
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
import { createRouter, createWebHashHistory } from 'vue-router'
|
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import ClientConfigure from '../views/ClientConfigure.vue'
|
import ClientConfigure from '../views/ClientConfigure.vue'
|
||||||
import ProxyDetail from '../views/ProxyDetail.vue'
|
|
||||||
import ProxyEdit from '../views/ProxyEdit.vue'
|
import ProxyEdit from '../views/ProxyEdit.vue'
|
||||||
import ProxyList from '../views/ProxyList.vue'
|
|
||||||
import VisitorDetail from '../views/VisitorDetail.vue'
|
|
||||||
import VisitorEdit from '../views/VisitorEdit.vue'
|
import VisitorEdit from '../views/VisitorEdit.vue'
|
||||||
import VisitorList from '../views/VisitorList.vue'
|
|
||||||
import { useProxyStore } from '../stores/proxy'
|
import { useProxyStore } from '../stores/proxy'
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
@@ -19,12 +15,12 @@ const router = createRouter({
|
|||||||
{
|
{
|
||||||
path: '/proxies',
|
path: '/proxies',
|
||||||
name: 'ProxyList',
|
name: 'ProxyList',
|
||||||
component: ProxyList,
|
component: () => import('../views/ProxyList.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/proxies/detail/:name',
|
path: '/proxies/detail/:name',
|
||||||
name: 'ProxyDetail',
|
name: 'ProxyDetail',
|
||||||
component: ProxyDetail,
|
component: () => import('../views/ProxyDetail.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/proxies/create',
|
path: '/proxies/create',
|
||||||
@@ -41,12 +37,12 @@ const router = createRouter({
|
|||||||
{
|
{
|
||||||
path: '/visitors',
|
path: '/visitors',
|
||||||
name: 'VisitorList',
|
name: 'VisitorList',
|
||||||
component: VisitorList,
|
component: () => import('../views/VisitorList.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/visitors/detail/:name',
|
path: '/visitors/detail/:name',
|
||||||
name: 'VisitorDetail',
|
name: 'VisitorDetail',
|
||||||
component: VisitorDetail,
|
component: () => import('../views/VisitorDetail.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/visitors/create',
|
path: '/visitors/create',
|
||||||
|
|||||||
Generated
+81
-61
@@ -640,10 +640,11 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/config-array/node_modules/brace-expansion": {
|
"node_modules/@eslint/config-array/node_modules/brace-expansion": {
|
||||||
"version": "1.1.14",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
"integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -720,10 +721,11 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
|
"node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
|
||||||
"version": "1.1.14",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
"integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -1335,10 +1337,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher/node_modules/picomatch": {
|
"node_modules/@parcel/watcher/node_modules/picomatch": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||||
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
@@ -1402,10 +1405,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/pluginutils/node_modules/picomatch": {
|
"node_modules/@rollup/pluginutils/node_modules/picomatch": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||||
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
@@ -2251,10 +2255,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/language-core/node_modules/picomatch": {
|
"node_modules/@vue/language-core/node_modules/picomatch": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||||
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
@@ -2567,10 +2572,11 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "5.0.5",
|
"version": "5.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz",
|
||||||
"integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
|
"integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^4.0.2"
|
"balanced-match": "^4.0.2"
|
||||||
},
|
},
|
||||||
@@ -3099,10 +3105,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/defu": {
|
"node_modules/defu": {
|
||||||
"version": "6.1.7",
|
"version": "6.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
|
||||||
"integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==",
|
"integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/destr": {
|
"node_modules/destr": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
@@ -3748,10 +3755,11 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/eslint/node_modules/brace-expansion": {
|
"node_modules/eslint/node_modules/brace-expansion": {
|
||||||
"version": "1.1.14",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
"integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -4990,14 +4998,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lodash": {
|
"node_modules/lodash": {
|
||||||
"version": "4.18.1",
|
"version": "4.17.23",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
|
||||||
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="
|
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/lodash-es": {
|
"node_modules/lodash-es": {
|
||||||
"version": "4.18.1",
|
"version": "4.17.23",
|
||||||
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz",
|
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz",
|
||||||
"integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A=="
|
"integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/lodash-unified": {
|
"node_modules/lodash-unified": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
@@ -5264,10 +5274,11 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/npm-run-all/node_modules/brace-expansion": {
|
"node_modules/npm-run-all/node_modules/brace-expansion": {
|
||||||
"version": "1.1.14",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
"integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -5675,10 +5686,11 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/picomatch": {
|
"node_modules/picomatch": {
|
||||||
"version": "2.3.2",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||||
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.6"
|
"node": ">=8.6"
|
||||||
},
|
},
|
||||||
@@ -6723,10 +6735,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tinyglobby/node_modules/picomatch": {
|
"node_modules/tinyglobby/node_modules/picomatch": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||||
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
@@ -6952,10 +6965,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/unctx/node_modules/picomatch": {
|
"node_modules/unctx/node_modules/picomatch": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||||
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
@@ -7070,10 +7084,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/unimport/node_modules/picomatch": {
|
"node_modules/unimport/node_modules/picomatch": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||||
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
@@ -7138,10 +7153,11 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/unplugin-auto-import/node_modules/brace-expansion": {
|
"node_modules/unplugin-auto-import/node_modules/brace-expansion": {
|
||||||
"version": "2.1.0",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||||
"integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
|
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0"
|
"balanced-match": "^1.0.0"
|
||||||
}
|
}
|
||||||
@@ -7242,10 +7258,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/unplugin-element-plus/node_modules/picomatch": {
|
"node_modules/unplugin-element-plus/node_modules/picomatch": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||||
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
@@ -7327,10 +7344,11 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/unplugin-vue-components/node_modules/brace-expansion": {
|
"node_modules/unplugin-vue-components/node_modules/brace-expansion": {
|
||||||
"version": "2.1.0",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||||
"integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
|
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0"
|
"balanced-match": "^1.0.0"
|
||||||
}
|
}
|
||||||
@@ -7461,10 +7479,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "7.3.2",
|
"version": "7.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
|
||||||
"integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==",
|
"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.27.0",
|
"esbuild": "^0.27.0",
|
||||||
"fdir": "^6.5.0",
|
"fdir": "^6.5.0",
|
||||||
@@ -7567,10 +7586,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/picomatch": {
|
"node_modules/vite/node_modules/picomatch": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||||
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user