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:
parent
04e0cec32c
commit
8ef3d4e966
@ -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
|
||||
}
|
||||
|
@ -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{}
|
||||
|
37
core/base.go
37
core/base.go
@ -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
|
||||
})
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
|
||||
var _ Model = (*Record)(nil)
|
||||
var _ ColumnValueMapper = (*Record)(nil)
|
||||
var _ FilesManager = (*Record)(nil)
|
||||
|
||||
type Record struct {
|
||||
BaseModel
|
||||
|
Loading…
x
Reference in New Issue
Block a user