mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-03-14 01:34:47 +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)
|
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
|
// @Tags Website
|
||||||
// @Summary Get AntiLeech conf
|
// @Summary Get AntiLeech conf
|
||||||
// @Description 获取防盗链配置
|
// @Description 获取防盗链配置
|
||||||
|
@ -33,6 +33,13 @@ type NginxAuth struct {
|
|||||||
Remark string `json:"remark"`
|
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
|
type NginxKey string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -44,6 +44,16 @@ type NginxAuthUpdate struct {
|
|||||||
Remark string `json:"remark"`
|
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 {
|
type NginxAuthReq struct {
|
||||||
WebsiteID uint `json:"websiteID" validate:"required"`
|
WebsiteID uint `json:"websiteID" validate:"required"`
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,10 @@ type NginxAuthRes struct {
|
|||||||
Items []dto.NginxAuth `json:"items"`
|
Items []dto.NginxAuth `json:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NginxPathAuthRes struct {
|
||||||
|
dto.NginxPathAuth
|
||||||
|
}
|
||||||
|
|
||||||
type NginxAntiLeechRes struct {
|
type NginxAntiLeechRes struct {
|
||||||
Enable bool `json:"enable"`
|
Enable bool `json:"enable"`
|
||||||
Extends string `json:"extends"`
|
Extends string `json:"extends"`
|
||||||
|
@ -89,17 +89,23 @@ type IWebsiteService interface {
|
|||||||
LoadWebsiteDirConfig(req request.WebsiteCommonReq) (*response.WebsiteDirConfig, error)
|
LoadWebsiteDirConfig(req request.WebsiteCommonReq) (*response.WebsiteDirConfig, error)
|
||||||
UpdateSiteDir(req request.WebsiteUpdateDir) error
|
UpdateSiteDir(req request.WebsiteUpdateDir) error
|
||||||
UpdateSitePermission(req request.WebsiteUpdateDirPermission) error
|
UpdateSitePermission(req request.WebsiteUpdateDirPermission) error
|
||||||
|
|
||||||
OperateProxy(req request.WebsiteProxyConfig) (err error)
|
OperateProxy(req request.WebsiteProxyConfig) (err error)
|
||||||
GetProxies(id uint) (res []request.WebsiteProxyConfig, err error)
|
GetProxies(id uint) (res []request.WebsiteProxyConfig, err error)
|
||||||
UpdateProxyFile(req request.NginxProxyUpdate) (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)
|
GetAntiLeech(id uint) (*response.NginxAntiLeechRes, error)
|
||||||
UpdateAntiLeech(req request.NginxAntiLeechUpdate) (err error)
|
UpdateAntiLeech(req request.NginxAntiLeechUpdate) (err error)
|
||||||
|
|
||||||
OperateRedirect(req request.NginxRedirectReq) (err error)
|
OperateRedirect(req request.NginxRedirectReq) (err error)
|
||||||
GetRedirect(id uint) (res []response.NginxRedirectConfig, err error)
|
GetRedirect(id uint) (res []response.NginxRedirectConfig, err error)
|
||||||
UpdateRedirectFile(req request.NginxRedirectUpdate) (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
|
UpdateDefaultHtml(req request.WebsiteHtmlUpdate) error
|
||||||
GetDefaultHtml(resourceType string) (*response.WebsiteHtmlRes, 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)
|
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) {
|
func (w WebsiteService) UpdateAuthBasic(req request.NginxAuthUpdate) (err error) {
|
||||||
var (
|
var (
|
||||||
website model.Website
|
website model.Website
|
||||||
@ -2064,12 +2114,11 @@ func (w WebsiteService) UpdateAuthBasic(req request.NginxAuthUpdate) (err error)
|
|||||||
return
|
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 (
|
var (
|
||||||
website model.Website
|
website model.Website
|
||||||
nginxInstall model.AppInstall
|
nginxInstall model.AppInstall
|
||||||
authContent []byte
|
authContent []byte
|
||||||
nginxParams []response.NginxParam
|
|
||||||
)
|
)
|
||||||
website, err = websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID))
|
website, err = websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -2079,35 +2128,127 @@ func (w WebsiteService) GetAuthBasics(req request.NginxAuthReq) (res response.Ng
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
authPath := fmt.Sprintf("/www/sites/%s/auth_basic/auth.pass", website.Alias)
|
|
||||||
absoluteAuthPath := path.Join(nginxInstall.GetPath(), authPath)
|
|
||||||
fileOp := files.NewFileOp()
|
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
|
return
|
||||||
}
|
}
|
||||||
nginxParams, err = getNginxParamsByKeys(constant.NginxScopeServer, []string{"auth_basic"}, &website)
|
|
||||||
|
entries, err := os.ReadDir(absoluteAuthDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
res.Enable = len(nginxParams[0].Params) > 0
|
|
||||||
authContent, err = fileOp.GetContent(absoluteAuthPath)
|
for _, entry := range entries {
|
||||||
authArray := strings.Split(string(authContent), "\n")
|
if !entry.IsDir() {
|
||||||
for _, line := range authArray {
|
name := strings.TrimSuffix(entry.Name(), ".conf")
|
||||||
if line == "" {
|
pathAuth := dto.NginxPathAuth{
|
||||||
continue
|
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
|
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) {
|
func (w WebsiteService) UpdateAntiLeech(req request.NginxAntiLeechUpdate) (err error) {
|
||||||
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID))
|
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -37,3 +37,6 @@ var DomainNotFoundHTML []byte
|
|||||||
|
|
||||||
//go:embed stop.html
|
//go:embed stop.html
|
||||||
var StopHTML []byte
|
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", baseApi.GetAuthConfig)
|
||||||
websiteRouter.POST("/auths/update", baseApi.UpdateAuthConfig)
|
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", baseApi.GetAntiLeech)
|
||||||
websiteRouter.POST("/leech/update", baseApi.UpdateAntiLeech)
|
websiteRouter.POST("/leech/update", baseApi.UpdateAntiLeech)
|
||||||
|
@ -393,6 +393,7 @@ export namespace Website {
|
|||||||
content?: string;
|
content?: string;
|
||||||
proxyAddress?: string;
|
proxyAddress?: string;
|
||||||
proxyProtocol?: string;
|
proxyProtocol?: string;
|
||||||
|
sni?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProxReplace {
|
export interface ProxReplace {
|
||||||
@ -425,6 +426,18 @@ export namespace Website {
|
|||||||
username: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
remark: 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 {
|
export interface LeechConfig {
|
||||||
|
@ -210,6 +210,14 @@ export const OperateAuthConfig = (req: Website.NginxAuthConfig) => {
|
|||||||
return http.post<any>(`/websites/auths/update`, req);
|
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) => {
|
export const GetAntiLeech = (req: Website.LeechReq) => {
|
||||||
return http.post<Website.LeechConfig>(`/websites/leech`, req);
|
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',
|
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',
|
proxyPassHelper: 'The proxied site must be a valid and accessible URL',
|
||||||
proxyHostHelper: 'Pass the domain name in the request header to the proxy server',
|
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',
|
modifier: 'Matching Rules',
|
||||||
modifierHelper: 'Example: = exact match, ~ regular match, ^~ match the beginning of the path, etc',
|
modifierHelper: 'Example: = exact match, ~ regular match, ^~ match the beginning of the path, etc',
|
||||||
replace: 'Text Replacement',
|
replace: 'Text Replacement',
|
||||||
@ -2134,6 +2133,7 @@ const message = {
|
|||||||
generateDomain: 'Generate',
|
generateDomain: 'Generate',
|
||||||
domainSSLHelper:
|
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',
|
'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: {
|
php: {
|
||||||
short_open_tag: 'Short tag support',
|
short_open_tag: 'Short tag support',
|
||||||
|
@ -1912,7 +1912,6 @@ const message = {
|
|||||||
proxyHelper1: '訪問這個目錄時將會把目標URL的內容返回並顯示',
|
proxyHelper1: '訪問這個目錄時將會把目標URL的內容返回並顯示',
|
||||||
proxyPassHelper: '代理的站點,必須為可正常訪問的URL',
|
proxyPassHelper: '代理的站點,必須為可正常訪問的URL',
|
||||||
proxyHostHelper: '將域名添加到請求頭傳遞到代理服務器',
|
proxyHostHelper: '將域名添加到請求頭傳遞到代理服務器',
|
||||||
replacementHelper: '最多可以添加5條替換內容,如果不需要替換請留空',
|
|
||||||
modifier: '匹配規則',
|
modifier: '匹配規則',
|
||||||
modifierHelper: '例:= 精確匹配,~ 正則匹配,^~ 匹配路徑開頭 等',
|
modifierHelper: '例:= 精確匹配,~ 正則匹配,^~ 匹配路徑開頭 等',
|
||||||
replace: '文本替換',
|
replace: '文本替換',
|
||||||
@ -1983,6 +1982,7 @@ const message = {
|
|||||||
batchAdd: '批量添加域名',
|
batchAdd: '批量添加域名',
|
||||||
generateDomain: '生成',
|
generateDomain: '生成',
|
||||||
domainSSLHelper: '非 443 端口開啟 SSL 會導致 443 端口移除監聽,如需 443 端口繼續監聽,請添加域名:443',
|
domainSSLHelper: '非 443 端口開啟 SSL 會導致 443 端口移除監聽,如需 443 端口繼續監聽,請添加域名:443',
|
||||||
|
global: '全局',
|
||||||
},
|
},
|
||||||
php: {
|
php: {
|
||||||
short_open_tag: '短標簽支持',
|
short_open_tag: '短標簽支持',
|
||||||
|
@ -1914,7 +1914,6 @@ const message = {
|
|||||||
proxyHelper1: '访问这个目录时将会把目标URL的内容返回并显示',
|
proxyHelper1: '访问这个目录时将会把目标URL的内容返回并显示',
|
||||||
proxyPassHelper: '代理的站点,必须为可正常访问的URL',
|
proxyPassHelper: '代理的站点,必须为可正常访问的URL',
|
||||||
proxyHostHelper: '将域名添加到请求头传递到代理服务器',
|
proxyHostHelper: '将域名添加到请求头传递到代理服务器',
|
||||||
replacementHelper: '最多可以添加5条替换内容,如果不需要替换请留空',
|
|
||||||
modifier: '匹配规则',
|
modifier: '匹配规则',
|
||||||
modifierHelper: '例:= 精确匹配,~ 正则匹配,^~ 匹配路径开头 等',
|
modifierHelper: '例:= 精确匹配,~ 正则匹配,^~ 匹配路径开头 等',
|
||||||
replace: '文本替换',
|
replace: '文本替换',
|
||||||
@ -1985,6 +1984,7 @@ const message = {
|
|||||||
batchAdd: '批量添加域名',
|
batchAdd: '批量添加域名',
|
||||||
generateDomain: '生成',
|
generateDomain: '生成',
|
||||||
domainSSLHelper: '非 443 端口开启 SSL 会导致 443 端口去掉监听,如需 443 端口继续监听,请添加域名:443',
|
domainSSLHelper: '非 443 端口开启 SSL 会导致 443 端口去掉监听,如需 443 端口继续监听,请添加域名:443',
|
||||||
|
global: '全局',
|
||||||
},
|
},
|
||||||
php: {
|
php: {
|
||||||
short_open_tag: '短标签支持',
|
short_open_tag: '短标签支持',
|
||||||
|
@ -20,8 +20,17 @@
|
|||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form ref="proxyForm" label-position="top" :model="authBasic" :rules="rules">
|
<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-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>
|
||||||
<el-form-item :label="$t('commons.login.password')" prop="password">
|
<el-form-item :label="$t('commons.login.password')" prop="password">
|
||||||
<el-input type="password" clearable show-password v-model.trim="authBasic.password">
|
<el-input type="password" clearable show-password v-model.trim="authBasic.password">
|
||||||
@ -51,7 +60,7 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
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 { Rules } from '@/global/form-rules';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { FormInstance } from 'element-plus';
|
import { FormInstance } from 'element-plus';
|
||||||
@ -64,6 +73,8 @@ const proxyForm = ref<FormInstance>();
|
|||||||
const rules = ref({
|
const rules = ref({
|
||||||
username: [Rules.requiredInput, Rules.name],
|
username: [Rules.requiredInput, Rules.name],
|
||||||
password: [Rules.requiredInput],
|
password: [Rules.requiredInput],
|
||||||
|
name: [Rules.requiredInput],
|
||||||
|
path: [Rules.requiredInput],
|
||||||
});
|
});
|
||||||
const open = ref(false);
|
const open = ref(false);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
@ -74,6 +85,8 @@ const initData = (): Website.NginxAuthConfig => ({
|
|||||||
username: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
remark: '',
|
remark: '',
|
||||||
|
scope: 'root',
|
||||||
|
path: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
let authBasic = ref(initData());
|
let authBasic = ref(initData());
|
||||||
@ -95,23 +108,36 @@ const acceptParams = (proxyParam: Website.NginxAuthConfig) => {
|
|||||||
|
|
||||||
const submit = async (formEl: FormInstance | undefined) => {
|
const submit = async (formEl: FormInstance | undefined) => {
|
||||||
if (!formEl) return;
|
if (!formEl) return;
|
||||||
await formEl.validate((valid) => {
|
await formEl.validate(async (valid) => {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
OperateAuthConfig(authBasic.value)
|
try {
|
||||||
.then(() => {
|
if (authBasic.value.scope == 'root') {
|
||||||
if (authBasic.value.operate == 'create') {
|
await OperateAuthConfig(authBasic.value);
|
||||||
MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
|
} else {
|
||||||
} else {
|
const req = {
|
||||||
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
|
websiteID: authBasic.value.websiteID,
|
||||||
}
|
path: authBasic.value.path,
|
||||||
handleClose();
|
name: authBasic.value.name,
|
||||||
})
|
username: authBasic.value.username,
|
||||||
.finally(() => {
|
password: authBasic.value.password,
|
||||||
loading.value = false;
|
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>
|
<template>
|
||||||
<el-form-item prop="enable" :label="$t('website.enableOrNot')">
|
<el-tabs type="border-card" @tab-change="searchAll()">
|
||||||
<el-switch v-model="enable" @change="changeEnable" :disabled="data.length === 0"></el-switch>
|
<el-tab-pane :label="$t('website.global')">
|
||||||
</el-form-item>
|
<ComplexTable :data="data" @search="search" v-loading="loading" :heightDiff="420">
|
||||||
<ComplexTable :data="data" @search="search" v-loading="loading" :heightDiff="420">
|
<template #toolbar>
|
||||||
<template #toolbar>
|
<el-button type="primary" plain @click="openCreate('root')">
|
||||||
<el-button type="primary" plain @click="openCreate">
|
{{ $t('commons.button.create') }}
|
||||||
{{ $t('commons.button.create') }}
|
</el-button>
|
||||||
</el-button>
|
<el-switch
|
||||||
</template>
|
class="ml-5"
|
||||||
<el-table-column :label="$t('commons.login.username')" prop="username"></el-table-column>
|
v-model="enable"
|
||||||
<el-table-column :label="$t('website.remark')" prop="remark"></el-table-column>
|
@change="changeEnable"
|
||||||
<fu-table-operations
|
:disabled="data.length === 0"
|
||||||
:ellipsis="10"
|
></el-switch>
|
||||||
width="260px"
|
</template>
|
||||||
:buttons="buttons"
|
<el-table-column :label="$t('commons.login.username')" prop="username"></el-table-column>
|
||||||
:label="$t('commons.table.operate')"
|
<el-table-column :label="$t('website.remark')" prop="remark"></el-table-column>
|
||||||
:fixed="mobile ? false : 'right'"
|
<fu-table-operations
|
||||||
fix
|
:ellipsis="10"
|
||||||
/>
|
width="260px"
|
||||||
</ComplexTable>
|
:buttons="buttons"
|
||||||
<Create ref="createRef" @close="search()" />
|
: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>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup name="proxy">
|
<script lang="ts" setup name="proxy">
|
||||||
import { Website } from '@/api/interface/website';
|
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 { computed, onMounted, ref } from 'vue';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import Create from './create/index.vue';
|
import Create from './create/index.vue';
|
||||||
@ -51,6 +79,7 @@ const data = ref([]);
|
|||||||
const createRef = ref();
|
const createRef = ref();
|
||||||
const enable = ref(false);
|
const enable = ref(false);
|
||||||
const opRef = ref();
|
const opRef = ref();
|
||||||
|
const pathData = ref([]);
|
||||||
|
|
||||||
const buttons = [
|
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 => ({
|
const initData = (id: number): Website.NginxAuthConfig => ({
|
||||||
websiteID: id,
|
websiteID: id,
|
||||||
operate: 'create',
|
operate: 'create',
|
||||||
username: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
remark: '',
|
remark: '',
|
||||||
|
scope: 'root',
|
||||||
});
|
});
|
||||||
|
|
||||||
const openCreate = () => {
|
const openCreate = (scope: string) => {
|
||||||
createRef.value.acceptParams(initData(id.value));
|
let req = initData(id.value);
|
||||||
|
req.scope = scope;
|
||||||
|
createRef.value.acceptParams(req);
|
||||||
};
|
};
|
||||||
|
|
||||||
const openEdit = (authConfig: Website.NginxAuthConfig) => {
|
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 changeEnable = () => {
|
||||||
const req = initData(id.value);
|
const req = initData(id.value);
|
||||||
req.operate = enable.value ? 'enable' : 'disable';
|
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();
|
search();
|
||||||
|
searchPath();
|
||||||
|
console.log(11111);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
searchAll();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -99,7 +99,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<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') }}
|
{{ $t('website.addReplace') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<div>
|
<div>
|
||||||
@ -159,6 +159,7 @@ const initData = (): Website.ProxyConfig => ({
|
|||||||
replaces: {},
|
replaces: {},
|
||||||
proxyAddress: '',
|
proxyAddress: '',
|
||||||
proxyProtocol: 'http://',
|
proxyProtocol: 'http://',
|
||||||
|
sni: false,
|
||||||
});
|
});
|
||||||
let proxy = ref(initData());
|
let proxy = ref(initData());
|
||||||
const replaces = ref<any>([]);
|
const replaces = ref<any>([]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user