diff --git a/backend/app/repo/app_install.go b/backend/app/repo/app_install.go index 2c3a22328..d68821bc1 100644 --- a/backend/app/repo/app_install.go +++ b/backend/app/repo/app_install.go @@ -47,13 +47,19 @@ func (a *AppInstallRepo) WithServiceName(serviceName string) DBOption { } } +func (a *AppInstallRepo) WithPort(port int) DBOption { + return func(db *gorm.DB) *gorm.DB { + return db.Where("https_port = ? or http_port = ?", port, port) + } +} + func (a *AppInstallRepo) WithIdNotInWebsite() DBOption { return func(db *gorm.DB) *gorm.DB { return db.Where("id not in (select app_install_id from websites)") } } -func (a *AppInstallRepo) GetBy(opts ...DBOption) ([]model.AppInstall, error) { +func (a *AppInstallRepo) ListBy(opts ...DBOption) ([]model.AppInstall, error) { var install []model.AppInstall db := getDb(opts...).Model(&model.AppInstall{}) err := db.Preload("App").Preload("Backups").Find(&install).Error diff --git a/backend/app/service/app.go b/backend/app/service/app.go index 081a0fce3..f0052ae2c 100644 --- a/backend/app/service/app.go +++ b/backend/app/service/app.go @@ -155,7 +155,7 @@ func (a AppService) GetAppDetail(appId uint, version string) (response.AppDetail } func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (*model.AppInstall, error) { - if list, _ := appInstallRepo.GetBy(commonRepo.WithByName(req.Name)); len(list) > 0 { + if list, _ := appInstallRepo.ListBy(commonRepo.WithByName(req.Name)); len(list) > 0 { return nil, buserr.New(constant.ErrNameIsExist) } diff --git a/backend/app/service/app_install.go b/backend/app/service/app_install.go index ce9dead40..812aa2010 100644 --- a/backend/app/service/app_install.go +++ b/backend/app/service/app_install.go @@ -137,12 +137,12 @@ func (a AppInstallService) SearchForWebsite(req request.AppInstalledSearch) ([]r opts = append(opts, appInstallRepo.WithIdNotInWebsite()) } opts = append(opts, appInstallRepo.WithAppIdsIn(ids)) - installs, err = appInstallRepo.GetBy(opts...) + installs, err = appInstallRepo.ListBy(opts...) if err != nil { return nil, err } } else { - installs, err = appInstallRepo.GetBy() + installs, err = appInstallRepo.ListBy() if err != nil { return nil, err } @@ -178,7 +178,7 @@ func (a AppInstallService) Operate(req request.AppInstalledOperate) error { install.Status = constant.Running case constant.Delete: tx, ctx := getTxAndContext() - if err := deleteAppInstall(ctx, install, req.DeleteBackup); err != nil && !req.ForceDelete { + if err := deleteAppInstall(ctx, install, req.DeleteBackup, req.ForceDelete); err != nil && !req.ForceDelete { tx.Rollback() return err } @@ -206,7 +206,7 @@ func (a AppInstallService) Operate(req request.AppInstalledOperate) error { } func (a AppInstallService) SyncAll() error { - allList, err := appInstallRepo.GetBy() + allList, err := appInstallRepo.ListBy() if err != nil { return err } @@ -253,7 +253,7 @@ func (a AppInstallService) GetServices(key string) ([]response.AppService, error if err != nil { return nil, err } - installs, err := appInstallRepo.GetBy(appInstallRepo.WithAppId(app.ID), appInstallRepo.WithStatus(constant.Running)) + installs, err := appInstallRepo.ListBy(appInstallRepo.WithAppId(app.ID), appInstallRepo.WithStatus(constant.Running)) if err != nil { return nil, err } diff --git a/backend/app/service/app_utils.go b/backend/app/service/app_utils.go index 379666b4d..e0b1130c6 100644 --- a/backend/app/service/app_utils.go +++ b/backend/app/service/app_utils.go @@ -40,8 +40,17 @@ func checkPort(key string, params map[string]interface{}) (int, error) { port, ok := params[key] if ok { portN := int(math.Ceil(port.(float64))) + + oldInstalled, _ := appInstallRepo.ListBy(appInstallRepo.WithPort(portN)) + if len(oldInstalled) > 0 { + var apps []string + for _, install := range oldInstalled { + apps = append(apps, install.App.Name) + } + return portN, buserr.WithMap(constant.ErrPortInOtherApp, map[string]interface{}{"port": portN, "apps": apps}, nil) + } if common.ScanPort(portN) { - return portN, buserr.WithMessage(constant.ErrPortInUsed, portN, nil) + return portN, buserr.WithDetail(constant.ErrPortInUsed, portN, nil) } else { return portN, nil } @@ -105,23 +114,23 @@ func createLink(ctx context.Context, app model.App, appInstall *model.AppInstall return nil } -func deleteAppInstall(ctx context.Context, install model.AppInstall, deleteBackup bool) error { +func deleteAppInstall(ctx context.Context, install model.AppInstall, deleteBackup bool, forceDelete bool) error { op := files.NewFileOp() appDir := install.GetPath() dir, _ := os.Stat(appDir) if dir != nil { out, err := compose.Down(install.GetComposePath()) - if err != nil { + if err != nil && !forceDelete { return handleErr(install, err, out) } - if err := op.DeleteDir(appDir); err != nil { + if err := op.DeleteDir(appDir); err != nil && !forceDelete { return err } } - if err := appInstallRepo.Delete(ctx, install); err != nil { + if err := appInstallRepo.Delete(ctx, install); err != nil && !forceDelete { return err } - if err := deleteLink(ctx, &install); err != nil { + if err := deleteLink(ctx, &install); err != nil && !forceDelete { return err } if deleteBackup { @@ -129,7 +138,7 @@ func deleteAppInstall(ctx context.Context, install model.AppInstall, deleteBacku for _, backup := range backups { _ = op.DeleteDir(backup.Path) } - if err := appInstallBackupRepo.Delete(ctx, appInstallBackupRepo.WithAppInstallID(install.ID)); err != nil { + if err := appInstallBackupRepo.Delete(ctx, appInstallBackupRepo.WithAppInstallID(install.ID)); err != nil && !forceDelete { return err } } @@ -320,7 +329,7 @@ func getContainerNames(install model.AppInstall) ([]string, error) { func checkLimit(app model.App) error { if app.Limit > 0 { - installs, err := appInstallRepo.GetBy(appInstallRepo.WithAppId(app.ID)) + installs, err := appInstallRepo.ListBy(appInstallRepo.WithAppId(app.ID)) if err != nil { return err } @@ -361,7 +370,7 @@ func checkRequiredAndLimit(app model.App) error { _, err = appInstallRepo.GetFirst(appInstallRepo.WithDetailIdsIn(detailIds)) if err != nil { - return buserr.WithMessage(constant.ErrAppRequired, requireApp.Name, nil) + return buserr.WithDetail(constant.ErrAppRequired, requireApp.Name, nil) } } } diff --git a/backend/app/service/dashboard.go b/backend/app/service/dashboard.go index fc545d47f..d40cf0e55 100644 --- a/backend/app/service/dashboard.go +++ b/backend/app/service/dashboard.go @@ -60,7 +60,7 @@ func (u *DashboardService) LoadBaseInfo(ioOption string, netOption string) (*dto } } - appInstall, err := appInstallRepo.GetBy() + appInstall, err := appInstallRepo.ListBy() if err != nil { return nil, err } diff --git a/backend/app/service/website.go b/backend/app/service/website.go index ef3d8dced..95364a62b 100644 --- a/backend/app/service/website.go +++ b/backend/app/service/website.go @@ -334,7 +334,7 @@ func (w WebsiteService) DeleteWebsite(req request.WebsiteDelete) error { return err } if !reflect.DeepEqual(model.AppInstall{}, appInstall) { - if err := deleteAppInstall(ctx, appInstall, true); err != nil && !req.ForceDelete { + if err := deleteAppInstall(ctx, appInstall, true, req.ForceDelete); err != nil && !req.ForceDelete { return err } } @@ -638,7 +638,7 @@ func (w WebsiteService) PreInstallCheck(req request.WebsiteInstallCheckReq) ([]r res = append(res, response.WebsitePreInstallCheck{ Name: appInstall.Name, AppName: app.Name, - Status: buserr.WithMessage(constant.ErrNotInstall, app.Name, nil).Error(), + Status: buserr.WithDetail(constant.ErrNotInstall, app.Name, nil).Error(), Version: appInstall.Version, }) showErr = true @@ -651,7 +651,7 @@ func (w WebsiteService) PreInstallCheck(req request.WebsiteInstallCheckReq) ([]r } } if len(checkIds) > 0 { - installList, _ := appInstallRepo.GetBy(commonRepo.WithIdsIn(checkIds)) + installList, _ := appInstallRepo.ListBy(commonRepo.WithIdsIn(checkIds)) for _, install := range installList { res = append(res, response.WebsitePreInstallCheck{ Name: install.Name, diff --git a/backend/buserr/errors.go b/backend/buserr/errors.go index 46a3898b6..43b843ec4 100644 --- a/backend/buserr/errors.go +++ b/backend/buserr/errors.go @@ -8,6 +8,7 @@ import ( type BusinessError struct { Msg string Detail interface{} + Map map[string]interface{} Err error } @@ -15,6 +16,8 @@ func (e BusinessError) Error() string { content := "" if e.Detail != nil { content = i18n.GetErrMsg(e.Msg, map[string]interface{}{"detail": e.Detail}) + } else if e.Map != nil { + content = i18n.GetErrMsg(e.Msg, e.Map) } else { content = i18n.GetErrMsg(e.Msg, nil) } @@ -35,10 +38,18 @@ func New(Key string) BusinessError { } } -func WithMessage(Key string, detail interface{}, err error) BusinessError { +func WithDetail(Key string, detail interface{}, err error) BusinessError { return BusinessError{ Msg: Key, Detail: detail, Err: err, } } + +func WithMap(Key string, maps map[string]interface{}, err error) BusinessError { + return BusinessError{ + Msg: Key, + Map: maps, + Err: err, + } +} diff --git a/backend/constant/errs.go b/backend/constant/errs.go index 4bccaafe7..e4e08f99b 100644 --- a/backend/constant/errs.go +++ b/backend/constant/errs.go @@ -54,6 +54,7 @@ var ( ErrFileCanNotRead = "ErrFileCanNotRead" ErrFileToLarge = "ErrFileToLarge" ErrNotInstall = "ErrNotInstall" + ErrPortInOtherApp = "ErrPortInOtherApp" ) //website diff --git a/backend/i18n/lang/en.yaml b/backend/i18n/lang/en.yaml index d4d339291..827cb2613 100644 --- a/backend/i18n/lang/en.yaml +++ b/backend/i18n/lang/en.yaml @@ -21,6 +21,7 @@ ErrPortInUsed: "{{ .detail }} port already in use" ErrAppLimit: "App exceeds install limit" ErrAppRequired: "{{ .detail }} app is required" ErrNotInstall: "App not installed" +ErrPortInOtherApp: "{{ .port }} port already in use by {{ .apps }}" #file diff --git a/backend/i18n/lang/zh.yaml b/backend/i18n/lang/zh.yaml index 8f7c20c43..d8e4a3b4a 100644 --- a/backend/i18n/lang/zh.yaml +++ b/backend/i18n/lang/zh.yaml @@ -21,6 +21,7 @@ ErrPortInUsed: "{{ .detail }} 端口已被占用!" ErrAppLimit: "应用超出安装数量限制" ErrAppRequired: "请先安装 {{ .detail }} 应用" ErrNotInstall: "应用未安装" +ErrPortInOtherApp: "{{ .port }} 端口已被 {{ .apps }}占用!" #file ErrFileCanNotRead: "此文件不支持预览" diff --git a/frontend/src/views/app-store/detail/params/index.vue b/frontend/src/views/app-store/detail/params/index.vue index 585681272..8407bac14 100644 --- a/frontend/src/views/app-store/detail/params/index.vue +++ b/frontend/src/views/app-store/detail/params/index.vue @@ -1,6 +1,6 @@