2020-02-05 16:14:21 +01:00
|
|
|
package resolvers
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2020-12-22 01:14:43 +01:00
|
|
|
"errors"
|
2020-02-05 16:14:21 +01:00
|
|
|
|
2020-12-17 22:51:43 +01:00
|
|
|
api "github.com/photoview/photoview/api/graphql"
|
|
|
|
"github.com/photoview/photoview/api/graphql/auth"
|
|
|
|
"github.com/photoview/photoview/api/graphql/models"
|
2020-12-22 01:14:43 +01:00
|
|
|
"gorm.io/gorm"
|
2020-02-05 16:14:21 +01:00
|
|
|
)
|
|
|
|
|
2020-09-07 12:04:14 +02:00
|
|
|
func (r *queryResolver) MyAlbums(ctx context.Context, filter *models.Filter, onlyRoot *bool, showEmpty *bool, onlyWithFavorites *bool) ([]*models.Album, error) {
|
2020-02-09 15:26:59 +01:00
|
|
|
user := auth.UserFromContext(ctx)
|
|
|
|
if user == nil {
|
|
|
|
return nil, auth.ErrUnauthorized
|
|
|
|
}
|
|
|
|
|
2020-12-22 01:14:43 +01:00
|
|
|
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)
|
2020-02-09 15:26:59 +01:00
|
|
|
|
2020-11-28 21:29:31 +01:00
|
|
|
if onlyRoot != nil && *onlyRoot == true {
|
2020-12-22 01:14:43 +01:00
|
|
|
query = query.Where("parent_album_id = (?)", r.Database.Model(&models.Album{}).Select("id").Where("parent_album_id IS NULL"))
|
2020-09-07 12:04:14 +02:00
|
|
|
}
|
|
|
|
|
2020-11-28 21:29:31 +01:00
|
|
|
if showEmpty == nil || *showEmpty == false {
|
2020-11-28 21:49:33 +01:00
|
|
|
subQuery := r.Database.Model(&models.Media{}).Where("album_id = albums.id")
|
2020-02-20 17:14:11 +01:00
|
|
|
|
2020-11-28 21:29:31 +01:00
|
|
|
if onlyWithFavorites != nil && *onlyWithFavorites == true {
|
|
|
|
subQuery = subQuery.Where("favorite = 1")
|
2020-02-20 17:14:11 +01:00
|
|
|
}
|
2020-11-28 21:29:31 +01:00
|
|
|
|
|
|
|
query = query.Where("EXISTS (?)", subQuery)
|
2020-02-09 15:26:59 +01:00
|
|
|
}
|
|
|
|
|
2020-12-17 21:32:13 +01:00
|
|
|
query = filter.FormatSQL(query)
|
2020-11-28 21:29:31 +01:00
|
|
|
|
|
|
|
var albums []*models.Album
|
2020-12-22 01:14:43 +01:00
|
|
|
if err := query.Scan(&albums).Error; err != nil {
|
2020-02-09 15:26:59 +01:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return albums, nil
|
2020-02-05 16:14:21 +01:00
|
|
|
}
|
2020-02-09 15:26:59 +01:00
|
|
|
|
2020-02-09 21:25:33 +01:00
|
|
|
func (r *queryResolver) Album(ctx context.Context, id int) (*models.Album, error) {
|
2020-02-05 16:14:21 +01:00
|
|
|
user := auth.UserFromContext(ctx)
|
|
|
|
if user == nil {
|
|
|
|
return nil, auth.ErrUnauthorized
|
|
|
|
}
|
|
|
|
|
2020-11-28 21:29:31 +01:00
|
|
|
var album models.Album
|
2020-12-22 01:14:43 +01:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
ownsAlbum, err := user.OwnsAlbum(r.Database, &album)
|
|
|
|
if err != nil {
|
2020-02-05 16:14:21 +01:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-12-22 01:14:43 +01:00
|
|
|
if !ownsAlbum {
|
|
|
|
return nil, errors.New("forbidden")
|
|
|
|
}
|
|
|
|
|
2020-11-28 21:29:31 +01:00
|
|
|
return &album, nil
|
2020-02-05 16:14:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *Resolver) Album() api.AlbumResolver {
|
|
|
|
return &albumResolver{r}
|
|
|
|
}
|
|
|
|
|
|
|
|
type albumResolver struct{ *Resolver }
|
|
|
|
|
2020-11-28 21:29:31 +01:00
|
|
|
func (r *albumResolver) Media(ctx context.Context, album *models.Album, filter *models.Filter, onlyFavorites *bool) ([]*models.Media, error) {
|
2020-02-09 15:26:59 +01:00
|
|
|
|
2020-11-28 21:29:31 +01:00
|
|
|
query := r.Database.
|
|
|
|
Joins("Album").
|
|
|
|
Where("Album.id = ?", album.ID).
|
2020-11-30 21:29:49 +01:00
|
|
|
Where("media.id IN (?)", r.Database.Model(&models.MediaURL{}).Select("media_urls.media_id").Where("media_urls.media_id = media.id"))
|
2020-02-09 15:26:59 +01:00
|
|
|
|
2020-11-28 21:29:31 +01:00
|
|
|
if onlyFavorites != nil && *onlyFavorites == true {
|
|
|
|
query = query.Where("media.favorite = 1")
|
2020-09-07 12:04:14 +02:00
|
|
|
}
|
|
|
|
|
2020-12-17 21:32:13 +01:00
|
|
|
query = filter.FormatSQL(query)
|
2020-02-05 16:14:21 +01:00
|
|
|
|
2020-11-28 21:29:31 +01:00
|
|
|
var media []*models.Media
|
|
|
|
if err := query.Find(&media).Error; err != nil {
|
2020-02-05 16:14:21 +01:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-07-10 14:26:19 +02:00
|
|
|
return media, nil
|
2020-02-05 16:14:21 +01:00
|
|
|
}
|
|
|
|
|
2020-07-10 14:26:19 +02:00
|
|
|
func (r *albumResolver) Thumbnail(ctx context.Context, obj *models.Album) (*models.Media, error) {
|
2020-02-09 16:16:41 +01:00
|
|
|
|
2020-12-08 16:24:08 +01:00
|
|
|
var media models.Media
|
|
|
|
|
|
|
|
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
|
|
|
|
)
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &media, nil
|
2020-02-09 16:16:41 +01:00
|
|
|
}
|
|
|
|
|
2020-11-28 21:29:31 +01:00
|
|
|
func (r *albumResolver) SubAlbums(ctx context.Context, parent *models.Album, filter *models.Filter) ([]*models.Album, error) {
|
2020-02-09 16:16:41 +01:00
|
|
|
|
2020-11-28 21:29:31 +01:00
|
|
|
var albums []*models.Album
|
2020-12-17 21:32:13 +01:00
|
|
|
|
|
|
|
query := r.Database.Where("parent_album_id = ?", parent.ID)
|
|
|
|
query = filter.FormatSQL(query)
|
|
|
|
|
|
|
|
if err := query.Find(&albums).Error; err != nil {
|
2020-02-09 15:26:59 +01:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return albums, nil
|
2020-02-05 16:14:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *albumResolver) ParentAlbum(ctx context.Context, obj *models.Album) (*models.Album, error) {
|
|
|
|
panic("not implemented")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *albumResolver) Owner(ctx context.Context, obj *models.Album) (*models.User, error) {
|
|
|
|
panic("not implemented")
|
|
|
|
}
|
2020-02-11 14:32:35 +01:00
|
|
|
|
2020-11-28 21:29:31 +01:00
|
|
|
func (r *albumResolver) Shares(ctx context.Context, album *models.Album) ([]*models.ShareToken, error) {
|
|
|
|
|
|
|
|
var shareTokens []*models.ShareToken
|
2020-11-28 21:49:33 +01:00
|
|
|
if err := r.Database.Where("album_id = ?", album.ID).Find(&shareTokens).Error; err != nil {
|
2020-02-11 14:32:35 +01:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-11-28 21:29:31 +01:00
|
|
|
return shareTokens, nil
|
2020-02-11 14:32:35 +01:00
|
|
|
}
|
2020-03-07 16:19:27 +01:00
|
|
|
|
|
|
|
func (r *albumResolver) Path(ctx context.Context, obj *models.Album) ([]*models.Album, error) {
|
|
|
|
|
2020-12-08 16:24:08 +01:00
|
|
|
user := auth.UserFromContext(ctx)
|
|
|
|
if user == nil {
|
|
|
|
empty := make([]*models.Album, 0)
|
|
|
|
return empty, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var album_path []*models.Album
|
|
|
|
|
|
|
|
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
|
|
|
|
)
|
2020-12-22 01:14:43 +01:00
|
|
|
SELECT * FROM path_albums WHERE id != ?
|
|
|
|
`, 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
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2020-12-08 16:24:08 +01:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return album_path, nil
|
2020-03-07 16:19:27 +01:00
|
|
|
}
|