From 1b4e6beb6165f98453586291d60baea1ade2cd22 Mon Sep 17 00:00:00 2001 From: Anders Pitman Date: Sun, 11 Oct 2020 13:32:10 -0600 Subject: [PATCH] Implement confirm dialog Also moved shared styles to separate file which is included by templates. --- boring_proxy_admin.go | 101 +++++++++++++++++++++++++++++++--------- webui/confirm.tmpl | 42 +++++++++++++++++ webui/index.tmpl | 105 ++---------------------------------------- webui/styles.css | 100 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 226 insertions(+), 122 deletions(-) create mode 100644 webui/confirm.tmpl create mode 100644 webui/styles.css diff --git a/boring_proxy_admin.go b/boring_proxy_admin.go index ead0aca..55d7387 100644 --- a/boring_proxy_admin.go +++ b/boring_proxy_admin.go @@ -10,18 +10,39 @@ import ( "strconv" ) + +type IndexData struct { + Styles template.CSS + Tunnels map[string]Tunnel +} + +type ConfirmData struct { + Styles template.CSS + Message string + ConfirmUrl string + CancelUrl string +} + func (p *BoringProxy) handleAdminRequest(w http.ResponseWriter, r *http.Request) { + box, err := rice.FindBox("webui") + if err != nil { + w.WriteHeader(500) + io.WriteString(w, "Error opening webui") + return + } + + stylesText, err := box.String("styles.css") + if err != nil { + w.WriteHeader(500) + io.WriteString(w, "Error reading styles.css") + return + } + switch r.URL.Path { case "/login": p.handleLogin(w, r) case "/": - box, err := rice.FindBox("webui") - if err != nil { - w.WriteHeader(500) - io.WriteString(w, "Error opening webui") - return - } token, err := extractToken("access_token", r) if err != nil { @@ -60,7 +81,12 @@ func (p *BoringProxy) handleAdminRequest(w http.ResponseWriter, r *http.Request) return } - tmpl.Execute(w, p.db.GetTunnels()) + indexData := IndexData { + Styles: template.CSS(stylesText), + Tunnels: p.db.GetTunnels(), + } + + tmpl.Execute(w, indexData) //io.WriteString(w, indexTemplate) @@ -81,6 +107,48 @@ func (p *BoringProxy) handleAdminRequest(w http.ResponseWriter, r *http.Request) p.handleTunnels(w, r) + case "/confirm-delete-tunnel": + box, err := rice.FindBox("webui") + if err != nil { + w.WriteHeader(500) + io.WriteString(w, "Error opening webui") + return + } + + confirmTemplate, err := box.String("confirm.tmpl") + if err != nil { + w.WriteHeader(500) + io.WriteString(w, "Error reading confirm.tmpl") + return + } + + tmpl, err := template.New("test").Parse(confirmTemplate) + if err != nil { + w.WriteHeader(500) + log.Println(err) + io.WriteString(w, "Error compiling confirm.tmpl") + return + } + + r.ParseForm() + + if len(r.Form["domain"]) != 1 { + w.WriteHeader(400) + w.Write([]byte("Invalid domain parameter")) + return + } + domain := r.Form["domain"][0] + + data := &ConfirmData{ + Styles: template.CSS(stylesText), + Message: fmt.Sprintf("Are you sure you want to delete %s?", domain), + ConfirmUrl: fmt.Sprintf("/delete-tunnel?domain=%s", domain), + CancelUrl: "/", + } + + tmpl.Execute(w, data) + + case "/delete-tunnel": token, err := extractToken("access_token", r) if err != nil { @@ -97,14 +165,14 @@ func (p *BoringProxy) handleAdminRequest(w http.ResponseWriter, r *http.Request) r.ParseForm() - if len(r.Form["host"]) != 1 { + if len(r.Form["domain"]) != 1 { w.WriteHeader(400) - w.Write([]byte("Invalid host parameter")) + w.Write([]byte("Invalid domain parameter")) return } - host := r.Form["host"][0] + domain := r.Form["domain"][0] - p.tunMan.DeleteTunnel(host) + p.tunMan.DeleteTunnel(domain) http.Redirect(w, r, "/", 307) default: @@ -116,20 +184,9 @@ func (p *BoringProxy) handleAdminRequest(w http.ResponseWriter, r *http.Request) func (p *BoringProxy) handleTunnels(w http.ResponseWriter, r *http.Request) { - query := r.URL.Query() - switch r.Method { case "POST": p.handleCreateTunnel(w, r) - case "DELETE": - if len(query["host"]) != 1 { - w.WriteHeader(400) - w.Write([]byte("Invalid host parameter")) - return - } - host := query["host"][0] - - p.tunMan.DeleteTunnel(host) default: w.WriteHeader(405) w.Write([]byte("Invalid method for /tunnels")) diff --git a/webui/confirm.tmpl b/webui/confirm.tmpl new file mode 100644 index 0000000..2c8972e --- /dev/null +++ b/webui/confirm.tmpl @@ -0,0 +1,42 @@ + + + + + + + boringproxy + + + + + + + + +
+
+

+ {{.Message}} +

+ +
+
+ + diff --git a/webui/index.tmpl b/webui/index.tmpl index 482b8c0..9014185 100644 --- a/webui/index.tmpl +++ b/webui/index.tmpl @@ -9,102 +9,7 @@ @@ -118,13 +23,13 @@ Tokens
- {{range $domain, $tunnel:= .}} + {{range $domain, $tunnel:= .Tunnels}}
{{$domain}}:{{$tunnel.TunnelPort}} -> {{$tunnel.ClientName}}:{{$tunnel.ClientPort}}
- - + +
{{end}} @@ -137,7 +42,7 @@ - +
diff --git a/webui/styles.css b/webui/styles.css new file mode 100644 index 0000000..d2bc126 --- /dev/null +++ b/webui/styles.css @@ -0,0 +1,100 @@ +:root { + --hover-color: #ddd; +} + +body { + font-family: Helvetica; + display: flex; + justify-content: center; +} + +main { + max-width: 900px; +} + +#menu-label { + font-size: 18px; + font-weight: bold; + display: block; + width: 100%; + border: 1px solid black; + cursor: pointer; + padding: 5px; + user-select: none; +} +#menu-label:hover { + background: var(--hover-color); +} + +.menu { + display: none; + flex-direction: column; + position: absolute; + background: #fff; + border: 1px solid black; + min-width: 256px; +} + +.menu-item { + border-bottom: 1px solid black; + padding: 5px; + text-decoration: none; +} +.menu-item:hover { + background: var(--hover-color); +} +.menu-item:visited { + color: #000; +} + +#menu-toggle { + display: none; +} + +#menu-toggle:checked ~ .menu { + display: flex; +} + +.button { + background: #ccc; + border: none; + border-radius: .25em; + margin: .5em; + padding: .4em .8em; + cursor: pointer; +} + +.green-button { + background: #4CAF50; + color: #fff; +} + +.red-button { + background: #f44336; + color: #fff; +} + +.button-row { + display: flex; + justify-content: center; +} + +.tunnel-list { + display: flex; + flex-direction: column; +} + +.tunnel { + padding: 5px; + border-bottom: 1px solid black; + display: flex; + justify-content: space-between; + align-items: center; +} +.tunnel:hover { + background: var(--hover-color); +} + +.tunnel-adder { + padding: 5px; +}