working album navigation and duplicate checks on backend

This commit is contained in:
wisplite
2025-11-22 23:18:53 -06:00
parent 8035be9a60
commit d9bad97a53
9 changed files with 146 additions and 19 deletions
+2 -2
View File
@@ -14,8 +14,8 @@ type Album struct {
Private bool `gorm:"not null"`
// Public albums have a default access level of 0 for all visitors, including guests.
// Private albums require a user with access to be logged in to view, or a magic link to be used.
ParentID string `gorm:"not null"` // The ID of the parent album, if any. This is an empty string for root albums.
Thumbnail string `gorm:"not null"` // The media ID of the thumbnail for the album.
ParentID string `gorm:"not null"` // The ID of the parent album, if any. This is an empty string for root albums.
Thumbnail string `gorm:"not null;default:''"` // The media ID of the thumbnail for the album.
CreatedAt time.Time
UpdatedAt time.Time
}
+1 -1
View File
@@ -4,7 +4,7 @@ import "time"
type User struct {
ID string `gorm:"primaryKey"`
Username string `gorm:"not null"`
Username string `gorm:"not null unique"`
Password string `gorm:"not null"`
IsAdmin bool `gorm:"not null"`
IsRoot bool `gorm:"not null"`
+15
View File
@@ -51,4 +51,19 @@ func RegisterAlbumRoutes(rg *gin.RouterGroup) {
}
c.JSON(http.StatusOK, result)
})
album.POST("/getIDFromPath", func(c *gin.Context) {
var request struct {
Path string `json:"path"`
}
if err := c.ShouldBindJSON(&request); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
id, err := services.GetIDFromPath(request.Path)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Album not found"})
return
}
c.JSON(http.StatusOK, gin.H{"id": id})
})
}
+38 -4
View File
@@ -2,6 +2,8 @@ package services
import (
"fmt"
"regexp"
"strings"
"github.com/google/uuid"
"github.com/wisplite/raster/internal/db"
@@ -67,19 +69,31 @@ func CreateAlbum(accessToken string, title string, description string, parentID
if accessLevel < 2 {
return models.Album{}, fmt.Errorf("user does not have permission to create albums in this parent")
}
if !regexp.MustCompile(`^[a-zA-Z0-9\s\-_]+$`).MatchString(title) {
return models.Album{}, fmt.Errorf("title can only contain alphanumeric characters, spaces, and hyphens/underscores")
}
// check for duplicate title in parent
existingAlbum := models.Album{}
result := db.GetDB().First(&existingAlbum, "title = ? AND parent_id = ?", title, parentID)
if result.Error != nil && result.Error != gorm.ErrRecordNotFound {
return models.Album{}, result.Error
}
if existingAlbum.ID != "" {
return models.Album{}, fmt.Errorf("album with this title already exists in this parent")
}
albumID := uuid.New().String()
album := models.Album{
newAlbum := models.Album{
ID: albumID,
Title: title,
Description: description,
ParentID: parentID,
Thumbnail: "",
}
result := db.GetDB().Create(&album)
if result.Error != nil {
newAlbumResult := db.GetDB().Create(&newAlbum)
if newAlbumResult.Error != nil {
return models.Album{}, result.Error
}
return album, nil
return newAlbum, nil
}
func CheckUserAlbumAccess(userID string, albumID string) (int, error) {
@@ -100,3 +114,23 @@ func CheckUserAlbumAccess(userID string, albumID string) (int, error) {
}
return userAccess.AccessLevel, nil
}
func GetIDFromPath(path string) (string, error) {
currentParentID := ""
segments := strings.Split(path, "/")
for _, segment := range segments {
if segment == "" {
continue
}
var album models.Album
result := db.GetDB().Where("title = ? AND parent_id = ?", segment, currentParentID).First(&album)
if result.Error != nil {
return "", result.Error
}
currentParentID = album.ID
}
return currentParentID, nil
}