fix: 解决同名网站备份恢复异常 (#3370)

Refs https://github.com/1Panel-dev/1Panel/issues/3355
This commit is contained in:
zhengkunwang 2023-12-18 17:54:15 +08:00 committed by GitHub
parent 9aaa387b23
commit 78f2b6f72d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 52 additions and 42 deletions

View file

@ -19,6 +19,7 @@ type IBackupRepo interface {
Update(id uint, vars map[string]interface{}) error Update(id uint, vars map[string]interface{}) error
Delete(opts ...DBOption) error Delete(opts ...DBOption) error
DeleteRecord(ctx context.Context, opts ...DBOption) error DeleteRecord(ctx context.Context, opts ...DBOption) error
UpdateRecord(record *model.BackupRecord) error
WithByDetailName(detailName string) DBOption WithByDetailName(detailName string) DBOption
WithByFileName(fileName string) DBOption WithByFileName(fileName string) DBOption
WithByType(backupType string) DBOption WithByType(backupType string) DBOption
@ -105,6 +106,10 @@ func (u *BackupRepo) CreateRecord(record *model.BackupRecord) error {
return global.DB.Create(record).Error return global.DB.Create(record).Error
} }
func (u *BackupRepo) UpdateRecord(record *model.BackupRecord) error {
return global.DB.Save(record).Error
}
func (u *BackupRepo) Update(id uint, vars map[string]interface{}) error { func (u *BackupRepo) Update(id uint, vars map[string]interface{}) error {
return global.DB.Model(&model.BackupAccount{}).Where("id = ?", id).Updates(vars).Error return global.DB.Model(&model.BackupAccount{}).Where("id = ?", id).Updates(vars).Error
} }

View file

@ -25,7 +25,7 @@ func (u *BackupService) WebsiteBackup(req dto.CommonBackup) error {
if err != nil { if err != nil {
return err return err
} }
website, err := websiteRepo.GetFirst(websiteRepo.WithDomain(req.Name)) website, err := websiteRepo.GetFirst(websiteRepo.WithAlias(req.DetailName))
if err != nil { if err != nil {
return err return err
} }
@ -40,7 +40,7 @@ func (u *BackupService) WebsiteBackup(req dto.CommonBackup) error {
record := &model.BackupRecord{ record := &model.BackupRecord{
Type: "website", Type: "website",
Name: website.PrimaryDomain, Name: website.PrimaryDomain,
DetailName: "", DetailName: req.DetailName,
Source: "LOCAL", Source: "LOCAL",
BackupType: "LOCAL", BackupType: "LOCAL",
FileDir: backupDir, FileDir: backupDir,
@ -54,14 +54,14 @@ func (u *BackupService) WebsiteBackup(req dto.CommonBackup) error {
} }
func (u *BackupService) WebsiteRecover(req dto.CommonRecover) error { func (u *BackupService) WebsiteRecover(req dto.CommonRecover) error {
website, err := websiteRepo.GetFirst(websiteRepo.WithDomain(req.Name))
if err != nil {
return err
}
fileOp := files.NewFileOp() fileOp := files.NewFileOp()
if !fileOp.Stat(req.File) { if !fileOp.Stat(req.File) {
return errors.New(fmt.Sprintf("%s file is not exist", req.File)) return errors.New(fmt.Sprintf("%s file is not exist", req.File))
} }
website, err := websiteRepo.GetFirst(websiteRepo.WithAlias(req.DetailName))
if err != nil {
return err
}
global.LOG.Infof("recover website %s from backup file %s", req.Name, req.File) global.LOG.Infof("recover website %s from backup file %s", req.Name, req.File)
if err := handleWebsiteRecover(&website, req.File, false); err != nil { if err := handleWebsiteRecover(&website, req.File, false); err != nil {
return err return err
@ -79,15 +79,6 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback
_ = os.RemoveAll(tmpPath) _ = os.RemoveAll(tmpPath)
}() }()
temPathWithName := tmpPath + "/" + website.Alias
if !fileOp.Stat(tmpPath+"/website.json") || !fileOp.Stat(temPathWithName+".conf") || !fileOp.Stat(temPathWithName+".web.tar.gz") {
return buserr.WithDetail(constant.ErrBackupExist, ".conf or .web.tar.gz", nil)
}
if website.Type == constant.Deployment {
if !fileOp.Stat(temPathWithName + ".app.tar.gz") {
return buserr.WithDetail(constant.ErrBackupExist, ".app.tar.gz", nil)
}
}
var oldWebsite model.Website var oldWebsite model.Website
websiteJson, err := os.ReadFile(tmpPath + "/website.json") websiteJson, err := os.ReadFile(tmpPath + "/website.json")
if err != nil { if err != nil {
@ -101,6 +92,16 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback
return err return err
} }
temPathWithName := tmpPath + "/" + website.Alias
if !fileOp.Stat(tmpPath+"/website.json") || !fileOp.Stat(temPathWithName+".conf") || !fileOp.Stat(temPathWithName+".web.tar.gz") {
return buserr.WithDetail(constant.ErrBackupExist, ".conf or .web.tar.gz", nil)
}
if website.Type == constant.Deployment {
if !fileOp.Stat(temPathWithName + ".app.tar.gz") {
return buserr.WithDetail(constant.ErrBackupExist, ".app.tar.gz", nil)
}
}
isOk := false isOk := false
if !isRollback { if !isRollback {
rollbackFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("website/%s_%s.tar.gz", website.Alias, time.Now().Format("20060102150405"))) rollbackFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("website/%s_%s.tar.gz", website.Alias, time.Now().Format("20060102150405")))

View file

@ -582,24 +582,6 @@ func (u *FirewallService) addAddressRecord(req dto.AddrRuleOperate) error {
return nil return nil
} }
func listIpRules(strategy string) ([]string, error) {
client, err := firewall.NewFirewallClient()
if err != nil {
return nil, err
}
addrs, err := client.ListAddress()
if err != nil {
return nil, err
}
var rules []string
for _, addr := range addrs {
if addr.Strategy == strategy {
rules = append(rules, addr.Address)
}
}
return rules, nil
}
func checkPortUsed(ports, proto string, apps []portOfApp) string { func checkPortUsed(ports, proto string, apps []portOfApp) string {
var portList []int var portList []int
if strings.Contains(ports, "-") || strings.Contains(ports, ",") { if strings.Contains(ports, "-") || strings.Contains(ports, ",") {

View file

@ -104,6 +104,9 @@ func (w WebsiteCAService) Create(create request.WebsiteCACreate) (*request.Websi
return nil, err return nil, err
} }
rootCert, err := x509.ParseCertificate(rootDer) rootCert, err := x509.ParseCertificate(rootDer)
if err != nil {
return nil, err
}
certBlock := &pem.Block{ certBlock := &pem.Block{
Type: "CERTIFICATE", Type: "CERTIFICATE",
Bytes: rootCert.Raw, Bytes: rootCert.Raw,

View file

@ -60,6 +60,7 @@ func Init() {
migrations.AddDatabaseSSL, migrations.AddDatabaseSSL,
migrations.AddDefaultCA, migrations.AddDefaultCA,
migrations.AddSettingRecycleBin, migrations.AddSettingRecycleBin,
migrations.UpdateWebsiteBackupRecord,
}) })
if err := m.Migrate(); err != nil { if err := m.Migrate(); err != nil {
global.LOG.Error(err) global.LOG.Error(err)

View file

@ -3,6 +3,7 @@ package migrations
import ( import (
"github.com/1Panel-dev/1Panel/backend/app/dto/request" "github.com/1Panel-dev/1Panel/backend/app/dto/request"
"github.com/1Panel-dev/1Panel/backend/app/model" "github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/app/repo"
"github.com/1Panel-dev/1Panel/backend/app/service" "github.com/1Panel-dev/1Panel/backend/app/service"
"github.com/go-gormigrate/gormigrate/v2" "github.com/go-gormigrate/gormigrate/v2"
"gorm.io/gorm" "gorm.io/gorm"
@ -87,3 +88,18 @@ var AddSettingRecycleBin = &gormigrate.Migration{
return nil return nil
}, },
} }
var UpdateWebsiteBackupRecord = &gormigrate.Migration{
ID: "20231218-update-backup-record-for-website",
Migrate: func(tx *gorm.DB) error {
backupRepo := repo.NewIBackupRepo()
websitesBackups, _ := backupRepo.ListRecord(repo.NewCommonRepo().WithByType("website"))
if len(websitesBackups) > 0 {
for _, backup := range websitesBackups {
backup.DetailName = backup.Name
_ = backupRepo.UpdateRecord(&backup)
}
}
return nil
},
}

View file

@ -88,13 +88,6 @@ func IsCrossVersion(version1, version2 string) bool {
return v2num > v1num return v2num > v1num
} }
func min(a, b int) int {
if a < b {
return a
}
return b
}
func GetUuid() string { func GetUuid() string {
b := make([]byte, 16) b := make([]byte, 16)
_, _ = io.ReadFull(rand.Reader, b) _, _ = io.ReadFull(rand.Reader, b)

View file

@ -142,6 +142,9 @@ const acceptParams = async (params: DialogProps): Promise<void> => {
} else { } else {
baseDir.value = `${pathRes.data}/uploads/${dir}/${name.value}/`; baseDir.value = `${pathRes.data}/uploads/${dir}/${name.value}/`;
} }
if (type.value === 'website') {
baseDir.value = `${pathRes.data}/uploads/database/${type.value}/${detailName.value}/`;
}
upVisible.value = true; upVisible.value = true;
search(); search();
}; };

View file

@ -5,6 +5,9 @@
<el-form-item :label="$t('website.primaryDomain')" prop="primaryDomain"> <el-form-item :label="$t('website.primaryDomain')" prop="primaryDomain">
<el-input v-model="form.primaryDomain"></el-input> <el-input v-model="form.primaryDomain"></el-input>
</el-form-item> </el-form-item>
<el-form-item :label="$t('website.alias')" prop="primaryDomain">
<el-input v-model="form.alias" disabled></el-input>
</el-form-item>
<el-form-item :label="$t('website.group')" prop="webSiteGroupID"> <el-form-item :label="$t('website.group')" prop="webSiteGroupID">
<el-select v-model="form.webSiteGroupId"> <el-select v-model="form.webSiteGroupId">
<el-option <el-option
@ -21,6 +24,7 @@
<el-form-item prop="IPV6"> <el-form-item prop="IPV6">
<el-checkbox v-model="form.IPV6" :label="$t('website.ipv6')" size="large" /> <el-checkbox v-model="form.IPV6" :label="$t('website.ipv6')" size="large" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="submit(websiteForm)" :disabled="loading"> <el-button type="primary" @click="submit(websiteForm)" :disabled="loading">
{{ $t('commons.button.save') }} {{ $t('commons.button.save') }}
@ -58,6 +62,7 @@ const form = reactive({
remark: '', remark: '',
webSiteGroupId: 0, webSiteGroupId: 0,
IPV6: false, IPV6: false,
alias: '',
}); });
const rules = ref({ const rules = ref({
primaryDomain: [Rules.requiredInput], primaryDomain: [Rules.requiredInput],
@ -91,6 +96,7 @@ const search = async () => {
form.remark = res.data.remark; form.remark = res.data.remark;
form.webSiteGroupId = res.data.webSiteGroupId; form.webSiteGroupId = res.data.webSiteGroupId;
form.IPV6 = res.data.IPV6; form.IPV6 = res.data.IPV6;
form.alias = res.data.alias;
}); });
}; };

View file

@ -379,7 +379,7 @@ const buttons = [
let params = { let params = {
type: 'website', type: 'website',
name: row.primaryDomain, name: row.primaryDomain,
detailName: '', detailName: row.alias,
}; };
dialogBackupRef.value!.acceptParams(params); dialogBackupRef.value!.acceptParams(params);
}, },
@ -390,7 +390,7 @@ const buttons = [
let params = { let params = {
type: 'website', type: 'website',
name: row.primaryDomain, name: row.primaryDomain,
detailName: '', detailName: row.alias,
}; };
uploadRef.value!.acceptParams(params); uploadRef.value!.acceptParams(params);
}, },