diff --git a/backend/internal/models/media.go b/backend/internal/models/media.go new file mode 100644 index 0000000..9463211 --- /dev/null +++ b/backend/internal/models/media.go @@ -0,0 +1,20 @@ +package models + +import ( + "time" + + "gorm.io/datatypes" +) + +type Media struct { + ID string `gorm:"primaryKey"` + Title string `gorm:"not null"` + Description string `gorm:"not null"` + Tags datatypes.JSON `gorm:"type:json"` + AlbumID string `gorm:"not null"` + Path string `gorm:"not null"` + Type string `gorm:"not null"` // MIME type + Metadata datatypes.JSON `gorm:"type:json"` // Metadata about the media. + CreatedAt time.Time + UpdatedAt time.Time +} diff --git a/backend/internal/routes/album.go b/backend/internal/routes/album.go index cdeb789..1a7d576 100644 --- a/backend/internal/routes/album.go +++ b/backend/internal/routes/album.go @@ -17,4 +17,22 @@ func RegisterAlbumRoutes(rg *gin.RouterGroup) { } c.JSON(http.StatusOK, albums) }) + album.POST("/createAlbum", func(c *gin.Context) { + accessToken := c.GetHeader("Authorization") + if accessToken == "" { + c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"}) + return + } + var request struct { + Title string `json:"title"` + Description string `json:"description"` + ParentID string `json:"parentId"` + } + result, err := services.CreateAlbum(accessToken, request.Title, request.Description, request.ParentID) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + c.JSON(http.StatusOK, result) + }) } diff --git a/backend/internal/services/accessTokens.go b/backend/internal/services/accessTokens.go index 55a546e..f185206 100644 --- a/backend/internal/services/accessTokens.go +++ b/backend/internal/services/accessTokens.go @@ -1,6 +1,7 @@ package services import ( + "fmt" "time" "github.com/google/uuid" @@ -22,3 +23,15 @@ func CreateAccessToken(userID string) (models.AccessToken, error) { } return accessToken, nil } + +func ValidateAccessToken(accessToken string) (string, error) { + accessTokenModel := models.AccessToken{} + result := db.GetDB().First(&accessTokenModel, "token = ?", accessToken) + if result.Error != nil { + return "", result.Error + } + if accessTokenModel.Expires.Before(time.Now()) { + return "", fmt.Errorf("access token expired") + } + return accessTokenModel.UserID, nil +} diff --git a/backend/internal/services/album.go b/backend/internal/services/album.go index 85590d8..da20865 100644 --- a/backend/internal/services/album.go +++ b/backend/internal/services/album.go @@ -1,8 +1,12 @@ package services import ( + "fmt" + + "github.com/google/uuid" "github.com/wisplite/raster/internal/db" "github.com/wisplite/raster/internal/models" + "gorm.io/gorm" ) func GetPublicAlbums() ([]models.Album, error) { @@ -23,3 +27,51 @@ func GetAlbum(id string, authToken string) (models.Album, error) { } return album, nil } + +func CreateAlbum(accessToken string, title string, description string, parentID string) (models.Album, error) { + userID, err := ValidateAccessToken(accessToken) + if err != nil { + return models.Album{}, err + } + if userID == "" { + return models.Album{}, fmt.Errorf("invalid access token") + } + accessLevel, err := CheckUserAlbumAccess(userID, parentID) + if err != nil { + return models.Album{}, err + } + if accessLevel < 2 { + return models.Album{}, fmt.Errorf("user does not have permission to create albums in this parent") + } + albumID := uuid.New().String() + album := models.Album{ + ID: albumID, + Title: title, + Description: description, + ParentID: parentID, + } + result := db.GetDB().Create(&album) + if result.Error != nil { + return models.Album{}, result.Error + } + return album, nil +} + +func CheckUserAlbumAccess(userID string, albumID string) (int, error) { + userAccess := models.UserAccess{} + result := db.GetDB().First(&userAccess, "user_id = ? AND album_id = ?", userID, albumID) + if result.Error != nil { + if result.Error == gorm.ErrRecordNotFound { + userData, err := GetUserByID(userID) + if err != nil { + return -1, err + } + if userData.IsAdmin || userData.IsRoot { + return 4, nil // Admin access + } + return -1, nil // No access + } + return -1, result.Error + } + return userAccess.AccessLevel, nil +} diff --git a/backend/internal/services/user.go b/backend/internal/services/user.go index b12e145..fac5712 100644 --- a/backend/internal/services/user.go +++ b/backend/internal/services/user.go @@ -97,3 +97,12 @@ func GetUserData(authToken string) (models.User, error) { } return userData, nil } + +func GetUserByID(userID string) (models.User, error) { + user := models.User{} + result := db.GetDB().First(&user, "id = ?", userID) + if result.Error != nil { + return models.User{}, result.Error + } + return user, nil +} diff --git a/frontend/src/gallery/components/AlbumCreateModal.jsx b/frontend/src/gallery/components/AlbumCreateModal.jsx index b88a13c..4c8b786 100644 --- a/frontend/src/gallery/components/AlbumCreateModal.jsx +++ b/frontend/src/gallery/components/AlbumCreateModal.jsx @@ -1,11 +1,14 @@ import Modal from '../../components/Modal' export default function AlbumCreateModal({ open, onOpenChange, trigger }) { + const handleCreateAlbum = () => { + console.log('Create Album') + } return (