Compare commits

...
50 Commits
Author SHA1 Message Date
zhengkunwang223 53756c382d feat: 取消网站 ipv6 的默认设置 (#1099) 2023-05-22 11:44:49 +08:00
zhengkunwang223 8533a71670 fix: 解决首页控制台报错的问题 (#1087) 2023-05-21 22:16:53 +08:00
zhengkunwang223 6b3c06a057 fix: 解决伪静态页面光标丢失的问题 (#1086) 2023-05-21 22:16:50 +08:00
zhengkunwang223 4fd87568cd fix: 解决搜索子目录模糊查询失败的问题 (#1085)
Refs https://github.com/1Panel-dev/1Panel/issues/1049
2023-05-21 22:16:44 +08:00
zhengkunwang223 56f8caf561 fix: 解决打开编辑文件页面确认按钮可能看不到的问题 (#1084)
Refs https://github.com/1Panel-dev/1Panel/issues/1042
2023-05-21 22:16:40 +08:00
zhengkunwang223 7d2f7a8d3b fix: 解决反向代理 1Panel 并启用 auth_basic 的时候无法登录的问题 (#1083)
Refs https://github.com/1Panel-dev/1Panel/issues/1082
2023-05-21 22:16:36 +08:00
xin.yang 01a9589be9 修复首页推荐应用处在窄窗口时显示异常的问题 2023-05-21 22:15:45 +08:00
zhengkunwang223 72eb02fd39 feat: 升级 distribution 版本到 v2.8.2 (#1067) 2023-05-21 22:15:16 +08:00
ssongliu c1332235a0 fix: 右侧抽屉宽度调整 (#1047) 2023-05-15 02:36:47 +00:00
ssongliu 212c8634ea fix: 容器配置界面样式调整 (#1045) 2023-05-15 02:22:47 +00:00
zhengkunwang223 b966ab3e11 fix: 解决创建数据库超时问题 (#1037) 2023-05-14 01:34:31 +00:00
zhengkunwang223 25c2246782 fix: 解决默认网站开启 https 443 端口没有设置 default_server 的问题 (#1034) 2023-05-14 01:04:31 +00:00
ssongliu 2ae1db4730 fix: 解决 ssl 启用和端口修改跳转问题 (#1030) 2023-05-13 12:20:30 +00:00
ssongliu 43652b2a54 fix: 解决数据库上传备份恢复失败的问题 (#1027) 2023-05-13 07:32:28 +00:00
ssongliu 574a504ec3 fix: 增加初始化逻辑 (#1026) 2023-05-13 04:20:29 +00:00
zhengkunwang223 52a8331c78 fix: 解决网站设置 https 情况下,设置默认网站失败的问题 (#1023) 2023-05-12 15:08:28 +00:00
ssongliu afa9eecf35 fix: 补全 swagger 文档 (#1022) 2023-05-12 22:30:50 +08:00
ssongliu 46e13d754f fix: 解决计划任务未勾选同步到本地造成的备份恢复问题 (#1021) 2023-05-12 22:30:26 +08:00
zhengkunwang223 0157326d61 fix: 限制应用失败情况下启动应用 (#1020) 2023-05-12 22:30:02 +08:00
ssongliu 7d08875f95 fix: 解决数据库用户指定多个 ip 无效的问题 (#1019) 2023-05-12 17:48:31 +08:00
zhengkunwang223 bd2a49e299 fix: 解决网站设置切换到 HTTPS 控制台报错的问题 (#1016)
fix https://github.com/1Panel-dev/1Panel/issues/672
2023-05-12 07:08:23 +00:00
ssongliu 06f1d03b93 fix: 端口校验正则表达式修改 (#1009) 2023-05-12 03:36:23 +00:00
Mystery0 M 4c39955f2f fix: 获取网站日志时,先检查一下日志文件大小,超过10M时直接报错 (#1011)
#### What this PR does / why we need it?

修复网站日志文件较大时,在界面上查看日志会导致系统短时间卡住的问题

相关Issue https://github.com/1Panel-dev/1Panel/issues/495
该提交可优化这个Issue的问题

#### Summary of your change

在获取文件内容之前,通过os.Stat获取文件的信息,并对文件大小进行判断,如果过大(目前是>10MB),则抛出错误中止流程

#### Please indicate you've done the following:

- [ ] Made sure tests are passing and test coverage is added if needed.
- [x] Made sure commit message follow the rule of [Conventional Commits specification](https://www.conventionalcommits.org/).
- [ ] Considered the docs impact and opened a new docs issue or PR with docs changes if needed.
2023-05-12 02:54:23 +00:00
maninhill 56f92310f8 Update README.md (#1005) 2023-05-11 23:27:01 +08:00
maninhill cb47806fd6 Update README.md 2023-05-11 21:28:57 +08:00
maninhill 16ae193e9f Update README.md 2023-05-11 15:33:17 +08:00
fossabot 8770939328 Add license scan report and status
Signed off by: fossabot <badges@fossa.com>
2023-05-11 15:33:17 +08:00
ssongliu d5bff6473e fix: 解决安全入口跳转失败的问题 (#995) 2023-05-10 15:28:18 +00:00
ssongliu a1c0408aae fix: 解决安全入口情况下升级后页面无法打开的问题 (#994) 2023-05-10 15:16:48 +00:00
ssongliu ab523b6879 fix: 解决密码过期后重定向到登录页的问题 (#990) 2023-05-10 09:12:18 +00:00
zhengkunwang223 740b4c52d2 fix: 修复已安装页面 php 应用丢失的问题 (#989) 2023-05-10 08:52:16 +00:00
ssongliu dbb94942df fix: 镜像导出增加默认值 (#988) 2023-05-10 08:16:15 +00:00
zhengkunwang223 1e4ea2f8c3 feat: 文件操作增加名称显示 (#985)
resolve  https://github.com/1Panel-dev/1Panel/issues/975
2023-05-10 07:02:15 +00:00
ssongliu 8083837333 fix: 容器监控适配部分单核系统 (#984) 2023-05-10 06:48:15 +00:00
ssongliu dd89933613 fix: ntp 依赖修改 (#983) 2023-05-10 06:36:15 +00:00
ssongliu 5101dace59 fix: 优化抽屉中操作对象的名称显示 (#982) 2023-05-10 06:34:19 +00:00
zhengkunwang223 81c56a740c feat: 限制 PHP 应用升级 (#981) 2023-05-10 06:32:23 +00:00
zhengkunwang223 27cc3bcccd fix: 解决运行环境版本与已安装应用版本不一致的问题 (#980)
Closes https://github.com/1Panel-dev/1Panel/issues/978
2023-05-10 06:20:16 +00:00
ssongliu 8ddaa26a57 fix: 解决本地备份账号更新失败的问题 (#977)
Closes #966
2023-05-10 06:08:14 +00:00
ssongliu 3a848428c3 fix: 忽略概览页异常数据 (#971) 2023-05-10 02:52:14 +00:00
ssongliu 4c18f3aa1d fix: 解决验证码加载失败的问题 (#970) 2023-05-10 02:50:18 +00:00
maninhill be6278c0b7 Update README.md 2023-05-09 23:50:17 +08:00
maninhill d5e08d5db2 Update README.md 2023-05-09 23:49:24 +08:00
zhengkunwang223 2d321b4a79 feat: app.yaml 增加 username 和 password 参数 (#960) 2023-05-09 09:31:44 +00:00
zhengkunwang223 fcd764d521 feat: 应用商店同步改为异步操作 (#956) 2023-05-09 07:47:43 +00:00
ssongliu 7d4a8782d8 fix: 解决登录情况下,输入任意路由跳转到安全入口的问题 (#954) 2023-05-09 07:45:47 +00:00
zhengkunwang223 eea28e8481 feat: 升级badger版本到v4 (#951) 2023-05-09 07:23:43 +00:00
FoXiMao 71d679d426 Fix maccms rewrite configuration file error (#948)
修复maccms rewrite 配置文件错误导致登陆时提示ERR_TOO_MANY_REDIRECTS 重定向次数过多的问题

#### What this PR does / why we need it?

#### Summary of your change

#### Please indicate you've done the following:

- [x] Made sure tests are passing and test coverage is added if needed.
- [x] Made sure commit message follow the rule of [Conventional Commits specification](https://www.conventionalcommits.org/).
- [ ] Considered the docs impact and opened a new docs issue or PR with docs changes if needed.
2023-05-09 07:21:47 +00:00
zhengkunwang223 2b23523bec fix: 修复文件列表总共条数显示问题 (#952) 2023-05-09 07:17:47 +00:00
wangdan-fit2cloud 149c26728c fix: 夜间模式ui优化(https://github.com/1Panel-dev/1Panel/issues/938) (#953)
#### What this PR does / why we need it?

#### Summary of your change

#### Please indicate you've done the following:

- [ ] Made sure tests are passing and test coverage is added if needed.
- [ ] Made sure commit message follow the rule of [Conventional Commits specification](https://www.conventionalcommits.org/).
- [ ] Considered the docs impact and opened a new docs issue or PR with docs changes if needed.
2023-05-09 07:15:46 +00:00
92 changed files with 717 additions and 344 deletions
+8 -3
View File
@@ -6,6 +6,7 @@
<a href="https://app.codacy.com/gh/1Panel-dev/1Panel?utm_source=github.com&utm_medium=referral&utm_content=1Panel-dev/1Panel&utm_campaign=Badge_Grade_Dashboard"><img src="https://app.codacy.com/project/badge/Grade/da67574fd82b473992781d1386b937ef" alt="Codacy"></a>
<a href="https://github.com/1Panel-dev/1Panel/releases"><img src="https://img.shields.io/github/v/release/1Panel-dev/1Panel" alt="GitHub release"></a>
<a href="https://github.com/1Panel-dev/1Panel"><img src="https://img.shields.io/github/stars/1Panel-dev/1Panel?color=%231890FF&style=flat-square" alt="Stars"></a>
<a href="https://app.fossa.com/projects/git%2Bgithub.com%2F1Panel-dev%2F1Panel?ref=badge_shield"><img src="https://app.fossa.com/api/projects/git%2Bgithub.com%2F1Panel-dev%2F1Panel.svg?type=shield" alt="FOSSA Status"></a>
</p>
------------------------------
@@ -13,9 +14,9 @@
1Panel 是一个现代化、开源的 Linux 服务器运维管理面板。1Panel 的功能和优势包括:
- **快速建站**:深度集成 Wordpress 和 [Halo](https://github.com/halo-dev/halo/),域名绑定、SSL 证书配置等一键搞定;
- **高效管理**:通过 Web 端轻松管理 Linux 服务器,包括应用管理、主机监控、文件管理、数据库管理、容器管理等;
- **安全可靠**:最小漏洞暴露面,提供防火墙和安全审计等功能;
- **一键备份**:支持一键备份和恢复,备份数据云端存储,永不丢失。
- **高效管理**:通过 Web 端轻松管理 Linux 服务器,包括主机监控、文件管理、数据库管理、容器管理等;
- **安全可靠**:基于容器来管理和部署应用,最小漏洞暴露面,提供防火墙和日志审计等功能;
- **一键备份**:支持一键备份和恢复,备份数据到各类云端存储,永不丢失。
## UI 展示
@@ -58,6 +59,10 @@ curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_
[![Star History Chart](https://api.star-history.com/svg?repos=1Panel-dev/1Panel&type=Date)](https://star-history.com/#1Panel-dev/1Panel&Date)
## FOSSA Status
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2F1Panel-dev%2F1Panel.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2F1Panel-dev%2F1Panel?ref=badge_large)
## License
Copyright (c) 2014-2023 [FIT2CLOUD 飞致云](https://fit2cloud.com/), All rights reserved.
+9 -8
View File
@@ -38,14 +38,15 @@ func (b *BaseApi) SearchApp(c *gin.Context) {
// @Router /apps/sync [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"应用商店同步","formatEN":"App store synchronization"}
func (b *BaseApi) SyncApp(c *gin.Context) {
appService.SyncAppListFromLocal()
global.LOG.Infof("sync app list start ...")
if err := appService.SyncAppListFromRemote(); err != nil {
global.LOG.Errorf("sync app list error [%s]", err.Error())
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
global.LOG.Infof("sync app list success!")
go appService.SyncAppListFromLocal()
go func() {
global.LOG.Infof("sync app list start ...")
if err := appService.SyncAppListFromRemote(); err != nil {
global.LOG.Errorf("sync app list error [%s]", err.Error())
} else {
global.LOG.Infof("sync app list success!")
}
}()
helper.SuccessWithData(c, "")
}
+10
View File
@@ -2,6 +2,8 @@ package v1
import (
"encoding/base64"
"fmt"
"path"
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
@@ -356,6 +358,14 @@ func (b *BaseApi) Recover(c *gin.Context) {
return
}
if req.Source != "LOCAL" {
downloadPath, err := backupService.DownloadRecord(dto.DownloadRecord{Source: req.Source, FileDir: path.Dir(req.File), FileName: path.Base(req.File)})
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, fmt.Errorf("download file failed, err: %v", err))
return
}
req.File = downloadPath
}
switch req.Type {
case "mysql":
if err := backupService.MysqlRecover(req); err != nil {
+2 -2
View File
@@ -138,7 +138,7 @@ func (b *BaseApi) OperateIPRule(c *gin.Context) {
// @Param request body dto.BatchRuleOperate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /hosts/firewall/ip [post]
// @Router /hosts/firewall/batch [post]
func (b *BaseApi) BatchOperateRule(c *gin.Context) {
var req dto.BatchRuleOperate
if err := c.ShouldBindJSON(&req); err != nil {
@@ -188,7 +188,7 @@ func (b *BaseApi) UpdatePortRule(c *gin.Context) {
// @Param request body dto.AddrRuleUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /hosts/firewall/update/ip [post]
// @Router /hosts/firewall/update/addr [post]
func (b *BaseApi) UpdateAddrRule(c *gin.Context) {
var req dto.AddrRuleUpdate
if err := c.ShouldBindJSON(&req); err != nil {
+1 -1
View File
@@ -196,7 +196,7 @@ func (b *BaseApi) HandlePasswordExpired(c *gin.Context) {
// @Router /settings/time/sync [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"系统时间同步","formatEN":"sync system time"}
func (b *BaseApi) SyncTime(c *gin.Context) {
ntime, err := ntp.Getremotetime()
ntime, err := ntp.GetRemoteTime()
if err != nil {
helper.SuccessWithData(c, time.Now().Format("2006-01-02 15:04:05 MST -0700"))
return
+1
View File
@@ -36,6 +36,7 @@ type CommonBackup struct {
DetailName string `json:"detailName"`
}
type CommonRecover struct {
Source string `json:"source" validate:"required,oneof=OSS S3 SFTP MINIO LOCAL COS KODO"`
Type string `json:"type" validate:"required,oneof=app mysql redis website"`
Name string `json:"name"`
DetailName string `json:"detailName"`
+3
View File
@@ -570,6 +570,9 @@ func getAppFromRepo(downloadPath, version string) error {
func handleInstalled(appInstallList []model.AppInstall, updated bool) ([]response.AppInstalledDTO, error) {
var res []response.AppInstalledDTO
for _, installed := range appInstallList {
if updated && installed.App.Type == "php" {
continue
}
installDTO := response.AppInstalledDTO{
AppInstall: installed,
}
+37 -21
View File
@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"os"
"path"
"strings"
"github.com/1Panel-dev/1Panel/backend/app/dto"
@@ -13,7 +14,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/cloud_storage"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
fileUtils "github.com/1Panel-dev/1Panel/backend/utils/files"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
)
@@ -109,15 +110,15 @@ func (u *BackupService) DownloadRecord(info dto.DownloadRecord) (string, error)
if err != nil {
return "", fmt.Errorf("new cloud storage client failed, err: %v", err)
}
tempPath := fmt.Sprintf("%sdownload%s", constant.DataDir, info.FileDir)
if _, err := os.Stat(tempPath); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(tempPath, os.ModePerm); err != nil {
global.LOG.Errorf("mkdir %s failed, err: %v", tempPath, err)
targetPath := fmt.Sprintf("%s/download/%s/%s", constant.DataDir, info.FileDir, info.FileName)
if _, err := os.Stat(path.Dir(targetPath)); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(path.Dir(targetPath), os.ModePerm); err != nil {
global.LOG.Errorf("mkdir %s failed, err: %v", path.Dir(targetPath), err)
}
}
targetPath := tempPath + info.FileName
if _, err = os.Stat(targetPath); err != nil && os.IsNotExist(err) {
isOK, err := backClient.Download(info.FileName, targetPath)
srcPath := fmt.Sprintf("%s/%s", info.FileDir, info.FileName)
if exist, _ := backClient.Exist(srcPath); exist {
isOK, err := backClient.Download(srcPath, targetPath)
if !isOK {
return "", fmt.Errorf("cloud storage download failed, err: %v", err)
}
@@ -179,7 +180,7 @@ func (u *BackupService) BatchDeleteRecord(ids []uint) error {
global.LOG.Errorf("remove file %s failed, err: %v", record.FileDir+record.FileName, err)
}
} else {
backupAccount, err := backupRepo.Get(commonRepo.WithByName(record.Source))
backupAccount, err := backupRepo.Get(commonRepo.WithByType(record.Source))
if err != nil {
return err
}
@@ -223,7 +224,7 @@ func (u *BackupService) Update(req dto.BackupOperate) error {
if strings.HasSuffix(dirStr, "/") {
dirStr = dirStr[:strings.LastIndex(dirStr, "/")]
}
if err := updateBackupDir(dirStr, oldDir); err != nil {
if err := copyDir(oldDir, dirStr); err != nil {
_ = backupRepo.Update(req.ID, (map[string]interface{}{"vars": oldVars}))
return err
}
@@ -309,18 +310,33 @@ func loadLocalDir() (string, error) {
return "", fmt.Errorf("error type dir: %T", varMap["dir"])
}
func updateBackupDir(dir, oldDir string) error {
if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(dir, os.ModePerm); err != nil {
return err
func copyDir(src, dst string) error {
srcInfo, err := os.Stat(src)
if err != nil {
return err
}
if err = os.MkdirAll(dst, srcInfo.Mode()); err != nil {
return err
}
files, err := os.ReadDir(src)
if err != nil {
return err
}
fileOP := fileUtils.NewFileOp()
for _, file := range files {
srcPath := fmt.Sprintf("%s/%s", src, file.Name())
dstPath := fmt.Sprintf("%s/%s", dst, file.Name())
if file.IsDir() {
if err = copyDir(srcPath, dstPath); err != nil {
global.LOG.Errorf("copy dir %s to %s failed, err: %v", srcPath, dstPath, err)
}
} else {
if err := fileOP.CopyFile(srcPath, dst); err != nil {
global.LOG.Errorf("copy file %s to %s failed, err: %v", srcPath, dstPath, err)
}
}
}
if strings.HasSuffix(oldDir, "/") {
oldDir = oldDir[:strings.LastIndex(oldDir, "/")]
}
stdout, err := cmd.Execf("cp -r %s/* %s", oldDir, dir)
if err != nil {
return errors.New(string(stdout))
}
return nil
}
+4 -1
View File
@@ -326,7 +326,10 @@ func calculateCPUPercentUnix(stats *types.StatsJSON) float64 {
systemDelta := float64(stats.CPUStats.SystemUsage) - float64(stats.PreCPUStats.SystemUsage)
if systemDelta > 0.0 && cpuDelta > 0.0 {
cpuPercent = (cpuDelta / systemDelta) * float64(len(stats.CPUStats.CPUUsage.PercpuUsage)) * 100.0
cpuPercent = (cpuDelta / systemDelta) * 100.0
if len(stats.CPUStats.CPUUsage.PercpuUsage) != 0 {
cpuPercent = cpuPercent * float64(len(stats.CPUStats.CPUUsage.PercpuUsage))
}
}
return cpuPercent
}
+69 -30
View File
@@ -14,6 +14,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/app/repo"
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
@@ -99,22 +100,7 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode
}
return nil, err
}
tmpPermission := req.Permission
if err := excSQL(app.ContainerName, app.Password, fmt.Sprintf("create user '%s'@'%s' identified by '%s';", req.Username, tmpPermission, req.Password)); err != nil {
_ = excSQL(app.ContainerName, app.Password, fmt.Sprintf("drop database `%s`", req.Name))
if strings.Contains(err.Error(), "ERROR 1396") {
return nil, buserr.New(constant.ErrUserIsExist)
}
return nil, err
}
grantStr := fmt.Sprintf("grant all privileges on `%s`.* to '%s'@'%s'", req.Name, req.Username, tmpPermission)
if req.Name == "*" {
grantStr = fmt.Sprintf("grant all privileges on *.* to '%s'@'%s'", mysql.Username, tmpPermission)
}
if app.Version == "5.7.39" {
grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, req.Password)
}
if err := excSQL(app.ContainerName, app.Password, grantStr); err != nil {
if err := u.createUser(app, req); err != nil {
return nil, err
}
@@ -271,6 +257,9 @@ func (u *MysqlService) ChangeAccess(info dto.ChangeDBInfo) error {
if err != nil {
return err
}
if info.Value == mysql.Permission {
return nil
}
}
app, err := appInstallRepo.LoadBaseInfo("mysql", "")
if err != nil {
@@ -284,24 +273,30 @@ func (u *MysqlService) ChangeAccess(info dto.ChangeDBInfo) error {
}
if info.Value != mysql.Permission {
if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("drop user if exists '%s'@'%s'", mysql.Username, mysql.Permission)); err != nil {
return err
var userlist []string
if strings.Contains(mysql.Permission, ",") {
userlist = strings.Split(mysql.Permission, ",")
} else {
userlist = append(userlist, mysql.Permission)
}
for _, user := range userlist {
if len(user) != 0 {
if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("drop user if exists '%s'@'%s'", mysql.Username, user)); err != nil {
return err
}
}
}
if info.ID == 0 {
return nil
}
}
if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("create user if not exists '%s'@'%s' identified by '%s';", mysql.Username, info.Value, mysql.Password)); err != nil {
return err
}
grantStr := fmt.Sprintf("grant all privileges on `%s`.* to '%s'@'%s'", mysql.Name, mysql.Username, info.Value)
if mysql.Name == "*" {
grantStr = fmt.Sprintf("grant all privileges on *.* to '%s'@'%s'", mysql.Username, info.Value)
}
if app.Version == "5.7.39" {
grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, mysql.Password)
}
if err := excuteSql(app.ContainerName, app.Password, grantStr); err != nil {
if err := u.createUser(app, dto.MysqlDBCreate{
Username: mysql.Username,
Name: mysql.Name,
Permission: info.Value,
Password: mysql.Password,
}); err != nil {
return err
}
if err := excuteSql(app.ContainerName, app.Password, "flush privileges"); err != nil {
@@ -475,6 +470,50 @@ func (u *MysqlService) LoadStatus() (*dto.MysqlStatus, error) {
return &info, nil
}
func (u *MysqlService) createUser(app *repo.RootInfo, req dto.MysqlDBCreate) error {
var userlist []string
if strings.Contains(req.Permission, ",") {
ips := strings.Split(req.Permission, ",")
for _, ip := range ips {
if len(ip) != 0 {
userlist = append(userlist, fmt.Sprintf("'%s'@'%s'", req.Username, ip))
}
}
} else {
userlist = append(userlist, fmt.Sprintf("'%s'@'%s'", req.Username, req.Permission))
}
for _, user := range userlist {
if err := excSQL(app.ContainerName, app.Password, fmt.Sprintf("create user %s identified by '%s';", user, req.Password)); err != nil {
handleCreateError(req.Name, userlist, app)
if strings.Contains(err.Error(), "ERROR 1396") {
return buserr.New(constant.ErrUserIsExist)
}
return err
}
grantStr := fmt.Sprintf("grant all privileges on `%s`.* to %s", req.Name, user)
if req.Name == "*" {
grantStr = fmt.Sprintf("grant all privileges on *.* to %s", user)
}
if app.Version == "5.7.39" {
grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, req.Password)
}
if err := excSQL(app.ContainerName, app.Password, grantStr); err != nil {
handleCreateError(req.Name, userlist, app)
return err
}
}
return nil
}
func handleCreateError(dbName string, userlist []string, app *repo.RootInfo) {
_ = excSQL(app.ContainerName, app.Password, fmt.Sprintf("drop database `%s`", dbName))
for _, user := range userlist {
if err := excSQL(app.ContainerName, app.Password, fmt.Sprintf("drop user if exists %s", user)); err != nil {
global.LOG.Errorf("drop user failed, err: %v", err)
}
}
}
func excuteSqlForMaps(containerName, password, command string) (map[string]string, error) {
cmd := exec.Command("docker", "exec", containerName, "mysql", "-uroot", "-p"+password, "-e", command)
stdout, err := cmd.CombinedOutput()
@@ -515,7 +554,7 @@ func excuteSql(containerName, password, command string) error {
}
func excSQL(containerName, password, command string) error {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, "docker", "exec", containerName, "mysql", "-uroot", "-p"+password, "-e", command)
stdout, err := cmd.CombinedOutput()
+49 -3
View File
@@ -854,7 +854,16 @@ func (w WebsiteService) OpWebsiteLog(req request.WebsiteLogReq) (*response.Websi
return res, nil
}
}
content, err := os.ReadFile(path.Join(sitePath, "log", req.LogType))
filePath := path.Join(sitePath, "log", req.LogType)
fileInfo, err := os.Stat(filePath)
if err != nil {
return nil, err
}
if fileInfo.Size() > 10<<20 {
return nil, buserr.New(constant.ErrFileToLarge)
}
fileInfo.Size()
content, err := os.ReadFile(filePath)
if err != nil {
return nil, err
}
@@ -903,7 +912,23 @@ func (w WebsiteService) OpWebsiteLog(req request.WebsiteLogReq) (*response.Websi
func (w WebsiteService) ChangeDefaultServer(id uint) error {
defaultWebsite, _ := websiteRepo.GetFirst(websiteRepo.WithDefaultServer())
if defaultWebsite.ID > 0 {
if err := updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "listen", Params: []string{"80"}}}, &defaultWebsite); err != nil {
params, err := getNginxParamsByKeys(constant.NginxScopeServer, []string{"listen"}, &defaultWebsite)
if err != nil {
return err
}
var changeParams []dto.NginxParam
for _, param := range params {
paramLen := len(param.Params)
var newParam []string
if paramLen > 1 && param.Params[paramLen-1] == components.DefaultServer {
newParam = param.Params[:paramLen-1]
}
changeParams = append(changeParams, dto.NginxParam{
Name: param.Name,
Params: newParam,
})
}
if err := updateNginxConfig(constant.NginxScopeServer, changeParams, &defaultWebsite); err != nil {
return err
}
defaultWebsite.DefaultServer = false
@@ -916,7 +941,28 @@ func (w WebsiteService) ChangeDefaultServer(id uint) error {
if err != nil {
return err
}
if err := updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "listen", Params: []string{"80", "default_server"}}}, &website); err != nil {
params, err := getNginxParamsByKeys(constant.NginxScopeServer, []string{"listen"}, &website)
if err != nil {
return err
}
var changeParams []dto.NginxParam
for _, param := range params {
paramLen := len(param.Params)
bind := param.Params[0]
var newParam []string
if bind == "80" || bind == "443" || bind == "[::]:80" || bind == "[::]:443" {
if param.Params[paramLen-1] == components.DefaultServer {
newParam = param.Params
} else {
newParam = append(param.Params, components.DefaultServer)
}
}
changeParams = append(changeParams, dto.NginxParam{
Name: param.Name,
Params: newParam,
})
}
if err := updateNginxConfig(constant.NginxScopeServer, changeParams, &website); err != nil {
return err
}
website.DefaultServer = true
+1 -4
View File
@@ -371,8 +371,7 @@ func applySSL(website model.Website, websiteSSL model.WebsiteSSL, req request.We
}
config := nginxFull.SiteConfig.Config
server := config.FindServers()[0]
server.UpdateListen("443", false, "ssl")
server.UpdateListen("[::]:443", false, "ssl")
server.UpdateListen("443", website.DefaultServer, "ssl")
switch req.HttpConfig {
case constant.HTTPSOnly:
@@ -381,11 +380,9 @@ func applySSL(website model.Website, websiteSSL model.WebsiteSSL, req request.We
server.RemoveDirective("if", []string{"($scheme"})
case constant.HTTPToHTTPS:
server.UpdateListen("80", website.DefaultServer)
server.UpdateListen("[::]:80", false)
server.AddHTTP2HTTPS()
case constant.HTTPAlso:
server.UpdateListen("80", website.DefaultServer)
server.UpdateListen("[::]:80", false)
server.RemoveDirective("if", []string{"($scheme"})
}
+19 -18
View File
@@ -1,22 +1,23 @@
package configs
type System struct {
Port string `mapstructure:"port"`
SSL string `mapstructure:"ssl"`
DbFile string `mapstructure:"db_file"`
DbPath string `mapstructure:"db_path"`
LogPath string `mapstructure:"log_path"`
DataDir string `mapstructure:"data_dir"`
TmpDir string `mapstructure:"tmp_dir"`
Cache string `mapstructure:"cache"`
Backup string `mapstructure:"backup"`
EncryptKey string `mapstructure:"encrypt_key"`
BaseDir string `mapstructure:"base_dir"`
Mode string `mapstructure:"mode"`
RepoUrl string `mapstructure:"repo_url"`
Version string `mapstructure:"version"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
Entrance string `mapstructure:"entrance"`
IsDemo bool `mapstructure:"is_demo"`
Port string `mapstructure:"port"`
SSL string `mapstructure:"ssl"`
DbFile string `mapstructure:"db_file"`
DbPath string `mapstructure:"db_path"`
LogPath string `mapstructure:"log_path"`
DataDir string `mapstructure:"data_dir"`
TmpDir string `mapstructure:"tmp_dir"`
Cache string `mapstructure:"cache"`
Backup string `mapstructure:"backup"`
EncryptKey string `mapstructure:"encrypt_key"`
BaseDir string `mapstructure:"base_dir"`
Mode string `mapstructure:"mode"`
RepoUrl string `mapstructure:"repo_url"`
Version string `mapstructure:"version"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
Entrance string `mapstructure:"entrance"`
IsDemo bool `mapstructure:"is_demo"`
ChangeUserInfo bool `mapstructure:"change_user_info"`
}
+1 -1
View File
@@ -5,7 +5,7 @@ const (
SessionName = "psession"
AuthMethodJWT = "jwt"
JWTHeaderName = "Authorization"
JWTHeaderName = "PanelAuthorization"
JWTBufferTime = 3600
JWTIssuer = "1Panel"
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"fmt"
"time"
"github.com/dgraph-io/badger/v3"
"github.com/dgraph-io/badger/v4"
"github.com/pkg/errors"
)
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/init/cache/badger_db"
"github.com/dgraph-io/badger/v3"
"github.com/dgraph-io/badger/v4"
)
func Init() {
+23 -1
View File
@@ -3,6 +3,9 @@ package hook
import (
"github.com/1Panel-dev/1Panel/backend/app/repo"
"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/encrypt"
)
func Init() {
@@ -27,6 +30,25 @@ func Init() {
_ = settingRepo.Create("SystemStatus", "Free")
}
if err := settingRepo.Update("SystemStatus", "Free"); err != nil {
global.LOG.Fatalf("init service before start failed, err: %v", "Free")
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)
}
if cmd.HasNoPasswordSudo() {
_, _ = cmd.Exec("sudo sed -i '/CHANGE_USER_INFO=true/d' /usr/local/bin/1pctl")
} else {
_, _ = cmd.Exec("sed -i '/CHANGE_USER_INFO=true/d' /usr/local/bin/1pctl")
}
}
}
+12 -3
View File
@@ -75,13 +75,13 @@ func Init() {
version = serverConfig.System.Version
}
if serverConfig.System.Username != "" {
version = serverConfig.System.Username
username = serverConfig.System.Username
}
if serverConfig.System.Password != "" {
version = serverConfig.System.Password
password = serverConfig.System.Password
}
if serverConfig.System.Entrance != "" {
version = serverConfig.System.Entrance
entrance = serverConfig.System.Entrance
}
}
@@ -99,6 +99,7 @@ func Init() {
global.CONF.System.Username = username
global.CONF.System.Password = password
global.CONF.System.Entrance = entrance
global.CONF.System.ChangeUserInfo = loadChange()
global.Viper = v
}
@@ -113,3 +114,11 @@ func loadParams(param string) string {
}
return info
}
func loadChange() bool {
stdout, err := cmd.Exec("grep '^CHANGE_USER_INFO=' /usr/bin/1pctl | cut -d'=' -f2")
if err != nil {
return false
}
return stdout == "true\n"
}
+4 -3
View File
@@ -67,10 +67,11 @@ func (cos cosClient) Exist(path string) (bool, error) {
if err != nil {
return false, err
}
if _, err := client.Object.IsExist(context.Background(), path); err != nil {
return true, err
exist, err := client.Object.IsExist(context.Background(), path)
if err != nil {
return false, err
}
return false, nil
return exist, nil
}
func (cos cosClient) Delete(path string) (bool, error) {
+2 -2
View File
@@ -59,9 +59,9 @@ func (kodo kodoClient) Exist(path string) (bool, error) {
return false, err
}
if _, err := kodo.client.Stat(bucket, path); err != nil {
return true, err
return false, err
}
return false, nil
return true, nil
}
func (kodo kodoClient) Delete(path string) (bool, error) {
+2 -2
View File
@@ -81,9 +81,9 @@ func (minIo minIoClient) Exist(path string) (bool, error) {
if _, ok := minIo.Vars["bucket"]; ok {
_, err := minIo.client.GetObject(context.Background(), minIo.Vars["bucket"].(string), path, minio.GetObjectOptions{})
if err != nil {
return true, err
return false, err
}
return false, nil
return true, nil
} else {
return false, constant.ErrInvalidParams
}
@@ -1,40 +0,0 @@
package client
import (
"encoding/json"
"fmt"
"testing"
"github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/init/db"
"github.com/1Panel-dev/1Panel/backend/init/log"
"github.com/1Panel-dev/1Panel/backend/init/viper"
)
func TestMinio(t *testing.T) {
viper.Init()
log.Init()
db.Init()
var backup model.BackupAccount
if err := global.DB.Where("id = ?", 3).First(&backup).Error; err != nil {
fmt.Println(err)
}
varMap := make(map[string]interface{})
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil {
fmt.Println(err)
}
varMap["type"] = backup.Type
varMap["bucket"] = backup.Bucket
switch backup.Type {
case constant.Sftp:
varMap["password"] = backup.Credential
case constant.OSS, constant.S3, constant.MinIo:
varMap["secretKey"] = backup.Credential
}
client, _ := NewMinIoClient(varMap)
_, _ = client.ListObjects("directory/directory-test-minio/")
}
+10
View File
@@ -83,6 +83,16 @@ func RandStr(n int) string {
return string(b)
}
func RandStrAndNum(n int) string {
mathRand.Seed(time.Now().UnixNano())
const charset = "abcdefghijklmnopqrstuvwxyz0123456789"
b := make([]byte, 10)
for i := range b {
b[i] = charset[mathRand.Int63()%int64(len(charset))]
}
return (string(b))
}
func ScanPort(port int) bool {
ln, err := net.Listen("tcp", ":"+strconv.Itoa(port))
if err != nil {
+4 -5
View File
@@ -99,7 +99,7 @@ func NewFileInfo(op FileOption) (*FileInfo, error) {
}
func (f *FileInfo) search(search string, count int) (files []FileSearchInfo, total int, err error) {
cmd := exec.Command("find", f.Path, "-name", search)
cmd := exec.Command("find", f.Path, "-name", fmt.Sprintf("*%s*", search))
output, err := cmd.StdoutPipe()
if err != nil {
return
@@ -113,7 +113,6 @@ func (f *FileInfo) search(search string, count int) (files []FileSearchInfo, tot
scanner := bufio.NewScanner(output)
for scanner.Scan() {
line := scanner.Text()
fmt.Println(line)
info, err := os.Stat(line)
if err != nil {
continue
@@ -159,8 +158,6 @@ func (f *FileInfo) listChildren(dir, showHidden, containSub bool, search string,
}
}
f.ItemTotal = 0
var items []*FileInfo
for _, df := range files {
if dir && !df.IsDir() {
@@ -222,7 +219,9 @@ func (f *FileInfo) listChildren(dir, showHidden, containSub bool, search string,
}
items = append(items, file)
}
f.ItemTotal = total
if containSub {
f.ItemTotal = total
}
start := (page - 1) * pageSize
end := pageSize + start
var result []*FileInfo
+17 -7
View File
@@ -65,7 +65,19 @@ func (s *Server) FindDirectives(directiveName string) []IDirective {
directives = append(directives, directive.GetBlock().FindDirectives(directiveName)...)
}
}
if directiveName == "listen" {
for _, listen := range s.Listens {
params := []string{listen.Bind}
params = append(params, listen.Parameters...)
if listen.DefaultServer != "" {
params = append(params, DefaultServer)
}
directives = append(directives, &Directive{
Name: "listen",
Parameters: params,
})
}
}
return directives
}
@@ -75,14 +87,12 @@ func (s *Server) UpdateDirective(key string, params []string) {
}
if key == "listen" {
defaultServer := false
if len(params) > 1 && params[1] == "default_server" {
paramLen := len(params)
if paramLen > 0 && params[paramLen-1] == "default_server" {
params = params[:paramLen-1]
defaultServer = true
}
if len(params) > 2 {
s.UpdateListen(params[0], defaultServer, params[2:]...)
} else {
s.UpdateListen(params[0], defaultServer)
}
s.UpdateListen(params[0], defaultServer, params[1:]...)
return
}
@@ -52,8 +52,8 @@ func (sl *ServerListen) GetBlock() IBlock {
func (sl *ServerListen) GetParameters() []string {
params := []string{sl.Bind}
params = append(params, sl.DefaultServer)
params = append(params, sl.Parameters...)
params = append(params, sl.DefaultServer)
return params
}
+4 -4
View File
@@ -7,7 +7,7 @@ import (
"runtime"
"time"
"github.com/gogf/gf/os/gproc"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
)
const ntpEpochOffset = 2208988800
@@ -30,7 +30,7 @@ type packet struct {
TxTimeFrac uint32
}
func Getremotetime() (time.Time, error) {
func GetRemoteTime() (time.Time, error) {
conn, err := net.Dial("udp", "pool.ntp.org:123")
if err != nil {
return time.Time{}, fmt.Errorf("failed to connect: %v", err)
@@ -62,10 +62,10 @@ func Getremotetime() (time.Time, error) {
func UpdateSystemDate(dateTime string) error {
system := runtime.GOOS
if system == "linux" {
if _, err := gproc.ShellExec(`date -s "` + dateTime + `"`); err != nil {
if _, err := cmd.Execf(`date -s "` + dateTime + `"`); err != nil {
return fmt.Errorf("update system date failed, err: %v", err)
}
return nil
}
return fmt.Errorf("The current system architecture does not support synchronization")
return fmt.Errorf("the current system architecture %v does not support synchronization", system)
}
+2
View File
@@ -5,6 +5,8 @@ system:
repo_url: https://resource.fit2cloud.com/1panel/package
is_demo: false
port: 9999
username: admin
password: admin123
log:
level: debug
+45 -2
View File
@@ -5377,7 +5377,7 @@ var doc = `{
}
}
},
"/hosts/firewall/ip": {
"/hosts/firewall/batch": {
"post": {
"security": [
{
@@ -5410,6 +5410,49 @@ var doc = `{
}
}
},
"/hosts/firewall/ip": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "创建防火墙 IP 规则",
"consumes": [
"application/json"
],
"tags": [
"Firewall"
],
"summary": "Create group",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.AddrRuleOperate"
}
}
],
"responses": {
"200": {
"description": ""
}
},
"x-panel-log": {
"BeforeFuntions": [],
"bodyKeys": [
"strategy",
"address"
],
"formatEN": "create address rules [strategy][address]",
"formatZH": "添加 ip 规则 [strategy] [address]",
"paramKeys": []
}
}
},
"/hosts/firewall/operate": {
"post": {
"security": [
@@ -5534,7 +5577,7 @@ var doc = `{
}
}
},
"/hosts/firewall/update/ip": {
"/hosts/firewall/update/addr": {
"post": {
"security": [
{
+45 -2
View File
@@ -5363,7 +5363,7 @@
}
}
},
"/hosts/firewall/ip": {
"/hosts/firewall/batch": {
"post": {
"security": [
{
@@ -5396,6 +5396,49 @@
}
}
},
"/hosts/firewall/ip": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "创建防火墙 IP 规则",
"consumes": [
"application/json"
],
"tags": [
"Firewall"
],
"summary": "Create group",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.AddrRuleOperate"
}
}
],
"responses": {
"200": {
"description": ""
}
},
"x-panel-log": {
"BeforeFuntions": [],
"bodyKeys": [
"strategy",
"address"
],
"formatEN": "create address rules [strategy][address]",
"formatZH": "添加 ip 规则 [strategy] [address]",
"paramKeys": []
}
}
},
"/hosts/firewall/operate": {
"post": {
"security": [
@@ -5520,7 +5563,7 @@
}
}
},
"/hosts/firewall/update/ip": {
"/hosts/firewall/update/addr": {
"post": {
"security": [
{
+30 -2
View File
@@ -6461,7 +6461,7 @@ paths:
summary: Load firewall base info
tags:
- Firewall
/hosts/firewall/ip:
/hosts/firewall/batch:
post:
consumes:
- application/json
@@ -6481,6 +6481,34 @@ paths:
summary: Create group
tags:
- Firewall
/hosts/firewall/ip:
post:
consumes:
- application/json
description: 创建防火墙 IP 规则
parameters:
- description: request
in: body
name: request
required: true
schema:
$ref: '#/definitions/dto.AddrRuleOperate'
responses:
"200":
description: ""
security:
- ApiKeyAuth: []
summary: Create group
tags:
- Firewall
x-panel-log:
BeforeFuntions: []
bodyKeys:
- strategy
- address
formatEN: create address rules [strategy][address]
formatZH: 添加 ip 规则 [strategy] [address]
paramKeys: []
/hosts/firewall/operate:
post:
consumes:
@@ -6560,7 +6588,7 @@ paths:
summary: Page firewall rules
tags:
- Firewall
/hosts/firewall/update/ip:
/hosts/firewall/update/addr:
post:
consumes:
- application/json
+13 -5
View File
@@ -1,5 +1,13 @@
rewrite ^/vod-(.*)$ /index.php?m=vod-$1 break;
rewrite ^/art-(.*)$ /index.php?m=art-$1 break;
rewrite ^/gbook-(.*)$ /index.php?m=gbook-$1 break;
rewrite ^/label-(.*)$ /index.php?m=label-$1 break;
rewrite ^/map-(.*)$ /index.php?m=map-$1 break;
if (!-e $request_filename) {
rewrite ^/index.php(.*)$ /index.php?s=$1 break;
# MacCMS要求强制修改后台文件名称 所以需要手动修改下方这条重写规则 将admin修改为你修改后的文件名即可
rewrite ^/admin.php(.*)$ /admin.php?s=$1 break;
rewrite ^/api.php(.*)$ /api.php?s=$1 break;
rewrite ^/(.*)$ /index.php?s=$1 break;
rewrite ^/vod-(.*)$ /index.php?m=vod-$1 break;
rewrite ^/art-(.*)$ /index.php?m=art-$1 break;
rewrite ^/gbook-(.*)$ /index.php?m=gbook-$1 break;
rewrite ^/label-(.*)$ /index.php?m=label-$1 break;
rewrite ^/map-(.*)$ /index.php?m=map-$1 break;
}
try_files $uri $uri/ /index.php?$query_string;
@@ -1,7 +1,5 @@
server {
listen 80;
listen [::]:80;
server_name ko.wp-1.com;
index index.php index.html index.htm default.php default.htm default.html;
+1
View File
@@ -13,6 +13,7 @@ export const checkStatus = (status: number, msg: string): void => {
MsgError(msg ? msg : i18n.global.t('commons.res.notFound'));
break;
case 403:
globalStore.setLogStatus(false);
router.replace({ name: 'entrance', params: { code: globalStore.entrance } });
MsgError(msg ? msg : i18n.global.t('commons.res.forbidden'));
break;
+1
View File
@@ -42,6 +42,7 @@ class RequestHttp {
globalStore.setCsrfToken(response.headers['x-csrf-token']);
}
if (data.code == ResultEnum.OVERDUE || data.code == ResultEnum.FORBIDDEN) {
globalStore.setLogStatus(false);
router.push({
name: 'entrance',
params: { code: globalStore.entrance },
+1
View File
@@ -49,6 +49,7 @@ export namespace Backup {
detailName: string;
}
export interface Recover {
source: string;
type: string;
name: string;
detailName: string;
+1
View File
@@ -55,6 +55,7 @@ export namespace File {
isSymlink?: boolean;
linkPath?: boolean;
sub?: boolean;
name?: string;
}
export interface FileDelete {
+1
View File
@@ -124,6 +124,7 @@ const onBackup = async () => {
const onRecover = async (row: Backup.RecordInfo) => {
let params = {
source: row.source,
type: type.value,
name: name.value,
detailName: detailName.value,
@@ -53,7 +53,11 @@
{{ upgradeInfo.latestVersion }} {{ $t('setting.latestVersion') }}
</el-radio>
</el-radio-group>
<MdEditor v-model="upgradeInfo.releaseNote" previewOnly />
<MdEditor
v-model="upgradeInfo.releaseNote"
previewOnly
:theme="globalStore.$state.themeConfig.theme || 'light'"
/>
</div>
<template #footer>
<span class="dialog-footer">
+1
View File
@@ -149,6 +149,7 @@ const search = async () => {
const onRecover = async (row: File.File) => {
let params = {
source: 'LOCAL',
type: type.value,
name: name.value,
detailName: detailName.value,
+9 -4
View File
@@ -300,7 +300,7 @@ const message = {
loadBackup: 'Import',
setting: 'Settings',
remoteAccess: 'Remote access',
remoteHelper: 'One in a row, for example:\n172.16.10.111\n172.16.10.112',
remoteHelper: 'Multiple IP comma-delimited, example: 172.16.10.111, 172.16.10.112',
remoteConnHelper:
'Remote connection to mysql as user root may have security risks. Therefore, perform this operation with caution.',
changePassword: 'Password',
@@ -493,6 +493,7 @@ const message = {
imageBuild: 'Image build',
pathSelect: 'Path',
label: 'Label',
imageTag: 'Image Tag',
push: 'Push',
fileName: 'FileName',
export: 'Export',
@@ -539,8 +540,10 @@ const message = {
imageRepo: 'Image repo',
repoHelper: 'Does it include a mirror repository/organization/project?',
auth: 'Auth',
mirrorHelper: 'One in a row, for example:\nhttps://hub-mirror.c.163.com \nhttps://reg-mirror.qiniu.com',
registrieHelper: 'One in a row, for example:\n172.16.10.111:8081 \n172.16.10.112:8081',
mirrorHelper:
'If there are multiple mirrors, newlines must be displayed, for example:\nhttps://hub-mirror.c.163.com \nhttps://reg-mirror.qiniu.com',
registrieHelper:
'If multiple private repositories exist, newlines must be displayed, for example:\n172.16.10.111:8081 \n172.16.10.112:8081',
compose: 'Compose',
fromChangeHelper: 'Switching the source will clear the current edited content. Do you want to continue?',
@@ -575,7 +578,8 @@ const message = {
daemonJsonPathHelper: 'Ensure that the configuration path is the same as that specified in docker.service.',
mirrors: 'Registry mirrors',
mirrorsHelper:
'Redirecting requests for a Docker image repository to a specified image accelerator can improve the download speed of the image',
'The acceleration URL is preferred to perform operations. If this parameter is set to empty, mirror acceleration is disabled.',
mirrorsHelper2: 'For details, see the official documents, ',
registries: 'Insecure registries',
liveHelper:
'Allows the running container state to be preserved in case of unexpected shutdown or crash of the Docker daemon',
@@ -1045,6 +1049,7 @@ const message = {
updateHelper: 'Updating parameters may cause the application to fail to start, please operate with caution',
updateWarn: 'Update parameters need to rebuild the application, Do you want to continue? ',
busPort: 'Service Port',
syncStart: 'Start syncing! Please refresh the app store later',
},
website: {
website: 'Website',
+8 -4
View File
@@ -314,7 +314,7 @@ const message = {
loadBackup: '导入备份',
setting: '设置',
remoteAccess: '远程访问',
remoteHelper: '一行一个,例:\n172.16.10.111\n172.16.10.112',
remoteHelper: '多个 ip 以逗号分隔,例:172.16.10.111,172.16.10.112',
remoteConnHelper: 'root 帐号远程连接 mysql 有安全风险,开启需谨慎!',
changePassword: '改密',
changePasswordHelper: '当前数据库已经关联应用,修改密码将同步修改应用中数据库密码,修改后重启生效。',
@@ -518,6 +518,7 @@ const message = {
build: '构建镜像',
pathSelect: '路径选择',
label: '标签',
imageTag: '镜像标签',
push: '推送',
fileName: '文件名',
export: '导出',
@@ -557,8 +558,9 @@ const message = {
imageRepo: '镜像仓库',
repoHelper: '是否包含镜像仓库/组织/项目?',
auth: '认证',
mirrorHelper: '一行一个,例:\nhttps://hub-mirror.c.163.com \nhttps://reg-mirror.qiniu.com',
registrieHelper: '一行一个,例:\n172.16.10.111:8081 \n172.16.10.112:8081',
mirrorHelper:
'当存在多个加速器时,需要换行显示,例: \nhttp://xxxxxx.m.daocloud.io \nhttps://xxxxxx.mirror.aliyuncs.com',
registrieHelper: '当存在多个私有仓库时,需要换行显示,例:\n172.16.10.111:8081 \n172.16.10.112:8081',
compose: '编排',
fromChangeHelper: '切换来源将清空当前已编辑内容,是否继续?',
@@ -589,7 +591,8 @@ const message = {
dockerStatus: 'Docker 服务',
daemonJsonPathHelper: '请保证配置路径与 docker.service 中指定的配置路径保持一致。',
mirrors: '镜像加速',
mirrorsHelper: '将 Docker 镜像库的请求重定向到指定的镜像加速器,从而提高镜像的下载速度',
mirrorsHelper: '优先使用加速 URL 执行操作,设置为空则取消镜像加速。',
mirrorsHelper2: '具体操作配置请参照官方文档,',
registries: '私有仓库',
liveHelper: '允许在 Docker 守护进程发生意外停机或崩溃时保留正在运行的容器状态',
liveWithSwarmHelper: 'live-restore 守护进程配置与 Swarm 模式不兼容',
@@ -1048,6 +1051,7 @@ const message = {
updateHelper: '更新参数可能导致应用无法启动,请提前备份并谨慎操作',
updateWarn: '更新参数需要重建应用,是否继续?',
busPort: '服务端口',
syncStart: '开始同步!请稍后刷新应用商店',
},
website: {
website: '网站',
+17 -2
View File
@@ -11,10 +11,24 @@ const axiosCanceler = new AxiosCanceler();
router.beforeEach((to, from, next) => {
NProgress.start();
axiosCanceler.removeAllPending();
const globalStore = GlobalStore();
if (to.name === 'entrance' && globalStore.isLogin) {
if (to.params.code === globalStore.entrance) {
globalStore.setLogStatus(false);
next({
name: 'entrance',
params: { code: globalStore.entrance },
});
NProgress.done();
return;
}
next({ name: '404' });
NProgress.done();
return;
}
if (!to.matched.some((record) => record.meta.requiresAuth)) return next();
const globalStore = GlobalStore();
if (!globalStore.isLogin) {
next({
name: 'entrance',
@@ -23,6 +37,7 @@ router.beforeEach((to, from, next) => {
NProgress.done();
return;
}
return next();
});
+9
View File
@@ -26,6 +26,7 @@ html.dark {
--panel-popup-color: #060708;
--panel-alert-bg: #2f3030;
--panel-path-bg: #2f3030;
--panel-button-disabled: #5a5a5a;
.el-tag.el-tag--info {
--el-tag-bg-color: rgb(49, 51, 51);
@@ -79,6 +80,10 @@ html.dark {
--w-e-textarea-bg-color: #1b1b1b;
--w-e-textarea-color: #eeeeee;
.md-editor-dark {
--md-bk-color: #111417;
}
// * 以下为自定义暗黑模式内容
// login
.login-container {
@@ -202,8 +207,12 @@ html.dark {
background: #1d2023;
border-color: #303438;
}
.el-button.is-link.is-disabled {
color: var(--panel-button-disabled) !important;
}
.el-button.is-disabled {
border-color: #303438;
color: var(--panel-button-disabled);
}
.el-popper.is-dark {
color: rgb(171 173 173);
+1 -1
View File
@@ -171,7 +171,7 @@ export function checkPort(value: string): boolean {
if (Number(value) <= 0) {
return true;
}
const reg = /^([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])$/;
const reg = /^([1-9](\d{0,3}))$|^([1-5]\d{4})$|^(6[0-4]\d{3})$|^(65[0-4]\d{2})$|^(655[0-2]\d)$|^(6553[0-5])$/;
if (!reg.test(value) && value !== '') {
return true;
} else {
+1 -1
View File
@@ -147,7 +147,7 @@ const sync = () => {
loading.value = true;
SyncApp()
.then(() => {
MsgSuccess(i18n.global.t('app.syncSuccess'));
MsgSuccess(i18n.global.t('app.syncStart'));
canUpdate.value = false;
search(req);
})
@@ -83,7 +83,11 @@
</div>
</div>
<div v-loading="loadingDetail" style="margin-left: 10px">
<MdEditor v-model="appDetail.readme" previewOnly />
<MdEditor
v-model="appDetail.readme"
previewOnly
:theme="globalStore.$state.themeConfig.theme || 'light'"
/>
</div>
</template>
</LayoutContent>
@@ -98,6 +102,8 @@ import { onMounted, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import Install from './install/index.vue';
import router from '@/routers';
import { GlobalStore } from '@/store';
const globalStore = GlobalStore();
const language = useI18n().locale.value;
@@ -9,11 +9,15 @@
</template>
</Header>
</template>
<el-descriptions border :column="1" v-if="!edit">
<el-descriptions-item v-for="(param, key) in params" :label="getLabel(param)" :key="key">
<span>{{ param.showValue && param.showValue != '' ? param.showValue : param.value }}</span>
</el-descriptions-item>
</el-descriptions>
<el-row v-if="!edit">
<el-col :span="22" :offset="1">
<el-descriptions border :column="1">
<el-descriptions-item v-for="(param, key) in params" :label="getLabel(param)" :key="key">
<span>{{ param.showValue && param.showValue != '' ? param.showValue : param.value }}</span>
</el-descriptions-item>
</el-descriptions>
</el-col>
</el-row>
<el-row v-else v-loading="loading">
<el-col :span="22" :offset="1">
<el-alert :title="$t('app.updateHelper')" type="warning" :closable="false" />
@@ -347,7 +347,7 @@ const buttons = [
openOperate(row, 'start');
},
disabled: (row: any) => {
return row.status === 'Running';
return row.status === 'Running' || row.status === 'Error';
},
},
{
@@ -269,6 +269,7 @@ const onComposeOperate = async (operation: string) => {
name: composeName.value,
path: composePath.value,
operation: operation,
withFile: false,
};
loading.value = true;
await composeOperator(params)
@@ -288,13 +289,13 @@ const onComposeOperate = async (operation: string) => {
};
const dialogMonitorRef = ref();
const onMonitor = (containerID: string) => {
dialogMonitorRef.value!.acceptParams({ containerID: containerID });
const onMonitor = (row: any) => {
dialogMonitorRef.value!.acceptParams({ containerID: row.containerID, container: row.name });
};
const dialogTerminalRef = ref();
const onTerminal = (containerID: string) => {
dialogTerminalRef.value!.acceptParams({ containerID: containerID });
const onTerminal = (row: any) => {
dialogTerminalRef.value!.acceptParams({ containerID: row.containerID, container: row.name });
};
const dialogContainerLogRef = ref();
@@ -306,7 +307,7 @@ const buttons = [
return row.state !== 'running';
},
click: (row: Container.ContainerInfo) => {
onTerminal(row.containerID);
onTerminal(row);
},
},
{
@@ -315,13 +316,13 @@ const buttons = [
return row.state !== 'running';
},
click: (row: Container.ContainerInfo) => {
onMonitor(row.containerID);
onMonitor(row);
},
},
{
label: i18n.global.t('commons.button.log'),
click: (row: Container.ContainerInfo) => {
dialogContainerLogRef.value!.acceptParams({ containerID: row.containerID });
dialogContainerLogRef.value!.acceptParams({ containerID: row.containerID, container: row.name });
},
},
];
@@ -1,7 +1,7 @@
<template>
<el-drawer v-model="composeVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
<template #header>
<DrawerHeader :header="$t('commons.button.edit')" :back="handleClose" />
<DrawerHeader :header="$t('commons.button.edit')" :resource="name" :back="handleClose" />
</template>
<div v-loading="loading">
<codemirror
@@ -215,13 +215,13 @@ const onCreate = () => {
};
const dialogMonitorRef = ref();
const onMonitor = (containerID: string) => {
dialogMonitorRef.value!.acceptParams({ containerID: containerID });
const onMonitor = (row: any) => {
dialogMonitorRef.value!.acceptParams({ containerID: row.containerID, container: row.name });
};
const dialogTerminalRef = ref();
const onTerminal = (containerID: string) => {
dialogTerminalRef.value!.acceptParams({ containerID: containerID });
const onTerminal = (row: any) => {
dialogTerminalRef.value!.acceptParams({ containerID: row.containerID, container: row.name });
};
const onInspect = async (id: string) => {
@@ -312,7 +312,7 @@ const buttons = [
return row.state !== 'running';
},
click: (row: Container.ContainerInfo) => {
onTerminal(row.containerID);
onTerminal(row);
},
},
{
@@ -321,7 +321,7 @@ const buttons = [
return row.state !== 'running';
},
click: (row: Container.ContainerInfo) => {
onMonitor(row.containerID);
onMonitor(row);
},
},
{
@@ -2,7 +2,7 @@
<div>
<el-drawer v-model="logVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
<template #header>
<DrawerHeader :header="$t('commons.button.log')" :back="handleClose" />
<DrawerHeader :header="$t('commons.button.log')" :resource="logSearch.container" :back="handleClose" />
</template>
<div>
<el-select @change="searchLogs" style="width: 30%; float: left" v-model="logSearch.mode">
@@ -7,7 +7,7 @@
size="50%"
>
<template #header>
<DrawerHeader :header="$t('container.monitor')" :back="handleClose" />
<DrawerHeader :header="$t('container.monitor')" :resource="title" :back="handleClose" />
</template>
<el-form label-position="top" @submit.prevent>
<el-form-item :label="$t('container.refreshTime')">
@@ -68,20 +68,24 @@ import VCharts from '@/components/v-charts/index.vue';
import i18n from '@/lang';
import DrawerHeader from '@/components/drawer-header/index.vue';
const title = ref();
const monitorVisiable = ref(false);
const timeInterval = ref();
let timer: NodeJS.Timer | null = null;
let isInit = ref<boolean>(true);
interface DialogProps {
containerID: string;
container: string;
}
const dialogData = ref<DialogProps>({
containerID: '',
container: '',
});
const acceptParams = async (params: DialogProps): Promise<void> => {
monitorVisiable.value = true;
dialogData.value.containerID = params.containerID;
title.value = params.container;
cpuDatas.value = [];
memDatas.value = [];
cacheDatas.value = [];
@@ -1,7 +1,7 @@
<template>
<el-drawer v-model="newNameVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
<template #header>
<DrawerHeader :header="$t('container.rename')" :back="handleClose" />
<DrawerHeader :header="$t('container.rename')" :resource="renameForm.name" :back="handleClose" />
</template>
<el-form @submit.prevent ref="newNameRef" v-loading="loading" :model="renameForm" label-position="top">
<el-row type="flex" justify="center">
@@ -7,7 +7,7 @@
size="50%"
>
<template #header>
<DrawerHeader :header="$t('container.containerTerminal')" :back="handleClose" />
<DrawerHeader :header="$t('container.containerTerminal')" :resource="title" :back="handleClose" />
</template>
<el-form ref="formRef" :model="form" label-position="top">
<el-form-item :label="$t('container.user')" prop="user">
@@ -56,6 +56,7 @@ import { Rules } from '@/global/form-rules';
import Terminal from '@/components/terminal/index.vue';
import DrawerHeader from '@/components/drawer-header/index.vue';
const title = ref();
const terminalVisiable = ref(false);
const terminalOpen = ref(false);
const form = reactive({
@@ -64,16 +65,17 @@ const form = reactive({
user: '',
containerID: '',
});
type FormInstance = InstanceType<typeof ElForm>;
const formRef = ref<FormInstance>();
const formRef = ref();
const terminalRef = ref<InstanceType<typeof Terminal> | null>(null);
interface DialogProps {
containerID: string;
container: string;
}
const acceptParams = async (params: DialogProps): Promise<void> => {
terminalVisiable.value = true;
form.containerID = params.containerID;
title.value = params.container;
form.isCustom = false;
form.user = '';
form.command = '/bin/bash';
@@ -173,6 +173,7 @@ const buttons = [
label: i18n.global.t('container.tag'),
click: (row: Container.ImageInfo) => {
let params = {
itemName: row.tags.length !== 0 ? row.tags[0].split(':')[0] : '',
repos: repos.value,
sourceID: row.id,
};
@@ -1,5 +1,5 @@
<template>
<el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
<el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
<template #header>
<DrawerHeader :header="$t('container.exportImage')" :back="handleClose" />
</template>
@@ -79,8 +79,8 @@ const dialogData = ref<DialogProps>({
const acceptParams = async (params: DialogProps): Promise<void> => {
drawerVisiable.value = true;
form.tags = params.tags;
form.tagName = form.tags.length !== 0 ? form.tags[0] : '';
form.path = '';
form.tagName = '';
form.name = '';
dialogData.value.repos = params.repos;
};
@@ -1,7 +1,7 @@
<template>
<el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
<el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
<template #header>
<DrawerHeader :header="$t('container.image') + ' Tag'" :back="handleClose" />
<DrawerHeader :header="$t('container.imageTag')" :resource="form.itemName" :back="handleClose" />
</template>
<el-form v-loading="loading" label-position="top" ref="formRef" :model="form" label-width="80px">
<el-row type="flex" justify="center">
@@ -56,6 +56,7 @@ const loading = ref(false);
const drawerVisiable = ref(false);
const repos = ref();
const form = reactive({
itemName: '',
sourceID: '',
fromRepo: true,
repoID: 1,
@@ -63,6 +64,7 @@ const form = reactive({
});
interface DialogProps {
itemName: string;
repos: Array<Container.RepoOptions>;
sourceID: string;
}
@@ -70,6 +72,7 @@ interface DialogProps {
const acceptParams = async (params: DialogProps): Promise<void> => {
drawerVisiable.value = true;
form.repoID = 1;
form.itemName = params.itemName;
form.sourceID = params.sourceID;
form.targetName = '';
form.fromRepo = true;
@@ -1,5 +1,5 @@
<template>
<el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
<el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
<template #header>
<DrawerHeader :header="$t('container.createNetwork')" :back="handleClose" />
</template>
@@ -174,6 +174,9 @@ const onCheckConn = async (row: Container.RepoInfo) => {
const buttons = [
{
label: i18n.global.t('commons.button.sync'),
disabled: (row: Container.RepoInfo) => {
return row.downloadUrl === 'docker.io';
},
click: (row: Container.RepoInfo) => {
onCheckConn(row);
},
@@ -1,7 +1,11 @@
<template>
<el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
<el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
<template #header>
<DrawerHeader :header="title + $t('container.repo')" :back="handleClose" />
<DrawerHeader
:header="title + $t('container.repo')"
:resource="dialogData.rowData?.name"
:back="handleClose"
/>
</template>
<el-form
ref="formRef"
+16 -1
View File
@@ -44,7 +44,7 @@
<el-row style="margin-top: 20px" v-if="confShowType === 'base'">
<el-col :span="1"><br /></el-col>
<el-col :span="10">
<el-form :model="form" label-position="left" ref="formRef" label-width="120px">
<el-form :model="form" label-position="left" ref="formRef" label-width="150px">
<el-form-item :label="$t('container.mirrors')" prop="mirrors">
<el-input
type="textarea"
@@ -53,6 +53,17 @@
v-model="form.mirrors"
/>
<span class="input-help">{{ $t('container.mirrorsHelper') }}</span>
<span class="input-help">
{{ $t('container.mirrorsHelper2') }}
<el-link
style="font-size: 12px; margin-left: 5px"
icon="Position"
@click="toDoc()"
type="primary"
>
{{ $t('firewall.quickJump') }}
</el-link>
</span>
</el-form-item>
<el-form-item :label="$t('container.registries')" prop="registries">
<el-input
@@ -219,6 +230,10 @@ const onSaveFile = async () => {
confirmDialogRef.value!.acceptParams(params);
};
const toDoc = () => {
window.open('https://1panel.cn/docs/user_manual/containers/setting/', '_blank');
};
const onChangeIptables = () => {
if (!form.iptables) {
iptablesVisiable.value = true;
@@ -1,7 +1,11 @@
<template>
<el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
<template #header>
<DrawerHeader :header="title + $t('container.composeTemplate')" :back="handleClose" />
<DrawerHeader
:header="title + $t('container.composeTemplate')"
:resource="dialogData.rowData?.name"
:back="handleClose"
/>
</template>
<el-form
v-loading="loading"
@@ -1,5 +1,5 @@
<template>
<el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
<el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
<template #header>
<DrawerHeader :header="$t('container.createVolume')" :back="handleClose" />
</template>
+1 -1
View File
@@ -1,7 +1,7 @@
<template>
<el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
<template #header>
<DrawerHeader :header="$t('cronjob.cronTask')" :back="handleClose" />
<DrawerHeader :header="$t('cronjob.cronTask')" :resource="dialogData.rowData?.name" :back="handleClose" />
</template>
<el-form ref="formRef" label-position="top" :model="dialogData.rowData" :rules="rules">
<el-row type="flex" justify="center">
@@ -1,5 +1,5 @@
<template>
<el-drawer v-model="createVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
<el-drawer v-model="createVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
<template #header>
<DrawerHeader :header="$t('database.create')" :back="handleClose" />
</template>
@@ -37,7 +37,13 @@
</el-select>
</el-form-item>
<el-form-item v-if="form.permission === 'ip'" prop="permissionIPs">
<el-input clearable v-model="form.permissionIPs" />
<el-input
clearable
:autosize="{ minRows: 2, maxRows: 5 }"
type="textarea"
v-model="form.permissionIPs"
/>
<span class="input-help">{{ $t('database.remoteHelper') }}</span>
</el-form-item>
<el-form-item :label="$t('commons.table.description')" prop="description">
<el-input type="textarea" clearable v-model="form.description" />
@@ -131,6 +137,10 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
createVisiable.value = false;
})
.catch(() => {
if (form.permission != '%') {
form.permissionIPs = form.permission;
form.permission = 'ip';
}
loading.value = false;
});
});
@@ -315,6 +315,7 @@ const buttons = [
click: (row: Database.MysqlDBInfo) => {
let param = {
id: row.id,
mysqlName: row.name,
operation: 'password',
username: row.username,
password: row.password,
@@ -327,6 +328,7 @@ const buttons = [
click: (row: Database.MysqlDBInfo) => {
let param = {
id: row.id,
mysqlName: row.name,
operation: 'privilege',
privilege: '',
privilegeIPs: '',
@@ -2,7 +2,7 @@
<div>
<el-drawer v-model="changeVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="30%">
<template #header>
<DrawerHeader :header="title" :back="handleClose" />
<DrawerHeader :header="title" :resource="changeForm.mysqlName" :back="handleClose" />
</template>
<el-form>
<el-form v-loading="loading" ref="changeFormRef" :model="changeForm" label-position="top">
@@ -38,12 +38,12 @@
:rules="Rules.requiredInput"
>
<el-input
:placeholder="$t('database.remoteHelper')"
clearable
:autosize="{ minRows: 2, maxRows: 5 }"
type="textarea"
v-model="changeForm.privilegeIPs"
/>
<span class="input-help">{{ $t('database.remoteHelper') }}</span>
</el-form-item>
</div>
</el-col>
@@ -158,7 +158,7 @@ const submitChangeInfo = async (formEl: FormInstance | undefined) => {
if (changeForm.privilege !== 'ip') {
param.value = changeForm.privilege;
} else {
param.value = changeForm.privilegeIPs.replaceAll('/n', ',');
param.value = changeForm.privilegeIPs;
}
loading.value = true;
await updateMysqlAccess(param)
@@ -1,5 +1,5 @@
<template>
<el-drawer v-model="dialogVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="40%">
<el-drawer v-model="dialogVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
<template #header>
<DrawerHeader :header="$t('database.remoteAccess')" :back="handleClose" />
</template>
@@ -201,6 +201,7 @@ const onBackup = async () => {
};
const onRecover = async () => {
let param = {
source: currentRow.value.source,
type: 'redis',
name: '',
detailName: '',
+2
View File
@@ -87,8 +87,10 @@ defineExpose({
.h-app-card {
cursor: pointer;
padding: 10px 15px;
margin-right: 10px;
.h-app-content {
padding-left: 15px;
.h-app-title {
font-weight: 500;
font-size: 15px;
+18 -12
View File
@@ -368,31 +368,37 @@ const onLoadCurrentInfo = async () => {
const res = await loadCurrentInfo(searchInfo.ioOption, searchInfo.netOption);
currentInfo.value.timeSinceUptime = res.data.timeSinceUptime;
currentChartInfo.netBytesSent = Number(
((res.data.netBytesSent - currentInfo.value.netBytesSent) / 1024 / 3).toFixed(2),
);
currentChartInfo.netBytesSent =
res.data.netBytesSent - currentInfo.value.netBytesSent > 0
? Number(((res.data.netBytesSent - currentInfo.value.netBytesSent) / 1024 / 3).toFixed(2))
: 0;
netBytesSents.value.push(currentChartInfo.netBytesSent);
if (netBytesSents.value.length > 20) {
netBytesSents.value.splice(0, 1);
}
currentChartInfo.netBytesRecv = Number(
((res.data.netBytesRecv - currentInfo.value.netBytesRecv) / 1024 / 3).toFixed(2),
);
currentChartInfo.netBytesRecv =
res.data.netBytesRecv - currentInfo.value.netBytesRecv > 0
? Number(((res.data.netBytesRecv - currentInfo.value.netBytesRecv) / 1024 / 3).toFixed(2))
: 0;
netBytesRecvs.value.push(currentChartInfo.netBytesRecv);
if (netBytesRecvs.value.length > 20) {
netBytesRecvs.value.splice(0, 1);
}
currentChartInfo.ioReadBytes = Number(
((res.data.ioReadBytes - currentInfo.value.ioReadBytes) / 1024 / 1024 / 3).toFixed(2),
);
currentChartInfo.ioReadBytes =
res.data.ioReadBytes - currentInfo.value.ioReadBytes > 0
? Number(((res.data.ioReadBytes - currentInfo.value.ioReadBytes) / 1024 / 1024 / 3).toFixed(2))
: 0;
ioReadBytes.value.push(currentChartInfo.ioReadBytes);
if (ioReadBytes.value.length > 20) {
ioReadBytes.value.splice(0, 1);
}
currentChartInfo.ioWriteBytes = Number(
((res.data.ioWriteBytes - currentInfo.value.ioWriteBytes) / 1024 / 1024 / 3).toFixed(2),
);
currentChartInfo.ioWriteBytes =
res.data.ioWriteBytes - currentInfo.value.ioWriteBytes > 0
? Number(((res.data.ioWriteBytes - currentInfo.value.ioWriteBytes) / 1024 / 1024 / 3).toFixed(2))
: 0;
ioWriteBytes.value.push(currentChartInfo.ioWriteBytes);
if (ioWriteBytes.value.length > 20) {
ioWriteBytes.value.splice(0, 1);
+3 -1
View File
@@ -290,7 +290,9 @@ const freshChart = (chartName: string, Title: string, Data: number) => {
},
],
};
myChart.setOption(option, true);
nextTick(function () {
myChart.setOption(option, true);
});
};
function loadStatus(val: number) {
@@ -1,7 +1,7 @@
<template>
<el-drawer v-model="open" :before-close="handleClose" :close-on-click-modal="false" width="50%">
<template #header>
<DrawerHeader :header="$t('file.setRole')" :back="handleClose" />
<DrawerHeader :header="$t('file.setRole')" :resource="name" :back="handleClose" />
</template>
<el-row>
@@ -30,10 +30,11 @@ import i18n from '@/lang';
import FileRole from '@/components/file-role/index.vue';
import { MsgSuccess } from '@/utils/message';
let open = ref(false);
let form = ref<File.FileCreate>({ path: '', isDir: false, mode: 0o755 });
let loading = ref<Boolean>(false);
let mode = ref('0755');
const open = ref(false);
const form = ref<File.FileCreate>({ path: '', isDir: false, mode: 0o755 });
const loading = ref<Boolean>(false);
const mode = ref('0755');
const name = ref('');
const em = defineEmits(['close']);
const handleClose = () => {
@@ -47,6 +48,7 @@ const acceptParams = (create: File.FileCreate) => {
form.value.path = create.path;
form.value.isLink = false;
form.value.sub = false;
name.value = create.name;
mode.value = String(create.mode);
};
@@ -1,7 +1,7 @@
<template>
<el-drawer v-model="open" size="40%">
<template #header>
<DrawerHeader :header="$t('file.changeOwner')" :back="handleClose" />
<DrawerHeader :header="$t('file.changeOwner')" :resource="name" :back="handleClose" />
</template>
<el-row>
<el-col :span="22" :offset="1">
@@ -50,12 +50,14 @@ interface OwnerProps {
user: string;
group: string;
isDir: boolean;
name: string;
}
const fileForm = ref<FormInstance>();
const loading = ref(false);
const open = ref(false);
const isDir = ref(false);
const name = ref('');
const addForm = reactive({
path: '',
@@ -101,6 +103,7 @@ const acceptParams = (props: OwnerProps) => {
addForm.path = props.path;
addForm.group = props.group;
isDir.value = props.isDir;
name.value = props.name;
open.value = true;
};
@@ -1,11 +1,12 @@
<template>
<el-dialog
v-model="open"
:title="$t('commons.button.edit')"
:title="$t('commons.button.edit') + ' - ' + fileName"
:before-close="handleClose"
destroy-on-close
width="70%"
@opened="onOpen"
:top="'5vh'"
>
<el-form :inline="true" :model="config">
<el-form-item :label="$t('file.theme')">
@@ -24,8 +25,8 @@
</el-select>
</el-form-item>
</el-form>
<div class="coder-editor" v-loading="loading">
<div id="codeBox" style="height: 60vh"></div>
<div v-loading="loading">
<div id="codeBox" style="height: 55vh"></div>
</div>
<template #footer>
<span class="dialog-footer">
@@ -84,6 +85,7 @@ interface EditorConfig {
const open = ref(false);
const loading = ref(false);
const fileName = ref('');
const config = reactive<EditorConfig>({
theme: 'vs-dark',
@@ -193,6 +195,7 @@ const acceptParams = (props: EditProps) => {
form.value.content = props.content;
form.value.path = props.path;
config.language = props.language;
fileName.value = props.name;
// TODO Now,1panel only support liunux,so we can use LF.
// better,We should rely on the actual line feed character of the file returned from the background
config.eol = monaco.editor.EndOfLineSequence.LF;
@@ -212,8 +215,8 @@ onBeforeUnmount(() => {
defineExpose({ acceptParams });
</script>
<style lang="scss">
.coder-editor {
margin-top: 10px;
<style>
.dialog-top {
top: 0;
}
</style>
@@ -75,12 +75,12 @@ const rules = reactive<FormRules>({
});
const fileForm = ref<FormInstance>();
let loading = ref(false);
let form = ref<File.FileCompress>({ files: [], type: 'zip', dst: '', name: '', replace: false });
let options = ref<string[]>([]);
let open = ref(false);
let title = ref('');
let operate = ref('compress');
const loading = ref(false);
const form = ref<File.FileCompress>({ files: [], type: 'zip', dst: '', name: '', replace: false });
const options = ref<string[]>([]);
const open = ref(false);
const title = ref('');
const operate = ref('compress');
const em = defineEmits(['close']);
@@ -7,7 +7,7 @@
size="40%"
>
<template #header>
<DrawerHeader :header="$t('file.deCompress')" :back="handleClose" />
<DrawerHeader :header="$t('file.deCompress')" :resource="name" :back="handleClose" />
</template>
<el-row>
<el-col :span="22" :offset="1">
@@ -7,14 +7,14 @@
<el-col>
<el-descriptions :column="1" border>
<el-descriptions-item :label="$t('file.fileName')">{{ data.name }}</el-descriptions-item>
<!-- <el-descriptions-item :label="$t('file.type')">{{ data.type }}</el-descriptions-item> -->
<el-descriptions-item :label="$t('file.type')">{{ data.type }}</el-descriptions-item>
<el-descriptions-item :label="$t('file.path')">{{ data.path }}</el-descriptions-item>
<el-descriptions-item :label="$t('file.size')">
{{ computeSize(data.size) }}
</el-descriptions-item>
<el-descriptions-item :label="$t('file.role')">{{ data.mode }}</el-descriptions-item>
<!-- <el-descriptions-item :label="$t('file.user')">{{ data.user }}</el-descriptions-item>
<el-descriptions-item :label="$t('file.group')">{{ data.group }}</el-descriptions-item> -->
<el-descriptions-item :label="$t('file.user')">{{ data.user }}</el-descriptions-item>
<el-descriptions-item :label="$t('file.group')">{{ data.group }}</el-descriptions-item>
<el-descriptions-item :label="$t('commons.table.updatedAt')">
{{ dateFormatSimple(data.modTime) }}
</el-descriptions-item>
@@ -90,7 +90,7 @@
clearable
@clear="search()"
@keydown.enter="search()"
:placeholder="req.containSub ? $t('file.searchHelper') : $t('file.search')"
:placeholder="$t('file.search')"
>
<template #prepend>
<el-checkbox v-model="req.containSub">
@@ -178,7 +178,7 @@
<Download ref="downloadRef" @close="search" />
<Process :open="processPage.open" @close="closeProcess" />
<Owner ref="chownRef" @close="search"></Owner>
<!-- <Detail ref="detailRef" /> -->
<Detail ref="detailRef" />
</LayoutContent>
</div>
</template>
@@ -205,7 +205,7 @@ import Download from './download/index.vue';
import Owner from './chown/index.vue';
import { Mimetypes, Languages } from '@/global/mimetype';
import Process from './process/index.vue';
// import Detail from './detail/index.vue';
import Detail from './detail/index.vue';
import { useRouter } from 'vue-router';
import { Back, Refresh } from '@element-plus/icons-vue';
import { MsgSuccess, MsgWarning } from '@/utils/message';
@@ -252,7 +252,7 @@ const processPage = reactive({ open: false });
const createRef = ref();
const roleRef = ref();
// const detailRef = ref();
const detailRef = ref();
const compressRef = ref();
const deCompressRef = ref();
const codeEditorRef = ref();
@@ -603,9 +603,9 @@ const openDownload = () => {
}
};
// const openDetail = (row: File.File) => {
// detailRef.value.acceptParams({ path: row.path });
// };
const openDetail = (row: File.File) => {
detailRef.value.acceptParams({ path: row.path });
};
const buttons = [
{
@@ -641,10 +641,10 @@ const buttons = [
label: i18n.global.t('commons.button.delete'),
click: delFile,
},
// {
// label: i18n.global.t('file.info'),
// click: openDetail,
// },
{
label: i18n.global.t('file.info'),
click: openDetail,
},
];
onMounted(() => {
@@ -1,7 +1,7 @@
<template>
<el-drawer v-model="open" size="40%">
<template #header>
<DrawerHeader :header="$t('file.rename')" :back="handleClose" />
<DrawerHeader :header="$t('file.rename')" :resource="oldName" :back="handleClose" />
</template>
<el-row>
<el-col :span="22" :offset="1">
@@ -47,7 +47,7 @@ interface RenameProps {
const fileForm = ref<FormInstance>();
const loading = ref(false);
let open = ref(false);
const open = ref(false);
const oldName = ref('');
const addForm = reactive({
@@ -270,6 +270,7 @@ const checkIsSystemDemo = async () => {
};
onMounted(() => {
loginVerify();
document.title = globalStore.themeConfig.panelName;
loginForm.agreeLicense = globalStore.agreeLicense;
checkIsSystemDemo();
@@ -28,7 +28,7 @@
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item :label="$t('setting.mfaHelper1')">
<ul>
<ul class="help-ul">
<li>Google Authenticator</li>
<li>Microsoft Authenticator</li>
<li>1Password</li>
@@ -136,3 +136,8 @@ defineExpose({
acceptParams,
});
</script>
<style scoped>
.help-ul {
color: #8f959e;
}
</style>
@@ -31,6 +31,8 @@ import { MsgSuccess } from '@/utils/message';
import { updatePort } from '@/api/modules/setting';
import { ElMessageBox, FormInstance } from 'element-plus';
import { Rules } from '@/global/form-rules';
import { GlobalStore } from '@/store';
const globalStore = GlobalStore();
interface DialogProps {
serverPort: number;
@@ -66,9 +68,10 @@ const onSavePort = async (formEl: FormInstance | undefined) => {
.then(() => {
loading.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
globalStore.isLogin = false;
let href = window.location.href;
let ip = href.split('//')[1].split(':')[0];
window.open(`${href.split('//')[0]}//${ip}:${form.serverPort}/`, '_self');
window.open(`${href.split('//')[0]}//${ip}:${form.serverPort}/${globalStore.entrance}`, '_self');
})
.catch(() => {
loading.value = false;
@@ -5,7 +5,7 @@
:destroy-on-close="true"
@close="handleClose"
:close-on-click-modal="false"
size="50%"
size="30%"
>
<template #header>
<DrawerHeader header="https" :back="handleClose" />
@@ -112,6 +112,8 @@ import { DownloadByPath } from '@/api/modules/files';
import { Rules } from '@/global/form-rules';
import { ElMessageBox, FormInstance } from 'element-plus';
import { Setting } from '@/api/interface/setting';
import { GlobalStore } from '@/store';
const globalStore = GlobalStore();
const loading = ref();
const drawerVisiable = ref();
@@ -207,8 +209,10 @@ const onSaveSSL = async (formEl: FormInstance | undefined) => {
await updateSSL(param).then(() => {
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
let href = window.location.href;
globalStore.isLogin = false;
let address = href.split('://')[1];
window.open(`https://${address}/`, '_self');
address = address.replaceAll('settings/safe', globalStore.entrance);
window.open(`https://${address}`, '_self');
});
});
});
@@ -1,6 +1,6 @@
<template>
<div v-loading="loading">
<el-drawer v-model="drawerVisiable" size="50%">
<el-drawer v-model="drawerVisiable" size="30%">
<template #header>
<DrawerHeader :header="$t('setting.importSnapshot')" :back="handleClose" />
</template>
@@ -1,7 +1,7 @@
<template>
<el-drawer :close-on-click-modal="false" v-model="open" size="50%">
<template #header>
<DrawerHeader :header="$t('runtime.' + mode)" :back="handleClose" />
<DrawerHeader :header="$t('runtime.' + mode)" :resource="runtime.name" :back="handleClose" />
</template>
<el-row v-loading="loading">
<el-col :span="22" :offset="1">
@@ -48,7 +48,11 @@
</el-select>
</el-col>
<el-col :span="12">
<el-select v-model="runtime.version" :disabled="mode === 'edit'">
<el-select
v-model="runtime.version"
:disabled="mode === 'edit'"
@change="changeVersion()"
>
<el-option
v-for="(version, index) in appVersions"
:key="index"
@@ -207,6 +211,16 @@ const changeApp = (appId: number) => {
}
};
const changeVersion = () => {
initParam.value = false;
GetAppDetail(runtime.value.appId, runtime.value.version, 'runtime').then((res) => {
runtime.value.appDetailId = res.data.id;
runtime.value.image = res.data.image + ':' + runtime.value.version;
appParams.value = res.data.params;
initParam.value = true;
});
};
const getApp = (appkey: string, mode: string) => {
GetApp(appkey).then((res) => {
appVersions.value = res.data.versions || [];
@@ -184,7 +184,7 @@ const get = () => {
if (res.data.httpConfig != '') {
form.httpConfig = res.data.httpConfig;
}
if (res.data.SSLProtocol.length > 0) {
if (res.data.SSLProtocol && res.data.SSLProtocol.length > 0) {
form.SSLProtocol = res.data.SSLProtocol;
}
if (res.data.algorithm != '') {
@@ -1,5 +1,5 @@
<template>
<div v-loading="loading">
<div>
<el-form-item :label="$t('website.rewriteMode')">
<el-select v-model="req.name" filterable @change="getRewriteConfig(req.name)">
<el-option :label="$t('website.current')" :value="'current'"></el-option>
@@ -11,8 +11,9 @@
></el-option>
</el-select>
</el-form-item>
<codemirror
<Codemirror
ref="codeRef"
v-loading="loading"
:autofocus="true"
placeholder=""
:indent-with-tab="true"
@@ -37,7 +38,7 @@
</template>
<script lang="ts" setup>
import { computed, onMounted, reactive, ref } from 'vue';
import { computed, nextTick, onMounted, reactive, ref } from 'vue';
import { Codemirror } from 'vue-codemirror';
import { oneDark } from '@codemirror/theme-one-dark';
import { StreamLanguage } from '@codemirror/language';
@@ -48,8 +49,9 @@ import { MsgSuccess } from '@/utils/message';
import i18n from '@/lang';
const loading = ref(false);
const content = ref('');
const content = ref(' ');
const extensions = [StreamLanguage.define(nginx), oneDark];
const codeRef = ref();
const props = defineProps({
id: {
@@ -69,7 +71,7 @@ const req = reactive({
const update = reactive({
websiteID: id.value,
content: '',
content: 'd',
name: '',
});
@@ -80,12 +82,24 @@ const getRewriteConfig = async (rewrite: string) => {
try {
const res = await GetRewriteConfig(req);
content.value = res.data.content;
if (res.data.content == '') {
content.value = ' ';
}
setCursorPosition();
} catch (error) {
} finally {
loading.value = false;
}
};
const setCursorPosition = () => {
nextTick(() => {
const codeMirrorInstance = codeRef.value?.codemirror;
codeMirrorInstance?.setCursor(0, 0);
});
};
const submit = async () => {
update.name = req.name;
update.websiteID = id.value;
+2 -5
View File
@@ -7,7 +7,7 @@ require (
github.com/aws/aws-sdk-go v1.44.99
github.com/compose-spec/compose-go v1.13.2
github.com/creack/pty v1.1.18
github.com/dgraph-io/badger/v3 v3.2103.5
github.com/dgraph-io/badger/v4 v4.1.0
github.com/docker/cli v23.0.1+incompatible
github.com/docker/compose/v2 v2.17.2
github.com/docker/docker v23.0.3+incompatible
@@ -21,7 +21,6 @@ require (
github.com/go-gormigrate/gormigrate/v2 v2.0.2
github.com/go-playground/validator/v10 v10.11.2
github.com/go-sql-driver/mysql v1.6.0
github.com/gogf/gf v1.16.9
github.com/golang-jwt/jwt/v4 v4.4.2
github.com/google/uuid v1.3.0
github.com/gorilla/websocket v1.5.0
@@ -81,7 +80,6 @@ require (
github.com/buger/goterm v1.0.4 // indirect
github.com/bytedance/sonic v1.8.0 // indirect
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28 // indirect
@@ -95,14 +93,13 @@ require (
github.com/dgraph-io/ristretto v0.1.1 // indirect
github.com/distribution/distribution/v3 v3.0.0-20230223072852-e5d5810851d1 // indirect
github.com/docker/buildx v0.10.4 // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect
github.com/docker/go-metrics v0.0.1 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/felixge/httpsnoop v1.0.2 // indirect
github.com/fsnotify/fsevents v0.1.1 // indirect
github.com/fvbommel/sortorder v1.0.2 // indirect
+4 -45
View File
@@ -61,8 +61,6 @@ github.com/Microsoft/hcsshim v0.9.7 h1:mKNHW/Xvv1aFH87Jb6ERDzXTJTLPlmzfZ28VBFD/b
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
@@ -83,7 +81,6 @@ github.com/aliyun/aliyun-oss-go-sdk v2.2.5+incompatible/go.mod h1:T/Aws4fEfogEE9
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aws/aws-sdk-go v1.44.99 h1:ITZ9q/fmH+Ksaz2TbyMU2d19vOOWs/hAlt8NbXAieHw=
github.com/aws/aws-sdk-go v1.44.99/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
@@ -131,8 +128,6 @@ github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInq
github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -176,11 +171,7 @@ github.com/containerd/ttrpc v1.1.0 h1:GbtyLRxb0gOLR0TYQWt3O6B0NvT8tMdorEHqIQo/lW
github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ=
github.com/containerd/typeurl v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY=
github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -193,8 +184,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/denisenkom/go-mssqldb v0.12.0 h1:VtrkII767ttSPNRfFekePK3sctr+joXgO58stqQbtUA=
github.com/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0AKt0akg=
github.com/dgraph-io/badger/v3 v3.2103.5/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw=
github.com/dgraph-io/badger/v4 v4.1.0 h1:E38jc0f+RATYrycSUf9LMv/t47XAy+3CApyYSq4APOQ=
github.com/dgraph-io/badger/v4 v4.1.0/go.mod h1:P50u28d39ibBRmIJuQC/NSdBOg46HnHw7al2SW5QRHg=
github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8=
github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
@@ -210,6 +201,8 @@ github.com/docker/compose/v2 v2.17.2/go.mod h1:h5uld3t0RsL5h8rtkRaJtrFLJ3TJ9GOKd
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v23.0.3+incompatible h1:9GhVsShNWz1hO//9BNg/dpMnZW25KydO4wtVxWAIbho=
github.com/docker/docker v23.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
@@ -247,9 +240,7 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o=
github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
@@ -340,8 +331,6 @@ github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
github.com/gogf/gf v1.16.9 h1:Q803UmmRo59+Ws08sMVFOcd8oNpkSWL9vS33hlo/Cyk=
github.com/gogf/gf v1.16.9/go.mod h1:8Q/kw05nlVRp+4vv7XASBsMe9L1tsVKiGoeP2AHnlkk=
github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0=
github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4=
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@@ -389,11 +378,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v1.8.5 h1:nRAxCa+SVsyjSBrtZmG/cqb6VbTmuRzpg/PoTFlpumc=
github.com/gomodule/redigo v1.8.5/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
@@ -458,8 +444,6 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
@@ -547,7 +531,6 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:C
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM=
github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
@@ -580,7 +563,6 @@ github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTRe
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -588,8 +570,6 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@@ -598,7 +578,6 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
@@ -625,7 +604,6 @@ github.com/minio/minio-go/v7 v7.0.36 h1:KPzAl8C6jcRFEUsGUHR6deRivvKATPNZThzi7D9y
github.com/minio/minio-go/v7 v7.0.36/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw=
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
@@ -676,8 +654,6 @@ github.com/nrdcg/dnspod-go v0.4.0/go.mod h1:vZSoFSFeQVm2gWLMkyX61LZ8HI3BaqtHZWgP
github.com/nwaples/rardecode/v2 v2.0.0-beta.2 h1:e3mzJFJs4k83GXBEiTaQ5HgSc/kOK8q0rDaRO0MPaOk=
github.com/nwaples/rardecode/v2 v2.0.0-beta.2/go.mod h1:yntwv/HfMc/Hbvtq9I19D1n58te3h6KsqCf3GxyfBGY=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
@@ -707,7 +683,6 @@ github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
github.com/package-url/packageurl-go v0.1.1-0.20220428063043-89078438f170 h1:DiLBVp4DAcZlBVBEtJpNWZpZVq0AEeCY7Hqk8URVs4o=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
@@ -775,7 +750,6 @@ github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6po
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY=
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
@@ -798,33 +772,24 @@ github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spdx/tools-golang v0.3.1-0.20230104082527-d6f58551be3f h1:9B623Cfs+mclYK6dsae7gLSwuIBHvlgmEup87qpqsAQ=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=
github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU=
github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
@@ -878,7 +843,6 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU=
@@ -904,7 +868,6 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xlzd/gotp v0.0.0-20220817083547-a63b9d03d72f h1:C8De+7emQKojPBC+mXA0fr39XN5mKjRm9IUzdxI4whI=
github.com/xlzd/gotp v0.0.0-20220817083547-a63b9d03d72f/go.mod h1:ndLJ3JKzi3xLmUProq4LLxCuECL93dG9WASNLpHz8qg=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -930,7 +893,6 @@ go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.29.0/go.mod h1:vHItvsnJtp7ES++nFLLFBzUWny7fJQSvTlxFcqQGUr4=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0 h1:SLme4Porm+UwX0DdHMxlwRt7FzPSE0sys81bet2o0pU=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0/go.mod h1:tLYsuf2v8fZreBVwp9gVMhefZlLFZaUiNVSq8QxXRII=
go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
go.opentelemetry.io/otel v1.4.0/go.mod h1:jeAqMFKy2uLIxCtKxoFj0FAL5zAPKQagc3+GtBWakzk=
go.opentelemetry.io/otel v1.4.1/go.mod h1:StM6F/0fSwpd8dKWDCdRr7uRvEPYdW0hBSlbdTiUde4=
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
@@ -949,7 +911,6 @@ go.opentelemetry.io/otel/metric v0.27.0 h1:HhJPsGhJoKRSegPQILFbODU56NS/L1UE4fS1s
go.opentelemetry.io/otel/metric v0.27.0/go.mod h1:raXDJ7uP2/Jc0nVZWQjJtzoyssOYWu/+pjZqRzfvZ7g=
go.opentelemetry.io/otel/sdk v1.4.1 h1:J7EaW71E0v87qflB4cDolaqq3AcujGrtyIPGQoZOB0Y=
go.opentelemetry.io/otel/sdk v1.4.1/go.mod h1:NBwHDgDIBYjwK2WNu1OPgsIc2IJzmBXNnvIJxJc8BpE=
go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
go.opentelemetry.io/otel/trace v1.4.0/go.mod h1:uc3eRsqDfWs9R7b92xbQbU42/eTNz4N+gLP8qJCi4aE=
go.opentelemetry.io/otel/trace v1.4.1/go.mod h1:iYEVbroFCNut9QkwEczV9vMRPHNKSSwYZjulEtsmhFc=
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
@@ -965,7 +926,6 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -1054,7 +1014,6 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=