Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow setting of arbitrary metadata, minor bug fixes #764

Merged
merged 1 commit into from
May 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/grpc/services/gateway/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1209,7 +1209,7 @@ func (s *svc) getPath(ctx context.Context, ref *provider.Reference) (string, err
return ref.GetPath(), nil
}

if ref.GetId() != nil {
if ref.GetId() != nil && ref.GetId().GetOpaqueId() != "" {
req := &provider.StatRequest{Ref: ref}
res, err := s.stat(ctx, req)
if err != nil {
Expand Down
20 changes: 16 additions & 4 deletions pkg/storage/fs/local/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func initializeDB(root string) (*sql.DB, error) {
return nil, errors.Wrap(err, "localfs: error executing create statement")
}

stmt, err = db.Prepare("CREATE TABLE IF NOT EXISTS metadata (resource TEXT PRIMARY KEY, etag TEXT DEFAULT '')")
stmt, err = db.Prepare("CREATE TABLE IF NOT EXISTS metadata (resource TEXT, key TEXT, value TEXT, PRIMARY KEY (resource, key))")
if err != nil {
return nil, errors.Wrap(err, "localfs: error preparing statement")
}
Expand Down Expand Up @@ -164,18 +164,30 @@ func (fs *localfs) removeFromFavoritesDB(ctx context.Context, resource, grantee
return nil
}

func (fs *localfs) addToEtagDB(ctx context.Context, resource, etag string) error {
stmt, err := fs.db.Prepare("INSERT INTO metadata (resource, etag) VALUES (?, ?) ON CONFLICT(resource) DO UPDATE SET etag=?")
func (fs *localfs) addToMetadataDB(ctx context.Context, resource, key, value string) error {
stmt, err := fs.db.Prepare("INSERT INTO metadata (resource, key, value) VALUES (?, ?, ?) ON CONFLICT(resource, key) DO UPDATE SET value=?")
if err != nil {
return errors.Wrap(err, "localfs: error preparing statement")
}
_, err = stmt.Exec(resource, etag, etag)
_, err = stmt.Exec(resource, key, value, value)
if err != nil {
return errors.Wrap(err, "localfs: error executing insert statement")
}
return nil
}

func (fs *localfs) removeFromMetadataDB(ctx context.Context, resource, key string) error {
stmt, err := fs.db.Prepare("DELETE FROM metadata WHERE resource=? AND key=?")
if err != nil {
return errors.Wrap(err, "localfs: error preparing statement")
}
_, err = stmt.Exec(resource, key)
if err != nil {
return errors.Wrap(err, "localfs: error executing delete statement")
}
return nil
}

func (fs *localfs) addToReferencesDB(ctx context.Context, resource, target string) error {
stmt, err := fs.db.Prepare("INSERT INTO share_references (resource, target) VALUES (?, ?) ON CONFLICT(resource) DO UPDATE SET target=?")
if err != nil {
Expand Down
67 changes: 43 additions & 24 deletions pkg/storage/fs/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -517,31 +517,41 @@ func (fs *localfs) SetArbitraryMetadata(ctx context.Context, ref *provider.Refer
} else {
return errors.Wrap(err, "could not parse mtime")
}
delete(md.Metadata, "mtime")
}

if _, ok := md.Metadata["etag"]; ok {
etag := calcEtag(ctx, fi)
if etag != md.Metadata["etag"] {
err = fs.addToEtagDB(ctx, np, etag)
err = fs.addToMetadataDB(ctx, np, "etag", etag)
if err != nil {
return errors.Wrap(err, "localfs: error adding entry to DB")
}
}
delete(md.Metadata, "etag")
}

if _, ok := md.Metadata["favorite"]; ok {
if u, err := getUser(ctx); err != nil {
if uid := u.GetId(); uid != nil {
usr := fmt.Sprintf("u:%s@%s", uid.GetOpaqueId(), uid.GetIdp())
if err = fs.addToFavoritesDB(ctx, np, usr); err != nil {
return errors.Wrap(err, "localfs: error adding entry to DB")
}
} else {
return errors.Wrap(errtypes.UserRequired("userrequired"), "user has no id")
u, err := getUser(ctx)
if err != nil {
return err
}
if uid := u.GetId(); uid != nil {
usr := fmt.Sprintf("u:%s@%s", uid.GetOpaqueId(), uid.GetIdp())
if err = fs.addToFavoritesDB(ctx, np, usr); err != nil {
return errors.Wrap(err, "localfs: error adding entry to DB")
}
} else {
return err
return errors.Wrap(errtypes.UserRequired("userrequired"), "user has no id")
}
delete(md.Metadata, "favorite")
}
}

for k, v := range md.Metadata {
err = fs.addToMetadataDB(ctx, np, k, v)
if err != nil {
return errors.Wrap(err, "localfs: error adding entry to DB")
}
}

Expand Down Expand Up @@ -587,20 +597,27 @@ func (fs *localfs) UnsetArbitraryMetadata(ctx context.Context, ref *provider.Ref
for _, k := range keys {
switch k {
case "favorite":
if u, err := getUser(ctx); err != nil {
if uid := u.GetId(); uid != nil {
usr := fmt.Sprintf("u:%s@%s", uid.GetOpaqueId(), uid.GetIdp())
if err = fs.removeFromFavoritesDB(ctx, np, usr); err != nil {
return errors.Wrap(err, "localfs: error removing entry from DB")
}
} else {
return errors.Wrap(errtypes.UserRequired("userrequired"), "user has no id")
u, err := getUser(ctx)
if err != nil {
return err
}
if uid := u.GetId(); uid != nil {
usr := fmt.Sprintf("u:%s@%s", uid.GetOpaqueId(), uid.GetIdp())
if err = fs.removeFromFavoritesDB(ctx, np, usr); err != nil {
return errors.Wrap(err, "localfs: error removing entry from DB")
}
} else {
return err
return errors.Wrap(errtypes.UserRequired("userrequired"), "user has no id")
}
case "etag":
return errors.Wrap(errtypes.NotSupported("unsetting etag not supported"), "could not unset metadata")
case "mtime":
return errors.Wrap(errtypes.NotSupported("unsetting mtime not supported"), "could not unset metadata")
default:
return errors.Wrap(errtypes.NotSupported("metadata not supported"), "could not unset metadata")
err = fs.removeFromMetadataDB(ctx, np, k)
if err != nil {
return errors.Wrap(err, "localfs: error adding entry to DB")
}
}
}

Expand Down Expand Up @@ -707,7 +724,7 @@ func (fs *localfs) Delete(ctx context.Context, ref *provider.Reference) error {
return errors.Wrap(err, "localfs: error adding entry to DB")
}

return fs.propagate(ctx, path.Dir(fn))
return fs.propagate(ctx, path.Dir(fp))
}

func (fs *localfs) Move(ctx context.Context, oldRef, newRef *provider.Reference) error {
Expand Down Expand Up @@ -974,7 +991,7 @@ func (fs *localfs) DownloadRevision(ctx context.Context, ref *provider.Reference
}

versionsDir := fs.wrapVersions(ctx, np)
vp := path.Join(versionsDir, fmt.Sprintf(".v%s", revisionKey))
vp := path.Join(versionsDir, revisionKey)

r, err := os.Open(vp)
if err != nil {
Expand All @@ -998,7 +1015,8 @@ func (fs *localfs) RestoreRevision(ctx context.Context, ref *provider.Reference,
}

versionsDir := fs.wrapVersions(ctx, np)
vp := path.Join(versionsDir, fmt.Sprintf(".v%s", revisionKey))
vp := path.Join(versionsDir, revisionKey)
np = fs.wrap(ctx, np)

// check revision exists
vs, err := os.Stat(vp)
Expand Down Expand Up @@ -1110,8 +1128,9 @@ func (fs *localfs) RestoreRecycleItem(ctx context.Context, restoreKey string) er
} else {
originalPath = fs.wrap(ctx, filePath)
}

if _, err = os.Stat(originalPath); err == nil {
return errors.Wrap(err, "localfs: can't restore - file already exists at original path")
return errors.New("localfs: can't restore - file already exists at original path")
}

rp := fs.wrapRecycleBin(ctx, restoreKey)
Expand Down