Files
gotermix/internals/workspace.go
T

119 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package internals
import (
"encoding/json"
"net/http"
"strings"
"sync"
)
// credsMu guards concurrent reads/writes of appCreds.Workspaces from HTTP
// handlers. Credential fields (Username/Hash/etc.) are only written at
// startup via CLI flags that call os.Exit, so they don't need the lock.
var credsMu sync.Mutex
// WorkspacePaneLayout is a recursive pane tree.
// Leaf nodes own a PTY session; split nodes contain two children.
type WorkspacePaneLayout struct {
Type string `json:"type"` // "leaf" | "split"
ID string `json:"id,omitempty"` // PTY session hex ID (leaf only)
Dir string `json:"dir,omitempty"` // "h" | "v" (split only)
Ratio float64 `json:"ratio,omitempty"` // 0.10.9 (split only)
A *WorkspacePaneLayout `json:"a,omitempty"`
B *WorkspacePaneLayout `json:"b,omitempty"`
}
// WorkspaceTabLayout stores one tab's label and pane tree.
type WorkspaceTabLayout struct {
TabID string `json:"tab_id"`
Label string `json:"label"`
Root WorkspacePaneLayout `json:"root"`
}
// WorkspaceLayout is the full layout stored per workspace ID in gws-creds.json.
type WorkspaceLayout struct {
ID string `json:"id"`
Tabs []WorkspaceTabLayout `json:"tabs"`
}
// handleWorkspaceAPI dispatches GET / PUT / DELETE for /api/workspace/<id>.
// All methods require auth.
func handleWorkspaceAPI(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
if !isAuthed(r) {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(`{"error":"unauthorized"}`))
return
}
id := strings.TrimPrefix(r.URL.Path, "/api/workspace/")
if !validID(id) {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{"error":"invalid id"}`))
return
}
switch r.Method {
case http.MethodGet:
workspaceGet(w, id)
case http.MethodPut:
workspacePut(w, r, id)
case http.MethodDelete:
workspaceDelete(w, id)
default:
w.WriteHeader(http.StatusMethodNotAllowed)
w.Write([]byte(`{"error":"method not allowed"}`))
}
}
func workspaceGet(w http.ResponseWriter, id string) {
credsMu.Lock()
ws := appCreds.Workspaces[id]
credsMu.Unlock()
if ws == nil {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte(`{"error":"not found"}`))
return
}
json.NewEncoder(w).Encode(ws) //nolint:errcheck
}
func workspacePut(w http.ResponseWriter, r *http.Request, id string) {
var ws WorkspaceLayout
if err := json.NewDecoder(r.Body).Decode(&ws); err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{"error":"bad json"}`))
return
}
ws.ID = id
credsMu.Lock()
if appCreds.Workspaces == nil {
appCreds.Workspaces = make(map[string]*WorkspaceLayout)
}
appCreds.Workspaces[id] = &ws
err := saveCreds(appCreds)
credsMu.Unlock()
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(`{"error":"save failed"}`))
return
}
w.Write([]byte(`{"ok":true}`))
}
func workspaceDelete(w http.ResponseWriter, id string) {
credsMu.Lock()
if appCreds.Workspaces != nil {
delete(appCreds.Workspaces, id)
}
err := saveCreds(appCreds)
credsMu.Unlock()
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(`{"error":"save failed"}`))
return
}
w.Write([]byte(`{"ok":true}`))
}