forked from usememos/memos
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathresource.go
155 lines (135 loc) · 3.8 KB
/
resource.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package store
import (
"context"
"log/slog"
"os"
"path/filepath"
"github.com/pkg/errors"
"github.com/usememos/memos/internal/util"
"github.com/usememos/memos/plugin/storage/s3"
storepb "github.com/usememos/memos/proto/gen/store"
)
type Resource struct {
// ID is the system generated unique identifier for the resource.
ID int32
// UID is the user defined unique identifier for the resource.
UID string
// Standard fields
CreatorID int32
CreatedTs int64
UpdatedTs int64
// Domain specific fields
Filename string
Blob []byte
Type string
Size int64
StorageType storepb.ResourceStorageType
Reference string
Payload *storepb.ResourcePayload
// The related memo ID.
MemoID *int32
}
type FindResource struct {
GetBlob bool
ID *int32
UID *string
CreatorID *int32
Filename *string
FilenameSearch *string
MemoID *int32
HasRelatedMemo bool
StorageType *storepb.ResourceStorageType
Limit *int
Offset *int
}
type UpdateResource struct {
ID int32
UID *string
UpdatedTs *int64
Filename *string
MemoID *int32
Reference *string
Payload *storepb.ResourcePayload
}
type DeleteResource struct {
ID int32
MemoID *int32
}
func (s *Store) CreateResource(ctx context.Context, create *Resource) (*Resource, error) {
if !util.UIDMatcher.MatchString(create.UID) {
return nil, errors.New("invalid uid")
}
return s.driver.CreateResource(ctx, create)
}
func (s *Store) ListResources(ctx context.Context, find *FindResource) ([]*Resource, error) {
return s.driver.ListResources(ctx, find)
}
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
}
func (s *Store) UpdateResource(ctx context.Context, update *UpdateResource) error {
if update.UID != nil && !util.UIDMatcher.MatchString(*update.UID) {
return errors.New("invalid uid")
}
return s.driver.UpdateResource(ctx, update)
}
func (s *Store) DeleteResource(ctx context.Context, delete *DeleteResource) error {
resource, err := s.GetResource(ctx, &FindResource{ID: &delete.ID})
if err != nil {
return errors.Wrap(err, "failed to get resource")
}
if resource == nil {
return errors.Wrap(nil, "resource not found")
}
if resource.StorageType == storepb.ResourceStorageType_LOCAL {
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 := s3ObjectPayload.S3Config
if s3Config == nil {
if workspaceStorageSetting.S3Config == nil {
return errors.Errorf("S3 config is not found")
}
s3Config = workspaceStorageSetting.S3Config
}
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", slog.Any("err", err))
}
}
return s.driver.DeleteResource(ctx, delete)
}