get initial scanner up and running
This commit is contained in:
parent
732ccd05ab
commit
aeb05bca49
|
@ -215,6 +215,8 @@ type AlbumResolver interface {
|
||||||
Media(ctx context.Context, obj *models.Album, filter *models.Filter, onlyFavorites *bool) ([]*models.Media, error)
|
Media(ctx context.Context, obj *models.Album, filter *models.Filter, onlyFavorites *bool) ([]*models.Media, error)
|
||||||
SubAlbums(ctx context.Context, obj *models.Album, filter *models.Filter) ([]*models.Album, error)
|
SubAlbums(ctx context.Context, obj *models.Album, filter *models.Filter) ([]*models.Album, error)
|
||||||
|
|
||||||
|
Owner(ctx context.Context, obj *models.Album) (*models.User, error)
|
||||||
|
|
||||||
Thumbnail(ctx context.Context, obj *models.Album) (*models.Media, error)
|
Thumbnail(ctx context.Context, obj *models.Album) (*models.Media, error)
|
||||||
Path(ctx context.Context, obj *models.Album) ([]*models.Album, error)
|
Path(ctx context.Context, obj *models.Album) ([]*models.Album, error)
|
||||||
Shares(ctx context.Context, obj *models.Album) ([]*models.ShareToken, error)
|
Shares(ctx context.Context, obj *models.Album) ([]*models.ShareToken, error)
|
||||||
|
@ -2366,14 +2368,14 @@ func (ec *executionContext) _Album_owner(ctx context.Context, field graphql.Coll
|
||||||
Object: "Album",
|
Object: "Album",
|
||||||
Field: field,
|
Field: field,
|
||||||
Args: nil,
|
Args: nil,
|
||||||
IsMethod: false,
|
IsMethod: true,
|
||||||
IsResolver: false,
|
IsResolver: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = graphql.WithFieldContext(ctx, fc)
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
ctx = rctx // use context from middleware stack in children
|
ctx = rctx // use context from middleware stack in children
|
||||||
return obj.Owner, nil
|
return ec.resolvers.Album().Owner(rctx, obj)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ec.Error(ctx, err)
|
ec.Error(ctx, err)
|
||||||
|
@ -2385,9 +2387,9 @@ func (ec *executionContext) _Album_owner(ctx context.Context, field graphql.Coll
|
||||||
}
|
}
|
||||||
return graphql.Null
|
return graphql.Null
|
||||||
}
|
}
|
||||||
res := resTmp.(models.User)
|
res := resTmp.(*models.User)
|
||||||
fc.Result = res
|
fc.Result = res
|
||||||
return ec.marshalNUser2githubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐUser(ctx, field.Selections, res)
|
return ec.marshalNUser2ᚖgithubᚗcomᚋphotoviewᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐUser(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Album_filePath(ctx context.Context, field graphql.CollectedField, obj *models.Album) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Album_filePath(ctx context.Context, field graphql.CollectedField, obj *models.Album) (ret graphql.Marshaler) {
|
||||||
|
@ -7534,10 +7536,19 @@ func (ec *executionContext) _Album(ctx context.Context, sel ast.SelectionSet, ob
|
||||||
case "parentAlbum":
|
case "parentAlbum":
|
||||||
out.Values[i] = ec._Album_parentAlbum(ctx, field, obj)
|
out.Values[i] = ec._Album_parentAlbum(ctx, field, obj)
|
||||||
case "owner":
|
case "owner":
|
||||||
out.Values[i] = ec._Album_owner(ctx, field, obj)
|
field := field
|
||||||
if out.Values[i] == graphql.Null {
|
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||||
atomic.AddUint32(&invalids, 1)
|
defer func() {
|
||||||
}
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
res = ec._Album_owner(ctx, field, obj)
|
||||||
|
if res == graphql.Null {
|
||||||
|
atomic.AddUint32(&invalids, 1)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
})
|
||||||
case "filePath":
|
case "filePath":
|
||||||
out.Values[i] = ec._Album_filePath(ctx, field, obj)
|
out.Values[i] = ec._Album_filePath(ctx, field, obj)
|
||||||
if out.Values[i] == graphql.Null {
|
if out.Values[i] == graphql.Null {
|
||||||
|
|
|
@ -12,10 +12,11 @@ type Album struct {
|
||||||
Title string `gorm:"not null"`
|
Title string `gorm:"not null"`
|
||||||
ParentAlbumID *int
|
ParentAlbumID *int
|
||||||
ParentAlbum *Album
|
ParentAlbum *Album
|
||||||
OwnerID int `gorm:"not null"`
|
// OwnerID int `gorm:"not null"`
|
||||||
Owner User
|
// Owner User
|
||||||
Path string `gorm:"not null"`
|
Owners []User `gorm:"many2many:user_albums"`
|
||||||
PathHash string `gorm:"unique"`
|
Path string `gorm:"not null"`
|
||||||
|
PathHash string `gorm:"unique"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Album) FilePath() string {
|
func (a *Album) FilePath() string {
|
||||||
|
|
|
@ -153,3 +153,30 @@ func VerifyTokenAndGetUser(db *gorm.DB, token string) (*User, error) {
|
||||||
|
|
||||||
return &user, nil
|
return &user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FillAlbums fill user.Albums with albums from database
|
||||||
|
func (user *User) FillAlbums(db *gorm.DB) error {
|
||||||
|
// Albums already present
|
||||||
|
if len(user.Albums) > 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.Model(&user).Association("Albums").Find(&user.Albums); err != nil {
|
||||||
|
return errors.Wrap(err, "fill user albums")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (user *User) OwnsAlbum(db *gorm.DB, album *Album) (bool, error) {
|
||||||
|
|
||||||
|
// user.QueryUserAlbums(db, db.Where("id = ?", album.ID))
|
||||||
|
|
||||||
|
// TODO: Implement this
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (user *User) OwnsMedia(db *gorm.DB, media *Media) (bool, error) {
|
||||||
|
// TODO: implement this
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
|
@ -2,10 +2,12 @@ package resolvers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
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"
|
||||||
"github.com/photoview/photoview/api/graphql/models"
|
"github.com/photoview/photoview/api/graphql/models"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *queryResolver) MyAlbums(ctx context.Context, filter *models.Filter, onlyRoot *bool, showEmpty *bool, onlyWithFavorites *bool) ([]*models.Album, error) {
|
func (r *queryResolver) MyAlbums(ctx context.Context, filter *models.Filter, onlyRoot *bool, showEmpty *bool, onlyWithFavorites *bool) ([]*models.Album, error) {
|
||||||
|
@ -14,10 +16,19 @@ func (r *queryResolver) MyAlbums(ctx context.Context, filter *models.Filter, onl
|
||||||
return nil, auth.ErrUnauthorized
|
return nil, auth.ErrUnauthorized
|
||||||
}
|
}
|
||||||
|
|
||||||
query := r.Database.Where("owner_id = ?", user.ID)
|
if err := user.FillAlbums(r.Database); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
userAlbumIDs := make([]int, len(user.Albums))
|
||||||
|
for i, album := range user.Albums {
|
||||||
|
userAlbumIDs[i] = album.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
query := r.Database.Model(models.Album{}).Where("id IN (?)", userAlbumIDs)
|
||||||
|
|
||||||
if onlyRoot != nil && *onlyRoot == true {
|
if onlyRoot != nil && *onlyRoot == true {
|
||||||
query = query.Where("parent_album_id = (?)", r.Database.Model(&models.Album{}).Select("id").Where("parent_album_id IS NULL AND owner_id = ?", user.ID))
|
query = query.Where("parent_album_id = (?)", r.Database.Model(&models.Album{}).Select("id").Where("parent_album_id IS NULL"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if showEmpty == nil || *showEmpty == false {
|
if showEmpty == nil || *showEmpty == false {
|
||||||
|
@ -33,7 +44,7 @@ func (r *queryResolver) MyAlbums(ctx context.Context, filter *models.Filter, onl
|
||||||
query = filter.FormatSQL(query)
|
query = filter.FormatSQL(query)
|
||||||
|
|
||||||
var albums []*models.Album
|
var albums []*models.Album
|
||||||
if err := query.Find(&albums).Error; err != nil {
|
if err := query.Scan(&albums).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,10 +58,22 @@ func (r *queryResolver) Album(ctx context.Context, id int) (*models.Album, error
|
||||||
}
|
}
|
||||||
|
|
||||||
var album models.Album
|
var album models.Album
|
||||||
if err := r.Database.Where("owner_id = ?", user.ID).First(&album, id).Error; err != nil {
|
if err := r.Database.First(&album, id).Error; err != nil {
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return nil, errors.New("album not found")
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ownsAlbum, err := user.OwnsAlbum(r.Database, &album)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ownsAlbum {
|
||||||
|
return nil, errors.New("forbidden")
|
||||||
|
}
|
||||||
|
|
||||||
return &album, nil
|
return &album, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,8 +177,24 @@ func (r *albumResolver) Path(ctx context.Context, obj *models.Album) ([]*models.
|
||||||
UNION
|
UNION
|
||||||
SELECT parent.* FROM path_albums child JOIN albums parent ON parent.id = child.parent_album_id
|
SELECT parent.* FROM path_albums child JOIN albums parent ON parent.id = child.parent_album_id
|
||||||
)
|
)
|
||||||
SELECT * FROM path_albums WHERE id != ? AND owner_id = ?
|
SELECT * FROM path_albums WHERE id != ?
|
||||||
`, obj.ID, obj.ID, user.ID).Scan(&album_path).Error
|
`, obj.ID, obj.ID).Scan(&album_path).Error
|
||||||
|
|
||||||
|
// Make sure to only return albums this user owns
|
||||||
|
for i := len(album_path) - 1; i >= 0; i-- {
|
||||||
|
album := album_path[i]
|
||||||
|
|
||||||
|
owns, err := user.OwnsAlbum(r.Database, album)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !owns {
|
||||||
|
album_path = album_path[i+1:]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -18,11 +18,20 @@ func (r *queryResolver) MyMedia(ctx context.Context, filter *models.Filter) ([]*
|
||||||
return nil, errors.New("unauthorized")
|
return nil, errors.New("unauthorized")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := user.FillAlbums(r.Database); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
userAlbumIDs := make([]int, len(user.Albums))
|
||||||
|
for i, album := range user.Albums {
|
||||||
|
userAlbumIDs[i] = album.ID
|
||||||
|
}
|
||||||
|
|
||||||
var media []*models.Media
|
var media []*models.Media
|
||||||
|
|
||||||
query := r.Database.
|
query := r.Database.
|
||||||
Joins("Album").
|
Joins("Album").
|
||||||
Where("albums.owner_id = ?", user.ID).
|
Where("albums.id IN (?)", userAlbumIDs).
|
||||||
Where("media.id IN (?)", r.Database.Model(&models.MediaURL{}).Select("id").Where("media_url.media_id = media.id"))
|
Where("media.id IN (?)", r.Database.Model(&models.MediaURL{}).Select("id").Where("media_url.media_id = media.id"))
|
||||||
|
|
||||||
query = filter.FormatSQL(query)
|
query = filter.FormatSQL(query)
|
||||||
|
|
|
@ -28,7 +28,6 @@ func (r *mutationResolver) ScanAll(ctx context.Context) (*models.ScannerResult,
|
||||||
func (r *mutationResolver) ScanUser(ctx context.Context, userID int) (*models.ScannerResult, error) {
|
func (r *mutationResolver) ScanUser(ctx context.Context, userID int) (*models.ScannerResult, error) {
|
||||||
|
|
||||||
var user models.User
|
var user models.User
|
||||||
|
|
||||||
if err := r.Database.First(&user, userID).Error; err != nil {
|
if err := r.Database.First(&user, userID).Error; err != nil {
|
||||||
return nil, errors.Wrap(err, "get user from database")
|
return nil, errors.Wrap(err, "get user from database")
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
|
|
||||||
"github.com/photoview/photoview/api/graphql/auth"
|
"github.com/photoview/photoview/api/graphql/auth"
|
||||||
"github.com/photoview/photoview/api/graphql/models"
|
"github.com/photoview/photoview/api/graphql/models"
|
||||||
|
"github.com/photoview/photoview/api/scanner"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
@ -84,6 +85,11 @@ func (r *mutationResolver) InitialSetupWizard(ctx context.Context, username stri
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err = scanner.NewRootAlbum(tx, rootPath, user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
token, err = user.GenerateAccessToken(tx)
|
token, err = user.GenerateAccessToken(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -19,7 +19,12 @@ func authenticateMedia(media *models.Media, db *gorm.DB, r *http.Request) (succe
|
||||||
return false, "internal server error", http.StatusInternalServerError, err
|
return false, "internal server error", http.StatusInternalServerError, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if album.OwnerID != user.ID {
|
ownsAlbum, err := user.OwnsAlbum(db, &album)
|
||||||
|
if err != nil {
|
||||||
|
return false, "internal server error", http.StatusInternalServerError, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ownsAlbum {
|
||||||
return false, "invalid credentials", http.StatusForbidden, nil
|
return false, "invalid credentials", http.StatusForbidden, nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/photoview/photoview/api/graphql/models"
|
"github.com/photoview/photoview/api/graphql/models"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -59,28 +58,32 @@ func deleteOldUserAlbums(db *gorm.DB, scannedAlbums []*models.Album, user *model
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
albumPaths := make([]interface{}, len(scannedAlbums))
|
scannedAlbumIDs := make([]interface{}, len(scannedAlbums))
|
||||||
for i, album := range scannedAlbums {
|
for i, album := range scannedAlbums {
|
||||||
albumPaths[i] = album.Path
|
scannedAlbumIDs[i] = album.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete old albums
|
// Delete old albums
|
||||||
album_args := make([]interface{}, 0)
|
|
||||||
album_args = append(album_args, user.ID)
|
|
||||||
album_args = append(album_args, albumPaths...)
|
|
||||||
|
|
||||||
var albums []models.Album
|
var albums []models.Album
|
||||||
|
|
||||||
albums_questions := strings.Repeat("MD5(?),", len(albumPaths))[:len(albumPaths)*7-1]
|
userAlbumIDs := make([]int, len(user.Albums))
|
||||||
if err := db.Where("owner_id = ? AND path_hash NOT IN ("+albums_questions+")", album_args...).Find(&albums).Error; err != nil {
|
for i, album := range user.Albums {
|
||||||
|
userAlbumIDs[i] = album.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
query := db.
|
||||||
|
Where("id IN (?)", userAlbumIDs).
|
||||||
|
Where("id NOT IN (?)", scannedAlbumIDs)
|
||||||
|
|
||||||
|
if err := query.Find(&albums).Error; err != nil {
|
||||||
return []error{errors.Wrap(err, "get albums to be deleted from database")}
|
return []error{errors.Wrap(err, "get albums to be deleted from database")}
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteErrors := make([]error, 0)
|
deleteErrors := make([]error, 0)
|
||||||
|
|
||||||
albumIDs := make([]int, 0)
|
deleteAlbumIDs := make([]int, len(albums))
|
||||||
for _, album := range albums {
|
for i, album := range albums {
|
||||||
albumIDs = append(albumIDs, album.ID)
|
deleteAlbumIDs[i] = album.ID
|
||||||
cachePath := path.Join(PhotoCache(), strconv.Itoa(int(album.ID)))
|
cachePath := path.Join(PhotoCache(), strconv.Itoa(int(album.ID)))
|
||||||
err := os.RemoveAll(cachePath)
|
err := os.RemoveAll(cachePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -88,7 +91,7 @@ func deleteOldUserAlbums(db *gorm.DB, scannedAlbums []*models.Album, user *model
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.Where("id IN ?", albumIDs).Delete(models.Album{}).Error; err != nil {
|
if err := db.Where("id IN ?", deleteAlbumIDs).Delete(models.Album{}).Error; err != nil {
|
||||||
ScannerError("Could not delete old albums from database:\n%s\n", err)
|
ScannerError("Could not delete old albums from database:\n%s\n", err)
|
||||||
deleteErrors = append(deleteErrors, errors.Wrap(err, "delete old albums from database"))
|
deleteErrors = append(deleteErrors, errors.Wrap(err, "delete old albums from database"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,25 @@ import (
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func NewRootAlbum(db *gorm.DB, rootPath string, owner *models.User) (*models.Album, error) {
|
||||||
|
|
||||||
|
owners := []models.User{
|
||||||
|
*owner,
|
||||||
|
}
|
||||||
|
|
||||||
|
album := models.Album{
|
||||||
|
Title: path.Base(rootPath),
|
||||||
|
Path: rootPath,
|
||||||
|
Owners: owners,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.Create(&album).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &album, nil
|
||||||
|
}
|
||||||
|
|
||||||
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()
|
||||||
|
|
|
@ -17,16 +17,25 @@ import (
|
||||||
|
|
||||||
func findAlbumsForUser(db *gorm.DB, user *models.User, album_cache *AlbumScannerCache) ([]*models.Album, []error) {
|
func findAlbumsForUser(db *gorm.DB, user *models.User, album_cache *AlbumScannerCache) ([]*models.Album, []error) {
|
||||||
|
|
||||||
|
if err := user.FillAlbums(db); err != nil {
|
||||||
|
return nil, []error{err}
|
||||||
|
}
|
||||||
|
|
||||||
|
userAlbumIDs := make([]int, len(user.Albums))
|
||||||
|
for i, album := range user.Albums {
|
||||||
|
userAlbumIDs[i] = album.ID
|
||||||
|
}
|
||||||
|
|
||||||
var userRootAlbums []*models.Album
|
var userRootAlbums []*models.Album
|
||||||
if err := db.Model(&user).Association("Albums").Find(&userRootAlbums); err != nil {
|
if err := db.Where("id IN (?)", userAlbumIDs).Where("parent_album_id IS NULL").Find(&userRootAlbums).Error; err != nil {
|
||||||
return nil, []error{errors.Wrapf(err, "get albums of user (%s)", user.Username)}
|
return nil, []error{err}
|
||||||
}
|
}
|
||||||
|
|
||||||
scanErrors := make([]error, 0)
|
scanErrors := make([]error, 0)
|
||||||
|
|
||||||
type scanInfo struct {
|
type scanInfo struct {
|
||||||
path string
|
path string
|
||||||
parentID *int
|
parent *models.Album
|
||||||
}
|
}
|
||||||
|
|
||||||
scanQueue := list.New()
|
scanQueue := list.New()
|
||||||
|
@ -41,8 +50,8 @@ func findAlbumsForUser(db *gorm.DB, user *models.User, album_cache *AlbumScanner
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
scanQueue.PushBack(scanInfo{
|
scanQueue.PushBack(scanInfo{
|
||||||
path: album.Path,
|
path: album.Path,
|
||||||
parentID: nil,
|
parent: nil,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +63,7 @@ func findAlbumsForUser(db *gorm.DB, user *models.User, album_cache *AlbumScanner
|
||||||
scanQueue.Remove(scanQueue.Front())
|
scanQueue.Remove(scanQueue.Front())
|
||||||
|
|
||||||
albumPath := albumInfo.path
|
albumPath := albumInfo.path
|
||||||
albumParentID := albumInfo.parentID
|
albumParent := albumInfo.parent
|
||||||
|
|
||||||
// Read path
|
// Read path
|
||||||
dirContent, err := ioutil.ReadDir(albumPath)
|
dirContent, err := ioutil.ReadDir(albumPath)
|
||||||
|
@ -64,26 +73,50 @@ func findAlbumsForUser(db *gorm.DB, user *models.User, album_cache *AlbumScanner
|
||||||
}
|
}
|
||||||
|
|
||||||
// Will become new album or album from db
|
// Will become new album or album from db
|
||||||
var album models.Album
|
var album *models.Album
|
||||||
|
|
||||||
transErr := db.Transaction(func(tx *gorm.DB) error {
|
transErr := db.Transaction(func(tx *gorm.DB) error {
|
||||||
log.Printf("Scanning directory: %s", albumPath)
|
log.Printf("Scanning directory: %s", albumPath)
|
||||||
|
|
||||||
// Make album if not exists
|
// check if album already exists
|
||||||
albumTitle := path.Base(albumPath)
|
var albumResult []models.Album
|
||||||
|
result := tx.Where("path_hash = md5(?)", albumPath).Find(&albumResult)
|
||||||
err = tx.FirstOrCreate(&album, models.Album{
|
if result.Error != nil {
|
||||||
Title: albumTitle,
|
return result.Error
|
||||||
ParentAlbumID: albumParentID,
|
|
||||||
OwnerID: user.ID,
|
|
||||||
Path: albumPath,
|
|
||||||
}).Error
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "insert album into database")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
userAlbums = append(userAlbums, &album)
|
// album does not exist, create new
|
||||||
|
if len(albumResult) == 0 {
|
||||||
|
albumTitle := path.Base(albumPath)
|
||||||
|
|
||||||
|
var albumParentID *int
|
||||||
|
parentOwners := make([]models.User, 0)
|
||||||
|
if albumParent != nil {
|
||||||
|
albumParentID = &albumParent.ID
|
||||||
|
|
||||||
|
if err := db.Model(&albumParent).Association("Owners").Find(&parentOwners); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
album = &models.Album{
|
||||||
|
Title: albumTitle,
|
||||||
|
ParentAlbumID: albumParentID,
|
||||||
|
Path: albumPath,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Create(&album).Error; err != nil {
|
||||||
|
return errors.Wrap(err, "insert album into database")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Model(&album).Association("Owners").Append(parentOwners); err != nil {
|
||||||
|
return errors.Wrap(err, "add owners to album")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
album = &albumResult[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
userAlbums = append(userAlbums, album)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
@ -104,8 +137,8 @@ func findAlbumsForUser(db *gorm.DB, user *models.User, album_cache *AlbumScanner
|
||||||
|
|
||||||
if item.IsDir() && directoryContainsPhotos(subalbumPath, album_cache) {
|
if item.IsDir() && directoryContainsPhotos(subalbumPath, album_cache) {
|
||||||
scanQueue.PushBack(scanInfo{
|
scanQueue.PushBack(scanInfo{
|
||||||
path: subalbumPath,
|
path: subalbumPath,
|
||||||
parentID: &album.ID,
|
parent: album,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ const USERS_QUERY = gql`
|
||||||
user {
|
user {
|
||||||
id
|
id
|
||||||
username
|
username
|
||||||
rootPath
|
# rootPath
|
||||||
admin
|
admin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue