mirror of
https://github.com/wisplite/raster.git
synced 2026-05-01 06:32:44 -05:00
add access token validation logic and some media stuff
This commit is contained in:
@@ -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
|
||||||
|
}
|
||||||
@@ -17,4 +17,22 @@ func RegisterAlbumRoutes(rg *gin.RouterGroup) {
|
|||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, albums)
|
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)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@@ -22,3 +23,15 @@ func CreateAccessToken(userID string) (models.AccessToken, error) {
|
|||||||
}
|
}
|
||||||
return accessToken, nil
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/wisplite/raster/internal/db"
|
"github.com/wisplite/raster/internal/db"
|
||||||
"github.com/wisplite/raster/internal/models"
|
"github.com/wisplite/raster/internal/models"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetPublicAlbums() ([]models.Album, error) {
|
func GetPublicAlbums() ([]models.Album, error) {
|
||||||
@@ -23,3 +27,51 @@ func GetAlbum(id string, authToken string) (models.Album, error) {
|
|||||||
}
|
}
|
||||||
return album, nil
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -97,3 +97,12 @@ func GetUserData(authToken string) (models.User, error) {
|
|||||||
}
|
}
|
||||||
return userData, nil
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
import Modal from '../../components/Modal'
|
import Modal from '../../components/Modal'
|
||||||
export default function AlbumCreateModal({ open, onOpenChange, trigger }) {
|
export default function AlbumCreateModal({ open, onOpenChange, trigger }) {
|
||||||
|
const handleCreateAlbum = () => {
|
||||||
|
console.log('Create Album')
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<Modal open={open} onOpenChange={onOpenChange} trigger={trigger} title="Create Album">
|
<Modal open={open} onOpenChange={onOpenChange} trigger={trigger} title="Create Album">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<input type="text" placeholder="Name" className="w-full px-3 py-2.5 bg-[#141414] border border-[#2B2B2B] rounded-md text-white placeholder-gray-600 focus:outline-none focus:border-[#3B3B3B] transition-colors red-hat-text" />
|
<input type="text" placeholder="Name" className="w-full px-3 py-2.5 bg-[#141414] border border-[#2B2B2B] rounded-md text-white placeholder-gray-600 focus:outline-none focus:border-[#3B3B3B] transition-colors red-hat-text" />
|
||||||
<textarea type="text" placeholder="Description" className="w-full h-[20vh] px-3 py-2.5 bg-[#141414] border border-[#2B2B2B] rounded-md text-white placeholder-gray-600 focus:outline-none focus:border-[#3B3B3B] transition-colors red-hat-text resize-none" />
|
<textarea type="text" placeholder="Description" className="w-full h-[20vh] px-3 py-2.5 bg-[#141414] border border-[#2B2B2B] rounded-md text-white placeholder-gray-600 focus:outline-none focus:border-[#3B3B3B] transition-colors red-hat-text resize-none" />
|
||||||
<button className="w-full py-2.5 bg-[#2B2B2B] hover:bg-[#3B3B3B] text-white rounded-md font-medium transition-colors red-hat-mono cursor-pointer mt-2">Create Album</button>
|
<button className="w-full py-2.5 bg-[#2B2B2B] hover:bg-[#3B3B3B] text-white rounded-md font-medium transition-colors red-hat-mono cursor-pointer mt-2" onClick={handleCreateAlbum}>Create Album</button>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user