mirror of
https://github.com/boringproxy/boringproxy.git
synced 2025-02-25 18:55:29 -06:00
Implement confirm dialog
Also moved shared styles to separate file which is included by templates.
This commit is contained in:
parent
af539f4d68
commit
1b4e6beb61
@ -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"))
|
||||
|
42
webui/confirm.tmpl
Normal file
42
webui/confirm.tmpl
Normal file
@ -0,0 +1,42 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<title>boringproxy</title>
|
||||
|
||||
<link rel="icon" href="data:image/gif;base64,R0lGODlhEAAQAAAAACwAAAAAAQABAAACASgAOw==">
|
||||
|
||||
<style>
|
||||
{{.Styles}}
|
||||
|
||||
.dialog {
|
||||
margin: 20px;
|
||||
padding: 20px;
|
||||
font-size: 18px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main>
|
||||
<div class='dialog'>
|
||||
<p>
|
||||
{{.Message}}
|
||||
</p>
|
||||
<div class='button-row'>
|
||||
<a href="{{.ConfirmUrl}}">
|
||||
<button class='button red-button'>Confirm</button>
|
||||
</a>
|
||||
<a href="{{.CancelUrl}}">
|
||||
<button class='button green-button'>Cancel</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
105
webui/index.tmpl
105
webui/index.tmpl
@ -9,102 +9,7 @@
|
||||
<link rel="icon" href="data:image/gif;base64,R0lGODlhEAAQAAAAACwAAAAAAQABAAACASgAOw==">
|
||||
|
||||
<style>
|
||||
|
||||
: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;
|
||||
padding: .4em .8em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.add-button {
|
||||
background: #4CAF50;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.delete-button {
|
||||
background: #f44336;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
{{.Styles}}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
@ -118,13 +23,13 @@
|
||||
<a class='menu-item' href='/tokens'>Tokens</a>
|
||||
</div>
|
||||
<div class='tunnel-list'>
|
||||
{{range $domain, $tunnel:= .}}
|
||||
{{range $domain, $tunnel:= .Tunnels}}
|
||||
<div class='tunnel'>
|
||||
<div>
|
||||
<a href="https://{{$domain}}">{{$domain}}</a>:{{$tunnel.TunnelPort}} -> {{$tunnel.ClientName}}:{{$tunnel.ClientPort}}
|
||||
</div>
|
||||
<a href="/delete-tunnel?host={{$domain}}">
|
||||
<button class='button delete-button'>Delete</button>
|
||||
<a href="/confirm-delete-tunnel?domain={{$domain}}">
|
||||
<button class='button red-button'>Delete</button>
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
@ -137,7 +42,7 @@
|
||||
<input type="text" id="client-name" name="client-name">
|
||||
<label for="client-port">Client Port:</label>
|
||||
<input type="text" id="client-port" name="client-port">
|
||||
<button class='button add-button' type="submit">Add/Update Tunnel</button>
|
||||
<button class='button green-button' type="submit">Add/Update Tunnel</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
100
webui/styles.css
Normal file
100
webui/styles.css
Normal file
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user