mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-10-24 14:38:23 +08:00
feat: 网站增加设置目录运行用户和用户组的功能 (#694)
This commit is contained in:
parent
2dbc7f28fd
commit
d660b7d315
11 changed files with 115 additions and 24 deletions
|
|
@ -626,3 +626,25 @@ func (b *BaseApi) UpdateSiteDir(c *gin.Context) {
|
||||||
}
|
}
|
||||||
helper.SuccessWithOutData(c)
|
helper.SuccessWithOutData(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Tags Website
|
||||||
|
// @Summary Update Site Dir permission
|
||||||
|
// @Description 更新网站目录权限
|
||||||
|
// @Accept json
|
||||||
|
// @Param request body request.WebsiteUpdateDirPermission true "request"
|
||||||
|
// @Success 200
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Router /websites/dir/permission [post]
|
||||||
|
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"id","isList":false,"db":"websites","output_colume":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] 目录权限","formatEN":"Update domain [domain] dir permission"}
|
||||||
|
func (b *BaseApi) UpdateSiteDirPermission(c *gin.Context) {
|
||||||
|
var req request.WebsiteUpdateDirPermission
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := websiteService.UpdateSitePermission(req); err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.SuccessWithOutData(c)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -150,3 +150,9 @@ type WebsiteUpdateDir struct {
|
||||||
ID uint `json:"id" validate:"required"`
|
ID uint `json:"id" validate:"required"`
|
||||||
SiteDir string `json:"siteDir" validate:"required"`
|
SiteDir string `json:"siteDir" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WebsiteUpdateDirPermission struct {
|
||||||
|
ID uint `json:"id" validate:"required"`
|
||||||
|
User string `json:"user" validate:"required"`
|
||||||
|
Group string `json:"group" validate:"required"`
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,9 @@ type Website struct {
|
||||||
RuntimeID uint `gorm:"type:integer" json:"runtimeID"`
|
RuntimeID uint `gorm:"type:integer" json:"runtimeID"`
|
||||||
AppInstallID uint `gorm:"type:integer" json:"appInstallId"`
|
AppInstallID uint `gorm:"type:integer" json:"appInstallId"`
|
||||||
|
|
||||||
|
User string `gorm:"type:varchar;" json:"user"`
|
||||||
|
Group string `gorm:"type:varchar;" json:"group"`
|
||||||
|
|
||||||
Domains []WebsiteDomain `json:"domains" gorm:"-:migration"`
|
Domains []WebsiteDomain `json:"domains" gorm:"-:migration"`
|
||||||
WebsiteSSL WebsiteSSL `json:"webSiteSSL" gorm:"-:migration"`
|
WebsiteSSL WebsiteSSL `json:"webSiteSSL" gorm:"-:migration"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||||
"github.com/1Panel-dev/1Panel/cmd/server/nginx_conf"
|
"github.com/1Panel-dev/1Panel/cmd/server/nginx_conf"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -62,6 +63,7 @@ type IWebsiteService interface {
|
||||||
GetRewriteConfig(req request.NginxRewriteReq) (*response.NginxRewriteRes, error)
|
GetRewriteConfig(req request.NginxRewriteReq) (*response.NginxRewriteRes, error)
|
||||||
UpdateRewriteConfig(req request.NginxRewriteUpdate) error
|
UpdateRewriteConfig(req request.NginxRewriteUpdate) error
|
||||||
UpdateSiteDir(req request.WebsiteUpdateDir) error
|
UpdateSiteDir(req request.WebsiteUpdateDir) error
|
||||||
|
UpdateSitePermission(req request.WebsiteUpdateDirPermission) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIWebsiteService() IWebsiteService {
|
func NewIWebsiteService() IWebsiteService {
|
||||||
|
|
@ -1075,3 +1077,25 @@ func (w WebsiteService) UpdateSiteDir(req request.WebsiteUpdateDir) error {
|
||||||
website.SiteDir = runDir
|
website.SiteDir = runDir
|
||||||
return websiteRepo.Save(context.Background(), &website)
|
return websiteRepo.Save(context.Background(), &website)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w WebsiteService) UpdateSitePermission(req request.WebsiteUpdateDirPermission) error {
|
||||||
|
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
absoluteIndexPath := path.Join(nginxInstall.GetPath(), "www", "sites", website.PrimaryDomain, "index")
|
||||||
|
if website.SiteDir != "/" {
|
||||||
|
absoluteIndexPath = path.Join(absoluteIndexPath, website.SiteDir)
|
||||||
|
}
|
||||||
|
chownCmd := fmt.Sprintf("chown -R %s:%s %s", req.User, req.Group, absoluteIndexPath)
|
||||||
|
if _, err := cmd.ExecWithTimeOut(chownCmd, 1*time.Second); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
website.User = req.User
|
||||||
|
website.Group = req.Group
|
||||||
|
return websiteRepo.Save(context.Background(), &website)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -276,7 +276,7 @@ var UpdateTableHost = &gormigrate.Migration{
|
||||||
}
|
}
|
||||||
|
|
||||||
var UpdateTableWebsite = &gormigrate.Migration{
|
var UpdateTableWebsite = &gormigrate.Migration{
|
||||||
ID: "20230417-update-table-website",
|
ID: "20230418-update-table-website",
|
||||||
Migrate: func(tx *gorm.DB) error {
|
Migrate: func(tx *gorm.DB) error {
|
||||||
if err := tx.AutoMigrate(&model.Website{}); err != nil {
|
if err := tx.AutoMigrate(&model.Website{}); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -50,5 +50,6 @@ func (a *WebsiteRouter) InitWebsiteRouter(Router *gin.RouterGroup) {
|
||||||
groupRouter.POST("/rewrite/update", baseApi.UpdateRewriteConfig)
|
groupRouter.POST("/rewrite/update", baseApi.UpdateRewriteConfig)
|
||||||
|
|
||||||
groupRouter.POST("/dir/update", baseApi.UpdateSiteDir)
|
groupRouter.POST("/dir/update", baseApi.UpdateSiteDir)
|
||||||
|
groupRouter.POST("/dir/permission", baseApi.UpdateSiteDirPermission)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ export namespace Website {
|
||||||
webSiteSSL: SSL;
|
webSiteSSL: SSL;
|
||||||
runtimeID: number;
|
runtimeID: number;
|
||||||
rewrite: string;
|
rewrite: string;
|
||||||
|
user: string;
|
||||||
|
group: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WebsiteDTO extends Website {
|
export interface WebsiteDTO extends Website {
|
||||||
|
|
@ -299,4 +301,10 @@ export namespace Website {
|
||||||
id: number;
|
id: number;
|
||||||
siteDir: string;
|
siteDir: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DirPermissionUpdate {
|
||||||
|
id: number;
|
||||||
|
user: string;
|
||||||
|
group: string;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,3 +182,7 @@ export const UpdateRewriteConfig = (req: Website.RewriteUpdate) => {
|
||||||
export const UpdateWebsiteDir = (req: Website.DirUpdate) => {
|
export const UpdateWebsiteDir = (req: Website.DirUpdate) => {
|
||||||
return http.post<any>(`/websites/dir/update`, req);
|
return http.post<any>(`/websites/dir/update`, req);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const UpdateWebsiteDirPermission = (req: Website.DirPermissionUpdate) => {
|
||||||
|
return http.post<any>(`/websites/dir/permission`, req);
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -428,6 +428,9 @@ const message = {
|
||||||
remoteConn: 'External connection address',
|
remoteConn: 'External connection address',
|
||||||
remoteConnHelper2: 'Use this address for non-container or external connections',
|
remoteConnHelper2: 'Use this address for non-container or external connections',
|
||||||
localIP: 'Local IP',
|
localIP: 'Local IP',
|
||||||
|
userGroup: 'User/Group',
|
||||||
|
user: 'User',
|
||||||
|
uGroup: 'Group',
|
||||||
},
|
},
|
||||||
container: {
|
container: {
|
||||||
createContainer: 'Create container',
|
createContainer: 'Create container',
|
||||||
|
|
|
||||||
|
|
@ -1172,7 +1172,10 @@ const message = {
|
||||||
runDir: '运行目录',
|
runDir: '运行目录',
|
||||||
runDirHelper: '部分程序需要指定二级目录作为运行目录,如ThinkPHP5,Laravel',
|
runDirHelper: '部分程序需要指定二级目录作为运行目录,如ThinkPHP5,Laravel',
|
||||||
runUserHelper:
|
runUserHelper:
|
||||||
'通过 PHP 运行环境部署的网站,需要将 index 和子目录下的所有文件、文件夹所有者和用户组设置为 1000,命令:chown -R 1000:1000 index',
|
'通过 PHP 运行环境部署的网站,需要将 index 和子目录下的所有文件、文件夹所有者和用户组设置为 1000',
|
||||||
|
userGroup: '运行用户/组',
|
||||||
|
user: '用户',
|
||||||
|
uGroup: '用户组',
|
||||||
},
|
},
|
||||||
php: {
|
php: {
|
||||||
short_open_tag: '短标签支持',
|
short_open_tag: '短标签支持',
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-space>
|
</el-space>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="configDir" :label="$t('website.runDir')" prop="runDir">
|
<el-form-item v-if="configDir" :label="$t('website.runDir')">
|
||||||
<el-space wrap>
|
<el-space wrap>
|
||||||
<el-select v-model="update.siteDir">
|
<el-select v-model="update.siteDir">
|
||||||
<el-option :label="'/'" :value="'/'"></el-option>
|
<el-option :label="'/'" :value="'/'"></el-option>
|
||||||
|
|
@ -31,26 +31,26 @@
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-space>
|
</el-space>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="运行用户/组" prop="runDir">
|
<el-form-item :label="$t('website.userGroup')">
|
||||||
<el-space wrap>
|
<el-space wrap>
|
||||||
<el-input v-model="update.siteDir" class="user-num-input">
|
<el-input v-model="updatePermission.user" class="user-num-input">
|
||||||
<template #prepend>用户</template>
|
<template #prepend>{{ $t('website.user') }}</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
<el-input v-model="update.siteDir" class="user-num-input">
|
<el-input v-model="updatePermission.group" class="user-num-input">
|
||||||
<template #prepend>用户组</template>
|
<template #prepend>{{ $t('website.uGroup') }}</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
<el-button type="primary" @click="submit(siteForm)">保存</el-button>
|
<el-button type="primary" @click="submitPermission()">
|
||||||
|
{{ $t('commons.button.save') }}
|
||||||
|
</el-button>
|
||||||
</el-space>
|
</el-space>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-form-item>
|
|
||||||
<el-alert :closable="false">
|
<el-alert :closable="false">
|
||||||
<template #default>
|
<template #default>
|
||||||
<span class="warnHelper">{{ $t('website.runDirHelper') }}</span>
|
<span class="warnHelper">{{ $t('website.runDirHelper') }}</span>
|
||||||
|
<span class="warnHelper">{{ $t('website.runUserHelper') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-alert>
|
</el-alert>
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<el-descriptions :title="$t('website.folderTitle')" :column="1" border>
|
<el-descriptions :title="$t('website.folderTitle')" :column="1" border>
|
||||||
<el-descriptions-item label="waf">{{ $t('website.wafFolder') }}</el-descriptions-item>
|
<el-descriptions-item label="waf">{{ $t('website.wafFolder') }}</el-descriptions-item>
|
||||||
|
|
@ -58,18 +58,12 @@
|
||||||
<el-descriptions-item label="log">{{ $t('website.logFoler') }}</el-descriptions-item>
|
<el-descriptions-item label="log">{{ $t('website.logFoler') }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="index">{{ $t('website.indexFolder') }}</el-descriptions-item>
|
<el-descriptions-item label="index">{{ $t('website.indexFolder') }}</el-descriptions-item>
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
<br />
|
|
||||||
<el-alert :closable="false">
|
|
||||||
<template #default>
|
|
||||||
<span class="warnHelper">{{ $t('website.runUserHelper') }}</span>
|
|
||||||
</template>
|
|
||||||
</el-alert>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { GetFilesList } from '@/api/modules/files';
|
import { GetFilesList } from '@/api/modules/files';
|
||||||
import { GetWebsite, UpdateWebsiteDir } from '@/api/modules/website';
|
import { GetWebsite, UpdateWebsiteDir, UpdateWebsiteDirPermission } from '@/api/modules/website';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
import { FormInstance } from 'element-plus';
|
import { FormInstance } from 'element-plus';
|
||||||
|
|
@ -93,6 +87,11 @@ const update = reactive({
|
||||||
id: 0,
|
id: 0,
|
||||||
siteDir: '/',
|
siteDir: '/',
|
||||||
});
|
});
|
||||||
|
const updatePermission = reactive({
|
||||||
|
id: 0,
|
||||||
|
user: '1000',
|
||||||
|
group: '1000',
|
||||||
|
});
|
||||||
const siteForm = ref<FormInstance>();
|
const siteForm = ref<FormInstance>();
|
||||||
const dirReq = reactive({
|
const dirReq = reactive({
|
||||||
path: '/',
|
path: '/',
|
||||||
|
|
@ -113,6 +112,9 @@ const search = () => {
|
||||||
website.value = res.data;
|
website.value = res.data;
|
||||||
update.id = website.value.id;
|
update.id = website.value.id;
|
||||||
update.siteDir = website.value.siteDir;
|
update.siteDir = website.value.siteDir;
|
||||||
|
updatePermission.id = website.value.id;
|
||||||
|
updatePermission.group = website.value.group === '' ? '1000' : website.value.group;
|
||||||
|
updatePermission.user = website.value.user === '' ? '1000' : website.value.user;
|
||||||
if (website.value.type === 'static' || website.value.runtimeID > 0) {
|
if (website.value.type === 'static' || website.value.runtimeID > 0) {
|
||||||
configDir.value = true;
|
configDir.value = true;
|
||||||
dirReq.path = website.value.sitePath + '/index';
|
dirReq.path = website.value.sitePath + '/index';
|
||||||
|
|
@ -142,6 +144,21 @@ const submit = async (formEl: FormInstance | undefined) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const submitPermission = async () => {
|
||||||
|
if (updatePermission.user === '' || updatePermission.group === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
UpdateWebsiteDirPermission(updatePermission)
|
||||||
|
.then(() => {
|
||||||
|
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
|
||||||
|
search();
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const getDirs = async () => {
|
const getDirs = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
await GetFilesList(dirReq)
|
await GetFilesList(dirReq)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue