1
0
mirror of https://github.com/pocketbase/pocketbase.git synced 2025-02-03 09:57:24 +02:00

[#151] remove files on cascade deletion

This commit is contained in:
Gani Georgiev 2022-07-18 12:04:27 +03:00
parent 04e0cec32c
commit 8ef3d4e966
6 changed files with 44 additions and 47 deletions

View File

@ -1,8 +1,6 @@
package apis
import (
"errors"
"log"
"net/http"
"github.com/labstack/echo/v5"
@ -160,13 +158,6 @@ func (api *collectionApi) delete(c echo.Context) error {
return rest.NewBadRequestError("Failed to delete collection. Make sure that the collection is not referenced by other collections.", err)
}
// try to delete the collection files
if err := api.deleteCollectionFiles(e.Collection); err != nil && api.app.IsDebug() {
// non critical error - only log for debug
// (usually could happen because of S3 api limits)
log.Println(err)
}
return e.HttpContext.NoContent(http.StatusNoContent)
})
@ -176,18 +167,3 @@ func (api *collectionApi) delete(c echo.Context) error {
return handlerErr
}
func (api *collectionApi) deleteCollectionFiles(collection *models.Collection) error {
fs, err := api.app.NewFilesystem()
if err != nil {
return err
}
defer fs.Close()
failed := fs.DeletePrefix(collection.BaseFilesPath())
if len(failed) > 0 {
return errors.New("Failed to delete all record files.")
}
return nil
}

View File

@ -356,13 +356,6 @@ func (api *recordApi) delete(c echo.Context) error {
return rest.NewBadRequestError("Failed to delete record. Make sure that the record is not part of a required relation reference.", err)
}
// try to delete the record files
if err := api.deleteRecordFiles(e.Record); err != nil && api.app.IsDebug() {
// non critical error - only log for debug
// (usually could happen due to S3 api limits)
log.Println(err)
}
return e.HttpContext.NoContent(http.StatusNoContent)
})
@ -373,21 +366,6 @@ func (api *recordApi) delete(c echo.Context) error {
return handlerErr
}
func (api *recordApi) deleteRecordFiles(record *models.Record) error {
fs, err := api.app.NewFilesystem()
if err != nil {
return err
}
defer fs.Close()
failed := fs.DeletePrefix(record.BaseFilesPath())
if len(failed) > 0 {
return fmt.Errorf("Failed to delete %d record files.", len(failed))
}
return nil
}
func (api *recordApi) exportRequestData(c echo.Context) map[string]any {
result := map[string]any{}
queryParams := map[string]any{}

View File

@ -5,6 +5,7 @@ import (
"database/sql"
"encoding/json"
"errors"
"log"
"os"
"path/filepath"
"time"
@ -123,7 +124,7 @@ type BaseApp struct {
//
// To initialize the app, you need to call `app.Bootsrap()`.
func NewBaseApp(dataDir string, encryptionEnv string, isDebug bool) *BaseApp {
return &BaseApp{
app := &BaseApp{
dataDir: dataDir,
isDebug: isDebug,
encryptionEnv: encryptionEnv,
@ -209,6 +210,10 @@ func NewBaseApp(dataDir string, encryptionEnv string, isDebug bool) *BaseApp {
onCollectionBeforeDeleteRequest: &hook.Hook[*CollectionDeleteEvent]{},
onCollectionAfterDeleteRequest: &hook.Hook[*CollectionDeleteEvent]{},
}
app.registerDefaultHooks()
return app
}
// Bootstrap initializes the application
@ -750,3 +755,33 @@ func (app *BaseApp) createDao(db dbx.Builder) *daos.Dao {
return dao
}
func (app *BaseApp) registerDefaultHooks() {
deletePrefix := func(prefix string) error {
fs, err := app.NewFilesystem()
if err != nil {
return err
}
defer fs.Close()
failed := fs.DeletePrefix(prefix)
if len(failed) > 0 {
return errors.New("Failed to delete the files at " + prefix)
}
return nil
}
// delete storage files from deleted Collection, Records, etc.
app.OnModelAfterDelete().Add(func(e *ModelEvent) error {
if m, ok := e.Model.(models.FilesManager); ok && m.BaseFilesPath() != "" {
if err := deletePrefix(m.BaseFilesPath()); err != nil && app.IsDebug() {
// non critical error - only log for debug
// (usually could happen because of S3 api limits)
log.Println(err)
}
}
return nil
})
}

View File

@ -15,6 +15,12 @@ type ColumnValueMapper interface {
ColumnValueMap() map[string]any
}
// FilesManager defines an interface with common methods that files manager models should implement.
type FilesManager interface {
// BaseFilesPath returns the storage dir path used by the interface instance.
BaseFilesPath() string
}
// Model defines an interface with common methods that all db models should have.
type Model interface {
TableName() string

View File

@ -3,6 +3,7 @@ package models
import "github.com/pocketbase/pocketbase/models/schema"
var _ Model = (*Collection)(nil)
var _ FilesManager = (*Collection)(nil)
type Collection struct {
BaseModel

View File

@ -16,6 +16,7 @@ import (
var _ Model = (*Record)(nil)
var _ ColumnValueMapper = (*Record)(nil)
var _ FilesManager = (*Record)(nil)
type Record struct {
BaseModel