mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-13 00:00:36 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72d95f8170 | ||
|
|
e90b201001 |
@@ -526,8 +526,10 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
|
||||
website.SiteDir = create.SiteDir
|
||||
}
|
||||
|
||||
createdFiles := &websiteCreateFiles{}
|
||||
configNginx := func(t *task.Task) error {
|
||||
if err = configDefaultNginx(website, domains, appInstall, runtime, create.StreamConfig, initialSSL); err != nil {
|
||||
return err
|
||||
}
|
||||
if create.Type == constant.Static && create.TemplateOutputID > 0 {
|
||||
templateOutput, err := websiteTemplateOutputRepo.GetFirst(repo.WithByID(create.TemplateOutputID))
|
||||
if err != nil {
|
||||
@@ -539,15 +541,12 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
|
||||
if _, err := os.Stat(templateOutput.OutputPath); err != nil {
|
||||
return buserr.New("ErrFileNotFound")
|
||||
}
|
||||
if err := createdFiles.copyTemplate(templateOutput.OutputPath, GetSitePath(*website, SiteIndexDir)); err != nil {
|
||||
if err := copyDir(templateOutput.OutputPath, GetSitePath(*website, SiteIndexDir)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err = configDefaultNginx(website, domains, appInstall, runtime, create.StreamConfig, initialSSL, createdFiles); err != nil {
|
||||
return err
|
||||
}
|
||||
if website.Type != constant.Stream {
|
||||
if err = createWafConfig(website, domains, createdFiles); err != nil {
|
||||
if err = createWafConfig(website, domains); err != nil {
|
||||
return err
|
||||
}
|
||||
if create.Type == constant.Runtime {
|
||||
@@ -556,9 +555,7 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
|
||||
return err
|
||||
}
|
||||
if runtime.Type == constant.RuntimePHP && runtime.Resource == constant.ResourceAppstore {
|
||||
if err := createdFiles.write(path.Join(GetSitePath(*website, SiteIndexDir), ".user.ini"), []byte(fmt.Sprintf("open_basedir=/www/sites/%s/index:/tmp/", website.Alias)), 0644, true); err != nil {
|
||||
return err
|
||||
}
|
||||
createOpenBasedirConfig(website)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -578,19 +575,12 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
|
||||
}
|
||||
}
|
||||
|
||||
if err := tx.Commit().Error; err != nil {
|
||||
return err
|
||||
}
|
||||
tx.Commit()
|
||||
return nil
|
||||
}
|
||||
|
||||
deleteWebsite := func(t *task.Task) {
|
||||
if rollbackErr := createdFiles.rollback(); rollbackErr != nil {
|
||||
t.Log(fmt.Sprintf("website file rollback: %v", rollbackErr))
|
||||
}
|
||||
if reloadErr := opNginx(nginxInstall.ContainerName, constant.NginxReload); reloadErr != nil {
|
||||
t.Log(fmt.Sprintf("reload OpenResty after rollback: %v", reloadErr))
|
||||
}
|
||||
_ = deleteWebsiteFolder(website)
|
||||
}
|
||||
|
||||
createTask.AddSubTask(i18n.GetMsgByKey("ConfigOpenresty"), configNginx, deleteWebsite)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
@@ -15,7 +14,6 @@ import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -126,255 +124,7 @@ func applyLocationProxyPass(location *components.Location, proxyPass string, sni
|
||||
location.UpdateDirective("proxy_ssl_name", []string{sslName})
|
||||
}
|
||||
|
||||
// websiteCreateFiles owns only paths actually created by this attempt.
|
||||
// Never recursively remove a reused directory (or a newly populated one).
|
||||
type websiteCreateFiles struct {
|
||||
mu sync.Mutex
|
||||
entries []websiteCreatedPath
|
||||
rolledBack bool
|
||||
restores []func() error
|
||||
}
|
||||
type websiteCreatedPath struct {
|
||||
path string
|
||||
info os.FileInfo
|
||||
}
|
||||
|
||||
func (f *websiteCreateFiles) mkdir(name string) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if f.rolledBack {
|
||||
return fmt.Errorf("website creation already rolled back")
|
||||
}
|
||||
return f.mkdirLocked(filepath.Clean(name))
|
||||
}
|
||||
|
||||
func (f *websiteCreateFiles) mkdirLocked(name string) error {
|
||||
info, err := os.Lstat(name)
|
||||
if err == nil {
|
||||
if !info.IsDir() {
|
||||
return fmt.Errorf("website path is not a directory: %s", name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
if err = f.mkdirLocked(filepath.Dir(name)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = os.Mkdir(name, constant.DirPerm); err != nil {
|
||||
if os.IsExist(err) {
|
||||
return f.mkdirLocked(name)
|
||||
}
|
||||
return err
|
||||
}
|
||||
info, err = os.Lstat(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.entries = append(f.entries, websiteCreatedPath{name, info})
|
||||
return nil
|
||||
}
|
||||
|
||||
// preserveExisting is for user content and logs; generated configuration must
|
||||
// fail on collision. Exclusive creation also protects against concurrent writes.
|
||||
func (f *websiteCreateFiles) write(name string, data []byte, mode os.FileMode, preserveExisting bool) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if f.rolledBack {
|
||||
return fmt.Errorf("website creation already rolled back")
|
||||
}
|
||||
if err := f.mkdirLocked(filepath.Dir(name)); err != nil {
|
||||
return err
|
||||
}
|
||||
file, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_EXCL, mode)
|
||||
if os.IsExist(err) && preserveExisting {
|
||||
info, statErr := os.Lstat(name)
|
||||
if statErr != nil {
|
||||
return statErr
|
||||
}
|
||||
if !info.Mode().IsRegular() {
|
||||
return fmt.Errorf("website path is not a regular file: %s", name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("create website file %s: %w", name, err)
|
||||
}
|
||||
info, err := file.Stat()
|
||||
if err != nil {
|
||||
_ = file.Close()
|
||||
return err
|
||||
}
|
||||
f.entries = append(f.entries, websiteCreatedPath{name, info})
|
||||
_, err = file.Write(data)
|
||||
closeErr := file.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return closeErr
|
||||
}
|
||||
|
||||
func (f *websiteCreateFiles) rollback() error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
f.rolledBack = true
|
||||
var firstErr error
|
||||
for i := len(f.restores) - 1; i >= 0; i-- {
|
||||
if err := f.restores[i](); err != nil && firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
f.restores = nil
|
||||
for i := len(f.entries) - 1; i >= 0; i-- {
|
||||
entry := f.entries[i]
|
||||
info, err := os.Lstat(entry.path)
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
if firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
continue
|
||||
}
|
||||
if !os.SameFile(entry.info, info) {
|
||||
continue
|
||||
}
|
||||
// os.Remove refuses non-empty directories, preserving untracked content.
|
||||
if err = os.Remove(entry.path); err != nil && firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
return firstErr
|
||||
}
|
||||
|
||||
func (f *websiteCreateFiles) copyTemplate(src, dst string) error {
|
||||
// Check the entire template before copying any files. Reject symlinks and
|
||||
// collisions rather than truncating existing content.
|
||||
err := filepath.Walk(src, func(name string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rel, err := filepath.Rel(src, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
target := filepath.Join(dst, rel)
|
||||
if !info.IsDir() && !info.Mode().IsRegular() {
|
||||
return fmt.Errorf("unsupported template file: %s", name)
|
||||
}
|
||||
existing, err := os.Lstat(target)
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.IsDir() && existing.IsDir() {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("website template path already exists: %s", target)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return filepath.Walk(src, func(name string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rel, err := filepath.Rel(src, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
target := filepath.Join(dst, rel)
|
||||
if info.IsDir() {
|
||||
return f.mkdir(target)
|
||||
}
|
||||
if !info.Mode().IsRegular() {
|
||||
return fmt.Errorf("unsupported template file: %s", name)
|
||||
}
|
||||
data, err := os.ReadFile(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return f.write(target, data, constant.FilePerm, false)
|
||||
})
|
||||
}
|
||||
|
||||
// Only change ownership on files created by this attempt, never recursively on
|
||||
// an existing document root.
|
||||
func (f *websiteCreateFiles) chownNew(root string) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if f.rolledBack {
|
||||
return fmt.Errorf("website creation already rolled back")
|
||||
}
|
||||
for _, entry := range f.entries {
|
||||
rel, err := filepath.Rel(root, entry.path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rel == ".." || filepath.IsAbs(rel) || (len(rel) > 3 && rel[:3] == "../") {
|
||||
continue
|
||||
}
|
||||
info, err := os.Lstat(entry.path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !os.SameFile(entry.info, info) {
|
||||
continue
|
||||
}
|
||||
if err := os.Chown(entry.path, constant.WebsiteUID, constant.WebsiteGID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shared WAF metadata is restored only while it still contains our exact write.
|
||||
// Never restore a stale snapshot over changes made by another operation.
|
||||
func (f *websiteCreateFiles) replaceShared(name string, before, after []byte) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if f.rolledBack {
|
||||
return fmt.Errorf("website creation already rolled back")
|
||||
}
|
||||
info, err := os.Lstat(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.Mode().IsRegular() {
|
||||
return fmt.Errorf("website config is not a regular file: %s", name)
|
||||
}
|
||||
current, err := os.ReadFile(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !bytes.Equal(current, before) {
|
||||
return fmt.Errorf("website config changed during creation: %s", name)
|
||||
}
|
||||
f.restores = append(f.restores, func() error {
|
||||
now, err := os.Lstat(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !os.SameFile(info, now) {
|
||||
return fmt.Errorf("website config replaced; skipping rollback: %s", name)
|
||||
}
|
||||
data, err := os.ReadFile(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !bytes.Equal(data, after) {
|
||||
return fmt.Errorf("website config changed; skipping rollback: %s", name)
|
||||
}
|
||||
return os.WriteFile(name, before, info.Mode().Perm())
|
||||
})
|
||||
return os.WriteFile(name, after, info.Mode().Perm())
|
||||
}
|
||||
|
||||
func createIndexFile(website *model.Website, runtime *model.Runtime, created *websiteCreateFiles) error {
|
||||
func createIndexFile(website *model.Website, runtime *model.Runtime) error {
|
||||
var (
|
||||
indexPath string
|
||||
indexContent string
|
||||
@@ -395,23 +145,49 @@ func createIndexFile(website *model.Website, runtime *model.Runtime, created *we
|
||||
}
|
||||
}
|
||||
|
||||
if err := created.write(indexPath, []byte(indexContent), constant.FilePerm, true); err != nil {
|
||||
return err
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(indexFolder) {
|
||||
if err := fileOp.CreateDir(indexFolder, constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
html404, _ := websiteService.GetDefaultHtml("404")
|
||||
if err := created.write(path.Join(indexFolder, "404.html"), []byte(html404.Content), constant.FilePerm, true); err != nil {
|
||||
return err
|
||||
if !fileOp.Stat(indexPath) {
|
||||
if err := fileOp.CreateFile(indexPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if website.Type == constant.Runtime && runtime.Resource == constant.ResourceAppstore {
|
||||
return created.chownNew(indexFolder)
|
||||
if err := chownRootDir(indexFolder); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := fileOp.WriteFile(indexPath, strings.NewReader(indexContent), constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
html404, _ := websiteService.GetDefaultHtml("404")
|
||||
path404 := path.Join(indexFolder, "404.html")
|
||||
if err := fileOp.WriteFile(path404, strings.NewReader(html404.Content), constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createProxyFile(website *model.Website, created *websiteCreateFiles) error {
|
||||
func createProxyFile(website *model.Website) error {
|
||||
proxyFolder := GetSitePath(*website, SiteProxyDir)
|
||||
filePath := path.Join(proxyFolder, "root.conf")
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(proxyFolder) {
|
||||
if err := fileOp.CreateDir(proxyFolder, constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if !fileOp.Stat(filePath) {
|
||||
if err := fileOp.CreateFile(filePath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
config, err := parser.NewStringParser(string(nginx_conf.Proxy)).Parse()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -425,40 +201,57 @@ func createProxyFile(website *model.Website, created *websiteCreateFiles) error
|
||||
location.ChangePath("^~", "/")
|
||||
applyLocationProxyPass(location, website.Proxy, nil, "")
|
||||
location.UpdateDirective("proxy_set_header", []string{"Host", "$host"})
|
||||
if err := created.write(filePath, []byte(nginx.DumpConfig(config, nginx.IndentedStyle)), constant.FilePerm, false); err != nil {
|
||||
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
||||
return buserr.WithErr("ErrUpdateBuWebsite", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createWebsiteFolder(website *model.Website, runtime *model.Runtime, created *websiteCreateFiles) error {
|
||||
func createWebsiteFolder(website *model.Website, runtime *model.Runtime) error {
|
||||
siteFolder := GetSiteDir(website.Alias)
|
||||
dirs := []string{siteFolder, path.Join(siteFolder, "log")}
|
||||
if website.Type != constant.Stream {
|
||||
dirs = append(dirs, path.Join(siteFolder, "index"), path.Join(siteFolder, "ssl"))
|
||||
}
|
||||
for _, dir := range dirs {
|
||||
if err := created.mkdir(dir); err != nil {
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(siteFolder) {
|
||||
if err := fileOp.CreateDir(siteFolder, constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, name := range []string{"access.log", "error.log"} {
|
||||
if err := created.write(path.Join(siteFolder, "log", name), nil, constant.FilePerm, true); err != nil {
|
||||
if err := fileOp.CreateDir(path.Join(siteFolder, "log"), constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if website.Type == constant.Runtime && runtime.Type == constant.RuntimePHP && runtime.Resource == constant.ResourceLocal {
|
||||
if err := created.write(path.Join(siteFolder, "php-pool", "php-fpm.sock"), nil, constant.FilePerm, true); err != nil {
|
||||
if err := fileOp.CreateFile(path.Join(siteFolder, "log", "access.log")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if website.Type == constant.Static || (website.Type == constant.Runtime && runtime.Type == constant.RuntimePHP) {
|
||||
if err := createIndexFile(website, runtime, created); err != nil {
|
||||
if err := fileOp.CreateFile(path.Join(siteFolder, "log", "error.log")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if website.Type == constant.Proxy {
|
||||
return createProxyFile(website, created)
|
||||
if website.Type != constant.Stream {
|
||||
if err := fileOp.CreateDir(path.Join(siteFolder, "index"), constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fileOp.CreateDir(path.Join(siteFolder, "ssl"), constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if website.Type == constant.Runtime {
|
||||
if runtime.Type == constant.RuntimePHP && runtime.Resource == constant.ResourceLocal {
|
||||
phpPoolDir := path.Join(siteFolder, "php-pool")
|
||||
if err := fileOp.CreateDir(phpPoolDir, constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fileOp.CreateFile(path.Join(phpPoolDir, "php-fpm.sock")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if website.Type == constant.Static || (website.Type == constant.Runtime && runtime.Type == constant.RuntimePHP) {
|
||||
if err := createIndexFile(website, runtime); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if website.Type == constant.Proxy {
|
||||
if err := createProxyFile(website); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -468,12 +261,12 @@ type websiteInitialSSL struct {
|
||||
request request.WebsiteHTTPSOp
|
||||
}
|
||||
|
||||
func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, appInstall *model.AppInstall, runtime *model.Runtime, streamConfig request.StreamConfig, initialSSL *websiteInitialSSL, created *websiteCreateFiles) error {
|
||||
func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, appInstall *model.AppInstall, runtime *model.Runtime, streamConfig request.StreamConfig, initialSSL *websiteInitialSSL) error {
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = createWebsiteFolder(website, runtime, created); err != nil {
|
||||
if err = createWebsiteFolder(website, runtime); err != nil {
|
||||
return err
|
||||
}
|
||||
var (
|
||||
@@ -541,10 +334,7 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
|
||||
if initialSSL != nil {
|
||||
plan := buildWebsiteTLSPlan(domains, nginxInstall.HttpPort, nginxInstall.HttpsPort)
|
||||
applyWebsiteSSLConfig(server, *website, plan, initialSSL.request)
|
||||
if err = created.write(path.Join(GetSitePath(*website, SiteSSLDir), "fullchain.pem"), []byte(initialSSL.certificate.Pem), constant.FilePerm, false); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = created.write(path.Join(GetSitePath(*website, SiteSSLDir), "privkey.pem"), []byte(initialSSL.certificate.PrivateKey), 0600, false); err != nil {
|
||||
if err = createPemFile(*website, initialSSL.certificate); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -614,7 +404,7 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
|
||||
}
|
||||
}
|
||||
config.FilePath = configPath
|
||||
if err = created.write(configPath, []byte(nginx.DumpConfig(config, nginx.IndentedStyle)), constant.FilePerm, false); err != nil {
|
||||
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = opNginx(nginxInstall.ContainerName, constant.NginxCheck); err != nil {
|
||||
@@ -709,7 +499,7 @@ func createOpenBasedirConfig(website *model.Website) {
|
||||
_ = fileOp.SaveFile(userIniPath, fmt.Sprintf("open_basedir=/www/sites/%s/index:/tmp/", website.Alias), 0644)
|
||||
}
|
||||
|
||||
func createWafConfig(website *model.Website, domains []model.WebsiteDomain, created *websiteCreateFiles) error {
|
||||
func createWafConfig(website *model.Website, domains []model.WebsiteDomain) error {
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -730,11 +520,6 @@ func createWafConfig(website *model.Website, domains []model.WebsiteDomain, crea
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, existing := range websitesArray {
|
||||
if existing.Key == website.Alias {
|
||||
return fmt.Errorf("WAF website already exists: %s", website.Alias)
|
||||
}
|
||||
}
|
||||
wafWebsite := request.WafWebsite{
|
||||
Key: website.Alias,
|
||||
Domains: make([]string, 0),
|
||||
@@ -750,6 +535,9 @@ func createWafConfig(website *model.Website, domains []model.WebsiteDomain, crea
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fileOp.SaveFileWithByte(websitesConfigPath, websitesContent, constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
sitesDir = path.Join(wafDataPath, "sites")
|
||||
@@ -763,25 +551,13 @@ func createWafConfig(website *model.Website, domains []model.WebsiteDomain, crea
|
||||
return err
|
||||
}
|
||||
|
||||
if err := created.write(path.Join(websiteDir, "config.json"), defaultConfigContent, constant.FilePerm, false); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := created.mkdir(path.Join(websiteDir, "rules")); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, name := range []string{"acl", "args", "cookie", "defaultUaBlack", "defaultUrlBlack", "fileExt", "header", "methodWhite", "cdn"} {
|
||||
data, err := os.ReadFile(path.Join(defaultRuleDir, name+".json"))
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
return err
|
||||
_ = fileOp.DeleteDir(websiteDir)
|
||||
}
|
||||
if err := created.write(path.Join(websiteDir, "rules", name+".json"), data, constant.FilePerm, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := created.replaceShared(websitesConfigPath, content, websitesContent); err != nil {
|
||||
}()
|
||||
|
||||
if err := moveDefaultWafConfig(websiteDir, defaultConfigContent, defaultRuleDir, fileOp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -10,7 +10,7 @@ require (
|
||||
github.com/creack/pty v1.1.24
|
||||
github.com/docker/cli v29.9.0+incompatible
|
||||
github.com/docker/docker v28.5.2+incompatible
|
||||
github.com/docker/go-connections v0.8.1
|
||||
github.com/docker/go-connections v0.8.2
|
||||
github.com/fsnotify/fsnotify v1.10.1
|
||||
github.com/gin-gonic/gin v1.12.0
|
||||
github.com/glebarez/sqlite v1.11.0
|
||||
@@ -66,6 +66,7 @@ require (
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.2.0 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||
github.com/BurntSushi/toml v1.6.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/alex-ant/gomath v0.0.0-20160516115720-89013a210a82 // indirect
|
||||
|
||||
+6
-32
@@ -228,18 +228,14 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/dlclark/regexp2 v1.12.0 h1:0j4c5qQmnC6XOWNjP3PIXURXN2gWx76rd3KvgdPkCz8=
|
||||
github.com/dlclark/regexp2 v1.12.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/docker/cli v29.7.2+incompatible h1:dlkwallR8XqfeVnA2ELEhdwvb4lsSwuB4IgsG8Q9cLY=
|
||||
github.com/docker/cli v29.7.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v29.8.1+incompatible h1:qYL1bCp6cRw2SB1xmLlIOPyV171dilw9W2Jew38vy9c=
|
||||
github.com/docker/cli v29.8.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v29.9.0+incompatible h1:Cw9x50ioSGgGwXJ4eO+hIBry/w3LLbyF8GPAEKz1fnE=
|
||||
github.com/docker/cli v29.9.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM=
|
||||
github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.9.5 h1:EFNN8DHvaiK8zVqFA2DT6BjXE0GzfLOZ38ggPTKePkY=
|
||||
github.com/docker/docker-credential-helpers v0.9.5/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c=
|
||||
github.com/docker/go-connections v0.8.1 h1:JibmG5hULs5qXSr/cp/w3Pw5fZuStt4MOHMUExb29/M=
|
||||
github.com/docker/go-connections v0.8.1/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q=
|
||||
github.com/docker/go-connections v0.8.2 h1:9d9DEokx5W7qlr0shkFXIxEA7+TTD+llwzcykSlxMNc=
|
||||
github.com/docker/go-connections v0.8.2/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4=
|
||||
@@ -252,8 +248,6 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m
|
||||
github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/ebitengine/purego v0.10.2 h1:W809HbnvzAxgdm+aOvlSekrM16wGCdT/e76+9tS7gzE=
|
||||
github.com/ebitengine/purego v0.10.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/ebitengine/purego v0.11.1 h1:2zpWRSQNVKN4eKsKO9eM1ILDgWfYMY9GwqRmK6XeQ/0=
|
||||
github.com/ebitengine/purego v0.11.1/go.mod h1:DCHPP08djqhNSoTfImcnHYQRZmd0qhakvrozqaEYhGQ=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
@@ -707,8 +701,6 @@ github.com/pkg/sftp v1.13.11/go.mod h1:uNkH9roSXglNJqM+glJJi+TQXQUm0fXFWqCFmT8hs
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/power-devops/perfstat v0.0.0-20260805114148-88456608a4f6 h1:jL3a8soXdzuTCcRnKhOmtcsVOObdDTFf4O2B403HPRU=
|
||||
github.com/power-devops/perfstat v0.0.0-20260805114148-88456608a4f6/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
@@ -758,10 +750,6 @@ github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9t
|
||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=
|
||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shirou/gopsutil/v4 v4.26.7 h1:IXzpHz/dkMRYAhKkOXr1HB6SuzWU3eoyyeWe7g3bNZc=
|
||||
github.com/shirou/gopsutil/v4 v4.26.7/go.mod h1:5O9FjBiXoTDFatIWjZZosqj4pV0DRtLx598xGbBehzM=
|
||||
github.com/shirou/gopsutil/v4 v4.26.8 h1:YQMTF/1J50B5+Y0vlo1eDRf5DoR7Gk69hY+8wjYkQeo=
|
||||
github.com/shirou/gopsutil/v4 v4.26.8/go.mod h1:5O9FjBiXoTDFatIWjZZosqj4pV0DRtLx598xGbBehzM=
|
||||
github.com/shirou/gopsutil/v4 v4.26.9 h1:CaBo/hBFqvlJoLvAQEKdHdf5GD97/MN2ACfyv63+2Ig=
|
||||
github.com/shirou/gopsutil/v4 v4.26.9/go.mod h1:nKH+8wX2zxr/mDbsR+AAy6Qd2z4ZOQ7wfQaEp+yrYmg=
|
||||
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
||||
@@ -888,14 +876,8 @@ go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3
|
||||
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
|
||||
go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0=
|
||||
go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo=
|
||||
go.mongodb.org/mongo-driver v1.17.9 h1:IexDdCuuNJ3BHrELgBlyaH9p60JXAvdzWR128q+U5tU=
|
||||
go.mongodb.org/mongo-driver v1.17.9/go.mod h1:LlOhpH5NUEfhxcAwG0UEkMqwYcc4JU18gtCdGudk/tQ=
|
||||
go.mongodb.org/mongo-driver v1.17.10 h1:kdAgQvu8TROXZpSkJQd5wzfaNCCrMbpZyKFtQ6qkPCE=
|
||||
go.mongodb.org/mongo-driver v1.17.10/go.mod h1:LlOhpH5NUEfhxcAwG0UEkMqwYcc4JU18gtCdGudk/tQ=
|
||||
go.mongodb.org/mongo-driver/v2 v2.9.0 h1:e2mQdOmbkiYz+dj3faM7lVDwl7WdnRD+g5VicafMhL0=
|
||||
go.mongodb.org/mongo-driver/v2 v2.9.0/go.mod h1:SHKN0IWkKmEVGHLjXnni6s4wPKX4v86FTgOeJJFuXcA=
|
||||
go.mongodb.org/mongo-driver/v2 v2.9.1 h1:jewiFs2m1/VOQp8qhFshX6hWZ+EAXDhZHXExAUMcOgQ=
|
||||
go.mongodb.org/mongo-driver/v2 v2.9.1/go.mod h1:SHKN0IWkKmEVGHLjXnni6s4wPKX4v86FTgOeJJFuXcA=
|
||||
go.mongodb.org/mongo-driver/v2 v2.9.2 h1:OCAdjI37pC/SVxucz/9CM8zD4jCdegtsY5QcKzYFCgE=
|
||||
go.mongodb.org/mongo-driver/v2 v2.9.2/go.mod h1:SHKN0IWkKmEVGHLjXnni6s4wPKX4v86FTgOeJJFuXcA=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
@@ -970,8 +952,6 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y=
|
||||
golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I=
|
||||
golang.org/x/crypto v0.57.0 h1:3ZVCjf8Ggz7zneR/EHRVx68Ctf+2pmIMP2UFhh9cC6M=
|
||||
golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZA=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@@ -1015,9 +995,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
|
||||
golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
|
||||
golang.org/x/mod v0.41.0 h1:qJmnOUb4YB+FsEuM3HcWucdZASCPGhsX6uljO6pog0c=
|
||||
golang.org/x/mod v0.41.0/go.mod h1:Ek9pY8RKWXwsWvd3rQiHYtMqkjSUV+s1Rj7j4H5Ur6o=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -1159,6 +1138,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -1175,8 +1155,6 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
||||
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo=
|
||||
golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
@@ -1192,9 +1170,8 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
|
||||
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
|
||||
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
|
||||
golang.org/x/term v0.46.0 h1:3+OXuTbaKDgwk8jTi3aSLHRlmWqHEUDUtxnbFigO4YE=
|
||||
golang.org/x/term v0.46.0/go.mod h1:+K02xbkittuwc0Am4abfA3Fc+XRGXkvBXNO88NCXPoc=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -1211,8 +1188,6 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=
|
||||
golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=
|
||||
golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI=
|
||||
golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -1276,9 +1251,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE=
|
||||
golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk=
|
||||
golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI=
|
||||
golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
@@ -32,32 +32,24 @@
|
||||
@user-change="currentUser = $event"
|
||||
/>
|
||||
<div class="user-actions" :class="{ 'is-collapsed': isCollapse }">
|
||||
<el-tooltip
|
||||
<button
|
||||
v-if="currentUser"
|
||||
:content="$t('xpack.user.userInfo')"
|
||||
placement="top"
|
||||
popper-class="sidebar-user-tooltip"
|
||||
type="button"
|
||||
class="user-entry"
|
||||
:aria-label="$t('xpack.user.userInfo') + ' ' + currentUser.name"
|
||||
@click="nodeSelectorRef?.openUserInfo()"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="user-entry"
|
||||
:aria-label="$t('xpack.user.userInfo') + ' ' + currentUser.name"
|
||||
@click="nodeSelectorRef?.openUserInfo()"
|
||||
>
|
||||
<SvgIcon class="icon" iconName="p-gerenzhongxin1" />
|
||||
<span v-if="!isCollapse" class="user-name">{{ currentUser.name }}</span>
|
||||
</button>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="$t('header.exitSystem')" placement="top" popper-class="sidebar-user-tooltip">
|
||||
<button
|
||||
type="button"
|
||||
class="user-entry logout-entry"
|
||||
:aria-label="$t('header.exitSystem')"
|
||||
@click="nodeSelectorRef?.logout()"
|
||||
>
|
||||
<SvgIcon class="icon" iconName="p-tuichudenglu3" />
|
||||
</button>
|
||||
</el-tooltip>
|
||||
<SvgIcon class="icon" iconName="p-gerenzhongxin1" />
|
||||
<span v-if="!isCollapse" class="user-name">{{ currentUser.name }}</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="user-entry logout-entry"
|
||||
:aria-label="$t('header.exitSystem')"
|
||||
@click="nodeSelectorRef?.logout()"
|
||||
>
|
||||
<SvgIcon class="icon" iconName="p-tuichudenglu3" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -441,16 +433,3 @@ watch(
|
||||
border-left: 1px solid var(--panel-footer-border);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.el-popper.sidebar-user-tooltip {
|
||||
background: var(--el-menu-item-bg-color);
|
||||
color: var(--el-color-primary);
|
||||
border-color: var(--panel-footer-border);
|
||||
|
||||
.el-popper__arrow::before {
|
||||
background: var(--el-menu-item-bg-color);
|
||||
border-color: var(--panel-footer-border);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user