feat: 增加反向代理类型

This commit is contained in:
zhengkunwang223 2022-12-12 15:36:45 +08:00 committed by zhengkunwang223
parent 6260281cac
commit b7d55801cd
14 changed files with 84 additions and 47 deletions

View File

@ -100,7 +100,7 @@ func (b *BaseApi) RecoverWebsite(c *gin.Context) {
}
func (b *BaseApi) DeleteWebSite(c *gin.Context) {
var req dto.WebSiteDel
var req request.WebSiteDel
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return

View File

@ -21,6 +21,7 @@ type WebSiteCreate struct {
Alias string `json:"alias" validate:"required"`
Remark string `json:"remark"`
OtherDomains string `json:"otherDomains"`
Proxy string `json:"proxy"`
AppType AppType `json:"appType"`
AppInstall NewAppInstall `json:"appInstall"`
AppID uint `json:"appID"`
@ -45,12 +46,6 @@ type NewAppInstall struct {
Params map[string]interface{} `json:"params"`
}
type WebSiteDel struct {
ID uint `json:"id"`
DeleteApp bool `json:"deleteApp"`
DeleteBackup bool `json:"deleteBackup"`
}
type WebSiteRecover struct {
WebsiteName string `json:"websiteName" validate:"required"`
Type string `json:"type" validate:"required"`

View File

@ -14,6 +14,7 @@ type WebSite struct {
AppInstallID uint `gorm:"type:integer" json:"appInstallId"`
WebSiteGroupID uint `gorm:"type:integer" json:"webSiteGroupId"`
WebSiteSSLID uint `gorm:"type:integer" json:"webSiteSSLId"`
Proxy string `gorm:"type:varchar(128);not null" json:"proxy"`
Domains []WebSiteDomain `json:"domains"`
WebSiteSSL WebSiteSSL `json:"webSiteSSL"`
}

View File

@ -11,3 +11,10 @@ type WebsiteWafUpdate struct {
Key string `json:"key" validate:"required"`
Enable bool `json:"enable" validate:"required"`
}
type WebSiteDel struct {
ID uint `json:"id" validate:"required"`
DeleteApp bool `json:"deleteApp"`
DeleteBackup bool `json:"deleteBackup"`
ForceDelete bool `json:"forceDelete"`
}

View File

@ -33,7 +33,7 @@ type IWebsiteService interface {
Recover(req dto.WebSiteRecover) error
RecoverByUpload(req dto.WebSiteRecoverByFile) error
UpdateWebsite(req dto.WebSiteUpdate) error
DeleteWebSite(req dto.WebSiteDel) error
DeleteWebSite(req request.WebSiteDel) error
GetWebsite(id uint) (dto.WebsiteDTO, error)
CreateWebsiteDomain(create dto.WebSiteDomainCreate) (model.WebSiteDomain, error)
GetWebsiteDomain(websiteId uint) ([]model.WebSiteDomain, error)
@ -88,9 +88,11 @@ func (w WebsiteService) CreateWebsite(create dto.WebSiteCreate) error {
AppInstallID: create.AppInstallID,
WebSiteGroupID: create.WebSiteGroupID,
Protocol: constant.ProtocolHTTP,
Proxy: create.Proxy,
}
if create.Type == "deployment" {
switch create.Type {
case constant.Deployment:
if create.AppType == dto.NewApp {
install, err := ServiceGroupApp.Install(create.AppInstall.Name, create.AppInstall.AppDetailId, create.AppInstall.Params)
if err != nil {
@ -98,7 +100,7 @@ func (w WebsiteService) CreateWebsite(create dto.WebSiteCreate) error {
}
website.AppInstallID = install.ID
}
} else {
case constant.Static:
if err := createStaticHtml(website); err != nil {
return err
}
@ -240,12 +242,12 @@ func (w WebsiteService) GetWebsite(id uint) (dto.WebsiteDTO, error) {
return res, nil
}
func (w WebsiteService) DeleteWebSite(req dto.WebSiteDel) error {
func (w WebsiteService) DeleteWebSite(req request.WebSiteDel) error {
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID))
if err != nil {
return err
}
if err := delNginxConfig(website); err != nil {
if err := delNginxConfig(website, req.ForceDelete); err != nil {
return err
}
tx, ctx := getTxAndContext()
@ -253,7 +255,7 @@ func (w WebsiteService) DeleteWebSite(req dto.WebSiteDel) error {
if req.DeleteApp {
websites, _ := websiteRepo.GetBy(websiteRepo.WithAppInstallId(website.AppInstallID))
if len(websites) > 1 {
return errors.New("other website use this app")
return buserr.New(constant.ErrAppDelete)
}
appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID))
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {

View File

@ -74,7 +74,6 @@ func createStaticHtml(website *model.WebSite) error {
}
func createWebsiteFolder(nginxInstall model.AppInstall, website *model.WebSite) error {
nginxFolder := path.Join(constant.AppInstallDir, "nginx", nginxInstall.Name)
siteFolder := path.Join(nginxFolder, "www", "sites", website.Alias)
fileOp := files.NewFileOp()
@ -99,7 +98,6 @@ func createWebsiteFolder(nginxInstall model.AppInstall, website *model.WebSite)
}
func configDefaultNginx(website *model.WebSite, domains []model.WebSiteDomain) error {
nginxInstall, err := getAppInstallByKey("nginx")
if err != nil {
return err
@ -131,16 +129,19 @@ func configDefaultNginx(website *model.WebSite, domains []model.WebSiteDomain) e
server.UpdateDirective("set", []string{"$RulePath", path.Join(siteFolder, "waf", "rules")})
server.UpdateDirective("set", []string{"$logdir", path.Join(siteFolder, "log")})
if website.Type == "deployment" {
switch website.Type {
case constant.Deployment:
appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID))
if err != nil {
return err
}
proxy := fmt.Sprintf("http://127.0.0.1:%d", appInstall.HttpPort)
server.UpdateRootProxy([]string{proxy})
} else {
case constant.Static:
server.UpdateRoot(path.Join("/www/sites", website.Alias))
server.UpdateRootLocation()
case constant.Proxy:
server.UpdateRootProxy([]string{website.Proxy})
}
config.FilePath = configPath
@ -154,8 +155,7 @@ func configDefaultNginx(website *model.WebSite, domains []model.WebSiteDomain) e
return opNginx(nginxInstall.ContainerName, constant.NginxReload)
}
func delNginxConfig(website model.WebSite) error {
func delNginxConfig(website model.WebSite, force bool) error {
nginxApp, err := appRepo.GetFirst(appRepo.WithKey("nginx"))
if err != nil {
return err
@ -178,11 +178,16 @@ func delNginxConfig(website model.WebSite) error {
if err := fileOp.DeleteFile(configPath); err != nil {
return err
}
return opNginx(nginxInstall.ContainerName, "reload")
if err := opNginx(nginxInstall.ContainerName, "reload"); err != nil {
if force {
return nil
}
return err
}
return nil
}
func addListenAndServerName(website model.WebSite, ports []int, domains []string) error {
nginxFull, err := getNginxFull(&website)
if err != nil {
return nil
@ -203,7 +208,6 @@ func addListenAndServerName(website model.WebSite, ports []int, domains []string
}
func deleteListenAndServerName(website model.WebSite, ports []int, domains []string) error {
nginxFull, err := getNginxFull(&website)
if err != nil {
return nil
@ -280,7 +284,6 @@ func createPemFile(website model.WebSite, websiteSSL model.WebSiteSSL) error {
}
func applySSL(website model.WebSite, websiteSSL model.WebSiteSSL) error {
nginxFull, err := getNginxFull(&website)
if err != nil {
return nil
@ -398,7 +401,7 @@ func handleWebsiteBackup(backupType, baseDir, backupDir, domain, backupName stri
return err
}
if website.Type == "deployment" {
if website.Type == constant.Deployment {
if err := mysqlOpration(&website, "backup", tmpDir); err != nil {
return err
}
@ -451,7 +454,7 @@ func handleWebsiteRecover(website *model.WebSite, fileDir string) error {
return err
}
if website.Type == "deployment" {
if website.Type == constant.Deployment {
if err := mysqlOpration(website, "recover", fileDir); err != nil {
return err
}

View File

@ -59,6 +59,7 @@ var (
var (
ErrDomainIsExist = "ErrDomainIsExist"
ErrAliasIsExist = "ErrAliasIsExist"
ErrAppDelete = "ErrAppDelete"
)
//ssl

View File

@ -14,3 +14,9 @@ const (
ProtocolHTTP = "HTTP"
ProtocolHTTPS = "HTTPS"
)
const (
Deployment = "deployment"
Static = "static"
Proxy = "proxy"
)

View File

@ -30,6 +30,7 @@ ErrFileToLarge: "file is too large"
#website
ErrDomainIsExist: "Domain is already exist"
ErrAliasIsExist: "Alias is already exist"
ErrAppDelete: 'Other Website use this App'
#ssl
ErrSSLCannotDelete: "The certificate is being used by the website and cannot be removed"

View File

@ -29,7 +29,7 @@ ErrFileToLarge: "文件超过10M,无法打开"
#website
ErrDomainIsExist: "域名已存在"
ErrAliasIsExist: "代号已存在"
ErrAppDelete: ''
ErrAppDelete: '其他网站使用此应用,不能删除'
#ssl
ErrSSLCannotDelete: "证书正在被网站使用,无法删除"

View File

@ -54,6 +54,7 @@ export namespace WebSite {
id: number;
deleteApp: boolean;
deleteBackup: boolean;
forceDelete: boolean;
}
export interface WebSiteCreateReq {
@ -65,6 +66,7 @@ export namespace WebSite {
appInstallId: number;
webSiteGroupId: number;
otherDomains: string;
proxy: string;
}
export interface WebSiteUpdateReq {

View File

@ -104,7 +104,7 @@ export default {
imageName: '支持英文中文数字:.-_,长度1-30',
complexityPassword: '请输入 8 位以上必须含有字母数字特殊符号的密码',
commonPassword: '请输入 6 位以上长度密码',
linuxName: '支持英文数字.-_,长度1-30',
linuxName: '支持英文数字._,长度1-30',
email: '请输入正确的邮箱',
number: '请输入正确的数字',
ip: '请输入正确的 IP 地址',
@ -786,7 +786,7 @@ export default {
otherDomains: '其他域名',
type: '类型',
static: '静态网站',
deployment: '反向代理',
deployment: '一键部署',
supportUpType: '仅支持 tar.gz 文件',
zipFormat: 'tar.gz 压缩包结构test.tar.gz 压缩包内必需包含 website.json 文件',
proxy: '反向代理',
@ -868,6 +868,9 @@ export default {
fileExtBlock: '文件扩展名黑名单',
value: '值',
enable: '开启',
proxyAddress: '代理地址',
proxyHelper: '例如: http://127.0.0.1:8080',
forceDelete: '强制删除',
},
nginx: {
serverNamesHashBucketSizeHelper: '服务器名字的hash表大小',

View File

@ -1,17 +1,24 @@
<template>
<el-dialog
v-model="open"
:destroy-on-close="true"
:close-on-click-modal="false"
:title="$t('website.create')"
width="40%"
:before-close="handleClose"
>
<el-form ref="websiteForm" label-position="right" :model="website" label-width="130px" :rules="rules">
<el-form
ref="websiteForm"
label-position="right"
:model="website"
label-width="130px"
:rules="rules"
:validate-on-rule-change="false"
>
<el-form-item :label="$t('website.type')" prop="type">
<el-select v-model="website.type">
<el-option :label="$t('website.deployment')" value="deployment"></el-option>
<el-option :label="$t('website.static')" value="static"></el-option>
<el-option :label="$t('website.proxy')" value="proxy"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('website.group')" prop="webSiteGroupId">
@ -103,6 +110,9 @@
<el-form-item :label="$t('website.alias')" prop="alias">
<el-input v-model="website.alias" :placeholder="$t('website.aliasHelper')"></el-input>
</el-form-item>
<el-form-item v-if="website.type === 'proxy'" :label="$t('website.proxyAddress')" prop="proxy">
<el-input v-model="website.proxy" :placeholder="$t('website.proxyHelper')"></el-input>
</el-form-item>
<el-form-item :label="$t('website.remark')" prop="remark">
<el-input v-model="website.remark"></el-input>
</el-form-item>
@ -141,6 +151,7 @@ const website = ref({
appInstallId: undefined,
webSiteGroupId: 1,
otherDomains: '',
proxy: '',
appinstall: {
appId: 0,
name: '',
@ -149,15 +160,16 @@ const website = ref({
version: '',
},
});
let rules = ref({
let rules = reactive({
primaryDomain: [Rules.linuxName],
alias: [Rules.linuxName],
type: [Rules.requiredInput],
webSiteGroupId: [Rules.requiredSelectBusiness],
appInstallId: [Rules.requiredSelectBusiness],
appType: [Rules.requiredInput],
proxy: [Rules.requiredInput],
appinstall: {
name: [Rules.requiredInput],
name: [Rules.linuxName],
appId: [Rules.requiredSelectBusiness],
params: {},
},

View File

@ -1,14 +1,14 @@
<template>
<el-dialog
v-model="open"
:destroy-on-close="true"
:close-on-click-modal="false"
:title="$t('website.delete')"
width="40%"
:before-close="handleClose"
>
<div style="text-align: center">
<el-checkbox v-model="deleteReq.deleteApp" :label="$t('website.deleteApp')" />
<div style="text-align: center" :key="key">
<el-checkbox v-model="deleteReq.forceDelete" :label="$t('website.forceDelete')" />
<el-checkbox v-if="type === 'deployment'" v-model="deleteReq.deleteApp" :label="$t('website.deleteApp')" />
<el-checkbox v-model="deleteReq.deleteBackup" :label="$t('website.deleteBackup')" />
</div>
<template #footer>
@ -26,22 +26,19 @@
import { DeleteWebsite } from '@/api/modules/website';
import i18n from '@/lang';
import { ElMessage } from 'element-plus';
import { reactive, ref } from 'vue';
// interface DeleteProps {
// id: number;
// }
// const deleteData = ref<DeleteProps>({
// id: 0,
// });
import { ref } from 'vue';
import { WebSite } from '@/api/interface/website';
let key = 1;
let open = ref(false);
let loading = ref(false);
let deleteReq = reactive({
let deleteReq = ref({
id: 0,
deleteApp: false,
deleteBackup: false,
forceDelete: false,
});
let type = ref('');
const em = defineEmits(['close']);
const handleClose = () => {
@ -49,14 +46,21 @@ const handleClose = () => {
em('close', false);
};
const acceptParams = async (id: number) => {
deleteReq.id = id;
const acceptParams = async (website: WebSite.WebSite) => {
deleteReq.value = {
id: 0,
deleteApp: false,
deleteBackup: false,
forceDelete: false,
};
deleteReq.value.id = website.id;
type.value = website.type;
open.value = true;
};
const submit = () => {
loading.value = true;
DeleteWebsite(deleteReq)
DeleteWebsite(deleteReq.value)
.then(() => {
handleClose();
ElMessage.success(i18n.global.t('commons.msg.deleteSuccess'));