From f0d580116bb92ee954a58f21217bb84159dd0c0e Mon Sep 17 00:00:00 2001 From: viktorstrate Date: Tue, 8 Dec 2020 16:24:08 +0100 Subject: [PATCH] Improve album and media resolvers --- api/database/database.go | 1 + api/graphql/resolvers/album.go | 81 +++++++++++-------------- api/graphql/resolvers/media.go | 107 +++++++++++---------------------- api/scanner/cache.go | 4 +- api/scanner/process_photo.go | 2 +- 5 files changed, 76 insertions(+), 119 deletions(-) diff --git a/api/database/database.go b/api/database/database.go index 9ca0095f..51391837 100644 --- a/api/database/database.go +++ b/api/database/database.go @@ -59,6 +59,7 @@ func MigrateDatabase(db *gorm.DB) error { &models.Album{}, &models.MediaEXIF{}, &models.VideoMetadata{}, + &models.ShareToken{}, ) return nil diff --git a/api/graphql/resolvers/album.go b/api/graphql/resolvers/album.go index 3b36f752..92701e96 100644 --- a/api/graphql/resolvers/album.go +++ b/api/graphql/resolvers/album.go @@ -2,8 +2,6 @@ package resolvers import ( "context" - "fmt" - "log" api "github.com/viktorstrate/photoview/api/graphql" "github.com/viktorstrate/photoview/api/graphql/auth" @@ -85,34 +83,27 @@ func (r *albumResolver) Media(ctx context.Context, album *models.Album, filter * func (r *albumResolver) Thumbnail(ctx context.Context, obj *models.Album) (*models.Media, error) { - log.Println("TODO: Album thumbnail migrated yet") + var media models.Media - return nil, nil + err := r.Database.Raw(` + WITH recursive sub_albums AS ( + SELECT * FROM albums AS root WHERE id = ? + UNION ALL + SELECT child.* FROM albums AS child JOIN sub_albums ON child.parent_album_id = sub_albums.id + ) - // row := r.Database.QueryRow(` - // WITH recursive sub_albums AS ( - // SELECT * FROM album AS root WHERE album_id = ? - // UNION ALL - // SELECT child.* FROM album AS child JOIN sub_albums ON child.parent_album = sub_albums.album_id - // ) + SELECT * FROM media WHERE media.album_id IN ( + SELECT id FROM sub_albums + ) AND media.id IN ( + SELECT media_id FROM media_urls WHERE media_urls.media_id = media.id + ) LIMIT 1 + `, obj.ID).Scan(&media).Error - // SELECT * FROM media WHERE media.album_id IN ( - // SELECT album_id FROM sub_albums - // ) AND media.media_id IN ( - // SELECT media_id FROM media_url WHERE media_url.media_id = media.media_id - // ) LIMIT 1 - // `, obj.AlbumID) + if err != nil { + return nil, err + } - // media, err := models.NewMediaFromRow(row) - // if err != nil { - // if err == sql.ErrNoRows { - // return nil, nil - // } else { - // return nil, err - // } - // } - - // return media, nil + return &media, nil } func (r *albumResolver) SubAlbums(ctx context.Context, parent *models.Album, filter *models.Filter) ([]*models.Album, error) { @@ -147,26 +138,26 @@ func (r *albumResolver) Shares(ctx context.Context, album *models.Album) ([]*mod func (r *albumResolver) Path(ctx context.Context, obj *models.Album) ([]*models.Album, error) { - fmt.Println("TODO: Album path not migrated yet") + user := auth.UserFromContext(ctx) + if user == nil { + empty := make([]*models.Album, 0) + return empty, nil + } - return make([]*models.Album, 0), nil - // user := auth.UserFromContext(ctx) - // if user == nil { - // empty := make([]*models.Album, 0) - // return empty, nil - // } + var album_path []*models.Album - // rows, err := r.Database.Query(` - // WITH recursive path_albums AS ( - // SELECT * FROM album anchor WHERE anchor.album_id = ? - // UNION - // SELECT parent.* FROM path_albums child JOIN album parent ON parent.album_id = child.parent_album - // ) - // SELECT * FROM path_albums WHERE album_id != ? AND owner_id = ? - // `, obj.AlbumID, obj.AlbumID, user.UserID) - // if err != nil { - // return nil, err - // } + err := r.Database.Raw(` + WITH recursive path_albums AS ( + SELECT * FROM albums anchor WHERE anchor.id = ? + UNION + 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 = ? + `, obj.ID, obj.ID, user.ID).Scan(&album_path).Error - // return models.NewAlbumsFromRows(rows) + if err != nil { + return nil, err + } + + return album_path, nil } diff --git a/api/graphql/resolvers/media.go b/api/graphql/resolvers/media.go index 91fff899..5ec5c6ed 100644 --- a/api/graphql/resolvers/media.go +++ b/api/graphql/resolvers/media.go @@ -17,19 +17,21 @@ func (r *queryResolver) MyMedia(ctx context.Context, filter *models.Filter) ([]* return nil, errors.New("unauthorized") } - filterSQL, err := filter.FormatSQL("media") - if err != nil { - return nil, err - } + // filterSQL, err := filter.FormatSQL("media") + // if err != nil { + // return nil, err + // } var media []*models.Media - err = r.Database.Raw(` - SELECT media.* FROM media, album - WHERE media.album_id = albums.id AND albums.owner_id = ? - AND media.media_id IN ( - SELECT media_id FROM media_url WHERE media_url.media_id = media.id - ) - `+filterSQL, user.ID).Scan(&media).Error + + // TODO: Incorporate filter.FormatSQL + + err := r.Database. + Joins("Album"). + Where("albums.owner_id = ?", user.ID). + Where("media.id IN (?)", r.Database.Model(&models.MediaURL{}).Select("id").Where("media_url.media_id = media.id")). + Scan(&media).Error + if err != nil { return nil, err } @@ -44,14 +46,13 @@ func (r *queryResolver) Media(ctx context.Context, id int) (*models.Media, error } var media models.Media - err := r.Database.Raw(` - SELECT media.* FROM media - JOIN albums ON media.album_id = albums.id - WHERE media.media_id = ? AND album.owner_id = ? - AND media.media_id IN ( - SELECT media_id FROM media_url WHERE media_url.media_id = media.media_id - ) - `, id, user.ID).Scan(&media).Error + + err := r.Database. + Joins("Album"). + Where("media.id = ?", id). + Where("Album.owner_id = ?", user.ID). + Where("media.id IN (?)", r.Database.Model(&models.MediaURL{}).Select("media_id").Where("media_urls.media_id = media.id")). + First(&media).Error if err != nil { return nil, errors.Wrap(err, "could not get media by media_id and user_id from database") @@ -71,22 +72,22 @@ func (r *queryResolver) MediaList(ctx context.Context, ids []int) ([]*models.Med } var media []*models.Media - // err := r.Database. - // Select("media.*"). - // Joins("Album"). - // Where("media.id IN ?", ids). - // Where("album.owner_id = ?", user.ID). - // Where("media.id IN (?)", r.Database.Model(&models.MediaURL{}).Select("media_id").Where("media_url.media_id = media.id")). - // Scan(&media).Error + err := r.Database. + Select("media.*"). + Joins("Album"). + Where("media.id IN ?", ids). + Where("album.owner_id = ?", user.ID). + // Where("media.id IN (?)", r.Database.Model(&models.MediaURL{}).Select("media_id").Where("media_url.media_id = media.id")). + Scan(&media).Error - err := r.Database.Raw(` - SELECT media.* FROM media - JOIN albums AS album ON media.album_id = album.id - WHERE media.media_id IN ? AND album.owner_id = ? - AND media.media_id IN ( - SELECT media_id FROM media_url WHERE media_url.media_id = media.media_id - ) - `, ids, user.ID).Error + // err := r.Database.Raw(` + // SELECT media.* FROM media + // JOIN albums AS album ON media.album_id = album.id + // WHERE media.media_id IN ? AND album.owner_id = ? + // AND media.media_id IN ( + // SELECT media_id FROM media_url WHERE media_url.media_id = media.media_id + // ) + // `, ids, user.ID).Error if err != nil { return nil, errors.Wrap(err, "could not get media list by media_id and user_id from database") @@ -197,44 +198,6 @@ func (r *mediaResolver) VideoWeb(ctx context.Context, media *models.Media) (*mod return &url, nil } -// func (r *mediaResolver) Album(ctx context.Context, media *models.Media) (*models.Album, error) { - -// r.Database.Model(&media).Joins("Album") - -// row := r.Database.QueryRow("SELECT album.* from media JOIN album ON media.album_id = album.album_id WHERE media_id = ?", media.MediaID) -// return models.NewAlbumFromRow(row) -// } - -// func (r *mediaResolver) Exif(ctx context.Context, obj *models.Media) (*models.MediaEXIF, error) { -// row := r.Database.QueryRow("SELECT media_exif.* FROM media NATURAL JOIN media_exif WHERE media.media_id = ?", obj.MediaID) - -// exif, err := models.NewMediaExifFromRow(row) -// if err != nil { -// if errors.Is(err, gorm.ErrRecordNotFound) { -// return nil, nil -// } else { -// return nil, errors.Wrapf(err, "could not get exif of media from database") -// } -// } - -// return exif, nil -// } - -// func (r *mediaResolver) VideoMetadata(ctx context.Context, obj *models.Media) (*models.VideoMetadata, error) { -// row := r.Database.QueryRow("SELECT video_metadata.* FROM media JOIN video_metadata ON media.video_metadata_id = video_metadata.metadata_id WHERE media.media_id = ?", obj.MediaID) - -// metadata, err := models.NewVideoMetadataFromRow(row) -// if err != nil { -// if errors.Is(err, gorm.ErrRecordNotFound) { -// return nil, nil -// } else { -// return nil, errors.Wrapf(err, "could not get video metadata of media from database") -// } -// } - -// return metadata, nil -// } - func (r *mutationResolver) FavoriteMedia(ctx context.Context, mediaID int, favorite bool) (*models.Media, error) { user := auth.UserFromContext(ctx) diff --git a/api/scanner/cache.go b/api/scanner/cache.go index 222451b1..64767bbd 100644 --- a/api/scanner/cache.go +++ b/api/scanner/cache.go @@ -3,6 +3,8 @@ package scanner import ( "path" "sync" + + "github.com/pkg/errors" ) type AlbumScannerCache struct { @@ -73,7 +75,7 @@ func (c *AlbumScannerCache) GetMediaType(path string) (*MediaType, error) { mediaType, err := getMediaType(path) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "get media type (%s)", path) } if mediaType != nil { diff --git a/api/scanner/process_photo.go b/api/scanner/process_photo.go index 1aeef08d..bd47db4f 100644 --- a/api/scanner/process_photo.go +++ b/api/scanner/process_photo.go @@ -26,7 +26,7 @@ func makePhotoURLChecker(tx *gorm.DB, mediaID int) func(purpose models.MediaPurp return func(purpose models.MediaPurpose) (*models.MediaURL, error) { var mediaURL []*models.MediaURL - result := tx.Where("purpose = ?", purpose).Find(&mediaURL, mediaID) + result := tx.Where("purpose = ?", purpose).Where("media_id = ?", mediaID).Find(&mediaURL) if result.Error != nil { return nil, result.Error