1
Fork 0

Properly clean up when a user <-> album relation is deleted

This commit is contained in:
viktorstrate 2021-01-06 17:28:06 +01:00
parent 59048c8416
commit a1a14286d6
No known key found for this signature in database
GPG Key ID: 3F855605109C1E8A
7 changed files with 82 additions and 42 deletions

View File

@ -11,7 +11,7 @@ type Album struct {
Model
Title string `gorm:"not null"`
ParentAlbumID *int
ParentAlbum *Album
ParentAlbum *Album `gorm:"constraint:OnDelete:SET NULL;"`
// OwnerID int `gorm:"not null"`
// Owner User
Owners []User `gorm:"many2many:user_albums"`

View File

@ -17,16 +17,16 @@ type Media struct {
Path string `gorm:"not null"`
PathHash string `gorm:"not null"`
AlbumID int `gorm:"not null"`
Album Album
Album Album `gorm:"constraint:OnDelete:CASCADE;"`
ExifID *int
Exif *MediaEXIF
MediaURL []MediaURL
DateShot time.Time `gorm:"not null"`
DateImported time.Time `gorm:"not null"`
Exif *MediaEXIF `gorm:"constraint:OnDelete:SET NULL;"`
MediaURL []MediaURL `gorm:"constraint:OnDelete:CASCADE;"`
DateShot time.Time `gorm:"not null"`
DateImported time.Time `gorm:"not null"`
// Favorite bool `gorm:"not null, default:false"`
Type MediaType `gorm:"not null"`
VideoMetadataID *int
VideoMetadata *VideoMetadata
VideoMetadata *VideoMetadata `gorm:"constraint:OnDelete:SET NULL;"`
SideCarPath *string
SideCarHash *string
@ -52,6 +52,18 @@ func (m *Media) BeforeSave(tx *gorm.DB) error {
return nil
}
func (m *Media) BeforeDelete(tx *gorm.DB) error {
if err := tx.Model(m).Association("Exif").Clear(); err != nil {
return err
}
if err := tx.Model(m).Association("MediaURL").Clear(); err != nil {
return err
}
return nil
}
type MediaPurpose string
const (
@ -64,8 +76,8 @@ const (
type MediaURL struct {
Model
MediaID int `gorm:"not null"`
Media Media
MediaID int `gorm:"not null"`
Media Media `gorm:"constraint:OnDelete:CASCADE;"`
MediaName string `gorm:"not null"`
Width int `gorm:"not null"`
Height int `gorm:"not null"`

View File

@ -8,13 +8,13 @@ type ShareToken struct {
Model
Value string `gorm:"not null"`
OwnerID int `gorm:"not null"`
Owner User
Owner User `gorm:"constraint:OnDelete:CASCADE;"`
Expire *time.Time
Password *string
AlbumID *int
Album *Album
Album *Album `gorm:"constraint:OnDelete:CASCADE;"`
MediaID *int
Media *Media
Media *Media `gorm:"constraint:OnDelete:CASCADE;"`
}
func (share *ShareToken) Token() string {

View File

@ -3,7 +3,9 @@ package resolvers
import (
"context"
"fmt"
"os"
"path"
"strconv"
"strings"
api "github.com/photoview/photoview/api/graphql"
@ -280,28 +282,65 @@ func (r *mutationResolver) UserRemoveRootAlbum(ctx context.Context, userID int,
return nil, err
}
if err := r.Database.Raw("DELETE FROM user_albums WHERE user_id = ? AND album_id = ?", userID, albumID).Error; err != nil {
return nil, err
}
var deletedAlbumIDs []int = nil
err := r.Database.Transaction(func(tx *gorm.DB) error {
if err := tx.Raw("DELETE FROM user_albums WHERE user_id = ? AND album_id = ?", userID, albumID).Error; err != nil {
return err
}
children, err := album.GetChildren(tx)
if err != nil {
return err
}
childAlbumIDs := make([]int, len(children))
for i, child := range children {
childAlbumIDs[i] = child.ID
}
result := tx.Exec("DELETE FROM user_albums WHERE user_id = ? and album_id IN (?)", userID, childAlbumIDs)
if result.Error != nil {
return result.Error
}
if result.RowsAffected == 0 {
return errors.New("No relation deleted")
}
// Cleanup if no user owns the album anymore
var count int
if err := tx.Raw("SELECT COUNT(user_id) FROM user_albums WHERE album_id = ?", albumID).Scan(&count).Error; err != nil {
return err
}
if count == 0 {
deletedAlbumIDs = append(childAlbumIDs, albumID)
childAlbumIDs = nil
// Delete albums from database
if err := tx.Delete(&models.Album{}, "id IN (?)", deletedAlbumIDs).Error; err != nil {
deletedAlbumIDs = nil
return err
}
}
return nil
})
children, err := album.GetChildren(r.Database)
if err != nil {
return nil, err
}
childAlbumIDs := make([]int, len(children))
for i, child := range children {
childAlbumIDs[i] = child.ID
}
if deletedAlbumIDs != nil {
// Delete albums from cache
for _, id := range deletedAlbumIDs {
cacheAlbumPath := path.Join(scanner.PhotoCache(), strconv.Itoa(id))
// result := r.Database.Delete(models.Album{}, "id IN (?) OR id = ?", childAlbumIDs, album.ID)
result := r.Database.Exec("DELETE FROM user_albums WHERE user_id = ? and album_id IN (?)", userID, childAlbumIDs)
if result.Error != nil {
return nil, result.Error
}
if result.RowsAffected == 0 {
return nil, errors.New("No relation deleted")
if err := os.RemoveAll(cacheAlbumPath); err != nil {
return nil, err
}
}
}
return &album, nil

View File

@ -63,7 +63,6 @@ const EditUserRow = ({
variables: {
id: user.id,
username: state.username,
rootPath: state.rootPath,
admin: state.admin,
},
})

View File

@ -93,6 +93,7 @@ const EditNewRootPath = ({ userID }) => {
icon: 'add',
content: 'Add',
onClick: () => {
setValue('')
addRootPath({
variables: {
id: userID,

View File

@ -5,21 +5,10 @@ import EditUserRow from './EditUserRow'
import ViewUserRow from './ViewUserRow'
const updateUserMutation = gql`
mutation updateUser(
$id: ID!
$username: String
$rootPath: String
$admin: Boolean
) {
updateUser(
id: $id
username: $username
rootPath: $rootPath
admin: $admin
) {
mutation updateUser($id: ID!, $username: String, $admin: Boolean) {
updateUser(id: $id, username: $username, admin: $admin) {
id
username
rootPath
admin
}
}