Skip to content
Draft
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
36 changes: 36 additions & 0 deletions dav/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,42 @@ func (d *DavBlobstore) Sign(dest string, action string, expiration time.Duration
}
}

func (d *DavBlobstore) SignInternal(dest string, action string, expiration time.Duration) (string, error) {
slog.Info("signing internal url for webdav", "dest", dest, "action", action, "expiration", expiration)
if err := validateBlobID(dest); err != nil {
return "", err
}
action = strings.ToUpper(action)
switch action {
case "GET", "PUT":
signedURL, err := d.storageClient.SignInternal(dest, action, expiration)
if err != nil {
return "", fmt.Errorf("failed to sign internal URL: %w", err)
}
return signedURL, nil
default:
return "", fmt.Errorf("action not implemented: %s", action)
}
}

func (d *DavBlobstore) SignPublic(dest string, action string, expiration time.Duration) (string, error) {
slog.Info("signing public url for webdav", "dest", dest, "action", action, "expiration", expiration)
if err := validateBlobID(dest); err != nil {
return "", err
}
action = strings.ToUpper(action)
switch action {
case "GET", "PUT":
signedURL, err := d.storageClient.SignPublic(dest, action, expiration)
if err != nil {
return "", fmt.Errorf("failed to sign public URL: %w", err)
}
return signedURL, nil
default:
return "", fmt.Errorf("action not implemented: %s", action)
}
}

func (d *DavBlobstore) DeleteRecursive(prefix string) error {
slog.Info("deleting blobs recursively from webdav", "prefix", prefix)
return d.storageClient.DeleteRecursive(prefix)
Expand Down
136 changes: 136 additions & 0 deletions dav/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,142 @@ var _ = Describe("Client", func() {
})
})

Context("SignInternal", func() {
var expiry = 100 * time.Second

It("forwards args to the storage client and returns the signed URL", func() {
fakeStorageClient := &clientfakes.FakeStorageClient{}
fakeStorageClient.SignInternalReturns("https://internal-url", nil)

davBlobstore := client.NewWithStorageClient(fakeStorageClient)
url, err := davBlobstore.SignInternal("blob/path", "get", expiry)

Expect(err).NotTo(HaveOccurred())
Expect(url).To(Equal("https://internal-url"))

Expect(fakeStorageClient.SignInternalCallCount()).To(Equal(1))
object, action, expiration := fakeStorageClient.SignInternalArgsForCall(0)
Expect(object).To(Equal("blob/path"))
Expect(action).To(Equal("GET"))
Expect(expiration).To(Equal(expiry))
})

It("uppercases the action before forwarding", func() {
fakeStorageClient := &clientfakes.FakeStorageClient{}
fakeStorageClient.SignInternalReturns("https://internal-url", nil)

davBlobstore := client.NewWithStorageClient(fakeStorageClient)
_, err := davBlobstore.SignInternal("blob/path", "put", expiry)
Expect(err).NotTo(HaveOccurred())

_, action, _ := fakeStorageClient.SignInternalArgsForCall(0)
Expect(action).To(Equal("PUT"))
})

It("rejects an invalid blob ID without calling the storage client", func() {
fakeStorageClient := &clientfakes.FakeStorageClient{}

davBlobstore := client.NewWithStorageClient(fakeStorageClient)
url, err := davBlobstore.SignInternal("", "get", expiry)

Expect(err).To(HaveOccurred())
Expect(url).To(Equal(""))
Expect(fakeStorageClient.SignInternalCallCount()).To(Equal(0))
})

It("rejects unknown actions without calling the storage client", func() {
fakeStorageClient := &clientfakes.FakeStorageClient{}

davBlobstore := client.NewWithStorageClient(fakeStorageClient)
url, err := davBlobstore.SignInternal("blob/path", "delete", expiry)

Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("action not implemented"))
Expect(url).To(Equal(""))
Expect(fakeStorageClient.SignInternalCallCount()).To(Equal(0))
})

It("propagates errors from the storage client", func() {
fakeStorageClient := &clientfakes.FakeStorageClient{}
fakeStorageClient.SignInternalReturns("", fmt.Errorf("internal-boom"))

davBlobstore := client.NewWithStorageClient(fakeStorageClient)
url, err := davBlobstore.SignInternal("blob/path", "get", expiry)

Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("internal-boom"))
Expect(url).To(Equal(""))
})
})

Context("SignPublic", func() {
var expiry = 100 * time.Second

It("forwards args to the storage client and returns the signed URL", func() {
fakeStorageClient := &clientfakes.FakeStorageClient{}
fakeStorageClient.SignPublicReturns("https://public-url", nil)

davBlobstore := client.NewWithStorageClient(fakeStorageClient)
url, err := davBlobstore.SignPublic("blob/path", "get", expiry)

Expect(err).NotTo(HaveOccurred())
Expect(url).To(Equal("https://public-url"))

Expect(fakeStorageClient.SignPublicCallCount()).To(Equal(1))
object, action, expiration := fakeStorageClient.SignPublicArgsForCall(0)
Expect(object).To(Equal("blob/path"))
Expect(action).To(Equal("GET"))
Expect(expiration).To(Equal(expiry))
})

It("uppercases the action before forwarding", func() {
fakeStorageClient := &clientfakes.FakeStorageClient{}
fakeStorageClient.SignPublicReturns("https://public-url", nil)

davBlobstore := client.NewWithStorageClient(fakeStorageClient)
_, err := davBlobstore.SignPublic("blob/path", "put", expiry)
Expect(err).NotTo(HaveOccurred())

_, action, _ := fakeStorageClient.SignPublicArgsForCall(0)
Expect(action).To(Equal("PUT"))
})

It("rejects an invalid blob ID without calling the storage client", func() {
fakeStorageClient := &clientfakes.FakeStorageClient{}

davBlobstore := client.NewWithStorageClient(fakeStorageClient)
url, err := davBlobstore.SignPublic("", "get", expiry)

Expect(err).To(HaveOccurred())
Expect(url).To(Equal(""))
Expect(fakeStorageClient.SignPublicCallCount()).To(Equal(0))
})

It("rejects unknown actions without calling the storage client", func() {
fakeStorageClient := &clientfakes.FakeStorageClient{}

davBlobstore := client.NewWithStorageClient(fakeStorageClient)
url, err := davBlobstore.SignPublic("blob/path", "delete", expiry)

Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("action not implemented"))
Expect(url).To(Equal(""))
Expect(fakeStorageClient.SignPublicCallCount()).To(Equal(0))
})

It("propagates errors from the storage client", func() {
fakeStorageClient := &clientfakes.FakeStorageClient{}
fakeStorageClient.SignPublicReturns("", fmt.Errorf("public-boom"))

davBlobstore := client.NewWithStorageClient(fakeStorageClient)
url, err := davBlobstore.SignPublic("blob/path", "get", expiry)

Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("public-boom"))
Expect(url).To(Equal(""))
})
})

Context("Copy", func() {
It("forwards source and destination to the storage client", func() {
fakeStorageClient := &clientfakes.FakeStorageClient{}
Expand Down
162 changes: 162 additions & 0 deletions dav/client/clientfakes/fake_storage_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading