setting up for basePath

pull/224/head^2
hunterlong 2020-01-12 23:11:53 -08:00
parent 8fe8b7e0b4
commit 479763f186
22 changed files with 85 additions and 62 deletions

View File

@ -274,6 +274,7 @@ func HelpEcho() {
fmt.Println(" HTTP_PROXY - Use a HTTP Proxy for HTTP Requests")
fmt.Println(" AUTH_USERNAME - HTTP Basic Authentication username")
fmt.Println(" AUTH_PASSWORD - HTTP Basic Authentication password")
fmt.Println(" BASE_PATH - Set the base URL prefix (set to 'monitor' if URL is domain.com/monitor)")
fmt.Println(" * You can insert environment variables into a '.env' file in root directory.")
fmt.Println("Give Statping a Star at https://github.com/hunterlong/statping")
}

View File

@ -12,6 +12,10 @@ import (
"time"
)
var (
basePath = "/"
)
var handlerFuncs = func(w http.ResponseWriter, r *http.Request) template.FuncMap {
return template.FuncMap{
"js": func(html interface{}) template.JS {
@ -88,7 +92,7 @@ var handlerFuncs = func(w http.ResponseWriter, r *http.Request) template.FuncMap
return utils.UnderScoreString(html)
},
"URL": func() string {
return r.URL.String()
return basePath + r.URL.String()
},
"CHART_DATA": func() string {
return ""
@ -145,5 +149,8 @@ var handlerFuncs = func(w http.ResponseWriter, r *http.Request) template.FuncMap
"NewGroup": func() *types.Group {
return new(types.Group)
},
"BasePath": func() string {
return basePath
},
}
}

View File

@ -45,13 +45,16 @@ var (
mainTmpl = `{{define "main" }} {{ template "base" . }} {{ end }}`
templates = []string{"base.gohtml", "head.gohtml", "nav.gohtml", "footer.gohtml", "scripts.gohtml", "form_service.gohtml", "form_notifier.gohtml", "form_integration.gohtml", "form_group.gohtml", "form_user.gohtml", "form_checkin.gohtml", "form_message.gohtml"}
javascripts = []string{"charts.js", "chart_index.js"}
mainTemplate *template.Template
)
// RunHTTPServer will start a HTTP server on a specific IP and port
func RunHTTPServer(ip string, port int) error {
host := fmt.Sprintf("%v:%v", ip, port)
if os.Getenv("BASE_PATH") != "" {
basePath = "/" + os.Getenv("BASE_PATH")
}
key := utils.FileExists(utils.Directory + "/server.key")
cert := utils.FileExists(utils.Directory + "/server.crt")
@ -184,22 +187,22 @@ func IsUser(r *http.Request) bool {
return session.Values["authenticated"].(bool)
}
func loadTemplate(w http.ResponseWriter, r *http.Request) error {
func loadTemplate(w http.ResponseWriter, r *http.Request) (*template.Template, error) {
var err error
mainTemplate = template.New("main")
mainTemplate.Funcs(handlerFuncs(w, r))
mainTemplate := template.New("main")
mainTemplate, err = mainTemplate.Parse(mainTmpl)
if err != nil {
log.Errorln(err)
return err
return nil, err
}
mainTemplate.Funcs(handlerFuncs(w, r))
// render all templates
for _, temp := range templates {
tmp, _ := source.TmplBox.String(temp)
mainTemplate, err = mainTemplate.Parse(tmp)
if err != nil {
log.Errorln(err)
return err
return nil, err
}
}
// render all javascript files
@ -208,22 +211,25 @@ func loadTemplate(w http.ResponseWriter, r *http.Request) error {
mainTemplate, err = mainTemplate.Parse(tmp)
if err != nil {
log.Errorln(err)
return err
return nil, err
}
}
return err
return mainTemplate, err
}
// ExecuteResponse will render a HTTP response for the front end user
func ExecuteResponse(w http.ResponseWriter, r *http.Request, file string, data interface{}, redirect interface{}) {
if url, ok := redirect.(string); ok {
http.Redirect(w, r, url, http.StatusSeeOther)
http.Redirect(w, r, basePath+url, http.StatusSeeOther)
return
}
if usingSSL {
w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
}
loadTemplate(w, r)
mainTemplate, err := loadTemplate(w, r)
if err != nil {
log.Errorln(err)
}
render, err := source.TmplBox.String(file)
if err != nil {
log.Errorln(err)

View File

@ -54,7 +54,7 @@ func authenticated(handler func(w http.ResponseWriter, r *http.Request), redirec
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !IsFullAuthenticated(r) {
if redirect {
http.Redirect(w, r, "/", http.StatusSeeOther)
http.Redirect(w, r, basePath, http.StatusSeeOther)
} else {
sendUnauthorizedJson(w, r)
}
@ -69,7 +69,7 @@ func readOnly(handler func(w http.ResponseWriter, r *http.Request), redirect boo
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !IsReadAuthenticated(r) {
if redirect {
http.Redirect(w, r, "/", http.StatusSeeOther)
http.Redirect(w, r, basePath, http.StatusSeeOther)
} else {
sendUnauthorizedJson(w, r)
}

View File

@ -86,7 +86,7 @@ func testNotificationHandler(w http.ResponseWriter, r *http.Request) {
fakeNotifer, notif, err := notifier.SelectNotifier(method)
if err != nil {
log.Errorln(fmt.Sprintf("issue saving notifier %v: %v", method, err))
ExecuteResponse(w, r, "settings.gohtml", core.CoreApp, "/settings")
ExecuteResponse(w, r, "settings.gohtml", core.CoreApp, "settings")
return
}

View File

@ -39,25 +39,30 @@ func Router() *mux.Router {
dir := utils.Directory
CacheStorage = NewStorage()
r := mux.NewRouter().StrictSlash(true)
if os.Getenv("AUTH_USERNAME") != "" && os.Getenv("AUTH_PASSWORD") != "" {
authUser = os.Getenv("AUTH_USERNAME")
authPass = os.Getenv("AUTH_PASSWORD")
r.Use(basicAuthHandler)
}
if basePath != "/" {
r = r.PathPrefix(basePath).Subrouter()
}
r.Use(sendLog)
r.Handle("/", http.HandlerFunc(indexHandler))
if source.UsingAssets(dir) {
indexHandler := http.FileServer(http.Dir(dir + "/assets/"))
r.PathPrefix("/css/").Handler(http.StripPrefix("/css/", http.FileServer(http.Dir(dir+"/assets/css"))))
r.PathPrefix("/font/").Handler(http.StripPrefix("/font/", http.FileServer(http.Dir(dir+"/assets/font"))))
r.PathPrefix("/js/").Handler(http.StripPrefix("/js/", http.FileServer(http.Dir(dir+"/assets/js"))))
r.PathPrefix("/css/").Handler(http.StripPrefix(basePath+"/css/", http.FileServer(http.Dir(dir+"/assets/css"))))
r.PathPrefix("/font/").Handler(http.StripPrefix(basePath+"/font/", http.FileServer(http.Dir(dir+"/assets/font"))))
r.PathPrefix("/js/").Handler(http.StripPrefix(basePath+"/js/", http.FileServer(http.Dir(dir+"/assets/js"))))
r.PathPrefix("/robots.txt").Handler(indexHandler)
r.PathPrefix("/favicon.ico").Handler(indexHandler)
r.PathPrefix("/banner.png").Handler(indexHandler)
} else {
r.PathPrefix("/css/").Handler(http.StripPrefix("/css/", http.FileServer(source.CssBox.HTTPBox())))
r.PathPrefix("/font/").Handler(http.StripPrefix("/font/", http.FileServer(source.FontBox.HTTPBox())))
r.PathPrefix("/js/").Handler(http.StripPrefix("/js/", http.FileServer(source.JsBox.HTTPBox())))
r.PathPrefix("/css/").Handler(http.StripPrefix(basePath+"/css/", http.FileServer(source.CssBox.HTTPBox())))
r.PathPrefix("/font/").Handler(http.StripPrefix(basePath+"/font/", http.FileServer(source.FontBox.HTTPBox())))
r.PathPrefix("/js/").Handler(http.StripPrefix(basePath+"/js/", http.FileServer(source.JsBox.HTTPBox())))
r.PathPrefix("/robots.txt").Handler(http.FileServer(source.TmplBox.HTTPBox()))
r.PathPrefix("/favicon.ico").Handler(http.FileServer(source.TmplBox.HTTPBox()))
r.PathPrefix("/banner.png").Handler(http.FileServer(source.TmplBox.HTTPBox()))

View File

@ -73,7 +73,7 @@ func saveSettingsHandler(w http.ResponseWriter, r *http.Request) {
}
//notifiers.OnSettingsSaved(core.CoreApp.ToCore())
ExecuteResponse(w, r, "settings.gohtml", core.CoreApp, "/settings")
ExecuteResponse(w, r, "settings.gohtml", core.CoreApp, "settings")
}
func saveSASSHandler(w http.ResponseWriter, r *http.Request) {
@ -86,7 +86,7 @@ func saveSASSHandler(w http.ResponseWriter, r *http.Request) {
source.SaveAsset([]byte(mobile), utils.Directory, "scss/mobile.scss")
source.CompileSASS(utils.Directory)
resetRouter()
ExecuteResponse(w, r, "settings.gohtml", core.CoreApp, "/settings")
ExecuteResponse(w, r, "settings.gohtml", core.CoreApp, "settings")
}
func saveAssetsHandler(w http.ResponseWriter, r *http.Request) {
@ -101,7 +101,7 @@ func saveAssetsHandler(w http.ResponseWriter, r *http.Request) {
log.Errorln("Default 'base.css' was inserted because SASS did not work.")
}
resetRouter()
ExecuteResponse(w, r, "settings.gohtml", core.CoreApp, "/settings")
ExecuteResponse(w, r, "settings.gohtml", core.CoreApp, "settings")
}
func deleteAssetsHandler(w http.ResponseWriter, r *http.Request) {
@ -109,7 +109,7 @@ func deleteAssetsHandler(w http.ResponseWriter, r *http.Request) {
log.Errorln(fmt.Errorf("error deleting all assets %v", err))
}
resetRouter()
ExecuteResponse(w, r, "settings.gohtml", core.CoreApp, "/settings")
ExecuteResponse(w, r, "settings.gohtml", core.CoreApp, "settings")
}
func bulkImportHandler(w http.ResponseWriter, r *http.Request) {

View File

@ -1,7 +1,7 @@
{{define "form_checkin"}}
<div class="card">
<div class="card-body">
<form class="ajax_form" action="/api/checkin" data-redirect="/service/{{.Id}}" method="POST">
<form class="ajax_form" action="api/checkin" data-redirect="/service/{{.Id}}" method="POST">
<div class="form-group row">
<div class="col-md-3">
<label for="checkin_interval" class="col-form-label">Checkin Name</label>

View File

@ -2,7 +2,7 @@
<div class="card">
<div class="card-body">
{{$message := .}}
<form class="ajax_form" action="/api/groups{{if ne .Id 0}}/{{.Id}}{{end}}" data-redirect="/services" method="POST">
<form class="ajax_form" action="api/groups{{if ne .Id 0}}/{{.Id}}{{end}}" data-redirect="services" method="POST">
<div class="form-group row">
<label for="username" class="col-sm-4 col-form-label">Group Name</label>
<div class="col-sm-8">

View File

@ -2,7 +2,7 @@
<div class="card">
<div class="card-body">
{{$message := .}}
<form class="ajax_form" action="/api/messages{{if ne .Id 0}}/{{.Id}}{{end}}" data-redirect="/messages" method="POST">
<form class="ajax_form" action="api/messages{{if ne .Id 0}}/{{.Id}}{{end}}" data-redirect="/messages" method="POST">
<div class="form-group row">
<label for="username" class="col-sm-4 col-form-label">Title</label>
<div class="col-sm-8">

View File

@ -1,6 +1,6 @@
{{define "form_integration"}}
{{$i := .Get}}
<form class="integration_{{underscore $i.ShortName }}" action="/settings/integrator/{{ $i.ShortName }}" method="POST">
<form class="integration_{{underscore $i.ShortName }}" action="settings/integrator/{{ $i.ShortName }}" method="POST">
<input type="hidden" name="integrator" class="form-control" value="{{ $i.ShortName }}">
{{if $i.ShortName}}<h4 class="text-capitalize">{{$i.ShortName}}</h4>{{end}}
{{if $i.Description}}<p class="small text-muted">{{safe $i.Description}}</p>{{end}}

View File

@ -2,7 +2,7 @@
<div class="card">
<div class="card-body">
{{$message := .}}
<form class="ajax_form" action="/api/messages{{if ne .Id 0}}/{{.Id}}{{end}}" data-redirect="/messages" method="POST">
<form class="ajax_form" action="api/messages{{if ne .Id 0}}/{{.Id}}{{end}}" data-redirect="messages" method="POST">
<div class="form-group row">
<label for="username" class="col-sm-4 col-form-label">Title</label>
<div class="col-sm-8">

View File

@ -1,6 +1,6 @@
{{define "form_notifier"}}
{{$n := .Select}}
<form class="ajax_form {{underscore $n.Method }}" data-func="SaveNotifier" action="/api/notifier/{{ $n.Method }}" method="POST">
<form class="ajax_form {{underscore $n.Method }}" data-func="SaveNotifier" action="api/notifier/{{ $n.Method }}" method="POST">
{{if $n.Title}}<h4 class="text-capitalize">{{$n.Title}}</h4>{{end}}
{{if $n.Description}}<p class="small text-muted">{{safe $n.Description}}</p>{{end}}

View File

@ -2,7 +2,7 @@
<div class="card">
<div class="card-body">
{{$s := .}}
<form class="ajax_form" action="/api/services{{if ne .Id 0}}/{{.Id}}{{end}}" data-redirect="/services" method="POST">
<form class="ajax_form" action="api/services{{if ne .Id 0}}/{{.Id}}{{end}}" data-redirect="services" method="POST">
<h4 class="mb-5 text-muted">Basic Information</h4>
<div class="form-group row">
<label for="service_name" class="col-sm-4 col-form-label">Service Name</label>

View File

@ -1,7 +1,7 @@
{{define "form_user"}}
<div class="card">
<div class="card-body">
<form class="ajax_form" action="/api/users{{if ne .Id 0}}/{{.Id}}{{end}}" data-redirect="/users" method="POST">
<form class="ajax_form" action="api/users{{if ne .Id 0}}/{{.Id}}{{end}}" data-redirect="users" method="POST">
<div class="form-group row">
<label for="username" class="col-sm-4 col-form-label">Username</label>
<div class="col-6 col-md-4">

View File

@ -4,16 +4,17 @@
<title>{{block "title" .}} {{end}}</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, maximum-scale=1.0, user-scalable=0">
<meta name="description" content="{{block "description" .}}{{end}}">
<base href="{{BasePath}}/">
{{if USE_CDN}}
<link rel="shortcut icon" type="image/x-icon" href="https://assets.statping.com/favicon.ico">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
<link rel="stylesheet" href="https://assets.statping.com/base.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.1/css/all.css" integrity="sha384-5sAR7xN1Nv6T6+dT2mhtzEpVJvfS3NScPQTrOxhwjIuvcA67KV2R5Jz6kr4abQsz" crossorigin="anonymous">
{{ else }}
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/base.css">
<link rel="stylesheet" href="/font/all.css">
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/base.css">
<link rel="stylesheet" href="font/all.css">
{{end}}
{{block "extra_css" .}} {{end}}
</head>

View File

@ -10,7 +10,7 @@
Incorrect login information submitted, try again.
</div>
{{ end }}
<form action="/dashboard" class="spin_form" method="POST">
<form action="dashboard" class="spin_form" method="POST">
<div class="form-group row">
<label for="username" class="col-sm-2 col-form-label">Username</label>
<div class="col-sm-10">

View File

@ -1,40 +1,40 @@
{{define "nav"}}
{{$isAdmin := Auth}}
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="/">Statping</a>
<a class="navbar-brand" href="#">Statping</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarText">
<ul class="navbar-nav mr-auto">
<li class="nav-item{{ if eq URL "/dashboard" }} active{{ end }}">
<a class="nav-link" href="/dashboard">Dashboard</a>
<li class="nav-item{{ if eq URL "dashboard" }} active{{ end }}">
<a class="nav-link" href="dashboard">Dashboard</a>
</li>
<li class="nav-item{{ if eq URL "/services" }} active{{ end }}">
<a class="nav-link" href="/services">Services</a>
<li class="nav-item{{ if eq URL "services" }} active{{ end }}">
<a class="nav-link" href="services">Services</a>
</li>
<li class="nav-item{{ if eq URL "/users" }} active{{ end }}">
<a class="nav-link" href="/users">Users</a>
<li class="nav-item{{ if eq URL "users" }} active{{ end }}">
<a class="nav-link" href="users">Users</a>
</li>
<li class="nav-item{{ if eq URL "/messages" }} active{{ end }}">
<a class="nav-link" href="/messages">Messages</a>
<li class="nav-item{{ if eq URL "messages" }} active{{ end }}">
<a class="nav-link" href="messages">Messages</a>
</li>
{{ if $isAdmin }}
<li class="nav-item{{ if eq URL "/settings" }} active{{ end }}">
<a class="nav-link" href="/settings">Settings</a>
<li class="nav-item{{ if eq URL "settings" }} active{{ end }}">
<a class="nav-link" href="settings">Settings</a>
</li>
<li class="nav-item{{ if eq URL "/logs" }} active{{ end }}">
<a class="nav-link" href="/logs">Logs</a>
<li class="nav-item{{ if eq URL "logs" }} active{{ end }}">
<a class="nav-link" href="logs">Logs</a>
</li>
{{end}}
<li class="nav-item{{ if eq URL "/help" }} active{{ end }}">
<a class="nav-link" href="/help">Help</a>
<li class="nav-item{{ if eq URL "help" }} active{{ end }}">
<a class="nav-link" href="help">Help</a>
</li>
</ul>
<span class="navbar-text">
<a class="nav-link" href="/logout">Logout</a>
<a class="nav-link" href="logout">Logout</a>
</span>
</div>
</nav>
{{end}}
{{end}}

View File

@ -5,10 +5,10 @@
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<script src="https://assets.statping.com/main.js"></script>
{{ else }}
<script src="/js/jquery-3.3.1.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
<script src="/js/apexcharts.min.js"></script>
<script src="/js/main.js"></script>
<script src="{{BasePath}}/js/jquery-3.3.1.min.js"></script>
<script src="{{BasePath}}/js/bootstrap.min.js"></script>
<script src="{{BasePath}}/js/apexcharts.min.js"></script>
<script src="{{BasePath}}/js/main.js"></script>
{{end}}
{{block "extra_scripts" .}} {{end}}
{{end}}

View File

@ -35,7 +35,7 @@
{{end}}
<div class="tab-content" id="v-pills-tabContent">
<div class="tab-pane fade show active" id="v-pills-home" role="tabpanel" aria-labelledby="v-pills-home-tab">
<form method="POST" action="/settings">
<form method="POST" action="settings">
<div class="form-group">
<label for="project">Project Name</label>
<input type="text" name="project" class="form-control" value="{{ .Name }}" id="project" placeholder="Great Uptime">
@ -196,7 +196,7 @@
</div>
</div>
{{ else }}
<form method="POST" action="/settings/css">
<form method="POST" action="settings/css">
<ul class="nav nav-pills mb-3" id="pills-tab" role="tablist">
<li class="nav-item col text-center">
<a class="nav-link active" id="pills-vars-tab" data-toggle="pill" href="#pills-vars" role="tab" aria-controls="pills-vars" aria-selected="true">Variables</a>

View File

@ -11,7 +11,7 @@
{{ .Error }}
</div>
{{ end }}
<form method="POST" id="setup_form" action="/setup">
<form method="POST" id="setup_form" action="setup">
<div class="row">
<div class="col-6">
<div class="form-group">

View File

@ -1,6 +1,9 @@
package utils
import "errors"
import (
"errors"
"os"
)
func DirWritable(path string) (bool, error) {
info, err := os.Stat(path)