mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-28 05:15:04 +08:00
feat: 网站密码认证支持子目录 (#6078)
Refs https://github.com/1Panel-dev/1Panel/issues/5863
This commit is contained in:
parent
e003d74506
commit
9114df9c2a
@ -643,6 +643,47 @@ func (b *BaseApi) UpdateAuthConfig(c *gin.Context) {
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Get AuthBasic conf
|
||||
// @Description 获取路由密码访问配置
|
||||
// @Accept json
|
||||
// @Param request body request.NginxAuthReq true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/auths/path [post]
|
||||
func (b *BaseApi) GetPathAuthConfig(c *gin.Context) {
|
||||
var req request.NginxAuthReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
res, err := websiteService.GetPathAuthBasics(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, res)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Get AuthBasic conf
|
||||
// @Description 更新路由密码访问配置
|
||||
// @Accept json
|
||||
// @Param request body request.NginxPathAuthUpdate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/auths/path/update [post]
|
||||
func (b *BaseApi) UpdatePathAuthConfig(c *gin.Context) {
|
||||
var req request.NginxPathAuthUpdate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := websiteService.UpdatePathAuthBasic(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Get AntiLeech conf
|
||||
// @Description 获取防盗链配置
|
||||
|
@ -33,6 +33,13 @@ type NginxAuth struct {
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type NginxPathAuth struct {
|
||||
Username string `json:"username"`
|
||||
Remark string `json:"remark"`
|
||||
Path string `json:"path"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type NginxKey string
|
||||
|
||||
const (
|
||||
|
@ -44,6 +44,16 @@ type NginxAuthUpdate struct {
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type NginxPathAuthUpdate struct {
|
||||
WebsiteID uint `json:"websiteID" validate:"required"`
|
||||
Operate string `json:"operate" validate:"required"`
|
||||
Name string `json:"name"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Path string `json:"path"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
type NginxAuthReq struct {
|
||||
WebsiteID uint `json:"websiteID" validate:"required"`
|
||||
}
|
||||
|
@ -22,6 +22,10 @@ type NginxAuthRes struct {
|
||||
Items []dto.NginxAuth `json:"items"`
|
||||
}
|
||||
|
||||
type NginxPathAuthRes struct {
|
||||
dto.NginxPathAuth
|
||||
}
|
||||
|
||||
type NginxAntiLeechRes struct {
|
||||
Enable bool `json:"enable"`
|
||||
Extends string `json:"extends"`
|
||||
|
@ -89,17 +89,23 @@ type IWebsiteService interface {
|
||||
LoadWebsiteDirConfig(req request.WebsiteCommonReq) (*response.WebsiteDirConfig, error)
|
||||
UpdateSiteDir(req request.WebsiteUpdateDir) error
|
||||
UpdateSitePermission(req request.WebsiteUpdateDirPermission) error
|
||||
|
||||
OperateProxy(req request.WebsiteProxyConfig) (err error)
|
||||
GetProxies(id uint) (res []request.WebsiteProxyConfig, err error)
|
||||
UpdateProxyFile(req request.NginxProxyUpdate) (err error)
|
||||
GetAuthBasics(req request.NginxAuthReq) (res response.NginxAuthRes, err error)
|
||||
UpdateAuthBasic(req request.NginxAuthUpdate) (err error)
|
||||
|
||||
GetAntiLeech(id uint) (*response.NginxAntiLeechRes, error)
|
||||
UpdateAntiLeech(req request.NginxAntiLeechUpdate) (err error)
|
||||
|
||||
OperateRedirect(req request.NginxRedirectReq) (err error)
|
||||
GetRedirect(id uint) (res []response.NginxRedirectConfig, err error)
|
||||
UpdateRedirectFile(req request.NginxRedirectUpdate) (err error)
|
||||
|
||||
GetAuthBasics(req request.NginxAuthReq) (res response.NginxAuthRes, err error)
|
||||
UpdateAuthBasic(req request.NginxAuthUpdate) (err error)
|
||||
GetPathAuthBasics(req request.NginxAuthReq) (res []response.NginxPathAuthRes, err error)
|
||||
UpdatePathAuthBasic(req request.NginxPathAuthUpdate) error
|
||||
|
||||
UpdateDefaultHtml(req request.WebsiteHtmlUpdate) error
|
||||
GetDefaultHtml(resourceType string) (*response.WebsiteHtmlRes, error)
|
||||
}
|
||||
@ -1935,6 +1941,50 @@ func (w WebsiteService) UpdateProxyFile(req request.NginxProxyUpdate) (err error
|
||||
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
|
||||
}
|
||||
|
||||
func (w WebsiteService) GetAuthBasics(req request.NginxAuthReq) (res response.NginxAuthRes, err error) {
|
||||
var (
|
||||
website model.Website
|
||||
nginxInstall model.AppInstall
|
||||
authContent []byte
|
||||
nginxParams []response.NginxParam
|
||||
)
|
||||
website, err = websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
nginxInstall, err = getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
authPath := fmt.Sprintf("/www/sites/%s/auth_basic/auth.pass", website.Alias)
|
||||
absoluteAuthPath := path.Join(nginxInstall.GetPath(), authPath)
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(absoluteAuthPath) {
|
||||
return
|
||||
}
|
||||
nginxParams, err = getNginxParamsByKeys(constant.NginxScopeServer, []string{"auth_basic"}, &website)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
res.Enable = len(nginxParams[0].Params) > 0
|
||||
authContent, err = fileOp.GetContent(absoluteAuthPath)
|
||||
authArray := strings.Split(string(authContent), "\n")
|
||||
for _, line := range authArray {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
params := strings.Split(line, ":")
|
||||
auth := dto.NginxAuth{
|
||||
Username: params[0],
|
||||
}
|
||||
if len(params) == 3 {
|
||||
auth.Remark = params[2]
|
||||
}
|
||||
res.Items = append(res.Items, auth)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (w WebsiteService) UpdateAuthBasic(req request.NginxAuthUpdate) (err error) {
|
||||
var (
|
||||
website model.Website
|
||||
@ -2064,12 +2114,11 @@ func (w WebsiteService) UpdateAuthBasic(req request.NginxAuthUpdate) (err error)
|
||||
return
|
||||
}
|
||||
|
||||
func (w WebsiteService) GetAuthBasics(req request.NginxAuthReq) (res response.NginxAuthRes, err error) {
|
||||
func (w WebsiteService) GetPathAuthBasics(req request.NginxAuthReq) (res []response.NginxPathAuthRes, err error) {
|
||||
var (
|
||||
website model.Website
|
||||
nginxInstall model.AppInstall
|
||||
authContent []byte
|
||||
nginxParams []response.NginxParam
|
||||
)
|
||||
website, err = websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
@ -2079,35 +2128,127 @@ func (w WebsiteService) GetAuthBasics(req request.NginxAuthReq) (res response.Ng
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
authPath := fmt.Sprintf("/www/sites/%s/auth_basic/auth.pass", website.Alias)
|
||||
absoluteAuthPath := path.Join(nginxInstall.GetPath(), authPath)
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(absoluteAuthPath) {
|
||||
authDir := fmt.Sprintf("/www/sites/%s/path_auth", website.Alias)
|
||||
absoluteAuthDir := path.Join(nginxInstall.GetPath(), authDir)
|
||||
passDir := path.Join(absoluteAuthDir, "pass")
|
||||
if !fileOp.Stat(absoluteAuthDir) || !fileOp.Stat(passDir) {
|
||||
return
|
||||
}
|
||||
nginxParams, err = getNginxParamsByKeys(constant.NginxScopeServer, []string{"auth_basic"}, &website)
|
||||
|
||||
entries, err := os.ReadDir(absoluteAuthDir)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
res.Enable = len(nginxParams[0].Params) > 0
|
||||
authContent, err = fileOp.GetContent(absoluteAuthPath)
|
||||
authArray := strings.Split(string(authContent), "\n")
|
||||
for _, line := range authArray {
|
||||
if line == "" {
|
||||
continue
|
||||
|
||||
for _, entry := range entries {
|
||||
if !entry.IsDir() {
|
||||
name := strings.TrimSuffix(entry.Name(), ".conf")
|
||||
pathAuth := dto.NginxPathAuth{
|
||||
Name: name,
|
||||
}
|
||||
configPath := path.Join(absoluteAuthDir, entry.Name())
|
||||
content, err := fileOp.GetContent(configPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config, err := parser.NewStringParser(string(content)).Parse()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
directives := config.Directives
|
||||
location, _ := directives[0].(*components.Location)
|
||||
pathAuth.Path = location.Match
|
||||
passPath := path.Join(passDir, fmt.Sprintf("%s.pass", name))
|
||||
authContent, err = fileOp.GetContent(passPath)
|
||||
authArray := strings.Split(string(authContent), "\n")
|
||||
for _, line := range authArray {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
params := strings.Split(line, ":")
|
||||
pathAuth.Username = params[0]
|
||||
if len(params) == 3 {
|
||||
pathAuth.Remark = params[2]
|
||||
}
|
||||
}
|
||||
res = append(res, response.NginxPathAuthRes{
|
||||
NginxPathAuth: pathAuth,
|
||||
})
|
||||
}
|
||||
params := strings.Split(line, ":")
|
||||
auth := dto.NginxAuth{
|
||||
Username: params[0],
|
||||
}
|
||||
if len(params) == 3 {
|
||||
auth.Remark = params[2]
|
||||
}
|
||||
res.Items = append(res.Items, auth)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (w WebsiteService) UpdatePathAuthBasic(req request.NginxPathAuthUpdate) error {
|
||||
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fileOp := files.NewFileOp()
|
||||
authDir := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "path_auth")
|
||||
if !fileOp.Stat(authDir) {
|
||||
_ = fileOp.CreateDir(authDir, 0755)
|
||||
}
|
||||
passDir := path.Join(authDir, "pass")
|
||||
if !fileOp.Stat(passDir) {
|
||||
_ = fileOp.CreateDir(passDir, 0755)
|
||||
}
|
||||
confPath := path.Join(authDir, fmt.Sprintf("%s.conf", req.Name))
|
||||
passPath := path.Join(passDir, fmt.Sprintf("%s.pass", req.Name))
|
||||
var config *components.Config
|
||||
switch req.Operate {
|
||||
case "delete":
|
||||
_ = fileOp.DeleteFile(confPath)
|
||||
_ = fileOp.DeleteFile(passPath)
|
||||
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
|
||||
case "create":
|
||||
config, err = parser.NewStringParser(string(nginx_conf.PathAuth)).Parse()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if fileOp.Stat(confPath) || fileOp.Stat(passPath) {
|
||||
return buserr.New(constant.ErrNameIsExist)
|
||||
}
|
||||
case "edit":
|
||||
par, err := parser.NewParser(confPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config, err = par.Parse()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
config.FilePath = confPath
|
||||
directives := config.Directives
|
||||
location, _ := directives[0].(*components.Location)
|
||||
location.UpdateDirective("auth_basic_user_file", []string{fmt.Sprintf("/www/sites/%s/path_auth/pass/%s", website.Alias, fmt.Sprintf("%s.pass", req.Name))})
|
||||
location.ChangePath("~*", req.Path)
|
||||
var passwdHash []byte
|
||||
passwdHash, err = bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
line := fmt.Sprintf("%s:%s\n", req.Username, passwdHash)
|
||||
if req.Remark != "" {
|
||||
line = fmt.Sprintf("%s:%s:%s\n", req.Username, passwdHash, req.Remark)
|
||||
}
|
||||
_ = fileOp.SaveFile(passPath, line, 0644)
|
||||
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
||||
return buserr.WithErr(constant.ErrUpdateBuWebsite, err)
|
||||
}
|
||||
nginxInclude := fmt.Sprintf("/www/sites/%s/path_auth/*.conf", website.Alias)
|
||||
if err = updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "include", Params: []string{nginxInclude}}}, &website); err != nil {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w WebsiteService) UpdateAntiLeech(req request.NginxAntiLeechUpdate) (err error) {
|
||||
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
|
@ -37,3 +37,6 @@ var DomainNotFoundHTML []byte
|
||||
|
||||
//go:embed stop.html
|
||||
var StopHTML []byte
|
||||
|
||||
//go:embed path_auth.conf
|
||||
var PathAuth []byte
|
||||
|
4
agent/cmd/server/nginx_conf/path_auth.conf
Normal file
4
agent/cmd/server/nginx_conf/path_auth.conf
Normal file
@ -0,0 +1,4 @@
|
||||
location ~* ^/test* {
|
||||
auth_basic "Authorization";
|
||||
auth_basic_user_file /www/site/pass/ceshi.pass ;
|
||||
}
|
@ -56,6 +56,8 @@ func (a *WebsiteRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
|
||||
websiteRouter.POST("/auths", baseApi.GetAuthConfig)
|
||||
websiteRouter.POST("/auths/update", baseApi.UpdateAuthConfig)
|
||||
websiteRouter.POST("/auths/path", baseApi.GetPathAuthConfig)
|
||||
websiteRouter.POST("/auths/path/update", baseApi.UpdatePathAuthConfig)
|
||||
|
||||
websiteRouter.POST("/leech", baseApi.GetAntiLeech)
|
||||
websiteRouter.POST("/leech/update", baseApi.UpdateAntiLeech)
|
||||
|
@ -393,6 +393,7 @@ export namespace Website {
|
||||
content?: string;
|
||||
proxyAddress?: string;
|
||||
proxyProtocol?: string;
|
||||
sni?: boolean;
|
||||
}
|
||||
|
||||
export interface ProxReplace {
|
||||
@ -425,6 +426,18 @@ export namespace Website {
|
||||
username: string;
|
||||
password: string;
|
||||
remark: string;
|
||||
scope: string;
|
||||
path?: '';
|
||||
name?: '';
|
||||
}
|
||||
|
||||
export interface NginxPathAuthConfig {
|
||||
websiteID: number;
|
||||
operate: string;
|
||||
path: string;
|
||||
username: string;
|
||||
password: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface LeechConfig {
|
||||
|
@ -210,6 +210,14 @@ export const OperateAuthConfig = (req: Website.NginxAuthConfig) => {
|
||||
return http.post<any>(`/websites/auths/update`, req);
|
||||
};
|
||||
|
||||
export const GetPathAuthConfig = (req: Website.AuthReq) => {
|
||||
return http.post<Website.NginxPathAuthConfig[]>(`/websites/auths/path`, req);
|
||||
};
|
||||
|
||||
export const OperatePathAuthConfig = (req: Website.NginxPathAuthConfig) => {
|
||||
return http.post(`/websites/auths/path/update`, req);
|
||||
};
|
||||
|
||||
export const GetAntiLeech = (req: Website.LeechReq) => {
|
||||
return http.post<Website.LeechConfig>(`/websites/leech`, req);
|
||||
};
|
||||
|
@ -2056,7 +2056,6 @@ const message = {
|
||||
proxyHelper1: 'When accessing this directory, the content of the target URL will be returned and displayed',
|
||||
proxyPassHelper: 'The proxied site must be a valid and accessible URL',
|
||||
proxyHostHelper: 'Pass the domain name in the request header to the proxy server',
|
||||
replacementHelper: 'Up to 5 replacements can be added, please leave blank if no replacement is required',
|
||||
modifier: 'Matching Rules',
|
||||
modifierHelper: 'Example: = exact match, ~ regular match, ^~ match the beginning of the path, etc',
|
||||
replace: 'Text Replacement',
|
||||
@ -2134,6 +2133,7 @@ const message = {
|
||||
generateDomain: 'Generate',
|
||||
domainSSLHelper:
|
||||
'Enabling SSL on a non-443 port will cause the 443 port to stop listening. If you need the 443 port to continue listening, please add the domain:443',
|
||||
global: 'Global',
|
||||
},
|
||||
php: {
|
||||
short_open_tag: 'Short tag support',
|
||||
|
@ -1912,7 +1912,6 @@ const message = {
|
||||
proxyHelper1: '訪問這個目錄時將會把目標URL的內容返回並顯示',
|
||||
proxyPassHelper: '代理的站點,必須為可正常訪問的URL',
|
||||
proxyHostHelper: '將域名添加到請求頭傳遞到代理服務器',
|
||||
replacementHelper: '最多可以添加5條替換內容,如果不需要替換請留空',
|
||||
modifier: '匹配規則',
|
||||
modifierHelper: '例:= 精確匹配,~ 正則匹配,^~ 匹配路徑開頭 等',
|
||||
replace: '文本替換',
|
||||
@ -1983,6 +1982,7 @@ const message = {
|
||||
batchAdd: '批量添加域名',
|
||||
generateDomain: '生成',
|
||||
domainSSLHelper: '非 443 端口開啟 SSL 會導致 443 端口移除監聽,如需 443 端口繼續監聽,請添加域名:443',
|
||||
global: '全局',
|
||||
},
|
||||
php: {
|
||||
short_open_tag: '短標簽支持',
|
||||
|
@ -1914,7 +1914,6 @@ const message = {
|
||||
proxyHelper1: '访问这个目录时将会把目标URL的内容返回并显示',
|
||||
proxyPassHelper: '代理的站点,必须为可正常访问的URL',
|
||||
proxyHostHelper: '将域名添加到请求头传递到代理服务器',
|
||||
replacementHelper: '最多可以添加5条替换内容,如果不需要替换请留空',
|
||||
modifier: '匹配规则',
|
||||
modifierHelper: '例:= 精确匹配,~ 正则匹配,^~ 匹配路径开头 等',
|
||||
replace: '文本替换',
|
||||
@ -1985,6 +1984,7 @@ const message = {
|
||||
batchAdd: '批量添加域名',
|
||||
generateDomain: '生成',
|
||||
domainSSLHelper: '非 443 端口开启 SSL 会导致 443 端口去掉监听,如需 443 端口继续监听,请添加域名:443',
|
||||
global: '全局',
|
||||
},
|
||||
php: {
|
||||
short_open_tag: '短标签支持',
|
||||
|
@ -20,8 +20,17 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form ref="proxyForm" label-position="top" :model="authBasic" :rules="rules">
|
||||
<el-form-item :label="$t('commons.table.name')" prop="name" v-if="authBasic.scope != 'root'">
|
||||
<el-input v-model.trim="authBasic.name" :disabled="authBasic.operate === 'edit'"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('website.path')" prop="path" v-if="authBasic.scope != 'root'">
|
||||
<el-input v-model.trim="authBasic.path" :disabled="authBasic.operate === 'edit'"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.login.username')" prop="username">
|
||||
<el-input v-model.trim="authBasic.username" :disabled="authBasic.operate === 'edit'"></el-input>
|
||||
<el-input
|
||||
v-model.trim="authBasic.username"
|
||||
:disabled="authBasic.scope == 'root' && authBasic.operate === 'edit'"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.login.password')" prop="password">
|
||||
<el-input type="password" clearable show-password v-model.trim="authBasic.password">
|
||||
@ -51,7 +60,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||
import { OperateAuthConfig } from '@/api/modules/website';
|
||||
import { OperateAuthConfig, OperatePathAuthConfig } from '@/api/modules/website';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import i18n from '@/lang';
|
||||
import { FormInstance } from 'element-plus';
|
||||
@ -64,6 +73,8 @@ const proxyForm = ref<FormInstance>();
|
||||
const rules = ref({
|
||||
username: [Rules.requiredInput, Rules.name],
|
||||
password: [Rules.requiredInput],
|
||||
name: [Rules.requiredInput],
|
||||
path: [Rules.requiredInput],
|
||||
});
|
||||
const open = ref(false);
|
||||
const loading = ref(false);
|
||||
@ -74,6 +85,8 @@ const initData = (): Website.NginxAuthConfig => ({
|
||||
username: '',
|
||||
password: '',
|
||||
remark: '',
|
||||
scope: 'root',
|
||||
path: '',
|
||||
});
|
||||
|
||||
let authBasic = ref(initData());
|
||||
@ -95,23 +108,36 @@ const acceptParams = (proxyParam: Website.NginxAuthConfig) => {
|
||||
|
||||
const submit = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
await formEl.validate((valid) => {
|
||||
await formEl.validate(async (valid) => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
OperateAuthConfig(authBasic.value)
|
||||
.then(() => {
|
||||
if (authBasic.value.operate == 'create') {
|
||||
MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
|
||||
} else {
|
||||
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
|
||||
}
|
||||
handleClose();
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
try {
|
||||
if (authBasic.value.scope == 'root') {
|
||||
await OperateAuthConfig(authBasic.value);
|
||||
} else {
|
||||
const req = {
|
||||
websiteID: authBasic.value.websiteID,
|
||||
path: authBasic.value.path,
|
||||
name: authBasic.value.name,
|
||||
username: authBasic.value.username,
|
||||
password: authBasic.value.password,
|
||||
operate: authBasic.value.operate,
|
||||
remark: authBasic.value.remark,
|
||||
};
|
||||
await OperatePathAuthConfig(req);
|
||||
}
|
||||
if (authBasic.value.operate == 'create') {
|
||||
MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
|
||||
} else {
|
||||
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
|
||||
}
|
||||
handleClose();
|
||||
} catch (error) {
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1,32 +1,60 @@
|
||||
<template>
|
||||
<el-form-item prop="enable" :label="$t('website.enableOrNot')">
|
||||
<el-switch v-model="enable" @change="changeEnable" :disabled="data.length === 0"></el-switch>
|
||||
</el-form-item>
|
||||
<ComplexTable :data="data" @search="search" v-loading="loading" :heightDiff="420">
|
||||
<template #toolbar>
|
||||
<el-button type="primary" plain @click="openCreate">
|
||||
{{ $t('commons.button.create') }}
|
||||
</el-button>
|
||||
</template>
|
||||
<el-table-column :label="$t('commons.login.username')" prop="username"></el-table-column>
|
||||
<el-table-column :label="$t('website.remark')" prop="remark"></el-table-column>
|
||||
<fu-table-operations
|
||||
:ellipsis="10"
|
||||
width="260px"
|
||||
:buttons="buttons"
|
||||
:label="$t('commons.table.operate')"
|
||||
:fixed="mobile ? false : 'right'"
|
||||
fix
|
||||
/>
|
||||
</ComplexTable>
|
||||
<Create ref="createRef" @close="search()" />
|
||||
<el-tabs type="border-card" @tab-change="searchAll()">
|
||||
<el-tab-pane :label="$t('website.global')">
|
||||
<ComplexTable :data="data" @search="search" v-loading="loading" :heightDiff="420">
|
||||
<template #toolbar>
|
||||
<el-button type="primary" plain @click="openCreate('root')">
|
||||
{{ $t('commons.button.create') }}
|
||||
</el-button>
|
||||
<el-switch
|
||||
class="ml-5"
|
||||
v-model="enable"
|
||||
@change="changeEnable"
|
||||
:disabled="data.length === 0"
|
||||
></el-switch>
|
||||
</template>
|
||||
<el-table-column :label="$t('commons.login.username')" prop="username"></el-table-column>
|
||||
<el-table-column :label="$t('website.remark')" prop="remark"></el-table-column>
|
||||
<fu-table-operations
|
||||
:ellipsis="10"
|
||||
width="260px"
|
||||
:buttons="buttons"
|
||||
:label="$t('commons.table.operate')"
|
||||
:fixed="mobile ? false : 'right'"
|
||||
fix
|
||||
/>
|
||||
</ComplexTable>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('website.path')">
|
||||
<ComplexTable :data="pathData" @search="searchPath" v-loading="loading" :heightDiff="420">
|
||||
<template #toolbar>
|
||||
<el-button type="primary" plain @click="openCreate('path')">
|
||||
{{ $t('commons.button.create') }}
|
||||
</el-button>
|
||||
</template>
|
||||
<el-table-column :label="$t('commons.table.name')" prop="name"></el-table-column>
|
||||
<el-table-column :label="$t('website.path')" prop="path"></el-table-column>
|
||||
<el-table-column :label="$t('commons.login.username')" prop="username"></el-table-column>
|
||||
<el-table-column :label="$t('website.remark')" prop="remark"></el-table-column>
|
||||
<fu-table-operations
|
||||
:ellipsis="10"
|
||||
width="260px"
|
||||
:buttons="pathButtons"
|
||||
:label="$t('commons.table.operate')"
|
||||
:fixed="mobile ? false : 'right'"
|
||||
fix
|
||||
/>
|
||||
</ComplexTable>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<OpDialog ref="opRef" @search="search" />
|
||||
<Create ref="createRef" @close="searchAll()" />
|
||||
<OpDialog ref="opRef" @search="searchAll" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="proxy">
|
||||
import { Website } from '@/api/interface/website';
|
||||
import { OperateAuthConfig, GetAuthConfig } from '@/api/modules/website';
|
||||
import { OperateAuthConfig, GetAuthConfig, GetPathAuthConfig, OperatePathAuthConfig } from '@/api/modules/website';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import i18n from '@/lang';
|
||||
import Create from './create/index.vue';
|
||||
@ -51,6 +79,7 @@ const data = ref([]);
|
||||
const createRef = ref();
|
||||
const enable = ref(false);
|
||||
const opRef = ref();
|
||||
const pathData = ref([]);
|
||||
|
||||
const buttons = [
|
||||
{
|
||||
@ -67,16 +96,34 @@ const buttons = [
|
||||
},
|
||||
];
|
||||
|
||||
const pathButtons = [
|
||||
{
|
||||
label: i18n.global.t('commons.button.edit'),
|
||||
click: function (row: Website.NginxAuthConfig) {
|
||||
openEdit(row);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('commons.button.delete'),
|
||||
click: function (row: Website.NginxPathAuthConfig) {
|
||||
deletePathAuth(row);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const initData = (id: number): Website.NginxAuthConfig => ({
|
||||
websiteID: id,
|
||||
operate: 'create',
|
||||
username: '',
|
||||
password: '',
|
||||
remark: '',
|
||||
scope: 'root',
|
||||
});
|
||||
|
||||
const openCreate = () => {
|
||||
createRef.value.acceptParams(initData(id.value));
|
||||
const openCreate = (scope: string) => {
|
||||
let req = initData(id.value);
|
||||
req.scope = scope;
|
||||
createRef.value.acceptParams(req);
|
||||
};
|
||||
|
||||
const openEdit = (authConfig: Website.NginxAuthConfig) => {
|
||||
@ -101,6 +148,21 @@ const deleteAuth = async (authConfig: Website.NginxAuthConfig) => {
|
||||
});
|
||||
};
|
||||
|
||||
const deletePathAuth = async (authConfig: Website.NginxPathAuthConfig) => {
|
||||
authConfig.operate = 'delete';
|
||||
authConfig.websiteID = id.value;
|
||||
opRef.value.acceptParams({
|
||||
title: i18n.global.t('commons.button.delete'),
|
||||
names: [authConfig.name],
|
||||
msg: i18n.global.t('commons.msg.operatorHelper', [
|
||||
i18n.global.t('website.basicAuth'),
|
||||
i18n.global.t('commons.button.delete'),
|
||||
]),
|
||||
api: OperatePathAuthConfig,
|
||||
params: authConfig,
|
||||
});
|
||||
};
|
||||
|
||||
const changeEnable = () => {
|
||||
const req = initData(id.value);
|
||||
req.operate = enable.value ? 'enable' : 'disable';
|
||||
@ -127,7 +189,24 @@ const search = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
const searchPath = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
const res = await GetPathAuthConfig({ websiteID: id.value });
|
||||
pathData.value = res.data || [];
|
||||
} catch (error) {
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const searchAll = () => {
|
||||
search();
|
||||
searchPath();
|
||||
console.log(11111);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
searchAll();
|
||||
});
|
||||
</script>
|
||||
|
@ -99,7 +99,7 @@
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="addReplaces" :disabled="replaces.length >= 5">
|
||||
<el-button type="primary" @click="addReplaces">
|
||||
{{ $t('website.addReplace') }}
|
||||
</el-button>
|
||||
<div>
|
||||
@ -159,6 +159,7 @@ const initData = (): Website.ProxyConfig => ({
|
||||
replaces: {},
|
||||
proxyAddress: '',
|
||||
proxyProtocol: 'http://',
|
||||
sni: false,
|
||||
});
|
||||
let proxy = ref(initData());
|
||||
const replaces = ref<any>([]);
|
||||
|
Loading…
Reference in New Issue
Block a user