v0.4.6: MariaDB validation fix + dashboard deployed-only + protected stack restart
- Fix ValidateDump() to scan first 10 lines for header (MariaDB 11.4+ sandbox comment) - Dashboard shows only deployed/protected stacks, heading "Telepített alkalmazások" - Protected stacks show restart button when operational (both dashboard + stacks page) - API blocks all actions except restart on protected stacks - docker-setup.sh creates .felhom.yml for FileBrowser (subdomain: files) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -207,6 +207,12 @@ func (r *Router) deployStack(w http.ResponseWriter, req *http.Request, name stri
|
|||||||
func (r *Router) actionStack(w http.ResponseWriter, action, name string) {
|
func (r *Router) actionStack(w http.ResponseWriter, action, name string) {
|
||||||
r.logger.Printf("[API] %s requested for stack: %s", action, name)
|
r.logger.Printf("[API] %s requested for stack: %s", action, name)
|
||||||
|
|
||||||
|
// Protected stacks only allow restart — block all other actions
|
||||||
|
if r.cfg.IsProtectedStack(name) && action != "restart" {
|
||||||
|
writeJSON(w, http.StatusForbidden, apiResponse{OK: false, Error: fmt.Sprintf("cannot %s protected stack %s", action, name)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
switch action {
|
switch action {
|
||||||
case "start":
|
case "start":
|
||||||
|
|||||||
@@ -264,18 +264,38 @@ func ValidateDump(filePath string, dbType DBType) DumpValidation {
|
|||||||
}
|
}
|
||||||
v.TableCount = tableCount
|
v.TableCount = tableCount
|
||||||
|
|
||||||
// Basic header check
|
// Header check — scan first 10 lines for expected dump header
|
||||||
|
// MariaDB 11.4+ prepends a sandbox comment before the header line
|
||||||
|
headerFound := false
|
||||||
|
lines := strings.SplitN(content, "\n", 11) // at most 11 parts = 10 lines
|
||||||
|
for i, line := range lines {
|
||||||
|
if i >= 10 {
|
||||||
|
break
|
||||||
|
}
|
||||||
switch dbType {
|
switch dbType {
|
||||||
case DBTypePostgres:
|
|
||||||
if !strings.HasPrefix(content, "--") {
|
|
||||||
v.Error = "PostgreSQL dump missing comment header"
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
case DBTypeMariaDB:
|
case DBTypeMariaDB:
|
||||||
if !strings.HasPrefix(content, "-- ") {
|
if strings.HasPrefix(line, "-- MariaDB dump") ||
|
||||||
v.Error = "MariaDB dump missing comment header"
|
strings.HasPrefix(line, "-- MySQL dump") ||
|
||||||
return v
|
strings.HasPrefix(line, "-- mysqldump") {
|
||||||
|
headerFound = true
|
||||||
}
|
}
|
||||||
|
case DBTypePostgres:
|
||||||
|
if strings.HasPrefix(line, "-- PostgreSQL database dump") {
|
||||||
|
headerFound = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if headerFound {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !headerFound {
|
||||||
|
switch dbType {
|
||||||
|
case DBTypeMariaDB:
|
||||||
|
v.Error = "MariaDB dump missing comment header"
|
||||||
|
case DBTypePostgres:
|
||||||
|
v.Error = "PostgreSQL dump missing comment header"
|
||||||
|
}
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
if tableCount == 0 {
|
if tableCount == 0 {
|
||||||
|
|||||||
@@ -36,10 +36,18 @@ func (s *Server) dashboardHandler(w http.ResponseWriter, _ *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter to deployed + protected stacks only for dashboard display
|
||||||
|
var deployedStacks []stacks.Stack
|
||||||
|
for _, st := range stackList {
|
||||||
|
if st.Deployed || st.Protected {
|
||||||
|
deployedStacks = append(deployedStacks, st)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sysInfo := system.GetInfo(s.cfg.Paths.HDDPath, s.cpuCollector)
|
sysInfo := system.GetInfo(s.cfg.Paths.HDDPath, s.cpuCollector)
|
||||||
|
|
||||||
data := s.baseData("dashboard", "Vezérlőpult")
|
data := s.baseData("dashboard", "Vezérlőpult")
|
||||||
data["Stacks"] = stackList
|
data["Stacks"] = deployedStacks
|
||||||
data["RunningCount"] = running
|
data["RunningCount"] = running
|
||||||
data["StoppedCount"] = stopped
|
data["StoppedCount"] = stopped
|
||||||
data["TotalCount"] = len(stackList)
|
data["TotalCount"] = len(stackList)
|
||||||
|
|||||||
@@ -120,7 +120,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
<h3>Alkalmazások állapota</h3>
|
<h3>Telepített alkalmazások</h3>
|
||||||
|
|
||||||
<div class="stack-list">
|
<div class="stack-list">
|
||||||
{{range .Stacks}}
|
{{range .Stacks}}
|
||||||
@@ -139,6 +139,9 @@
|
|||||||
|
|
||||||
{{if .Protected}}
|
{{if .Protected}}
|
||||||
<span class="badge badge-protected">Védett</span>
|
<span class="badge badge-protected">Védett</span>
|
||||||
|
{{if isOperational .State}}
|
||||||
|
<button class="btn btn-sm btn-warning" onclick="stackAction('{{.Name}}', 'restart')">↻</button>
|
||||||
|
{{end}}
|
||||||
{{else if not .Deployed}}
|
{{else if not .Deployed}}
|
||||||
<a href="/stacks/{{.Name}}/deploy" class="btn btn-sm btn-primary" onclick="return checkBeforeDeploy(event, '{{.Name}}')">Telepítés</a>
|
<a href="/stacks/{{.Name}}/deploy" class="btn btn-sm btn-primary" onclick="return checkBeforeDeploy(event, '{{.Name}}')">Telepítés</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|||||||
@@ -59,6 +59,9 @@
|
|||||||
<div class="stack-detail-actions">
|
<div class="stack-detail-actions">
|
||||||
{{if .Protected}}
|
{{if .Protected}}
|
||||||
<span class="badge badge-protected">Védett rendszerkomponens</span>
|
<span class="badge badge-protected">Védett rendszerkomponens</span>
|
||||||
|
{{if isOperational .State}}
|
||||||
|
<button class="btn btn-warning" onclick="stackAction('{{.Name}}', 'restart')">Újraindítás</button>
|
||||||
|
{{end}}
|
||||||
{{else if not .Deployed}}
|
{{else if not .Deployed}}
|
||||||
<a href="/stacks/{{.Name}}/deploy" class="btn btn-primary" onclick="return checkBeforeDeploy(event, '{{.Name}}')">Telepítés</a>
|
<a href="/stacks/{{.Name}}/deploy" class="btn btn-primary" onclick="return checkBeforeDeploy(event, '{{.Name}}')">Telepítés</a>
|
||||||
<a href="{{appPageURL .Meta.Slug}}" class="btn btn-outline">Részletek</a>
|
<a href="{{appPageURL .Meta.Slug}}" class="btn btn-outline">Részletek</a>
|
||||||
|
|||||||
@@ -1323,6 +1323,27 @@ networks:
|
|||||||
external: true
|
external: true
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# Create .felhom.yml metadata
|
||||||
|
cat > "${FILEBROWSER_DIR}/.felhom.yml" << 'METAEOF'
|
||||||
|
display_name: Filebrowser
|
||||||
|
slug: filebrowser
|
||||||
|
description: Fájlkezelő a külső merevlemezhez
|
||||||
|
subdomain: files
|
||||||
|
category: storage
|
||||||
|
app_info:
|
||||||
|
tagline: Web-alapú fájlkezelő a külső merevlemezhez
|
||||||
|
use_cases:
|
||||||
|
- Fájlok böngészése és letöltése a külső HDD-ről
|
||||||
|
- Médiafájlok megosztása családtagokkal
|
||||||
|
- Dokumentumok feltöltése és kezelése
|
||||||
|
first_steps:
|
||||||
|
- Nyisd meg a files.DOMAIN címet a böngészőben
|
||||||
|
- Jelentkezz be az admin fiókkal
|
||||||
|
- Tallózd a /srv mappákat
|
||||||
|
prerequisites:
|
||||||
|
- Külső HDD csatlakoztatva és felcsatolva
|
||||||
|
METAEOF
|
||||||
|
|
||||||
# Create .env file
|
# Create .env file
|
||||||
cat > "${FILEBROWSER_DIR}/.env" << ENVEOF
|
cat > "${FILEBROWSER_DIR}/.env" << ENVEOF
|
||||||
# FileBrowser environment — generated by docker-setup.sh
|
# FileBrowser environment — generated by docker-setup.sh
|
||||||
|
|||||||
Reference in New Issue
Block a user