feat: 增加修改网站默认页面功能 (#5491)

This commit is contained in:
zhengkunwang 2024-06-19 10:17:36 +08:00 committed by GitHub
parent 7e182d32a6
commit 39a5767319
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 416 additions and 48 deletions

View File

@ -778,3 +778,45 @@ func (b *BaseApi) GetDirConfig(c *gin.Context) {
}
helper.SuccessWithData(c, res)
}
// @Tags Website
// @Summary Get default html
// @Description 获取默认 html
// @Accept json
// @Success 200 {object} response.FileInfo
// @Security ApiKeyAuth
// @Router /websites/default/html/:type [get]
func (b *BaseApi) GetDefaultHtml(c *gin.Context) {
resourceType, err := helper.GetStrParamByKey(c, "type")
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil)
return
}
fileInfo, err := websiteService.GetDefaultHtml(resourceType)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, fileInfo)
}
// @Tags Website
// @Summary Update default html
// @Description 更新默认 html
// @Accept json
// @Param request body request.WebsiteHtmlUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /websites/default/html/update [post]
// @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新默认 html","formatEN":"Update default html"}
func (b *BaseApi) UpdateDefaultHtml(c *gin.Context) {
var req request.WebsiteHtmlUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdateDefaultHtml(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithOutData(c)
}

View File

@ -208,3 +208,12 @@ type WafWebsite struct {
Domains []string `json:"domains"`
Host []string `json:"host"`
}
type WebsiteHtmlReq struct {
Type string `json:"type" validate:"required"`
}
type WebsiteHtmlUpdate struct {
Type string `json:"type" validate:"required"`
Content string `json:"content" validate:"required"`
}

View File

@ -82,3 +82,7 @@ type WebsiteDirConfig struct {
UserGroup string `json:"userGroup"`
Msg string `json:"msg"`
}
type WebsiteHtmlRes struct {
Content string `json:"content"`
}

View File

@ -96,6 +96,9 @@ type IWebsiteService interface {
OperateRedirect(req request.NginxRedirectReq) (err error)
GetRedirect(id uint) (res []response.NginxRedirectConfig, err error)
UpdateRedirectFile(req request.NginxRedirectUpdate) (err error)
UpdateDefaultHtml(req request.WebsiteHtmlUpdate) error
GetDefaultHtml(resourceType string) (*response.WebsiteHtmlRes, error)
}
func NewIWebsiteService() IWebsiteService {
@ -2459,3 +2462,91 @@ func (w WebsiteService) LoadWebsiteDirConfig(req request.WebsiteCommonReq) (*res
return res, nil
}
func (w WebsiteService) GetDefaultHtml(resourceType string) (*response.WebsiteHtmlRes, error) {
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return nil, err
}
rootPath := path.Join(nginxInstall.GetPath(), "root")
fileOp := files.NewFileOp()
defaultPath := path.Join(rootPath, "default")
if !fileOp.Stat(defaultPath) {
_ = fileOp.CreateDir(defaultPath, 0755)
}
res := &response.WebsiteHtmlRes{}
switch resourceType {
case "404":
resourcePath := path.Join(defaultPath, "404.html")
if content, _ := getResourceContent(fileOp, resourcePath); content != "" {
res.Content = content
return res, nil
}
res.Content = string(nginx_conf.NotFoundHTML)
return res, nil
case "php":
resourcePath := path.Join(defaultPath, "index.php")
if content, _ := getResourceContent(fileOp, resourcePath); content != "" {
res.Content = content
return res, nil
}
res.Content = string(nginx_conf.IndexPHP)
return res, nil
case "index":
resourcePath := path.Join(defaultPath, "index.html")
if content, _ := getResourceContent(fileOp, resourcePath); content != "" {
res.Content = content
return res, nil
}
res.Content = string(nginx_conf.Index)
return res, nil
case "domain404":
resourcePath := path.Join(rootPath, "404.html")
if content, _ := getResourceContent(fileOp, resourcePath); content != "" {
res.Content = content
return res, nil
}
res.Content = string(nginx_conf.DomainNotFoundHTML)
return res, nil
case "stop":
resourcePath := path.Join(rootPath, "stop", "index.html")
if content, _ := getResourceContent(fileOp, resourcePath); content != "" {
res.Content = content
return res, nil
}
res.Content = string(nginx_conf.StopHTML)
return res, nil
}
return res, nil
}
func (w WebsiteService) UpdateDefaultHtml(req request.WebsiteHtmlUpdate) error {
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return err
}
rootPath := path.Join(nginxInstall.GetPath(), "root")
fileOp := files.NewFileOp()
defaultPath := path.Join(rootPath, "default")
if !fileOp.Stat(defaultPath) {
_ = fileOp.CreateDir(defaultPath, 0755)
}
var resourcePath string
switch req.Type {
case "404":
resourcePath = path.Join(defaultPath, "404.html")
case "php":
resourcePath = path.Join(defaultPath, "index.php")
case "index":
resourcePath = path.Join(defaultPath, "index.html")
case "domain404":
resourcePath = path.Join(rootPath, "404.html")
case "stop":
resourcePath = path.Join(rootPath, "stop", "index.html")
default:
return nil
}
return fileOp.SaveFile(resourcePath, req.Content, 0644)
}

