refactor: reorganize project structure and update configurations
- Move migrations/ to database/schema/ for clarity on database schema definitions - Move sqlc.yaml to internal/database/ to group with database code - Move static/ to cmd/server/static/ to co-locate with server - Update all configuration files and documentation - Follow Go project conventions for better organization
This commit is contained in:
@@ -4,11 +4,14 @@ import (
|
||||
"bookmann/internal/database"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
jwt "github.com/golang-jwt/jwt/v5"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
"github.com/labstack/echo/v4"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
@@ -370,6 +373,31 @@ type AddEbookFolderRequest struct {
|
||||
FolderPath string `json:"folder_path" validate:"required"`
|
||||
}
|
||||
|
||||
// normalizePath cleans and normalizes folder paths for consistent storage and comparison
|
||||
func normalizePath(path string) string {
|
||||
fmt.Printf("normalizePath input: '%s'\n", path)
|
||||
|
||||
var cleaned string
|
||||
// Handle home directory expansion (~)
|
||||
if strings.HasPrefix(path, "~/") {
|
||||
// Keep the original path for ~ to preserve user's formatting
|
||||
// Just normalize separators and that's it
|
||||
cleaned = strings.ReplaceAll(path, "\\", "/")
|
||||
} else {
|
||||
// Clean the path to remove redundant separators, ., .. etc.
|
||||
cleaned = filepath.Clean(path)
|
||||
// Convert to consistent path separators (use forward slashes for storage)
|
||||
cleaned = strings.ReplaceAll(cleaned, "\\", "/")
|
||||
// Remove trailing slash unless it's root path
|
||||
if len(cleaned) > 1 && strings.HasSuffix(cleaned, "/") {
|
||||
cleaned = strings.TrimSuffix(cleaned, "/")
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("normalizePath output: '%s'\n", cleaned)
|
||||
return cleaned
|
||||
}
|
||||
|
||||
type EbookFolderResponse struct {
|
||||
ID string `json:"id"`
|
||||
UserID string `json:"user_id"`
|
||||
@@ -397,9 +425,12 @@ func (h *AuthHandler) AddEbookFolder(c echo.Context) error {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
// Normalize the folder path before storing
|
||||
normalizedPath := normalizePath(req.FolderPath)
|
||||
|
||||
folder, err := h.db.AddUserEbookFolder(c.Request().Context(), database.AddUserEbookFolderParams{
|
||||
UserID: pgtype.UUID{Bytes: userUUID, Valid: true},
|
||||
FolderPath: req.FolderPath,
|
||||
FolderPath: normalizedPath,
|
||||
})
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
@@ -426,6 +457,12 @@ func (h *AuthHandler) GetEbookFolders(c echo.Context) error {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
fmt.Printf("GetEbookFolders: user_id='%s'\n", userID)
|
||||
for _, folder := range folders {
|
||||
fmt.Printf(" Folder in DB: id='%s', path='%s'\n",
|
||||
uuid.UUID(folder.ID.Bytes).String(), folder.FolderPath)
|
||||
}
|
||||
|
||||
var response []EbookFolderResponse
|
||||
for _, folder := range folders {
|
||||
response = append(response, EbookFolderResponse{
|
||||
@@ -455,14 +492,26 @@ func (h *AuthHandler) DeleteEbookFolder(c echo.Context) error {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
err = h.db.DeleteUserEbookFolder(c.Request().Context(), database.DeleteUserEbookFolderParams{
|
||||
// Normalize the folder path before deletion
|
||||
normalizedPath := normalizePath(req.FolderPath)
|
||||
|
||||
// Debug logging - remove in production
|
||||
fmt.Printf("DeleteEbookFolder: original path='%s', normalized path='%s', user_id='%s'\n",
|
||||
req.FolderPath, normalizedPath, userID)
|
||||
|
||||
deletedFolder, err := h.db.DeleteUserEbookFolder(c.Request().Context(), database.DeleteUserEbookFolderParams{
|
||||
UserID: pgtype.UUID{Bytes: userUUID, Valid: true},
|
||||
FolderPath: req.FolderPath,
|
||||
FolderPath: normalizedPath,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Printf("DeleteEbookFolder failed: %v\n", err)
|
||||
if err == pgx.ErrNoRows {
|
||||
return c.JSON(http.StatusNotFound, map[string]string{"error": "ebook folder not found"})
|
||||
}
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
fmt.Printf("DeleteEbookFolder succeeded: deleted folder with path '%s'\n", deletedFolder.FolderPath)
|
||||
return c.JSON(http.StatusOK, map[string]string{"message": "ebook folder deleted successfully"})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user