mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-09 08:00:27 +00:00
Compare commits
109
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5fdff61ff | ||
|
|
4832081b82 | ||
|
|
ef5a13f87f | ||
|
|
e2bc8e800a | ||
|
|
85a397949e | ||
|
|
5cfdcedf9a | ||
|
|
c5bb8dab8c | ||
|
|
f1421ba7f9 | ||
|
|
9e44db53a7 | ||
|
|
4814a76c47 | ||
|
|
2ec4b2561c | ||
|
|
4efe7240ad | ||
|
|
ed13136221 | ||
|
|
735fc75e35 | ||
|
|
b8a52ae707 | ||
|
|
2501a9f78a | ||
|
|
5a8d6db43e | ||
|
|
a3312331d2 | ||
|
|
fbd0e836d7 | ||
|
|
4935d88301 | ||
|
|
8625979cc3 | ||
|
|
c77742e72e | ||
|
|
43a6b4b735 | ||
|
|
f4ee534101 | ||
|
|
c055a07e57 | ||
|
|
62bead5c50 | ||
|
|
9edafc13a3 | ||
|
|
e6ccf8be1f | ||
|
|
222089d56a | ||
|
|
96e48847d0 | ||
|
|
38b0c42555 | ||
|
|
2eae8274f6 | ||
|
|
0de79e537e | ||
|
|
e37b87d63e | ||
|
|
37a0329d4a | ||
|
|
e037b69f52 | ||
|
|
34498392dc | ||
|
|
1687b99526 | ||
|
|
0bf6db1cf8 | ||
|
|
0cd06803e2 | ||
|
|
45f6a415de | ||
|
|
3e3f0d9452 | ||
|
|
35785f1e40 | ||
|
|
437d6eb0fd | ||
|
|
1e2c85e771 | ||
|
|
ef075df3fe | ||
|
|
1e22769c8b | ||
|
|
0751326b46 | ||
|
|
db4973cfde | ||
|
|
0b47d692b8 | ||
|
|
672ef66be8 | ||
|
|
7ab005540b | ||
|
|
7c928735cd | ||
|
|
9ec1610f34 | ||
|
|
4f2a340212 | ||
|
|
e69fd3b388 | ||
|
|
6991c773da | ||
|
|
9b88979b69 | ||
|
|
7c9608727d | ||
|
|
62828c464e | ||
|
|
f1ed051135 | ||
|
|
33a0c2ba30 | ||
|
|
494da3c209 | ||
|
|
646fc4e678 | ||
|
|
cdbe24a523 | ||
|
|
10012c6148 | ||
|
|
bb4fd69f3a | ||
|
|
6ff0f14841 | ||
|
|
1088034a5c | ||
|
|
8a011b1cf9 | ||
|
|
e3eebc938a | ||
|
|
08da7802c6 | ||
|
|
79ca1b4d6b | ||
|
|
47119e508b | ||
|
|
13bb5e0d30 | ||
|
|
218c165c26 | ||
|
|
d6006d34c0 | ||
|
|
810ea03ac1 | ||
|
|
e046315616 | ||
|
|
0a7f1eb286 | ||
|
|
b0411b2df6 | ||
|
|
471b7d9657 | ||
|
|
1527c63d37 | ||
|
|
0ebeeaebd6 | ||
|
|
1ae5bef40d | ||
|
|
9b9fe5444d | ||
|
|
a5d853c61a | ||
|
|
6610a3debe | ||
|
|
6b244b2b03 | ||
|
|
0b26d70927 | ||
|
|
18faed79f3 | ||
|
|
b0cc1248f0 | ||
|
|
8013c7fd96 | ||
|
|
306082d625 | ||
|
|
821b8dfe63 | ||
|
|
8d88ed812c | ||
|
|
aa93a6d373 | ||
|
|
b4e8c8503c | ||
|
|
4de733e084 | ||
|
|
6c67dc6ed4 | ||
|
|
ba6991bfb6 | ||
|
|
33309d2d93 | ||
|
|
1b2208a4d0 | ||
|
|
e3fb97fc8c | ||
|
|
1ff5bf85e9 | ||
|
|
062b2f2ae6 | ||
|
|
44445aca93 | ||
|
|
94de830637 | ||
|
|
9160726127 |
+5
-1
@@ -1 +1,5 @@
|
||||
*.ts linguist-language=Go
|
||||
*.ts linguist-language=Go
|
||||
*.js linguist-language=Go
|
||||
*.css linguist-language=Go
|
||||
*.scss linguist-language=Go
|
||||
*.html linguist-language=Go
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
name: 为 PR 添加标签
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions-ecosystem/action-add-labels@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUBTOKEN }}
|
||||
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
uses: Yikun/hub-mirror-action@master
|
||||
with:
|
||||
src: 'github/1Panel-dev'
|
||||
dst: 'gitee/fit2cloud-xlab'
|
||||
dst: 'gitee/fit2cloud-feizhiyun'
|
||||
dst_key: ${{ secrets.GITEE_PRIVATE_KEY }}
|
||||
dst_token: ${{ secrets.GITEE_TOKEN }}
|
||||
static_list: "1Panel"
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
name: Typos Check
|
||||
on: pull_request
|
||||
|
||||
jobs:
|
||||
run:
|
||||
name: Spell Check with Typos
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Actions Repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Check spelling
|
||||
uses: crate-ci/typos@master
|
||||
+4
-6
@@ -16,7 +16,8 @@ build/1panel
|
||||
*.factorypath
|
||||
|
||||
# IntelliJ IDEA
|
||||
.idea
|
||||
.idea/*
|
||||
!.idea/icon.png
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
@@ -41,11 +42,7 @@ frontend/src/xpack
|
||||
backend/xpack
|
||||
backend/router/entry_xpack.go
|
||||
backend/server/init_xpack.go
|
||||
plugins/openresty/waf/db
|
||||
plugins/openresty/waf/data
|
||||
plugins/openresty/waf/sites
|
||||
plugins/openresty/waf/conf/websites.json
|
||||
|
||||
backend/utils/xpack/xpack_xpack.go
|
||||
|
||||
.history/
|
||||
dist/
|
||||
@@ -55,3 +52,4 @@ install.sh
|
||||
quick_start.sh
|
||||
cmd/server/fileList.txt
|
||||
.fileList.txt
|
||||
1Panel.code-workspace
|
||||
|
||||
@@ -13,6 +13,7 @@ builds:
|
||||
- main: ./cmd/server/main.go
|
||||
binary: 1panel
|
||||
flags:
|
||||
- -tags=xpack
|
||||
- -trimpath
|
||||
ldflags:
|
||||
- -w -s
|
||||
|
||||
Generated
BIN
Binary file not shown.
|
After Width: | Height: | Size: 9.1 KiB |
@@ -19,6 +19,8 @@
|
||||
- **安全可靠**:基于容器管理并部署应用,实现最小的漏洞暴露面,同时提供防火墙和日志审计等功能;
|
||||
- **一键备份**:支持一键备份和恢复,用户可以将数据备份到各类云端存储介质,永不丢失。
|
||||
|
||||
1Panel 三分钟速览:https://www.bilibili.com/video/BV1Mt421n7LZ/
|
||||
|
||||
## UI 展示
|
||||
|
||||

|
||||
@@ -56,6 +58,13 @@ curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_
|
||||
|
||||
[](https://star-history.com/#1Panel-dev/1Panel&Date)
|
||||
|
||||
## 我们的其他明星项目
|
||||
- [JumpServer](https://github.com/jumpserver/jumpserver/) - 广受欢迎的开源堡垒机
|
||||
- [DataEase](https://github.com/dataease/dataease/) - 人人可用的开源数据可视化分析工具
|
||||
- [MeterSphere](https://github.com/metersphere/metersphere/) - 一站式开源自动化测试平台
|
||||
- [Halo](https://github.com/halo-dev/halo/) - 强大易用的开源建站工具
|
||||
|
||||
|
||||
## FOSSA Status
|
||||
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2F1Panel-dev%2F1Panel?ref=badge_large)
|
||||
|
||||
@@ -3,9 +3,6 @@
|
||||
如果您发现安全问题,请直接联系我们:
|
||||
|
||||
- wanghe@fit2cloud.com
|
||||
- zhengkun@fit2cloud.com
|
||||
- support@fit2cloud.com
|
||||
- 400-052-0755
|
||||
|
||||
感谢您的支持!
|
||||
|
||||
@@ -14,8 +11,5 @@
|
||||
All security bugs should be reported to the contact as below:
|
||||
|
||||
- wanghe@fit2cloud.com
|
||||
- zhengkun@fit2cloud.com
|
||||
- support@fit2cloud.com
|
||||
- +86 400-052-0755
|
||||
|
||||
Thanks for your support!
|
||||
|
||||
@@ -137,7 +137,7 @@ func (b *BaseApi) GetAppDetailByID(c *gin.Context) {
|
||||
// @Accept json
|
||||
// @Success 200 {object} response.IgnoredApp
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /apps/ingored [get]
|
||||
// @Router /apps/ignored [get]
|
||||
func (b *BaseApi) GetIgnoredApp(c *gin.Context) {
|
||||
res, err := appService.GetIgnoredApp()
|
||||
if err != nil {
|
||||
|
||||
@@ -121,6 +121,15 @@ func (b *BaseApi) CheckIsSafety(c *gin.Context) {
|
||||
helper.SuccessWithData(c, status)
|
||||
}
|
||||
|
||||
func (b *BaseApi) GetResponsePage(c *gin.Context) {
|
||||
pageCode, err := authService.GetResponsePage()
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, pageCode)
|
||||
}
|
||||
|
||||
// @Tags Auth
|
||||
// @Summary Check System isDemo
|
||||
// @Description 判断是否为demo环境
|
||||
|
||||
@@ -301,28 +301,83 @@ func (b *BaseApi) UploadFiles(c *gin.Context) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
files := form.File["file"]
|
||||
uploadFiles := form.File["file"]
|
||||
paths := form.Value["path"]
|
||||
|
||||
overwrite := true
|
||||
if ow, ok := form.Value["overwrite"]; ok {
|
||||
if len(ow) != 0 {
|
||||
parseBool, _ := strconv.ParseBool(ow[0])
|
||||
overwrite = parseBool
|
||||
}
|
||||
}
|
||||
|
||||
if len(paths) == 0 || !strings.Contains(paths[0], "/") {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error paths in request"))
|
||||
return
|
||||
}
|
||||
dir := path.Dir(paths[0])
|
||||
if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
|
||||
info, err := os.Stat(dir)
|
||||
if err != nil && os.IsNotExist(err) {
|
||||
mode, err := files.GetParentMode(dir)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
if err = os.MkdirAll(dir, mode); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, fmt.Errorf("mkdir %s failed, err: %v", dir, err))
|
||||
return
|
||||
}
|
||||
}
|
||||
info, err = os.Stat(dir)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
mode := info.Mode()
|
||||
|
||||
fileOp := files.NewFileOp()
|
||||
|
||||
success := 0
|
||||
failures := make(buserr.MultiErr)
|
||||
for _, file := range files {
|
||||
if err := c.SaveUploadedFile(file, path.Join(paths[0], file.Filename)); err != nil {
|
||||
for _, file := range uploadFiles {
|
||||
dstFilename := path.Join(paths[0], file.Filename)
|
||||
dstDir := path.Dir(dstFilename)
|
||||
if !fileOp.Stat(dstDir) {
|
||||
if err = fileOp.CreateDir(dstDir, mode); err != nil {
|
||||
e := fmt.Errorf("create dir [%s] failed, err: %v", path.Dir(dstFilename), err)
|
||||
failures[file.Filename] = e
|
||||
global.LOG.Error(e)
|
||||
continue
|
||||
}
|
||||
}
|
||||
tmpFilename := dstFilename + ".tmp"
|
||||
if err := c.SaveUploadedFile(file, tmpFilename); err != nil {
|
||||
_ = os.Remove(tmpFilename)
|
||||
e := fmt.Errorf("upload [%s] file failed, err: %v", file.Filename, err)
|
||||
failures[file.Filename] = e
|
||||
global.LOG.Error(e)
|
||||
continue
|
||||
}
|
||||
dstInfo, statErr := os.Stat(dstFilename)
|
||||
if overwrite {
|
||||
_ = os.Remove(dstFilename)
|
||||
}
|
||||
|
||||
err = os.Rename(tmpFilename, dstFilename)
|
||||
if err != nil {
|
||||
_ = os.Remove(tmpFilename)
|
||||
e := fmt.Errorf("upload [%s] file failed, err: %v", file.Filename, err)
|
||||
failures[file.Filename] = e
|
||||
global.LOG.Error(e)
|
||||
continue
|
||||
}
|
||||
if statErr == nil {
|
||||
_ = os.Chmod(dstFilename, dstInfo.Mode())
|
||||
} else {
|
||||
_ = os.Chmod(dstFilename, mode)
|
||||
}
|
||||
success++
|
||||
}
|
||||
if success == 0 {
|
||||
@@ -539,16 +594,20 @@ func (b *BaseApi) Size(c *gin.Context) {
|
||||
func mergeChunks(fileName string, fileDir string, dstDir string, chunkCount int) error {
|
||||
op := files.NewFileOp()
|
||||
dstDir = strings.TrimSpace(dstDir)
|
||||
mode, _ := files.GetParentMode(dstDir)
|
||||
if mode == 0 {
|
||||
mode = 0755
|
||||
}
|
||||
if _, err := os.Stat(dstDir); err != nil && os.IsNotExist(err) {
|
||||
if err = op.CreateDir(dstDir, os.ModePerm); err != nil {
|
||||
if err = op.CreateDir(dstDir, mode); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
targetFile, err := os.Create(filepath.Join(dstDir, fileName))
|
||||
|
||||
targetFile, err := os.OpenFile(filepath.Join(dstDir, fileName), os.O_RDWR|os.O_CREATE, mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer targetFile.Close()
|
||||
|
||||
for i := 0; i < chunkCount; i++ {
|
||||
chunkPath := filepath.Join(fileDir, fmt.Sprintf("%s.%d", fileName, i))
|
||||
|
||||
@@ -15,6 +15,13 @@ import (
|
||||
"github.com/shirou/gopsutil/v3/net"
|
||||
)
|
||||
|
||||
// @Tags Monitor
|
||||
// @Summary Load monitor datas
|
||||
// @Description 获取监控数据
|
||||
// @Param request body dto.MonitorSearch true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /hosts/monitor/search [post]
|
||||
func (b *BaseApi) LoadMonitor(c *gin.Context) {
|
||||
var req dto.MonitorSearch
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -28,7 +35,7 @@ func (b *BaseApi) LoadMonitor(c *gin.Context) {
|
||||
var backdatas []dto.MonitorData
|
||||
if req.Param == "all" || req.Param == "cpu" || req.Param == "memory" || req.Param == "load" {
|
||||
var bases []model.MonitorBase
|
||||
if err := global.DB.
|
||||
if err := global.MonitorDB.
|
||||
Where("created_at > ? AND created_at < ?", req.StartTime, req.EndTime).
|
||||
Find(&bases).Error; err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
@@ -45,7 +52,7 @@ func (b *BaseApi) LoadMonitor(c *gin.Context) {
|
||||
}
|
||||
if req.Param == "all" || req.Param == "io" {
|
||||
var bases []model.MonitorIO
|
||||
if err := global.DB.
|
||||
if err := global.MonitorDB.
|
||||
Where("created_at > ? AND created_at < ?", req.StartTime, req.EndTime).
|
||||
Find(&bases).Error; err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
@@ -62,7 +69,7 @@ func (b *BaseApi) LoadMonitor(c *gin.Context) {
|
||||
}
|
||||
if req.Param == "all" || req.Param == "network" {
|
||||
var bases []model.MonitorNetwork
|
||||
if err := global.DB.
|
||||
if err := global.MonitorDB.
|
||||
Where("name = ? AND created_at > ? AND created_at < ?", req.Info, req.StartTime, req.EndTime).
|
||||
Find(&bases).Error; err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
@@ -80,6 +87,30 @@ func (b *BaseApi) LoadMonitor(c *gin.Context) {
|
||||
helper.SuccessWithData(c, backdatas)
|
||||
}
|
||||
|
||||
// @Tags Monitor
|
||||
// @Summary Clean monitor datas
|
||||
// @Description 清空监控数据
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /hosts/monitor/clean [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清空监控数据","formatEN":"clean monitor datas"}
|
||||
func (b *BaseApi) CleanMonitor(c *gin.Context) {
|
||||
if err := global.MonitorDB.Exec("DELETE FROM monitor_bases").Error; err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
if err := global.MonitorDB.Exec("DELETE FROM monitor_ios").Error; err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
if err := global.MonitorDB.Exec("DELETE FROM monitor_networks").Error; err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
func (b *BaseApi) GetNetworkOptions(c *gin.Context) {
|
||||
netStat, _ := net.IOCounters(true)
|
||||
var options []string
|
||||
|
||||
@@ -60,6 +60,28 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) {
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Update system setting
|
||||
// @Description 隐藏高级功能菜单
|
||||
// @Accept json
|
||||
// @Param request body dto.SettingUpdate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/menu/update [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"隐藏高级功能菜单","formatEN":"Hide advanced feature menu."}
|
||||
func (b *BaseApi) UpdateMenu(c *gin.Context) {
|
||||
var req dto.SettingUpdate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := settingService.Update(req.Key, req.Value); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Update system password
|
||||
// @Description 更新系统登录密码
|
||||
@@ -227,30 +249,6 @@ func (b *BaseApi) LoadBaseDir(c *gin.Context) {
|
||||
helper.SuccessWithData(c, global.CONF.System.DataDir)
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Clean monitor datas
|
||||
// @Description 清空监控数据
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/monitor/clean [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清空监控数据","formatEN":"clean monitor datas"}
|
||||
func (b *BaseApi) CleanMonitor(c *gin.Context) {
|
||||
if err := global.DB.Exec("DELETE FROM monitor_bases").Error; err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
if err := global.DB.Exec("DELETE FROM monitor_ios").Error; err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
if err := global.DB.Exec("DELETE FROM monitor_networks").Error; err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Load mfa info
|
||||
// @Description 获取 mfa 信息
|
||||
|
||||
@@ -102,7 +102,7 @@ func (b *BaseApi) RedisWsSsh(c *gin.Context) {
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
defer killBash(redisConf.ContainerName, commands, pidMap)
|
||||
defer killBash(redisConf.ContainerName, pidMap)
|
||||
defer slave.Close()
|
||||
|
||||
tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false)
|
||||
@@ -170,7 +170,7 @@ func (b *BaseApi) ContainerWsSsh(c *gin.Context) {
|
||||
if wshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
defer killBash(containerID, command, pidMap)
|
||||
defer killBash(containerID, pidMap)
|
||||
defer slave.Close()
|
||||
|
||||
tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, true)
|
||||
@@ -221,26 +221,26 @@ func loadMapFromDockerTop(containerID string) map[string]string {
|
||||
lines := strings.Split(stdout, "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) != 2 {
|
||||
if len(parts) == 0 {
|
||||
continue
|
||||
}
|
||||
pidMap[parts[0]] = parts[1]
|
||||
pidMap[parts[0]] = strings.Join(parts, " ")
|
||||
}
|
||||
return pidMap
|
||||
}
|
||||
|
||||
func killBash(containerID, comm string, pidMap map[string]string) {
|
||||
func killBash(containerID string, pidMap map[string]string) {
|
||||
sudo := cmd.SudoHandleCmd()
|
||||
newPidMap := loadMapFromDockerTop(containerID)
|
||||
for pid, command := range newPidMap {
|
||||
for pid, newCmd := range newPidMap {
|
||||
isOld := false
|
||||
for pid2 := range pidMap {
|
||||
if pid == pid2 {
|
||||
for pid2, oldCmd := range pidMap {
|
||||
if pid == pid2 && oldCmd == newCmd {
|
||||
isOld = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isOld && command == comm {
|
||||
if !isOld {
|
||||
_, _ = cmd.Execf("%s kill -9 %s", sudo, pid)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,69 +305,6 @@ func (b *BaseApi) CreateWebsiteCheck(c *gin.Context) {
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Tags Website WAF
|
||||
// @Summary Load websit waf conf
|
||||
// @Description 获取网站 waf 配置
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteWafReq true "request"
|
||||
// @Success 200 {object} response.WebsiteWafConfig
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/waf/config [post]
|
||||
func (b *BaseApi) GetWebsiteWafConfig(c *gin.Context) {
|
||||
var req request.WebsiteWafReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
data, err := websiteService.GetWafConfig(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Tags Website WAF
|
||||
// @Summary Update website waf conf
|
||||
// @Description 更新 网站 waf 配置
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteWafUpdate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/waf/update [post]
|
||||
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"WAF 配置修改 [domain]","formatEN":"WAF conf update [domain]"}
|
||||
func (b *BaseApi) UpdateWebsiteWafConfig(c *gin.Context) {
|
||||
var req request.WebsiteWafUpdate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := websiteService.UpdateWafConfig(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags Website WAF
|
||||
// @Summary Update website waf file
|
||||
// @Description 更新 网站 waf 配置文件
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteWafUpdate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/waf/file/update [post]
|
||||
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"WAF 配置文件修改 [domain]","formatEN":"WAF conf file update [domain]"}
|
||||
func (b *BaseApi) UpdateWebsiteWafFile(c *gin.Context) {
|
||||
var req request.WebsiteWafFileUpdate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := websiteService.UpdateWafFile(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags Website Nginx
|
||||
// @Summary Update website nginx conf
|
||||
// @Description 更新 网站 nginx 配置
|
||||
@@ -433,7 +370,7 @@ func (b *BaseApi) ChangeDefaultServer(c *gin.Context) {
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Load websit php conf
|
||||
// @Summary Load website php conf
|
||||
// @Description 获取网站 php 配置
|
||||
// @Accept json
|
||||
// @Param id path integer true "request"
|
||||
|
||||
@@ -48,6 +48,8 @@ type ContainerOperate struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Image string `json:"image" validate:"required"`
|
||||
Network string `json:"network"`
|
||||
Ipv4 string `json:"ipv4"`
|
||||
Ipv6 string `json:"ipv6"`
|
||||
PublishAllPorts bool `json:"publishAllPorts"`
|
||||
ExposedPorts []PortHelper `json:"exposedPorts"`
|
||||
Tty bool `json:"tty"`
|
||||
@@ -98,6 +100,7 @@ type ContainerStats struct {
|
||||
}
|
||||
|
||||
type VolumeHelper struct {
|
||||
Type string `json:"type"`
|
||||
SourceDir string `json:"sourceDir"`
|
||||
ContainerDir string `json:"containerDir"`
|
||||
Mode string `json:"mode"`
|
||||
|
||||
@@ -8,6 +8,7 @@ type CronjobCreate struct {
|
||||
Spec string `json:"spec" validate:"required"`
|
||||
|
||||
Script string `json:"script"`
|
||||
Command string `json:"command"`
|
||||
ContainerName string `json:"containerName"`
|
||||
AppID string `json:"appID"`
|
||||
Website string `json:"website"`
|
||||
@@ -28,6 +29,7 @@ type CronjobUpdate struct {
|
||||
Spec string `json:"spec" validate:"required"`
|
||||
|
||||
Script string `json:"script"`
|
||||
Command string `json:"command"`
|
||||
ContainerName string `json:"containerName"`
|
||||
AppID string `json:"appID"`
|
||||
Website string `json:"website"`
|
||||
@@ -70,6 +72,7 @@ type CronjobInfo struct {
|
||||
Spec string `json:"spec"`
|
||||
|
||||
Script string `json:"script"`
|
||||
Command string `json:"command"`
|
||||
ContainerName string `json:"containerName"`
|
||||
AppID string `json:"appID"`
|
||||
Website string `json:"website"`
|
||||
|
||||
@@ -69,6 +69,8 @@ type DashboardCurrent struct {
|
||||
NetBytesSent uint64 `json:"netBytesSent"`
|
||||
NetBytesRecv uint64 `json:"netBytesRecv"`
|
||||
|
||||
GPUData []GPUInfo `json:"gpuData"`
|
||||
|
||||
ShotTime time.Time `json:"shotTime"`
|
||||
}
|
||||
|
||||
@@ -86,3 +88,18 @@ type DiskInfo struct {
|
||||
InodesFree uint64 `json:"inodesFree"`
|
||||
InodesUsedPercent float64 `json:"inodesUsedPercent"`
|
||||
}
|
||||
|
||||
type GPUInfo struct {
|
||||
Index uint `json:"index"`
|
||||
ProductName string `json:"productName"`
|
||||
GPUUtil string `json:"gpuUtil"`
|
||||
Temperature string `json:"temperature"`
|
||||
PerformanceState string `json:"performanceState"`
|
||||
PowerUsage string `json:"powerUsage"`
|
||||
PowerDraw string `json:"powerDraw"`
|
||||
MaxPowerLimit string `json:"maxPowerLimit"`
|
||||
MemoryUsage string `json:"memoryUsage"`
|
||||
MemUsed string `json:"memUsed"`
|
||||
MemTotal string `json:"memTotal"`
|
||||
FanSpeed string `json:"fanSpeed"`
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ type MysqlStatus struct {
|
||||
}
|
||||
|
||||
type MysqlVariables struct {
|
||||
BinlogCachSize string `json:"binlog_cache_size"`
|
||||
BinlogCacheSize string `json:"binlog_cache_size"`
|
||||
InnodbBufferPoolSize string `json:"innodb_buffer_pool_size"`
|
||||
InnodbLogBufferSize string `json:"innodb_log_buffer_size"`
|
||||
JoinBufferSize string `json:"join_buffer_size"`
|
||||
|
||||
@@ -22,7 +22,7 @@ type FileCreate struct {
|
||||
Path string `json:"path" validate:"required"`
|
||||
Content string `json:"content"`
|
||||
IsDir bool `json:"isDir"`
|
||||
Mode int64 `json:"mode" validate:"required"`
|
||||
Mode int64 `json:"mode"`
|
||||
IsLink bool `json:"isLink"`
|
||||
IsSymlink bool `json:"isSymlink"`
|
||||
LinkPath string `json:"linkPath"`
|
||||
|
||||
@@ -69,24 +69,12 @@ type WebsiteOp struct {
|
||||
Operate string `json:"operate"`
|
||||
}
|
||||
|
||||
type WebsiteWafReq struct {
|
||||
WebsiteID uint `json:"websiteId" validate:"required"`
|
||||
Key string `json:"key" validate:"required"`
|
||||
Rule string `json:"rule" validate:"required"`
|
||||
}
|
||||
|
||||
type WebsiteRedirectUpdate struct {
|
||||
WebsiteID uint `json:"websiteId" validate:"required"`
|
||||
Key string `json:"key" validate:"required"`
|
||||
Enable bool `json:"enable"`
|
||||
}
|
||||
|
||||
type WebsiteWafUpdate struct {
|
||||
WebsiteID uint `json:"websiteId" validate:"required"`
|
||||
Key string `json:"key" validate:"required"`
|
||||
Enable bool `json:"enable"`
|
||||
}
|
||||
|
||||
type WebsiteRecover struct {
|
||||
WebsiteName string `json:"websiteName" validate:"required"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
@@ -207,12 +195,12 @@ type WebsiteRedirectReq struct {
|
||||
WebsiteID uint `json:"websiteId" validate:"required"`
|
||||
}
|
||||
|
||||
type WebsiteWafFileUpdate struct {
|
||||
WebsiteID uint `json:"websiteID" validate:"required"`
|
||||
Content string `json:"content" validate:"required"`
|
||||
Type string `json:"type" validate:"required,oneof=cc ip_white ip_block url_white url_block cookie_block args_check post_check ua_check file_ext_block user_agent"`
|
||||
}
|
||||
|
||||
type WebsiteCommonReq struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
}
|
||||
|
||||
type WafWebsite struct {
|
||||
Key string `json:"key"`
|
||||
Domains []string `json:"domains"`
|
||||
Host []string `json:"host"`
|
||||
}
|
||||
|
||||
@@ -31,11 +31,6 @@ type WebsiteNginxConfig struct {
|
||||
Params []NginxParam `json:"params"`
|
||||
}
|
||||
|
||||
type WebsiteWafConfig struct {
|
||||
Enable bool `json:"enable"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
type WebsiteHTTPS struct {
|
||||
Enable bool `json:"enable"`
|
||||
HttpConfig string `json:"httpConfig"`
|
||||
|
||||
@@ -19,6 +19,7 @@ type SettingInfo struct {
|
||||
BindAddress string `json:"bindAddress"`
|
||||
PanelName string `json:"panelName"`
|
||||
Theme string `json:"theme"`
|
||||
MenuTabs string `json:"menuTabs"`
|
||||
Language string `json:"language"`
|
||||
DefaultNetwork string `json:"defaultNetwork"`
|
||||
LastCleanTime string `json:"lastCleanTime"`
|
||||
@@ -54,6 +55,8 @@ type SettingInfo struct {
|
||||
FileRecycleBin string `json:"fileRecycleBin"`
|
||||
|
||||
SnapshotIgnore string `json:"snapshotIgnore"`
|
||||
XpackHideMenu string `json:"xpackHideMenu"`
|
||||
NoAuthSetting string `json:"noAuthSetting"`
|
||||
}
|
||||
|
||||
type SettingUpdate struct {
|
||||
|
||||
@@ -9,6 +9,7 @@ type Cronjob struct {
|
||||
Type string `gorm:"type:varchar(64);not null" json:"type"`
|
||||
Spec string `gorm:"type:varchar(64);not null" json:"spec"`
|
||||
|
||||
Command string `gorm:"type:varchar(64)" json:"command"`
|
||||
ContainerName string `gorm:"type:varchar(64)" json:"containerName"`
|
||||
Script string `gorm:"longtext" json:"script"`
|
||||
Website string `gorm:"type:varchar(64)" json:"website"`
|
||||
|
||||
@@ -68,20 +68,20 @@ func (u *SettingRepo) Update(key, value string) error {
|
||||
}
|
||||
|
||||
func (u *SettingRepo) CreateMonitorBase(model model.MonitorBase) error {
|
||||
return global.DB.Create(&model).Error
|
||||
return global.MonitorDB.Create(&model).Error
|
||||
}
|
||||
func (u *SettingRepo) BatchCreateMonitorIO(ioList []model.MonitorIO) error {
|
||||
return global.DB.CreateInBatches(ioList, len(ioList)).Error
|
||||
return global.MonitorDB.CreateInBatches(ioList, len(ioList)).Error
|
||||
}
|
||||
func (u *SettingRepo) BatchCreateMonitorNet(ioList []model.MonitorNetwork) error {
|
||||
return global.DB.CreateInBatches(ioList, len(ioList)).Error
|
||||
return global.MonitorDB.CreateInBatches(ioList, len(ioList)).Error
|
||||
}
|
||||
func (u *SettingRepo) DelMonitorBase(timeForDelete time.Time) error {
|
||||
return global.DB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorBase{}).Error
|
||||
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorBase{}).Error
|
||||
}
|
||||
func (u *SettingRepo) DelMonitorIO(timeForDelete time.Time) error {
|
||||
return global.DB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorIO{}).Error
|
||||
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorIO{}).Error
|
||||
}
|
||||
func (u *SettingRepo) DelMonitorNet(timeForDelete time.Time) error {
|
||||
return global.DB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorNetwork{}).Error
|
||||
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorNetwork{}).Error
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/xpack"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"math"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -37,7 +39,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/compose"
|
||||
composeV2 "github.com/1Panel-dev/1Panel/backend/utils/docker"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
dockerTypes "github.com/docker/docker/api/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -364,6 +365,7 @@ func deleteAppInstall(install model.AppInstall, deleteBackup bool, forceDelete b
|
||||
}
|
||||
_ = websiteRepo.DeleteAll(ctx)
|
||||
_ = websiteDomainRepo.DeleteAll(ctx)
|
||||
xpack.RemoveTamper("")
|
||||
case constant.AppMysql, constant.AppMariaDB:
|
||||
_ = mysqlRepo.Delete(ctx, mysqlRepo.WithByMysqlName(install.Name))
|
||||
case constant.AppPostgresql:
|
||||
@@ -693,8 +695,8 @@ func handleMap(params map[string]interface{}, envParams map[string]string) {
|
||||
strArray[i] = strings.ToLower(fmt.Sprintf("%v", t[i]))
|
||||
}
|
||||
envParams[k] = strings.Join(strArray, ",")
|
||||
default:
|
||||
envParams[k] = t.(string)
|
||||
case map[string]interface{}:
|
||||
handleMap(t, envParams)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -827,7 +829,7 @@ func checkContainerNameIsExist(containerName, appDir string) (bool, error) {
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
var options dockerTypes.ContainerListOptions
|
||||
var options container.ListOptions
|
||||
list, err := client.ContainerList(context.Background(), options)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -1225,14 +1227,20 @@ func addDockerComposeCommonParam(composeMap map[string]interface{}, serviceName
|
||||
return buserr.New(constant.ErrFileParse)
|
||||
}
|
||||
serviceValue := service.(map[string]interface{})
|
||||
deploy := map[string]interface{}{
|
||||
"resources": map[string]interface{}{
|
||||
"limits": map[string]interface{}{
|
||||
"cpus": "${CPUS}",
|
||||
"memory": "${MEMORY_LIMIT}",
|
||||
},
|
||||
},
|
||||
|
||||
deploy := map[string]interface{}{}
|
||||
if de, ok := serviceValue["deploy"]; ok {
|
||||
deploy = de.(map[string]interface{})
|
||||
}
|
||||
resource := map[string]interface{}{}
|
||||
if res, ok := deploy["resources"]; ok {
|
||||
resource = res.(map[string]interface{})
|
||||
}
|
||||
resource["limits"] = map[string]interface{}{
|
||||
"cpus": "${CPUS}",
|
||||
"memory": "${MEMORY_LIMIT}",
|
||||
}
|
||||
deploy["resources"] = resource
|
||||
serviceValue["deploy"] = deploy
|
||||
|
||||
ports, ok := serviceValue["ports"].([]interface{})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"strconv"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
@@ -19,6 +20,7 @@ type AuthService struct{}
|
||||
|
||||
type IAuthService interface {
|
||||
CheckIsSafety(code string) (string, error)
|
||||
GetResponsePage() (string, error)
|
||||
VerifyCode(code string) (bool, error)
|
||||
Login(c *gin.Context, info dto.Login, entrance string) (*dto.UserLoginInfo, error)
|
||||
LogOut(c *gin.Context) error
|
||||
@@ -42,7 +44,7 @@ func (u *AuthService) Login(c *gin.Context, info dto.Login, entrance string) (*d
|
||||
if err != nil {
|
||||
return nil, constant.ErrAuth
|
||||
}
|
||||
if info.Password != pass || nameSetting.Value != info.Name {
|
||||
if !hmac.Equal([]byte(info.Password), []byte(pass)) || nameSetting.Value != info.Name {
|
||||
return nil, constant.ErrAuth
|
||||
}
|
||||
entranceSetting, err := settingRepo.Get(settingRepo.WithByKey("SecurityEntrance"))
|
||||
@@ -78,7 +80,7 @@ func (u *AuthService) MFALogin(c *gin.Context, info dto.MFALogin, entrance strin
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if info.Password != pass || nameSetting.Value != info.Name {
|
||||
if !hmac.Equal([]byte(info.Password), []byte(pass)) || nameSetting.Value != info.Name {
|
||||
return nil, constant.ErrAuth
|
||||
}
|
||||
entranceSetting, err := settingRepo.Get(settingRepo.WithByKey("SecurityEntrance"))
|
||||
@@ -168,7 +170,7 @@ func (u *AuthService) VerifyCode(code string) (bool, error) {
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return setting.Value == code, nil
|
||||
return hmac.Equal([]byte(setting.Value), []byte(code)), nil
|
||||
}
|
||||
|
||||
func (u *AuthService) CheckIsSafety(code string) (string, error) {
|
||||
@@ -184,3 +186,11 @@ func (u *AuthService) CheckIsSafety(code string) (string, error) {
|
||||
}
|
||||
return "unpass", nil
|
||||
}
|
||||
|
||||
func (u *AuthService) GetResponsePage() (string, error) {
|
||||
pageCode, err := settingRepo.Get(settingRepo.WithByKey("NoAuthSetting"))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return pageCode.Value, nil
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/client"
|
||||
@@ -87,7 +88,9 @@ func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, erro
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
options := types.ContainerListOptions{All: true}
|
||||
options := container.ListOptions{
|
||||
All: true,
|
||||
}
|
||||
if len(req.Filters) != 0 {
|
||||
options.Filters = filters.NewArgs()
|
||||
options.Filters.Add("label", req.Filters)
|
||||
@@ -216,7 +219,7 @@ func (u *ContainerService) List() ([]string, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
containers, err := client.ContainerList(context.Background(), types.ContainerListOptions{All: true})
|
||||
containers, err := client.ContainerList(context.Background(), container.ListOptions{All: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -237,7 +240,7 @@ func (u *ContainerService) ContainerListStats() ([]dto.ContainerListStats, error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list, err := client.ContainerList(context.Background(), types.ContainerListOptions{All: true})
|
||||
list, err := client.ContainerList(context.Background(), container.ListOptions{All: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -376,14 +379,14 @@ func (u *ContainerService) ContainerCreate(req dto.ContainerOperate) error {
|
||||
return err
|
||||
}
|
||||
global.LOG.Infof("new container info %s has been made, now start to create", req.Name)
|
||||
container, err := client.ContainerCreate(ctx, config, hostConf, networkConf, &v1.Platform{}, req.Name)
|
||||
con, err := client.ContainerCreate(ctx, config, hostConf, networkConf, &v1.Platform{}, req.Name)
|
||||
if err != nil {
|
||||
_ = client.ContainerRemove(ctx, req.Name, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true})
|
||||
_ = client.ContainerRemove(ctx, req.Name, container.RemoveOptions{RemoveVolumes: true, Force: true})
|
||||
return err
|
||||
}
|
||||
global.LOG.Infof("create container %s successful! now check if the container is started and delete the container information if it is not.", req.Name)
|
||||
if err := client.ContainerStart(ctx, container.ID, types.ContainerStartOptions{}); err != nil {
|
||||
_ = client.ContainerRemove(ctx, req.Name, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true})
|
||||
if err := client.ContainerStart(ctx, con.ID, container.StartOptions{}); err != nil {
|
||||
_ = client.ContainerRemove(ctx, req.Name, container.RemoveOptions{RemoveVolumes: true, Force: true})
|
||||
return fmt.Errorf("create successful but start failed, err: %v", err)
|
||||
}
|
||||
return nil
|
||||
@@ -410,6 +413,18 @@ func (u *ContainerService) ContainerInfo(req dto.OperationWithName) (*dto.Contai
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
networkSettings := oldContainer.NetworkSettings
|
||||
bridgeNetworkSettings := networkSettings.Networks[data.Network]
|
||||
if bridgeNetworkSettings.IPAMConfig != nil {
|
||||
ipv4Address := bridgeNetworkSettings.IPAMConfig.IPv4Address
|
||||
data.Ipv4 = ipv4Address
|
||||
ipv6Address := bridgeNetworkSettings.IPAMConfig.IPv6Address
|
||||
data.Ipv6 = ipv6Address
|
||||
} else {
|
||||
data.Ipv4 = bridgeNetworkSettings.IPAddress
|
||||
}
|
||||
|
||||
data.Cmd = oldContainer.Config.Cmd
|
||||
data.OpenStdin = oldContainer.Config.OpenStdin
|
||||
data.Tty = oldContainer.Config.Tty
|
||||
@@ -442,7 +457,7 @@ func (u *ContainerService) ContainerInfo(req dto.OperationWithName) (*dto.Contai
|
||||
if oldContainer.HostConfig.Memory != 0 {
|
||||
data.Memory = float64(oldContainer.HostConfig.Memory) / 1024 / 1024
|
||||
}
|
||||
data.Volumes = loadVolumeBinds(oldContainer.HostConfig.Binds)
|
||||
data.Volumes = loadVolumeBinds(oldContainer.Mounts)
|
||||
|
||||
return &data, nil
|
||||
}
|
||||
@@ -471,7 +486,7 @@ func (u *ContainerService) ContainerUpdate(req dto.ContainerOperate) error {
|
||||
}
|
||||
}
|
||||
|
||||
if err := client.ContainerRemove(ctx, req.ContainerID, types.ContainerRemoveOptions{Force: true}); err != nil {
|
||||
if err := client.ContainerRemove(ctx, req.ContainerID, container.RemoveOptions{Force: true}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -482,13 +497,13 @@ func (u *ContainerService) ContainerUpdate(req dto.ContainerOperate) error {
|
||||
}
|
||||
|
||||
global.LOG.Infof("new container info %s has been update, now start to recreate", req.Name)
|
||||
container, err := client.ContainerCreate(ctx, config, hostConf, networkConf, &v1.Platform{}, req.Name)
|
||||
con, err := client.ContainerCreate(ctx, config, hostConf, networkConf, &v1.Platform{}, req.Name)
|
||||
if err != nil {
|
||||
reCreateAfterUpdate(req.Name, client, oldContainer.Config, oldContainer.HostConfig, oldContainer.NetworkSettings)
|
||||
return fmt.Errorf("update container failed, err: %v", err)
|
||||
}
|
||||
global.LOG.Infof("update container %s successful! now check if the container is started.", req.Name)
|
||||
if err := client.ContainerStart(ctx, container.ID, types.ContainerStartOptions{}); err != nil {
|
||||
if err := client.ContainerStart(ctx, con.ID, container.StartOptions{}); err != nil {
|
||||
return fmt.Errorf("update successful but start failed, err: %v", err)
|
||||
}
|
||||
|
||||
@@ -523,18 +538,18 @@ func (u *ContainerService) ContainerUpgrade(req dto.ContainerUpgrade) error {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err := client.ContainerRemove(ctx, req.Name, types.ContainerRemoveOptions{Force: true}); err != nil {
|
||||
if err := client.ContainerRemove(ctx, req.Name, container.RemoveOptions{Force: true}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
global.LOG.Infof("new container info %s has been update, now start to recreate", req.Name)
|
||||
container, err := client.ContainerCreate(ctx, config, hostConf, &networkConf, &v1.Platform{}, req.Name)
|
||||
con, err := client.ContainerCreate(ctx, config, hostConf, &networkConf, &v1.Platform{}, req.Name)
|
||||
if err != nil {
|
||||
reCreateAfterUpdate(req.Name, client, oldContainer.Config, oldContainer.HostConfig, oldContainer.NetworkSettings)
|
||||
return fmt.Errorf("upgrade container failed, err: %v", err)
|
||||
}
|
||||
global.LOG.Infof("upgrade container %s successful! now check if the container is started.", req.Name)
|
||||
if err := client.ContainerStart(ctx, container.ID, types.ContainerStartOptions{}); err != nil {
|
||||
if err := client.ContainerStart(ctx, con.ID, container.StartOptions{}); err != nil {
|
||||
return fmt.Errorf("upgrade successful but start failed, err: %v", err)
|
||||
}
|
||||
|
||||
@@ -566,7 +581,7 @@ func (u *ContainerService) ContainerOperation(req dto.ContainerOperation) error
|
||||
global.LOG.Infof("start container %s operation %s", item, req.Operation)
|
||||
switch req.Operation {
|
||||
case constant.ContainerOpStart:
|
||||
err = client.ContainerStart(ctx, item, types.ContainerStartOptions{})
|
||||
err = client.ContainerStart(ctx, item, container.StartOptions{})
|
||||
case constant.ContainerOpStop:
|
||||
err = client.ContainerStop(ctx, item, container.StopOptions{})
|
||||
case constant.ContainerOpRestart:
|
||||
@@ -578,7 +593,7 @@ func (u *ContainerService) ContainerOperation(req dto.ContainerOperation) error
|
||||
case constant.ContainerOpUnpause:
|
||||
err = client.ContainerUnpause(ctx, item)
|
||||
case constant.ContainerOpRemove:
|
||||
err = client.ContainerRemove(ctx, item, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true})
|
||||
err = client.ContainerRemove(ctx, item, container.RemoveOptions{RemoveVolumes: true, Force: true})
|
||||
}
|
||||
}
|
||||
return err
|
||||
@@ -612,7 +627,7 @@ func (u *ContainerService) ContainerLogClean(req dto.OperationWithName) error {
|
||||
_ = os.Remove(file)
|
||||
}
|
||||
|
||||
if err := client.ContainerStart(ctx, containerItem.ID, types.ContainerStartOptions{}); err != nil {
|
||||
if err := client.ContainerStart(ctx, containerItem.ID, container.StartOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -623,22 +638,26 @@ func (u *ContainerService) ContainerLogs(wsConn *websocket.Conn, containerType,
|
||||
if cmd.CheckIllegal(container, since, tail) {
|
||||
return buserr.New(constant.ErrCmdIllegal)
|
||||
}
|
||||
command := fmt.Sprintf("docker logs %s", container)
|
||||
commandName := "docker"
|
||||
commandArg := []string{"logs", container}
|
||||
if containerType == "compose" {
|
||||
command = fmt.Sprintf("docker-compose -f %s logs", container)
|
||||
commandName = "docker-compose"
|
||||
commandArg = []string{"-f", container, "logs"}
|
||||
}
|
||||
if tail != "0" {
|
||||
command += " --tail " + tail
|
||||
commandArg = append(commandArg, "--tail")
|
||||
commandArg = append(commandArg, tail)
|
||||
}
|
||||
if since != "all" {
|
||||
command += " --since " + since
|
||||
commandArg = append(commandArg, "--since")
|
||||
commandArg = append(commandArg, since)
|
||||
}
|
||||
if follow {
|
||||
command += " -f"
|
||||
commandArg = append(commandArg, "-f")
|
||||
}
|
||||
command += " 2>&1"
|
||||
cmd := exec.Command("bash", "-c", command)
|
||||
if !follow {
|
||||
cmd := exec.Command(commandName, commandArg...)
|
||||
cmd.Stderr = cmd.Stdout
|
||||
stdout, _ := cmd.CombinedOutput()
|
||||
if !utf8.Valid(stdout) {
|
||||
return errors.New("invalid utf8")
|
||||
@@ -649,50 +668,53 @@ func (u *ContainerService) ContainerLogs(wsConn *websocket.Conn, containerType,
|
||||
return nil
|
||||
}
|
||||
|
||||
cmd := exec.Command(commandName, commandArg...)
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
_ = cmd.Process.Signal(syscall.SIGTERM)
|
||||
_ = cmd.Wait()
|
||||
}()
|
||||
var exitCh chan struct{}
|
||||
if follow {
|
||||
go func() {
|
||||
_, wsData, _ := wsConn.ReadMessage()
|
||||
if string(wsData) == "close conn" {
|
||||
exitCh <- struct{}{}
|
||||
}
|
||||
}()
|
||||
return err
|
||||
}
|
||||
cmd.Stderr = cmd.Stdout
|
||||
if err := cmd.Start(); err != nil {
|
||||
_ = cmd.Process.Signal(syscall.SIGTERM)
|
||||
return err
|
||||
}
|
||||
exitCh := make(chan struct{})
|
||||
go func() {
|
||||
_, wsData, _ := wsConn.ReadMessage()
|
||||
if string(wsData) == "close conn" {
|
||||
_ = cmd.Process.Signal(syscall.SIGTERM)
|
||||
exitCh <- struct{}{}
|
||||
}
|
||||
}()
|
||||
|
||||
buffer := make([]byte, 1024)
|
||||
for {
|
||||
select {
|
||||
case <-exitCh:
|
||||
return nil
|
||||
default:
|
||||
n, err := stdout.Read(buffer)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return err
|
||||
go func() {
|
||||
buffer := make([]byte, 1024)
|
||||
for {
|
||||
select {
|
||||
case <-exitCh:
|
||||
return
|
||||
default:
|
||||
n, err := stdout.Read(buffer)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return
|
||||
}
|
||||
global.LOG.Errorf("read bytes from log failed, err: %v", err)
|
||||
continue
|
||||
}
|
||||
if !utf8.Valid(buffer[:n]) {
|
||||
continue
|
||||
}
|
||||
if err = wsConn.WriteMessage(websocket.TextMessage, buffer[:n]); err != nil {
|
||||
global.LOG.Errorf("send message with log to ws failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
global.LOG.Errorf("read bytes from log failed, err: %v", err)
|
||||
continue
|
||||
}
|
||||
if !utf8.Valid(buffer[:n]) {
|
||||
continue
|
||||
}
|
||||
if err = wsConn.WriteMessage(websocket.TextMessage, buffer[:n]); err != nil {
|
||||
global.LOG.Errorf("send message with log to ws failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
_ = cmd.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *ContainerService) ContainerStats(id string) (*dto.ContainerStats, error) {
|
||||
@@ -735,7 +757,7 @@ func (u *ContainerService) LoadContainerLogs(req dto.OperationWithNameAndType) s
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
options := types.ContainerListOptions{All: true}
|
||||
options := container.ListOptions{All: true}
|
||||
options.Filters = filters.NewArgs()
|
||||
options.Filters.Add("label", fmt.Sprintf("%s=%s", composeProjectLabel, req.Name))
|
||||
containers, err := cli.ContainerList(context.Background(), options)
|
||||
@@ -976,8 +998,21 @@ func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *types
|
||||
case "host", "none", "bridge":
|
||||
hostConf.NetworkMode = container.NetworkMode(req.Network)
|
||||
}
|
||||
networkConf.EndpointsConfig = map[string]*network.EndpointSettings{req.Network: {}}
|
||||
if req.Ipv4 != "" || req.Ipv6 != "" {
|
||||
networkConf.EndpointsConfig = map[string]*network.EndpointSettings{
|
||||
req.Network: {
|
||||
IPAMConfig: &network.EndpointIPAMConfig{
|
||||
IPv4Address: req.Ipv4,
|
||||
IPv6Address: req.Ipv6,
|
||||
},
|
||||
}}
|
||||
} else {
|
||||
networkConf.EndpointsConfig = map[string]*network.EndpointSettings{req.Network: {}}
|
||||
}
|
||||
} else {
|
||||
if req.Ipv4 != "" || req.Ipv6 != "" {
|
||||
return nil, nil, nil, fmt.Errorf("Please set up the network")
|
||||
}
|
||||
networkConf = network.NetworkingConfig{}
|
||||
}
|
||||
|
||||
@@ -994,10 +1029,19 @@ func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *types
|
||||
hostConf.MemorySwap = 0
|
||||
hostConf.PortBindings = portMap
|
||||
hostConf.Binds = []string{}
|
||||
hostConf.Mounts = []mount.Mount{}
|
||||
config.Volumes = make(map[string]struct{})
|
||||
for _, volume := range req.Volumes {
|
||||
config.Volumes[volume.ContainerDir] = struct{}{}
|
||||
hostConf.Binds = append(hostConf.Binds, fmt.Sprintf("%s:%s:%s", volume.SourceDir, volume.ContainerDir, volume.Mode))
|
||||
if volume.Type == "volume" {
|
||||
hostConf.Mounts = append(hostConf.Mounts, mount.Mount{
|
||||
Type: mount.Type(volume.Type),
|
||||
Source: volume.SourceDir,
|
||||
Target: volume.ContainerDir,
|
||||
})
|
||||
config.Volumes[volume.ContainerDir] = struct{}{}
|
||||
} else {
|
||||
hostConf.Binds = append(hostConf.Binds, fmt.Sprintf("%s:%s:%s", volume.SourceDir, volume.ContainerDir, volume.Mode))
|
||||
}
|
||||
}
|
||||
return &config, &hostConf, &networkConf, nil
|
||||
}
|
||||
@@ -1018,46 +1062,27 @@ func reCreateAfterUpdate(name string, client *client.Client, config *container.C
|
||||
global.LOG.Errorf("recreate after container update failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
if err := client.ContainerStart(ctx, oldContainer.ID, types.ContainerStartOptions{}); err != nil {
|
||||
if err := client.ContainerStart(ctx, oldContainer.ID, container.StartOptions{}); err != nil {
|
||||
global.LOG.Errorf("restart after container update failed, err: %v", err)
|
||||
}
|
||||
global.LOG.Errorf("recreate after container update successful")
|
||||
}
|
||||
|
||||
func loadVolumeBinds(binds []string) []dto.VolumeHelper {
|
||||
func loadVolumeBinds(binds []types.MountPoint) []dto.VolumeHelper {
|
||||
var datas []dto.VolumeHelper
|
||||
for _, bind := range binds {
|
||||
parts := strings.Split(bind, ":")
|
||||
var volumeItem dto.VolumeHelper
|
||||
if len(parts) > 3 {
|
||||
continue
|
||||
volumeItem.Type = string(bind.Type)
|
||||
if bind.Type == "volume" {
|
||||
volumeItem.SourceDir = bind.Name
|
||||
} else {
|
||||
volumeItem.SourceDir = bind.Source
|
||||
}
|
||||
volumeItem.SourceDir = parts[0]
|
||||
if len(parts) == 1 {
|
||||
volumeItem.ContainerDir = parts[0]
|
||||
volumeItem.ContainerDir = bind.Destination
|
||||
volumeItem.Mode = "ro"
|
||||
if bind.RW {
|
||||
volumeItem.Mode = "rw"
|
||||
}
|
||||
if len(parts) == 2 {
|
||||
switch parts[1] {
|
||||
case "r", "ro":
|
||||
volumeItem.ContainerDir = parts[0]
|
||||
volumeItem.Mode = "ro"
|
||||
case "rw":
|
||||
volumeItem.ContainerDir = parts[0]
|
||||
volumeItem.Mode = "rw"
|
||||
default:
|
||||
volumeItem.ContainerDir = parts[1]
|
||||
volumeItem.Mode = "rw"
|
||||
}
|
||||
}
|
||||
if len(parts) == 3 {
|
||||
volumeItem.ContainerDir = parts[1]
|
||||
if parts[2] == "r" {
|
||||
volumeItem.Mode = "ro"
|
||||
} else {
|
||||
volumeItem.Mode = parts[2]
|
||||
}
|
||||
}
|
||||
datas = append(datas, volumeItem)
|
||||
}
|
||||
return datas
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -20,7 +21,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/compose"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/docker"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
@@ -40,7 +40,7 @@ func (u *ContainerService) PageCompose(req dto.SearchWithPage) (int64, interface
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
options := types.ContainerListOptions{All: true}
|
||||
options := container.ListOptions{All: true}
|
||||
options.Filters = filters.NewArgs()
|
||||
options.Filters.Add("label", composeProjectLabel)
|
||||
|
||||
|
||||
@@ -265,6 +265,7 @@ func (u *CronjobService) Update(id uint, req dto.CronjobUpdate) error {
|
||||
upMap["name"] = req.Name
|
||||
upMap["spec"] = spec
|
||||
upMap["script"] = req.Script
|
||||
upMap["command"] = req.Command
|
||||
upMap["container_name"] = req.ContainerName
|
||||
upMap["app_id"] = req.AppID
|
||||
upMap["website"] = req.Website
|
||||
|
||||
@@ -326,7 +326,7 @@ func handleBackupLogs(targetDir, fileName string) error {
|
||||
if len(logFiles) != 0 {
|
||||
for i := 0; i < len(logFiles); i++ {
|
||||
if !logFiles[i].IsDir() {
|
||||
_ = cpBinary([]string{path.Join(itemDir, logFiles[i].Name())}, dirItem)
|
||||
_ = common.CopyFile(path.Join(itemDir, logFiles[i].Name()), dirItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -335,7 +335,7 @@ func handleBackupLogs(targetDir, fileName string) error {
|
||||
if len(logFiles2) != 0 {
|
||||
for i := 0; i < len(logFiles2); i++ {
|
||||
if !logFiles2[i].IsDir() {
|
||||
_ = cpBinary([]string{path.Join(itemDir2, logFiles2[i].Name())}, dirItem)
|
||||
_ = common.CopyFile(path.Join(itemDir2, logFiles2[i].Name()), dirItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -354,7 +354,7 @@ func handleBackupLogs(targetDir, fileName string) error {
|
||||
if len(systemLogFiles) != 0 {
|
||||
for i := 0; i < len(systemLogFiles); i++ {
|
||||
if !systemLogFiles[i].IsDir() {
|
||||
_ = cpBinary([]string{path.Join(systemLogDir, systemLogFiles[i].Name())}, systemDir)
|
||||
_ = common.CopyFile(path.Join(systemLogDir, systemLogFiles[i].Name()), systemDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -370,7 +370,7 @@ func handleBackupLogs(targetDir, fileName string) error {
|
||||
if len(loginLogFiles) != 0 {
|
||||
for i := 0; i < len(loginLogFiles); i++ {
|
||||
if !loginLogFiles[i].IsDir() && (strings.HasPrefix(loginLogFiles[i].Name(), "secure") || strings.HasPrefix(loginLogFiles[i].Name(), "auth.log")) {
|
||||
_ = cpBinary([]string{path.Join("/var/log", loginLogFiles[i].Name())}, loginDir)
|
||||
_ = common.CopyFile(path.Join("/var/log", loginLogFiles[i].Name()), loginDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
@@ -38,7 +39,11 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) {
|
||||
_ = cronjobRepo.UpdateRecords(record.ID, map[string]interface{}{"records": record.Records})
|
||||
script := cronjob.Script
|
||||
if len(cronjob.ContainerName) != 0 {
|
||||
script = fmt.Sprintf("docker exec %s %s", cronjob.ContainerName, cronjob.Script)
|
||||
command := "sh"
|
||||
if len(cronjob.Command) != 0 {
|
||||
command = cronjob.Command
|
||||
}
|
||||
script = fmt.Sprintf("docker exec %s %s -c \"%s\"", cronjob.ContainerName, command, strings.ReplaceAll(cronjob.Script, "\"", "\\\""))
|
||||
}
|
||||
err = u.handleShell(cronjob.Type, cronjob.Name, script, record.Records)
|
||||
u.removeExpiredLog(*cronjob)
|
||||
@@ -271,6 +276,21 @@ func loadClientMap(backupAccounts string) (map[string]cronjobUploadHelper, error
|
||||
if account.BackupPath != "/" {
|
||||
pathItem = strings.TrimPrefix(account.BackupPath, "/")
|
||||
}
|
||||
if target == constant.Local {
|
||||
varMap := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(account.Vars), &varMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := varMap["dir"]; !ok {
|
||||
return nil, errors.New("load local backup dir failed")
|
||||
}
|
||||
baseDir, ok := varMap["dir"].(string)
|
||||
if ok {
|
||||
pathItem = baseDir
|
||||
} else {
|
||||
return nil, fmt.Errorf("error type dir: %T", varMap["dir"])
|
||||
}
|
||||
}
|
||||
clients[target] = cronjobUploadHelper{
|
||||
client: client,
|
||||
backupPath: pathItem,
|
||||
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/copier"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/xpack"
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/shirou/gopsutil/v3/host"
|
||||
@@ -154,6 +156,7 @@ func (u *DashboardService) LoadCurrentInfo(ioOption string, netOption string) *d
|
||||
currentInfo.SwapMemoryUsedPercent = swapInfo.UsedPercent
|
||||
|
||||
currentInfo.DiskData = loadDiskInfo()
|
||||
currentInfo.GPUData = loadGPUInfo()
|
||||
|
||||
if ioOption == "all" {
|
||||
diskInfo, _ := disk.IOCounters()
|
||||
@@ -289,3 +292,21 @@ func loadDiskInfo() []dto.DiskInfo {
|
||||
})
|
||||
return datas
|
||||
}
|
||||
|
||||
func loadGPUInfo() []dto.GPUInfo {
|
||||
list := xpack.LoadGpuInfo()
|
||||
if len(list) == 0 {
|
||||
return nil
|
||||
}
|
||||
var data []dto.GPUInfo
|
||||
for _, gpu := range list {
|
||||
var dataItem dto.GPUInfo
|
||||
if err := copier.Copy(&dataItem, &gpu); err != nil {
|
||||
continue
|
||||
}
|
||||
dataItem.PowerUsage = dataItem.PowerDraw + " / " + dataItem.MaxPowerLimit
|
||||
dataItem.MemoryUsage = dataItem.MemUsed + " / " + dataItem.MemTotal
|
||||
data = append(data, dataItem)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
@@ -116,22 +116,32 @@ func (f *FileService) GetFileTree(op request.FileOption) ([]response.FileTree, e
|
||||
}
|
||||
|
||||
func (f *FileService) Create(op request.FileCreate) error {
|
||||
if files.IsInvalidChar(op.Path) {
|
||||
return buserr.New("ErrInvalidChar")
|
||||
}
|
||||
fo := files.NewFileOp()
|
||||
if fo.Stat(op.Path) {
|
||||
return buserr.New(constant.ErrFileIsExit)
|
||||
}
|
||||
if op.IsDir {
|
||||
return fo.CreateDir(op.Path, fs.FileMode(op.Mode))
|
||||
} else {
|
||||
if op.IsLink {
|
||||
if !fo.Stat(op.LinkPath) {
|
||||
return buserr.New(constant.ErrLinkPathNotFound)
|
||||
}
|
||||
return fo.LinkFile(op.LinkPath, op.Path, op.IsSymlink)
|
||||
mode := op.Mode
|
||||
if mode == 0 {
|
||||
fileInfo, err := os.Stat(filepath.Dir(op.Path))
|
||||
if err == nil {
|
||||
mode = int64(fileInfo.Mode().Perm())
|
||||
} else {
|
||||
return fo.CreateFile(op.Path)
|
||||
mode = 0755
|
||||
}
|
||||
}
|
||||
if op.IsDir {
|
||||
return fo.CreateDir(op.Path, fs.FileMode(mode))
|
||||
}
|
||||
if op.IsLink {
|
||||
if !fo.Stat(op.LinkPath) {
|
||||
return buserr.New(constant.ErrLinkPathNotFound)
|
||||
}
|
||||
return fo.LinkFile(op.LinkPath, op.Path, op.IsSymlink)
|
||||
}
|
||||
return fo.CreateFileWithMode(op.Path, fs.FileMode(mode))
|
||||
}
|
||||
|
||||
func (f *FileService) Delete(op request.FileDelete) error {
|
||||
@@ -236,6 +246,9 @@ func (f *FileService) SaveContent(edit request.FileEdit) error {
|
||||
}
|
||||
|
||||
func (f *FileService) ChangeName(req request.FileRename) error {
|
||||
if files.IsInvalidChar(req.NewName) {
|
||||
return buserr.New("ErrInvalidChar")
|
||||
}
|
||||
fo := files.NewFileOp()
|
||||
return fo.Rename(req.OldName, req.NewName)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/image"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
@@ -43,7 +45,7 @@ func NewIImageService() IImageService {
|
||||
}
|
||||
func (u *ImageService) Page(req dto.SearchWithPage) (int64, interface{}, error) {
|
||||
var (
|
||||
list []types.ImageSummary
|
||||
list []image.Summary
|
||||
records []dto.ImageInfo
|
||||
backDatas []dto.ImageInfo
|
||||
)
|
||||
@@ -51,11 +53,11 @@ func (u *ImageService) Page(req dto.SearchWithPage) (int64, interface{}, error)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
list, err = client.ImageList(context.Background(), types.ImageListOptions{})
|
||||
list, err = client.ImageList(context.Background(), image.ListOptions{})
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
containers, _ := client.ContainerList(context.Background(), types.ContainerListOptions{All: true})
|
||||
containers, _ := client.ContainerList(context.Background(), container.ListOptions{All: true})
|
||||
if len(req.Info) != 0 {
|
||||
length, count := len(list), 0
|
||||
for count < length {
|
||||
@@ -104,11 +106,11 @@ func (u *ImageService) ListAll() ([]dto.ImageInfo, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list, err := client.ImageList(context.Background(), types.ImageListOptions{})
|
||||
list, err := client.ImageList(context.Background(), image.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
containers, _ := client.ContainerList(context.Background(), types.ContainerListOptions{All: true})
|
||||
containers, _ := client.ContainerList(context.Background(), container.ListOptions{All: true})
|
||||
for _, image := range list {
|
||||
size := formatFileSize(image.Size)
|
||||
records = append(records, dto.ImageInfo{
|
||||
@@ -124,14 +126,14 @@ func (u *ImageService) ListAll() ([]dto.ImageInfo, error) {
|
||||
|
||||
func (u *ImageService) List() ([]dto.Options, error) {
|
||||
var (
|
||||
list []types.ImageSummary
|
||||
list []image.Summary
|
||||
backDatas []dto.Options
|
||||
)
|
||||
client, err := docker.NewDockerClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list, err = client.ImageList(context.Background(), types.ImageListOptions{})
|
||||
list, err = client.ImageList(context.Background(), image.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -385,15 +385,6 @@ func updateRecoverStatus(id uint, isRecover bool, interruptStep, status, message
|
||||
}
|
||||
}
|
||||
|
||||
func cpBinary(src []string, dst string) error {
|
||||
global.LOG.Debugf(fmt.Sprintf("\\cp -f %s %s", strings.Join(src, " "), dst))
|
||||
stdout, err := cmd.Exec(fmt.Sprintf("\\cp -f %s %s", strings.Join(src, " "), dst))
|
||||
if err != nil {
|
||||
return fmt.Errorf("cp file failed, stdout: %v, err: %v", stdout, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *SnapshotService) handleUnTar(sourceDir, targetDir string) error {
|
||||
if _, err := os.Stat(targetDir); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(targetDir, os.ModePerm); err != nil {
|
||||
|
||||
@@ -43,7 +43,15 @@ func snapPanel(snap snapHelper, targetDir string) {
|
||||
defer snap.Wg.Done()
|
||||
_ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"panel": constant.Running})
|
||||
status := constant.StatusDone
|
||||
if err := cpBinary([]string{"/usr/local/bin/1panel", "/usr/local/bin/1pctl", "/etc/systemd/system/1panel.service"}, targetDir); err != nil {
|
||||
if err := common.CopyFile("/usr/local/bin/1panel", path.Join(targetDir, "1panel")); err != nil {
|
||||
status = err.Error()
|
||||
}
|
||||
|
||||
if err := common.CopyFile("/usr/local/bin/1pctl", targetDir); err != nil {
|
||||
status = err.Error()
|
||||
}
|
||||
|
||||
if err := common.CopyFile("/etc/systemd/system/1panel.service", targetDir); err != nil {
|
||||
status = err.Error()
|
||||
}
|
||||
snap.Status.Panel = status
|
||||
@@ -59,7 +67,7 @@ func snapDaemonJson(snap snapHelper, targetDir string) {
|
||||
return
|
||||
}
|
||||
_ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"daemon_json": constant.Running})
|
||||
if err := cpBinary([]string{"/etc/docker/daemon.json"}, path.Join(targetDir, "daemon.json")); err != nil {
|
||||
if err := common.CopyFile("/etc/docker/daemon.json", targetDir); err != nil {
|
||||
status = err.Error()
|
||||
}
|
||||
snap.Status.DaemonJson = status
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@@ -88,7 +89,7 @@ func (u *SnapshotService) HandleSnapshotRecover(snap model.Snapshot, isRecover b
|
||||
}
|
||||
|
||||
if req.IsNew || snap.InterruptStep == "1PanelBinary" {
|
||||
if err := recoverPanel(path.Join(snapFileDir, "1panel/1panel"), "/usr/local/bin/1panel"); err != nil {
|
||||
if err := recoverPanel(path.Join(snapFileDir, "1panel/1panel"), "/usr/local/bin"); err != nil {
|
||||
updateRecoverStatus(snap.ID, isRecover, "1PanelBinary", constant.StatusFailed, err.Error())
|
||||
return
|
||||
}
|
||||
@@ -96,7 +97,7 @@ func (u *SnapshotService) HandleSnapshotRecover(snap model.Snapshot, isRecover b
|
||||
req.IsNew = true
|
||||
}
|
||||
if req.IsNew || snap.InterruptStep == "1PctlBinary" {
|
||||
if err := recoverPanel(path.Join(snapFileDir, "1panel/1pctl"), "/usr/local/bin/1pctl"); err != nil {
|
||||
if err := recoverPanel(path.Join(snapFileDir, "1panel/1pctl"), "/usr/local/bin"); err != nil {
|
||||
updateRecoverStatus(snap.ID, isRecover, "1PctlBinary", constant.StatusFailed, err.Error())
|
||||
return
|
||||
}
|
||||
@@ -104,7 +105,7 @@ func (u *SnapshotService) HandleSnapshotRecover(snap model.Snapshot, isRecover b
|
||||
req.IsNew = true
|
||||
}
|
||||
if req.IsNew || snap.InterruptStep == "1PanelService" {
|
||||
if err := recoverPanel(path.Join(snapFileDir, "1panel/1panel.service"), "/etc/systemd/system/1panel.service"); err != nil {
|
||||
if err := recoverPanel(path.Join(snapFileDir, "1panel/1panel.service"), "/etc/systemd/system"); err != nil {
|
||||
updateRecoverStatus(snap.ID, isRecover, "1PanelService", constant.StatusFailed, err.Error())
|
||||
return
|
||||
}
|
||||
@@ -235,10 +236,8 @@ func recoverPanel(src string, dst string) error {
|
||||
if _, err := os.Stat(src); err != nil {
|
||||
return fmt.Errorf("file is not found in %s, err: %v", src, err)
|
||||
}
|
||||
global.LOG.Debugf(fmt.Sprintf("\\cp -f %s %s", src, dst))
|
||||
stdout, err := cmd.Exec(fmt.Sprintf("\\cp -f %s %s", src, dst))
|
||||
if err != nil {
|
||||
return fmt.Errorf("cp file failed, stdout: %v, err: %v", stdout, err)
|
||||
if err := common.CopyFile(src, dst); err != nil {
|
||||
return fmt.Errorf("cp file failed, err: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ func (u *UpgradeService) SearchUpgrade() (*dto.UpgradeInfo, error) {
|
||||
global.LOG.Infof("load latest version failed, err: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
if !common.CompareVersion(string(latestVersion), currentVersion.Value) {
|
||||
if !common.ComparePanelVersion(string(latestVersion), currentVersion.Value) {
|
||||
return nil, err
|
||||
}
|
||||
upgrade.LatestVersion = latestVersion
|
||||
@@ -130,13 +130,13 @@ func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
|
||||
}
|
||||
global.LOG.Info("backup original data successful, now start to upgrade!")
|
||||
|
||||
if err := cpBinary([]string{tmpDir + "/1panel"}, "/usr/local/bin/1panel"); err != nil {
|
||||
if err := common.CopyFile(path.Join(tmpDir, "1panel"), "/usr/local/bin"); err != nil {
|
||||
global.LOG.Errorf("upgrade 1panel failed, err: %v", err)
|
||||
u.handleRollback(originalDir, 1)
|
||||
return
|
||||
}
|
||||
|
||||
if err := cpBinary([]string{tmpDir + "/1pctl"}, "/usr/local/bin/1pctl"); err != nil {
|
||||
if err := common.CopyFile(path.Join(tmpDir, "1pctl"), "/usr/local/bin"); err != nil {
|
||||
global.LOG.Errorf("upgrade 1pctl failed, err: %v", err)
|
||||
u.handleRollback(originalDir, 2)
|
||||
return
|
||||
@@ -147,7 +147,7 @@ func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
|
||||
return
|
||||
}
|
||||
|
||||
if err := cpBinary([]string{tmpDir + "/1panel.service"}, "/etc/systemd/system/1panel.service"); err != nil {
|
||||
if err := common.CopyFile(path.Join(tmpDir, "1panel.service"), "/etc/systemd/system"); err != nil {
|
||||
global.LOG.Errorf("upgrade 1panel.service failed, err: %v", err)
|
||||
u.handleRollback(originalDir, 3)
|
||||
return
|
||||
@@ -181,24 +181,23 @@ func (u *UpgradeService) handleBackup(fileOp files.FileOp, originalDir string) e
|
||||
}
|
||||
|
||||
func (u *UpgradeService) handleRollback(originalDir string, errStep int) {
|
||||
dbPath := global.CONF.System.DbPath + "/1Panel.db"
|
||||
_ = settingRepo.Update("SystemStatus", "Free")
|
||||
if err := cpBinary([]string{originalDir + "/1Panel.db"}, dbPath); err != nil {
|
||||
if err := common.CopyFile(path.Join(originalDir, "1Panel.db"), global.CONF.System.DbPath); err != nil {
|
||||
global.LOG.Errorf("rollback 1panel failed, err: %v", err)
|
||||
}
|
||||
if err := cpBinary([]string{originalDir + "/1panel"}, "/usr/local/bin/1panel"); err != nil {
|
||||
if err := common.CopyFile(path.Join(originalDir, "1panel"), "/usr/local/bin"); err != nil {
|
||||
global.LOG.Errorf("rollback 1pctl failed, err: %v", err)
|
||||
}
|
||||
if errStep == 1 {
|
||||
return
|
||||
}
|
||||
if err := cpBinary([]string{originalDir + "/1pctl"}, "/usr/local/bin/1pctl"); err != nil {
|
||||
if err := common.CopyFile(path.Join(originalDir, "1pctl"), "/usr/local/bin"); err != nil {
|
||||
global.LOG.Errorf("rollback 1panel failed, err: %v", err)
|
||||
}
|
||||
if errStep == 2 {
|
||||
return
|
||||
}
|
||||
if err := cpBinary([]string{originalDir + "/1panel.service"}, "/etc/systemd/system/1panel.service"); err != nil {
|
||||
if err := common.CopyFile(path.Join(originalDir, "1panel.service"), "/etc/systemd/system"); err != nil {
|
||||
global.LOG.Errorf("rollback 1panel failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
+122
-84
@@ -61,6 +61,7 @@ type IWebsiteService interface {
|
||||
UpdateWebsite(req request.WebsiteUpdate) error
|
||||
DeleteWebsite(req request.WebsiteDelete) error
|
||||
GetWebsite(id uint) (response.WebsiteDTO, error)
|
||||
|
||||
CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error)
|
||||
GetWebsiteDomain(websiteId uint) ([]model.WebsiteDomain, error)
|
||||
DeleteWebsiteDomain(domainId uint) error
|
||||
@@ -75,10 +76,6 @@ type IWebsiteService interface {
|
||||
ChangeDefaultServer(id uint) error
|
||||
PreInstallCheck(req request.WebsiteInstallCheckReq) ([]response.WebsitePreInstallCheck, error)
|
||||
|
||||
GetWafConfig(req request.WebsiteWafReq) (response.WebsiteWafConfig, error)
|
||||
UpdateWafConfig(req request.WebsiteWafUpdate) error
|
||||
UpdateWafFile(req request.WebsiteWafFileUpdate) (err error)
|
||||
|
||||
GetPHPConfig(id uint) (*response.PHPConfig, error)
|
||||
UpdatePHPConfig(req request.WebsitePHPConfigUpdate) error
|
||||
UpdatePHPConfigFile(req request.WebsitePHPFileUpdate) error
|
||||
@@ -182,8 +179,6 @@ func (w WebsiteService) GetWebsites() ([]response.WebsiteDTO, error) {
|
||||
}
|
||||
|
||||
func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error) {
|
||||
primaryDomainArray := strings.Split(create.PrimaryDomain, ":")
|
||||
primaryDomain := primaryDomainArray[0]
|
||||
alias := create.Alias
|
||||
if common.ContainsChinese(alias) {
|
||||
alias, err = common.PunycodeEncode(alias)
|
||||
@@ -217,7 +212,7 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
|
||||
|
||||
defaultDate, _ := time.Parse(constant.DateLayout, constant.DefaultDate)
|
||||
website := &model.Website{
|
||||
PrimaryDomain: primaryDomain,
|
||||
PrimaryDomain: create.PrimaryDomain,
|
||||
Type: create.Type,
|
||||
Alias: alias,
|
||||
Remark: create.Remark,
|
||||
@@ -327,12 +322,16 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
|
||||
case constant.RuntimeNode:
|
||||
website.Proxy = fmt.Sprintf("127.0.0.1:%d", runtime.Port)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if err = configDefaultNginx(website, domains, appInstall, runtime); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = createWafConfig(website, domains); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tx, ctx := helper.GetTxAndContext()
|
||||
defer tx.Rollback()
|
||||
if err = websiteRepo.Create(ctx, website); err != nil {
|
||||
@@ -425,17 +424,18 @@ func (w WebsiteService) DeleteWebsite(req request.WebsiteDelete) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := delNginxConfig(website, req.ForceDelete); err != nil {
|
||||
if err = delNginxConfig(website, req.ForceDelete); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = delWafConfig(website, req.ForceDelete); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if checkIsLinkApp(website) && req.DeleteApp {
|
||||
appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID))
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
if !reflect.DeepEqual(model.AppInstall{}, appInstall) {
|
||||
if err := deleteAppInstall(appInstall, true, req.ForceDelete, true); err != nil && !req.ForceDelete {
|
||||
appInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID))
|
||||
if appInstall.ID > 0 {
|
||||
if err = deleteAppInstall(appInstall, true, req.ForceDelete, true); err != nil && !req.ForceDelete {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -494,6 +494,53 @@ func (w WebsiteService) CreateWebsiteDomain(create request.WebsiteDomainCreate)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data")
|
||||
fileOp := files.NewFileOp()
|
||||
if fileOp.Stat(wafDataPath) {
|
||||
websitesConfigPath := path.Join(wafDataPath, "conf", "sites.json")
|
||||
content, err := fileOp.GetContent(websitesConfigPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var websitesArray []request.WafWebsite
|
||||
if content != nil {
|
||||
if err := json.Unmarshal(content, &websitesArray); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
for index, wafWebsite := range websitesArray {
|
||||
if wafWebsite.Key == website.Alias {
|
||||
wafSite := request.WafWebsite{
|
||||
Key: website.Alias,
|
||||
Domains: wafWebsite.Domains,
|
||||
Host: wafWebsite.Host,
|
||||
}
|
||||
for _, domain := range domainModels {
|
||||
wafSite.Domains = append(wafSite.Domains, domain.Domain)
|
||||
if domain.Port != 80 && domain.Port != 443 {
|
||||
wafSite.Host = append(wafSite.Host, domain.Domain+":"+string(rune(domain.Port)))
|
||||
}
|
||||
}
|
||||
if len(wafSite.Host) == 0 {
|
||||
wafSite.Host = []string{}
|
||||
}
|
||||
websitesArray[index] = wafSite
|
||||
break
|
||||
}
|
||||
}
|
||||
websitesContent, err := json.Marshal(websitesArray)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := fileOp.SaveFileWithByte(websitesConfigPath, websitesContent, 0644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return domainModels, websiteDomainRepo.BatchCreate(context.TODO(), domainModels)
|
||||
}
|
||||
|
||||
@@ -523,6 +570,7 @@ func (w WebsiteService) DeleteWebsiteDomain(domainId uint) error {
|
||||
if oldDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(webSiteDomain.WebsiteID), websiteDomainRepo.WithDomain(webSiteDomain.Domain)); len(oldDomains) == 1 {
|
||||
domains = append(domains, webSiteDomain.Domain)
|
||||
}
|
||||
|
||||
if len(ports) > 0 || len(domains) > 0 {
|
||||
stringBinds := make([]string, len(ports))
|
||||
for i := 0; i < len(ports); i++ {
|
||||
@@ -533,6 +581,63 @@ func (w WebsiteService) DeleteWebsiteDomain(domainId uint) error {
|
||||
}
|
||||
}
|
||||
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data")
|
||||
fileOp := files.NewFileOp()
|
||||
if fileOp.Stat(wafDataPath) {
|
||||
websitesConfigPath := path.Join(wafDataPath, "conf", "sites.json")
|
||||
content, err := fileOp.GetContent(websitesConfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var websitesArray []request.WafWebsite
|
||||
var newWebsitesArray []request.WafWebsite
|
||||
if content != nil {
|
||||
if err := json.Unmarshal(content, &websitesArray); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, wafWebsite := range websitesArray {
|
||||
if wafWebsite.Key == website.Alias {
|
||||
wafSite := wafWebsite
|
||||
oldDomains := wafSite.Domains
|
||||
var newDomains []string
|
||||
for _, domain := range oldDomains {
|
||||
if domain == webSiteDomain.Domain {
|
||||
continue
|
||||
}
|
||||
newDomains = append(newDomains, domain)
|
||||
}
|
||||
wafSite.Domains = newDomains
|
||||
oldHostArray := wafSite.Host
|
||||
var newHostArray []string
|
||||
for _, host := range oldHostArray {
|
||||
if host == webSiteDomain.Domain+":"+string(rune(webSiteDomain.Port)) {
|
||||
continue
|
||||
}
|
||||
newHostArray = append(newHostArray, host)
|
||||
}
|
||||
wafSite.Host = newHostArray
|
||||
if len(wafSite.Host) == 0 {
|
||||
wafSite.Host = []string{}
|
||||
}
|
||||
newWebsitesArray = append(newWebsitesArray, wafSite)
|
||||
} else {
|
||||
newWebsitesArray = append(newWebsitesArray, wafWebsite)
|
||||
}
|
||||
}
|
||||
websitesContent, err := json.Marshal(newWebsitesArray)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = fileOp.SaveFileWithByte(websitesConfigPath, websitesContent, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return websiteDomainRepo.DeleteBy(context.TODO(), commonRepo.WithByID(domainId))
|
||||
}
|
||||
|
||||
@@ -852,56 +957,6 @@ func (w WebsiteService) PreInstallCheck(req request.WebsiteInstallCheckReq) ([]r
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (w WebsiteService) GetWafConfig(req request.WebsiteWafReq) (response.WebsiteWafConfig, error) {
|
||||
var res response.WebsiteWafConfig
|
||||
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
res.Enable = true
|
||||
if req.Key != "" {
|
||||
params, err := getNginxParamsByKeys(constant.NginxScopeServer, []string{"set"}, &website)
|
||||
if err != nil {
|
||||
return res, nil
|
||||
}
|
||||
for _, param := range params {
|
||||
if param.Params[0] == req.Key {
|
||||
res.Enable = len(param.Params) > 1 && param.Params[1] == "on"
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nginxFull, err := getNginxFull(&website)
|
||||
if err != nil {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
filePath := path.Join(nginxFull.SiteDir, "sites", website.Alias, "waf", "rules", req.Rule+".json")
|
||||
content, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return res, nil
|
||||
}
|
||||
res.Content = string(content)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (w WebsiteService) UpdateWafConfig(req request.WebsiteWafUpdate) error {
|
||||
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updateValue := "on"
|
||||
if !req.Enable {
|
||||
updateValue = "off"
|
||||
}
|
||||
return updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{
|
||||
{Name: "set", Params: []string{req.Key, updateValue}},
|
||||
}, &website)
|
||||
}
|
||||
|
||||
func (w WebsiteService) UpdateNginxConfigFile(req request.WebsiteNginxUpdate) error {
|
||||
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
@@ -1899,7 +1954,7 @@ func (w WebsiteService) UpdateAntiLeech(req request.NginxAntiLeechUpdate) (err e
|
||||
Parameters: []string{"off"},
|
||||
})
|
||||
validDir := &components.Directive{
|
||||
Name: "valid_referers",
|
||||
Name: "valid_referrers",
|
||||
Parameters: []string{},
|
||||
}
|
||||
if req.NoneRef {
|
||||
@@ -1968,7 +2023,7 @@ func (w WebsiteService) GetAntiLeech(id uint) (*response.NginxAntiLeechRes, erro
|
||||
}
|
||||
lDirectives := location.GetBlock().GetDirectives()
|
||||
for _, lDir := range lDirectives {
|
||||
if lDir.GetName() == "valid_referers" {
|
||||
if lDir.GetName() == "valid_referrers" {
|
||||
res.Enable = true
|
||||
params := lDir.GetParameters()
|
||||
for _, param := range params {
|
||||
@@ -2339,23 +2394,6 @@ func (w WebsiteService) UpdateRedirectFile(req request.NginxRedirectUpdate) (err
|
||||
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
|
||||
}
|
||||
|
||||
func (w WebsiteService) UpdateWafFile(req request.WebsiteWafFileUpdate) (err error) {
|
||||
var (
|
||||
website model.Website
|
||||
nginxInstall model.AppInstall
|
||||
)
|
||||
website, err = websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nginxInstall, err = getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
rulePath := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "waf", "rules", fmt.Sprintf("%s.json", req.Type))
|
||||
return files.NewFileOp().WriteFile(rulePath, strings.NewReader(req.Content), 0755)
|
||||
}
|
||||
|
||||
func (w WebsiteService) LoadWebsiteDirConfig(req request.WebsiteCommonReq) (*response.WebsiteDirConfig, error) {
|
||||
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/xpack"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
@@ -197,7 +199,7 @@ func createWebsiteFolder(nginxInstall model.AppInstall, website *model.Website,
|
||||
}
|
||||
}
|
||||
}
|
||||
return fileOp.CopyDir(path.Join(nginxFolder, "www", "common", "waf", "rules"), path.Join(siteFolder, "waf"))
|
||||
return nil
|
||||
}
|
||||
|
||||
func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, appInstall *model.AppInstall, runtime *model.Runtime) error {
|
||||
@@ -233,12 +235,8 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
|
||||
server.UpdateServerName(serverNames)
|
||||
|
||||
siteFolder := path.Join("/www", "sites", website.Alias)
|
||||
commonFolder := path.Join("/www", "common")
|
||||
server.UpdateDirective("access_log", []string{path.Join(siteFolder, "log", "access.log")})
|
||||
server.UpdateDirective("error_log", []string{path.Join(siteFolder, "log", "error.log")})
|
||||
server.UpdateDirective("access_by_lua_file", []string{path.Join(commonFolder, "waf", "access.lua")})
|
||||
server.UpdateDirective("set", []string{"$RulePath", path.Join(siteFolder, "waf", "rules")})
|
||||
server.UpdateDirective("set", []string{"$logdir", path.Join(siteFolder, "log")})
|
||||
|
||||
rootIndex := path.Join("/www/sites", website.Alias, "index")
|
||||
switch website.Type {
|
||||
@@ -285,6 +283,99 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
|
||||
return nil
|
||||
}
|
||||
|
||||
func createWafConfig(website *model.Website, domains []model.WebsiteDomain) error {
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data")
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(wafDataPath) {
|
||||
return nil
|
||||
}
|
||||
websitesConfigPath := path.Join(wafDataPath, "conf", "sites.json")
|
||||
content, err := fileOp.GetContent(websitesConfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var websitesArray []request.WafWebsite
|
||||
if len(content) != 0 {
|
||||
if err := json.Unmarshal(content, &websitesArray); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
wafWebsite := request.WafWebsite{
|
||||
Key: website.Alias,
|
||||
Domains: make([]string, 0),
|
||||
Host: make([]string, 0),
|
||||
}
|
||||
|
||||
for _, domain := range domains {
|
||||
wafWebsite.Domains = append(wafWebsite.Domains, domain.Domain)
|
||||
if domain.Port != 80 && domain.Port != 443 {
|
||||
wafWebsite.Host = append(wafWebsite.Host, domain.Domain+":"+string(rune(domain.Port)))
|
||||
}
|
||||
}
|
||||
websitesArray = append(websitesArray, wafWebsite)
|
||||
websitesContent, err := json.Marshal(websitesArray)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fileOp.SaveFileWithByte(websitesConfigPath, websitesContent, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
sitesDir = path.Join(wafDataPath, "sites")
|
||||
defaultConfigPath = path.Join(wafDataPath, "conf", "siteConfig.json")
|
||||
defaultRuleDir = path.Join(wafDataPath, "rules")
|
||||
websiteDir = path.Join(sitesDir, website.Alias)
|
||||
)
|
||||
|
||||
defaultConfigContent, err := fileOp.GetContent(defaultConfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !fileOp.Stat(websiteDir) {
|
||||
if err = fileOp.CreateDir(websiteDir, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = fileOp.DeleteDir(websiteDir)
|
||||
}
|
||||
}()
|
||||
|
||||
if err = fileOp.SaveFileWithByte(path.Join(websiteDir, "config.json"), defaultConfigContent, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
websiteRuleDir := path.Join(websiteDir, "rules")
|
||||
if !fileOp.Stat(websiteRuleDir) {
|
||||
if err := fileOp.CreateDir(websiteRuleDir, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
defaultRulesName := []string{"acl", "args", "cookie", "defaultUaBlack", "defaultUrlBlack", "fileExt", "header", "methodWhite"}
|
||||
for _, ruleName := range defaultRulesName {
|
||||
srcPath := path.Join(defaultRuleDir, ruleName+".json")
|
||||
if err = fileOp.Copy(srcPath, websiteRuleDir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err = opNginx(nginxInstall.ContainerName, constant.NginxCheck); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func delNginxConfig(website model.Website, force bool) error {
|
||||
nginxApp, err := appRepo.GetFirst(appRepo.WithKey(constant.AppOpenresty))
|
||||
if err != nil {
|
||||
@@ -310,6 +401,7 @@ func delNginxConfig(website model.Website, force bool) error {
|
||||
}
|
||||
sitePath := path.Join(constant.AppInstallDir, constant.AppOpenresty, nginxInstall.Name, "www", "sites", website.Alias)
|
||||
if fileOp.Stat(sitePath) {
|
||||
xpack.RemoveTamper(website.Alias)
|
||||
_ = fileOp.DeleteDir(sitePath)
|
||||
}
|
||||
|
||||
@@ -322,6 +414,52 @@ func delNginxConfig(website model.Website, force bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func delWafConfig(website model.Website, force bool) error {
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data")
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(wafDataPath) {
|
||||
return nil
|
||||
}
|
||||
websitesConfigPath := path.Join(wafDataPath, "conf", "sites.json")
|
||||
content, err := fileOp.GetContent(websitesConfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var websitesArray []request.WafWebsite
|
||||
var newWebsiteArray []request.WafWebsite
|
||||
if len(content) > 0 {
|
||||
if err = json.Unmarshal(content, &websitesArray); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, wafWebsite := range websitesArray {
|
||||
if wafWebsite.Key != website.Alias {
|
||||
newWebsiteArray = append(newWebsiteArray, wafWebsite)
|
||||
}
|
||||
}
|
||||
websitesContent, err := json.Marshal(newWebsiteArray)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fileOp.SaveFileWithByte(websitesConfigPath, websitesContent, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_ = fileOp.DeleteDir(path.Join(wafDataPath, "sites", website.Alias))
|
||||
|
||||
if err := opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil {
|
||||
if force {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addListenAndServerName(website model.Website, ports []int, domains []string) error {
|
||||
nginxFull, err := getNginxFull(&website)
|
||||
if err != nil {
|
||||
|
||||
@@ -47,10 +47,14 @@ func WithDetail(Key string, detail interface{}, err error) BusinessError {
|
||||
}
|
||||
|
||||
func WithErr(Key string, err error) BusinessError {
|
||||
paramMap := map[string]interface{}{}
|
||||
if err != nil {
|
||||
paramMap["err"] = err
|
||||
}
|
||||
return BusinessError{
|
||||
Msg: Key,
|
||||
Detail: "",
|
||||
Err: err,
|
||||
Msg: Key,
|
||||
Map: paramMap,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ type System struct {
|
||||
Entrance string `mapstructure:"entrance"`
|
||||
IsDemo bool `mapstructure:"is_demo"`
|
||||
AppRepo string `mapstructure:"app_repo"`
|
||||
ChangeUserInfo bool `mapstructure:"change_user_info"`
|
||||
ChangeUserInfo string `mapstructure:"change_user_info"`
|
||||
OneDriveID string `mapstructure:"one_drive_id"`
|
||||
OneDriveSc string `mapstructure:"one_drive_sc"`
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ const (
|
||||
CodeErrDomain = 409
|
||||
CodeErrInternalServer = 500
|
||||
CodeErrHeader = 406
|
||||
|
||||
CodeErrXpack = 410
|
||||
)
|
||||
|
||||
// internal
|
||||
@@ -43,6 +45,9 @@ var (
|
||||
ErrNameIsExist = "ErrNameIsExist"
|
||||
ErrDemoEnvironment = "ErrDemoEnvironment"
|
||||
ErrCmdIllegal = "ErrCmdIllegal"
|
||||
ErrXpackNotFound = "ErrXpackNotFound"
|
||||
ErrXpackNotActive = "ErrXpackNotActive"
|
||||
ErrXpackOutOfDate = "ErrXpackOutOfDate"
|
||||
)
|
||||
|
||||
// app
|
||||
@@ -150,3 +155,11 @@ var (
|
||||
var (
|
||||
ErrNotExistUser = "ErrNotExistUser"
|
||||
)
|
||||
|
||||
// license
|
||||
var (
|
||||
ErrLicense = "ErrLicense"
|
||||
ErrLicenseCheck = "ErrLicenseCheck"
|
||||
ErrLicenseSave = "ErrLicenseSave"
|
||||
ErrLicenseSync = "ErrLicenseSync"
|
||||
)
|
||||
|
||||
@@ -13,13 +13,14 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
DB *gorm.DB
|
||||
LOG *logrus.Logger
|
||||
CONF configs.ServerConfig
|
||||
VALID *validator.Validate
|
||||
SESSION *psession.PSession
|
||||
CACHE *badger_db.Cache
|
||||
Viper *viper.Viper
|
||||
DB *gorm.DB
|
||||
MonitorDB *gorm.DB
|
||||
LOG *logrus.Logger
|
||||
CONF configs.ServerConfig
|
||||
VALID *validator.Validate
|
||||
SESSION *psession.PSession
|
||||
CACHE *badger_db.Cache
|
||||
Viper *viper.Viper
|
||||
|
||||
Cron *cron.Cron
|
||||
MonitorCronID cron.EntryID
|
||||
|
||||
@@ -74,6 +74,7 @@ ErrFileDownloadDir: "Download folder not supported"
|
||||
ErrCmdNotFound: "{{ .name}} command does not exist, please install this command on the host first"
|
||||
ErrSourcePathNotFound: "Source directory does not exist"
|
||||
ErrFavoriteExist: "This path has been collected"
|
||||
ErrInvalidChar: "Illegal characters are prohibited"
|
||||
|
||||
#website
|
||||
ErrDomainIsExist: "Domain is already exist"
|
||||
@@ -144,7 +145,7 @@ ErrNodeModulesNotFound: "The node_modules folder does not exist! Please edit the
|
||||
#setting
|
||||
ErrBackupInUsed: "The backup account is already being used in a cronjob and cannot be deleted."
|
||||
ErrBackupCheck: "Backup account test connection failed {{ .err}}"
|
||||
ErrOSSConn: "Unable to successfully request the latest version. Please check if the server can connect to the external network environment."
|
||||
ErrOSSConn: "Unable to retrieve the latest version, please check if the server can connect to the external network."
|
||||
ErrEntrance: "Security entrance information error. Please check and try again!"
|
||||
|
||||
#tool
|
||||
@@ -171,4 +172,18 @@ ErrBanAction: "Setting failed, the current {{ .name }} service is unavailable, p
|
||||
ErrScope: "Modification of this configuration is not supported"
|
||||
ErrStateChange: "State modification failed"
|
||||
ErrRuleExist: "Rule is Exist"
|
||||
ErrRuleNotExist: "Rule is not Exist"
|
||||
ErrRuleNotExist: "Rule is not Exist"
|
||||
ErrParseIP: "IP format error"
|
||||
ErrDefaultIP: "default is a reserved name, please change it to another name"
|
||||
ErrGroupInUse: "The IP group is used by the black/white list and cannot be deleted"
|
||||
ErrGroupExist: "IP group name already exists"
|
||||
ErrIPRange: "Wrong IP range"
|
||||
|
||||
#license
|
||||
ErrLicense: "License format error, please check and try again!"
|
||||
ErrLicenseCheck: "License verification failed, please check and try again!"
|
||||
ErrLicenseSave: "Failed to save license information, error {{ .err }}, please try again!"
|
||||
ErrLicenseSync: "Failed to sync license information, no license information detected in the database!"
|
||||
ErrXpackNotFound: "This section is a professional edition feature, please import the license first in Panel Settings-License interface"
|
||||
ErrXpackNotActive: "This section is a professional edition feature, please synchronize the license status first in Panel Settings-License interface"
|
||||
ErrXpackOutOfDate: "The current license has expired, please re-import the license in Panel Settings-License interface"
|
||||
|
||||
@@ -23,6 +23,7 @@ ErrTypePortRange: '連接埠範圍需要在 1-65535 之間'
|
||||
Success: "成功"
|
||||
Failed: "失敗"
|
||||
SystemRestart: "系統重啟導致任務中斷"
|
||||
ErrInvalidChar: "禁止使用非法字元"
|
||||
|
||||
#app
|
||||
ErrPortInUsed: "{{ .detail }} 端口已被佔用!"
|
||||
@@ -145,7 +146,7 @@ ErrNodeModulesNotFound: "node_modules 文件夾不存在!請編輯運行環境
|
||||
#setting
|
||||
ErrBackupInUsed: "該備份帳號已在計劃任務中使用,無法刪除"
|
||||
ErrBackupCheck: "備份帳號測試連接失敗 {{ .err}}"
|
||||
ErrOSSConn: "無法成功請求最新版本,請檢查伺服器是否能夠連接到外部網絡環境。"
|
||||
ErrOSSConn: "無法獲取最新版本,請確認伺服器是否能夠連接外部網路。"
|
||||
ErrEntrance: "安全入口信息錯誤,請檢查後重試!"
|
||||
|
||||
#tool
|
||||
@@ -173,3 +174,17 @@ ErrScope: "不支援修改此配置"
|
||||
ErrStateChange: "狀態修改失敗"
|
||||
ErrRuleExist: "規則名稱已存在"
|
||||
ErrRuleNotExist: "規則不存在"
|
||||
ErrParseIP: "IP 格式錯誤"
|
||||
ErrDefaultIP: "default 為保留名稱,請更換其他名稱"
|
||||
ErrGroupInUse: "IP 群組被黑/白名單使用,無法刪除"
|
||||
ErrGroupExist: "IP 群組名稱已存在"
|
||||
ErrIPRange: "IP 範圍錯誤"
|
||||
|
||||
#license
|
||||
ErrLicense: "許可證格式錯誤,請檢查後重試!"
|
||||
ErrLicenseCheck: "許可證校驗失敗,請檢查後重試!"
|
||||
ErrLicenseSave: "許可證信息保存失敗,錯誤 {{ .err }}, 請重試!"
|
||||
ErrLicenseSync: "許可證信息同步失敗,資料庫中未檢測到許可證信息!"
|
||||
ErrXpackNotFound: "該部分為專業版功能,請先在 面板設置-許可證 界面導入許可證"
|
||||
ErrXpackNotActive: "該部分為專業版功能,請先在 面板設置-許可證 界面同步許可證狀態"
|
||||
ErrXpackOutOfDate: "當前許可證已過期,請重新在 面板設置-許可證 界面導入許可證"
|
||||
|
||||
@@ -74,6 +74,7 @@ ErrFileDownloadDir: "不支持下载文件夹"
|
||||
ErrCmdNotFound: "{{ .name}} 命令不存在,请先在宿主机安装此命令"
|
||||
ErrSourcePathNotFound: "源目录不存在"
|
||||
ErrFavoriteExist: "已收藏此路径"
|
||||
ErrInvalidChar: "禁止使用非法字符"
|
||||
|
||||
#website
|
||||
ErrDomainIsExist: "域名已存在"
|
||||
@@ -144,7 +145,7 @@ ErrNodeModulesNotFound: "node_modules 文件夹不存在!请编辑运行环境
|
||||
#setting
|
||||
ErrBackupInUsed: "该备份账号已在计划任务中使用,无法删除"
|
||||
ErrBackupCheck: "备份账号测试连接失败 {{ .err}}"
|
||||
ErrOSSConn: "无法成功请求最新版本,请检查服务器是否能够连接到外部网络环境。"
|
||||
ErrOSSConn: "无法获取最新版本,请确认服务器是否能够连接外部网络。"
|
||||
ErrEntrance: "安全入口信息错误,请检查后重试!"
|
||||
|
||||
#tool
|
||||
@@ -171,4 +172,19 @@ ErrBanAction: "设置失败,当前 {{ .name }} 服务不可用,请检查后
|
||||
ErrScope: "不支持修改此配置"
|
||||
ErrStateChange: "状态修改失败"
|
||||
ErrRuleExist: "规则名称已存在"
|
||||
ErrRuleNotExist: "规则不存在"
|
||||
ErrRuleNotExist: "规则不存在"
|
||||
ErrParseIP: "IP 格式错误"
|
||||
ErrDefaultIP: "default 为保留名称,请更换其他名称"
|
||||
ErrGroupInUse: "IP 组被黑/白名单使用,无法删除"
|
||||
ErrGroupExist: "IP 组名称已存在"
|
||||
ErrIPRange: "IP 范围错误"
|
||||
|
||||
#license
|
||||
ErrLicense: "许可证格式错误,请检查后重试!"
|
||||
ErrLicenseCheck: "许可证校验失败,请检查后重试!"
|
||||
ErrLicenseSave: "许可证信息保存失败,错误 {{ .err }},请重试!"
|
||||
ErrLicenseSync: "许可证信息同步失败,数据库中未检测到许可证信息!"
|
||||
ErrXpackNotFound: "该部分为专业版功能,请先在 面板设置-许可证 界面导入许可证"
|
||||
ErrXpackNotActive: "该部分为专业版功能,请先在 面板设置-许可证 界面同步许可证状态"
|
||||
ErrXpackOutOfDate: "当前许可证已过期,请重新在 面板设置-许可证 界面导入许可证"
|
||||
|
||||
|
||||
+35
-1
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
@@ -34,6 +35,7 @@ func Init() {
|
||||
Colorful: false,
|
||||
},
|
||||
)
|
||||
initMonitorDB(newLogger)
|
||||
|
||||
db, err := gorm.Open(sqlite.Open(fullPath), &gorm.Config{
|
||||
DisableForeignKeyConstraintWhenMigrating: true,
|
||||
@@ -45,7 +47,7 @@ func Init() {
|
||||
_ = db.Exec("PRAGMA journal_mode = WAL;")
|
||||
sqlDB, dbError := db.DB()
|
||||
if dbError != nil {
|
||||
panic(err)
|
||||
panic(dbError)
|
||||
}
|
||||
sqlDB.SetConnMaxIdleTime(10)
|
||||
sqlDB.SetMaxOpenConns(100)
|
||||
@@ -54,3 +56,35 @@ func Init() {
|
||||
global.DB = db
|
||||
global.LOG.Info("init db successfully")
|
||||
}
|
||||
|
||||
func initMonitorDB(newLogger logger.Interface) {
|
||||
if _, err := os.Stat(global.CONF.System.DbPath); err != nil {
|
||||
if err := os.MkdirAll(global.CONF.System.DbPath, os.ModePerm); err != nil {
|
||||
panic(fmt.Errorf("init db dir failed, err: %v", err))
|
||||
}
|
||||
}
|
||||
fullPath := path.Join(global.CONF.System.DbPath, "monitor.db")
|
||||
if _, err := os.Stat(fullPath); err != nil {
|
||||
if _, err := os.Create(fullPath); err != nil {
|
||||
panic(fmt.Errorf("init db file failed, err: %v", err))
|
||||
}
|
||||
}
|
||||
|
||||
db, err := gorm.Open(sqlite.Open(fullPath), &gorm.Config{
|
||||
DisableForeignKeyConstraintWhenMigrating: true,
|
||||
Logger: newLogger,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
sqlDB, dbError := db.DB()
|
||||
if dbError != nil {
|
||||
panic(dbError)
|
||||
}
|
||||
sqlDB.SetConnMaxIdleTime(10)
|
||||
sqlDB.SetMaxOpenConns(100)
|
||||
sqlDB.SetConnMaxLifetime(time.Hour)
|
||||
|
||||
global.MonitorDB = db
|
||||
global.LOG.Info("init monitor db successfully")
|
||||
}
|
||||
|
||||
+40
-15
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/repo"
|
||||
@@ -57,21 +58,7 @@ func Init() {
|
||||
global.LOG.Fatalf("init service before start failed, err: %v", err)
|
||||
}
|
||||
|
||||
if global.CONF.System.ChangeUserInfo {
|
||||
if err := settingRepo.Update("UserName", common.RandStrAndNum(10)); err != nil {
|
||||
global.LOG.Fatalf("init username before start failed, err: %v", err)
|
||||
}
|
||||
pass, _ := encrypt.StringEncrypt(common.RandStrAndNum(10))
|
||||
if err := settingRepo.Update("Password", pass); err != nil {
|
||||
global.LOG.Fatalf("init password before start failed, err: %v", err)
|
||||
}
|
||||
if err := settingRepo.Update("SecurityEntrance", common.RandStrAndNum(10)); err != nil {
|
||||
global.LOG.Fatalf("init entrance before start failed, err: %v", err)
|
||||
}
|
||||
|
||||
sudo := cmd.SudoHandleCmd()
|
||||
_, _ = cmd.Execf("%s sed -i '/CHANGE_USER_INFO=true/d' /usr/local/bin/1pctl", sudo)
|
||||
}
|
||||
handleUserInfo(global.CONF.System.ChangeUserInfo, settingRepo)
|
||||
|
||||
handleCronjobStatus()
|
||||
handleSnapStatus()
|
||||
@@ -173,3 +160,41 @@ func loadLocalDir() {
|
||||
}
|
||||
global.LOG.Errorf("error type dir: %T", varMap["dir"])
|
||||
}
|
||||
|
||||
func handleUserInfo(tags string, settingRepo repo.ISettingRepo) {
|
||||
if len(tags) == 0 {
|
||||
return
|
||||
}
|
||||
if tags == "all" {
|
||||
if err := settingRepo.Update("UserName", common.RandStrAndNum(10)); err != nil {
|
||||
global.LOG.Fatalf("init username before start failed, err: %v", err)
|
||||
}
|
||||
pass, _ := encrypt.StringEncrypt(common.RandStrAndNum(10))
|
||||
if err := settingRepo.Update("Password", pass); err != nil {
|
||||
global.LOG.Fatalf("init password before start failed, err: %v", err)
|
||||
}
|
||||
if err := settingRepo.Update("SecurityEntrance", common.RandStrAndNum(10)); err != nil {
|
||||
global.LOG.Fatalf("init entrance before start failed, err: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if strings.Contains(global.CONF.System.ChangeUserInfo, "username") {
|
||||
if err := settingRepo.Update("UserName", common.RandStrAndNum(10)); err != nil {
|
||||
global.LOG.Fatalf("init username before start failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
if strings.Contains(global.CONF.System.ChangeUserInfo, "password") {
|
||||
pass, _ := encrypt.StringEncrypt(common.RandStrAndNum(10))
|
||||
if err := settingRepo.Update("Password", pass); err != nil {
|
||||
global.LOG.Fatalf("init password before start failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
if strings.Contains(global.CONF.System.ChangeUserInfo, "entrance") {
|
||||
if err := settingRepo.Update("SecurityEntrance", common.RandStrAndNum(10)); err != nil {
|
||||
global.LOG.Fatalf("init entrance before start failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
sudo := cmd.SudoHandleCmd()
|
||||
_, _ = cmd.Execf("%s sed -i '/CHANGE_USER_INFO=%v/d' /usr/local/bin/1pctl", sudo, global.CONF.System.ChangeUserInfo)
|
||||
}
|
||||
|
||||
@@ -75,6 +75,12 @@ func Init() {
|
||||
|
||||
migrations.AddSnapshotIgnore,
|
||||
migrations.AddDatabaseIsDelete,
|
||||
migrations.AddXpackHideMenu,
|
||||
migrations.AddCronjobCommand,
|
||||
migrations.NewMonitorDB,
|
||||
migrations.AddNoAuthSetting,
|
||||
migrations.UpdateXpackHideMenu,
|
||||
migrations.AddMenuTabsSetting,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
||||
@@ -2,6 +2,7 @@ package migrations
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -25,3 +26,115 @@ var AddDatabaseIsDelete = &gormigrate.Migration{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var AddXpackHideMenu = &gormigrate.Migration{
|
||||
ID: "20240328-add-xpack-hide-menu",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.Create(&model.Setting{Key: "XpackHideMenu", Value: "{\"id\":\"1\",\"label\":\"/xpack\",\"isCheck\":true,\"title\":\"xpack.menu\",\"children\":[{\"id\":\"2\",\"title\":\"xpack.waf.name\",\"path\":\"/xpack/waf/dashboard\",\"label\":\"Dashboard\",\"isCheck\":true},{\"id\":\"3\",\"title\":\"xpack.tamper.tamper\",\"path\":\"/xpack/tamper\",\"label\":\"Tamper\",\"isCheck\":true},{\"id\":\"4\",\"title\":\"xpack.setting.setting\",\"path\":\"/xpack/setting\",\"label\":\"XSetting\",\"isCheck\":true}]}"}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var AddCronjobCommand = &gormigrate.Migration{
|
||||
ID: "20240403-add-cronjob-command",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.Cronjob{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var NewMonitorDB = &gormigrate.Migration{
|
||||
ID: "20240408-new-monitor-db",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
var (
|
||||
bases []model.MonitorBase
|
||||
ios []model.MonitorIO
|
||||
networks []model.MonitorNetwork
|
||||
)
|
||||
_ = tx.Find(&bases).Error
|
||||
_ = tx.Find(&ios).Error
|
||||
_ = tx.Find(&networks).Error
|
||||
|
||||
if err := global.MonitorDB.AutoMigrate(&model.MonitorBase{}, &model.MonitorIO{}, &model.MonitorNetwork{}); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = global.MonitorDB.Exec("DELETE FROM monitor_bases").Error
|
||||
_ = global.MonitorDB.Exec("DELETE FROM monitor_ios").Error
|
||||
_ = global.MonitorDB.Exec("DELETE FROM monitor_networks").Error
|
||||
|
||||
if len(bases) != 0 {
|
||||
for i := 0; i <= len(bases)/200; i++ {
|
||||
var itemData []model.MonitorBase
|
||||
if 200*(i+1) <= len(bases) {
|
||||
itemData = bases[200*i : 200*(i+1)]
|
||||
} else {
|
||||
itemData = bases[200*i:]
|
||||
}
|
||||
if err := global.MonitorDB.Create(&itemData).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(ios) != 0 {
|
||||
for i := 0; i <= len(ios)/200; i++ {
|
||||
var itemData []model.MonitorIO
|
||||
if 200*(i+1) <= len(ios) {
|
||||
itemData = ios[200*i : 200*(i+1)]
|
||||
} else {
|
||||
itemData = ios[200*i:]
|
||||
}
|
||||
if err := global.MonitorDB.Create(&itemData).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(networks) != 0 {
|
||||
for i := 0; i <= len(networks)/200; i++ {
|
||||
var itemData []model.MonitorNetwork
|
||||
if 200*(i+1) <= len(networks) {
|
||||
itemData = networks[200*i : 200*(i+1)]
|
||||
} else {
|
||||
itemData = networks[200*i:]
|
||||
}
|
||||
if err := global.MonitorDB.Create(&itemData).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var AddNoAuthSetting = &gormigrate.Migration{
|
||||
ID: "20240328-add-no-auth-setting",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.Create(&model.Setting{Key: "NoAuthSetting", Value: "200"}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var UpdateXpackHideMenu = &gormigrate.Migration{
|
||||
ID: "20240411-update-xpack-hide-menu",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.Model(&model.Setting{}).Where("key", "XpackHideMenu").Updates(map[string]interface{}{"value": "{\"id\":\"1\",\"label\":\"/xpack\",\"isCheck\":true,\"title\":\"xpack.menu\",\"children\":[{\"id\":\"2\",\"title\":\"xpack.waf.name\",\"path\":\"/xpack/waf/dashboard\",\"label\":\"Dashboard\",\"isCheck\":true},{\"id\":\"3\",\"title\":\"xpack.tamper.tamper\",\"path\":\"/xpack/tamper\",\"label\":\"Tamper\",\"isCheck\":true},{\"id\":\"4\",\"title\":\"xpack.gpu.gpu\",\"path\":\"/xpack/gpu\",\"label\":\"GPU\",\"isCheck\":true},{\"id\":\"5\",\"title\":\"xpack.setting.setting\",\"path\":\"/xpack/setting\",\"label\":\"XSetting\",\"isCheck\":true}]}"}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var AddMenuTabsSetting = &gormigrate.Migration{
|
||||
ID: "20240415-add-menu-tabs-setting",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.Create(&model.Setting{Key: "MenuTabs", Value: "disable"}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@ package router
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/i18n"
|
||||
"github.com/1Panel-dev/1Panel/backend/middleware"
|
||||
@@ -12,7 +15,6 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
swaggerfiles "github.com/swaggo/files"
|
||||
ginSwagger "github.com/swaggo/gin-swagger"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -21,6 +23,7 @@ var (
|
||||
|
||||
func setWebStatic(rootRouter *gin.RouterGroup) {
|
||||
rootRouter.StaticFS("/public", http.FS(web.Favicon))
|
||||
rootRouter.Static("/api/v1/images", "./uploads")
|
||||
rootRouter.Use(func(c *gin.Context) {
|
||||
c.Next()
|
||||
})
|
||||
@@ -61,6 +64,8 @@ func Routers() *gin.Engine {
|
||||
PublicGroup.GET("/health", func(c *gin.Context) {
|
||||
c.JSON(200, "ok")
|
||||
})
|
||||
baseApi := v1.ApiGroupApp.BaseApi
|
||||
PublicGroup.GET("/api/v1/respagecode", baseApi.GetResponsePage)
|
||||
PublicGroup.Use(gzip.Gzip(gzip.DefaultCompression))
|
||||
setWebStatic(PublicGroup)
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ func Init() {
|
||||
global.CONF.System.Username = username
|
||||
global.CONF.System.Password = password
|
||||
global.CONF.System.Entrance = entrance
|
||||
global.CONF.System.ChangeUserInfo = loadChange()
|
||||
global.CONF.System.ChangeUserInfo = loadChangeInfo()
|
||||
global.Viper = v
|
||||
}
|
||||
|
||||
@@ -112,10 +112,10 @@ func loadParams(param string) string {
|
||||
return info
|
||||
}
|
||||
|
||||
func loadChange() bool {
|
||||
func loadChangeInfo() string {
|
||||
stdout, err := cmd.Exec("grep '^CHANGE_USER_INFO=' /usr/bin/1pctl | cut -d'=' -f2")
|
||||
if err != nil {
|
||||
return false
|
||||
return ""
|
||||
}
|
||||
return stdout == "true\n"
|
||||
return strings.ReplaceAll(stdout, "\n", "")
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ func commonGroups() []CommonRouter {
|
||||
&DashboardRouter{},
|
||||
&HostRouter{},
|
||||
&ContainerRouter{},
|
||||
&MonitorRouter{},
|
||||
&LogRouter{},
|
||||
&FileRouter{},
|
||||
&ToolboxRouter{},
|
||||
|
||||
@@ -35,6 +35,11 @@ func (s *HostRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
hostRouter.POST("/firewall/update/addr", baseApi.UpdateAddrRule)
|
||||
hostRouter.POST("/firewall/update/description", baseApi.UpdateFirewallDescription)
|
||||
|
||||
hostRouter.POST("/monitor/search", baseApi.LoadMonitor)
|
||||
hostRouter.POST("/monitor/clean", baseApi.CleanMonitor)
|
||||
hostRouter.GET("/monitor/netoptions", baseApi.GetNetworkOptions)
|
||||
hostRouter.GET("/monitor/iooptions", baseApi.GetIOOptions)
|
||||
|
||||
hostRouter.GET("/ssh/conf", baseApi.LoadSSHConf)
|
||||
hostRouter.POST("/ssh/search", baseApi.GetSSHInfo)
|
||||
hostRouter.POST("/ssh/update", baseApi.UpdateSSH)
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
v1 "github.com/1Panel-dev/1Panel/backend/app/api/v1"
|
||||
"github.com/1Panel-dev/1Panel/backend/middleware"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type MonitorRouter struct{}
|
||||
|
||||
func (s *MonitorRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
monitorRouter := Router.Group("monitors").
|
||||
Use(middleware.JwtAuth()).
|
||||
Use(middleware.SessionAuth()).
|
||||
Use(middleware.PasswordExpired())
|
||||
baseApi := v1.ApiGroupApp.BaseApi
|
||||
{
|
||||
monitorRouter.POST("/search", baseApi.LoadMonitor)
|
||||
monitorRouter.GET("/netoptions", baseApi.GetNetworkOptions)
|
||||
monitorRouter.GET("/iooptions", baseApi.GetIOOptions)
|
||||
}
|
||||
}
|
||||
@@ -23,13 +23,13 @@ func (s *SettingRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
settingRouter.GET("/search/available", baseApi.GetSystemAvailable)
|
||||
settingRouter.POST("/update", baseApi.UpdateSetting)
|
||||
settingRouter.GET("/interface", baseApi.LoadInterfaceAddr)
|
||||
settingRouter.POST("/menu/update", baseApi.UpdateMenu)
|
||||
settingRouter.POST("/bind/update", baseApi.UpdateBindInfo)
|
||||
settingRouter.POST("/port/update", baseApi.UpdatePort)
|
||||
settingRouter.POST("/ssl/update", baseApi.UpdateSSL)
|
||||
settingRouter.GET("/ssl/info", baseApi.LoadFromCert)
|
||||
settingRouter.POST("/ssl/download", baseApi.DownloadSSL)
|
||||
settingRouter.POST("/password/update", baseApi.UpdatePassword)
|
||||
settingRouter.POST("/monitor/clean", baseApi.CleanMonitor)
|
||||
settingRouter.POST("/mfa", baseApi.LoadMFA)
|
||||
settingRouter.POST("/mfa/bind", baseApi.MFABind)
|
||||
|
||||
|
||||
@@ -39,10 +39,6 @@ func (a *WebsiteRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
groupRouter.GET("/:id/https", baseApi.GetHTTPSConfig)
|
||||
groupRouter.POST("/:id/https", baseApi.UpdateHTTPSConfig)
|
||||
|
||||
groupRouter.POST("/waf/config", baseApi.GetWebsiteWafConfig)
|
||||
groupRouter.POST("/waf/update", baseApi.UpdateWebsiteWafConfig)
|
||||
groupRouter.POST("/waf/file/update", baseApi.UpdateWebsiteWafFile)
|
||||
|
||||
groupRouter.GET("/php/config/:id", baseApi.GetWebsitePHPConfig)
|
||||
groupRouter.POST("/php/config", baseApi.UpdateWebsitePHPConfig)
|
||||
groupRouter.POST("/php/update", baseApi.UpdatePHPFile)
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||
)
|
||||
|
||||
type localClient struct {
|
||||
@@ -54,9 +54,8 @@ func (c localClient) Upload(src, target string) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
stdout, err := cmd.Execf("\\cp -f %s %s", src, path.Join(c.dir, target))
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("cp file failed, stdout: %v, err: %v", stdout, err)
|
||||
if err := common.CopyFile(src, target); err != nil {
|
||||
return false, fmt.Errorf("cp file failed, err: %v", err)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
@@ -73,9 +72,8 @@ func (c localClient) Download(src, target string) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
stdout, err := cmd.Execf("\\cp -f %s %s", localPath, target)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("cp file failed, stdout: %v, err: %v", stdout, err)
|
||||
if err := common.CopyFile(localPath, target); err != nil {
|
||||
return false, fmt.Errorf("cp file failed, err: %v", err)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -120,10 +120,12 @@ func (m minIoClient) Download(src, target string) (bool, error) {
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer object.Close()
|
||||
localFile, err := os.Create(target)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer localFile.Close()
|
||||
if _, err = io.Copy(localFile, object); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ func CheckIllegal(args ...string) bool {
|
||||
if strings.Contains(arg, "&") || strings.Contains(arg, "|") || strings.Contains(arg, ";") ||
|
||||
strings.Contains(arg, "$") || strings.Contains(arg, "'") || strings.Contains(arg, "`") ||
|
||||
strings.Contains(arg, "(") || strings.Contains(arg, ")") || strings.Contains(arg, "\"") ||
|
||||
strings.Contains(arg, "\n") || strings.Contains(arg, "\r") {
|
||||
strings.Contains(arg, "\n") || strings.Contains(arg, "\r") || strings.Contains(arg, ">") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"io"
|
||||
mathRand "math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
@@ -43,6 +45,35 @@ func CompareVersion(version1, version2 string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func ComparePanelVersion(version1, version2 string) bool {
|
||||
if version1 == version2 {
|
||||
return false
|
||||
}
|
||||
version1s := strings.Split(version1, ".")
|
||||
version2s := strings.Split(version2, ".")
|
||||
|
||||
if len(version2s) > len(version1s) {
|
||||
for i := 0; i < len(version2s)-len(version1s); i++ {
|
||||
version1s = append(version1s, "0")
|
||||
}
|
||||
}
|
||||
if len(version1s) > len(version2s) {
|
||||
for i := 0; i < len(version1s)-len(version2s); i++ {
|
||||
version2s = append(version2s, "0")
|
||||
}
|
||||
}
|
||||
|
||||
n := min(len(version1s), len(version2s))
|
||||
for i := 0; i < n; i++ {
|
||||
if version1s[i] == version2s[i] {
|
||||
continue
|
||||
} else {
|
||||
return version1s[i] > version2s[i]
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func extractNumbers(version string) []string {
|
||||
var numbers []string
|
||||
start := -1
|
||||
@@ -82,6 +113,36 @@ func GetSortedVersions(versions []string) []string {
|
||||
return versions
|
||||
}
|
||||
|
||||
func CopyFile(src, dst string) error {
|
||||
source, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer source.Close()
|
||||
|
||||
if path.Base(src) != path.Base(dst) {
|
||||
dst = path.Join(dst, path.Base(src))
|
||||
}
|
||||
if _, err := os.Stat(path.Dir(dst)); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
_ = os.MkdirAll(path.Dir(dst), os.ModePerm)
|
||||
}
|
||||
}
|
||||
target, err := os.OpenFile(dst+"_temp", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer target.Close()
|
||||
|
||||
if _, err = io.Copy(target, source); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = os.Rename(dst+"_temp", dst); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func IsCrossVersion(version1, version2 string) bool {
|
||||
version1s := strings.Split(version1, ".")
|
||||
version2s := strings.Split(version2, ".")
|
||||
|
||||
@@ -54,7 +54,17 @@ func (f FileOp) GetContent(dst string) ([]byte, error) {
|
||||
}
|
||||
|
||||
func (f FileOp) CreateDir(dst string, mode fs.FileMode) error {
|
||||
return f.Fs.MkdirAll(dst, mode)
|
||||
if err := f.Fs.MkdirAll(dst, mode); err != nil {
|
||||
return err
|
||||
}
|
||||
modStr := fmt.Sprintf("%o", mode)
|
||||
|
||||
modeInt, err := strconv.ParseInt(modStr, 10, 64)
|
||||
if err != nil {
|
||||
modeInt = 0755
|
||||
}
|
||||
|
||||
return f.ChmodR(dst, modeInt, true)
|
||||
}
|
||||
|
||||
func (f FileOp) CreateFile(dst string) error {
|
||||
@@ -64,6 +74,14 @@ func (f FileOp) CreateFile(dst string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f FileOp) CreateFileWithMode(dst string, mode fs.FileMode) error {
|
||||
file, err := f.Fs.OpenFile(dst, os.O_CREATE, mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return file.Close()
|
||||
}
|
||||
|
||||
func (f FileOp) LinkFile(source string, dst string, isSymlink bool) error {
|
||||
if isSymlink {
|
||||
osFs := afero.OsFs{}
|
||||
@@ -149,7 +167,7 @@ func (f FileOp) ChownR(dst string, uid string, gid string, sub bool) error {
|
||||
if cmd.HasNoPasswordSudo() {
|
||||
cmdStr = fmt.Sprintf("sudo %s", cmdStr)
|
||||
}
|
||||
if msg, err := cmd.ExecWithTimeOut(cmdStr, 2*time.Second); err != nil {
|
||||
if msg, err := cmd.ExecWithTimeOut(cmdStr, 10*time.Second); err != nil {
|
||||
if msg != "" {
|
||||
return errors.New(msg)
|
||||
}
|
||||
@@ -166,7 +184,7 @@ func (f FileOp) ChmodR(dst string, mode int64, sub bool) error {
|
||||
if cmd.HasNoPasswordSudo() {
|
||||
cmdStr = fmt.Sprintf("sudo %s", cmdStr)
|
||||
}
|
||||
if msg, err := cmd.ExecWithTimeOut(cmdStr, 2*time.Second); err != nil {
|
||||
if msg, err := cmd.ExecWithTimeOut(cmdStr, 10*time.Second); err != nil {
|
||||
if msg != "" {
|
||||
return errors.New(msg)
|
||||
}
|
||||
@@ -314,7 +332,7 @@ func (f FileOp) Cut(oldPaths []string, dst, name string, cover bool) error {
|
||||
coverFlag = "-f"
|
||||
}
|
||||
|
||||
cmdStr := fmt.Sprintf(`mv %s "%s" "%s"`, coverFlag, p, dstPath)
|
||||
cmdStr := fmt.Sprintf(`mv %s '%s' '%s'`, coverFlag, p, dstPath)
|
||||
if err := cmd.ExecCmd(cmdStr); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -323,7 +341,7 @@ func (f FileOp) Cut(oldPaths []string, dst, name string, cover bool) error {
|
||||
}
|
||||
|
||||
func (f FileOp) Mv(oldPath, dstPath string) error {
|
||||
cmdStr := fmt.Sprintf(`mv "%s" "%s"`, oldPath, dstPath)
|
||||
cmdStr := fmt.Sprintf(`mv '%s' '%s'`, oldPath, dstPath)
|
||||
if err := cmd.ExecCmd(cmdStr); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -377,13 +395,13 @@ func (f FileOp) CopyAndReName(src, dst, name string, cover bool) error {
|
||||
if name != "" && !cover {
|
||||
dstPath = filepath.Join(dst, name)
|
||||
}
|
||||
return cmd.ExecCmd(fmt.Sprintf(`cp -rf "%s" "%s"`, src, dstPath))
|
||||
return cmd.ExecCmd(fmt.Sprintf(`cp -rf '%s' '%s'`, src, dstPath))
|
||||
} else {
|
||||
dstPath := filepath.Join(dst, name)
|
||||
if cover {
|
||||
dstPath = dst
|
||||
}
|
||||
return cmd.ExecCmd(fmt.Sprintf(`cp -f "%s" "%s"`, src, dstPath))
|
||||
return cmd.ExecCmd(fmt.Sprintf(`cp -f '%s' '%s'`, src, dstPath))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,12 +414,12 @@ func (f FileOp) CopyDir(src, dst string) error {
|
||||
if err = f.Fs.MkdirAll(dstDir, srcInfo.Mode()); err != nil {
|
||||
return err
|
||||
}
|
||||
return cmd.ExecCmd(fmt.Sprintf(`cp -rf "%s" "%s"`, src, dst+"/"))
|
||||
return cmd.ExecCmd(fmt.Sprintf(`cp -rf '%s' '%s'`, src, dst+"/"))
|
||||
}
|
||||
|
||||
func (f FileOp) CopyFile(src, dst string) error {
|
||||
dst = filepath.Clean(dst) + string(filepath.Separator)
|
||||
return cmd.ExecCmd(fmt.Sprintf(`cp -f "%s" "%s"`, src, dst+"/"))
|
||||
return cmd.ExecCmd(fmt.Sprintf(`cp -f '%s' '%s'`, src, dst+"/"))
|
||||
}
|
||||
|
||||
func (f FileOp) GetDirSize(path string) (float64, error) {
|
||||
|
||||
@@ -311,20 +311,22 @@ func (f *FileInfo) listChildren(option FileOption) error {
|
||||
}
|
||||
|
||||
func (f *FileInfo) getContent() error {
|
||||
if f.Size <= 10*1024*1024 {
|
||||
afs := &afero.Afero{Fs: f.Fs}
|
||||
cByte, err := afs.ReadFile(f.Path)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if len(cByte) > 0 && DetectBinary(cByte) {
|
||||
return buserr.New(constant.ErrFileCanNotRead)
|
||||
}
|
||||
f.Content = string(cByte)
|
||||
return nil
|
||||
} else {
|
||||
if IsBlockDevice(f.FileMode) {
|
||||
return buserr.New(constant.ErrFileCanNotRead)
|
||||
}
|
||||
if f.Size > 10*1024*1024 {
|
||||
return buserr.New("ErrFileToLarge")
|
||||
}
|
||||
afs := &afero.Afero{Fs: f.Fs}
|
||||
cByte, err := afs.ReadFile(f.Path)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if len(cByte) > 0 && DetectBinary(cByte) {
|
||||
return buserr.New(constant.ErrFileCanNotRead)
|
||||
}
|
||||
f.Content = string(cByte)
|
||||
return nil
|
||||
}
|
||||
|
||||
func DetectBinary(buf []byte) bool {
|
||||
|
||||
@@ -2,6 +2,7 @@ package files
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/spf13/afero"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -9,6 +10,7 @@ import (
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -16,6 +18,10 @@ func IsSymlink(mode os.FileMode) bool {
|
||||
return mode&os.ModeSymlink != 0
|
||||
}
|
||||
|
||||
func IsBlockDevice(mode os.FileMode) bool {
|
||||
return mode&os.ModeDevice != 0 && mode&os.ModeCharDevice == 0
|
||||
}
|
||||
|
||||
func GetMimeType(path string) string {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
@@ -113,3 +119,33 @@ func ReadFileByLine(filename string, page, pageSize int) ([]string, bool, error)
|
||||
|
||||
return lines, isEndOfFile, nil
|
||||
}
|
||||
|
||||
func GetParentMode(path string) (os.FileMode, error) {
|
||||
absPath, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
for {
|
||||
fileInfo, err := os.Stat(absPath)
|
||||
if err == nil {
|
||||
return fileInfo.Mode() & os.ModePerm, nil
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
parentDir := filepath.Dir(absPath)
|
||||
if parentDir == absPath {
|
||||
return 0, fmt.Errorf("no existing directory found in the path: %s", path)
|
||||
}
|
||||
absPath = parentDir
|
||||
}
|
||||
}
|
||||
|
||||
func IsInvalidChar(name string) bool {
|
||||
if strings.Contains(name, "&") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ func NewParserFromLexer(lexer *lexer) *Parser {
|
||||
|
||||
parser.directiveWrappers = map[string]func(*components.Directive) components.IDirective{
|
||||
"server": func(directive *components.Directive) components.IDirective {
|
||||
return parser.wrapServer(directive)
|
||||
return parser.parseUpstreamServer(directive)
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
package ps
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/v3/host"
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
)
|
||||
|
||||
func TestPs(t *testing.T) {
|
||||
processes, err := process.Processes()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, pro := range processes {
|
||||
var (
|
||||
name string
|
||||
parentID int32
|
||||
userName string
|
||||
status string
|
||||
startTime string
|
||||
numThreads int32
|
||||
numConnections int
|
||||
cpuPercent float64
|
||||
//mem string
|
||||
rss string
|
||||
ioRead string
|
||||
ioWrite string
|
||||
)
|
||||
name, _ = pro.Name()
|
||||
parentID, _ = pro.Ppid()
|
||||
userName, _ = pro.Username()
|
||||
array, err := pro.Status()
|
||||
if err == nil {
|
||||
status = array[0]
|
||||
}
|
||||
createTime, err := pro.CreateTime()
|
||||
if err == nil {
|
||||
t := time.Unix(createTime/1000, 0)
|
||||
startTime = t.Format("2006-1-2 15:04:05")
|
||||
}
|
||||
numThreads, _ = pro.NumThreads()
|
||||
connections, err := pro.Connections()
|
||||
if err == nil && len(connections) > 0 {
|
||||
numConnections = len(connections)
|
||||
}
|
||||
cpuPercent, _ = pro.CPUPercent()
|
||||
menInfo, err := pro.MemoryInfo()
|
||||
if err == nil {
|
||||
rssF := float64(menInfo.RSS) / 1048576
|
||||
rss = fmt.Sprintf("%.2f", rssF)
|
||||
}
|
||||
ioStat, err := pro.IOCounters()
|
||||
if err == nil {
|
||||
ioWrite = strconv.FormatUint(ioStat.WriteBytes, 10)
|
||||
ioRead = strconv.FormatUint(ioStat.ReadBytes, 10)
|
||||
}
|
||||
|
||||
cmdLine, err := pro.Cmdline()
|
||||
if err == nil {
|
||||
fmt.Println(cmdLine)
|
||||
}
|
||||
ss, err := pro.Terminal()
|
||||
if err == nil {
|
||||
fmt.Println(ss)
|
||||
}
|
||||
|
||||
fmt.Printf("Name: %s PId: %v ParentID: %v Username: %v status:%s startTime: %s numThreads: %v numConnections:%v cpuPercent:%v rss:%s MB IORead: %s IOWrite: %s \n",
|
||||
name, pro.Pid, parentID, userName, status, startTime, numThreads, numConnections, cpuPercent, rss, ioRead, ioWrite)
|
||||
}
|
||||
users, err := host.Users()
|
||||
if err == nil {
|
||||
fmt.Println(users)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,457 +0,0 @@
|
||||
package ssl
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"github.com/go-acme/lego/v4/providers/dns/cloudflare"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/go-acme/lego/v4/acme/api"
|
||||
"github.com/go-acme/lego/v4/certcrypto"
|
||||
"github.com/go-acme/lego/v4/certificate"
|
||||
"github.com/go-acme/lego/v4/challenge"
|
||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||
"github.com/go-acme/lego/v4/lego"
|
||||
"github.com/go-acme/lego/v4/registration"
|
||||
|
||||
"log"
|
||||
)
|
||||
|
||||
type AppList struct {
|
||||
Version string `json:"version"`
|
||||
Tags []Tag `json:"tags"`
|
||||
Items []AppDefine `json:"items"`
|
||||
}
|
||||
|
||||
type NewAppDefine struct {
|
||||
Name string `yaml:"name"`
|
||||
Tags []string `yaml:"tags"`
|
||||
Title string `yaml:"title"`
|
||||
Type string `yaml:"type"`
|
||||
Description string `yaml:"description"`
|
||||
AdditionalProperties AppDefine `yaml:"additionalProperties"`
|
||||
}
|
||||
|
||||
type NewAppConfig struct {
|
||||
AdditionalProperties map[string]interface{} `yaml:"additionalProperties"`
|
||||
}
|
||||
|
||||
type AppDefine struct {
|
||||
Key string `json:"key" yaml:"key"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Tags []string `json:"tags" yaml:"tags"`
|
||||
Versions []string `json:"versions" yaml:"-"`
|
||||
ShortDescZh string `json:"shortDescZh" yaml:"shortDescZh"`
|
||||
ShortDescEn string `json:"shortDescEn" yaml:"shortDescEn"`
|
||||
Type string `json:"type" yaml:"type"`
|
||||
CrossVersionUpdate bool `json:"crossVersionUpdate" yaml:"crossVersionUpdate"`
|
||||
Limit int `json:"limit" yaml:"limit"`
|
||||
Recommend int `json:"recommend" yaml:"recommend"`
|
||||
Website string `json:"website" yaml:"website"`
|
||||
Github string `json:"github" yaml:"github"`
|
||||
Document string `json:"document" yaml:"document"`
|
||||
}
|
||||
|
||||
type Tag struct {
|
||||
Key string `json:"key" yaml:"key"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
}
|
||||
|
||||
func getTagName(key string, tags []Tag) string {
|
||||
result := "应用"
|
||||
for _, tag := range tags {
|
||||
if tag.Key == key {
|
||||
return tag.Name
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func TestAppToV2(t *testing.T) {
|
||||
oldDir := "/Users/wangzhengkun/projects/github.com/1Panel-dev/appstore/apps"
|
||||
newDir := "/Users/wangzhengkun/projects/github.com/1Panel-dev/appstore/apps_new"
|
||||
listJsonDir := path.Join(oldDir, "list.json")
|
||||
fileOp := files.NewFileOp()
|
||||
content, err := fileOp.GetContent(listJsonDir)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
appList := &AppList{}
|
||||
if err = json.Unmarshal(content, appList); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, appDefine := range appList.Items {
|
||||
newAppDefine := &NewAppDefine{
|
||||
Name: appDefine.Name,
|
||||
Tags: []string{getTagName(appDefine.Tags[0], appList.Tags)},
|
||||
Type: getTagName(appDefine.Tags[0], appList.Tags),
|
||||
Title: appDefine.ShortDescZh,
|
||||
Description: appDefine.ShortDescZh,
|
||||
AdditionalProperties: appDefine,
|
||||
}
|
||||
|
||||
yamlContent, err := yaml.Marshal(newAppDefine)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
oldAppDir := oldDir + "/" + appDefine.Key
|
||||
newAppDir := newDir + "/" + appDefine.Key
|
||||
if !fileOp.Stat(newAppDir) {
|
||||
if err := fileOp.CreateDir(newAppDir, 0755); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
// logo
|
||||
oldLogoPath := oldAppDir + "/metadata/logo.png"
|
||||
if err := fileOp.CopyFile(oldLogoPath, newAppDir); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, version := range appDefine.Versions {
|
||||
oldVersionDir := oldAppDir + "/versions/" + version
|
||||
if err := fileOp.CopyDir(oldVersionDir, newAppDir); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
oldConfigPath := oldVersionDir + "/config.json"
|
||||
configContent, err := fileOp.GetContent(oldConfigPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var result map[string]interface{}
|
||||
if err := json.Unmarshal(configContent, &result); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
newConfigD := &NewAppConfig{}
|
||||
newConfigD.AdditionalProperties = result
|
||||
configYamlByte, err := yaml.Marshal(newConfigD)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
newVersionDir := newAppDir + "/" + version
|
||||
if err := fileOp.WriteFile(newVersionDir+"/data.yml", bytes.NewReader(configYamlByte), 0755); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := fileOp.WriteFile(newAppDir+"/data.yml", bytes.NewReader(yamlContent), 0755); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_ = fileOp.DeleteFile(newVersionDir + "/config.json")
|
||||
oldReadMefile := newVersionDir + "/README.md"
|
||||
_ = fileOp.Cut([]string{oldReadMefile}, newAppDir, "", false)
|
||||
_ = fileOp.DeleteFile(oldReadMefile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreatePrivate(t *testing.T) {
|
||||
priKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
derStream := x509.MarshalPKCS1PrivateKey(priKey)
|
||||
block := &pem.Block{
|
||||
Type: "privateKey",
|
||||
Bytes: derStream,
|
||||
}
|
||||
file, err := os.Create("private.key")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = pem.Encode(file, block); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestSSL(t *testing.T) {
|
||||
|
||||
priKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate private key: %v", err)
|
||||
}
|
||||
|
||||
myUser := AcmeUser{
|
||||
Email: "you2@yours.com",
|
||||
Key: priKey,
|
||||
}
|
||||
|
||||
config := lego.NewConfig(&myUser)
|
||||
//config.CADirURL = "https://acme-v02.api.letsencrypt.org/directory"
|
||||
config.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
config.CADirURL = "https://acme.zerossl.com/v2/DV90"
|
||||
config.UserAgent = "acm_go/0.0.1"
|
||||
|
||||
config.Certificate.KeyType = certcrypto.RSA2048
|
||||
//config.HTTPClient = httpClient
|
||||
|
||||
client, err := lego.NewClient(config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
myUser.Registration = reg
|
||||
|
||||
//获取证书
|
||||
//certificates, err := client.Certificate.Get("https://acme-v02.api.letsencrypt.org/acme/cert/049cb98a8b3ea5a73f08dcdcf89263af8323", true)
|
||||
//if err != nil {
|
||||
// panic(err)
|
||||
//}
|
||||
//certificates, err = client.Certificate.Renew(*certificates, true, true, "")
|
||||
//if err != nil {
|
||||
// panic(err)
|
||||
//}
|
||||
|
||||
//申请证书
|
||||
ewDomain := "tuxpanel.com"
|
||||
|
||||
request := certificate.ObtainRequest{
|
||||
Domains: []string{ewDomain},
|
||||
// 证书链
|
||||
Bundle: true,
|
||||
}
|
||||
|
||||
err = client.Challenge.SetDNS01Provider(&manualDnsProvider{}, dns01.AddDNSTimeout(6*time.Minute))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
core, err := api.New(config.HTTPClient, config.UserAgent, config.CADirURL, reg.URI, priKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
order, err := core.Orders.New([]string{ewDomain})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
auth, err := core.Authorizations.Get(order.Authorizations[0])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
domain := challenge.GetTargetedDomain(auth)
|
||||
chlng, err := challenge.FindChallenge(challenge.DNS01, auth)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
keyAuth, err := core.GetKeyAuthorization(chlng.Token)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
||||
fmt.Println("fqdn", fqdn, value)
|
||||
|
||||
//
|
||||
//keyAuth, err := client.Challenge.core.GetKeyAuthorization(chlng.Token)
|
||||
//if err != nil {
|
||||
// panic(err)
|
||||
//}
|
||||
//
|
||||
|
||||
//httpProvider, err := webroot.NewHTTPProvider("/opt/1Panel/data/apps/nginx/nginx-1/www/wwwroot")
|
||||
//if err != nil {
|
||||
// panic(err)
|
||||
//}
|
||||
//
|
||||
//err = client.Challenge.SetHTTP01Provider(httpProvider)
|
||||
//if err != nil {
|
||||
// panic(err)
|
||||
//}
|
||||
//err = client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("43.142.178.16", "443"))
|
||||
//if err != nil {
|
||||
// panic(err)
|
||||
//}
|
||||
|
||||
certificates, err := client.Certificate.Obtain(request)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println("---private---")
|
||||
fmt.Println(string(certificates.PrivateKey))
|
||||
fmt.Println("---.pem---")
|
||||
fmt.Println(string(certificates.Certificate))
|
||||
fmt.Println("---.domain---")
|
||||
fmt.Println(certificates.Domain)
|
||||
fmt.Println("---.certUrl---")
|
||||
fmt.Println(certificates.CertURL)
|
||||
fmt.Println("---.csr---")
|
||||
fmt.Println(certificates.CSR)
|
||||
fmt.Println("---.cert string---")
|
||||
fmt.Println(string(certificates.IssuerCertificate))
|
||||
|
||||
cer1, _ := pem.Decode(certificates.Certificate)
|
||||
|
||||
cert, err := x509.ParseCertificate(cer1.Bytes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(cert)
|
||||
|
||||
cer2, _ := pem.Decode(certificates.IssuerCertificate)
|
||||
|
||||
cert2, err := x509.ParseCertificate(cer2.Bytes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(cert2)
|
||||
|
||||
}
|
||||
|
||||
func generateCSR(privateKey crypto.PrivateKey, domain string) ([]byte, error) {
|
||||
// 创建证书请求的模板
|
||||
template := x509.CertificateRequest{
|
||||
Subject: pkix.Name{
|
||||
CommonName: domain,
|
||||
},
|
||||
SignatureAlgorithm: x509.ECDSAWithSHA256,
|
||||
}
|
||||
|
||||
// 生成 CSR
|
||||
csrBytes, err := x509.CreateCertificateRequest(rand.Reader, &template, privateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 将 CSR 编码为 PEM 格式
|
||||
csrPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrBytes})
|
||||
|
||||
// 这里可以将 CSR 写入文件或者返回
|
||||
err = os.WriteFile("csr.pem", csrPEM, 0644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return csrPEM, nil
|
||||
}
|
||||
|
||||
func TestZeroSSL(t *testing.T) {
|
||||
|
||||
domain := "1panel.store"
|
||||
acmeServer := "https://acme.zerossl.com/v2/DV90"
|
||||
|
||||
//acmeServer = "https://api.test4.buypass.no/acme/directory"
|
||||
//
|
||||
//acmeServer = "https://api.buypass.com/acme/directory"
|
||||
|
||||
priKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate private key: %v", err)
|
||||
}
|
||||
|
||||
user := AcmeUser{
|
||||
Email: "zhengkunwang123@sina.com",
|
||||
Key: priKey,
|
||||
}
|
||||
|
||||
//logFile, err := os.OpenFile("/opt/1panel/ssl.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||
//if err != nil {
|
||||
// log.Fatalf("Failed to open log file: %v", err)
|
||||
//}
|
||||
//defer logFile.Close()
|
||||
//
|
||||
//logger := log.New(logFile, "", log.LstdFlags)
|
||||
//legoLogger.Logger = logger
|
||||
|
||||
config := lego.NewConfig(&user)
|
||||
|
||||
// 设置ACME服务器URL
|
||||
config.CADirURL = acmeServer
|
||||
config.Certificate.KeyType = certcrypto.RSA2048
|
||||
config.UserAgent = "acm_go/0.0.1"
|
||||
|
||||
// 创建ACME客户端
|
||||
client, err := lego.NewClient(config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// ZeroSSl
|
||||
|
||||
kid := ""
|
||||
hmacEncoded := ""
|
||||
|
||||
eabOptions := registration.RegisterEABOptions{
|
||||
TermsOfServiceAgreed: true,
|
||||
Kid: kid,
|
||||
HmacEncoded: hmacEncoded,
|
||||
}
|
||||
|
||||
reg, err := client.Registration.RegisterWithExternalAccountBinding(eabOptions)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// ZeroSSl
|
||||
|
||||
//reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
|
||||
//if err != nil {
|
||||
// log.Fatal(err)
|
||||
//}
|
||||
|
||||
user.Registration = reg
|
||||
|
||||
cloudflareConfig := cloudflare.NewDefaultConfig()
|
||||
cloudflareConfig.AuthEmail = ""
|
||||
cloudflareConfig.AuthKey = ""
|
||||
p, err := cloudflare.NewDNSProviderConfig(cloudflareConfig)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := client.Challenge.SetDNS01Provider(p, dns01.AddDNSTimeout(3*time.Minute)); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// 申请证书
|
||||
pk, err := certcrypto.GeneratePrivateKey(certcrypto.EC256)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
request := certificate.ObtainRequest{
|
||||
Domains: []string{domain},
|
||||
Bundle: true,
|
||||
PrivateKey: pk,
|
||||
}
|
||||
certificates, err := client.Certificate.Obtain(request)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// 保存证书
|
||||
err = os.WriteFile("certificate.crt", certificates.Certificate, 0644)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = os.WriteFile("private.key", certificates.PrivateKey, 0644)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetEABCre(t *testing.T) {
|
||||
res, err := getZeroSSLEabCredentials("zen@11.com")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("%v", res)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
//go:build !xpack
|
||||
|
||||
package xpack
|
||||
|
||||
func RemoveTamper(website string) {}
|
||||
|
||||
func LoadGpuInfo() []interface{} {
|
||||
return nil
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"strings"
|
||||
|
||||
cmdUtils "github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -43,19 +43,19 @@ var restoreCmd = &cobra.Command{
|
||||
tmpPath = path.Join(upgradeDir, tmpPath, "original")
|
||||
fmt.Printf("(0/4) 开始从 %s 目录回滚 1Panel 服务及数据... \n", tmpPath)
|
||||
|
||||
if err := cpBinary(path.Join(tmpPath, "1panel"), "/usr/local/bin/1panel"); err != nil {
|
||||
if err := common.CopyFile(path.Join(tmpPath, "1panel"), "/usr/local/bin"); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("(1/4) 1panel 二进制回滚成功")
|
||||
if err := cpBinary(path.Join(tmpPath, "1pctl"), "/usr/local/bin/1pctl"); err != nil {
|
||||
if err := common.CopyFile(path.Join(tmpPath, "1pctl"), "/usr/local/bin"); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("(2/4) 1panel 脚本回滚成功")
|
||||
if err := cpBinary(path.Join(tmpPath, "1panel.service"), "/etc/systemd/system/1panel.service"); err != nil {
|
||||
if err := common.CopyFile(path.Join(tmpPath, "1panel.service"), "/etc/systemd/system"); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("(3/4) 1panel 服务回滚成功")
|
||||
if err := cpBinary(path.Join(tmpPath, "1Panel.db"), path.Join(baseDir, "1panel", "db", "1Panel.db")); err != nil {
|
||||
if err := common.CopyFile(path.Join(tmpPath, "1Panel.db"), path.Join(baseDir, "1panel", "db")); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("(4/4) 1panel 数据回滚成功 \n\n")
|
||||
@@ -87,11 +87,3 @@ func loadRestorePath(upgradeDir string) (string, error) {
|
||||
})
|
||||
return folders[0], nil
|
||||
}
|
||||
|
||||
func cpBinary(src string, dst string) error {
|
||||
stderr, err := cmdUtils.Exec(fmt.Sprintf("\\cp -f %s %s", src, dst))
|
||||
if err != nil {
|
||||
return errors.New(stderr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -59,6 +59,14 @@ func getSettingByKey(db *gorm.DB, key string) string {
|
||||
return setting.Value
|
||||
}
|
||||
|
||||
type LoginLog struct{}
|
||||
|
||||
func isDefault(db *gorm.DB) bool {
|
||||
logCount := int64(0)
|
||||
_ = db.Model(&LoginLog{}).Where("status = ?", "Success").Count(&logCount).Error
|
||||
return logCount == 0
|
||||
}
|
||||
|
||||
func setSettingByKey(db *gorm.DB, key, value string) error {
|
||||
return db.Model(&setting{}).Where("key = ?", key).Updates(map[string]interface{}{"value": value}).Error
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package cmd
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/encrypt"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -23,6 +25,15 @@ var userinfoCmd = &cobra.Command{
|
||||
return fmt.Errorf("init my db conn failed, err: %v \n", err)
|
||||
}
|
||||
user := getSettingByKey(db, "UserName")
|
||||
pass := "********"
|
||||
if isDefault(db) {
|
||||
encryptSetting := getSettingByKey(db, "EncryptKey")
|
||||
pass = getSettingByKey(db, "Password")
|
||||
if len(encryptSetting) == 16 {
|
||||
global.CONF.System.EncryptKey = encryptSetting
|
||||
pass, _ = encrypt.StringDecrypt(pass)
|
||||
}
|
||||
}
|
||||
port := getSettingByKey(db, "ServerPort")
|
||||
ssl := getSettingByKey(db, "SSL")
|
||||
entrance := getSettingByKey(db, "SecurityEntrance")
|
||||
@@ -38,7 +49,7 @@ var userinfoCmd = &cobra.Command{
|
||||
|
||||
fmt.Printf("面板地址: %s://%s:%s/%s \n", protocol, address, port, entrance)
|
||||
fmt.Println("面板用户: ", user)
|
||||
fmt.Println("面板密码: ", "********")
|
||||
fmt.Println("面板密码: ", pass)
|
||||
fmt.Println("提示:修改密码可执行命令:1pctl update password")
|
||||
return nil
|
||||
},
|
||||
|
||||
+210
-215
@@ -156,7 +156,7 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/apps/ingored": {
|
||||
"/apps/ignored": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
@@ -8097,6 +8097,62 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/hosts/monitor/clean": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "清空监控数据",
|
||||
"tags": [
|
||||
"Monitor"
|
||||
],
|
||||
"summary": "Clean monitor datas",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "clean monitor datas",
|
||||
"formatZH": "清空监控数据",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/hosts/monitor/search": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "获取监控数据",
|
||||
"tags": [
|
||||
"Monitor"
|
||||
],
|
||||
"summary": "Load monitor datas",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.MonitorSearch"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/hosts/search": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -9158,6 +9214,28 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/runtimes/sync": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "同步运行环境状态",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Runtime"
|
||||
],
|
||||
"summary": "Sync runtime status",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/runtimes/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -9901,6 +9979,46 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/menu/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "隐藏高级功能菜单",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"System Setting"
|
||||
],
|
||||
"summary": "Update system setting",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.SettingUpdate"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "Hide advanced feature menu.",
|
||||
"formatZH": "隐藏高级功能菜单",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/mfa": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -9977,32 +10095,6 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/monitor/clean": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "清空监控数据",
|
||||
"tags": [
|
||||
"System Setting"
|
||||
],
|
||||
"summary": "Clean monitor datas",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "clean monitor datas",
|
||||
"formatZH": "清空监控数据",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/password/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -12940,7 +13032,7 @@ const docTemplate = `{
|
||||
"tags": [
|
||||
"Website"
|
||||
],
|
||||
"summary": "Load websit php conf",
|
||||
"summary": "Load website php conf",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
@@ -13918,144 +14010,6 @@ const docTemplate = `{
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/waf/config": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "获取网站 waf 配置",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Website WAF"
|
||||
],
|
||||
"summary": "Load websit waf conf",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.WebsiteWafReq"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.WebsiteWafConfig"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/waf/file/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "更新 网站 waf 配置文件",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Website WAF"
|
||||
],
|
||||
"summary": "Update website waf file",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.WebsiteWafUpdate"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [
|
||||
{
|
||||
"db": "websites",
|
||||
"input_column": "id",
|
||||
"input_value": "websiteId",
|
||||
"isList": false,
|
||||
"output_column": "primary_domain",
|
||||
"output_value": "domain"
|
||||
}
|
||||
],
|
||||
"bodyKeys": [
|
||||
"websiteId"
|
||||
],
|
||||
"formatEN": "WAF conf file update [domain]",
|
||||
"formatZH": "WAF 配置文件修改 [domain]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/waf/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "更新 网站 waf 配置",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Website WAF"
|
||||
],
|
||||
"summary": "Update website waf conf",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.WebsiteWafUpdate"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [
|
||||
{
|
||||
"db": "websites",
|
||||
"input_column": "id",
|
||||
"input_value": "websiteId",
|
||||
"isList": false,
|
||||
"output_column": "primary_domain",
|
||||
"output_value": "domain"
|
||||
}
|
||||
],
|
||||
"bodyKeys": [
|
||||
"websiteId"
|
||||
],
|
||||
"formatEN": "WAF conf update [domain]",
|
||||
"formatZH": "WAF 配置修改 [domain]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
@@ -14930,6 +14884,9 @@ const docTemplate = `{
|
||||
"backupAccounts": {
|
||||
"type": "string"
|
||||
},
|
||||
"command": {
|
||||
"type": "string"
|
||||
},
|
||||
"containerName": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -15001,6 +14958,9 @@ const docTemplate = `{
|
||||
"backupAccounts": {
|
||||
"type": "string"
|
||||
},
|
||||
"command": {
|
||||
"type": "string"
|
||||
},
|
||||
"containerName": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -15234,6 +15194,12 @@ const docTemplate = `{
|
||||
"$ref": "#/definitions/dto.DiskInfo"
|
||||
}
|
||||
},
|
||||
"gpuData": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/dto.GPUInfo"
|
||||
}
|
||||
},
|
||||
"ioCount": {
|
||||
"type": "integer"
|
||||
},
|
||||
@@ -15817,6 +15783,47 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.GPUInfo": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fanSpeed": {
|
||||
"type": "string"
|
||||
},
|
||||
"gpuUtil": {
|
||||
"type": "string"
|
||||
},
|
||||
"index": {
|
||||
"type": "integer"
|
||||
},
|
||||
"maxPowerLimit": {
|
||||
"type": "string"
|
||||
},
|
||||
"memTotal": {
|
||||
"type": "string"
|
||||
},
|
||||
"memUsed": {
|
||||
"type": "string"
|
||||
},
|
||||
"memoryUsage": {
|
||||
"type": "string"
|
||||
},
|
||||
"performanceState": {
|
||||
"type": "string"
|
||||
},
|
||||
"powerDraw": {
|
||||
"type": "string"
|
||||
},
|
||||
"powerUsage": {
|
||||
"type": "string"
|
||||
},
|
||||
"productName": {
|
||||
"type": "string"
|
||||
},
|
||||
"temperature": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.GenerateLoad": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -16324,6 +16331,34 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.MonitorSearch": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"param"
|
||||
],
|
||||
"properties": {
|
||||
"endTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"info": {
|
||||
"type": "string"
|
||||
},
|
||||
"param": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"all",
|
||||
"cpu",
|
||||
"memory",
|
||||
"load",
|
||||
"io",
|
||||
"network"
|
||||
]
|
||||
},
|
||||
"startTime": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.MysqlDBCreate": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -17800,6 +17835,9 @@ const docTemplate = `{
|
||||
"monitorStoreDays": {
|
||||
"type": "string"
|
||||
},
|
||||
"noAuthSetting": {
|
||||
"type": "string"
|
||||
},
|
||||
"ntpSite": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -17844,6 +17882,9 @@ const docTemplate = `{
|
||||
},
|
||||
"weChatVars": {
|
||||
"type": "string"
|
||||
},
|
||||
"xpackHideMenu": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -18090,6 +18131,9 @@ const docTemplate = `{
|
||||
},
|
||||
"sourceDir": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -18921,7 +18965,6 @@ const docTemplate = `{
|
||||
"request.FileCreate": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"mode",
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
@@ -20777,43 +20820,6 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.WebsiteWafReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"key",
|
||||
"rule",
|
||||
"websiteId"
|
||||
],
|
||||
"properties": {
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"rule": {
|
||||
"type": "string"
|
||||
},
|
||||
"websiteId": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.WebsiteWafUpdate": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"key",
|
||||
"websiteId"
|
||||
],
|
||||
"properties": {
|
||||
"enable": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"websiteId": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"response.AppDTO": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -21493,17 +21499,6 @@ const docTemplate = `{
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"response.WebsiteWafConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"content": {
|
||||
"type": "string"
|
||||
},
|
||||
"enable": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
+210
-215
@@ -149,7 +149,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/apps/ingored": {
|
||||
"/apps/ignored": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
@@ -8090,6 +8090,62 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/hosts/monitor/clean": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "清空监控数据",
|
||||
"tags": [
|
||||
"Monitor"
|
||||
],
|
||||
"summary": "Clean monitor datas",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "clean monitor datas",
|
||||
"formatZH": "清空监控数据",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/hosts/monitor/search": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "获取监控数据",
|
||||
"tags": [
|
||||
"Monitor"
|
||||
],
|
||||
"summary": "Load monitor datas",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.MonitorSearch"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/hosts/search": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -9151,6 +9207,28 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/runtimes/sync": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "同步运行环境状态",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Runtime"
|
||||
],
|
||||
"summary": "Sync runtime status",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/runtimes/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -9894,6 +9972,46 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/menu/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "隐藏高级功能菜单",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"System Setting"
|
||||
],
|
||||
"summary": "Update system setting",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.SettingUpdate"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "Hide advanced feature menu.",
|
||||
"formatZH": "隐藏高级功能菜单",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/mfa": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -9970,32 +10088,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/monitor/clean": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "清空监控数据",
|
||||
"tags": [
|
||||
"System Setting"
|
||||
],
|
||||
"summary": "Clean monitor datas",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "clean monitor datas",
|
||||
"formatZH": "清空监控数据",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/password/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -12933,7 +13025,7 @@
|
||||
"tags": [
|
||||
"Website"
|
||||
],
|
||||
"summary": "Load websit php conf",
|
||||
"summary": "Load website php conf",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
@@ -13911,144 +14003,6 @@
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/waf/config": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "获取网站 waf 配置",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Website WAF"
|
||||
],
|
||||
"summary": "Load websit waf conf",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.WebsiteWafReq"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/response.WebsiteWafConfig"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/waf/file/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "更新 网站 waf 配置文件",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Website WAF"
|
||||
],
|
||||
"summary": "Update website waf file",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.WebsiteWafUpdate"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [
|
||||
{
|
||||
"db": "websites",
|
||||
"input_column": "id",
|
||||
"input_value": "websiteId",
|
||||
"isList": false,
|
||||
"output_column": "primary_domain",
|
||||
"output_value": "domain"
|
||||
}
|
||||
],
|
||||
"bodyKeys": [
|
||||
"websiteId"
|
||||
],
|
||||
"formatEN": "WAF conf file update [domain]",
|
||||
"formatZH": "WAF 配置文件修改 [domain]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/waf/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "更新 网站 waf 配置",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Website WAF"
|
||||
],
|
||||
"summary": "Update website waf conf",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.WebsiteWafUpdate"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFunctions": [
|
||||
{
|
||||
"db": "websites",
|
||||
"input_column": "id",
|
||||
"input_value": "websiteId",
|
||||
"isList": false,
|
||||
"output_column": "primary_domain",
|
||||
"output_value": "domain"
|
||||
}
|
||||
],
|
||||
"bodyKeys": [
|
||||
"websiteId"
|
||||
],
|
||||
"formatEN": "WAF conf update [domain]",
|
||||
"formatZH": "WAF 配置修改 [domain]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
@@ -14923,6 +14877,9 @@
|
||||
"backupAccounts": {
|
||||
"type": "string"
|
||||
},
|
||||
"command": {
|
||||
"type": "string"
|
||||
},
|
||||
"containerName": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -14994,6 +14951,9 @@
|
||||
"backupAccounts": {
|
||||
"type": "string"
|
||||
},
|
||||
"command": {
|
||||
"type": "string"
|
||||
},
|
||||
"containerName": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -15227,6 +15187,12 @@
|
||||
"$ref": "#/definitions/dto.DiskInfo"
|
||||
}
|
||||
},
|
||||
"gpuData": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/dto.GPUInfo"
|
||||
}
|
||||
},
|
||||
"ioCount": {
|
||||
"type": "integer"
|
||||
},
|
||||
@@ -15810,6 +15776,47 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.GPUInfo": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fanSpeed": {
|
||||
"type": "string"
|
||||
},
|
||||
"gpuUtil": {
|
||||
"type": "string"
|
||||
},
|
||||
"index": {
|
||||
"type": "integer"
|
||||
},
|
||||
"maxPowerLimit": {
|
||||
"type": "string"
|
||||
},
|
||||
"memTotal": {
|
||||
"type": "string"
|
||||
},
|
||||
"memUsed": {
|
||||
"type": "string"
|
||||
},
|
||||
"memoryUsage": {
|
||||
"type": "string"
|
||||
},
|
||||
"performanceState": {
|
||||
"type": "string"
|
||||
},
|
||||
"powerDraw": {
|
||||
"type": "string"
|
||||
},
|
||||
"powerUsage": {
|
||||
"type": "string"
|
||||
},
|
||||
"productName": {
|
||||
"type": "string"
|
||||
},
|
||||
"temperature": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.GenerateLoad": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -16317,6 +16324,34 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.MonitorSearch": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"param"
|
||||
],
|
||||
"properties": {
|
||||
"endTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"info": {
|
||||
"type": "string"
|
||||
},
|
||||
"param": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"all",
|
||||
"cpu",
|
||||
"memory",
|
||||
"load",
|
||||
"io",
|
||||
"network"
|
||||
]
|
||||
},
|
||||
"startTime": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.MysqlDBCreate": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -17793,6 +17828,9 @@
|
||||
"monitorStoreDays": {
|
||||
"type": "string"
|
||||
},
|
||||
"noAuthSetting": {
|
||||
"type": "string"
|
||||
},
|
||||
"ntpSite": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -17837,6 +17875,9 @@
|
||||
},
|
||||
"weChatVars": {
|
||||
"type": "string"
|
||||
},
|
||||
"xpackHideMenu": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -18083,6 +18124,9 @@
|
||||
},
|
||||
"sourceDir": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -18914,7 +18958,6 @@
|
||||
"request.FileCreate": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"mode",
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
@@ -20770,43 +20813,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.WebsiteWafReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"key",
|
||||
"rule",
|
||||
"websiteId"
|
||||
],
|
||||
"properties": {
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"rule": {
|
||||
"type": "string"
|
||||
},
|
||||
"websiteId": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.WebsiteWafUpdate": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"key",
|
||||
"websiteId"
|
||||
],
|
||||
"properties": {
|
||||
"enable": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"websiteId": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"response.AppDTO": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -21486,17 +21492,6 @@
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"response.WebsiteWafConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"content": {
|
||||
"type": "string"
|
||||
},
|
||||
"enable": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+137
-140
@@ -584,6 +584,8 @@ definitions:
|
||||
type: string
|
||||
backupAccounts:
|
||||
type: string
|
||||
command:
|
||||
type: string
|
||||
containerName:
|
||||
type: string
|
||||
dbName:
|
||||
@@ -632,6 +634,8 @@ definitions:
|
||||
type: string
|
||||
backupAccounts:
|
||||
type: string
|
||||
command:
|
||||
type: string
|
||||
containerName:
|
||||
type: string
|
||||
dbName:
|
||||
@@ -791,6 +795,10 @@ definitions:
|
||||
items:
|
||||
$ref: '#/definitions/dto.DiskInfo'
|
||||
type: array
|
||||
gpuData:
|
||||
items:
|
||||
$ref: '#/definitions/dto.GPUInfo'
|
||||
type: array
|
||||
ioCount:
|
||||
type: integer
|
||||
ioReadBytes:
|
||||
@@ -1186,6 +1194,33 @@ definitions:
|
||||
- type
|
||||
- vars
|
||||
type: object
|
||||
dto.GPUInfo:
|
||||
properties:
|
||||
fanSpeed:
|
||||
type: string
|
||||
gpuUtil:
|
||||
type: string
|
||||
index:
|
||||
type: integer
|
||||
maxPowerLimit:
|
||||
type: string
|
||||
memTotal:
|
||||
type: string
|
||||
memUsed:
|
||||
type: string
|
||||
memoryUsage:
|
||||
type: string
|
||||
performanceState:
|
||||
type: string
|
||||
powerDraw:
|
||||
type: string
|
||||
powerUsage:
|
||||
type: string
|
||||
productName:
|
||||
type: string
|
||||
temperature:
|
||||
type: string
|
||||
type: object
|
||||
dto.GenerateLoad:
|
||||
properties:
|
||||
encryptionMode:
|
||||
@@ -1528,6 +1563,26 @@ definitions:
|
||||
- interval
|
||||
- secret
|
||||
type: object
|
||||
dto.MonitorSearch:
|
||||
properties:
|
||||
endTime:
|
||||
type: string
|
||||
info:
|
||||
type: string
|
||||
param:
|
||||
enum:
|
||||
- all
|
||||
- cpu
|
||||
- memory
|
||||
- load
|
||||
- io
|
||||
- network
|
||||
type: string
|
||||
startTime:
|
||||
type: string
|
||||
required:
|
||||
- param
|
||||
type: object
|
||||
dto.MysqlDBCreate:
|
||||
properties:
|
||||
database:
|
||||
@@ -2526,6 +2581,8 @@ definitions:
|
||||
type: string
|
||||
monitorStoreDays:
|
||||
type: string
|
||||
noAuthSetting:
|
||||
type: string
|
||||
ntpSite:
|
||||
type: string
|
||||
panelName:
|
||||
@@ -2556,6 +2613,8 @@ definitions:
|
||||
type: string
|
||||
weChatVars:
|
||||
type: string
|
||||
xpackHideMenu:
|
||||
type: string
|
||||
type: object
|
||||
dto.SettingUpdate:
|
||||
properties:
|
||||
@@ -2717,6 +2776,8 @@ definitions:
|
||||
type: string
|
||||
sourceDir:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
files.FileInfo:
|
||||
properties:
|
||||
@@ -3283,7 +3344,6 @@ definitions:
|
||||
sub:
|
||||
type: boolean
|
||||
required:
|
||||
- mode
|
||||
- path
|
||||
type: object
|
||||
request.FileDeCompress:
|
||||
@@ -4517,31 +4577,6 @@ definitions:
|
||||
- id
|
||||
- user
|
||||
type: object
|
||||
request.WebsiteWafReq:
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
rule:
|
||||
type: string
|
||||
websiteId:
|
||||
type: integer
|
||||
required:
|
||||
- key
|
||||
- rule
|
||||
- websiteId
|
||||
type: object
|
||||
request.WebsiteWafUpdate:
|
||||
properties:
|
||||
enable:
|
||||
type: boolean
|
||||
key:
|
||||
type: string
|
||||
websiteId:
|
||||
type: integer
|
||||
required:
|
||||
- key
|
||||
- websiteId
|
||||
type: object
|
||||
response.AppDTO:
|
||||
properties:
|
||||
createdAt:
|
||||
@@ -4990,13 +5025,6 @@ definitions:
|
||||
version:
|
||||
type: string
|
||||
type: object
|
||||
response.WebsiteWafConfig:
|
||||
properties:
|
||||
content:
|
||||
type: string
|
||||
enable:
|
||||
type: boolean
|
||||
type: object
|
||||
host: localhost
|
||||
info:
|
||||
contact: {}
|
||||
@@ -5092,7 +5120,7 @@ paths:
|
||||
summary: Get app detail by id
|
||||
tags:
|
||||
- App
|
||||
/apps/ingored:
|
||||
/apps/ignored:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
@@ -10130,6 +10158,41 @@ paths:
|
||||
summary: Create group
|
||||
tags:
|
||||
- Firewall
|
||||
/hosts/monitor/clean:
|
||||
post:
|
||||
description: 清空监控数据
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Clean monitor datas
|
||||
tags:
|
||||
- Monitor
|
||||
x-panel-log:
|
||||
BeforeFunctions: []
|
||||
bodyKeys: []
|
||||
formatEN: clean monitor datas
|
||||
formatZH: 清空监控数据
|
||||
paramKeys: []
|
||||
/hosts/monitor/search:
|
||||
post:
|
||||
description: 获取监控数据
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/dto.MonitorSearch'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Load monitor datas
|
||||
tags:
|
||||
- Monitor
|
||||
/hosts/search:
|
||||
post:
|
||||
consumes:
|
||||
@@ -10791,6 +10854,19 @@ paths:
|
||||
summary: List runtimes
|
||||
tags:
|
||||
- Runtime
|
||||
/runtimes/sync:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 同步运行环境状态
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Sync runtime status
|
||||
tags:
|
||||
- Runtime
|
||||
/runtimes/update:
|
||||
post:
|
||||
consumes:
|
||||
@@ -11263,6 +11339,32 @@ paths:
|
||||
summary: Load system address
|
||||
tags:
|
||||
- System Setting
|
||||
/settings/menu/update:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 隐藏高级功能菜单
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/dto.SettingUpdate'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Update system setting
|
||||
tags:
|
||||
- System Setting
|
||||
x-panel-log:
|
||||
BeforeFunctions: []
|
||||
bodyKeys: []
|
||||
formatEN: Hide advanced feature menu.
|
||||
formatZH: 隐藏高级功能菜单
|
||||
paramKeys: []
|
||||
/settings/mfa:
|
||||
post:
|
||||
consumes:
|
||||
@@ -11311,23 +11413,6 @@ paths:
|
||||
formatEN: bind mfa
|
||||
formatZH: mfa 绑定
|
||||
paramKeys: []
|
||||
/settings/monitor/clean:
|
||||
post:
|
||||
description: 清空监控数据
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Clean monitor datas
|
||||
tags:
|
||||
- System Setting
|
||||
x-panel-log:
|
||||
BeforeFunctions: []
|
||||
bodyKeys: []
|
||||
formatEN: clean monitor datas
|
||||
formatZH: 清空监控数据
|
||||
paramKeys: []
|
||||
/settings/password/update:
|
||||
post:
|
||||
consumes:
|
||||
@@ -13197,7 +13282,7 @@ paths:
|
||||
$ref: '#/definitions/response.PHPConfig'
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Load websit php conf
|
||||
summary: Load website php conf
|
||||
tags:
|
||||
- Website
|
||||
/websites/php/update:
|
||||
@@ -13810,92 +13895,4 @@ paths:
|
||||
formatEN: Update website [primaryDomain]
|
||||
formatZH: 更新网站 [primaryDomain]
|
||||
paramKeys: []
|
||||
/websites/waf/config:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取网站 waf 配置
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/request.WebsiteWafReq'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/response.WebsiteWafConfig'
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Load websit waf conf
|
||||
tags:
|
||||
- Website WAF
|
||||
/websites/waf/file/update:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 更新 网站 waf 配置文件
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/request.WebsiteWafUpdate'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Update website waf file
|
||||
tags:
|
||||
- Website WAF
|
||||
x-panel-log:
|
||||
BeforeFunctions:
|
||||
- db: websites
|
||||
input_column: id
|
||||
input_value: websiteId
|
||||
isList: false
|
||||
output_column: primary_domain
|
||||
output_value: domain
|
||||
bodyKeys:
|
||||
- websiteId
|
||||
formatEN: WAF conf file update [domain]
|
||||
formatZH: WAF 配置文件修改 [domain]
|
||||
paramKeys: []
|
||||
/websites/waf/update:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 更新 网站 waf 配置
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/request.WebsiteWafUpdate'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Update website waf conf
|
||||
tags:
|
||||
- Website WAF
|
||||
x-panel-log:
|
||||
BeforeFunctions:
|
||||
- db: websites
|
||||
input_column: id
|
||||
input_value: websiteId
|
||||
isList: false
|
||||
output_column: primary_domain
|
||||
output_value: domain
|
||||
bodyKeys:
|
||||
- websiteId
|
||||
formatEN: WAF conf update [domain]
|
||||
formatZH: WAF 配置修改 [domain]
|
||||
paramKeys: []
|
||||
swagger: "2.0"
|
||||
|
||||
@@ -16,22 +16,6 @@ server {
|
||||
access_log /www/sites/domain/log/access.log;
|
||||
error_log /www/sites/domain/log/error.log;
|
||||
|
||||
access_by_lua_file /www/common/waf/access.lua;
|
||||
set $RulePath /www/sites/domain/waf/rules;
|
||||
set $logdir /www/sites/domain/waf/log;
|
||||
set $redirect on;
|
||||
set $attackLog on;
|
||||
set $CCDeny off;
|
||||
set $urlWhiteAllow off;
|
||||
set $urlBlockDeny off;
|
||||
set $argsDeny off;
|
||||
set $postDeny off;
|
||||
set $cookieDeny off;
|
||||
set $fileExtDeny off;
|
||||
set $ipBlockDeny off;
|
||||
set $ipWhiteAllow off;
|
||||
|
||||
|
||||
location ^~ /.well-known/acme-challenge {
|
||||
allow all;
|
||||
root /usr/share/nginx/html;
|
||||
|
||||
@@ -54,6 +54,14 @@ If you discover any security issues, please contact us through:
|
||||
- Email: support@fit2cloud.com
|
||||
- Phone: 400-052-0755
|
||||
|
||||
## Our Other Star Projects
|
||||
|
||||
- [JumpServer](https://github.com/jumpserver/jumpserver/) - A popular open-source PAM system
|
||||
- [DataEase](https://github.com/dataease/dataease/) - An open-source data visualization and analysis tool for everyone
|
||||
- [MeterSphere](https://github.com/metersphere/metersphere/) - An all-in-one open-source automated testing platform
|
||||
- [Halo](https://github.com/halo-dev/halo/) - A powerful and user-friendly open-source website building tool
|
||||
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#1Panel-dev/1Panel&Date)
|
||||
|
||||
@@ -54,6 +54,13 @@ curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_
|
||||
- メール: support@fit2cloud.com
|
||||
- 電話番号: 400-052-0755
|
||||
|
||||
## その他の主要プロジェクト
|
||||
|
||||
- [JumpServer](https://github.com/jumpserver/jumpserver/) - 人気のあるオープンソースのバスチョンホスト管理ツール
|
||||
- [DataEase](https://github.com/dataease/dataease/) - 誰でも利用できるオープンソースのデータ可視化および分析ツール
|
||||
- [MeterSphere](https://github.com/metersphere/metersphere/) - オールインワンのオープンソース自動化テストプラットフォーム
|
||||
- [Halo](https://github.com/halo-dev/halo/) - 強力で使いやすいオープンソースのウェブサイト構築ツール
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#1Panel-dev/1Panel&Date)
|
||||
|
||||
@@ -52,6 +52,13 @@ curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_
|
||||
- 郵箱:support@fit2cloud.com
|
||||
- 電話:400-052-0755
|
||||
|
||||
## 我們的其他明星專案
|
||||
|
||||
- [JumpServer](https://github.com/jumpserver/jumpserver/) - 受歡迎的開源堡壘機管理工具
|
||||
- [DataEase](https://github.com/dataease/dataease/) - 開源的數據可視化和分析工具,適用於所有人
|
||||
- [MeterSphere](https://github.com/metersphere/metersphere/) - 一站式開源自動化測試平台
|
||||
- [Halo](https://github.com/halo-dev/halo/) - 強大且易於使用的開源網站建設工具
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#1Panel-dev/1Panel&Date)
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/public/favicon.png" />
|
||||
<meta name="robots" content="noindex,nofollow" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
||||
<title>loading...</title>
|
||||
|
||||
@@ -42,9 +42,6 @@ class RequestHttp {
|
||||
this.service.interceptors.response.use(
|
||||
(response: AxiosResponse) => {
|
||||
const { data } = response;
|
||||
if (response.headers['x-csrf-token']) {
|
||||
globalStore.setCsrfToken(response.headers['x-csrf-token']);
|
||||
}
|
||||
if (data.code == ResultEnum.OVERDUE || data.code == ResultEnum.FORBIDDEN) {
|
||||
globalStore.setLogStatus(false);
|
||||
router.push({
|
||||
@@ -73,6 +70,11 @@ class RequestHttp {
|
||||
});
|
||||
return Promise.reject(data);
|
||||
}
|
||||
if (data.code == ResultEnum.ERRXPACK) {
|
||||
globalStore.isProductPro = false;
|
||||
window.location.reload();
|
||||
return Promise.reject(data);
|
||||
}
|
||||
if (data.code == ResultEnum.ERRGLOBALLOADDING) {
|
||||
globalStore.setGlobalLoading(true);
|
||||
globalStore.setLoadingText(data.message);
|
||||
|
||||
@@ -27,6 +27,8 @@ export namespace Container {
|
||||
imageInput: boolean;
|
||||
forcePull: boolean;
|
||||
network: string;
|
||||
ipv4: string;
|
||||
ipv6: string;
|
||||
cmdStr: string;
|
||||
entrypointStr: string;
|
||||
memoryItem: number;
|
||||
@@ -56,10 +58,10 @@ export namespace Container {
|
||||
protocol: string;
|
||||
}
|
||||
export interface Volume {
|
||||
type: string;
|
||||
sourceDir: string;
|
||||
containerDir: string;
|
||||
mode: string;
|
||||
isVolume: boolean;
|
||||
}
|
||||
export interface ContainerInfo {
|
||||
containerID: string;
|
||||
|
||||
@@ -9,6 +9,8 @@ export namespace Cronjob {
|
||||
specObjs: Array<SpecObj>;
|
||||
|
||||
script: string;
|
||||
isCustom: boolean;
|
||||
command: string;
|
||||
inContainer: boolean;
|
||||
containerName: string;
|
||||
appID: string;
|
||||
|
||||
@@ -59,6 +59,8 @@ export namespace Dashboard {
|
||||
|
||||
diskData: Array<DiskInfo>;
|
||||
|
||||
gpuData: Array<GPUInfo>;
|
||||
|
||||
netBytesSent: number;
|
||||
netBytesRecv: number;
|
||||
|
||||
@@ -78,4 +80,14 @@ export namespace Dashboard {
|
||||
inodesFree: number;
|
||||
inodesUsedPercent: number;
|
||||
}
|
||||
export interface GPUInfo {
|
||||
index: number;
|
||||
productName: string;
|
||||
gpuUtil: string;
|
||||
temperature: string;
|
||||
performanceState: string;
|
||||
powerUsage: string;
|
||||
memoryUsage: string;
|
||||
fanSpeed: string;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ export namespace File {
|
||||
export interface FileCreate {
|
||||
path: string;
|
||||
isDir: boolean;
|
||||
mode: number;
|
||||
mode?: number;
|
||||
isLink?: boolean;
|
||||
isSymlink?: boolean;
|
||||
linkPath?: boolean;
|
||||
|
||||
@@ -116,6 +116,18 @@ export namespace Host {
|
||||
rules: Array<RulePort>;
|
||||
}
|
||||
|
||||
export interface MonitorData {
|
||||
param: string;
|
||||
date: Array<Date>;
|
||||
value: Array<any>;
|
||||
}
|
||||
export interface MonitorSearch {
|
||||
param: string;
|
||||
info: string;
|
||||
startTime: Date;
|
||||
endTime: Date;
|
||||
}
|
||||
|
||||
export interface SSHInfo {
|
||||
autoStart: boolean;
|
||||
status: string;
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
export namespace Monitor {
|
||||
export interface MonitorData {
|
||||
param: string;
|
||||
date: Array<Date>;
|
||||
value: Array<any>;
|
||||
}
|
||||
export interface MonitorSearch {
|
||||
param: string;
|
||||
info: string;
|
||||
startTime: Date;
|
||||
endTime: Date;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ export namespace Setting {
|
||||
|
||||
panelName: string;
|
||||
theme: string;
|
||||
menuTabs: string;
|
||||
language: string;
|
||||
defaultNetwork: string;
|
||||
lastCleanTime: string;
|
||||
@@ -46,6 +47,8 @@ export namespace Setting {
|
||||
weChatVars: string;
|
||||
dingVars: string;
|
||||
snapshotIgnore: string;
|
||||
xpackHideMenu: string;
|
||||
noAuthSetting: string;
|
||||
}
|
||||
export interface SettingUpdate {
|
||||
key: string;
|
||||
@@ -140,4 +143,12 @@ export namespace Setting {
|
||||
latestVersion: string;
|
||||
releaseNote: string;
|
||||
}
|
||||
|
||||
export interface License {
|
||||
licenseName: string;
|
||||
assigneeName: string;
|
||||
productPro: string;
|
||||
trial: boolean;
|
||||
status: string;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,29 +258,6 @@ export namespace Website {
|
||||
appName: string;
|
||||
}
|
||||
|
||||
export interface WafReq {
|
||||
websiteId: number;
|
||||
key: string;
|
||||
rule: string;
|
||||
}
|
||||
|
||||
export interface WafRes {
|
||||
enable: boolean;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface WafUpdate {
|
||||
enable: boolean;
|
||||
websiteId: number;
|
||||
key: string;
|
||||
}
|
||||
|
||||
export interface WafFileUpdate {
|
||||
websiteId: number;
|
||||
type: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface DelReq {
|
||||
id: number;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,10 @@ export const checkIsSafety = (code: string) => {
|
||||
return http.get<string>(`/auth/issafety?code=${code}`);
|
||||
};
|
||||
|
||||
export const getResponsePage = () => {
|
||||
return http.get<string>(`/respagecode`);
|
||||
};
|
||||
|
||||
export const checkIsDemo = () => {
|
||||
return http.get<boolean>('/auth/demo');
|
||||
};
|
||||
|
||||
@@ -101,6 +101,20 @@ export const batchOperateRule = (params: Host.BatchRule) => {
|
||||
return http.post(`/hosts/firewall/batch`, params, TimeoutEnum.T_60S);
|
||||
};
|
||||
|
||||
// monitors
|
||||
export const loadMonitor = (param: Host.MonitorSearch) => {
|
||||
return http.post<Array<Host.MonitorData>>(`/hosts/monitor/search`, param);
|
||||
};
|
||||
export const getNetworkOptions = () => {
|
||||
return http.get<Array<string>>(`/hosts/monitor/netoptions`);
|
||||
};
|
||||
export const getIOOptions = () => {
|
||||
return http.get<Array<string>>(`/hosts/monitor/iooptions`);
|
||||
};
|
||||
export const cleanMonitors = () => {
|
||||
return http.post(`/hosts/monitor/clean`, {});
|
||||
};
|
||||
|
||||
// ssh
|
||||
export const getSSHInfo = () => {
|
||||
return http.post<Host.SSHInfo>(`/hosts/ssh/search`);
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import http from '@/api';
|
||||
import { Monitor } from '../interface/monitor';
|
||||
|
||||
export const loadMonitor = (param: Monitor.MonitorSearch) => {
|
||||
return http.post<Array<Monitor.MonitorData>>(`/monitors/search`, param);
|
||||
};
|
||||
|
||||
export const getNetworkOptions = () => {
|
||||
return http.get<Array<string>>(`/monitors/netoptions`);
|
||||
};
|
||||
|
||||
export const getIOOptions = () => {
|
||||
return http.get<Array<string>>(`/monitors/iooptions`);
|
||||
};
|
||||
@@ -6,6 +6,22 @@ import { Backup } from '../interface/backup';
|
||||
import { Setting } from '../interface/setting';
|
||||
import { TimeoutEnum } from '@/enums/http-enum';
|
||||
|
||||
export const UploadFileData = (params: FormData) => {
|
||||
return http.upload('/licenses/upload', params);
|
||||
};
|
||||
|
||||
export const getLicense = () => {
|
||||
return http.get<Setting.License>(`/licenses/get`);
|
||||
};
|
||||
|
||||
export const syncLicense = () => {
|
||||
return http.post(`/licenses/sync`);
|
||||
};
|
||||
|
||||
export const unbindLicense = () => {
|
||||
return http.post(`/licenses/unbind`);
|
||||
};
|
||||
|
||||
export const getSettingInfo = () => {
|
||||
return http.post<Setting.SettingInfo>(`/settings/search`);
|
||||
};
|
||||
@@ -17,6 +33,10 @@ export const updateSetting = (param: Setting.SettingUpdate) => {
|
||||
return http.post(`/settings/update`, param);
|
||||
};
|
||||
|
||||
export const updateMenu = (param: Setting.SettingUpdate) => {
|
||||
return http.post(`/settings/menu/update`, param);
|
||||
};
|
||||
|
||||
export const updatePassword = (param: Setting.PasswordUpdate) => {
|
||||
return http.post(`/settings/password/update`, param);
|
||||
};
|
||||
@@ -54,10 +74,6 @@ export const syncTime = (ntpSite: string) => {
|
||||
return http.post<string>(`/settings/time/sync`, { ntpSite: ntpSite });
|
||||
};
|
||||
|
||||
export const cleanMonitors = () => {
|
||||
return http.post(`/settings/monitor/clean`, {});
|
||||
};
|
||||
|
||||
export const loadMFA = (param: Setting.MFARequest) => {
|
||||
return http.post<Setting.MFAInfo>(`/settings/mfa`, param);
|
||||
};
|
||||
|
||||
@@ -144,18 +144,6 @@ export const PreCheck = (req: Website.CheckReq) => {
|
||||
return http.post<Website.CheckRes[]>(`/websites/check`, req);
|
||||
};
|
||||
|
||||
export const GetWafConfig = (req: Website.WafReq) => {
|
||||
return http.post<Website.WafRes>(`/websites/waf/config`, req);
|
||||
};
|
||||
|
||||
export const UpdateWafEnable = (req: Website.WafUpdate) => {
|
||||
return http.post<any>(`/websites/waf/update`, req);
|
||||
};
|
||||
|
||||
export const UpdateWafFile = (req: Website.WafFileUpdate) => {
|
||||
return http.post<any>(`/websites/waf/file/update`, req);
|
||||
};
|
||||
|
||||
export const UpdateNginxFile = (req: Website.NginxUpdate) => {
|
||||
return http.post<any>(`/websites/nginx/update`, req);
|
||||
};
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
@font-face {
|
||||
font-family: "panel"; /* Project id 3575356 */
|
||||
src: url('iconfont.woff2?t=1701341406915') format('woff2'),
|
||||
url('iconfont.woff?t=1701341406915') format('woff'),
|
||||
url('iconfont.ttf?t=1701341406915') format('truetype'),
|
||||
url('iconfont.svg?t=1701341406915#panel') format('svg');
|
||||
src: url('iconfont.woff2?t=1712830223091') format('woff2'),
|
||||
url('iconfont.woff?t=1712830223091') format('woff'),
|
||||
url('iconfont.ttf?t=1712830223091') format('truetype'),
|
||||
url('iconfont.svg?t=1712830223091#panel') format('svg');
|
||||
}
|
||||
|
||||
.panel {
|
||||
@@ -14,6 +14,66 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.p-xpack:before {
|
||||
content: "\e604";
|
||||
}
|
||||
|
||||
.p-gpu-2:before {
|
||||
content: "\e6d8";
|
||||
}
|
||||
|
||||
.p-gpu-1:before {
|
||||
content: "\e623";
|
||||
}
|
||||
|
||||
.p-waf-4:before {
|
||||
content: "\e608";
|
||||
}
|
||||
|
||||
.p-waf-1:before {
|
||||
content: "\e62a";
|
||||
}
|
||||
|
||||
.p-waf-2:before {
|
||||
content: "\e682";
|
||||
}
|
||||
|
||||
.p-waf-3:before {
|
||||
content: "\e666";
|
||||
}
|
||||
|
||||
.p-setting-1:before {
|
||||
content: "\e626";
|
||||
}
|
||||
|
||||
.p-setting-2:before {
|
||||
content: "\e630";
|
||||
}
|
||||
|
||||
.p-setting-3:before {
|
||||
content: "\e617";
|
||||
}
|
||||
|
||||
.p-tamper-4:before {
|
||||
content: "\e7c3";
|
||||
}
|
||||
|
||||
.p-tamper-2:before {
|
||||
content: "\e610";
|
||||
}
|
||||
|
||||
.p-tamper-3:before {
|
||||
content: "\ec4d";
|
||||
}
|
||||
|
||||
.p-tamper-1:before {
|
||||
content: "\e687";
|
||||
}
|
||||
|
||||
.p-tongji:before {
|
||||
content: "\e856";
|
||||
}
|
||||
|
||||
.p-webdav:before {
|
||||
content: "\e622";
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -5,6 +5,111 @@
|
||||
"css_prefix_text": "p-",
|
||||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "3722144",
|
||||
"name": "钻石",
|
||||
"font_class": "xpack",
|
||||
"unicode": "e604",
|
||||
"unicode_decimal": 58884
|
||||
},
|
||||
{
|
||||
"icon_id": "640495",
|
||||
"name": "详细信息",
|
||||
"font_class": "gpu-2",
|
||||
"unicode": "e6d8",
|
||||
"unicode_decimal": 59096
|
||||
},
|
||||
{
|
||||
"icon_id": "6176565",
|
||||
"name": "监控",
|
||||
"font_class": "gpu-1",
|
||||
"unicode": "e623",
|
||||
"unicode_decimal": 58915
|
||||
},
|
||||
{
|
||||
"icon_id": "8229531",
|
||||
"name": "ACL策略",
|
||||
"font_class": "waf-4",
|
||||
"unicode": "e608",
|
||||
"unicode_decimal": 58888
|
||||
},
|
||||
{
|
||||
"icon_id": "8765146",
|
||||
"name": "地图",
|
||||
"font_class": "waf-1",
|
||||
"unicode": "e62a",
|
||||
"unicode_decimal": 58922
|
||||
},
|
||||
{
|
||||
"icon_id": "16563651",
|
||||
"name": "8-4限制区域",
|
||||
"font_class": "waf-2",
|
||||
"unicode": "e682",
|
||||
"unicode_decimal": 59010
|
||||
},
|
||||
{
|
||||
"icon_id": "17064153",
|
||||
"name": "拦截",
|
||||
"font_class": "waf-3",
|
||||
"unicode": "e666",
|
||||
"unicode_decimal": 58982
|
||||
},
|
||||
{
|
||||
"icon_id": "899647",
|
||||
"name": "欢迎页",
|
||||
"font_class": "setting-1",
|
||||
"unicode": "e626",
|
||||
"unicode_decimal": 58918
|
||||
},
|
||||
{
|
||||
"icon_id": "1114667",
|
||||
"name": "图标",
|
||||
"font_class": "setting-2",
|
||||
"unicode": "e630",
|
||||
"unicode_decimal": 58928
|
||||
},
|
||||
{
|
||||
"icon_id": "12010559",
|
||||
"name": "注册网站",
|
||||
"font_class": "setting-3",
|
||||
"unicode": "e617",
|
||||
"unicode_decimal": 58903
|
||||
},
|
||||
{
|
||||
"icon_id": "435944",
|
||||
"name": "日志",
|
||||
"font_class": "tamper-4",
|
||||
"unicode": "e7c3",
|
||||
"unicode_decimal": 59331
|
||||
},
|
||||
{
|
||||
"icon_id": "5799978",
|
||||
"name": "扫描",
|
||||
"font_class": "tamper-2",
|
||||
"unicode": "e610",
|
||||
"unicode_decimal": 58896
|
||||
},
|
||||
{
|
||||
"icon_id": "5961299",
|
||||
"name": "安全",
|
||||
"font_class": "tamper-3",
|
||||
"unicode": "ec4d",
|
||||
"unicode_decimal": 60493
|
||||
},
|
||||
{
|
||||
"icon_id": "28131805",
|
||||
"name": "完整性检查",
|
||||
"font_class": "tamper-1",
|
||||
"unicode": "e687",
|
||||
"unicode_decimal": 59015
|
||||
},
|
||||
{
|
||||
"icon_id": "5838475",
|
||||
"name": "统计",
|
||||
"font_class": "tongji",
|
||||
"unicode": "e856",
|
||||
"unicode_decimal": 59478
|
||||
},
|
||||
{
|
||||
"icon_id": "23044673",
|
||||
"name": "webdav",
|
||||
|
||||
@@ -14,6 +14,36 @@
|
||||
/>
|
||||
<missing-glyph />
|
||||
|
||||
<glyph glyph-name="xpack" unicode="" d="M971.527 503.922L839.149 726.406c-5.729 11.652-17.836 20.114-32.248 20.114H217.227v-0.442c-12.134 0-24.007-5.962-30.647-17.394L54.201 506.903c-10.077-14.177-8.931-33.836 3.645-46.178l428.043-428.499 1.133-0.456c13.943-13.722 36.362-13.722 50.306 0l428.707 428.955h-0.222c11.43 11.431 14.412 29.267 5.714 43.197zM760.032 674.968l-85.743-140.632a47.989 47.989 0 0 1-3.789 0.164c-2.771 0-5.48-0.25-8.12-0.706l-98.988 141.174h196.64z m-132.05-166.793c-0.136-0.271-0.273-0.541-0.404-0.815H401.421a47.213 47.213 0 0 1-2.563 4.683l113.537 161.311 115.587-165.179zM460.736 674.968l-98.403-140.636a48.105 48.105 0 0 1-3.833 0.167c-2.775 0-5.49-0.251-8.135-0.708l-86.504 141.176h196.875z m-234.605-19.45l89.842-147.361c-0.132-0.265-0.267-0.528-0.394-0.796h-178.16l88.712 148.157zM154.799 464.37h161.928c6.511-11.994 18.04-20.861 31.767-23.805l98.051-267.719L154.799 464.37z m357.597-345.475L390.021 451.478a47.675 47.675 0 0 1 10.252 12.892h228.454a47.625 47.625 0 0 1 6.843-9.55L512.396 118.89499999999998z m64.939 53.951l97.977 266.896c15.992 1.609 29.644 11.149 36.962 24.628h156.364L577.335 172.846zM713.422 507.36a47.323 47.323 0 0 1-2.727 4.938l87.756 143.22 88.022-148.158H713.422z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="gpu-2" unicode="" d="M392.585795 223.71443399999998l-93.230358 0c-14.145162 0-25.611308-11.466146-25.611308-25.611308s11.467169-25.611308 25.611308-25.611308l93.230358 0c14.145162 0 25.611308 11.466146 25.611308 25.611308S406.729933 223.71443399999998 392.585795 223.71443399999998zM392.585795 103.84434599999997l-93.230358 0c-14.145162 0-25.611308-11.466146-25.611308-25.611308s11.467169-25.611308 25.611308-25.611308l93.230358 0c14.145162 0 25.611308 11.466146 25.611308 25.611308S406.729933 103.84434599999997 392.585795 103.84434599999997zM392.585795 330.26312199999995l-93.230358 0c-14.145162 0-25.611308-11.466146-25.611308-25.611308s11.467169-25.611308 25.611308-25.611308l93.230358 0c14.145162 0 25.611308 11.466146 25.611308 25.611308S406.729933 330.26312199999995 392.585795 330.26312199999995zM473.523175 304.65181399999994c0-14.145162 11.467169-25.611308 25.611308-25.611308l226.416729 0c14.145162 0 25.611308 11.466146 25.611308 25.611308s-11.466146 25.611308-25.611308 25.611308l-226.416729 0C484.990345 330.26312199999995 473.523175 318.796976 473.523175 304.65181399999994zM852.245729 471.110987c-54.019311 71.51887-226.167043 271.164886-294.330492 347.954807-2.820232 3.175319-6.088672 5.656837-9.639544 7.385201l-2.437515 2.849908-9.704013 0c-0.049119 0-0.097214 0.004093-0.146333 0.004093-0.039909 0-0.079818-0.004093-0.12075-0.004093L213.635123 829.300902c-15.878642 0-32.363082-6.886851-45.228087-18.896372-13.467733-12.571317-21.190625-29.167297-21.190625-45.533033L147.216411 5.710303999999951c0-16.116049 7.467065-32.885991 20.48659-46.007847 13.072737-13.175067 29.815049-20.732184 45.933145-20.732184l602.350774 0c16.676821 0 33.07428 8.121981 44.989657 22.281469 10.622942 12.624529 16.714683 28.828582 16.714683 44.457538L877.691261 441.366545 852.245729 471.110987zM559.654858 734.350366l239.987816-280.545534L563.927161 453.804832c-2.067079 3.163039-4.272303 9.214872-4.272303 13.115716L559.654858 734.350366zM826.467623 5.710303999999951c0-7.726985-7.185656-15.516392-10.480702-15.516392L213.635123-9.806087000000048c-5.396917 0-15.196097 10.005888-15.196097 15.516392L198.439026 764.87252c0 4.66423 8.933463 13.205766 15.196097 13.205766l294.79712 0 0-311.158762c0-26.295899 18.24555-64.339354 51.235918-64.339354l266.799462 0L826.467623 5.710303999999951zM430.875866 634.92696L297.690518 634.92696c-14.145162 0-25.611308-11.467169-25.611308-25.611308l0-133.186372c0-14.145162 11.467169-25.612331 25.611308-25.612331l133.185348 0c14.145162 0 25.611308 11.467169 25.611308 25.612331L456.487174 609.314629C456.487174 623.45979 445.021028 634.92696 430.875866 634.92696zM405.264559 501.739565l-81.962733 0 0 81.963757 81.962733 0L405.264559 501.739565zM725.551212 223.71443399999998l-226.416729 0c-14.145162 0-25.611308-11.466146-25.611308-25.611308s11.467169-25.611308 25.611308-25.611308l226.416729 0c14.145162 0 25.611308 11.466146 25.611308 25.611308S739.697397 223.71443399999998 725.551212 223.71443399999998zM725.551212 103.84434599999997l-226.416729 0c-14.145162 0-25.611308-11.466146-25.611308-25.611308s11.467169-25.611308 25.611308-25.611308l226.416729 0c14.145162 0 25.611308 11.466146 25.611308 25.611308S739.697397 103.84434599999997 725.551212 103.84434599999997z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="gpu-1" unicode="" d="M838.22 139.59000000000003H187.78a89.1 89.1 0 0 0-89.1 89.1V697.46a89.1 89.1 0 0 0 89.1 89.1h650.44a89.1 89.1 0 0 0 89.1-89.1v-468.77a89.1 89.1 0 0 0-89.1-89.1zM852 224.64999999999998V701.5a9 9 0 0 1-9 8.95H183a9 9 0 0 1-9-8.95v-476.85a9 9 0 0 1 9-8.94h660a9 9 0 0 1 9 8.94zM287.01 63.48000000000002m37.86 0l376.26 0q37.86 0 37.86-37.86l0-0.39q0-37.86-37.86-37.86l-376.26 0q-37.86 0-37.86 37.86l0 0.39q0 37.86 37.86 37.86ZM249.34 558.22m31.68 0l11.97 0q31.68 0 31.68-31.68l0-203.04q0-31.68-31.68-31.68l-11.97 0q-31.68 0-31.68 31.68l0 203.04q0 31.68 31.68 31.68ZM400 444.05m37.67 0l-0.01 0q37.67 0 37.67-37.67l0-76.89q0-37.67-37.67-37.67l0.01 0q-37.67 0-37.67 37.67l0 76.89q0 37.67 37.67 37.67ZM550.67 634.3299999999999m37.67 0l-0.01 0q37.67 0 37.67-37.67l0-267.17q0-37.67-37.67-37.67l0.01 0q-37.67 0-37.67 37.67l0 267.17q0 37.67 37.67 37.67ZM701.33 482.11m37.67 0l-0.01 0q37.67 0 37.67-37.67l0-114.94q0-37.67-37.67-37.67l0.01 0q-37.67 0-37.67 37.67l0 114.94q0 37.67 37.67 37.67Z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="waf-4" unicode="" d="M136.533333 759.466667h546.133334v-68.266667H136.533333zM136.533333 622.933333h546.133334v-68.266666H136.533333zM136.533333 486.4h546.133334v-68.266667H136.533333zM136.533333 349.866667h68.266667v-68.266667H136.533333zM136.533333 213.33333300000004h68.266667v-68.266666H136.533333zM466.261333 55.63733300000001h68.266667L546.133333 8.53333299999997h43.690667l-68.266667 204.8H477.866667l-68.266667-204.8h43.008z m30.037334 105.130667a81.92 81.92 0 0 1 0 17.066667 84.650667 84.650667 0 0 1 0-17.749334l21.162666-68.266666H477.866667zM691.541333 8.53333299999997a115.370667 115.370667 0 0 1 53.248 10.922667v38.912a84.650667 84.650667 0 0 0-45.738666-12.970667 53.248 53.248 0 0 0-42.325334 17.749334 68.266667 68.266667 0 0 0-15.701333 47.104 68.266667 68.266667 0 0 0 16.384 48.469333 55.296 55.296 0 0 0 43.690667 18.432 79.872 79.872 0 0 0 43.008-11.605333v40.96a121.514667 121.514667 0 0 1-45.738667 7.509333 92.842667 92.842667 0 0 1-68.266667-30.037333 108.544 108.544 0 0 1-27.989333-76.458667 101.034667 101.034667 0 0 1 24.576-68.266667 86.698667 86.698667 0 0 1 64.853333-30.72zM887.466667 44.03200000000004h-69.632V213.33333300000004h-40.277334v-204.8H887.466667v35.498667zM819.2 349.866667V896H0v-1024h1024V349.866667zM68.266667-59.733333000000016V827.733333h682.666666v-477.866666H273.066667v-409.6z m887.466666 0H341.333333V281.6h614.4z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="waf-1" unicode="" d="M1017.6 6.399999999999977c-6.4 12.8-6.4 19.2-6.4 19.2l-121.6 236.8-6.4 6.4-6.4 6.4c-12.8 19.2-25.6 44.8-57.6 44.8h-128c-19.2 0-25.6-12.8-25.6-25.6s12.8-25.6 25.6-25.6h128s6.4-6.4 12.8-19.2l6.4-6.4 121.6-217.6s-6.4-6.4-12.8-6.4h-870.4s-6.4 0-6.4 6.4l128 217.6s6.4 6.4 6.4 12.8 6.4 6.4 0 6.4h115.2c19.2 0 25.6 12.8 25.6 25.6s-12.8 25.6-25.6 25.6h-115.2c-32 0-44.8-19.2-51.2-32l-6.4-6.4s-6.4-6.4-6.4-12.8l-134.4-230.4v-12.8c0-38.4 32-64 70.4-64h870.4c32-6.4 70.4 12.8 70.4 51.2zM512 492.8c70.4 0 128 57.6 128 128s-57.6 128-128 128-128-57.6-128-128 57.6-128 128-128z m0 198.4c38.4 0 70.4-32 70.4-70.4-6.4-38.4-38.4-70.4-70.4-70.4-38.4 0-70.4 32-70.4 70.4 0 38.4 32 70.4 70.4 70.4zM441.6 211.20000000000005c25.6-32 44.8-44.8 70.4-44.8s44.8 12.8 70.4 44.8c70.4 76.8 160 185.6 192 307.2 25.6 83.2 6.4 172.8-44.8 249.6-51.2 64-134.4 102.4-217.6 102.4-96 0-172.8-38.4-230.4-102.4-51.2-64-64-160-32-249.6 25.6-83.2 89.6-192 192-307.2z m-115.2 524.8c32 51.2 96 76.8 179.2 76.8 64 0 128-32 166.4-83.2 44.8-57.6 64-134.4 44.8-198.4-32-115.2-115.2-217.6-185.6-281.6l-25.6-25.6s-6.4 6.4-6.4 12.8c-6.4 6.4-6.4 12.8-12.8 12.8l-12.8 12.8c-44.8 51.2-140.8 166.4-172.8 275.2-19.2 70.4-12.8 140.8 25.6 198.4z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="waf-2" unicode="" d="M458.752 857.6C360.96 857.6 281.6 778.24 281.6 680.448c0-23.04 12.8-79.872 98.304-201.216 29.184-41.472 58.88-78.848 78.848-102.912 19.968 24.064 49.664 61.44 78.848 102.912 85.504 121.344 98.304 178.176 98.304 201.216 0 97.792-79.36 177.152-177.152 177.152z m0-257.024c-50.176 0-91.136 40.96-91.136 91.136s40.96 91.136 91.136 91.136 91.136-40.96 91.136-91.136-40.96-91.136-91.136-91.136zM417.28 161.27999999999997H141.312v286.72h132.096v61.44H129.024c-27.136 0-49.152-22.016-49.152-49.152V148.48000000000002c0-27.136 22.016-49.152 49.152-49.152H419.84c-2.048 14.336-3.072 28.672-3.072 43.52 0 6.144 0 12.288 0.512 18.432zM837.632 460.288c0 27.136-22.016 49.152-49.152 49.152h-138.752v-61.44h126.464V430.08c21.504-4.608 41.984-11.776 61.44-20.992v51.2zM381.952 371.20000000000005H227.328v-133.12h205.312c6.144 17.408 13.824 34.304 22.528 50.176l-73.216 82.944zM711.168 314.88c94.72 0 171.52-76.8 171.52-171.52s-76.8-171.52-171.52-171.52-171.52 76.8-171.52 171.52 76.8 171.52 171.52 171.52m0 61.44c-128.512 0-232.96-104.448-232.96-232.96s104.448-232.96 232.96-232.96 232.96 104.448 232.96 232.96-104.448 232.96-232.96 232.96zM526.40768 42.94143999999994l334.90944 261.6064 37.82144-48.41984-334.90944-261.6064z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="waf-3" unicode="" d="M818.869708 193.34349299999997h-185.924226a38.390594 38.390594 0 1 1 0-75.07494h185.924226a38.390594 38.390594 0 1 1 0 75.07494zM198.136454 623.8868990000001h441.634022a42.656216 42.656216 0 0 1 45.499964 38.049344 49.139961 49.139961 0 0 1-45.499964 45.499964H198.07958a42.656216 42.656216 0 0 1-38.049345-45.499964 35.944971 35.944971 0 0 1 38.049345-38.049344z m152.311129-319.807869H198.136454a42.656216 42.656216 0 0 1-38.049344-45.499964 35.944971 35.944971 0 0 1 38.049344-38.049345h144.689885a35.944971 35.944971 0 0 1 38.049344 38.049345c0 22.749982-7.621244 45.499964-30.484975 45.499964zM548.429299 463.954527a35.944971 35.944971 0 0 1-38.049344 38.049344H205.473324a38.10622 38.10622 0 0 1 0-76.155564h304.565381c23.091232-7.564369 38.333719 15.299363 38.333719 38.163095zM806.072843 431.080803V779.553649a97.313047 97.313047 0 0 1-58.069328 94.412425A65.918072 65.918072 0 0 1 697.157305 895.749181H116.35027A105.73054 105.73054 0 0 1 29.21784 859.46296 109.199913 109.199913 0 0 1 0.154738 779.553649v-675.21946a126.717399 126.717399 0 0 1 29.063102-87.13243 109.199913 109.199913 0 0 1 79.624936-29.063102h341.249727a33.214973 33.214973 0 0 1 36.286221 29.063102c21.783108-21.783108 36.286221-43.566215 58.069329-65.349323A280.507276 280.507276 0 0 1 740.723521-128 283.521648 283.521648 0 0 1 1023.903919 155.18039899999997a287.616645 287.616645 0 0 1-217.831076 275.900404z m138.20614-275.900404a202.929838 202.929838 0 0 0-203.555462-203.555463 230.571066 230.571066 0 0 0-145.201759 58.069329 205.375461 205.375461 0 0 0 145.201759 348.529721 207.764209 207.764209 0 0 0 203.555462-203.043587z m-486.678986-87.132431h-341.249727c-7.279994 0-21.783108 7.279994-29.063102 7.279994-7.507494 7.109369-7.507494 14.503113-7.507494 29.006227V779.553649a43.679965 43.679965 0 0 0 7.279994 29.063102 43.679965 43.679965 0 0 0 29.290602 7.507494h573.583916c7.279994 0 14.503113-7.279994 21.783108-7.279994a37.708095 37.708095 0 0 0 14.503113-29.063102V431.080803a284.374773 284.374773 0 0 1-268.62041-275.900404 513.410214 513.410214 0 0 1 14.616863-87.132431h-14.616863z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="setting-1" unicode="" d="M586.587654-76.34850100000006l0 299.434215c0 3.973192 0 7.585185 0 10.835979 0.361199 11.197178 0.361199 21.310758-2.528395 24.200353-1.444797 1.444797-5.05679 3.250794-14.447972 3.250794l-114.861376 0c-9.391182 0-13.003175-1.805996-14.447972-3.250794-3.250794-3.250794-2.889594-13.003175-2.528395-24.200353 0-3.250794 0-6.862787 0-10.835979l0-299.434215L282.096649-76.34850100000006c-65.015873 0-118.112169 58.514286-118.112169 130.392945l0 263.314286L123.891358 317.35873000000004c-31.424339 0-55.985891 15.17037-67.905467 41.17672-9.391182 21.310758-7.223986 57.069489 26.728748 92.828219l341.694533 355.420106c23.116755 24.200353 54.179894 37.203527 87.410229 37.203527 33.230335 0 64.293474-13.364374 87.410229-37.203527l341.694533-355.420106c34.313933-35.397531 36.119929-71.156261 26.728748-92.467019-5.417989-12.280776-23.116755-41.17672-67.905467-41.17672l-40.093122 0L859.654321 54.40564400000005c0-71.87866-53.096296-130.392945-118.112169-130.392945L586.587654-75.987302zM741.903351 0.22574999999994816c24.922751 0 41.537919 28.173545 41.537919 54.179894L783.44127 393.932981l104.747795 0c-1.083598 1.805996-2.167196 3.611993-3.611993 4.695591l-341.694533 355.058907c-8.668783 9.029982-19.504762 14.086772-29.979541 14.086772 0 0-0.361199 0-0.361199 0-11.197178 0-22.755556-5.05679-31.424339-14.086772l-341.694533-355.058907c-1.444797-1.444797-2.528395-2.889594-3.611993-4.695591l104.747795 0L240.55873 54.40564400000005c0-26.367549 16.615168-54.179894 41.537919-54.179894L361.199295 0.22574999999994816l0 223.221164c0 77.296649 30.70194 114.500176 93.189418 114.500176l114.861376 0c62.848677 0 93.550617-37.564727 93.550617-114.500176L662.800705 0.22574999999994816 741.903351 0.22574999999994816z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="setting-2" unicode="" d="M437.996 198.481L437.996 198.481 437.996 309.278 327.195 309.278c-61.187 0-110.797-49.61-110.797-110.797 0-61.195 49.61-110.797 110.797-110.797C388.387 87.68399999999997 437.996 137.28599999999994 437.996 198.481L437.996 198.481 437.996 198.481 437.996 198.481zM493.395 198.481c0-91.789-74.411-166.195-166.2-166.195C235.41 32.285999999999945 161 106.69200000000001 161 198.481c0 91.789 74.41 166.195 166.195 166.195l110.801 0 55.399 0 0-55.398L493.395 198.481 493.395 198.481 493.395 198.481zM585.723 198.481L585.723 309.278 696.52 309.278c61.195 0 110.796-49.61 110.796-110.797 0-61.195-49.601-110.797-110.796-110.797C635.332 87.68399999999997 585.723 137.28599999999994 585.723 198.481L585.723 198.481 585.723 198.481zM530.324 198.481c0-91.789 74.41-166.195 166.196-166.195 91.789 0 166.199 74.406 166.199 166.195 0 91.789-74.41 166.195-166.199 166.195L585.723 364.67600000000004l-55.399 0 0-55.398L530.324 198.481 530.324 198.481 530.324 198.481zM437.996 567.8050000000001l0-110.801L327.195 457.004c-61.187 0-110.797 49.61-110.797 110.801 0 61.188 49.61 110.797 110.797 110.797C388.387 678.602 437.996 628.9929999999999 437.996 567.8050000000001L437.996 567.8050000000001 437.996 567.8050000000001zM493.395 567.8050000000001c0 91.785-74.411 166.195-166.2 166.195C235.41 734 161 659.59 161 567.8050000000001c0-91.789 74.41-166.199 166.195-166.199l110.801 0 55.399 0 0 55.398L493.395 567.8050000000001 493.395 567.8050000000001 493.395 567.8050000000001zM585.723 567.8050000000001l0-110.801L696.52 457.004c61.195 0 110.796 49.61 110.796 110.801 0 61.188-49.601 110.797-110.796 110.797C635.332 678.602 585.723 628.9929999999999 585.723 567.8050000000001L585.723 567.8050000000001 585.723 567.8050000000001zM530.324 567.8050000000001L530.324 567.8050000000001C530.324 659.59 604.734 734 696.52 734c91.789 0 166.199-74.41 166.199-166.195 0-91.789-74.41-166.199-166.199-166.199L585.723 401.606l-55.399 0 0 55.398L530.324 567.8050000000001 530.324 567.8050000000001 530.324 567.8050000000001zM530.324 567.8050000000001" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="setting-3" unicode="" d="M827.5 118.60000000000002c60.5 71.8 97 164.4 97 265.4 0 227.4-185.1 412.5-412.5 412.5S99.5 611.4 99.5 384 284.6-28.5 512-28.5c121 0 230 52.4 305.5 135.6l2.7-1.5 7.3 13zM512 534.8c28.7 0 57.2 1.8 85.4 5.3 10.1-47.5 16-97.1 17.2-147.9H415.5c1.2 50.5 7 99.9 17 147.2 26.2-3.1 52.8-4.6 79.5-4.6z m-70.1 43.8C458.8 641 483.4 699 515 750c31.5-50.8 56-108.5 72.9-170.7-25.1-2.9-50.4-4.4-75.9-4.4-23.6 0-46.9 1.2-70.1 3.7z m212.8-186.4c-1.2 52.7-7.2 104.4-17.6 154 61.3 11.3 120.3 30.9 174.9 58.3 44-59.7 70.7-133 72.4-212.3H654.7z m-279.3 0H139.7c1.7 79.3 28.4 152.6 72.4 212.3 56.4-28.3 117.3-48.3 180.7-59.4-10.4-49.2-16.2-100.5-17.4-152.9z m0-40.1c1.1-46.8 6-93 14.5-137.8-60.7-10.9-119.2-30-173.4-56.7-42.1 54.8-69.3 121.7-75.5 194.4h234.4z m40.1 0h199.1c-1.1-45.1-5.9-89.6-14.2-132.5-29.1 3.7-58.6 5.7-88.4 5.7-27.7 0-55.2-1.7-82.4-4.9-8.3 42.6-13 86.8-14.1 131.7z m239.2 0H883c-6.2-72.7-33.4-139.6-75.5-194.4-52.5 25.8-108.9 44.5-167.5 55.6 8.6 45 13.6 91.6 14.7 138.8z m131 284.2c-49.5-23.9-102.7-41-157.9-51-16 60.5-38.9 117.3-68.1 168.1 88.9-11.5 168.1-54.3 226-117.1zM470.8 754.1c-29.6-51.4-52.8-108.7-68.9-169.9-57.3 9.8-112.4 27.3-163.7 52.1 59.4 64.3 141.1 107.7 232.6 117.8zM243.5 126.20000000000005c48.7 22.9 100.8 39.3 154.8 48.9 13.8-56.8 33.5-110.6 58.6-159.4-83.2 12.4-157.6 52.4-213.4 110.5z m261.2-114.5c-29 50.7-51.3 108.1-66.5 169.2 24.4 2.8 49 4.2 73.8 4.2 26.8 0 53.5-1.6 79.7-4.9-15.1-60.8-37.5-117.9-66.3-168.4-4.5-0.2-8.9-0.2-13.4-0.2-2.4 0-4.9 0-7.3 0.1z m68.9 5c24.7 48.3 44.2 101.4 57.9 157.4 52-9.7 102.1-25.8 149-47.9-54.3-56.5-126.3-96-206.9-109.5z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="tamper-4" unicode="" d="M781.824 552.5333330000001L242.133333 552.5333330000001c-11.797333 0-21.354667-9.557333-21.354667-21.354667 0-11.797333 9.557333-21.354667 21.354667-21.354667l539.690667 0c11.84 0 21.376 9.578667 21.376 21.354667C803.2 542.954667 793.664 552.5333330000001 781.824 552.5333330000001zM242.133333 362.624l441.578667 0c11.84 0 21.376 9.6 21.376 21.376s-9.536 21.354667-21.376 21.354667L242.133333 405.354667c-11.797333 0-21.354667-9.557333-21.354667-21.354667S230.336 362.624 242.133333 362.624zM781.824 258.218667L242.133333 258.218667c-11.797333 0-21.354667-9.557333-21.354667-21.376 0-11.84 9.557333-21.376 21.354667-21.376l539.690667 0c11.84 0 21.376 9.536 21.376 21.376C803.2 248.64 793.664 258.218667 781.824 258.218667zM683.712 110.99733300000003L242.133333 110.99733300000003c-11.797333 0-21.354667-9.557333-21.354667-21.376 0-11.84 9.557333-21.354667 21.354667-21.354667l441.578667 0c11.84 0 21.376 9.514667 21.376 21.354667C705.088 101.44000000000005 695.552 110.99733300000003 683.712 110.99733300000003zM781.824 773.333333l-35.008 0c-12.906667 28.864-41.770667 49.088-75.370667 49.088l-66.922667 0C594.794667 864.490667 556.949333 896 512 896c-45.034667 0-82.816-31.509333-92.544-73.578667l-66.922667 0c-33.621333 0-62.485333-20.224-75.413333-49.088l-23.765333 0c-95.765333 0-179.776-78.762667-179.776-168.554667L73.578667 40.53333299999997c0-89.749333 84.010667-168.533333 179.776-168.533333l528.469333 0c92.906667 0 168.576 75.626667 168.554667 168.533333L950.378667 604.778667C950.4 697.7280000000001 874.773333 773.333333 781.824 773.333333zM352.533333 779.690667l85.888 0c11.776 0 21.354667 9.557333 21.354667 21.354667 0 28.778667 23.445333 52.224 52.224 52.224 28.8 0 52.202667-23.424 52.202667-52.224 0-11.797333 9.536-21.354667 21.333333-21.354667l85.909333 0c21.994667 0 39.957333-17.92 39.957333-39.978667 0-22.037333-17.962667-39.978667-39.957333-39.978667l-318.933333 0c-22.058667 0-39.978667 17.941333-39.978667 39.978667C312.554667 761.770667 330.517333 779.690667 352.533333 779.690667zM907.648 40.53333299999997c0-69.376-56.448-125.802667-125.802667-125.802667L253.354667-85.26933299999996c-73.002667 0-137.045333 58.794667-137.045333 125.802667L116.309333 604.778667c0 67.029333 64.042667 125.824 137.045333 125.824l17.386667 0c4.608-41.28 39.317333-73.6 81.770667-73.6l318.933333 0c42.453333 0 77.141333 32.32 81.749333 73.6l28.629333 0c69.376 0 125.802667-56.448 125.802667-125.824L907.626667 40.53333299999997z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="tamper-2" unicode="" d="M512 266.66666699999996a117.333333 117.333333 0 1 0 117.333333 117.333333 117.546667 117.546667 0 0 0-117.333333-117.333333z m0 213.333333a96 96 0 1 1 96-96 96 96 0 0 1-96 96zM512 106.66666699999996a277.333333 277.333333 0 1 0 277.333333 277.333333 277.333333 277.333333 0 0 0-277.333333-277.333333z m0 533.333333a256 256 0 1 1 256-256 256 256 0 0 1-256 256zM512-53.33333300000004A437.333333 437.333333 0 1 0 949.333333 384 437.76 437.76 0 0 0 512-53.33333300000004z m0 853.333333A416 416 0 1 1 928 384 416.426667 416.426667 0 0 1 512 800zM85.333333 394.666667h853.333334v-21.333334H85.333333zM501.333333 810.666667h21.333334v-853.333334h-21.333334zM293.76 548.48m-34.56 0a34.56 34.56 0 1 1 69.12 0 34.56 34.56 0 1 1-69.12 0ZM778.666667 384m-34.56 0a34.56 34.56 0 1 1 69.12 0 34.56 34.56 0 1 1-69.12 0Z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="tamper-3" unicode="" d="M867.584 735.808c-149.632 16.928-262.208 57.408-334.592 120.352l-19.04 16.544-20.544-14.656C379.968 777.056 267.776 736 160 736H128v-448c0-137.344 121.088-261.92 370.208-380.864l13.088-6.24 13.344 5.728C771.072 12.480000000000018 896 140.76800000000003 896 288V732.576l-28.416 3.232zM832 288c0-116.8-107.392-223.36-319.328-316.8C299.872 74.976 192 181.53599999999994 192 288V673.024c104.672 6.784 211.584 46.688 318.496 118.944C587.232 733.472 695.168 694.4639999999999 832 675.744V288zM359.776 427.328a32 32 0 1 1-47.968-42.4l121.792-137.824c12.608-14.24 30.176-21.568 47.904-21.568a64.384 64.384 0 0 1 49.696 23.52l197.6 242.72a32 32 0 0 1-49.632 40.416l-197.6-242.688-121.792 137.824z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="tamper-1" unicode="" d="M499.2 128c-147.2 0-268.8 121.6-268.8 268.8 0 147.2 121.6 268.8 268.8 268.8 147.2 0 268.8-121.6 268.8-268.8 0-150.4-121.6-268.8-268.8-268.8z m0 486.4c-121.6 0-220.8-99.2-220.8-220.8s99.2-220.8 220.8-220.8 220.8 99.2 220.8 220.8-99.2 220.8-220.8 220.8zM800 70.39999999999998c-6.4 0-12.8 3.2-16 6.4l-105.6 105.6c-9.6 9.6-9.6 25.6 0 35.2 9.6 9.6 25.6 9.6 35.2 0l105.6-105.6c9.6-9.6 9.6-25.6 0-35.2-6.4-3.2-12.8-6.4-19.2-6.4z m-288 233.6h-102.4c-12.8 0-22.4 9.6-22.4 22.4 0 12.8 9.6 22.4 22.4 22.4H512c12.8 0 22.4-9.6 22.4-22.4 3.2-12.8-9.6-22.4-22.4-22.4z m73.6 134.4h-176c-12.8 0-22.4 9.6-22.4 22.4 0 12.8 9.6 22.4 22.4 22.4h176c12.8 0 22.4-9.6 22.4-22.4 3.2-9.6-6.4-22.4-22.4-22.4zM512 896C230.4 896 0 665.6 0 384s230.4-512 512-512c67.2 0 134.4 12.8 195.2 38.4 6.4 3.2 16 6.4 22.4 9.6 6.4 3.2 12.8 9.6 16 16 3.2 6.4 3.2 16 0 22.4-6.4 16-25.6 19.2-38.4 12.8l-19.2-9.6c-54.4-22.4-112-35.2-172.8-35.2C262.4-70.39999999999998 57.6 134.39999999999998 57.6 384S262.4 838.4 512 838.4 966.4 633.6 966.4 384c0-48-6.4-99.2-22.4-144-6.4-16-9.6-28.8-16-44.8-3.2-6.4-3.2-16 0-22.4 3.2-6.4 9.6-12.8 16-16 6.4-3.2 16-3.2 22.4 0 6.4 3.2 12.8 9.6 16 16 6.4 16 12.8 32 19.2 51.2 19.2 51.2 25.6 108.8 25.6 163.2C1024 665.6 793.6 896 512 896z" horiz-adv-x="1027" />
|
||||
|
||||
<glyph glyph-name="tongji" unicode="" d="M157.538462 29.538462h787.692307v-78.769231H78.769231V817.230769h78.769231v-787.692307z m78.76923 374.153846h78.769231v-315.076923h-78.769231V403.692308z m177.23077 118.153846h78.76923v-433.230769h-78.76923V521.846154z m177.230769-118.153846h78.769231v-315.076923h-78.769231V403.692308z m177.230769 157.538461h78.769231v-472.615384h-78.769231V561.230769z m-470.468923-13.075692l-43.697231 65.536L452.923077 746.417231l173.784615-115.849846 154.505846 137.334153 52.322462-58.88-199.936-177.723076L452.923077 651.736615l-155.392-103.581538z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="webdav" unicode="" d="M512 846.451613c255.405419 0 462.451613-207.046194 462.451613-462.451613S767.405419-78.45161299999995 512-78.45161299999995 49.548387 128.59458099999995 49.548387 384 256.594581 846.451613 512 846.451613z m0-66.064516C293.07871 780.387097 115.612903 602.92129 115.612903 384s177.465806-396.387097 396.387097-396.387097 396.387097 177.465806 396.387097 396.387097S730.92129 780.387097 512 780.387097zM332.122839 565.677419a33.032258 33.032258 0 0 0 32.090838-25.236645l54.618839-224.916645 57.575226 225.296516A33.032258 33.032258 0 0 0 508.416 565.677419h17.061161a33.032258 33.032258 0 0 0 32.008258-24.856774l57.575226-225.296516 54.618839 224.916645A33.032258 33.032258 0 0 0 701.786839 565.677419h12.684387a29.217032 29.217032 0 0 0 28.110451-37.194322l-85.80129-302.146065A33.032258 33.032258 0 0 0 625.003355 202.322581h-19.059613a33.032258 33.032258 0 0 0-32.008258 24.87329L517.169548 450.064516 459.974194 227.14632300000005A33.032258 33.032258 0 0 0 427.982452 202.322581h-19.555097a33.032258 33.032258 0 0 0-31.777032 24.047484l-85.371871 302.113032A29.233548 29.233548 0 0 0 319.438452 565.677419h12.684387z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="xiangqing" unicode="" d="M512 654.27010918m-77.34417915 0a77.34417915 77.34417915 0 1 1 154.6883583 0 77.34417915 77.34417915 0 1 1-154.6883583 0ZM512 384m-77.34417915 0a77.34417915 77.34417915 0 1 1 154.6883583 0 77.34417915 77.34417915 0 1 1-154.6883583 0ZM512 113.72989082000004m-77.34417915 0a77.34417915 77.34417915 0 1 1 154.6883583 0 77.34417915 77.34417915 0 1 1-154.6883583 0Z" horiz-adv-x="1024" />
|
||||
|
||||
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 90 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user