View File

@ -317,7 +317,7 @@ func createWafConfig(website *model.Website, domains []model.WebsiteDomain) erro
for _, domain := range domains {
wafWebsite.Domains = append(wafWebsite.Domains, domain.Domain)
if domain.Port != 80 && domain.Port != 443 {
wafWebsite.Host = append(wafWebsite.Host, domain.Domain+":"+string(rune(domain.Port)))
wafWebsite.Host = append(wafWebsite.Host, domain.Domain+":"+strconv.Itoa(domain.Port))
}
}
websitesArray = append(websitesArray, wafWebsite)
@ -1092,3 +1092,14 @@ func checkSSLStatus(expireDate time.Time) string {
}
return "success"
}
func getResourceContent(fileOp files.FileOp, resourcePath string) (string, error) {
if fileOp.Stat(resourcePath) {
content, err := fileOp.GetContent(resourcePath)
if err != nil {
return "", err
}
return string(content), nil
}
return "", nil
}

View File

@ -10,59 +10,62 @@ type WebsiteRouter struct {
}
func (a *WebsiteRouter) InitRouter(Router *gin.RouterGroup) {
groupRouter := Router.Group("websites")
groupRouter.Use(middleware.JwtAuth()).Use(middleware.SessionAuth()).Use(middleware.PasswordExpired())
websiteRouter := Router.Group("websites")
websiteRouter.Use(middleware.JwtAuth()).Use(middleware.SessionAuth()).Use(middleware.PasswordExpired())
baseApi := v1.ApiGroupApp.BaseApi
{
groupRouter.POST("/search", baseApi.PageWebsite)
groupRouter.GET("/list", baseApi.GetWebsites)
groupRouter.POST("", baseApi.CreateWebsite)
groupRouter.POST("/operate", baseApi.OpWebsite)
groupRouter.POST("/log", baseApi.OpWebsiteLog)
groupRouter.POST("/check", baseApi.CreateWebsiteCheck)
groupRouter.GET("/options", baseApi.GetWebsiteOptions)
groupRouter.POST("/update", baseApi.UpdateWebsite)
groupRouter.GET("/:id", baseApi.GetWebsite)
groupRouter.POST("/del", baseApi.DeleteWebsite)
groupRouter.POST("/default/server", baseApi.ChangeDefaultServer)
websiteRouter.POST("/search", baseApi.PageWebsite)
websiteRouter.GET("/list", baseApi.GetWebsites)
websiteRouter.POST("", baseApi.CreateWebsite)
websiteRouter.POST("/operate", baseApi.OpWebsite)
websiteRouter.POST("/log", baseApi.OpWebsiteLog)
websiteRouter.POST("/check", baseApi.CreateWebsiteCheck)
websiteRouter.GET("/options", baseApi.GetWebsiteOptions)
websiteRouter.POST("/update", baseApi.UpdateWebsite)
websiteRouter.GET("/:id", baseApi.GetWebsite)
websiteRouter.POST("/del", baseApi.DeleteWebsite)
websiteRouter.POST("/default/server", baseApi.ChangeDefaultServer)
groupRouter.GET("/domains/:websiteId", baseApi.GetWebDomains)
groupRouter.POST("/domains/del", baseApi.DeleteWebDomain)
groupRouter.POST("/domains", baseApi.CreateWebDomain)
websiteRouter.GET("/domains/:websiteId", baseApi.GetWebDomains)
websiteRouter.POST("/domains/del", baseApi.DeleteWebDomain)
websiteRouter.POST("/domains", baseApi.CreateWebDomain)
groupRouter.GET("/:id/config/:type", baseApi.GetWebsiteNginx)
groupRouter.POST("/config", baseApi.GetNginxConfig)
groupRouter.POST("/config/update", baseApi.UpdateNginxConfig)
groupRouter.POST("/nginx/update", baseApi.UpdateWebsiteNginxConfig)
websiteRouter.GET("/:id/config/:type", baseApi.GetWebsiteNginx)
websiteRouter.POST("/config", baseApi.GetNginxConfig)
websiteRouter.POST("/config/update", baseApi.UpdateNginxConfig)
websiteRouter.POST("/nginx/update", baseApi.UpdateWebsiteNginxConfig)
groupRouter.GET("/:id/https", baseApi.GetHTTPSConfig)
groupRouter.POST("/:id/https", baseApi.UpdateHTTPSConfig)
websiteRouter.GET("/:id/https", baseApi.GetHTTPSConfig)
websiteRouter.POST("/:id/https", baseApi.UpdateHTTPSConfig)
groupRouter.GET("/php/config/:id", baseApi.GetWebsitePHPConfig)
groupRouter.POST("/php/config", baseApi.UpdateWebsitePHPConfig)
groupRouter.POST("/php/update", baseApi.UpdatePHPFile)
groupRouter.POST("/php/version", baseApi.ChangePHPVersion)
websiteRouter.GET("/php/config/:id", baseApi.GetWebsitePHPConfig)
websiteRouter.POST("/php/config", baseApi.UpdateWebsitePHPConfig)
websiteRouter.POST("/php/update", baseApi.UpdatePHPFile)
websiteRouter.POST("/php/version", baseApi.ChangePHPVersion)
groupRouter.POST("/rewrite", baseApi.GetRewriteConfig)
groupRouter.POST("/rewrite/update", baseApi.UpdateRewriteConfig)
websiteRouter.POST("/rewrite", baseApi.GetRewriteConfig)
websiteRouter.POST("/rewrite/update", baseApi.UpdateRewriteConfig)
groupRouter.POST("/dir/update", baseApi.UpdateSiteDir)
groupRouter.POST("/dir/permission", baseApi.UpdateSiteDirPermission)
groupRouter.POST("/dir", baseApi.GetDirConfig)
websiteRouter.POST("/dir/update", baseApi.UpdateSiteDir)
websiteRouter.POST("/dir/permission", baseApi.UpdateSiteDirPermission)
websiteRouter.POST("/dir", baseApi.GetDirConfig)
groupRouter.POST("/proxies", baseApi.GetProxyConfig)
groupRouter.POST("/proxies/update", baseApi.UpdateProxyConfig)
groupRouter.POST("/proxies/file", baseApi.UpdateProxyConfigFile)
websiteRouter.POST("/proxies", baseApi.GetProxyConfig)
websiteRouter.POST("/proxies/update", baseApi.UpdateProxyConfig)
websiteRouter.POST("/proxies/file", baseApi.UpdateProxyConfigFile)
groupRouter.POST("/auths", baseApi.GetAuthConfig)
groupRouter.POST("/auths/update", baseApi.UpdateAuthConfig)
websiteRouter.POST("/auths", baseApi.GetAuthConfig)
websiteRouter.POST("/auths/update", baseApi.UpdateAuthConfig)
groupRouter.POST("/leech", baseApi.GetAntiLeech)
groupRouter.POST("/leech/update", baseApi.UpdateAntiLeech)
websiteRouter.POST("/leech", baseApi.GetAntiLeech)
websiteRouter.POST("/leech/update", baseApi.UpdateAntiLeech)
groupRouter.POST("/redirect/update", baseApi.UpdateRedirectConfig)
groupRouter.POST("/redirect", baseApi.GetRedirectConfig)
groupRouter.POST("/redirect/file", baseApi.UpdateRedirectConfigFile)
websiteRouter.POST("/redirect/update", baseApi.UpdateRedirectConfig)
websiteRouter.POST("/redirect", baseApi.GetRedirectConfig)
websiteRouter.POST("/redirect/file", baseApi.UpdateRedirectConfigFile)
websiteRouter.GET("/default/html/:type", baseApi.GetDefaultHtml)
websiteRouter.POST("/default/html/update", baseApi.UpdateDefaultHtml)
}
}

