mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-06 23:57:21 +02:00
parent
dce58343db
commit
4f7f60188f
@ -55,6 +55,10 @@ func initAPIs() {
|
|||||||
authRouter.HandleFunc("/api/proxy/setIncoming", HandleIncomingPortSet)
|
authRouter.HandleFunc("/api/proxy/setIncoming", HandleIncomingPortSet)
|
||||||
authRouter.HandleFunc("/api/proxy/useHttpsRedirect", HandleUpdateHttpsRedirect)
|
authRouter.HandleFunc("/api/proxy/useHttpsRedirect", HandleUpdateHttpsRedirect)
|
||||||
authRouter.HandleFunc("/api/proxy/requestIsProxied", HandleManagementProxyCheck)
|
authRouter.HandleFunc("/api/proxy/requestIsProxied", HandleManagementProxyCheck)
|
||||||
|
//Reverse proxy auth related APIs
|
||||||
|
authRouter.HandleFunc("/api/proxy/auth/exceptions/list", ListProxyBasicAuthExceptionPaths)
|
||||||
|
authRouter.HandleFunc("/api/proxy/auth/exceptions/add", AddProxyBasicAuthExceptionPaths)
|
||||||
|
authRouter.HandleFunc("/api/proxy/auth/exceptions/delete", RemoveProxyBasicAuthExceptionPaths)
|
||||||
|
|
||||||
//TLS / SSL config
|
//TLS / SSL config
|
||||||
authRouter.HandleFunc("/api/cert/tls", handleToggleTLSProxy)
|
authRouter.HandleFunc("/api/cert/tls", handleToggleTLSProxy)
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@ -26,16 +25,18 @@ import (
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
type Record struct {
|
type Record struct {
|
||||||
ProxyType string
|
ProxyType string
|
||||||
Rootname string
|
Rootname string
|
||||||
ProxyTarget string
|
ProxyTarget string
|
||||||
UseTLS bool
|
UseTLS bool
|
||||||
SkipTlsValidation bool
|
SkipTlsValidation bool
|
||||||
RequireBasicAuth bool
|
RequireBasicAuth bool
|
||||||
BasicAuthCredentials []*dynamicproxy.BasicAuthCredentials
|
BasicAuthCredentials []*dynamicproxy.BasicAuthCredentials
|
||||||
|
BasicAuthExceptionRules []*dynamicproxy.BasicAuthExceptionRule
|
||||||
}
|
}
|
||||||
|
|
||||||
func SaveReverseProxyConfig(proxyConfigRecord *Record) error {
|
// Save a reverse proxy config record to file
|
||||||
|
func SaveReverseProxyConfigToFile(proxyConfigRecord *Record) error {
|
||||||
//TODO: Make this accept new def types
|
//TODO: Make this accept new def types
|
||||||
os.MkdirAll("./conf/proxy/", 0775)
|
os.MkdirAll("./conf/proxy/", 0775)
|
||||||
filename := getFilenameFromRootName(proxyConfigRecord.Rootname)
|
filename := getFilenameFromRootName(proxyConfigRecord.Rootname)
|
||||||
@ -45,10 +46,19 @@ func SaveReverseProxyConfig(proxyConfigRecord *Record) error {
|
|||||||
|
|
||||||
//Write to file
|
//Write to file
|
||||||
js, _ := json.MarshalIndent(thisRecord, "", " ")
|
js, _ := json.MarshalIndent(thisRecord, "", " ")
|
||||||
return ioutil.WriteFile(filepath.Join("./conf/proxy/", filename), js, 0775)
|
return os.WriteFile(filepath.Join("./conf/proxy/", filename), js, 0775)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RemoveReverseProxyConfig(rootname string) error {
|
// Save a running reverse proxy endpoint to file (with automatic endpoint to record conversion)
|
||||||
|
func SaveReverseProxyEndpointToFile(proxyEndpoint *dynamicproxy.ProxyEndpoint) error {
|
||||||
|
recordToSave, err := ConvertProxyEndpointToRecord(proxyEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return SaveReverseProxyConfigToFile(recordToSave)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RemoveReverseProxyConfigFile(rootname string) error {
|
||||||
filename := getFilenameFromRootName(rootname)
|
filename := getFilenameFromRootName(rootname)
|
||||||
removePendingFile := strings.ReplaceAll(filepath.Join("./conf/proxy/", filename), "\\", "/")
|
removePendingFile := strings.ReplaceAll(filepath.Join("./conf/proxy/", filename), "\\", "/")
|
||||||
log.Println("Config Removed: ", removePendingFile)
|
log.Println("Config Removed: ", removePendingFile)
|
||||||
@ -66,8 +76,18 @@ func RemoveReverseProxyConfig(rootname string) error {
|
|||||||
|
|
||||||
// Return ptype, rootname and proxyTarget, error if any
|
// Return ptype, rootname and proxyTarget, error if any
|
||||||
func LoadReverseProxyConfig(filename string) (*Record, error) {
|
func LoadReverseProxyConfig(filename string) (*Record, error) {
|
||||||
thisRecord := Record{}
|
thisRecord := Record{
|
||||||
configContent, err := ioutil.ReadFile(filename)
|
ProxyType: "",
|
||||||
|
Rootname: "",
|
||||||
|
ProxyTarget: "",
|
||||||
|
UseTLS: false,
|
||||||
|
SkipTlsValidation: false,
|
||||||
|
RequireBasicAuth: false,
|
||||||
|
BasicAuthCredentials: []*dynamicproxy.BasicAuthCredentials{},
|
||||||
|
BasicAuthExceptionRules: []*dynamicproxy.BasicAuthExceptionRule{},
|
||||||
|
}
|
||||||
|
|
||||||
|
configContent, err := os.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &thisRecord, err
|
return &thisRecord, err
|
||||||
}
|
}
|
||||||
@ -82,6 +102,22 @@ func LoadReverseProxyConfig(filename string) (*Record, error) {
|
|||||||
return &thisRecord, nil
|
return &thisRecord, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert a running proxy endpoint object into a save-able record struct
|
||||||
|
func ConvertProxyEndpointToRecord(targetProxyEndpoint *dynamicproxy.ProxyEndpoint) (*Record, error) {
|
||||||
|
thisProxyConfigRecord := Record{
|
||||||
|
ProxyType: targetProxyEndpoint.GetProxyTypeString(),
|
||||||
|
Rootname: targetProxyEndpoint.RootOrMatchingDomain,
|
||||||
|
ProxyTarget: targetProxyEndpoint.Domain,
|
||||||
|
UseTLS: targetProxyEndpoint.RequireTLS,
|
||||||
|
SkipTlsValidation: targetProxyEndpoint.SkipCertValidations,
|
||||||
|
RequireBasicAuth: targetProxyEndpoint.RequireBasicAuth,
|
||||||
|
BasicAuthCredentials: targetProxyEndpoint.BasicAuthCredentials,
|
||||||
|
BasicAuthExceptionRules: targetProxyEndpoint.BasicAuthExceptionRules,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &thisProxyConfigRecord, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getFilenameFromRootName(rootname string) string {
|
func getFilenameFromRootName(rootname string) string {
|
||||||
//Generate a filename for this rootname
|
//Generate a filename for this rootname
|
||||||
filename := strings.ReplaceAll(rootname, ".", "_")
|
filename := strings.ReplaceAll(rootname, ".", "_")
|
||||||
|
@ -98,7 +98,7 @@ func ShutdownSeq() {
|
|||||||
fmt.Println("- Closing Statistic Collector")
|
fmt.Println("- Closing Statistic Collector")
|
||||||
statisticCollector.Close()
|
statisticCollector.Close()
|
||||||
if mdnsTickerStop != nil {
|
if mdnsTickerStop != nil {
|
||||||
fmt.Println("- Stopping mDNS Discoverer")
|
fmt.Println("- Stopping mDNS Discoverer (might take a few minutes)")
|
||||||
// Stop the mdns service
|
// Stop the mdns service
|
||||||
mdnsTickerStop <- true
|
mdnsTickerStop <- true
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package dynamicproxy
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"imuslab.com/zoraxy/mod/auth"
|
"imuslab.com/zoraxy/mod/auth"
|
||||||
)
|
)
|
||||||
@ -15,6 +16,16 @@ import (
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
func (h *ProxyHandler) handleBasicAuthRouting(w http.ResponseWriter, r *http.Request, pe *ProxyEndpoint) error {
|
func (h *ProxyHandler) handleBasicAuthRouting(w http.ResponseWriter, r *http.Request, pe *ProxyEndpoint) error {
|
||||||
|
if len(pe.BasicAuthExceptionRules) > 0 {
|
||||||
|
//Check if the current path matches the exception rules
|
||||||
|
for _, exceptionRule := range pe.BasicAuthExceptionRules {
|
||||||
|
if strings.HasPrefix(r.RequestURI, exceptionRule.PathPrefix) {
|
||||||
|
//This path is excluded from basic auth
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
proxyType := "vdir-auth"
|
proxyType := "vdir-auth"
|
||||||
if pe.ProxyType == ProxyType_Subdomain {
|
if pe.ProxyType == ProxyType_Subdomain {
|
||||||
proxyType = "subd-auth"
|
proxyType = "subd-auth"
|
||||||
|
@ -246,14 +246,15 @@ func (router *Router) AddVirtualDirectoryProxyService(options *VdirOptions) erro
|
|||||||
proxy := dpcore.NewDynamicProxyCore(path, options.RootName, options.SkipCertValidations)
|
proxy := dpcore.NewDynamicProxyCore(path, options.RootName, options.SkipCertValidations)
|
||||||
|
|
||||||
endpointObject := ProxyEndpoint{
|
endpointObject := ProxyEndpoint{
|
||||||
ProxyType: ProxyType_Vdir,
|
ProxyType: ProxyType_Vdir,
|
||||||
RootOrMatchingDomain: options.RootName,
|
RootOrMatchingDomain: options.RootName,
|
||||||
Domain: domain,
|
Domain: domain,
|
||||||
RequireTLS: options.RequireTLS,
|
RequireTLS: options.RequireTLS,
|
||||||
SkipCertValidations: options.SkipCertValidations,
|
SkipCertValidations: options.SkipCertValidations,
|
||||||
RequireBasicAuth: options.RequireBasicAuth,
|
RequireBasicAuth: options.RequireBasicAuth,
|
||||||
BasicAuthCredentials: options.BasicAuthCredentials,
|
BasicAuthCredentials: options.BasicAuthCredentials,
|
||||||
Proxy: proxy,
|
BasicAuthExceptionRules: options.BasicAuthExceptionRules,
|
||||||
|
Proxy: proxy,
|
||||||
}
|
}
|
||||||
|
|
||||||
router.ProxyEndpoints.Store(options.RootName, &endpointObject)
|
router.ProxyEndpoints.Store(options.RootName, &endpointObject)
|
||||||
@ -271,46 +272,24 @@ func (router *Router) LoadProxy(ptype string, key string) (*ProxyEndpoint, error
|
|||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("target proxy not found")
|
return nil, errors.New("target proxy not found")
|
||||||
}
|
}
|
||||||
return proxy.(*ProxyEndpoint), nil
|
|
||||||
|
targetProxy := proxy.(*ProxyEndpoint)
|
||||||
|
targetProxy.parent = router
|
||||||
|
return targetProxy, nil
|
||||||
} else if ptype == "subd" {
|
} else if ptype == "subd" {
|
||||||
proxy, ok := router.SubdomainEndpoint.Load(key)
|
proxy, ok := router.SubdomainEndpoint.Load(key)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("target proxy not found")
|
return nil, errors.New("target proxy not found")
|
||||||
}
|
}
|
||||||
return proxy.(*ProxyEndpoint), nil
|
|
||||||
|
targetProxy := proxy.(*ProxyEndpoint)
|
||||||
|
targetProxy.parent = router
|
||||||
|
return targetProxy, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New("unsupported ptype")
|
return nil, errors.New("unsupported ptype")
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Save routing from RP
|
|
||||||
*/
|
|
||||||
func (router *Router) SaveProxy(ptype string, key string, newConfig *ProxyEndpoint) {
|
|
||||||
if ptype == "vdir" {
|
|
||||||
router.ProxyEndpoints.Store(key, newConfig)
|
|
||||||
|
|
||||||
} else if ptype == "subd" {
|
|
||||||
router.SubdomainEndpoint.Store(key, newConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Remove routing from RP
|
|
||||||
*/
|
|
||||||
func (router *Router) RemoveProxy(ptype string, key string) error {
|
|
||||||
//fmt.Println(ptype, key)
|
|
||||||
if ptype == "vdir" {
|
|
||||||
router.ProxyEndpoints.Delete(key)
|
|
||||||
return nil
|
|
||||||
} else if ptype == "subd" {
|
|
||||||
router.SubdomainEndpoint.Delete(key)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return errors.New("invalid ptype")
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Add an default router for the proxy server
|
Add an default router for the proxy server
|
||||||
*/
|
*/
|
||||||
|
68
src/mod/dynamicproxy/proxyEndpoint.go
Normal file
68
src/mod/dynamicproxy/proxyEndpoint.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package dynamicproxy
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
/*
|
||||||
|
ProxyEndpoint.go
|
||||||
|
author: tobychui
|
||||||
|
|
||||||
|
This script handle the proxy endpoint object actions
|
||||||
|
so proxyEndpoint can be handled like a proper oop object
|
||||||
|
|
||||||
|
Most of the functions are implemented in dynamicproxy.go
|
||||||
|
*/
|
||||||
|
|
||||||
|
//Get the string version of proxy type
|
||||||
|
func (ep *ProxyEndpoint) GetProxyTypeString() string {
|
||||||
|
if ep.ProxyType == ProxyType_Subdomain {
|
||||||
|
return "subd"
|
||||||
|
} else if ep.ProxyType == ProxyType_Vdir {
|
||||||
|
return "vdir"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
//Update change in the current running proxy endpoint config
|
||||||
|
func (ep *ProxyEndpoint) UpdateToRuntime() {
|
||||||
|
if ep.IsVdir() {
|
||||||
|
ep.parent.ProxyEndpoints.Store(ep.RootOrMatchingDomain, ep)
|
||||||
|
|
||||||
|
} else if ep.IsSubDomain() {
|
||||||
|
ep.parent.SubdomainEndpoint.Store(ep.RootOrMatchingDomain, ep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Return true if the endpoint type is virtual directory
|
||||||
|
func (ep *ProxyEndpoint) IsVdir() bool {
|
||||||
|
return ep.ProxyType == ProxyType_Vdir
|
||||||
|
}
|
||||||
|
|
||||||
|
//Return true if the endpoint type is subdomain
|
||||||
|
func (ep *ProxyEndpoint) IsSubDomain() bool {
|
||||||
|
return ep.ProxyType == ProxyType_Subdomain
|
||||||
|
}
|
||||||
|
|
||||||
|
//Remove this proxy endpoint from running proxy endpoint list
|
||||||
|
func (ep *ProxyEndpoint) Remove() error {
|
||||||
|
//fmt.Println(ptype, key)
|
||||||
|
if ep.IsVdir() {
|
||||||
|
ep.parent.ProxyEndpoints.Delete(ep.RootOrMatchingDomain)
|
||||||
|
return nil
|
||||||
|
} else if ep.IsSubDomain() {
|
||||||
|
ep.parent.SubdomainEndpoint.Delete(ep.RootOrMatchingDomain)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("invalid or unsupported type")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//ProxyEndpoint remove provide global access by key
|
||||||
|
func (router *Router) RemoveProxyEndpointByRootname(proxyType string, rootnameOrMatchingDomain string) error {
|
||||||
|
targetEpt, err := router.LoadProxy(proxyType, rootnameOrMatchingDomain)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetEpt.Remove()
|
||||||
|
}
|
@ -34,13 +34,14 @@ func (router *Router) AddSubdomainRoutingService(options *SubdOptions) error {
|
|||||||
proxy := dpcore.NewDynamicProxyCore(path, "", options.SkipCertValidations)
|
proxy := dpcore.NewDynamicProxyCore(path, "", options.SkipCertValidations)
|
||||||
|
|
||||||
router.SubdomainEndpoint.Store(options.MatchingDomain, &ProxyEndpoint{
|
router.SubdomainEndpoint.Store(options.MatchingDomain, &ProxyEndpoint{
|
||||||
RootOrMatchingDomain: options.MatchingDomain,
|
RootOrMatchingDomain: options.MatchingDomain,
|
||||||
Domain: domain,
|
Domain: domain,
|
||||||
RequireTLS: options.RequireTLS,
|
RequireTLS: options.RequireTLS,
|
||||||
Proxy: proxy,
|
Proxy: proxy,
|
||||||
SkipCertValidations: options.SkipCertValidations,
|
SkipCertValidations: options.SkipCertValidations,
|
||||||
RequireBasicAuth: options.RequireBasicAuth,
|
RequireBasicAuth: options.RequireBasicAuth,
|
||||||
BasicAuthCredentials: options.BasicAuthCredentials,
|
BasicAuthCredentials: options.BasicAuthCredentials,
|
||||||
|
BasicAuthExceptionRules: options.BasicAuthExceptionRules,
|
||||||
})
|
})
|
||||||
|
|
||||||
log.Println("Adding Subdomain Rule: ", options.MatchingDomain+" to "+domain)
|
log.Println("Adding Subdomain Rule: ", options.MatchingDomain+" to "+domain)
|
||||||
|
@ -59,56 +59,51 @@ type BasicAuthUnhashedCredentials struct {
|
|||||||
Password string
|
Password string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Paths to exclude in basic auth enabled proxy handler
|
||||||
|
type BasicAuthExceptionRule struct {
|
||||||
|
PathPrefix string
|
||||||
|
}
|
||||||
|
|
||||||
// A proxy endpoint record
|
// A proxy endpoint record
|
||||||
type ProxyEndpoint struct {
|
type ProxyEndpoint struct {
|
||||||
ProxyType int //The type of this proxy, see const def
|
ProxyType int //The type of this proxy, see const def
|
||||||
RootOrMatchingDomain string //Root for vdir or Matching domain for subd
|
RootOrMatchingDomain string //Root for vdir or Matching domain for subd, also act as key
|
||||||
Domain string //Domain or IP to proxy to
|
Domain string //Domain or IP to proxy to
|
||||||
RequireTLS bool //Target domain require TLS
|
RequireTLS bool //Target domain require TLS
|
||||||
SkipCertValidations bool //Set to true to accept self signed certs
|
SkipCertValidations bool //Set to true to accept self signed certs
|
||||||
RequireBasicAuth bool //Set to true to request basic auth before proxy
|
RequireBasicAuth bool //Set to true to request basic auth before proxy
|
||||||
BasicAuthCredentials []*BasicAuthCredentials `json:"-"`
|
BasicAuthCredentials []*BasicAuthCredentials `json:"-"` //Basic auth credentials
|
||||||
Proxy *dpcore.ReverseProxy `json:"-"`
|
BasicAuthExceptionRules []*BasicAuthExceptionRule //Path to exclude in a basic auth enabled proxy target
|
||||||
|
Proxy *dpcore.ReverseProxy `json:"-"`
|
||||||
|
|
||||||
|
parent *Router
|
||||||
}
|
}
|
||||||
|
|
||||||
type RootOptions struct {
|
type RootOptions struct {
|
||||||
ProxyLocation string
|
ProxyLocation string
|
||||||
RequireTLS bool
|
RequireTLS bool
|
||||||
SkipCertValidations bool
|
SkipCertValidations bool
|
||||||
RequireBasicAuth bool
|
RequireBasicAuth bool
|
||||||
BasicAuthCredentials []*BasicAuthCredentials
|
BasicAuthCredentials []*BasicAuthCredentials
|
||||||
|
BasicAuthExceptionRules []*BasicAuthExceptionRule
|
||||||
}
|
}
|
||||||
|
|
||||||
type VdirOptions struct {
|
type VdirOptions struct {
|
||||||
RootName string
|
RootName string
|
||||||
Domain string
|
Domain string
|
||||||
RequireTLS bool
|
RequireTLS bool
|
||||||
SkipCertValidations bool
|
SkipCertValidations bool
|
||||||
RequireBasicAuth bool
|
RequireBasicAuth bool
|
||||||
BasicAuthCredentials []*BasicAuthCredentials
|
BasicAuthCredentials []*BasicAuthCredentials
|
||||||
|
BasicAuthExceptionRules []*BasicAuthExceptionRule
|
||||||
}
|
}
|
||||||
|
|
||||||
type SubdOptions struct {
|
type SubdOptions struct {
|
||||||
MatchingDomain string
|
MatchingDomain string
|
||||||
Domain string
|
Domain string
|
||||||
RequireTLS bool
|
RequireTLS bool
|
||||||
SkipCertValidations bool
|
SkipCertValidations bool
|
||||||
RequireBasicAuth bool
|
RequireBasicAuth bool
|
||||||
BasicAuthCredentials []*BasicAuthCredentials
|
BasicAuthCredentials []*BasicAuthCredentials
|
||||||
|
BasicAuthExceptionRules []*BasicAuthExceptionRule
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
type ProxyEndpoint struct {
|
|
||||||
Root string
|
|
||||||
Domain string
|
|
||||||
RequireTLS bool
|
|
||||||
Proxy *reverseproxy.ReverseProxy `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SubdomainEndpoint struct {
|
|
||||||
MatchingDomain string
|
|
||||||
Domain string
|
|
||||||
RequireTLS bool
|
|
||||||
Proxy *reverseproxy.ReverseProxy `json:"-"`
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
@ -88,21 +88,23 @@ func ReverseProxtInit() {
|
|||||||
})
|
})
|
||||||
} else if record.ProxyType == "subd" {
|
} else if record.ProxyType == "subd" {
|
||||||
dynamicProxyRouter.AddSubdomainRoutingService(&dynamicproxy.SubdOptions{
|
dynamicProxyRouter.AddSubdomainRoutingService(&dynamicproxy.SubdOptions{
|
||||||
MatchingDomain: record.Rootname,
|
MatchingDomain: record.Rootname,
|
||||||
Domain: record.ProxyTarget,
|
Domain: record.ProxyTarget,
|
||||||
RequireTLS: record.UseTLS,
|
RequireTLS: record.UseTLS,
|
||||||
SkipCertValidations: record.SkipTlsValidation,
|
SkipCertValidations: record.SkipTlsValidation,
|
||||||
RequireBasicAuth: record.RequireBasicAuth,
|
RequireBasicAuth: record.RequireBasicAuth,
|
||||||
BasicAuthCredentials: record.BasicAuthCredentials,
|
BasicAuthCredentials: record.BasicAuthCredentials,
|
||||||
|
BasicAuthExceptionRules: record.BasicAuthExceptionRules,
|
||||||
})
|
})
|
||||||
} else if record.ProxyType == "vdir" {
|
} else if record.ProxyType == "vdir" {
|
||||||
dynamicProxyRouter.AddVirtualDirectoryProxyService(&dynamicproxy.VdirOptions{
|
dynamicProxyRouter.AddVirtualDirectoryProxyService(&dynamicproxy.VdirOptions{
|
||||||
RootName: record.Rootname,
|
RootName: record.Rootname,
|
||||||
Domain: record.ProxyTarget,
|
Domain: record.ProxyTarget,
|
||||||
RequireTLS: record.UseTLS,
|
RequireTLS: record.UseTLS,
|
||||||
SkipCertValidations: record.SkipTlsValidation,
|
SkipCertValidations: record.SkipTlsValidation,
|
||||||
RequireBasicAuth: record.RequireBasicAuth,
|
RequireBasicAuth: record.RequireBasicAuth,
|
||||||
BasicAuthCredentials: record.BasicAuthCredentials,
|
BasicAuthCredentials: record.BasicAuthCredentials,
|
||||||
|
BasicAuthExceptionRules: record.BasicAuthExceptionRules,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
log.Println("Unsupported endpoint type: " + record.ProxyType + ". Skipping " + filepath.Base(conf))
|
log.Println("Unsupported endpoint type: " + record.ProxyType + ". Skipping " + filepath.Base(conf))
|
||||||
@ -282,7 +284,7 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
RequireBasicAuth: requireBasicAuth,
|
RequireBasicAuth: requireBasicAuth,
|
||||||
BasicAuthCredentials: basicAuthCredentials,
|
BasicAuthCredentials: basicAuthCredentials,
|
||||||
}
|
}
|
||||||
SaveReverseProxyConfig(&thisProxyConfigRecord)
|
SaveReverseProxyConfigToFile(&thisProxyConfigRecord)
|
||||||
|
|
||||||
//Update utm if exists
|
//Update utm if exists
|
||||||
if uptimeMonitor != nil {
|
if uptimeMonitor != nil {
|
||||||
@ -355,7 +357,7 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
RequireBasicAuth: requireBasicAuth,
|
RequireBasicAuth: requireBasicAuth,
|
||||||
BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
|
BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
|
||||||
}
|
}
|
||||||
dynamicProxyRouter.RemoveProxy("vdir", thisOption.RootName)
|
targetProxyEntry.Remove()
|
||||||
dynamicProxyRouter.AddVirtualDirectoryProxyService(&thisOption)
|
dynamicProxyRouter.AddVirtualDirectoryProxyService(&thisOption)
|
||||||
|
|
||||||
} else if eptype == "subd" {
|
} else if eptype == "subd" {
|
||||||
@ -367,7 +369,7 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
RequireBasicAuth: requireBasicAuth,
|
RequireBasicAuth: requireBasicAuth,
|
||||||
BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
|
BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
|
||||||
}
|
}
|
||||||
dynamicProxyRouter.RemoveProxy("subd", thisOption.MatchingDomain)
|
targetProxyEntry.Remove()
|
||||||
dynamicProxyRouter.AddSubdomainRoutingService(&thisOption)
|
dynamicProxyRouter.AddSubdomainRoutingService(&thisOption)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,7 +383,7 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
RequireBasicAuth: requireBasicAuth,
|
RequireBasicAuth: requireBasicAuth,
|
||||||
BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
|
BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
|
||||||
}
|
}
|
||||||
SaveReverseProxyConfig(&thisProxyConfigRecord)
|
SaveReverseProxyConfigToFile(&thisProxyConfigRecord)
|
||||||
utils.SendOK(w)
|
utils.SendOK(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,13 +400,15 @@ func DeleteProxyEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = dynamicProxyRouter.RemoveProxy(ptype, ep)
|
//Remove the config from runtime
|
||||||
|
err = dynamicProxyRouter.RemoveProxyEndpointByRootname(ptype, ep)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.SendErrorResponse(w, err.Error())
|
utils.SendErrorResponse(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveReverseProxyConfig(ep)
|
//Remove the config from file
|
||||||
|
RemoveReverseProxyConfigFile(ep)
|
||||||
|
|
||||||
//Update utm if exists
|
//Update utm if exists
|
||||||
if uptimeMonitor != nil {
|
if uptimeMonitor != nil {
|
||||||
@ -528,19 +532,10 @@ func UpdateProxyBasicAuthCredentials(w http.ResponseWriter, r *http.Request) {
|
|||||||
targetProxy.BasicAuthCredentials = mergedCredentials
|
targetProxy.BasicAuthCredentials = mergedCredentials
|
||||||
|
|
||||||
//Save it to file
|
//Save it to file
|
||||||
thisProxyConfigRecord := Record{
|
SaveReverseProxyEndpointToFile(targetProxy)
|
||||||
ProxyType: ptype,
|
|
||||||
Rootname: targetProxy.RootOrMatchingDomain,
|
|
||||||
ProxyTarget: targetProxy.Domain,
|
|
||||||
UseTLS: targetProxy.RequireTLS,
|
|
||||||
SkipTlsValidation: targetProxy.SkipCertValidations,
|
|
||||||
RequireBasicAuth: targetProxy.RequireBasicAuth,
|
|
||||||
BasicAuthCredentials: targetProxy.BasicAuthCredentials,
|
|
||||||
}
|
|
||||||
SaveReverseProxyConfig(&thisProxyConfigRecord)
|
|
||||||
|
|
||||||
//Replace runtime configuration
|
//Replace runtime configuration
|
||||||
dynamicProxyRouter.SaveProxy(ptype, ep, targetProxy)
|
targetProxy.UpdateToRuntime()
|
||||||
utils.SendOK(w)
|
utils.SendOK(w)
|
||||||
} else {
|
} else {
|
||||||
http.Error(w, "invalid usage", http.StatusMethodNotAllowed)
|
http.Error(w, "invalid usage", http.StatusMethodNotAllowed)
|
||||||
@ -548,6 +543,147 @@ func UpdateProxyBasicAuthCredentials(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// List, Update or Remove the exception paths for basic auth.
|
||||||
|
func ListProxyBasicAuthExceptionPaths(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
if r.Method != http.MethodGet {
|
||||||
|
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
|
||||||
|
}
|
||||||
|
ep, err := utils.GetPara(r, "ep")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "Invalid ep given")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ptype, err := utils.GetPara(r, "ptype")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "Invalid ptype given")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Load the target proxy object from router
|
||||||
|
targetProxy, err := dynamicProxyRouter.LoadProxy(ptype, ep)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//List all the exception paths for this proxy
|
||||||
|
results := targetProxy.BasicAuthExceptionRules
|
||||||
|
if results == nil {
|
||||||
|
//It is a config from a really old version of zoraxy. Overwrite it with empty array
|
||||||
|
results = []*dynamicproxy.BasicAuthExceptionRule{}
|
||||||
|
}
|
||||||
|
js, _ := json.Marshal(results)
|
||||||
|
utils.SendJSONResponse(w, string(js))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddProxyBasicAuthExceptionPaths(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ep, err := utils.PostPara(r, "ep")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "Invalid ep given")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ptype, err := utils.PostPara(r, "ptype")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "Invalid ptype given")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
matchingPrefix, err := utils.PostPara(r, "prefix")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "Invalid matching prefix given")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Load the target proxy object from router
|
||||||
|
targetProxy, err := dynamicProxyRouter.LoadProxy(ptype, ep)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if the prefix starts with /. If not, prepend it
|
||||||
|
if !strings.HasPrefix(matchingPrefix, "/") {
|
||||||
|
matchingPrefix = "/" + matchingPrefix
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add a new exception rule if it is not already exists
|
||||||
|
alreadyExists := false
|
||||||
|
for _, thisExceptionRule := range targetProxy.BasicAuthExceptionRules {
|
||||||
|
if thisExceptionRule.PathPrefix == matchingPrefix {
|
||||||
|
alreadyExists = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if alreadyExists {
|
||||||
|
utils.SendErrorResponse(w, "This matching path already exists")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
targetProxy.BasicAuthExceptionRules = append(targetProxy.BasicAuthExceptionRules, &dynamicproxy.BasicAuthExceptionRule{
|
||||||
|
PathPrefix: strings.TrimSpace(matchingPrefix),
|
||||||
|
})
|
||||||
|
|
||||||
|
//Save configs to runtime and file
|
||||||
|
targetProxy.UpdateToRuntime()
|
||||||
|
SaveReverseProxyEndpointToFile(targetProxy)
|
||||||
|
|
||||||
|
utils.SendOK(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RemoveProxyBasicAuthExceptionPaths(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Delete a rule
|
||||||
|
ep, err := utils.PostPara(r, "ep")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "Invalid ep given")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ptype, err := utils.PostPara(r, "ptype")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "Invalid ptype given")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
matchingPrefix, err := utils.PostPara(r, "prefix")
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, "Invalid matching prefix given")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the target proxy object from router
|
||||||
|
targetProxy, err := dynamicProxyRouter.LoadProxy(ptype, ep)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
newExceptionRuleList := []*dynamicproxy.BasicAuthExceptionRule{}
|
||||||
|
matchingExists := false
|
||||||
|
for _, thisExceptionalRule := range targetProxy.BasicAuthExceptionRules {
|
||||||
|
if thisExceptionalRule.PathPrefix != matchingPrefix {
|
||||||
|
newExceptionRuleList = append(newExceptionRuleList, thisExceptionalRule)
|
||||||
|
} else {
|
||||||
|
matchingExists = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !matchingExists {
|
||||||
|
utils.SendErrorResponse(w, "target matching rule not exists")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
targetProxy.BasicAuthExceptionRules = newExceptionRuleList
|
||||||
|
|
||||||
|
// Save configs to runtime and file
|
||||||
|
targetProxy.UpdateToRuntime()
|
||||||
|
SaveReverseProxyEndpointToFile(targetProxy)
|
||||||
|
|
||||||
|
utils.SendOK(w)
|
||||||
|
}
|
||||||
|
|
||||||
func ReverseProxyStatus(w http.ResponseWriter, r *http.Request) {
|
func ReverseProxyStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
js, _ := json.Marshal(dynamicProxyRouter)
|
js, _ := json.Marshal(dynamicProxyRouter)
|
||||||
utils.SendJSONResponse(w, string(js))
|
utils.SendJSONResponse(w, string(js))
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
<style>
|
||||||
|
.expired.certdate{
|
||||||
|
font-weight: bolder;
|
||||||
|
color: #bd001c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.valid.certdate{
|
||||||
|
color: #31c071;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<div class="standardContainer">
|
<div class="standardContainer">
|
||||||
<div class="ui basic segment">
|
<div class="ui basic segment">
|
||||||
<h2>TLS / SSL Certificates</h2>
|
<h2>TLS / SSL Certificates</h2>
|
||||||
@ -111,10 +121,12 @@
|
|||||||
return a.Domain > b.Domain
|
return a.Domain > b.Domain
|
||||||
});
|
});
|
||||||
data.forEach(entry => {
|
data.forEach(entry => {
|
||||||
|
let isExpired = entry.RemainingDays <= 0;
|
||||||
|
|
||||||
$("#certifiedDomainList").append(`<tr>
|
$("#certifiedDomainList").append(`<tr>
|
||||||
<td>${entry.Domain}</td>
|
<td>${entry.Domain}</td>
|
||||||
<td>${entry.LastModifiedDate}</td>
|
<td>${entry.LastModifiedDate}</td>
|
||||||
<td>${entry.ExpireDate} (${entry.RemainingDays} days left)</td>
|
<td class="${isExpired?"expired":"valid"} certdate">${entry.ExpireDate} (${!isExpired?entry.RemainingDays+" days left":"Expired"})</td>
|
||||||
<td><button title="Delete key-pair" class="ui mini basic red icon button" onclick="deleteCertificate('${entry.Domain}');"><i class="ui red trash icon"></i></button></td>
|
<td><button title="Delete key-pair" class="ui mini basic red icon button" onclick="deleteCertificate('${entry.Domain}');"><i class="ui red trash icon"></i></button></td>
|
||||||
</tr>`);
|
</tr>`);
|
||||||
});
|
});
|
||||||
|
@ -42,40 +42,54 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="field" >
|
<div class="field" >
|
||||||
<button class="ui basic button" onclick="addCredentialsToEditingList();"><i class="blue add icon"></i> Add Credential</button>
|
<button class="ui basic button" onclick="addCredentialsToEditingList();"><i class="blue add icon"></i> Add Credential</button>
|
||||||
|
<button class="ui basic button" style="float: right;" onclick="saveCredentials();"><i class="green save icon"></i> Save Credential</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
<div class="field" >
|
|
||||||
<button class="ui basic button" style="float: right;" onclick="saveCredentials();"><i class="green save icon"></i> Save</button>
|
|
||||||
<button class="ui basic button" style="float: right;" onclick="cancelCredentialEdit();"><i class="remove icon"></i> Cancel</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
<h3 class="ui header">No-Auth Paths</h3>
|
<h3 class="ui header">Authentication Exclusion Paths</h3>
|
||||||
<div class="scrolling content ui form">
|
<div class="scrolling content ui form">
|
||||||
<p>Exclude specific paths from the basic auth interface. Useful if you are hosting services require remote API access.</p>
|
<p>Exclude specific directories / paths which contains the following subpath prefix from authentication. Useful if you are hosting services require remote API access.</p>
|
||||||
<table class="ui very basic compacted unstackable celled table">
|
<table class="ui very basic compacted unstackable celled table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Username</th>
|
<th>Path Prefix</th>
|
||||||
<th>Password</th>
|
<th>Remove</th>
|
||||||
<th>Remove</th>
|
</tr></thead>
|
||||||
</tr></thead>
|
<tbody id="exclusionPaths">
|
||||||
<tbody id="inlineEditExclusionPaths">
|
<tr>
|
||||||
<tr>
|
<td colspan="2"><i class="ui green circle check icon"></i> No Path Excluded</td>
|
||||||
<td colspan="3"><i class="ui green circle check icon"></i> No Path Excluded</td>
|
</tr>
|
||||||
</tr>
|
</tbody>
|
||||||
</tbody>
|
</table>
|
||||||
</table>
|
<div class="field">
|
||||||
<div class="field">
|
<input id="newExclusionPath" type="text" placeholder="/public/api/" autocomplete="off">
|
||||||
<input id="inlineEditExclusionPath" type="text" placeholder="/api" autocomplete="off">
|
<small>Make sure you add the tailing slash for only selecting the files / folder inside that path.</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="field" >
|
<div class="field" >
|
||||||
<button class="ui basic button" onclick="addCredentialsToEditingList();"><i class="blue add icon"></i> Add Credential</button>
|
<button class="ui basic button" onclick="addExceptionPath();"><i class="blue add icon"></i> Add Exception</button>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui basic message">
|
||||||
|
<h4>How to use set excluded paths?</h4>
|
||||||
|
<p>All request URI that contains the given prefix will be allowed to bypass authentication and <b>the prefix must start with a slash.</b> For example, given the following prefix.<br>
|
||||||
|
<code>/public/res/</code><br>
|
||||||
|
<br>
|
||||||
|
Zoraxy will allow authentication bypass of any subdirectories or resources under the /public/res/ directory. For example, the following paths access will be able to bypass basic auth mechanism under this setting.<br>
|
||||||
|
<code>/public/res/photo.png</code><br>
|
||||||
|
<code>/public/res/far/boo/</code></p>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
<div class="field" >
|
||||||
|
<button class="ui basic button" style="float: right;" onclick="closeThisWrapper();">Close</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<br><br><br><br>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
let editingCredentials = [];
|
let editingCredentials = [];
|
||||||
@ -151,6 +165,80 @@
|
|||||||
updateEditingCredentialList();
|
updateEditingCredentialList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addExceptionPath(){
|
||||||
|
// Retrieve the username and password input values
|
||||||
|
var newExclusionPathMatchingPrefix = $('#newExclusionPath').val().trim();
|
||||||
|
if (newExclusionPathMatchingPrefix == ""){
|
||||||
|
parent.msgbox("Matching prefix cannot be empty!", false, 5000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/proxy/auth/exceptions/add",
|
||||||
|
data:{
|
||||||
|
ptype: editingEndpoint.ept,
|
||||||
|
ep: editingEndpoint.ep,
|
||||||
|
prefix: newExclusionPathMatchingPrefix
|
||||||
|
},
|
||||||
|
method: "POST",
|
||||||
|
success: function(data){
|
||||||
|
if (data.error != undefined){
|
||||||
|
parent.msgbox(data.error, false, 5000);
|
||||||
|
}else{
|
||||||
|
initExceptionPaths();
|
||||||
|
parent.msgbox("New exception path added", true);
|
||||||
|
$('#newExclusionPath').val("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeExceptionPath(object){
|
||||||
|
let matchingPrefix = $(object).attr("prefix");
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/proxy/auth/exceptions/delete",
|
||||||
|
data:{
|
||||||
|
ptype: editingEndpoint.ept,
|
||||||
|
ep: editingEndpoint.ep,
|
||||||
|
prefix: matchingPrefix
|
||||||
|
},
|
||||||
|
method: "POST",
|
||||||
|
success: function(data){
|
||||||
|
if (data.error != undefined){
|
||||||
|
parent.msgbox(data.error, false, 5000);
|
||||||
|
}else{
|
||||||
|
initExceptionPaths();
|
||||||
|
parent.msgbox("Exception path removed", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//Load exception paths from server
|
||||||
|
function initExceptionPaths(){
|
||||||
|
$.get(`/api/proxy/auth/exceptions/list?ptype=${editingEndpoint.ept}&ep=${editingEndpoint.ep}`, function(data){
|
||||||
|
if (data.error != undefined){
|
||||||
|
parent.msgbox(data.error, false, 5000);
|
||||||
|
}else{
|
||||||
|
if (data.length == 0){
|
||||||
|
$("#exclusionPaths").html(` <tr>
|
||||||
|
<td colspan="2"><i class="ui green circle check icon"></i> No Path Excluded</td>
|
||||||
|
</tr>`);
|
||||||
|
}else{
|
||||||
|
$("#exclusionPaths").html("");
|
||||||
|
data.forEach(function(rule){
|
||||||
|
$("#exclusionPaths").append(` <tr>
|
||||||
|
<td>${rule.PathPrefix}</td>
|
||||||
|
<td><button class="ui red basic mini icon button" onclick="removeExceptionPath(this);" prefix="${rule.PathPrefix}"><i class="ui red times icon"></i></button></td>
|
||||||
|
</tr>`);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
initExceptionPaths();
|
||||||
|
|
||||||
function updateEditingCredentialList() {
|
function updateEditingCredentialList() {
|
||||||
var tableBody = $('#inlineEditBasicAuthCredentialTable');
|
var tableBody = $('#inlineEditBasicAuthCredentialTable');
|
||||||
tableBody.empty();
|
tableBody.empty();
|
||||||
@ -195,7 +283,7 @@
|
|||||||
return isExists;
|
return isExists;
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancelCredentialEdit(){
|
function closeThisWrapper(){
|
||||||
parent.hideSideWrapper(true);
|
parent.hideSideWrapper(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +301,7 @@
|
|||||||
parent.msgbox(data.error, false, 6000);
|
parent.msgbox(data.error, false, 6000);
|
||||||
}else{
|
}else{
|
||||||
parent.msgbox("Credentials Updated");
|
parent.msgbox("Credentials Updated");
|
||||||
parent.hideSideWrapper(true);
|
//parent.hideSideWrapper(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user