mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-10-11 07:55:59 +08:00
feat: add openBaseDir for php website config (#8866)
This commit is contained in:
parent
a4d63434cb
commit
71d92c30e3
17 changed files with 127 additions and 22 deletions
|
@ -1101,3 +1101,23 @@ func (b *BaseApi) ClearProxyCache(c *gin.Context) {
|
||||||
}
|
}
|
||||||
helper.Success(c)
|
helper.Success(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Tags Website
|
||||||
|
// @Summary Operate Cross Site Access
|
||||||
|
// @Accept json
|
||||||
|
// @Param request body request.CrossSiteAccessOp true "request"
|
||||||
|
// @Success 200
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Security Timestamp
|
||||||
|
// @Router /websites/crosssite [post]
|
||||||
|
func (b *BaseApi) OperateCrossSiteAccess(c *gin.Context) {
|
||||||
|
var req request.CrossSiteAccessOp
|
||||||
|
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := websiteService.OperateCrossSiteAccess(req); err != nil {
|
||||||
|
helper.InternalServer(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.Success(c)
|
||||||
|
}
|
||||||
|
|
|
@ -289,3 +289,8 @@ type WebsiteProxyDel struct {
|
||||||
ID uint `json:"id" validate:"required"`
|
ID uint `json:"id" validate:"required"`
|
||||||
Name string `json:"name" validate:"required"`
|
Name string `json:"name" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CrossSiteAccessOp struct {
|
||||||
|
WebsiteID uint `json:"websiteID" validate:"required"`
|
||||||
|
Operation string `json:"operation" validate:"required,oneof=Enable Disable"`
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ type WebsiteDTO struct {
|
||||||
RuntimeName string `json:"runtimeName"`
|
RuntimeName string `json:"runtimeName"`
|
||||||
RuntimeType string `json:"runtimeType"`
|
RuntimeType string `json:"runtimeType"`
|
||||||
SiteDir string `json:"siteDir"`
|
SiteDir string `json:"siteDir"`
|
||||||
|
OpenBaseDir bool `json:"openBaseDir"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebsiteRes struct {
|
type WebsiteRes struct {
|
||||||
|
|
|
@ -124,6 +124,8 @@ type IWebsiteService interface {
|
||||||
GetWebsiteResource(websiteID uint) ([]response.Resource, error)
|
GetWebsiteResource(websiteID uint) ([]response.Resource, error)
|
||||||
ListDatabases() ([]response.Database, error)
|
ListDatabases() ([]response.Database, error)
|
||||||
ChangeDatabase(req request.ChangeDatabase) error
|
ChangeDatabase(req request.ChangeDatabase) error
|
||||||
|
|
||||||
|
OperateCrossSiteAccess(req request.CrossSiteAccessOp) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIWebsiteService() IWebsiteService {
|
func NewIWebsiteService() IWebsiteService {
|
||||||
|
@ -428,7 +430,7 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if runtime.Type == constant.RuntimePHP && runtime.Resource == constant.ResourceAppstore {
|
if runtime.Type == constant.RuntimePHP && runtime.Resource == constant.ResourceAppstore {
|
||||||
createPHPConfig(website)
|
createOpenBasedirConfig(website)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tx, ctx := helper.GetTxAndContext()
|
tx, ctx := helper.GetTxAndContext()
|
||||||
|
@ -573,6 +575,9 @@ func (w WebsiteService) GetWebsite(id uint) (response.WebsiteDTO, error) {
|
||||||
}
|
}
|
||||||
res.RuntimeType = runtime.Type
|
res.RuntimeType = runtime.Type
|
||||||
res.RuntimeName = runtime.Name
|
res.RuntimeName = runtime.Name
|
||||||
|
if runtime.Type == constant.RuntimePHP {
|
||||||
|
res.OpenBaseDir = files.NewFileOp().Stat(path.Join(GetSitePath(website, SiteIndexDir), ".user.ini"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
@ -3278,3 +3283,18 @@ func (w WebsiteService) ChangeDatabase(req request.ChangeDatabase) error {
|
||||||
website.DbType = req.DatabaseType
|
website.DbType = req.DatabaseType
|
||||||
return websiteRepo.Save(context.Background(), &website)
|
return websiteRepo.Save(context.Background(), &website)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w WebsiteService) OperateCrossSiteAccess(req request.CrossSiteAccessOp) error {
|
||||||
|
website, err := websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if req.Operation == constant.StatusEnable {
|
||||||
|
createOpenBasedirConfig(&website)
|
||||||
|
}
|
||||||
|
if req.Operation == constant.StatusDisable {
|
||||||
|
fileOp := files.NewFileOp()
|
||||||
|
return fileOp.DeleteFile(path.Join(GetSitePath(website, SiteIndexDir), ".user.ini"))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -349,11 +349,11 @@ func createAllWebsitesWAFConfig(websites []model.Website) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createPHPConfig(website *model.Website) {
|
func createOpenBasedirConfig(website *model.Website) {
|
||||||
fileOp := files.NewFileOp()
|
fileOp := files.NewFileOp()
|
||||||
userIniPath := path.Join(GetSitePath(*website, SiteIndexDir), ".user.ini")
|
userIniPath := path.Join(GetSitePath(*website, SiteIndexDir), ".user.ini")
|
||||||
_ = fileOp.CreateFile(userIniPath)
|
_ = fileOp.CreateFile(userIniPath)
|
||||||
_ = fileOp.SaveFile(userIniPath, fmt.Sprintf("open_basedir=/www/sites/%s/index", website.Alias), 0644)
|
_ = fileOp.SaveFile(userIniPath, fmt.Sprintf("open_basedir=/www/sites/%s/index:/tmp/", website.Alias), 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createWafConfig(website *model.Website, domains []model.WebsiteDomain) error {
|
func createWafConfig(website *model.Website, domains []model.WebsiteDomain) error {
|
||||||
|
|
|
@ -84,5 +84,7 @@ func (a *WebsiteRouter) InitRouter(Router *gin.RouterGroup) {
|
||||||
websiteRouter.GET("/resource/:id", baseApi.GetWebsiteResource)
|
websiteRouter.GET("/resource/:id", baseApi.GetWebsiteResource)
|
||||||
websiteRouter.GET("/databases", baseApi.GetWebsiteDatabase)
|
websiteRouter.GET("/databases", baseApi.GetWebsiteDatabase)
|
||||||
websiteRouter.POST("/databases", baseApi.ChangeWebsiteDatabase)
|
websiteRouter.POST("/databases", baseApi.ChangeWebsiteDatabase)
|
||||||
|
|
||||||
|
websiteRouter.POST("/crosssite", baseApi.OperateCrossSiteAccess)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ export namespace Website {
|
||||||
appName: string;
|
appName: string;
|
||||||
runtimeName: string;
|
runtimeName: string;
|
||||||
runtimeType: string;
|
runtimeType: string;
|
||||||
|
openBaseDir: boolean;
|
||||||
}
|
}
|
||||||
export interface WebsiteRes extends CommonModel {
|
export interface WebsiteRes extends CommonModel {
|
||||||
protocol: string;
|
protocol: string;
|
||||||
|
@ -646,4 +647,9 @@ export namespace Website {
|
||||||
databaseID: number;
|
databaseID: number;
|
||||||
databaseType: string;
|
databaseType: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CrossSiteAccessOp {
|
||||||
|
websiteID: number;
|
||||||
|
operation: string;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -343,3 +343,7 @@ export const operateCustomRewrite = (req: Website.CustomRewirte) => {
|
||||||
export const listCustomRewrite = () => {
|
export const listCustomRewrite = () => {
|
||||||
return http.get<string[]>(`/websites/rewrite/custom`);
|
return http.get<string[]>(`/websites/rewrite/custom`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const operateCrossSiteAccess = (req: Website.CrossSiteAccessOp) => {
|
||||||
|
return http.post(`/websites/crosssite`, req);
|
||||||
|
};
|
||||||
|
|
|
@ -2476,6 +2476,9 @@ const message = {
|
||||||
useProxy: 'Use Proxy',
|
useProxy: 'Use Proxy',
|
||||||
useProxyHelper: 'Use the proxy server address in the panel settings',
|
useProxyHelper: 'Use the proxy server address in the panel settings',
|
||||||
westCN: 'West Digital',
|
westCN: 'West Digital',
|
||||||
|
openBaseDir: 'Prevent Cross-Site Attacks',
|
||||||
|
openBaseDirHelper:
|
||||||
|
'open_basedir is used to restrict the PHP file access path, which helps prevent cross-site access and enhance security',
|
||||||
},
|
},
|
||||||
php: {
|
php: {
|
||||||
short_open_tag: 'Short tag support',
|
short_open_tag: 'Short tag support',
|
||||||
|
|
|
@ -2382,6 +2382,9 @@ const message = {
|
||||||
useProxy: 'プロキシを使用',
|
useProxy: 'プロキシを使用',
|
||||||
useProxyHelper: 'パネル設定のプロキシサーバーアドレスを使用',
|
useProxyHelper: 'パネル設定のプロキシサーバーアドレスを使用',
|
||||||
westCN: '西部デジタル',
|
westCN: '西部デジタル',
|
||||||
|
openBaseDir: 'クロスサイト攻撃を防ぐ',
|
||||||
|
openBaseDirHelper:
|
||||||
|
'open_basedir は PHP ファイルのアクセスパスを制限し、クロスサイトアクセスを防ぎセキュリティを向上させるために使用されます',
|
||||||
},
|
},
|
||||||
php: {
|
php: {
|
||||||
short_open_tag: '短いタグサポート',
|
short_open_tag: '短いタグサポート',
|
||||||
|
|
|
@ -2341,6 +2341,9 @@ const message = {
|
||||||
useProxy: '프록시 사용',
|
useProxy: '프록시 사용',
|
||||||
useProxyHelper: '패널 설정의 프록시 서버 주소 사용',
|
useProxyHelper: '패널 설정의 프록시 서버 주소 사용',
|
||||||
westCN: '서부 디지털',
|
westCN: '서부 디지털',
|
||||||
|
openBaseDir: '사이트 간 공격 방지',
|
||||||
|
openBaseDirHelper:
|
||||||
|
'open_basedir는 PHP 파일 액세스 경로를 제한하여 사이트 간 액세스를 방지하고 보안을 향상시키는 데 사용됩니다',
|
||||||
},
|
},
|
||||||
php: {
|
php: {
|
||||||
short_open_tag: '짧은 태그 지원',
|
short_open_tag: '짧은 태그 지원',
|
||||||
|
|
|
@ -2436,6 +2436,9 @@ const message = {
|
||||||
useProxy: 'Gunakan Proksi',
|
useProxy: 'Gunakan Proksi',
|
||||||
useProxyHelper: 'Gunakan alamat pelayan proksi dalam tetapan panel',
|
useProxyHelper: 'Gunakan alamat pelayan proksi dalam tetapan panel',
|
||||||
westCN: 'West Digital',
|
westCN: 'West Digital',
|
||||||
|
openBaseDir: 'Pencegahan Serangan Lintas Situs',
|
||||||
|
openBaseDirHelper:
|
||||||
|
'open_basedir digunakan untuk membatasi jalur akses file PHP, yang membantu mencegah akses lintas situs dan meningkatkan keamanan',
|
||||||
},
|
},
|
||||||
php: {
|
php: {
|
||||||
short_open_tag: 'Sokongan tag pendek',
|
short_open_tag: 'Sokongan tag pendek',
|
||||||
|
|
|
@ -2433,6 +2433,9 @@ const message = {
|
||||||
useProxy: 'Usar Proxy',
|
useProxy: 'Usar Proxy',
|
||||||
useProxyHelper: 'Usar o endereço do servidor proxy nas configurações do painel',
|
useProxyHelper: 'Usar o endereço do servidor proxy nas configurações do painel',
|
||||||
westCN: 'West Digital',
|
westCN: 'West Digital',
|
||||||
|
openBaseDir: 'Prevenir Ataques entre Sites',
|
||||||
|
openBaseDirHelper:
|
||||||
|
'open_basedir é usado para restringir o caminho de acesso a arquivos PHP, ajudando a prevenir acesso entre sites e aumentar a segurança',
|
||||||
},
|
},
|
||||||
php: {
|
php: {
|
||||||
short_open_tag: 'Suporte para short tags',
|
short_open_tag: 'Suporte para short tags',
|
||||||
|
|
|
@ -2432,6 +2432,9 @@ const message = {
|
||||||
useProxy: 'Использовать прокси',
|
useProxy: 'Использовать прокси',
|
||||||
useProxyHelper: 'Использовать адрес прокси-сервера в настройках панели',
|
useProxyHelper: 'Использовать адрес прокси-сервера в настройках панели',
|
||||||
westCN: 'Западный цифровой',
|
westCN: 'Западный цифровой',
|
||||||
|
openBaseDir: 'Предотвращение межсайтовых атак',
|
||||||
|
openBaseDirHelper:
|
||||||
|
'open_basedir используется для ограничения пути доступа к файлам PHP, что помогает предотвратить межсайтовый доступ и повысить безопасность',
|
||||||
},
|
},
|
||||||
php: {
|
php: {
|
||||||
short_open_tag: 'Поддержка коротких тегов',
|
short_open_tag: 'Поддержка коротких тегов',
|
||||||
|
|
|
@ -2296,6 +2296,8 @@ const message = {
|
||||||
useProxy: '使用代理',
|
useProxy: '使用代理',
|
||||||
useProxyHelper: '使用面板設置中的代理服務器地址',
|
useProxyHelper: '使用面板設置中的代理服務器地址',
|
||||||
westCN: '西部數碼',
|
westCN: '西部數碼',
|
||||||
|
openBaseDir: '防跨站攻擊',
|
||||||
|
openBaseDirHelper: 'open_basedir 用於限制 PHP 文件訪問路徑,有助於防止跨站訪問和提升安全性',
|
||||||
},
|
},
|
||||||
php: {
|
php: {
|
||||||
short_open_tag: '短標簽支持',
|
short_open_tag: '短標簽支持',
|
||||||
|
|
|
@ -2286,6 +2286,8 @@ const message = {
|
||||||
useProxy: '使用代理',
|
useProxy: '使用代理',
|
||||||
useProxyHelper: '使用面板设置中的代理服务器地址',
|
useProxyHelper: '使用面板设置中的代理服务器地址',
|
||||||
westCN: '西部数码',
|
westCN: '西部数码',
|
||||||
|
openBaseDir: '防跨站攻击',
|
||||||
|
openBaseDirHelper: 'open_basedir 用于限制 PHP 文件访问路径,有助于防止跨站访问和提升安全性',
|
||||||
},
|
},
|
||||||
php: {
|
php: {
|
||||||
short_open_tag: '短标签支持',
|
short_open_tag: '短标签支持',
|
||||||
|
|
|
@ -2,28 +2,39 @@
|
||||||
<div v-loading="loading">
|
<div v-loading="loading">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :xs="20" :sm="12" :md="10" :lg="10" :xl="8">
|
<el-col :xs="20" :sm="12" :md="10" :lg="10" :xl="8">
|
||||||
<el-form label-position="right" label-width="80px">
|
<el-form label-position="right" label-width="120px">
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<div v-if="website.type === 'static'">
|
<el-text type="info" v-if="website.type === 'static'">
|
||||||
<el-text type="info">{{ $t('website.staticChangePHPHelper') }}</el-text>
|
{{ $t('website.staticChangePHPHelper') }}
|
||||||
</div>
|
</el-text>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="$t('website.changeVersion')">
|
<el-form-item :label="$t('website.changeVersion')">
|
||||||
<el-select v-model="versionReq.runtimeID" class="w-full">
|
<el-row :gutter="20">
|
||||||
<el-option :key="-1" :label="$t('website.static')" :value="0"></el-option>
|
<el-col :span="20">
|
||||||
<el-option
|
<el-select v-model="versionReq.runtimeID" class="p-w-200">
|
||||||
v-for="(item, index) in versions"
|
<el-option :key="-1" :label="$t('website.static')" :value="0"></el-option>
|
||||||
:key="index"
|
<el-option
|
||||||
:label="item.label"
|
v-for="(item, index) in versions"
|
||||||
:value="item.value"
|
:key="index"
|
||||||
></el-option>
|
:label="item.label"
|
||||||
</el-select>
|
:value="item.value"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="4">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="submit()"
|
||||||
|
:disabled="versionReq.runtimeID === oldRuntimeID"
|
||||||
|
>
|
||||||
|
{{ $t('commons.button.save') }}
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item :label="$t('website.openBaseDir')">
|
||||||
<el-button type="primary" @click="submit()" :disabled="versionReq.runtimeID === oldRuntimeID">
|
<el-switch v-model="openBaseDir" @change="operateCrossSite"></el-switch>
|
||||||
{{ $t('commons.button.save') }}
|
<span class="input-help">{{ $t('website.openBaseDirHelper') }}</span>
|
||||||
</el-button>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
@ -36,7 +47,7 @@ import { SearchRuntimes } from '@/api/modules/runtime';
|
||||||
import { onMounted, reactive, ref } from 'vue';
|
import { onMounted, reactive, ref } from 'vue';
|
||||||
import { Runtime } from '@/api/interface/runtime';
|
import { Runtime } from '@/api/interface/runtime';
|
||||||
import { Website } from '@/api/interface/website';
|
import { Website } from '@/api/interface/website';
|
||||||
import { changePHPVersion, getWebsite } from '@/api/modules/website';
|
import { changePHPVersion, getWebsite, operateCrossSiteAccess } from '@/api/modules/website';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -56,7 +67,9 @@ const loading = ref(false);
|
||||||
const oldRuntimeID = ref(0);
|
const oldRuntimeID = ref(0);
|
||||||
const website = ref({
|
const website = ref({
|
||||||
type: '',
|
type: '',
|
||||||
|
openBaseDir: false,
|
||||||
});
|
});
|
||||||
|
const openBaseDir = ref(false);
|
||||||
|
|
||||||
const getRuntimes = async () => {
|
const getRuntimes = async () => {
|
||||||
try {
|
try {
|
||||||
|
@ -95,6 +108,18 @@ const getWebsiteDetail = async () => {
|
||||||
versionReq.runtimeID = res.data.runtimeID;
|
versionReq.runtimeID = res.data.runtimeID;
|
||||||
oldRuntimeID.value = res.data.runtimeID;
|
oldRuntimeID.value = res.data.runtimeID;
|
||||||
website.value = res.data;
|
website.value = res.data;
|
||||||
|
openBaseDir.value = res.data.openBaseDir || false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const operateCrossSite = async () => {
|
||||||
|
try {
|
||||||
|
await operateCrossSiteAccess({
|
||||||
|
websiteID: props.id,
|
||||||
|
operation: openBaseDir.value ? 'Enable' : 'Disable',
|
||||||
|
});
|
||||||
|
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
|
||||||
|
getWebsiteDetail();
|
||||||
|
} catch (error) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
Loading…
Add table
Reference in a new issue