feat: 新增创建域名

This commit is contained in:
zhengkunwang223 2022-11-03 18:02:07 +08:00 committed by zhengkunwang223
parent 35e85930b9
commit cfa5f08cdd
10 changed files with 199 additions and 19 deletions

View File

@ -82,3 +82,17 @@ func (b *BaseApi) DeleteWebDomain(c *gin.Context) {
}
helper.SuccessWithData(c, nil)
}
func (b *BaseApi) CreateWebDomain(c *gin.Context) {
var req dto.WebSiteDomainCreate
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
domain, err := websiteService.CreateWebsiteDomain(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, domain)
}

View File

@ -1,6 +1,9 @@
package dto
import "github.com/1Panel-dev/1Panel/backend/app/model"
import (
"github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/utils/nginx/components"
)
type WebSiteReq struct {
PageInfo
@ -43,16 +46,23 @@ type WebSiteDTO struct {
}
type WebSiteGroupCreate struct {
Name string
Name string `json:"name"`
}
type WebSiteGroupUpdate struct {
ID uint
Name string
ID uint `json:"id"`
Name string `json:"name"`
}
type WebSiteDomainCreate struct {
WebSiteID uint `json:"webSiteId"`
Port int `json:"port"`
Domain string `json:"domain"`
}
type WebSiteDomainDel struct {
type NginxConfig struct {
FilePath string `json:"filePath"`
ContainerName string `json:"containerName"`
Config *components.Config `json:"config"`
OldContent string `json:"oldContent"`
}

View File

@ -126,8 +126,28 @@ func (w WebsiteService) DeleteWebSite(req dto.WebSiteDel) error {
return nil
}
func (w WebsiteService) CreateWebsiteDomain() {
func (w WebsiteService) CreateWebsiteDomain(create dto.WebSiteDomainCreate) (model.WebSiteDomain, error) {
var domainModel model.WebSiteDomain
var ports []int
var domains []string
website, err := websiteRepo.GetFirst(commonRepo.WithByID(create.WebSiteID))
if err != nil {
return domainModel, err
}
if oldDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebSiteId(create.WebSiteID), websiteDomainRepo.WithPort(create.Port)); len(oldDomains) == 0 {
ports = append(ports, create.Port)
}
domains = append(domains, create.Domain)
if err := addListenAndServerName(website, ports, domains); err != nil {
return domainModel, err
}
domainModel = model.WebSiteDomain{
Domain: create.Domain,
Port: create.Port,
WebSiteID: create.WebSiteID,
}
return domainModel, websiteDomainRepo.Create(context.TODO(), &domainModel)
}
func (w WebsiteService) GetWebsiteDomain(websiteId uint) ([]model.WebSiteDomain, error) {

View File

@ -2,6 +2,7 @@ package service
import (
"fmt"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
@ -137,23 +138,59 @@ func nginxCheckAndReload(oldContent string, filePath string, containerName strin
return nil
}
func deleteListenAndServerName(website model.WebSite, ports []int, domains []string) error {
func getNginxConfig(primaryDomain string) (dto.NginxConfig, error) {
var nginxConfig dto.NginxConfig
nginxApp, err := appRepo.GetFirst(appRepo.WithKey("nginx"))
if err != nil {
return err
return nginxConfig, err
}
nginxInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithAppId(nginxApp.ID))
if err != nil {
return err
return nginxConfig, err
}
configPath := path.Join(constant.AppInstallDir, "nginx", nginxInstall.Name, "conf", "conf.d", website.PrimaryDomain+".conf")
configPath := path.Join(constant.AppInstallDir, "nginx", nginxInstall.Name, "conf", "conf.d", primaryDomain+".conf")
content, err := os.ReadFile(configPath)
if err != nil {
return err
return nginxConfig, err
}
config := parser.NewStringParser(string(content)).Parse()
config.FilePath = configPath
nginxConfig.Config = config
nginxConfig.OldContent = string(content)
nginxConfig.ContainerName = nginxInstall.ContainerName
nginxConfig.FilePath = configPath
return nginxConfig, nil
}
func addListenAndServerName(website model.WebSite, ports []int, domains []string) error {
nginxConfig, err := getNginxConfig(website.PrimaryDomain)
if err != nil {
return nil
}
config := nginxConfig.Config
server := config.FindServers()[0]
for _, port := range ports {
server.AddListen(strconv.Itoa(port), false)
}
for _, domain := range domains {
server.AddServerName(domain)
}
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
return err
}
return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxConfig.ContainerName)
}
func deleteListenAndServerName(website model.WebSite, ports []int, domains []string) error {
nginxConfig, err := getNginxConfig(website.PrimaryDomain)
if err != nil {
return nil
}
config := nginxConfig.Config
server := config.FindServers()[0]
for _, port := range ports {
server.DeleteListen(strconv.Itoa(port))
@ -162,10 +199,8 @@ func deleteListenAndServerName(website model.WebSite, ports []int, domains []str
server.DeleteServerName(domain)
}
config.FilePath = configPath
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
return err
}
return nginxCheckAndReload(string(content), configPath, nginxInstall.ContainerName)
return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxConfig.ContainerName)
}

View File

@ -20,5 +20,6 @@ func (a *WebsiteRouter) InitWebsiteRouter(Router *gin.RouterGroup) {
groupRouter.POST("/del", baseApi.DeleteWebSite)
groupRouter.GET("/domains/:websiteId", baseApi.GetWebDomains)
groupRouter.DELETE("/domains/:id", baseApi.DeleteWebDomain)
groupRouter.POST("/domains", baseApi.CreateWebDomain)
}
}

