1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-03-14 01:34:47 +08:00

feat: 网站应用创建可以选择存量数据库,删除应用增加删除数据库选项

This commit is contained in:
zhengkunwang223 2023-03-06 17:24:00 +08:00 committed by zhengkunwang223
parent a1c3fa644c
commit e1518e842f
12 changed files with 52 additions and 21 deletions

View File

@ -45,6 +45,7 @@ type AppInstalledOperate struct {
Operate constant.AppOperate `json:"operate" validate:"required"` Operate constant.AppOperate `json:"operate" validate:"required"`
ForceDelete bool `json:"forceDelete"` ForceDelete bool `json:"forceDelete"`
DeleteBackup bool `json:"deleteBackup"` DeleteBackup bool `json:"deleteBackup"`
DeleteDB bool `json:"deleteDB"`
} }
type PortUpdate struct { type PortUpdate struct {

View File

@ -33,7 +33,6 @@ type IAppService interface {
GetApp(key string) (*response.AppDTO, error) GetApp(key string) (*response.AppDTO, error)
GetAppDetail(appId uint, version string) (response.AppDetailDTO, error) GetAppDetail(appId uint, version string) (response.AppDetailDTO, error)
Install(ctx context.Context, req request.AppInstallCreate) (*model.AppInstall, error) Install(ctx context.Context, req request.AppInstallCreate) (*model.AppInstall, error)
//SyncInstalled(installId uint) error
SyncAppList() error SyncAppList() error
} }

View File

@ -184,7 +184,7 @@ func (a AppInstallService) Operate(req request.AppInstalledOperate) error {
install.Status = constant.Running install.Status = constant.Running
case constant.Delete: case constant.Delete:
tx, ctx := getTxAndContext() tx, ctx := getTxAndContext()
if err := deleteAppInstall(ctx, install, req.DeleteBackup, req.ForceDelete); err != nil && !req.ForceDelete { if err := deleteAppInstall(ctx, install, req.DeleteBackup, req.ForceDelete, req.DeleteDB); err != nil && !req.ForceDelete {
tx.Rollback() tx.Rollback()
return err return err
} }

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/1Panel-dev/1Panel/backend/app/repo"
"math" "math"
"os" "os"
"path" "path"
@ -88,18 +89,29 @@ func createLink(ctx context.Context, app model.App, appInstall *model.AppInstall
if err != nil { if err != nil {
return err return err
} }
var createMysql dto.MysqlDBCreate iMysqlRepo := repo.NewIMysqlRepo()
createMysql.Name = dbConfig.DbName oldMysqlDb, _ := iMysqlRepo.Get(commonRepo.WithByName(dbConfig.DbName))
createMysql.Username = dbConfig.DbUser resourceId := oldMysqlDb.ID
createMysql.Format = "utf8mb4" if oldMysqlDb.ID > 0 {
createMysql.Permission = "%" if oldMysqlDb.Username != dbConfig.DbUser || oldMysqlDb.Password != dbConfig.Password {
createMysql.Password = dbConfig.Password return buserr.New(constant.ErrDbUserNotValid)
mysqldb, err := NewIMysqlService().Create(ctx, createMysql) }
if err != nil { } else {
return err var createMysql dto.MysqlDBCreate
createMysql.Name = dbConfig.DbName
createMysql.Username = dbConfig.DbUser
createMysql.Format = "utf8mb4"
createMysql.Permission = "%"
createMysql.Password = dbConfig.Password
mysqldb, err := NewIMysqlService().Create(ctx, createMysql)
if err != nil {
return err
}
resourceId = mysqldb.ID
} }
var installResource model.AppInstallResource var installResource model.AppInstallResource
installResource.ResourceId = mysqldb.ID installResource.ResourceId = resourceId
installResource.AppInstallId = appInstall.ID installResource.AppInstallId = appInstall.ID
installResource.LinkId = dbInstall.ID installResource.LinkId = dbInstall.ID
installResource.Key = dbInstall.App.Key installResource.Key = dbInstall.App.Key
@ -110,7 +122,7 @@ func createLink(ctx context.Context, app model.App, appInstall *model.AppInstall
return nil return nil
} }
func deleteAppInstall(ctx context.Context, install model.AppInstall, deleteBackup bool, forceDelete bool) error { func deleteAppInstall(ctx context.Context, install model.AppInstall, deleteBackup bool, forceDelete bool, deleteDB bool) error {
op := files.NewFileOp() op := files.NewFileOp()
appDir := install.GetPath() appDir := install.GetPath()
dir, _ := os.Stat(appDir) dir, _ := os.Stat(appDir)
@ -126,7 +138,7 @@ func deleteAppInstall(ctx context.Context, install model.AppInstall, deleteBacku
if err := appInstallRepo.Delete(ctx, install); err != nil && !forceDelete { if err := appInstallRepo.Delete(ctx, install); err != nil && !forceDelete {
return err return err
} }
if err := deleteLink(ctx, &install); err != nil && !forceDelete { if err := deleteLink(ctx, &install, deleteDB); err != nil && !forceDelete {
return err return err
} }
uploadDir := fmt.Sprintf("%s/1panel/uploads/app/%s/%s", global.CONF.System.BaseDir, install.App.Key, install.Name) uploadDir := fmt.Sprintf("%s/1panel/uploads/app/%s/%s", global.CONF.System.BaseDir, install.App.Key, install.Name)
@ -149,14 +161,14 @@ func deleteAppInstall(ctx context.Context, install model.AppInstall, deleteBacku
return nil return nil
} }
func deleteLink(ctx context.Context, install *model.AppInstall) error { func deleteLink(ctx context.Context, install *model.AppInstall, deleteDB bool) error {
resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID)) resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID))
if len(resources) == 0 { if len(resources) == 0 {
return nil return nil
} }
for _, re := range resources { for _, re := range resources {
mysqlService := NewIMysqlService() mysqlService := NewIMysqlService()
if re.Key == "mysql" { if re.Key == "mysql" && deleteDB {
database, _ := mysqlRepo.Get(commonRepo.WithByID(re.ResourceId)) database, _ := mysqlRepo.Get(commonRepo.WithByID(re.ResourceId))
if reflect.DeepEqual(database, model.DatabaseMysql{}) { if reflect.DeepEqual(database, model.DatabaseMysql{}) {
continue continue

View File

@ -253,7 +253,7 @@ func (w WebsiteService) DeleteWebsite(ctx context.Context, req request.WebsiteDe
return err return err
} }
if !reflect.DeepEqual(model.AppInstall{}, appInstall) { if !reflect.DeepEqual(model.AppInstall{}, appInstall) {
if err := deleteAppInstall(ctx, appInstall, true, req.ForceDelete); err != nil && !req.ForceDelete { if err := deleteAppInstall(ctx, appInstall, true, req.ForceDelete, true); err != nil && !req.ForceDelete {
return err return err
} }
} }

View File

@ -57,6 +57,7 @@ var (
ErrFileToLarge = "ErrFileToLarge" ErrFileToLarge = "ErrFileToLarge"
ErrNotInstall = "ErrNotInstall" ErrNotInstall = "ErrNotInstall"
ErrPortInOtherApp = "ErrPortInOtherApp" ErrPortInOtherApp = "ErrPortInOtherApp"
ErrDbUserNotValid = "ErrDbUserNotValid"
) )
//website //website

View File

@ -23,6 +23,7 @@ ErrAppLimit: "App exceeds install limit"
ErrAppRequired: "{{ .detail }} app is required" ErrAppRequired: "{{ .detail }} app is required"
ErrNotInstall: "App not installed" ErrNotInstall: "App not installed"
ErrPortInOtherApp: "{{ .port }} port already in use by {{ .apps }}" ErrPortInOtherApp: "{{ .port }} port already in use by {{ .apps }}"
ErrDbUserNotValid: "Stock database, username and password do not match"
#file #file
ErrFileCanNotRead: "File can not read" ErrFileCanNotRead: "File can not read"

View File

@ -23,6 +23,7 @@ ErrAppLimit: "应用超出安装数量限制"
ErrAppRequired: "请先安装 {{ .detail }} 应用" ErrAppRequired: "请先安装 {{ .detail }} 应用"
ErrNotInstall: "应用未安装" ErrNotInstall: "应用未安装"
ErrPortInOtherApp: "{{ .port }} 端口已被 {{ .apps }}占用!" ErrPortInOtherApp: "{{ .port }} 端口已被 {{ .apps }}占用!"
ErrDbUserNotValid: "存量数据库,用户名密码不匹配!"
#file #file
ErrFileCanNotRead: "此文件不支持预览" ErrFileCanNotRead: "此文件不支持预览"

View File

@ -863,6 +863,7 @@ export default {
all: 'All', all: 'All',
version: 'Version', version: 'Version',
detail: 'Details', detail: 'Details',
params: 'Param',
install: 'Install', install: 'Install',
author: 'Author', author: 'Author',
source: 'Source', source: 'Source',
@ -905,7 +906,9 @@ export default {
forceDeleteHelper: forceDeleteHelper:
'Forced deletion will ignore errors generated during the deletion process and eventually delete metadata', 'Forced deletion will ignore errors generated during the deletion process and eventually delete metadata',
deleteBackup: 'Delete backup', deleteBackup: 'Delete backup',
deleteBackupHelper: 'Delete application backup at the same time', deleteBackupHelper: 'Also delete the application backup',
deleteDB: 'Delete Database',
deleteDBHelper: 'Also delete the database',
noService: 'No {0}', noService: 'No {0}',
toInstall: 'to install', toInstall: 'to install',
param: 'parameter configuration', param: 'parameter configuration',

View File

@ -866,7 +866,8 @@ export default {
installed: '已安装', installed: '已安装',
all: '全部', all: '全部',
version: '版本', version: '版本',
detail: '参数', detail: '详情',
params: '参数',
install: '安装', install: '安装',
author: '作者', author: '作者',
source: '来源', source: '来源',
@ -907,6 +908,8 @@ export default {
forceDeleteHelper: '强制删除会忽略删除过程中产生的错误并最终删除元数据', forceDeleteHelper: '强制删除会忽略删除过程中产生的错误并最终删除元数据',
deleteBackup: '删除备份', deleteBackup: '删除备份',
deleteBackupHelper: '同时删除应用备份', deleteBackupHelper: '同时删除应用备份',
deleteDB: '删除数据库',
deleteDBHelper: '同时删除与应用关联的数据库',
noService: '{0}', noService: '{0}',
toInstall: '去安装', toInstall: '去安装',
param: '参数配置', param: '参数配置',

View File

@ -2,7 +2,7 @@
<el-dialog <el-dialog
v-model="open" v-model="open"
:title="$t('commons.button.delete') + ' - ' + appInstallName" :title="$t('commons.button.delete') + ' - ' + appInstallName"
width="30%" width="40%"
:close-on-click-modal="false" :close-on-click-modal="false"
:before-close="handleClose" :before-close="handleClose"
> >
@ -19,6 +19,12 @@
{{ $t('app.deleteBackupHelper') }} {{ $t('app.deleteBackupHelper') }}
</span> </span>
</el-form-item> </el-form-item>
<el-form-item v-if="appType === 'website'">
<el-checkbox v-model="deleteReq.deleteDB" :label="$t('app.deleteDB')" />
<span class="input-help">
{{ $t('app.deleteDBHelper') }}
</span>
</el-form-item>
<el-form-item> <el-form-item>
<span v-html="deleteHelper"></span> <span v-html="deleteHelper"></span>
<el-input v-model="deleteInfo" :placeholder="appInstallName" /> <el-input v-model="deleteInfo" :placeholder="appInstallName" />
@ -50,12 +56,14 @@ let deleteReq = ref({
installId: 0, installId: 0,
deleteBackup: false, deleteBackup: false,
forceDelete: false, forceDelete: false,
deleteDB: true,
}); });
let open = ref(false); let open = ref(false);
let loading = ref(false); let loading = ref(false);
let deleteHelper = ref(''); let deleteHelper = ref('');
let deleteInfo = ref(''); let deleteInfo = ref('');
let appInstallName = ref(''); let appInstallName = ref('');
let appType = ref('');
const deleteForm = ref<FormInstance>(); const deleteForm = ref<FormInstance>();
const em = defineEmits(['close']); const em = defineEmits(['close']);
@ -71,9 +79,11 @@ const acceptParams = async (app: App.AppInstalled) => {
installId: 0, installId: 0,
deleteBackup: false, deleteBackup: false,
forceDelete: false, forceDelete: false,
deleteDB: true,
}; };
deleteInfo.value = ''; deleteInfo.value = '';
deleteReq.value.installId = app.id; deleteReq.value.installId = app.id;
appType.value = app.app.type;
deleteHelper.value = i18n.global.t('website.deleteConfirmHelper', [app.name]); deleteHelper.value = i18n.global.t('website.deleteConfirmHelper', [app.name]);
appInstallName.value = app.name; appInstallName.value = app.name;
open.value = true; open.value = true;

View File

@ -348,7 +348,7 @@ const buttons = [
}, },
}, },
{ {
label: i18n.global.t('app.detail'), label: i18n.global.t('app.params'),
click: (row: any) => { click: (row: any) => {
openParam(row.id); openParam(row.id);
}, },