memos/store/resource.go

148 lines
3.6 KiB
Go
Raw Normal View History

package store
2022-02-03 15:32:03 +08:00
import (
2022-08-07 10:17:12 +08:00
"context"
2024-05-02 21:44:17 +08:00
"log/slog"
2023-10-28 10:42:39 +08:00
"os"
"path/filepath"
"github.com/pkg/errors"
"github.com/usememos/memos/internal/util"
2024-05-02 21:44:17 +08:00
"github.com/usememos/memos/plugin/storage/s3"
2024-05-02 21:28:06 +08:00
storepb "github.com/usememos/memos/proto/gen/store"
2022-02-03 15:32:03 +08:00
)
type Resource struct {
2024-03-20 20:39:16 +08:00
// ID is the system generated unique identifier for the resource.
ID int32
// UID is the user defined unique identifier for the resource.
UID string
2022-05-19 18:32:04 +08:00
// Standard fields
2023-08-04 21:55:07 +08:00
CreatorID int32
2022-05-19 18:32:04 +08:00
CreatedTs int64
UpdatedTs int64
// Domain specific fields
2024-05-02 21:28:06 +08:00
Filename string
Blob []byte
Type string
Size int64
StorageType storepb.ResourceStorageType
Reference string
Payload *storepb.ResourcePayload
// The related memo ID.
MemoID *int32
2022-05-19 18:32:04 +08:00
}
type FindResource struct {
2023-09-16 11:48:53 +08:00
GetBlob bool
ID *int32
2024-03-20 20:39:16 +08:00
UID *string
2023-09-16 11:48:53 +08:00
CreatorID *int32
Filename *string
MemoID *int32
HasRelatedMemo bool
Limit *int
Offset *int
2022-05-19 18:32:04 +08:00
}
type UpdateResource struct {
2024-05-02 21:28:06 +08:00
ID int32
UID *string
UpdatedTs *int64
Filename *string
MemoID *int32
}
2022-10-01 10:37:02 +08:00
type DeleteResource struct {
ID int32
MemoID *int32
2022-02-03 15:32:03 +08:00
}
func (s *Store) CreateResource(ctx context.Context, create *Resource) (*Resource, error) {
2024-03-20 20:39:16 +08:00
if !util.UIDMatcher.MatchString(create.UID) {
return nil, errors.New("invalid uid")
2024-01-21 10:49:30 +08:00
}
return s.driver.CreateResource(ctx, create)
2023-05-26 00:38:27 +08:00
}
func (s *Store) ListResources(ctx context.Context, find *FindResource) ([]*Resource, error) {
return s.driver.ListResources(ctx, find)
2022-11-06 12:21:58 +08:00
}
func (s *Store) GetResource(ctx context.Context, find *FindResource) (*Resource, error) {
resources, err := s.ListResources(ctx, find)
if err != nil {
return nil, err
}
if len(resources) == 0 {
return nil, nil
}
return resources[0], nil
}
2024-05-02 21:28:06 +08:00
func (s *Store) UpdateResource(ctx context.Context, update *UpdateResource) error {
2024-03-20 20:39:16 +08:00
if update.UID != nil && !util.UIDMatcher.MatchString(*update.UID) {
2024-05-02 21:28:06 +08:00
return errors.New("invalid uid")
2024-01-21 10:49:30 +08:00
}
return s.driver.UpdateResource(ctx, update)
}
func (s *Store) DeleteResource(ctx context.Context, delete *DeleteResource) error {
2023-10-28 10:42:39 +08:00
resource, err := s.GetResource(ctx, &FindResource{ID: &delete.ID})
if err != nil {
return errors.Wrap(err, "failed to get resource")
}
2023-10-28 10:51:03 +08:00
if resource == nil {
return errors.Wrap(nil, "resource not found")
}
2023-10-28 10:42:39 +08:00
2024-05-02 21:28:06 +08:00
if resource.StorageType == storepb.ResourceStorageType_LOCAL {
2024-05-02 21:44:17 +08:00
if err := func() error {
p := filepath.FromSlash(resource.Reference)
if !filepath.IsAbs(p) {
p = filepath.Join(s.Profile.Data, p)
}
err := os.Remove(p)
if err != nil {
return errors.Wrap(err, "failed to delete local file")
}
return nil
}(); err != nil {
return errors.Wrap(err, "failed to delete local file")
}
} else if resource.StorageType == storepb.ResourceStorageType_S3 {
if err := func() error {
s3ObjectPayload := resource.Payload.GetS3Object()
if s3ObjectPayload == nil {
return errors.Errorf("No s3 object found")
}
workspaceStorageSetting, err := s.GetWorkspaceStorageSetting(ctx)
if err != nil {
return errors.Wrap(err, "failed to get workspace storage setting")
}
s3Config := workspaceStorageSetting.S3Config
if s3Config == nil {
return errors.Errorf("No actived external storage found")
}
s3Client, err := s3.NewClient(ctx, s3Config)
if err != nil {
return errors.Wrap(err, "Failed to create s3 client")
}
if err := s3Client.DeleteObject(ctx, s3ObjectPayload.Key); err != nil {
return errors.Wrap(err, "Failed to delete s3 object")
}
return nil
}(); err != nil {
slog.Warn("Failed to delete s3 object", err)
}
2023-10-28 10:42:39 +08:00
}
2024-01-21 10:49:30 +08:00
return s.driver.DeleteResource(ctx, delete)
}