View File

@ -112,6 +112,13 @@ func (s *Server) DeleteServerName(name string) {
s.UpdateServerName(names)
}
func (s *Server) AddServerName(name string) {
dirs := s.FindDirectives("server_name")
params := dirs[0].GetParameters()
params = append(params, name)
s.UpdateServerName(params)
}
func (s *Server) UpdateServerName(names []string) {
serverNameDirective := Directive{
Name: "server_name",

View File

@ -52,8 +52,15 @@ export namespace WebSite {
}
export interface Domain {
name: string;
websiteId: number;
port: number;
id: number;
domain: string;
}
export interface DomainCreate {
websiteId: number;
port: number;
domain: string;
}
}

View File

@ -37,3 +37,7 @@ export const ListDomains = (id: number) => {
export const DeleteDomain = (id: number) => {
return http.delete<any>(`/websites/domains/${id}`);
};
export const CreateDomain = (req: WebSite.DomainCreate) => {
return http.post<any>(`/websites/domains`, req);
};

View File

@ -0,0 +1,77 @@
<template>
<el-dialog v-model="open" :title="$t('website.create')" width="40%" :before-close="handleClose">
<el-form ref="domainForm" label-position="right" :model="domain" label-width="130px" :rules="rules">
<el-form-item :label="$t('website.domain')" prop="domain">
<el-input v-model="domain.domain"></el-input>
</el-form-item>
<el-form-item :label="$t('website.port')" prop="port">
<el-input v-model.number="domain.port"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
<el-button type="primary" @click="submit(domainForm)" :loading="loading">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { CreateDomain } from '@/api/modules/website';
import { Rules } from '@/global/form-rules';
import i18n from '@/lang';
import { ElMessage, FormInstance } from 'element-plus';
import { ref } from 'vue';
const domainForm = ref<FormInstance>();
let rules = ref({
domain: [Rules.requiredInput],
port: [Rules.requiredInput],
});
let open = ref(false);
let loading = ref(false);
let domain = ref({
websiteId: 0,
domain: '',
port: 80,
});
const em = defineEmits(['close']);
const handleClose = () => {
open.value = false;
em('close', false);
};
const acceptParams = async (websiteId: number) => {
domain.value.websiteId = Number(websiteId);
open.value = true;
};
const submit = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
await formEl.validate((valid) => {
if (!valid) {
return;
}
loading.value = true;
console.log(domain.value);
CreateDomain(domain.value)
.then(() => {
ElMessage.success(i18n.global.t('commons.msg.createSuccess'));
handleClose();
})
.finally(() => {
loading.value = false;
});
});
};
defineExpose({
acceptParams,
});
</script>

View File

@ -1,16 +1,18 @@
<template>
<ComplexTable :data="data" @search="search" v-loading="loading">
<template #toolbar>
<el-button type="primary" plain>{{ $t('website.addDomain') }}</el-button>
<el-button type="primary" plain @click="openCreate">{{ $t('website.addDomain') }}</el-button>
</template>
<el-table-column :label="$t('website.domain')" prop="domain"></el-table-column>
<el-table-column :label="$t('website.port')" prop="port"></el-table-column>
<fu-table-operations :ellipsis="1" :buttons="buttons" :label="$t('commons.table.operate')" fixed="right" fix />
</ComplexTable>
<Domain ref="domainRef" @close="search(id)"></Domain>
</template>
<script lang="ts" setup>
import ComplexTable from '@/components/complex-table/index.vue';
import Domain from './create/index.vue';
import { WebSite } from '@/api/interface/website';
import { DeleteDomain, ListDomains } from '@/api/modules/website';
import { computed, onMounted, ref } from 'vue';
@ -23,13 +25,12 @@ const props = defineProps({
default: 0,
},
});
const id = computed(() => {
return props.id;
});
let loading = ref(false);
const data = ref<WebSite.Domain[]>([]);
const domainRef = ref();
const buttons = [
{
@ -40,6 +41,10 @@ const buttons = [
},
];
const openCreate = () => {
domainRef.value.acceptParams(id.value);
};
const deleteDoamin = async (domainId: number) => {
await useDeleteData(DeleteDomain, domainId, 'commons.msg.delete', loading.value);
search(id.value);