Major Improvements: - Added retry deployment buttons in machine list for failed deployments - Added retry button in SSH console modal footer for enhanced UX - Enhanced deployment process with comprehensive cleanup of existing services - Improved binary installation with password-based sudo authentication - Updated configuration generation to include all required sections (agent, ai, network, security) - Fixed deployment verification and error handling Security Enhancements: - Enhanced verifiedStopExistingServices with thorough cleanup process - Improved binary copying with proper sudo authentication - Added comprehensive configuration validation UX Improvements: - Users can retry deployments without re-running machine discovery - Retry buttons available from both machine list and console modal - Real-time deployment progress with detailed console output - Clear error states with actionable retry options Technical Changes: - Modified ServiceDeployment.tsx with retry button components - Enhanced api/setup_manager.go with improved deployment functions - Updated main.go with command line argument support (--config, --setup) - Added comprehensive zero-trust security validation system 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
79 lines
2.0 KiB
Go
79 lines
2.0 KiB
Go
package web
|
|
|
|
import (
|
|
"embed"
|
|
"net/http"
|
|
"strings"
|
|
)
|
|
|
|
// Static files embedded at build time
|
|
//go:embed static
|
|
//go:embed static/_next
|
|
//go:embed static/_next/static
|
|
//go:embed static/_next/static/css
|
|
//go:embed static/_next/static/chunks
|
|
var staticFiles embed.FS
|
|
|
|
// GetWebUIHandler returns HTTP handler for embedded web UI
|
|
func GetWebUIHandler() http.Handler {
|
|
// Use the embedded files directly (no static subdirectory)
|
|
staticFS := staticFiles
|
|
_, err := staticFiles.ReadFile("static/index.html")
|
|
if err != nil {
|
|
// Fallback to empty filesystem if no static files
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "text/html")
|
|
w.WriteHeader(200)
|
|
w.Write([]byte(`
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head><title>BZZZ Setup</title></head>
|
|
<body>
|
|
<h1>BZZZ Setup</h1>
|
|
<p>Web UI not yet built. Please build the React app first.</p>
|
|
<p>Run: <code>cd install/config-ui && npm run build</code></p>
|
|
</body>
|
|
</html>
|
|
`))
|
|
})
|
|
}
|
|
|
|
return http.FileServer(http.FS(staticFS))
|
|
}
|
|
|
|
// IsEmbeddedFileAvailable checks if a file exists in the embedded filesystem
|
|
func IsEmbeddedFileAvailable(path string) bool {
|
|
path = strings.TrimPrefix(path, "/")
|
|
if path == "" {
|
|
path = "index.html"
|
|
}
|
|
_, err := staticFiles.ReadFile("static/" + path)
|
|
return err == nil
|
|
}
|
|
|
|
// ServeEmbeddedFile serves a file from the embedded filesystem
|
|
func ServeEmbeddedFile(w http.ResponseWriter, r *http.Request, path string) {
|
|
path = strings.TrimPrefix(path, "/")
|
|
if path == "" {
|
|
path = "index.html"
|
|
}
|
|
|
|
content, err := staticFiles.ReadFile("static/" + path)
|
|
if err != nil {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
|
|
// Set content type based on file extension
|
|
contentType := "text/html"
|
|
if strings.HasSuffix(path, ".js") {
|
|
contentType = "application/javascript"
|
|
} else if strings.HasSuffix(path, ".css") {
|
|
contentType = "text/css"
|
|
} else if strings.HasSuffix(path, ".json") {
|
|
contentType = "application/json"
|
|
}
|
|
|
|
w.Header().Set("Content-Type", contentType)
|
|
w.Write(content)
|
|
} |