Compare commits

...
27 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
54 changed files with 469 additions and 176 deletions
+5
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>
------------------------------
@@ -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.
+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
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"`
+9 -8
View File
@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"os"
"path"
"strings"
"github.com/1Panel-dev/1Panel/backend/app/dto"
@@ -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
}
+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"
+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")
}
}
}
+9
View File
@@ -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 {
+1 -1
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
+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
}
+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
@@ -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
@@ -49,6 +49,7 @@ export namespace Backup {
detailName: string;
}
export interface Recover {
source: string;
type: string;
name: string;
detailName: string;
+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,
+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,
+7 -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',
@@ -540,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?',
@@ -576,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',
+6 -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: '当前数据库已经关联应用,修改密码将同步修改应用中数据库密码,修改后重启生效。',
@@ -558,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: '切换来源将清空当前已编辑内容,是否继续?',
@@ -590,7 +591,8 @@ const message = {
dockerStatus: 'Docker 服务',
daemonJsonPathHelper: '请保证配置路径与 docker.service 中指定的配置路径保持一致。',
mirrors: '镜像加速',
mirrorsHelper: '将 Docker 镜像库的请求重定向到指定的镜像加速器,从而提高镜像的下载速度',
mirrorsHelper: '优先使用加速 URL 执行操作,设置为空则取消镜像加速。',
mirrorsHelper2: '具体操作配置请参照官方文档,',
registries: '私有仓库',
liveHelper: '允许在 Docker 守护进程发生意外停机或崩溃时保留正在运行的容器状态',
liveWithSwarmHelper: 'live-restore 守护进程配置与 Swarm 模式不兼容',
+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 {
@@ -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';
},
},
{
@@ -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>
@@ -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.imageTag')" :resource="form.itemName" :back="handleClose" />
</template>
@@ -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,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="title + $t('container.repo')"
+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,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,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;
});
});
@@ -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;
+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) {
@@ -6,6 +6,7 @@
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">
@@ -214,8 +215,8 @@ onBeforeUnmount(() => {
defineExpose({ acceptParams });
</script>
<style lang="scss">
.coder-editor {
margin-top: 10px;
<style>
.dialog-top {
top: 0;
}
</style>
@@ -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">
@@ -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>
@@ -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;
+1 -1
View File
@@ -93,7 +93,7 @@ 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
+2
View File
@@ -201,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=