1
Fork 0

Improve scanner_album NewRootPath tests

This commit is contained in:
viktorstrate 2021-04-26 20:37:29 +02:00
parent 253f126aaf
commit 542e5c8532
No known key found for this signature in database
GPG Key ID: 3F855605109C1E8A
7 changed files with 80 additions and 59 deletions

View File

@ -159,6 +159,7 @@ var database_models []interface{} = []interface{}{
&models.VideoMetadata{}, &models.VideoMetadata{},
&models.ShareToken{}, &models.ShareToken{},
&models.UserMediaData{}, &models.UserMediaData{},
&models.UserAlbums{},
&models.UserPreferences{}, &models.UserPreferences{},
// Face detection // Face detection
@ -167,9 +168,12 @@ var database_models []interface{} = []interface{}{
} }
func MigrateDatabase(db *gorm.DB) error { func MigrateDatabase(db *gorm.DB) error {
err := db.AutoMigrate(database_models...)
if err != nil { if err := db.SetupJoinTable(&models.User{}, "Albums", &models.UserAlbums{}); err != nil {
log.Printf("Setup UserAlbums join table failed: %v\n", err)
}
if err := db.AutoMigrate(database_models...); err != nil {
log.Printf("Auto migration failed: %v\n", err) log.Printf("Auto migration failed: %v\n", err)
} }
@ -180,8 +184,7 @@ func MigrateDatabase(db *gorm.DB) error {
// v2.3.0 - Changed type of MediaEXIF.Exposure and MediaEXIF.Flash // v2.3.0 - Changed type of MediaEXIF.Exposure and MediaEXIF.Flash
// from string values to decimal and int respectively // from string values to decimal and int respectively
err = migrate_exif_fields(db) if err := migrate_exif_fields(db); err != nil {
if err != nil {
log.Printf("Failed to run exif fields migration: %v\n", err) log.Printf("Failed to run exif fields migration: %v\n", err)
} }

View File

@ -14,7 +14,7 @@ type Album struct {
ParentAlbum *Album `gorm:"constraint:OnDelete:SET NULL;"` ParentAlbum *Album `gorm:"constraint:OnDelete:SET NULL;"`
// OwnerID int `gorm:"not null"` // OwnerID int `gorm:"not null"`
// Owner User // Owner User
Owners []User `gorm:"many2many:user_albums"` Owners []User `gorm:"many2many:user_albums;constraint:OnDelete:CASCADE;"`
Path string `gorm:"not null"` Path string `gorm:"not null"`
PathHash string `gorm:"unique"` PathHash string `gorm:"unique"`
} }

View File

@ -3,8 +3,6 @@ package models
import ( import (
"crypto/rand" "crypto/rand"
"fmt" "fmt"
"log"
"os"
"time" "time"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -17,7 +15,7 @@ type User struct {
Username string `gorm:"unique;size:128"` Username string `gorm:"unique;size:128"`
Password *string `gorm:"size:256"` Password *string `gorm:"size:256"`
// RootPath string `gorm:"size:512` // RootPath string `gorm:"size:512`
Albums []Album `gorm:"many2many:user_albums"` Albums []Album `gorm:"many2many:user_albums;constraint:OnDelete:CASCADE;"`
Admin bool `gorm:"default:false"` Admin bool `gorm:"default:false"`
} }
@ -28,6 +26,11 @@ type UserMediaData struct {
Favorite bool `gorm:"not null;default:false"` Favorite bool `gorm:"not null;default:false"`
} }
type UserAlbums struct {
UserID int `gorm:"primaryKey;autoIncrement:false;constraint:OnDelete:CASCADE;"`
AlbumID int `gorm:"primaryKey;autoIncrement:false;constraint:OnDelete:CASCADE;"`
}
type AccessToken struct { type AccessToken struct {
Model Model
UserID int `gorm:"not null;index"` UserID int `gorm:"not null;index"`
@ -95,18 +98,6 @@ func AuthorizeUser(db *gorm.DB, username string, password string) (*User, error)
return &user, nil return &user, nil
} }
var ErrorInvalidRootPath = errors.New("invalid root path")
func ValidRootPath(rootPath string) bool {
_, err := os.Stat(rootPath)
if err != nil {
log.Printf("Warn: invalid root path: '%s'\n%s\n", rootPath, err)
return false
}
return true
}
func RegisterUser(db *gorm.DB, username string, password *string, admin bool) (*User, error) { func RegisterUser(db *gorm.DB, username string, password *string, admin bool) (*User, error) {
user := User{ user := User{
Username: username, Username: username,

View File

@ -2,11 +2,9 @@ package resolvers
import ( import (
"context" "context"
"fmt"
"os" "os"
"path" "path"
"strconv" "strconv"
"strings"
api "github.com/photoview/photoview/api/graphql" api "github.com/photoview/photoview/api/graphql"
"github.com/photoview/photoview/api/graphql/auth" "github.com/photoview/photoview/api/graphql/auth"
@ -314,39 +312,6 @@ func (r *mutationResolver) UserAddRootPath(ctx context.Context, id int, rootPath
return nil, err return nil, err
} }
if !models.ValidRootPath(rootPath) {
return nil, errors.New("invalid root path")
}
upperPaths := make([]string, 1)
upperPath := rootPath
upperPaths[0] = upperPath
for {
substrIndex := strings.LastIndex(upperPath, "/")
if substrIndex == -1 {
break
}
if substrIndex == 0 {
upperPaths = append(upperPaths, "/")
break
}
upperPath = upperPath[0:substrIndex]
upperPaths = append(upperPaths, upperPath)
}
var upperAlbums []models.Album
if err := r.Database.Model(&user).Association("Albums").Find(&upperAlbums, "albums.path IN (?)", upperPaths); err != nil {
// if err := r.Database.Model(models.Album{}).Where("path IN (?)", upperPaths).Find(&upperAlbums).Error; err != nil {
return nil, err
}
if len(upperAlbums) > 0 {
return nil, errors.New(fmt.Sprintf("user already owns a path containing this path: %s", upperAlbums[0].Path))
}
newAlbum, err := scanner.NewRootAlbum(r.Database, rootPath, &user) newAlbum, err := scanner.NewRootAlbum(r.Database, rootPath, &user)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"os"
"path" "path"
"time" "time"
@ -18,6 +19,19 @@ import (
func NewRootAlbum(db *gorm.DB, rootPath string, owner *models.User) (*models.Album, error) { func NewRootAlbum(db *gorm.DB, rootPath string, owner *models.User) (*models.Album, error) {
if !ValidRootPath(rootPath) {
return nil, ErrorInvalidRootPath
}
if !path.IsAbs(rootPath) {
wd, err := os.Getwd()
if err != nil {
return nil, err
}
rootPath = path.Join(wd, rootPath)
}
owners := []models.User{ owners := []models.User{
*owner, *owner,
} }
@ -36,7 +50,7 @@ func NewRootAlbum(db *gorm.DB, rootPath string, owner *models.User) (*models.Alb
} }
if matchedUserAlbumCount > 0 { if matchedUserAlbumCount > 0 {
return nil, errors.New(fmt.Sprintf("user already owns path (%s)", rootPath)) return nil, errors.New(fmt.Sprintf("user already owns a path containing this path: %s", rootPath))
} }
if err := db.Model(&owner).Association("Albums").Append(&album); err != nil { if err := db.Model(&owner).Association("Albums").Append(&album); err != nil {
@ -59,6 +73,18 @@ func NewRootAlbum(db *gorm.DB, rootPath string, owner *models.User) (*models.Alb
} }
} }
var ErrorInvalidRootPath = errors.New("invalid root path")
func ValidRootPath(rootPath string) bool {
_, err := os.Stat(rootPath)
if err != nil {
log.Printf("Warn: invalid root path: '%s'\n%s\n", rootPath, err)
return false
}
return true
}
func scanAlbum(album *models.Album, cache *AlbumScannerCache, db *gorm.DB) { func scanAlbum(album *models.Album, cache *AlbumScannerCache, db *gorm.DB) {
album_notify_key := utils.GenerateToken() album_notify_key := utils.GenerateToken()

View File

@ -27,7 +27,7 @@ func TestNewRootPath(t *testing.T) {
} }
assert.NotNil(t, album) assert.NotNil(t, album)
assert.Equal(t, "./test_data", album.Path) assert.Contains(t, album.Path, "/api/scanner/test_data")
assert.NotEmpty(t, album.Owners) assert.NotEmpty(t, album.Owners)
}) })
@ -36,7 +36,37 @@ func TestNewRootPath(t *testing.T) {
_, err := scanner.NewRootAlbum(db, "./test_data", &user) _, err := scanner.NewRootAlbum(db, "./test_data", &user)
assert.Error(t, err) assert.Error(t, err)
assert.Equal(t, err.Error(), "user already owns path (./test_data)") assert.Contains(t, err.Error(), "user already owns a path containing this path:")
})
t.Run("Insert invalid root album", func(t *testing.T) {
_, err := scanner.NewRootAlbum(db, "./invalid_path", &user)
assert.Error(t, err)
assert.Equal(t, err.Error(), "invalid root path")
})
t.Run("Add existing root album to new user", func(t *testing.T) {
user2 := models.User{
Username: "user2",
}
if !assert.NoError(t, db.Save(&user2).Error) {
return
}
album, err := scanner.NewRootAlbum(db, "./test_data", &user2)
if !assert.NoError(t, err) {
return
}
assert.NotNil(t, album)
assert.Contains(t, album.Path, "/api/scanner/test_data")
owner_count := db.Model(&album).Association("Owners").Count()
assert.EqualValues(t, 2, owner_count)
}) })
} }

View File

@ -23,6 +23,10 @@ func (dbm *TestDBManager) Close() error {
return nil return nil
} }
if err := dbm.reset(); err != nil {
return err
}
sqlDB, err := dbm.DB.DB() sqlDB, err := dbm.DB.DB()
if err != nil { if err != nil {
return errors.Wrap(err, "get db instance when closing test database") return errors.Wrap(err, "get db instance when closing test database")
@ -47,7 +51,9 @@ func (dbm *TestDBManager) setup() error {
dbm.DB = db dbm.DB = db
dbm.reset() if err := dbm.reset(); err != nil {
return err
}
return nil return nil
} }