From f77972fa38e9ffc68a884d69f143f395119f0556 Mon Sep 17 00:00:00 2001 From: zhengkunwang223 <31820853+zhengkunwang223@users.noreply.github.com> Date: Wed, 24 May 2023 16:31:18 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20PHP=20=E7=BD=91=E7=AB=99=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E7=A6=81=E7=94=A8=E5=87=BD=E6=95=B0=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=20(#1125)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs https://github.com/1Panel-dev/1Panel/issues/663 --- backend/app/dto/request/website.go | 6 +- backend/app/dto/response/website.go | 3 +- backend/app/service/website.go | 77 ++++++++-- frontend/components.d.ts | 4 +- frontend/src/api/interface/website.ts | 5 +- frontend/src/global/form-rules.ts | 19 +++ frontend/src/lang/modules/en.ts | 3 + frontend/src/lang/modules/zh.ts | 3 + .../website/config/php/config/index.vue | 2 +- .../website/config/php/function/index.vue | 142 ++++++++++++++++++ .../website/website/config/php/index.vue | 10 +- frontend/src/views/website/website/index.vue | 2 +- 12 files changed, 249 insertions(+), 27 deletions(-) create mode 100644 frontend/src/views/website/website/config/php/function/index.vue diff --git a/backend/app/dto/request/website.go b/backend/app/dto/request/website.go index d95a891ae..59597e58d 100644 --- a/backend/app/dto/request/website.go +++ b/backend/app/dto/request/website.go @@ -138,8 +138,10 @@ type WebsiteDefaultUpdate struct { } type WebsitePHPConfigUpdate struct { - ID uint `json:"id" validate:"required"` - Params map[string]string `json:"params" validate:"required"` + ID uint `json:"id" validate:"required"` + Params map[string]string `json:"params"` + Scope string `json:"scope" validate:"required"` + DisableFunctions []string `json:"disableFunctions"` } type WebsitePHPFileUpdate struct { diff --git a/backend/app/dto/response/website.go b/backend/app/dto/response/website.go index 699a53de3..313fb7d77 100644 --- a/backend/app/dto/response/website.go +++ b/backend/app/dto/response/website.go @@ -45,7 +45,8 @@ type WebsiteLog struct { } type PHPConfig struct { - Params map[string]string `json:"params"` + Params map[string]string `json:"params"` + DisableFunctions []string `json:"disableFunctions"` } type NginxRewriteRes struct { diff --git a/backend/app/service/website.go b/backend/app/service/website.go index 562301058..1c43c9df3 100644 --- a/backend/app/service/website.go +++ b/backend/app/service/website.go @@ -16,6 +16,7 @@ import ( "github.com/1Panel-dev/1Panel/backend/utils/nginx/parser" "github.com/1Panel-dev/1Panel/cmd/server/nginx_conf" "golang.org/x/crypto/bcrypt" + "gopkg.in/ini.v1" "gorm.io/gorm" "os" "path" @@ -1009,7 +1010,23 @@ func (w WebsiteService) GetPHPConfig(id uint) (*response.PHPConfig, error) { params[matches[1]] = matches[2] } } - return &response.PHPConfig{Params: params}, nil + cfg, err := ini.Load(phpConfigPath) + if err != nil { + return nil, err + } + phpConfig, err := cfg.GetSection("PHP") + if err != nil { + return nil, err + } + disableFunctionStr := phpConfig.Key("disable_functions").Value() + res := &response.PHPConfig{Params: params} + if disableFunctionStr != "" { + disableFunctions := strings.Split(disableFunctionStr, ",") + if len(disableFunctions) > 0 { + res.DisableFunctions = disableFunctions + } + } + return res, nil } func (w WebsiteService) UpdatePHPConfig(req request.WebsitePHPConfigUpdate) (err error) { @@ -1033,23 +1050,50 @@ func (w WebsiteService) UpdatePHPConfig(req request.WebsitePHPConfigUpdate) (err defer configFile.Close() contentBytes, err := fileOp.GetContent(phpConfigPath) - content := string(contentBytes) - lines := strings.Split(content, "\n") - for i, line := range lines { - if strings.HasPrefix(line, ";") { - continue - } - for key, value := range req.Params { - pattern := "^" + regexp.QuoteMeta(key) + "\\s*=\\s*.*$" - if matched, _ := regexp.MatchString(pattern, line); matched { - lines[i] = key + " = " + value - } - } - } - updatedContent := strings.Join(lines, "\n") - if err := fileOp.WriteFile(phpConfigPath, strings.NewReader(updatedContent), 0755); err != nil { + if err != nil { return err } + + if req.Scope == "params" { + content := string(contentBytes) + lines := strings.Split(content, "\n") + for i, line := range lines { + if strings.HasPrefix(line, ";") { + continue + } + for key, value := range req.Params { + pattern := "^" + regexp.QuoteMeta(key) + "\\s*=\\s*.*$" + if matched, _ := regexp.MatchString(pattern, line); matched { + lines[i] = key + " = " + value + } + } + } + updatedContent := strings.Join(lines, "\n") + if err := fileOp.WriteFile(phpConfigPath, strings.NewReader(updatedContent), 0755); err != nil { + return err + } + } + + cfg, err := ini.Load(phpConfigPath) + if err != nil { + return err + } + phpConfig, err := cfg.GetSection("PHP") + if err != nil { + return err + } + if req.Scope == "disable_functions" { + disable := phpConfig.Key("disable_functions") + disable.SetValue(strings.Join(req.DisableFunctions, ",")) + if err = cfg.SaveTo(phpConfigPath); err != nil { + return err + } + } + if req.Scope == "uploadSize" { + postMaxSize := phpConfig.Key("post_max_size") + postMaxSize.SetValue("") + } + appInstallReq := request.AppInstalledOperate{ InstallId: appInstall.ID, Operate: constant.Restart, @@ -1058,6 +1102,7 @@ func (w WebsiteService) UpdatePHPConfig(req request.WebsitePHPConfigUpdate) (err _ = fileOp.WriteFile(phpConfigPath, strings.NewReader(string(contentBytes)), 0755) return err } + return nil } diff --git a/frontend/components.d.ts b/frontend/components.d.ts index 123cd1dd8..25e7f23ee 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -44,7 +44,7 @@ declare module 'vue' { ElIcon: typeof import('element-plus/es')['ElIcon'] ElImage: typeof import('element-plus/es')['ElImage']; ElInput: typeof import('element-plus/es')['ElInput'] - ElInputNumber: typeof import('element-plus/es')['ElInputNumber']; + ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] ElLink: typeof import('element-plus/es')['ElLink'] ElMain: typeof import('element-plus/es')['ElMain']; ElMenu: typeof import('element-plus/es')['ElMenu'] @@ -76,7 +76,7 @@ declare module 'vue' { FileRole: typeof import('./src/components/file-role/index.vue')['default'] FormButton: typeof import('./src/components/layout-content/form-button.vue')['default'] Group: typeof import('./src/components/group/index.vue')['default'] - InfiniteScroll: typeof import('element-plus/es')['ElInfiniteScroll']; + InfiniteScroll: typeof import('element-plus/es')['ElInfiniteScroll'] LayoutContent: typeof import('./src/components/layout-content/index.vue')['default'] Line: typeof import('./src/components/v-charts/components/Line.vue')['default'] Loading: typeof import('element-plus/es')['ElLoadingDirective'] diff --git a/frontend/src/api/interface/website.ts b/frontend/src/api/interface/website.ts index 00b12473e..8932168bd 100644 --- a/frontend/src/api/interface/website.ts +++ b/frontend/src/api/interface/website.ts @@ -269,11 +269,14 @@ export namespace Website { export interface PHPConfig { params: any; + disableFunctions: string[]; } export interface PHPConfigUpdate { id: number; - params: any; + params?: any; + disableFunctions?: string[]; + scope: string; } export interface PHPUpdate { diff --git a/frontend/src/global/form-rules.ts b/frontend/src/global/form-rules.ts index 198dbb11b..a6e331d63 100644 --- a/frontend/src/global/form-rules.ts +++ b/frontend/src/global/form-rules.ts @@ -277,6 +277,19 @@ const checkConatinerName = (rule: any, value: any, callback: any) => { } }; +const checkDisableFunctions = (rule: any, value: any, callback: any) => { + if (value === '' || typeof value === 'undefined' || value == null) { + callback(new Error(i18n.global.t('commons.rule.disableFunction'))); + } else { + const reg = /^[a-zA-Z,]+$/; + if (!reg.test(value) && value !== '') { + callback(new Error(i18n.global.t('commons.rule.disableFunction'))); + } else { + callback(); + } + } +}; + interface CommonRule { requiredInput: FormItemRule; requiredSelect: FormItemRule; @@ -300,6 +313,7 @@ interface CommonRule { nginxDoc: FormItemRule; appName: FormItemRule; containerName: FormItemRule; + disabledFunctions: FormItemRule; paramCommon: FormItemRule; paramComplexity: FormItemRule; @@ -446,4 +460,9 @@ export const Rules: CommonRule = { trigger: 'blur', validator: checkConatinerName, }, + disabledFunctions: { + required: true, + trigger: 'blur', + validator: checkDisableFunctions, + }, }; diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index da5bd9e55..73229d108 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -159,6 +159,7 @@ const message = { nginxDoc: 'Only supports English case, numbers, and .', appName: 'Support English, numbers, - and _, length 2-30, and cannot start and end with -_', conatinerName: 'Supports letters, numbers, underscores, hyphens and dots, cannot end with hyphen- or dot.', + disableFunction: 'Only support letters and,', }, res: { paramError: 'The request failed, please try again later!', @@ -1384,6 +1385,8 @@ const message = { cgi_fix_pathinfo: 'Whether to open pathinfo', date_timezone: 'Time zone', second: 'Second', + disableFunction: 'Disable function', + disableFunctionHelper: 'Enter the function to be disabled, such as exec, please use multiple, split', }, nginx: { serverNamesHashBucketSizeHelper: 'The hash table size of the server name', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index a30fd742b..1241c2a52 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -162,6 +162,7 @@ const message = { nginxDoc: '仅支持英文大小写,数字,和.', appName: '支持英文、数字、-和_,长度2-30,并且不能以-_开头和结尾', conatinerName: '支持字母、数字、下划线、连字符和点,不能以连字符-或点.结尾', + disableFunction: '仅支持字母和,', }, res: { paramError: '请求失败,请稍后重试!', @@ -1365,6 +1366,8 @@ const message = { cgi_fix_pathinfo: '是否开启pathinfo', date_timezone: '时区', second: '秒', + disableFunction: '禁用函数', + disableFunctionHelper: '输入要禁用的函数,例如exec,多个请用,分割', }, nginx: { serverNamesHashBucketSizeHelper: '服务器名字的hash表大小', diff --git a/frontend/src/views/website/website/config/php/config/index.vue b/frontend/src/views/website/website/config/php/config/index.vue index e78e45063..8f6ef5f3a 100644 --- a/frontend/src/views/website/website/config/php/config/index.vue +++ b/frontend/src/views/website/website/config/php/config/index.vue @@ -184,7 +184,7 @@ const submit = async () => { display_errors: form.display_errors, }; loading.value = true; - UpdatePHPConfig({ id: id.value, params: params }) + UpdatePHPConfig({ id: id.value, params: params, scope: 'params' }) .then(() => { MsgSuccess(i18n.global.t('commons.msg.updateSuccess')); }) diff --git a/frontend/src/views/website/website/config/php/function/index.vue b/frontend/src/views/website/website/config/php/function/index.vue new file mode 100644 index 000000000..62eba6e8f --- /dev/null +++ b/frontend/src/views/website/website/config/php/function/index.vue @@ -0,0 +1,142 @@ + + diff --git a/frontend/src/views/website/website/config/php/index.vue b/frontend/src/views/website/website/config/php/index.vue index 3b66e1afc..9f637acbd 100644 --- a/frontend/src/views/website/website/config/php/index.vue +++ b/frontend/src/views/website/website/config/php/index.vue @@ -3,6 +3,9 @@ + + + @@ -11,6 +14,7 @@ import { GetRuntime } from '@/api/modules/runtime'; import { GetWebsite } from '@/api/modules/website'; import { computed, onMounted, ref } from 'vue'; import Config from './config/index.vue'; +import Function from './function/index.vue'; const props = defineProps({ id: { @@ -23,9 +27,9 @@ const id = computed(() => { return props.id; }); -let index = ref('0'); -let configPHP = ref(false); -let installId = ref(0); +const index = ref('0'); +const configPHP = ref(false); +const installId = ref(0); const getWebsiteDetail = async () => { const res = await GetWebsite(props.id); diff --git a/frontend/src/views/website/website/index.vue b/frontend/src/views/website/website/index.vue index b068b8e6a..11bc9415c 100644 --- a/frontend/src/views/website/website/index.vue +++ b/frontend/src/views/website/website/index.vue @@ -153,7 +153,6 @@ - @@ -161,6 +160,7 @@ +