mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 08:19:15 +08:00
feat: 增加nginx文件编辑功能
This commit is contained in:
parent
7c6e96e10e
commit
55aed7943e
@ -0,0 +1,21 @@
|
||||
{
|
||||
"formFields": [
|
||||
{
|
||||
"type": "number",
|
||||
"labelZh": "Http 端口",
|
||||
"labelEn": "Http Port",
|
||||
"required": true,
|
||||
"default": 80,
|
||||
"envKey": "PANEL_APP_PORT_HTTP"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"labelZh": "Https 端口",
|
||||
"labelEn": "Https Port",
|
||||
"required": true,
|
||||
"default": 443,
|
||||
"envKey": "PANEL_APP_PORT_HTTPS"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
services:
|
||||
nginx1.23.1:
|
||||
container_name: ${CONTAINER_NAME}
|
||||
image: nginx:1.23.1
|
||||
restart: always
|
||||
networks:
|
||||
- 1panel
|
||||
ports:
|
||||
- ${PANEL_APP_PORT_HTTP}:80
|
||||
- ${PANEL_APP_PORT_HTTPS}:443
|
||||
volumes:
|
||||
- ./conf/nginx.conf:/etc/nginx/nginx.conf
|
||||
- ./log:/var/log/nginx
|
||||
- ./conf/conf.d:/etc/nginx/conf.d/
|
||||
- ./ssl:/etc/nginx/ssl
|
||||
|
||||
networks:
|
||||
1panel:
|
||||
external: true
|
@ -9,7 +9,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/captcha"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/qqwry"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@ -115,12 +114,12 @@ func saveLoginLogs(c *gin.Context, err error) {
|
||||
logs.Status = constant.StatusSuccess
|
||||
}
|
||||
logs.IP = c.ClientIP()
|
||||
qqWry, err := qqwry.NewQQwry()
|
||||
if err != nil {
|
||||
global.LOG.Errorf("load qqwry datas failed: %s", err)
|
||||
}
|
||||
res := qqWry.Find(logs.IP)
|
||||
logs.Agent = c.GetHeader("User-Agent")
|
||||
logs.Address = res.Area
|
||||
_ = logService.CreateLoginLog(logs)
|
||||
//qqWry, err := qqwry.NewQQwry()
|
||||
//if err != nil {
|
||||
// global.LOG.Errorf("load qqwry datas failed: %s", err)
|
||||
//}
|
||||
//res := qqWry.Find(logs.IP)
|
||||
//logs.Agent = c.GetHeader("User-Agent")
|
||||
//logs.Address = res.Area
|
||||
//_ = logService.CreateLoginLog(logs)
|
||||
}
|
||||
|
@ -80,6 +80,21 @@ func (b *BaseApi) GetWebSite(c *gin.Context) {
|
||||
helper.SuccessWithData(c, website)
|
||||
}
|
||||
|
||||
func (b *BaseApi) GetWebSiteNginx(c *gin.Context) {
|
||||
|
||||
id, err := helper.GetParamID(c)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil)
|
||||
return
|
||||
}
|
||||
fileInfo, err := websiteService.GetWebsiteNginxConfig(id)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, fileInfo)
|
||||
}
|
||||
|
||||
func (b *BaseApi) GetWebDomains(c *gin.Context) {
|
||||
|
||||
websiteId, err := helper.GetIntParamByKey(c, "websiteId")
|
||||
|
@ -4,18 +4,16 @@ import "time"
|
||||
|
||||
type WebSite struct {
|
||||
BaseModel
|
||||
PrimaryDomain string `gorm:"type:varchar(128);not null" json:"primaryDomain"`
|
||||
Type string `gorm:"type:varchar(64);not null" json:"type"`
|
||||
Alias string `gorm:"type:varchar(128);not null" json:"alias"`
|
||||
Remark string `gorm:"type:longtext;" json:"remark"`
|
||||
Status string `gorm:"type:varchar(64);not null" json:"status"`
|
||||
ExpireDate time.Time `json:"expireDate"`
|
||||
AppInstallID uint `gorm:"type:integer" json:"appInstallId"`
|
||||
WebSiteGroupID uint `gorm:"type:integer" json:"webSiteGroupId"`
|
||||
WebSiteSSLID uint `gorm:"type:integer" json:"webSiteSSLId"`
|
||||
WebsiteDnsAccountID uint `gorm:"type:integer" json:"websiteDnsAccountId"`
|
||||
WebsiteAcmeAccountID uint `gorm:"type:integer" json:"websiteAcmeAccountId"`
|
||||
Domains []WebSiteDomain `json:"domains"`
|
||||
PrimaryDomain string `gorm:"type:varchar(128);not null" json:"primaryDomain"`
|
||||
Type string `gorm:"type:varchar(64);not null" json:"type"`
|
||||
Alias string `gorm:"type:varchar(128);not null" json:"alias"`
|
||||
Remark string `gorm:"type:longtext;" json:"remark"`
|
||||
Status string `gorm:"type:varchar(64);not null" json:"status"`
|
||||
ExpireDate time.Time `json:"expireDate"`
|
||||
AppInstallID uint `gorm:"type:integer" json:"appInstallId"`
|
||||
WebSiteGroupID uint `gorm:"type:integer" json:"webSiteGroupId"`
|
||||
WebSiteSSLID uint `gorm:"type:integer" json:"webSiteSSLId"`
|
||||
Domains []WebSiteDomain `json:"domains"`
|
||||
}
|
||||
|
||||
func (w WebSite) TableName() string {
|
||||
|
@ -6,8 +6,10 @@ import (
|
||||
"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/files"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
"path"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
@ -61,6 +63,9 @@ func (w WebsiteService) CreateWebsite(create dto.WebSiteCreate) error {
|
||||
|
||||
otherDomainArray := strings.Split(create.OtherDomains, "\n")
|
||||
for _, domain := range otherDomainArray {
|
||||
if domain == "" {
|
||||
continue
|
||||
}
|
||||
domainModel, err := getDomain(domain, website.ID)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
@ -239,3 +244,30 @@ func (w WebsiteService) UpdateNginxConfigByScope(req dto.NginxConfigReq) error {
|
||||
|
||||
return updateNginxConfig(website, getNginxParams(req.Params, keys), req.Scope)
|
||||
}
|
||||
|
||||
func (w WebsiteService) GetWebsiteNginxConfig(websiteId uint) (dto.FileInfo, error) {
|
||||
website, err := websiteRepo.GetFirst(commonRepo.WithByID(websiteId))
|
||||
if err != nil {
|
||||
return dto.FileInfo{}, err
|
||||
}
|
||||
|
||||
nginxApp, err := appRepo.GetFirst(appRepo.WithKey("nginx"))
|
||||
if err != nil {
|
||||
return dto.FileInfo{}, err
|
||||
}
|
||||
nginxInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithAppId(nginxApp.ID))
|
||||
if err != nil {
|
||||
return dto.FileInfo{}, err
|
||||
}
|
||||
|
||||
configPath := path.Join(constant.AppInstallDir, "nginx", nginxInstall.Name, "conf", "conf.d", website.Alias+".conf")
|
||||
|
||||
info, err := files.NewFileInfo(files.FileOption{
|
||||
Path: configPath,
|
||||
Expand: true,
|
||||
})
|
||||
if err != nil {
|
||||
return dto.FileInfo{}, err
|
||||
}
|
||||
return dto.FileInfo{FileInfo: *info}, nil
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ func (a *WebsiteRouter) InitWebsiteRouter(Router *gin.RouterGroup) {
|
||||
groupRouter.POST("", baseApi.CreateWebsite)
|
||||
groupRouter.POST("/update", baseApi.UpdateWebSite)
|
||||
groupRouter.GET("/:id", baseApi.GetWebSite)
|
||||
groupRouter.GET("/:id/nginx", baseApi.GetWebSiteNginx)
|
||||
groupRouter.POST("/search", baseApi.PageWebsite)
|
||||
groupRouter.POST("/del", baseApi.DeleteWebSite)
|
||||
groupRouter.GET("/domains/:websiteId", baseApi.GetWebDomains)
|
||||
|
@ -1,6 +1,7 @@
|
||||
import http from '@/api';
|
||||
import { ReqPage, ResPage } from '../interface';
|
||||
import { WebSite } from '../interface/website';
|
||||
import { File } from '../interface/file';
|
||||
|
||||
export const SearchWebSites = (req: WebSite.WebSiteSearch) => {
|
||||
return http.post<ResPage<WebSite.WebSite>>(`/websites/search`, req);
|
||||
@ -18,6 +19,10 @@ export const GetWebsite = (id: number) => {
|
||||
return http.get<WebSite.WebSiteDTO>(`/websites/${id}`);
|
||||
};
|
||||
|
||||
export const GetWebsiteNginx = (id: number) => {
|
||||
return http.get<File.File>(`/websites/${id}/nginx`);
|
||||
};
|
||||
|
||||
export const DeleteWebsite = (req: WebSite.WebSiteDel) => {
|
||||
return http.post<any>(`/websites/del`, req);
|
||||
};
|
||||
|
@ -8,7 +8,9 @@
|
||||
<Safety :key="id" :id="id" v-if="index === 'safety'"></Safety>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="备份">反代</el-tab-pane>
|
||||
<el-tab-pane label="源文">反代</el-tab-pane>
|
||||
<el-tab-pane label="源文" name="resource">
|
||||
<Resource :key="id" :id="id" v-if="index === 'resource'"></Resource>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</LayoutContent>
|
||||
</template>
|
||||
@ -18,6 +20,7 @@ import LayoutContent from '@/layout/layout-content.vue';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import Basic from './basic/index.vue';
|
||||
import Safety from './safety/index.vue';
|
||||
import Resource from './resource/index.vue';
|
||||
import router from '@/routers';
|
||||
|
||||
const props = defineProps({
|
||||
|
25
frontend/src/views/website/website/config/resource/index.vue
Normal file
25
frontend/src/views/website/website/config/resource/index.vue
Normal file
@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<el-tabs tab-position="left" type="border-card" v-model="index">
|
||||
<el-tab-pane :label="'Nginx'">
|
||||
<Nginx :id="id"></Nginx>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import Nginx from './nginx/index.vue';
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
});
|
||||
|
||||
const id = computed(() => {
|
||||
return props.id;
|
||||
});
|
||||
|
||||
let index = ref('0');
|
||||
</script>
|
@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<div>
|
||||
<codemirror
|
||||
:autofocus="true"
|
||||
placeholder="None data"
|
||||
:indent-with-tab="true"
|
||||
:tabSize="4"
|
||||
style="margin-top: 10px; max-height: 500px"
|
||||
:lineWrapping="true"
|
||||
:matchBrackets="true"
|
||||
theme="cobalt"
|
||||
:styleActiveLine="true"
|
||||
:extensions="extensions"
|
||||
v-model="content"
|
||||
:readOnly="true"
|
||||
/>
|
||||
<div style="float: right; margin-top: 10px">
|
||||
<el-button type="primary" @click="submit()" :loading="loading">
|
||||
{{ $t('commons.button.save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { Codemirror } from 'vue-codemirror';
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { oneDark } from '@codemirror/theme-one-dark';
|
||||
import { GetWebsiteNginx } from '@/api/modules/website';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { File } from '@/api/interface/file';
|
||||
import { SaveFileContent } from '@/api/modules/files';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import i18n from '@/lang';
|
||||
|
||||
const extensions = [javascript(), oneDark];
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
});
|
||||
|
||||
const id = computed(() => {
|
||||
return props.id;
|
||||
});
|
||||
|
||||
let data = ref<File.File>();
|
||||
let loading = ref(false);
|
||||
let content = ref('');
|
||||
|
||||
const get = () => {
|
||||
loading.value = true;
|
||||
GetWebsiteNginx(id.value)
|
||||
.then((res) => {
|
||||
data.value = res.data;
|
||||
content.value = data.value.content;
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const submit = () => {
|
||||
loading.value = true;
|
||||
SaveFileContent({
|
||||
path: data.value.path,
|
||||
content: content.value,
|
||||
})
|
||||
.then(() => {
|
||||
ElMessage.success(i18n.global.t('commons.msg.updateSuccess'));
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
get();
|
||||
});
|
||||
</script>
|
Loading…
x
Reference in New Issue
Block a user