Implement managing clients through web UI

This commit is contained in:
Anders Pitman 2022-02-17 13:38:27 -07:00
parent 5ae2b81882
commit 53aa3735a9
3 changed files with 136 additions and 1 deletions

31
templates/clients.tmpl Normal file
View File

@ -0,0 +1,31 @@
{{ template "header.tmpl" . }}
<div class='list'>
{{range $username, $user := .Users}}
{{range $clientName, $client := $user.Clients}}
<div class='list-item'>
<span class='client'>{{$clientName}} ({{$username}})</span>
<a href="/confirm-delete-client?owner={{$username}}&client-name={{$clientName}}">
<button class='button'>Delete</button>
</a>
</div>
{{end}}
{{end}}
</div>
<div class='client-adder'>
<form action="/clients" method="POST">
<label for="client-owner">Owner:</label>
<select id="client-owner" name="owner">
{{range $username, $user := .Users}}
<option value="{{$username}}">{{$username}}</option>
{{end}}
</select>
<label for="client-name">Client Name:</label>
<input type="text" name="client-name" required></input>
<button class='button' type="submit">Add Client</button>
</form>
</div>
{{ template "footer.tmpl" . }}

View File

@ -26,6 +26,7 @@
<a class='menu-item' href='/tunnels'>Tunnels</a>
<a class='menu-item' href='/edit-tunnel'>Add Tunnel</a>
<a class='menu-item' href='/tokens'>Tokens</a>
<a class='menu-item' href='/clients'>Clients</a>
{{ if $.User.IsAdmin }}
<a class='menu-item' href='/users'>Users</a>
{{ end }}

View File

@ -235,10 +235,16 @@ func (h *WebUiHandler) handleWebUiRequest(w http.ResponseWriter, r *http.Request
}
case "/tokens":
h.handleTokens(w, r, user, tokenData)
case "/clients":
h.handleClients(w, r, user, tokenData)
case "/confirm-delete-token":
h.confirmDeleteToken(w, r)
case "/delete-token":
h.deleteToken(w, r, tokenData)
case "/confirm-delete-client":
h.confirmDeleteClient(w, r)
case "/delete-client":
h.deleteClient(w, r, tokenData)
case "/confirm-logout":
data := &ConfirmData{
@ -402,6 +408,66 @@ func (h *WebUiHandler) handleTokens(w http.ResponseWriter, r *http.Request, user
}
}
func (h *WebUiHandler) handleClients(w http.ResponseWriter, r *http.Request, user User, tokenData TokenData) {
r.ParseForm()
switch r.Method {
case "GET":
var users map[string]User
// TODO: handle security checks in api
if user.IsAdmin {
users = h.db.GetUsers()
} else {
user, _ := h.db.GetUser(tokenData.Owner)
users = make(map[string]User)
users[tokenData.Owner] = user
}
clients := make(map[string]DbClient)
for _, user := range users {
for clientName, client := range user.Clients {
clients[clientName] = client
}
}
templateData := struct {
User User
Users map[string]User
Clients map[string]DbClient
}{
User: user,
Users: users,
Clients: clients,
}
err := h.tmpl.ExecuteTemplate(w, "clients.tmpl", templateData)
if err != nil {
w.WriteHeader(500)
io.WriteString(w, err.Error())
return
}
case "POST":
owner := r.Form.Get("owner")
clientName := r.Form.Get("client-name")
err := h.api.SetClient(tokenData, r.Form, owner, clientName)
if err != nil {
w.WriteHeader(500)
h.alertDialog(w, r, err.Error(), "/clients")
return
}
http.Redirect(w, r, "/clients", 303)
default:
w.WriteHeader(405)
h.alertDialog(w, r, "Invalid method for tokens", "/tokens")
return
}
}
func (h *WebUiHandler) handleLogin(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
@ -646,7 +712,6 @@ func (h *WebUiHandler) confirmDeleteToken(w http.ResponseWriter, r *http.Request
return
}
}
func (h *WebUiHandler) deleteToken(w http.ResponseWriter, r *http.Request, tokenData TokenData) {
r.ParseForm()
@ -660,6 +725,44 @@ func (h *WebUiHandler) deleteToken(w http.ResponseWriter, r *http.Request, token
http.Redirect(w, r, "/tokens", 303)
}
func (h *WebUiHandler) confirmDeleteClient(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
owner := r.Form.Get("owner")
clientName := r.Form.Get("client-name")
data := &ConfirmData{
Head: h.headHtml,
Message: fmt.Sprintf("Are you sure you want to delete client %s for user %s?", clientName, owner),
ConfirmUrl: fmt.Sprintf("/delete-client?owner=%s&client-name=%s", owner, clientName),
CancelUrl: "/clients",
}
err := h.tmpl.ExecuteTemplate(w, "confirm.tmpl", data)
if err != nil {
w.WriteHeader(500)
h.alertDialog(w, r, err.Error(), "/clients")
return
}
}
func (h *WebUiHandler) deleteClient(w http.ResponseWriter, r *http.Request, tokenData TokenData) {
r.ParseForm()
owner := r.Form.Get("owner")
clientName := r.Form.Get("client-name")
err := h.api.DeleteClient(tokenData, owner, clientName)
if err != nil {
w.WriteHeader(500)
h.alertDialog(w, r, err.Error(), "/clients")
return
}
http.Redirect(w, r, "/clients", 303)
}
func (h *WebUiHandler) alertDialog(w http.ResponseWriter, r *http.Request, message, redirectUrl string) error {
err := h.tmpl.ExecuteTemplate(w, "alert.tmpl", &AlertData{
Head: h.headHtml,