fix(library): reject reserved names (cache, .uploads) with 400 reserved_name (B8)
This commit is contained in:
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/jackc/pgx/v5"
|
||||
|
||||
"booklib/internal/bookfile"
|
||||
"booklib/internal/media"
|
||||
"booklib/internal/store"
|
||||
)
|
||||
|
||||
@@ -61,6 +62,11 @@ func (h *H) CreateLibrary(c *gin.Context) {
|
||||
err(c, http.StatusBadRequest, "bad_request", "bad name")
|
||||
return
|
||||
}
|
||||
// B8: reject reserved names that conflict with system directories.
|
||||
if media.IsReservedName(safe) {
|
||||
err(c, http.StatusBadRequest, "bad_request", "reserved_name")
|
||||
return
|
||||
}
|
||||
root := filepath.Join(filepath.Clean(h.cfg.BooksDir), safe)
|
||||
id, e := h.st.CreateLibrary(c, req.Name, root)
|
||||
if e != nil {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package media
|
||||
|
||||
import "strings"
|
||||
|
||||
// reservedNames are library names that conflict with system directories.
|
||||
// This is the single source of truth for reserved name validation (B8).
|
||||
var reservedNames = map[string]bool{
|
||||
"cache": true, // CACHE_DIR
|
||||
".uploads": true, // upload session directory
|
||||
".trash": true, // potential future use
|
||||
}
|
||||
|
||||
// IsReservedName reports whether name conflicts with system directories.
|
||||
func IsReservedName(name string) bool {
|
||||
return reservedNames[strings.ToLower(name)]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package media
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestIsReservedName(t *testing.T) {
|
||||
for _, n := range []string{"cache", "Cache", "CACHE", ".uploads", ".Uploads", ".trash"} {
|
||||
if !IsReservedName(n) {
|
||||
t.Errorf("IsReservedName(%q) = false, want true", n)
|
||||
}
|
||||
}
|
||||
for _, n := range []string{"comics", "books", "my-library", "Cache1"} {
|
||||
if IsReservedName(n) {
|
||||
t.Errorf("IsReservedName(%q) = true, want false", n)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user