View File

@ -0,0 +1,6 @@
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>

View File

@ -0,0 +1,6 @@
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>

View File

@ -28,3 +28,12 @@ var Proxy []byte
//go:embed proxy_cache.conf
var ProxyCache []byte
//go:embed 404.html
var NotFoundHTML []byte
//go:embed domain404.html
var DomainNotFoundHTML []byte
//go:embed stop.html
var StopHTML []byte

View File

@ -0,0 +1,33 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>抱歉站点已暂停</title>
<style>
html,body,div,h1,*{margin:0;padding:0;}
body{
background-color:#fefefe;
color:#333
}
.box{
width:580px;
margin:0 auto;
}
h1{
font-size:20px;
text-align:center;
background:url(data:image/png;base64,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) no-repeat top center;
padding-top:160px;
margin-top:30%;
font-weight:normal;
}
</style>
</head>
<body>
<div class="box">
<h1>抱歉该站点已经被管理员停止运行请联系管理员了解详情</h1>
</div>
</body>
</html>

View File

@ -20,7 +20,9 @@
"prettier": "prettier --write ."
},
"dependencies": {
"@codemirror/lang-html": "^6.4.9",
"@codemirror/lang-javascript": "^6.2.2",
"@codemirror/lang-php": "^6.0.1",
"@codemirror/language": "^6.10.2",
"@codemirror/legacy-modes": "^6.4.0",
"@codemirror/theme-one-dark": "^6.1.2",
@ -30,6 +32,7 @@
"@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.5.0",
"axios": "^1.7.2",
"codemirror": "^6.0.1",
"echarts": "^5.5.0",
"element-plus": "^2.7.5",
"fit2cloud-ui-plus": "^1.1.4",

View File

@ -519,4 +519,12 @@ export namespace Website {
export interface SSLDownload {
id: number;
}
export interface WebsiteHtml {
content: string;
}
export interface WebsiteHtmlUpdate {
type: string;
content: string;
}
}

View File

@ -268,3 +268,11 @@ export const DownloadFile = (params: Website.SSLDownload) => {
export const GetCA = (id: number) => {
return http.get<Website.CADTO>(`/websites/ca/${id}`);
};
export const GetDefaultHtml = (type: string) => {
return http.get<Website.WebsiteHtml>(`/websites/default/html/${type}`);
};
export const UpdateDefaultHtml = (req: Website.WebsiteHtmlUpdate) => {
return http.post(`/websites/default/html/update`, req);
};

View File

@ -2032,6 +2032,12 @@ const message = {
'Only supports importing local backups, importing backups from other machines may cause recovery failure',
ipWebsiteWarn: 'Websites with IP as domain names need to be set as default sites to be accessed normally',
hstsHelper: 'Enabling HSTS can increase website security',
defaultHtml: 'Default page',
website404: 'Website 404 error page',
domain404: 'Website page does not exist',
indexHtml: 'Static website default page',
stopHtml: 'Website stop page',
indePhp: 'PHP website default page',
sslExpireDate: 'Certificate expiration date',
},
php: {

View File

@ -1891,6 +1891,12 @@ const message = {
websiteBackupWarn: '僅支援導入本機備份導入其他機器備份可能會恢復失敗',
ipWebsiteWarn: 'IP 為網域名稱的網站需要設定為預設網站才能正常存取',
hstsHelper: '開啟 HSTS 可以增加網站安全性',
defaultHtml: '預設頁面',
website404: '網站 404 錯誤頁',
domain404: '網站不存在頁面',
indexHtml: '靜態網站預設頁',
stopHtml: '網站停用頁',
indePhp: 'PHP 網站預設頁',
sslExpireDate: '憑證過期時間',
},
php: {

View File

@ -1893,6 +1893,12 @@ const message = {
websiteBackupWarn: '仅支持导入本机备份导入其他机器备份可能会恢复失败',
ipWebsiteWarn: 'IP 为域名的网站需要设置为默认站点才能正常访问',
hstsHelper: '开启 HSTS 可以增加网站安全性',
defaultHtml: '默认页面',
website404: '网站 404 错误页',
domain404: '网站不存在页',
indexHtml: '静态网站默认页',
stopHtml: '网站停用页',
indePhp: 'PHP 网站默认页',
sslExpireDate: '证书过期时间',
},
php: {

View File

@ -0,0 +1,107 @@
<template>
<el-drawer :close-on-click-modal="false" :close-on-press-escape="false" v-model="open" size="40%">
<template #header>
<DrawerHeader :header="$t('website.defaultServer')" :back="handleClose"></DrawerHeader>
</template>
<el-row v-loading="loading">
<el-col :span="22" :offset="1">
<el-select v-model="type" class="w-full" @change="get()">
<el-option :value="'404'" :label="$t('website.website404')"></el-option>
<el-option :value="'domain404'" :label="$t('website.domain404')"></el-option>
<el-option :value="'index'" :label="$t('website.indexHtml')"></el-option>
<el-option :value="'php'" :label="$t('website.indePhp')"></el-option>
<el-option :value="'stop'" :label="$t('website.stopHtml')"></el-option>
</el-select>
<div ref="htmlRef" class="default-html"></div>
</el-col>
</el-row>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
<el-button type="primary" @click="submit()" :disabled="loading">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
</template>
</el-drawer>
</template>
<script lang="ts" setup>
import DrawerHeader from '@/components/drawer-header/index.vue';
import { UpdateDefaultHtml, GetDefaultHtml } from '@/api/modules/website';
import i18n from '@/lang';
import { ref } from 'vue';
import { MsgSuccess } from '@/utils/message';
import { EditorState } from '@codemirror/state';
import { basicSetup, EditorView } from 'codemirror';
import { html } from '@codemirror/lang-html';
import { php } from '@codemirror/lang-php';
import { oneDark } from '@codemirror/theme-one-dark';
let open = ref(false);
let loading = ref(false);
const content = ref('');
const type = ref('404');
const view = ref();
const htmlRef = ref();
const acceptParams = () => {
type.value = '404';
get();
open.value = true;
};
const handleClose = () => {
open.value = false;
};
const get = async () => {
const res = await GetDefaultHtml(type.value);
content.value = res.data.content;
initEditor();
};
const initEditor = () => {
if (view.value) {
view.value.destroy();
}
let extensions = [basicSetup, oneDark];
if (type.value === 'php') {
extensions.push(php());
} else {
extensions.push(html());
}
const startState = EditorState.create({
doc: content.value,
extensions: extensions,
});
if (htmlRef.value) {
view.value = new EditorView({
state: startState,
parent: htmlRef.value,
});
}
};
const submit = async () => {
loading.value = true;
try {
const content = view.value.state.doc.toString();
await UpdateDefaultHtml({ type: type.value, content: content });
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
handleClose();
} catch (error) {
} finally {
loading.value = false;
}
};
defineExpose({ acceptParams });
</script>
<style scoped lang="scss">
.default-html {
width: 100%;
min-height: 300px;
margin-top: 20px;
}
</style>

View File

@ -30,6 +30,9 @@
<el-button type="primary" plain @click="openDefault">
{{ $t('website.defaultServer') }}
</el-button>
<el-button type="primary" plain @click="openDefaultHtml">
{{ $t('website.defaultHtml') }}
</el-button>
</el-col>
<el-col :xs="24" :sm="4" :md="4" :lg="4" :xl="4">
<TableSearch @search="search()" v-model:searchName="req.name" />
@ -182,6 +185,7 @@
<DefaultServer ref="defaultRef" />
<GroupDialog @search="listGroup" ref="groupRef" />
<NginxConfig v-if="openNginxConfig" v-loading="loading" :containerName="containerName" :status="nginxStatus" />
<DefaultHtml ref="defaultHtmlRef" />
</div>
</template>
@ -189,16 +193,17 @@
import Backups from '@/components/backup/index.vue';
import UploadDialog from '@/components/upload/index.vue';
import DefaultServer from '@/views/website/website/default/index.vue';
import { onMounted, reactive, ref, computed } from '@vue/runtime-core';
import CreateWebSite from './create/index.vue';
import DeleteWebsite from './delete/index.vue';
import DefaultHtml from '@/views/website/website/html/index.vue';
import CreateWebSite from '@/views/website/website/create/index.vue';
import DeleteWebsite from '@/views/website/website/delete/index.vue';
import NginxConfig from '@/views/website/website/nginx/index.vue';
import GroupDialog from '@/components/group/index.vue';
import { OpWebsite, SearchWebsites, UpdateWebsite } from '@/api/modules/website';
import { Website } from '@/api/interface/website';
import AppStatus from '@/components/app-status/index.vue';
import NginxConfig from './nginx/index.vue';
import i18n from '@/lang';
import router from '@/routers';
import { onMounted, reactive, ref, computed } from '@vue/runtime-core';
import { OpWebsite, SearchWebsites, UpdateWebsite } from '@/api/modules/website';
import { Website } from '@/api/interface/website';
import { App } from '@/api/interface/app';
import { ElMessageBox } from 'element-plus';
import { dateFormatSimple } from '@/utils/util';
@ -232,6 +237,7 @@ const maskShow = ref(true);
const createRef = ref();
const deleteRef = ref();
const groupRef = ref();
const defaultHtmlRef = ref();
const openNginxConfig = ref(false);
const nginxIsExist = ref(false);
const containerName = ref('');
@ -418,6 +424,10 @@ const openDefault = () => {
defaultRef.value.acceptParams();
};
const openDefaultHtml = () => {
defaultHtmlRef.value.acceptParams();
};
const checkExist = (data: App.CheckInstalled) => {
nginxIsExist.value = data.isExist;
containerName.value = data.containerName;