Merge pull request #9771 from owncloud/collaboration_connector_refactor

Collaboration connector refactor
This commit is contained in:
Juan Pablo Villafañez
2024-08-13 11:37:56 +02:00
committed by GitHub
16 changed files with 744 additions and 797 deletions

View File

@@ -65,11 +65,11 @@ $(HUGO): $(BINGO_DIR)/hugo.mod
@echo "(re)installing $(GOBIN)/hugo-v0.123.7"
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=hugo.mod -o=$(GOBIN)/hugo-v0.123.7 "github.com/gohugoio/hugo"
MOCKERY := $(GOBIN)/mockery-v2.40.2
MOCKERY := $(GOBIN)/mockery-v2.43.2
$(MOCKERY): $(BINGO_DIR)/mockery.mod
@# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies.
@echo "(re)installing $(GOBIN)/mockery-v2.40.2"
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=mockery.mod -o=$(GOBIN)/mockery-v2.40.2 "github.com/vektra/mockery/v2"
@echo "(re)installing $(GOBIN)/mockery-v2.43.2"
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=mockery.mod -o=$(GOBIN)/mockery-v2.43.2 "github.com/vektra/mockery/v2"
MUTAGEN := $(GOBIN)/mutagen-v0.14.0
$(MUTAGEN): $(BINGO_DIR)/mutagen.mod

View File

@@ -1,5 +1,7 @@
module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT
go 1.21.6
go 1.22
require github.com/vektra/mockery/v2 v2.40.2
toolchain go1.22.1
require github.com/vektra/mockery/v2 v2.43.2

View File

@@ -192,6 +192,8 @@ github.com/vektra/mockery/v2 v2.40.1 h1:8D01rBqloDLDHKZGXkyUD9Yj5Z+oDXBqDZ+tRXYM
github.com/vektra/mockery/v2 v2.40.1/go.mod h1:dPzGtjT0/Uu4hqpF6QNHwz+GLago7lq1bxdj9wHbGKo=
github.com/vektra/mockery/v2 v2.40.2 h1:JKuQ74IXibMCGKG6F0yvH/s2sNs1CHy/nGBP0We5DJ8=
github.com/vektra/mockery/v2 v2.40.2/go.mod h1:KYBZF/7sqOa86BaOZPYsoCZWEWLS90a5oBLg2pVudxY=
github.com/vektra/mockery/v2 v2.43.2 h1:OdivAsQL/uoQ55UnTt25tliRI8kaj5j6caHk9xaAUD0=
github.com/vektra/mockery/v2 v2.43.2/go.mod h1:XNTE9RIu3deGAGQRVjP1VZxGpQNm0YedZx4oDs3prr8=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=

View File

@@ -24,7 +24,7 @@ GOVULNCHECK="${GOBIN}/govulncheck-v1.0.1"
HUGO="${GOBIN}/hugo-v0.123.7"
MOCKERY="${GOBIN}/mockery-v2.40.2"
MOCKERY="${GOBIN}/mockery-v2.43.2"
MUTAGEN="${GOBIN}/mutagen-v0.14.0"

View File

@@ -0,0 +1,5 @@
Enhancement: Refactor the connector in the collaboration service
This will simplify and homogenize the code around the connector
https://github.com/owncloud/ocis/pull/9771

View File

@@ -4,6 +4,9 @@ package mocks
import (
context "context"
connector "github.com/owncloud/ocis/v2/services/collaboration/pkg/connector"
io "io"
mock "github.com/stretchr/testify/mock"
@@ -70,22 +73,24 @@ func (_c *ContentConnectorService_GetFile_Call) RunAndReturn(run func(context.Co
}
// PutFile provides a mock function with given fields: ctx, stream, streamLength, lockID
func (_m *ContentConnectorService) PutFile(ctx context.Context, stream io.Reader, streamLength int64, lockID string) (string, error) {
func (_m *ContentConnectorService) PutFile(ctx context.Context, stream io.Reader, streamLength int64, lockID string) (*connector.ConnectorResponse, error) {
ret := _m.Called(ctx, stream, streamLength, lockID)
if len(ret) == 0 {
panic("no return value specified for PutFile")
}
var r0 string
var r0 *connector.ConnectorResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, io.Reader, int64, string) (string, error)); ok {
if rf, ok := ret.Get(0).(func(context.Context, io.Reader, int64, string) (*connector.ConnectorResponse, error)); ok {
return rf(ctx, stream, streamLength, lockID)
}
if rf, ok := ret.Get(0).(func(context.Context, io.Reader, int64, string) string); ok {
if rf, ok := ret.Get(0).(func(context.Context, io.Reader, int64, string) *connector.ConnectorResponse); ok {
r0 = rf(ctx, stream, streamLength, lockID)
} else {
r0 = ret.Get(0).(string)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*connector.ConnectorResponse)
}
}
if rf, ok := ret.Get(1).(func(context.Context, io.Reader, int64, string) error); ok {
@@ -118,12 +123,12 @@ func (_c *ContentConnectorService_PutFile_Call) Run(run func(ctx context.Context
return _c
}
func (_c *ContentConnectorService_PutFile_Call) Return(_a0 string, _a1 error) *ContentConnectorService_PutFile_Call {
func (_c *ContentConnectorService_PutFile_Call) Return(_a0 *connector.ConnectorResponse, _a1 error) *ContentConnectorService_PutFile_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *ContentConnectorService_PutFile_Call) RunAndReturn(run func(context.Context, io.Reader, int64, string) (string, error)) *ContentConnectorService_PutFile_Call {
func (_c *ContentConnectorService_PutFile_Call) RunAndReturn(run func(context.Context, io.Reader, int64, string) (*connector.ConnectorResponse, error)) *ContentConnectorService_PutFile_Call {
_c.Call.Return(run)
return _c
}

View File

@@ -7,8 +7,6 @@ import (
connector "github.com/owncloud/ocis/v2/services/collaboration/pkg/connector"
fileinfo "github.com/owncloud/ocis/v2/services/collaboration/pkg/connector/fileinfo"
io "io"
mock "github.com/stretchr/testify/mock"
@@ -28,23 +26,23 @@ func (_m *FileConnectorService) EXPECT() *FileConnectorService_Expecter {
}
// CheckFileInfo provides a mock function with given fields: ctx
func (_m *FileConnectorService) CheckFileInfo(ctx context.Context) (fileinfo.FileInfo, error) {
func (_m *FileConnectorService) CheckFileInfo(ctx context.Context) (*connector.ConnectorResponse, error) {
ret := _m.Called(ctx)
if len(ret) == 0 {
panic("no return value specified for CheckFileInfo")
}
var r0 fileinfo.FileInfo
var r0 *connector.ConnectorResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context) (fileinfo.FileInfo, error)); ok {
if rf, ok := ret.Get(0).(func(context.Context) (*connector.ConnectorResponse, error)); ok {
return rf(ctx)
}
if rf, ok := ret.Get(0).(func(context.Context) fileinfo.FileInfo); ok {
if rf, ok := ret.Get(0).(func(context.Context) *connector.ConnectorResponse); ok {
r0 = rf(ctx)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(fileinfo.FileInfo)
r0 = ret.Get(0).(*connector.ConnectorResponse)
}
}
@@ -75,33 +73,35 @@ func (_c *FileConnectorService_CheckFileInfo_Call) Run(run func(ctx context.Cont
return _c
}
func (_c *FileConnectorService_CheckFileInfo_Call) Return(_a0 fileinfo.FileInfo, _a1 error) *FileConnectorService_CheckFileInfo_Call {
func (_c *FileConnectorService_CheckFileInfo_Call) Return(_a0 *connector.ConnectorResponse, _a1 error) *FileConnectorService_CheckFileInfo_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *FileConnectorService_CheckFileInfo_Call) RunAndReturn(run func(context.Context) (fileinfo.FileInfo, error)) *FileConnectorService_CheckFileInfo_Call {
func (_c *FileConnectorService_CheckFileInfo_Call) RunAndReturn(run func(context.Context) (*connector.ConnectorResponse, error)) *FileConnectorService_CheckFileInfo_Call {
_c.Call.Return(run)
return _c
}
// DeleteFile provides a mock function with given fields: ctx, lockID
func (_m *FileConnectorService) DeleteFile(ctx context.Context, lockID string) (string, error) {
func (_m *FileConnectorService) DeleteFile(ctx context.Context, lockID string) (*connector.ConnectorResponse, error) {
ret := _m.Called(ctx, lockID)
if len(ret) == 0 {
panic("no return value specified for DeleteFile")
}
var r0 string
var r0 *connector.ConnectorResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, string) (string, error)); ok {
if rf, ok := ret.Get(0).(func(context.Context, string) (*connector.ConnectorResponse, error)); ok {
return rf(ctx, lockID)
}
if rf, ok := ret.Get(0).(func(context.Context, string) string); ok {
if rf, ok := ret.Get(0).(func(context.Context, string) *connector.ConnectorResponse); ok {
r0 = rf(ctx, lockID)
} else {
r0 = ret.Get(0).(string)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*connector.ConnectorResponse)
}
}
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
@@ -132,33 +132,35 @@ func (_c *FileConnectorService_DeleteFile_Call) Run(run func(ctx context.Context
return _c
}
func (_c *FileConnectorService_DeleteFile_Call) Return(_a0 string, _a1 error) *FileConnectorService_DeleteFile_Call {
func (_c *FileConnectorService_DeleteFile_Call) Return(_a0 *connector.ConnectorResponse, _a1 error) *FileConnectorService_DeleteFile_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *FileConnectorService_DeleteFile_Call) RunAndReturn(run func(context.Context, string) (string, error)) *FileConnectorService_DeleteFile_Call {
func (_c *FileConnectorService_DeleteFile_Call) RunAndReturn(run func(context.Context, string) (*connector.ConnectorResponse, error)) *FileConnectorService_DeleteFile_Call {
_c.Call.Return(run)
return _c
}
// GetLock provides a mock function with given fields: ctx
func (_m *FileConnectorService) GetLock(ctx context.Context) (string, error) {
func (_m *FileConnectorService) GetLock(ctx context.Context) (*connector.ConnectorResponse, error) {
ret := _m.Called(ctx)
if len(ret) == 0 {
panic("no return value specified for GetLock")
}
var r0 string
var r0 *connector.ConnectorResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context) (string, error)); ok {
if rf, ok := ret.Get(0).(func(context.Context) (*connector.ConnectorResponse, error)); ok {
return rf(ctx)
}
if rf, ok := ret.Get(0).(func(context.Context) string); ok {
if rf, ok := ret.Get(0).(func(context.Context) *connector.ConnectorResponse); ok {
r0 = rf(ctx)
} else {
r0 = ret.Get(0).(string)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*connector.ConnectorResponse)
}
}
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
@@ -188,33 +190,35 @@ func (_c *FileConnectorService_GetLock_Call) Run(run func(ctx context.Context))
return _c
}
func (_c *FileConnectorService_GetLock_Call) Return(_a0 string, _a1 error) *FileConnectorService_GetLock_Call {
func (_c *FileConnectorService_GetLock_Call) Return(_a0 *connector.ConnectorResponse, _a1 error) *FileConnectorService_GetLock_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *FileConnectorService_GetLock_Call) RunAndReturn(run func(context.Context) (string, error)) *FileConnectorService_GetLock_Call {
func (_c *FileConnectorService_GetLock_Call) RunAndReturn(run func(context.Context) (*connector.ConnectorResponse, error)) *FileConnectorService_GetLock_Call {
_c.Call.Return(run)
return _c
}
// Lock provides a mock function with given fields: ctx, lockID, oldLockID
func (_m *FileConnectorService) Lock(ctx context.Context, lockID string, oldLockID string) (string, error) {
func (_m *FileConnectorService) Lock(ctx context.Context, lockID string, oldLockID string) (*connector.ConnectorResponse, error) {
ret := _m.Called(ctx, lockID, oldLockID)
if len(ret) == 0 {
panic("no return value specified for Lock")
}
var r0 string
var r0 *connector.ConnectorResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, string, string) (string, error)); ok {
if rf, ok := ret.Get(0).(func(context.Context, string, string) (*connector.ConnectorResponse, error)); ok {
return rf(ctx, lockID, oldLockID)
}
if rf, ok := ret.Get(0).(func(context.Context, string, string) string); ok {
if rf, ok := ret.Get(0).(func(context.Context, string, string) *connector.ConnectorResponse); ok {
r0 = rf(ctx, lockID, oldLockID)
} else {
r0 = ret.Get(0).(string)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*connector.ConnectorResponse)
}
}
if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
@@ -246,53 +250,44 @@ func (_c *FileConnectorService_Lock_Call) Run(run func(ctx context.Context, lock
return _c
}
func (_c *FileConnectorService_Lock_Call) Return(_a0 string, _a1 error) *FileConnectorService_Lock_Call {
func (_c *FileConnectorService_Lock_Call) Return(_a0 *connector.ConnectorResponse, _a1 error) *FileConnectorService_Lock_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *FileConnectorService_Lock_Call) RunAndReturn(run func(context.Context, string, string) (string, error)) *FileConnectorService_Lock_Call {
func (_c *FileConnectorService_Lock_Call) RunAndReturn(run func(context.Context, string, string) (*connector.ConnectorResponse, error)) *FileConnectorService_Lock_Call {
_c.Call.Return(run)
return _c
}
// PutRelativeFileRelative provides a mock function with given fields: ctx, ccs, stream, streamLength, target
func (_m *FileConnectorService) PutRelativeFileRelative(ctx context.Context, ccs connector.ContentConnectorService, stream io.Reader, streamLength int64, target string) (*connector.PutRelativeResponse, *connector.PutRelativeHeaders, error) {
func (_m *FileConnectorService) PutRelativeFileRelative(ctx context.Context, ccs connector.ContentConnectorService, stream io.Reader, streamLength int64, target string) (*connector.ConnectorResponse, error) {
ret := _m.Called(ctx, ccs, stream, streamLength, target)
if len(ret) == 0 {
panic("no return value specified for PutRelativeFileRelative")
}
var r0 *connector.PutRelativeResponse
var r1 *connector.PutRelativeHeaders
var r2 error
if rf, ok := ret.Get(0).(func(context.Context, connector.ContentConnectorService, io.Reader, int64, string) (*connector.PutRelativeResponse, *connector.PutRelativeHeaders, error)); ok {
var r0 *connector.ConnectorResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, connector.ContentConnectorService, io.Reader, int64, string) (*connector.ConnectorResponse, error)); ok {
return rf(ctx, ccs, stream, streamLength, target)
}
if rf, ok := ret.Get(0).(func(context.Context, connector.ContentConnectorService, io.Reader, int64, string) *connector.PutRelativeResponse); ok {
if rf, ok := ret.Get(0).(func(context.Context, connector.ContentConnectorService, io.Reader, int64, string) *connector.ConnectorResponse); ok {
r0 = rf(ctx, ccs, stream, streamLength, target)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*connector.PutRelativeResponse)
r0 = ret.Get(0).(*connector.ConnectorResponse)
}
}
if rf, ok := ret.Get(1).(func(context.Context, connector.ContentConnectorService, io.Reader, int64, string) *connector.PutRelativeHeaders); ok {
if rf, ok := ret.Get(1).(func(context.Context, connector.ContentConnectorService, io.Reader, int64, string) error); ok {
r1 = rf(ctx, ccs, stream, streamLength, target)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*connector.PutRelativeHeaders)
}
r1 = ret.Error(1)
}
if rf, ok := ret.Get(2).(func(context.Context, connector.ContentConnectorService, io.Reader, int64, string) error); ok {
r2 = rf(ctx, ccs, stream, streamLength, target)
} else {
r2 = ret.Error(2)
}
return r0, r1, r2
return r0, r1
}
// FileConnectorService_PutRelativeFileRelative_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PutRelativeFileRelative'
@@ -317,34 +312,34 @@ func (_c *FileConnectorService_PutRelativeFileRelative_Call) Run(run func(ctx co
return _c
}
func (_c *FileConnectorService_PutRelativeFileRelative_Call) Return(_a0 *connector.PutRelativeResponse, _a1 *connector.PutRelativeHeaders, _a2 error) *FileConnectorService_PutRelativeFileRelative_Call {
_c.Call.Return(_a0, _a1, _a2)
func (_c *FileConnectorService_PutRelativeFileRelative_Call) Return(_a0 *connector.ConnectorResponse, _a1 error) *FileConnectorService_PutRelativeFileRelative_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *FileConnectorService_PutRelativeFileRelative_Call) RunAndReturn(run func(context.Context, connector.ContentConnectorService, io.Reader, int64, string) (*connector.PutRelativeResponse, *connector.PutRelativeHeaders, error)) *FileConnectorService_PutRelativeFileRelative_Call {
func (_c *FileConnectorService_PutRelativeFileRelative_Call) RunAndReturn(run func(context.Context, connector.ContentConnectorService, io.Reader, int64, string) (*connector.ConnectorResponse, error)) *FileConnectorService_PutRelativeFileRelative_Call {
_c.Call.Return(run)
return _c
}
// PutRelativeFileSuggested provides a mock function with given fields: ctx, ccs, stream, streamLength, target
func (_m *FileConnectorService) PutRelativeFileSuggested(ctx context.Context, ccs connector.ContentConnectorService, stream io.Reader, streamLength int64, target string) (*connector.PutRelativeResponse, error) {
func (_m *FileConnectorService) PutRelativeFileSuggested(ctx context.Context, ccs connector.ContentConnectorService, stream io.Reader, streamLength int64, target string) (*connector.ConnectorResponse, error) {
ret := _m.Called(ctx, ccs, stream, streamLength, target)
if len(ret) == 0 {
panic("no return value specified for PutRelativeFileSuggested")
}
var r0 *connector.PutRelativeResponse
var r0 *connector.ConnectorResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, connector.ContentConnectorService, io.Reader, int64, string) (*connector.PutRelativeResponse, error)); ok {
if rf, ok := ret.Get(0).(func(context.Context, connector.ContentConnectorService, io.Reader, int64, string) (*connector.ConnectorResponse, error)); ok {
return rf(ctx, ccs, stream, streamLength, target)
}
if rf, ok := ret.Get(0).(func(context.Context, connector.ContentConnectorService, io.Reader, int64, string) *connector.PutRelativeResponse); ok {
if rf, ok := ret.Get(0).(func(context.Context, connector.ContentConnectorService, io.Reader, int64, string) *connector.ConnectorResponse); ok {
r0 = rf(ctx, ccs, stream, streamLength, target)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*connector.PutRelativeResponse)
r0 = ret.Get(0).(*connector.ConnectorResponse)
}
}
@@ -379,33 +374,35 @@ func (_c *FileConnectorService_PutRelativeFileSuggested_Call) Run(run func(ctx c
return _c
}
func (_c *FileConnectorService_PutRelativeFileSuggested_Call) Return(_a0 *connector.PutRelativeResponse, _a1 error) *FileConnectorService_PutRelativeFileSuggested_Call {
func (_c *FileConnectorService_PutRelativeFileSuggested_Call) Return(_a0 *connector.ConnectorResponse, _a1 error) *FileConnectorService_PutRelativeFileSuggested_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *FileConnectorService_PutRelativeFileSuggested_Call) RunAndReturn(run func(context.Context, connector.ContentConnectorService, io.Reader, int64, string) (*connector.PutRelativeResponse, error)) *FileConnectorService_PutRelativeFileSuggested_Call {
func (_c *FileConnectorService_PutRelativeFileSuggested_Call) RunAndReturn(run func(context.Context, connector.ContentConnectorService, io.Reader, int64, string) (*connector.ConnectorResponse, error)) *FileConnectorService_PutRelativeFileSuggested_Call {
_c.Call.Return(run)
return _c
}
// RefreshLock provides a mock function with given fields: ctx, lockID
func (_m *FileConnectorService) RefreshLock(ctx context.Context, lockID string) (string, error) {
func (_m *FileConnectorService) RefreshLock(ctx context.Context, lockID string) (*connector.ConnectorResponse, error) {
ret := _m.Called(ctx, lockID)
if len(ret) == 0 {
panic("no return value specified for RefreshLock")
}
var r0 string
var r0 *connector.ConnectorResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, string) (string, error)); ok {
if rf, ok := ret.Get(0).(func(context.Context, string) (*connector.ConnectorResponse, error)); ok {
return rf(ctx, lockID)
}
if rf, ok := ret.Get(0).(func(context.Context, string) string); ok {
if rf, ok := ret.Get(0).(func(context.Context, string) *connector.ConnectorResponse); ok {
r0 = rf(ctx, lockID)
} else {
r0 = ret.Get(0).(string)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*connector.ConnectorResponse)
}
}
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
@@ -436,51 +433,44 @@ func (_c *FileConnectorService_RefreshLock_Call) Run(run func(ctx context.Contex
return _c
}
func (_c *FileConnectorService_RefreshLock_Call) Return(_a0 string, _a1 error) *FileConnectorService_RefreshLock_Call {
func (_c *FileConnectorService_RefreshLock_Call) Return(_a0 *connector.ConnectorResponse, _a1 error) *FileConnectorService_RefreshLock_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *FileConnectorService_RefreshLock_Call) RunAndReturn(run func(context.Context, string) (string, error)) *FileConnectorService_RefreshLock_Call {
func (_c *FileConnectorService_RefreshLock_Call) RunAndReturn(run func(context.Context, string) (*connector.ConnectorResponse, error)) *FileConnectorService_RefreshLock_Call {
_c.Call.Return(run)
return _c
}
// RenameFile provides a mock function with given fields: ctx, lockID, target
func (_m *FileConnectorService) RenameFile(ctx context.Context, lockID string, target string) (*connector.RenameResponse, string, error) {
func (_m *FileConnectorService) RenameFile(ctx context.Context, lockID string, target string) (*connector.ConnectorResponse, error) {
ret := _m.Called(ctx, lockID, target)
if len(ret) == 0 {
panic("no return value specified for RenameFile")
}
var r0 *connector.RenameResponse
var r1 string
var r2 error
if rf, ok := ret.Get(0).(func(context.Context, string, string) (*connector.RenameResponse, string, error)); ok {
var r0 *connector.ConnectorResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, string, string) (*connector.ConnectorResponse, error)); ok {
return rf(ctx, lockID, target)
}
if rf, ok := ret.Get(0).(func(context.Context, string, string) *connector.RenameResponse); ok {
if rf, ok := ret.Get(0).(func(context.Context, string, string) *connector.ConnectorResponse); ok {
r0 = rf(ctx, lockID, target)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*connector.RenameResponse)
r0 = ret.Get(0).(*connector.ConnectorResponse)
}
}
if rf, ok := ret.Get(1).(func(context.Context, string, string) string); ok {
if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
r1 = rf(ctx, lockID, target)
} else {
r1 = ret.Get(1).(string)
r1 = ret.Error(1)
}
if rf, ok := ret.Get(2).(func(context.Context, string, string) error); ok {
r2 = rf(ctx, lockID, target)
} else {
r2 = ret.Error(2)
}
return r0, r1, r2
return r0, r1
}
// FileConnectorService_RenameFile_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RenameFile'
@@ -503,33 +493,35 @@ func (_c *FileConnectorService_RenameFile_Call) Run(run func(ctx context.Context
return _c
}
func (_c *FileConnectorService_RenameFile_Call) Return(_a0 *connector.RenameResponse, _a1 string, _a2 error) *FileConnectorService_RenameFile_Call {
_c.Call.Return(_a0, _a1, _a2)
func (_c *FileConnectorService_RenameFile_Call) Return(_a0 *connector.ConnectorResponse, _a1 error) *FileConnectorService_RenameFile_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *FileConnectorService_RenameFile_Call) RunAndReturn(run func(context.Context, string, string) (*connector.RenameResponse, string, error)) *FileConnectorService_RenameFile_Call {
func (_c *FileConnectorService_RenameFile_Call) RunAndReturn(run func(context.Context, string, string) (*connector.ConnectorResponse, error)) *FileConnectorService_RenameFile_Call {
_c.Call.Return(run)
return _c
}
// UnLock provides a mock function with given fields: ctx, lockID
func (_m *FileConnectorService) UnLock(ctx context.Context, lockID string) (string, error) {
func (_m *FileConnectorService) UnLock(ctx context.Context, lockID string) (*connector.ConnectorResponse, error) {
ret := _m.Called(ctx, lockID)
if len(ret) == 0 {
panic("no return value specified for UnLock")
}
var r0 string
var r0 *connector.ConnectorResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, string) (string, error)); ok {
if rf, ok := ret.Get(0).(func(context.Context, string) (*connector.ConnectorResponse, error)); ok {
return rf(ctx, lockID)
}
if rf, ok := ret.Get(0).(func(context.Context, string) string); ok {
if rf, ok := ret.Get(0).(func(context.Context, string) *connector.ConnectorResponse); ok {
r0 = rf(ctx, lockID)
} else {
r0 = ret.Get(0).(string)
if ret.Get(0) != nil {
r0 = ret.Get(0).(*connector.ConnectorResponse)
}
}
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
@@ -560,12 +552,12 @@ func (_c *FileConnectorService_UnLock_Call) Run(run func(ctx context.Context, lo
return _c
}
func (_c *FileConnectorService_UnLock_Call) Return(_a0 string, _a1 error) *FileConnectorService_UnLock_Call {
func (_c *FileConnectorService_UnLock_Call) Return(_a0 *connector.ConnectorResponse, _a1 error) *FileConnectorService_UnLock_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *FileConnectorService_UnLock_Call) RunAndReturn(run func(context.Context, string) (string, error)) *FileConnectorService_UnLock_Call {
func (_c *FileConnectorService_UnLock_Call) RunAndReturn(run func(context.Context, string) (*connector.ConnectorResponse, error)) *FileConnectorService_UnLock_Call {
_c.Call.Return(run)
return _c
}

View File

@@ -1,5 +1,79 @@
package connector
// ConnectorResponse represent a response from the FileConnectorService.
// The ConnectorResponse is oriented to HTTP, so it has the Status, Headers
// and Body that the actual HTTP response should have. This includes HTTP
// errors with status 4xx and 5xx, which will also represent some error
// conditions for the FileConnectorService.
// Note that the Body is expected to be JSON-encoded outside before sending.
type ConnectorResponse struct {
Status int
Headers map[string]string
Body interface{}
}
// NewResponse creates a new ConnectorResponse with just the specified status.
// Headers and Body will be nil
func NewResponse(status int) *ConnectorResponse {
return &ConnectorResponse{Status: status}
}
// NewResponse creates a new ConnectorResponse with the specified status
// and the "X-WOPI-Lock" header having the value in the lockID parameter.
//
// This is usually used for conflict responses where the current lock id needs
// to be returned, although the `GetLock` method also uses this method for a
// successful response (with the lock id included)
func NewResponseWithLock(status int, lockID string) *ConnectorResponse {
return &ConnectorResponse{
Status: status,
Headers: map[string]string{
HeaderWopiLock: lockID,
},
}
}
// NewResponseSuccessBody creates a new ConnectorResponse with a fixed 200
// (success) status and the specified body. The headers will be nil.
//
// This is used for the `CheckFileInfo` method in order to return the fileinfo
func NewResponseSuccessBody(body interface{}) *ConnectorResponse {
return &ConnectorResponse{
Status: 200,
Body: body,
}
}
// NewResponseSuccessBodyName creates a new ConnectorResponse with a fixed 200
// (success) status and a "map[string]interface{}" body. The body will contain
// a "Name" key with the supplied name as value.
//
// This is used for the `RenameFile` method in order to return the final name
// of the renamed file if the operation is successful
func NewResponseSuccessBodyName(name string) *ConnectorResponse {
return &ConnectorResponse{
Status: 200,
Body: map[string]interface{}{
"Name": name,
},
}
}
// NewResponseSuccessBodyNameUrl creates a new ConnectorResponse with a fixed
// 200 (success) status and a "map[string]interface{}" body. The body will
// contain "Name" and "Url" keys with their respective suplied values
//
// This is used in the `PutRelativeFile` methods (both suggested and relative).
func NewResponseSuccessBodyNameUrl(name, url string) *ConnectorResponse {
return &ConnectorResponse{
Status: 200,
Body: map[string]interface{}{
"Name": name,
"Url": url,
},
}
}
// ConnectorError defines an error in the connector. It contains an error code
// and a message.
// For convenience, the error code can be used as HTTP error code, although

View File

@@ -7,7 +7,7 @@ import (
. "github.com/onsi/gomega"
)
func TestGraph(t *testing.T) {
func TestConnector(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Connector Suite")
}

View File

@@ -34,7 +34,7 @@ type ContentConnectorService interface {
// locked beforehand, so the lockID needs to be provided.
// The current lockID will be returned ONLY if a conflict happens (the file is
// locked with a different lockID)
PutFile(ctx context.Context, stream io.Reader, streamLength int64, lockID string) (string, error)
PutFile(ctx context.Context, stream io.Reader, streamLength int64, lockID string) (*ConnectorResponse, error)
}
// ContentConnector implements the "File contents" endpoint.
@@ -199,10 +199,10 @@ func (c *ContentConnector) GetFile(ctx context.Context, writer io.Writer) error
// lock ID that should be used in the X-WOPI-Lock header. In other error
// cases or if the method is successful, an empty string will be returned
// (check for err != nil to know if something went wrong)
func (c *ContentConnector) PutFile(ctx context.Context, stream io.Reader, streamLength int64, lockID string) (string, error) {
func (c *ContentConnector) PutFile(ctx context.Context, stream io.Reader, streamLength int64, lockID string) (*ConnectorResponse, error) {
wopiContext, err := middleware.WopiContextFromCtx(ctx)
if err != nil {
return "", err
return nil, err
}
logger := zerolog.Ctx(ctx).With().
@@ -219,7 +219,7 @@ func (c *ContentConnector) PutFile(ctx context.Context, stream io.Reader, stream
})
if err != nil {
logger.Error().Err(err).Msg("PutFile: stat failed")
return "", err
return nil, err
}
if statRes.GetStatus().GetCode() != rpcv1beta1.Code_CODE_OK && statRes.GetStatus().GetCode() != rpcv1beta1.Code_CODE_NOT_FOUND {
@@ -227,7 +227,7 @@ func (c *ContentConnector) PutFile(ctx context.Context, stream io.Reader, stream
Str("StatusCode", statRes.GetStatus().GetCode().String()).
Str("StatusMsg", statRes.GetStatus().GetMessage()).
Msg("PutFile: stat failed with unexpected status")
return "", NewConnectorError(500, statRes.GetStatus().GetCode().String()+" "+statRes.GetStatus().GetMessage())
return NewResponse(500), nil
}
// If there is a lock and it mismatches, return 409
@@ -236,7 +236,7 @@ func (c *ContentConnector) PutFile(ctx context.Context, stream io.Reader, stream
Str("LockID", statRes.GetInfo().GetLock().GetLockId()).
Msg("PutFile: wrong lock")
// onlyoffice says it's required to send the current lockId, MS doesn't say anything
return statRes.GetInfo().GetLock().GetLockId(), NewConnectorError(409, "Wrong lock")
return NewResponseWithLock(409, statRes.GetInfo().GetLock().GetLockId()), nil
}
// only unlocked uploads can go through if the target file is empty,
@@ -246,7 +246,7 @@ func (c *ContentConnector) PutFile(ctx context.Context, stream io.Reader, stream
if lockID == "" && statRes.GetInfo().GetLock() == nil && statRes.GetInfo().GetSize() > 0 {
logger.Error().Msg("PutFile: file must be locked first")
// onlyoffice says to send an empty string if the file is unlocked, MS doesn't say anything
return "", NewConnectorError(409, "File must be locked first")
return NewResponseWithLock(409, ""), nil
}
// Prepare the data to initiate the upload
@@ -274,7 +274,7 @@ func (c *ContentConnector) PutFile(ctx context.Context, stream io.Reader, stream
resp, err := c.gwc.InitiateFileUpload(ctx, req)
if err != nil {
logger.Error().Err(err).Msg("UploadHelper: InitiateFileUpload failed")
return "", err
return nil, err
}
if resp.GetStatus().GetCode() != rpcv1beta1.Code_CODE_OK {
@@ -282,7 +282,7 @@ func (c *ContentConnector) PutFile(ctx context.Context, stream io.Reader, stream
Str("StatusCode", resp.GetStatus().GetCode().String()).
Str("StatusMsg", resp.GetStatus().GetMessage()).
Msg("UploadHelper: InitiateFileUpload failed with wrong status")
return "", NewConnectorError(500, resp.GetStatus().GetCode().String()+" "+resp.GetStatus().GetMessage())
return NewResponse(500), nil
}
// if the content length is greater than 0, we need to upload the content to the
@@ -307,7 +307,7 @@ func (c *ContentConnector) PutFile(ctx context.Context, stream io.Reader, stream
Str("Endpoint", uploadEndpoint).
Bool("HasUploadToken", hasUploadToken).
Msg("UploadHelper: Upload endpoint or token is missing")
return "", NewConnectorError(500, "upload endpoint or token is missing")
return NewResponse(500), nil
}
httpClient := http.Client{
@@ -327,7 +327,7 @@ func (c *ContentConnector) PutFile(ctx context.Context, stream io.Reader, stream
Str("Endpoint", uploadEndpoint).
Bool("HasUploadToken", hasUploadToken).
Msg("UploadHelper: Could not create the request to the endpoint")
return "", err
return nil, err
}
// "stream" is an *http.body and doesn't fill the httpReq.ContentLength automatically
// we need to fill the ContentLength ourselves, and must match the stream length in order
@@ -355,7 +355,7 @@ func (c *ContentConnector) PutFile(ctx context.Context, stream io.Reader, stream
Str("Endpoint", uploadEndpoint).
Bool("HasUploadToken", hasUploadToken).
Msg("UploadHelper: Put request to the upload endpoint failed")
return "", err
return nil, err
}
defer httpResp.Body.Close()
@@ -365,10 +365,10 @@ func (c *ContentConnector) PutFile(ctx context.Context, stream io.Reader, stream
Bool("HasUploadToken", hasUploadToken).
Int("HttpCode", httpResp.StatusCode).
Msg("UploadHelper: Put request to the upload endpoint failed with unexpected status")
return "", NewConnectorError(500, "PutFile: Uploading the file failed")
return NewResponse(500), nil
}
}
logger.Debug().Msg("PutFile: success")
return "", nil
return NewResponse(200), nil
}

View File

@@ -220,9 +220,9 @@ var _ = Describe("ContentConnector", func() {
It("No valid context", func() {
reader := strings.NewReader("Content to upload is here!")
ctx := context.Background()
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "notARandomLockId")
response, err := cc.PutFile(ctx, reader, reader.Size(), "notARandomLockId")
Expect(err).To(HaveOccurred())
Expect(newLockId).To(Equal(""))
Expect(response).To(BeNil())
})
It("Stat call failed", func() {
@@ -234,9 +234,9 @@ var _ = Describe("ContentConnector", func() {
Status: status.NewInternal(ctx, "Something failed"),
}, targetErr)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "notARandomLockId")
response, err := cc.PutFile(ctx, reader, reader.Size(), "notARandomLockId")
Expect(err).To(Equal(targetErr))
Expect(newLockId).To(Equal(""))
Expect(response).To(BeNil())
})
It("Stat call status not ok", func() {
@@ -247,11 +247,10 @@ var _ = Describe("ContentConnector", func() {
Status: status.NewInternal(ctx, "Something failed"),
}, nil)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "notARandomLockId")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
Expect(newLockId).To(Equal(""))
response, err := cc.PutFile(ctx, reader, reader.Size(), "notARandomLockId")
Expect(err).To(Succeed())
Expect(response.Status).To(Equal(500))
Expect(response.Headers).To(BeNil())
})
It("Mismatched lockId", func() {
@@ -268,11 +267,10 @@ var _ = Describe("ContentConnector", func() {
},
}, nil)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "notARandomLockId")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(409))
Expect(newLockId).To(Equal("goodAndValidLock"))
response, err := cc.PutFile(ctx, reader, reader.Size(), "notARandomLockId")
Expect(err).To(Succeed())
Expect(response.Status).To(Equal(409))
Expect(response.Headers[connector.HeaderWopiLock]).To(Equal("goodAndValidLock"))
})
It("Upload without lockId but on a non empty file", func() {
@@ -287,11 +285,10 @@ var _ = Describe("ContentConnector", func() {
},
}, nil)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(409))
Expect(newLockId).To(Equal(""))
response, err := cc.PutFile(ctx, reader, reader.Size(), "")
Expect(err).To(Succeed())
Expect(response.Status).To(Equal(409))
Expect(response.Headers[connector.HeaderWopiLock]).To(Equal(""))
})
It("Initiate upload fails", func() {
@@ -314,9 +311,9 @@ var _ = Describe("ContentConnector", func() {
Status: status.NewInternal(ctx, "Something failed"),
}, targetErr)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
response, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
Expect(err).To(HaveOccurred())
Expect(newLockId).To(Equal(""))
Expect(response).To(BeNil())
})
It("Initiate upload status not ok", func() {
@@ -338,11 +335,10 @@ var _ = Describe("ContentConnector", func() {
Status: status.NewInternal(ctx, "Something failed"),
}, nil)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
Expect(newLockId).To(Equal(""))
response, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
Expect(err).To(Succeed())
Expect(response.Status).To(Equal(500))
Expect(response.Headers).To(BeNil())
})
It("Empty upload successful", func() {
@@ -364,9 +360,10 @@ var _ = Describe("ContentConnector", func() {
Status: status.NewOK(ctx),
}, nil)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
response, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
Expect(err).To(Succeed())
Expect(newLockId).To(Equal(""))
Expect(response.Status).To(Equal(200))
Expect(response.Headers).To(BeNil())
})
It("Missing upload endpoint", func() {
@@ -388,11 +385,10 @@ var _ = Describe("ContentConnector", func() {
Status: status.NewOK(ctx),
}, nil)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
Expect(newLockId).To(Equal(""))
response, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
Expect(err).To(BeNil())
Expect(response.Status).To(Equal(500))
Expect(response.Headers).To(BeNil())
})
It("upload request failed", func() {
@@ -420,12 +416,11 @@ var _ = Describe("ContentConnector", func() {
},
}, nil)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
response, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
Expect(srvReqHeader.Get("X-Access-Token")).To(Equal(wopiCtx.AccessToken))
Expect(err).To(HaveOccurred())
conErr := err.(*connector.ConnectorError)
Expect(conErr.HttpCodeOut).To(Equal(500))
Expect(newLockId).To(Equal(""))
Expect(err).To(Succeed())
Expect(response.Status).To(Equal(500))
Expect(response.Headers).To(BeNil())
})
It("upload request success", func() {
@@ -453,10 +448,11 @@ var _ = Describe("ContentConnector", func() {
},
}, nil)
newLockId, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
response, err := cc.PutFile(ctx, reader, reader.Size(), "goodAndValidLock")
Expect(srvReqHeader.Get("X-Access-Token")).To(Equal(wopiCtx.AccessToken))
Expect(err).To(Succeed())
Expect(newLockId).To(Equal(""))
Expect(response.Status).To(Equal(200))
Expect(response.Headers).To(BeNil())
})
})
})

View File

@@ -7,7 +7,6 @@ import (
"encoding/base64"
"encoding/binary"
"encoding/hex"
"errors"
"io"
"net/url"
"path"
@@ -36,30 +35,6 @@ const (
lockDuration time.Duration = 30 * time.Minute
)
// PutRelativeHeaders contains the values for headers used in a
// "PutRelative" WOPI response
type PutRelativeHeaders struct {
ValidTarget string
LockID string
}
// PutRelativeResponse contains the values for the body used in a
// "PutRelative" WOPI response
type PutRelativeResponse struct {
Name string
Url string
// These are optional and not used for now
HostView string
HostEdit string
}
// RenameResponse contains the values for the body used in a
// "RenameFile" WOPI response
type RenameResponse struct {
Name string
}
// FileConnectorService is the interface to implement the "Files"
// endpoint. Basically lock operations on the file plus the CheckFileInfo.
// All operations need a context containing a WOPI context and, optionally,
@@ -67,23 +42,23 @@ type RenameResponse struct {
// Target file is within the WOPI context
type FileConnectorService interface {
// GetLock will return the lockID present in the target file.
GetLock(ctx context.Context) (string, error)
GetLock(ctx context.Context) (*ConnectorResponse, error)
// Lock will lock the target file with the provided lockID. If the oldLockID
// is provided (not empty), the method will perform an unlockAndRelock
// operation (unlock the file with the oldLockID and immediately relock
// the file with the new lockID).
// The current lockID will be returned if a conflict happens
Lock(ctx context.Context, lockID, oldLockID string) (string, error)
Lock(ctx context.Context, lockID, oldLockID string) (*ConnectorResponse, error)
// RefreshLock will extend the lock time 30 minutes. The current lockID
// needs to be provided.
// The current lockID will be returned if a conflict happens
RefreshLock(ctx context.Context, lockID string) (string, error)
RefreshLock(ctx context.Context, lockID string) (*ConnectorResponse, error)
// Unlock will unlock the target file. The current lockID needs to be
// provided.
// The current lockID will be returned if a conflict happens
UnLock(ctx context.Context, lockID string) (string, error)
UnLock(ctx context.Context, lockID string) (*ConnectorResponse, error)
// CheckFileInfo will return the file information of the target file
CheckFileInfo(ctx context.Context) (fileinfo.FileInfo, error)
CheckFileInfo(ctx context.Context) (*ConnectorResponse, error)
// PutRelativeFileSuggested will create a new file based on the contents of the
// current file. Target is the filename that will be used for this
// new file.
@@ -91,7 +66,7 @@ type FileConnectorService interface {
// Since we need to upload contents, it will be done through the provided
// The target must be UTF8-encoded.
// ContentConnectorService
PutRelativeFileSuggested(ctx context.Context, ccs ContentConnectorService, stream io.Reader, streamLength int64, target string) (*PutRelativeResponse, error)
PutRelativeFileSuggested(ctx context.Context, ccs ContentConnectorService, stream io.Reader, streamLength int64, target string) (*ConnectorResponse, error)
// PutRelativeFileRelative will create a new file based on the contents of the
// current file. Target is the filename that will be used for this
// new file.
@@ -101,17 +76,17 @@ type FileConnectorService interface {
// The target must be UTF8-encoded.
// Since we need to upload contents, it will be done through the provided
// ContentConnectorService
PutRelativeFileRelative(ctx context.Context, ccs ContentConnectorService, stream io.Reader, streamLength int64, target string) (*PutRelativeResponse, *PutRelativeHeaders, error)
PutRelativeFileRelative(ctx context.Context, ccs ContentConnectorService, stream io.Reader, streamLength int64, target string) (*ConnectorResponse, error)
// DeleteFile will delete the provided file in the context. Although
// not documented, a lockID can be used to try to delete a locked file
// assuming the lock matches.
// The current lockID will be returned if the file is locked.
DeleteFile(ctx context.Context, lockID string) (string, error)
DeleteFile(ctx context.Context, lockID string) (*ConnectorResponse, error)
// RenameFile will rename the provided file in the context to the requested
// filename. The filename must be UTF8-encoded.
// In case of conflict, this method will return the actual lockId in
// the file as second return value.
RenameFile(ctx context.Context, lockID, target string) (*RenameResponse, string, error)
RenameFile(ctx context.Context, lockID, target string) (*ConnectorResponse, error)
}
// FileConnector implements the "File" endpoint.
@@ -140,10 +115,10 @@ func NewFileConnector(gwc gatewayv1beta1.GatewayAPIClient, cfg *config.Config) *
// The lock ID applied to the file reference in the context will be returned
// (if any). An error will be returned if something goes wrong. The error
// could be a ConnectorError
func (f *FileConnector) GetLock(ctx context.Context) (string, error) {
func (f *FileConnector) GetLock(ctx context.Context) (*ConnectorResponse, error) {
wopiContext, err := middleware.WopiContextFromCtx(ctx)
if err != nil {
return "", err
return nil, err
}
logger := zerolog.Ctx(ctx)
@@ -155,7 +130,7 @@ func (f *FileConnector) GetLock(ctx context.Context) (string, error) {
resp, err := f.gwc.GetLock(ctx, req)
if err != nil {
logger.Error().Err(err).Msg("GetLock failed")
return "", err
return nil, err
}
if resp.GetStatus().GetCode() != rpcv1beta1.Code_CODE_OK {
@@ -164,7 +139,7 @@ func (f *FileConnector) GetLock(ctx context.Context) (string, error) {
Str("StatusMsg", resp.GetStatus().GetMessage()).
Msg("GetLock failed with unexpected status")
// TODO: Should we be more strict? There could be more causes for the failure
return "", NewConnectorError(404, resp.GetStatus().GetCode().String()+" "+resp.GetStatus().GetMessage())
return NewResponse(404), nil
}
lockID := ""
@@ -177,7 +152,7 @@ func (f *FileConnector) GetLock(ctx context.Context) (string, error) {
Str("LockID", lockID).
Msg("GetLock success")
return lockID, nil
return NewResponseWithLock(200, lockID), nil
}
// Lock returns a WOPI lock or performs an unlock and relock
@@ -198,10 +173,10 @@ func (f *FileConnector) GetLock(ctx context.Context) (string, error) {
// the method will return an empty lock id.
//
// For the "unlock and relock" operation, the behavior will be the same.
func (f *FileConnector) Lock(ctx context.Context, lockID, oldLockID string) (string, error) {
func (f *FileConnector) Lock(ctx context.Context, lockID, oldLockID string) (*ConnectorResponse, error) {
wopiContext, err := middleware.WopiContextFromCtx(ctx)
if err != nil {
return "", err
return nil, err
}
logger := zerolog.Ctx(ctx).With().
@@ -212,7 +187,7 @@ func (f *FileConnector) Lock(ctx context.Context, lockID, oldLockID string) (str
if lockID == "" {
logger.Error().Msg("Lock failed due to empty lockID")
return "", NewConnectorError(400, "Requested lockID is empty")
return NewResponse(400), nil
}
var setOrRefreshStatus *rpcv1beta1.Status
@@ -234,7 +209,7 @@ func (f *FileConnector) Lock(ctx context.Context, lockID, oldLockID string) (str
resp, err := f.gwc.SetLock(ctx, req)
if err != nil {
logger.Error().Err(err).Msg("SetLock failed")
return "", err
return nil, err
}
setOrRefreshStatus = resp.GetStatus()
} else {
@@ -257,7 +232,7 @@ func (f *FileConnector) Lock(ctx context.Context, lockID, oldLockID string) (str
resp, err := f.gwc.RefreshLock(ctx, req)
if err != nil {
logger.Error().Err(err).Msg("UnlockAndRefresh failed")
return "", err
return nil, err
}
setOrRefreshStatus = resp.GetStatus()
}
@@ -266,7 +241,7 @@ func (f *FileConnector) Lock(ctx context.Context, lockID, oldLockID string) (str
switch setOrRefreshStatus.GetCode() {
case rpcv1beta1.Code_CODE_OK:
logger.Debug().Msg("SetLock successful")
return "", nil
return NewResponse(200), nil
case rpcv1beta1.Code_CODE_FAILED_PRECONDITION, rpcv1beta1.Code_CODE_ABORTED:
// Code_CODE_FAILED_PRECONDITION -> Lock operation mismatched lock
@@ -280,7 +255,7 @@ func (f *FileConnector) Lock(ctx context.Context, lockID, oldLockID string) (str
resp, err := f.gwc.GetLock(ctx, req)
if err != nil {
logger.Error().Err(err).Msg("SetLock failed, fallback to GetLock failed too")
return "", err
return nil, err
}
if resp.GetStatus().GetCode() != rpcv1beta1.Code_CODE_OK {
@@ -296,7 +271,7 @@ func (f *FileConnector) Lock(ctx context.Context, lockID, oldLockID string) (str
logger.Warn().
Str("LockID", resp.GetLock().GetLockId()).
Msg("SetLock conflict")
return resp.GetLock().GetLockId(), NewConnectorError(409, "Lock conflict")
return NewResponseWithLock(409, resp.GetLock().GetLockId()), nil
}
// TODO: according to the spec we need to treat this as a RefreshLock
@@ -307,22 +282,22 @@ func (f *FileConnector) Lock(ctx context.Context, lockID, oldLockID string) (str
logger.Warn().
Str("LockID", resp.GetLock().GetLockId()).
Msg("SetLock lock refreshed instead")
return resp.GetLock().GetLockId(), nil
return NewResponse(200), nil // no need to send the lockID for a 200 code
}
logger.Error().Msg("SetLock failed and could not refresh")
return "", NewConnectorError(500, "Could not refresh the lock")
return NewResponse(500), nil
case rpcv1beta1.Code_CODE_NOT_FOUND:
logger.Error().Msg("SetLock failed, file not found")
return "", NewConnectorError(404, "File not found")
return NewResponse(404), nil
default:
logger.Error().
Str("StatusCode", setOrRefreshStatus.GetCode().String()).
Str("StatusMsg", setOrRefreshStatus.GetMessage()).
Msg("SetLock failed with unexpected status")
return "", NewConnectorError(500, setOrRefreshStatus.GetCode().String()+" "+setOrRefreshStatus.GetMessage())
return NewResponse(500), nil
}
}
@@ -339,10 +314,10 @@ func (f *FileConnector) Lock(ctx context.Context, lockID, oldLockID string) (str
// return an empty lock id.
// The conflict happens if the provided lockID doesn't match the one actually
// applied in the target file.
func (f *FileConnector) RefreshLock(ctx context.Context, lockID string) (string, error) {
func (f *FileConnector) RefreshLock(ctx context.Context, lockID string) (*ConnectorResponse, error) {
wopiContext, err := middleware.WopiContextFromCtx(ctx)
if err != nil {
return "", err
return nil, err
}
logger := zerolog.Ctx(ctx).With().
@@ -352,7 +327,7 @@ func (f *FileConnector) RefreshLock(ctx context.Context, lockID string) (string,
if lockID == "" {
logger.Error().Msg("RefreshLock failed due to empty lockID")
return "", NewConnectorError(400, "Requested lockID is empty")
return NewResponse(400), nil
}
req := &providerv1beta1.RefreshLockRequest{
@@ -370,20 +345,20 @@ func (f *FileConnector) RefreshLock(ctx context.Context, lockID string) (string,
resp, err := f.gwc.RefreshLock(ctx, req)
if err != nil {
logger.Error().Err(err).Msg("RefreshLock failed")
return "", err
return nil, err
}
switch resp.GetStatus().GetCode() {
case rpcv1beta1.Code_CODE_OK:
logger.Debug().Msg("RefreshLock successful")
return "", nil
return NewResponse(200), nil
case rpcv1beta1.Code_CODE_NOT_FOUND:
logger.Error().
Str("StatusCode", resp.GetStatus().GetCode().String()).
Str("StatusMsg", resp.GetStatus().GetMessage()).
Msg("RefreshLock failed, file reference not found")
return "", NewConnectorError(404, "File reference not found")
return NewResponse(404), nil
case rpcv1beta1.Code_CODE_ABORTED:
logger.Error().
@@ -400,7 +375,7 @@ func (f *FileConnector) RefreshLock(ctx context.Context, lockID string) (string,
resp, err := f.gwc.GetLock(ctx, req)
if err != nil {
logger.Error().Err(err).Msg("RefreshLock failed trying to get the current lock")
return "", err
return nil, err
}
if resp.GetStatus().GetCode() != rpcv1beta1.Code_CODE_OK {
@@ -408,7 +383,7 @@ func (f *FileConnector) RefreshLock(ctx context.Context, lockID string) (string,
Str("StatusCode", resp.GetStatus().GetCode().String()).
Str("StatusMsg", resp.GetStatus().GetMessage()).
Msg("RefreshLock failed, tried to get the current lock failed with unexpected status")
return "", NewConnectorError(500, resp.GetStatus().GetCode().String()+" "+resp.GetStatus().GetMessage())
return NewResponse(500), nil
}
if resp.GetLock() == nil {
@@ -416,7 +391,7 @@ func (f *FileConnector) RefreshLock(ctx context.Context, lockID string) (string,
Str("StatusCode", resp.GetStatus().GetCode().String()).
Str("StatusMsg", resp.GetStatus().GetMessage()).
Msg("RefreshLock failed, no lock on file")
return "", NewConnectorError(409, "No lock on file")
return NewResponseWithLock(409, ""), nil
} else {
// lock is different than the one requested, otherwise we wouldn't reached this point
logger.Error().
@@ -424,14 +399,14 @@ func (f *FileConnector) RefreshLock(ctx context.Context, lockID string) (string,
Str("StatusCode", resp.GetStatus().GetCode().String()).
Str("StatusMsg", resp.GetStatus().GetMessage()).
Msg("RefreshLock failed, lock mismatch")
return resp.GetLock().GetLockId(), NewConnectorError(409, "Lock mismatch")
return NewResponseWithLock(409, resp.GetLock().GetLockId()), nil
}
default:
logger.Error().
Str("StatusCode", resp.GetStatus().GetCode().String()).
Str("StatusMsg", resp.GetStatus().GetMessage()).
Msg("RefreshLock failed with unexpected status")
return "", NewConnectorError(500, resp.GetStatus().GetCode().String()+" "+resp.GetStatus().GetMessage())
return NewResponse(500), nil
}
}
@@ -448,10 +423,10 @@ func (f *FileConnector) RefreshLock(ctx context.Context, lockID string) (string,
// return an empty lock id.
// The conflict happens if the provided lockID doesn't match the one actually
// applied in the target file.
func (f *FileConnector) UnLock(ctx context.Context, lockID string) (string, error) {
func (f *FileConnector) UnLock(ctx context.Context, lockID string) (*ConnectorResponse, error) {
wopiContext, err := middleware.WopiContextFromCtx(ctx)
if err != nil {
return "", err
return nil, err
}
logger := zerolog.Ctx(ctx).With().
@@ -461,7 +436,7 @@ func (f *FileConnector) UnLock(ctx context.Context, lockID string) (string, erro
if lockID == "" {
logger.Error().Msg("Unlock failed due to empty lockID")
return "", NewConnectorError(400, "Requested lockID is empty")
return NewResponse(400), nil
}
req := &providerv1beta1.UnlockRequest{
@@ -475,17 +450,17 @@ func (f *FileConnector) UnLock(ctx context.Context, lockID string) (string, erro
resp, err := f.gwc.Unlock(ctx, req)
if err != nil {
logger.Error().Err(err).Msg("Unlock failed")
return "", err
return nil, err
}
switch resp.GetStatus().GetCode() {
case rpcv1beta1.Code_CODE_OK:
logger.Debug().Msg("Unlock successful")
return "", nil
return NewResponse(200), nil
case rpcv1beta1.Code_CODE_ABORTED:
// File isn't locked. Need to return 409 with empty lock
logger.Error().Err(err).Msg("Unlock failed, file isn't locked")
return "", NewConnectorError(409, "File is not locked")
return NewResponseWithLock(409, ""), nil
case rpcv1beta1.Code_CODE_LOCKED:
// We need to return 409 with the current lock
req := &providerv1beta1.GetLockRequest{
@@ -495,7 +470,7 @@ func (f *FileConnector) UnLock(ctx context.Context, lockID string) (string, erro
resp, err := f.gwc.GetLock(ctx, req)
if err != nil {
logger.Error().Err(err).Msg("Unlock failed trying to get the current lock")
return "", err
return nil, err
}
if resp.GetStatus().GetCode() != rpcv1beta1.Code_CODE_OK {
@@ -503,7 +478,7 @@ func (f *FileConnector) UnLock(ctx context.Context, lockID string) (string, erro
Str("StatusCode", resp.GetStatus().GetCode().String()).
Str("StatusMsg", resp.GetStatus().GetMessage()).
Msg("Unlock failed, tried to get the current lock failed with unexpected status")
return "", NewConnectorError(500, resp.GetStatus().GetCode().String()+" "+resp.GetStatus().GetMessage())
return NewResponse(500), nil
}
var outLockId string
@@ -522,13 +497,13 @@ func (f *FileConnector) UnLock(ctx context.Context, lockID string) (string, erro
Msg("Unlock failed, lock mismatch")
outLockId = resp.GetLock().GetLockId()
}
return outLockId, NewConnectorError(409, "Lock mismatch")
return NewResponseWithLock(409, outLockId), nil
default:
logger.Error().
Str("StatusCode", resp.GetStatus().GetCode().String()).
Str("StatusMsg", resp.GetStatus().GetMessage()).
Msg("Unlock failed with unexpected status")
return "", NewConnectorError(500, resp.GetStatus().GetCode().String()+" "+resp.GetStatus().GetMessage())
return NewResponse(500), nil
}
}
@@ -558,7 +533,7 @@ func (f *FileConnector) UnLock(ctx context.Context, lockID string) (string, erro
// Since the upload won't use any lock, the upload will fail if the target file
// already exists and it isn't empty. This means that, this method can only
// generate new files.
func (f *FileConnector) PutRelativeFileSuggested(ctx context.Context, ccs ContentConnectorService, stream io.Reader, streamLength int64, target string) (*PutRelativeResponse, error) {
func (f *FileConnector) PutRelativeFileSuggested(ctx context.Context, ccs ContentConnectorService, stream io.Reader, streamLength int64, target string) (*ConnectorResponse, error) {
// assume the target is a full name
wopiContext, err := middleware.WopiContextFromCtx(ctx)
if err != nil {
@@ -583,7 +558,7 @@ func (f *FileConnector) PutRelativeFileSuggested(ctx context.Context, ccs Conten
Str("StatusCode", oldStatRes.GetStatus().GetCode().String()).
Str("StatusMsg", oldStatRes.GetStatus().GetMessage()).
Msg("PutRelativeFileSuggested: stat failed with unexpected status")
return nil, NewConnectorError(500, oldStatRes.GetStatus().GetCode().String()+" "+oldStatRes.GetStatus().GetMessage())
return NewResponse(500), nil
}
if strings.HasPrefix(target, ".") {
@@ -597,8 +572,6 @@ func (f *FileConnector) PutRelativeFileSuggested(ctx context.Context, ccs Conten
finalTarget := target
newLogger := logger
for isDone := false; !isDone; {
var conError *ConnectorError
targetPath := utils.MakeRelativePath(finalTarget)
// need to change the file reference of the wopicontext to point to the new path
wopiContext.FileReference = &providerv1beta1.Reference{
@@ -611,29 +584,27 @@ func (f *FileConnector) PutRelativeFileSuggested(ctx context.Context, ccs Conten
newCtx := middleware.WopiContextToCtx(newLogger.WithContext(ctx), wopiContext)
// try to put the file. It mustn't return a 400 or 409
_, err := ccs.PutFile(newCtx, stream, streamLength, "")
putResponse, err := ccs.PutFile(newCtx, stream, streamLength, "")
if err != nil {
// if the error isn't a connectorError, fail the request
if !errors.As(err, &conError) {
newLogger.Error().Err(err).Msg("PutRelativeFileSuggested: put file failed")
return nil, err
}
newLogger.Error().Err(err).Msg("PutRelativeFileSuggested: put file failed")
return nil, err
}
if conError.HttpCodeOut == 409 {
// if conflict generate a different name and retry.
// this should happen only once
actualFilename, _ := f.extractFilenameAndPrefix(target)
finalTarget = f.generatePrefix() + " " + actualFilename
} else {
// TODO: code 400 might happen, what to do?
// in other cases, just return the error
newLogger.Error().Err(err).Msg("PutRelativeFileSuggested: put file failed with unhandled status")
return nil, err
}
} else {
switch putResponse.Status {
case 200:
// if the put is successful, exit the loop and move on
isDone = true
logger = newLogger
case 409:
// if conflict generate a different name and retry.
// this should happen only once
actualFilename, _ := f.extractFilenameAndPrefix(target)
finalTarget = f.generatePrefix() + " " + actualFilename
default:
// TODO: code 400 might happen, what to do?
// in other cases, just return the error
newLogger.Error().Msg("PutRelativeFileSuggested: put file failed with unhandled status")
return NewResponse(500), nil
}
}
@@ -648,16 +619,11 @@ func (f *FileConnector) PutRelativeFileSuggested(ctx context.Context, ccs Conten
return nil, err
}
// send the info
result := &PutRelativeResponse{
Name: finalTarget,
Url: wopiSrcURL.String(),
}
logger.Debug().
Str("FinalReference", wopiContext.FileReference.String()).
Msg("PutRelativeFileSuggested: success")
return result, nil
return NewResponseSuccessBodyNameUrl(finalTarget, wopiSrcURL.String()), nil
}
// PutRelativeFileRelative upload a file using the provided target name
@@ -684,11 +650,11 @@ func (f *FileConnector) PutRelativeFileSuggested(ctx context.Context, ccs Conten
// Since the upload won't use any lock, the upload will fail if the target file
// already exists and it isn't empty. This means that, this method can only
// generate new files.
func (f *FileConnector) PutRelativeFileRelative(ctx context.Context, ccs ContentConnectorService, stream io.Reader, streamLength int64, target string) (*PutRelativeResponse, *PutRelativeHeaders, error) {
func (f *FileConnector) PutRelativeFileRelative(ctx context.Context, ccs ContentConnectorService, stream io.Reader, streamLength int64, target string) (*ConnectorResponse, error) {
// assume the target is a full name
wopiContext, err := middleware.WopiContextFromCtx(ctx)
if err != nil {
return nil, nil, err
return nil, err
}
logger := zerolog.Ctx(ctx).With().
@@ -701,7 +667,7 @@ func (f *FileConnector) PutRelativeFileRelative(ctx context.Context, ccs Content
})
if err != nil {
logger.Error().Err(err).Msg("PutRelativeFileRelative: stat failed")
return nil, nil, err
return nil, err
}
if oldStatRes.GetStatus().GetCode() != rpcv1beta1.Code_CODE_OK {
@@ -709,7 +675,7 @@ func (f *FileConnector) PutRelativeFileRelative(ctx context.Context, ccs Content
Str("StatusCode", oldStatRes.GetStatus().GetCode().String()).
Str("StatusMsg", oldStatRes.GetStatus().GetMessage()).
Msg("PutRelativeFileRelative: stat failed with unexpected status")
return nil, nil, NewConnectorError(500, oldStatRes.GetStatus().GetCode().String()+" "+oldStatRes.GetStatus().GetMessage())
return NewResponse(500), nil
}
targetPath := utils.MakeRelativePath(target)
@@ -723,72 +689,74 @@ func (f *FileConnector) PutRelativeFileRelative(ctx context.Context, ccs Content
newLogger := logger.With().Str("NewFileReference", wopiContext.FileReference.String()).Logger()
newCtx := middleware.WopiContextToCtx(newLogger.WithContext(ctx), wopiContext)
var conError *ConnectorError
// try to put the file
lockID, err := ccs.PutFile(newCtx, stream, streamLength, "")
putResponse, err := ccs.PutFile(newCtx, stream, streamLength, "")
if err != nil {
// if the error isn't a connectorError, fail the request
if !errors.As(err, &conError) {
newLogger.Error().Err(err).Msg("PutRelativeFileRelative: put file failed")
return nil, nil, err
newLogger.Error().Err(err).Msg("PutRelativeFileRelative: put file failed")
return nil, err
}
lockID := ""
if putResponse.Headers != nil {
lockID = putResponse.Headers[HeaderWopiLock]
}
switch putResponse.Status {
case 200: // success case, so don't do anything
case 409:
if err := f.adjustWopiReference(ctx, &wopiContext, newLogger); err != nil {
return nil, err
}
// if conflict generate a different name and retry.
// this should happen only once
wopiSrcURL, err2 := f.generateWOPISrc(ctx, wopiContext, newLogger)
if err2 != nil {
newLogger.Error().
Err(err2).
Str("LockID", lockID).
Msg("PutRelativeFileRelative: error generating the WOPISrc parameter for conflict response")
return nil, err2
}
if conError.HttpCodeOut == 409 {
if err := f.adjustWopiReference(ctx, &wopiContext, newLogger); err != nil {
return nil, nil, err
}
// if conflict generate a different name and retry.
// this should happen only once
wopiSrcURL, err2 := f.generateWOPISrc(ctx, wopiContext, newLogger)
if err2 != nil {
newLogger.Error().
Err(err2).
Str("LockID", lockID).
Msg("PutRelativeFileRelative: error generating the WOPISrc parameter for conflict response")
return nil, nil, err
}
actualFilename, _ := f.extractFilenameAndPrefix(target)
finalTarget := f.generatePrefix() + " " + actualFilename
actualFilename, _ := f.extractFilenameAndPrefix(target)
finalTarget := f.generatePrefix() + " " + actualFilename
headers := &PutRelativeHeaders{
ValidTarget: finalTarget,
LockID: lockID,
}
response := &PutRelativeResponse{
Name: target,
Url: wopiSrcURL.String(),
}
newLogger.Error().
Err(err).
Str("LockID", lockID).
Msg("PutRelativeFileRelative: error conflict")
return response, headers, err
} else {
newLogger.Error().
Err(err).
Str("LockID", lockID).
Msg("PutRelativeFileRelative: put file failed with unhandled status")
return nil, nil, err
}
newLogger.Error().
Str("LockID", lockID).
Msg("PutRelativeFileRelative: error conflict")
// need to build the response ourselves
return &ConnectorResponse{
Status: 409,
Headers: map[string]string{
HeaderWopiValidRT: finalTarget,
HeaderWopiLock: lockID,
},
Body: map[string]interface{}{
"Name": target,
"Url": wopiSrcURL.String(),
},
}, nil
default:
newLogger.Error().
Str("LockID", lockID).
Msg("PutRelativeFileRelative: put file failed with unhandled status")
return NewResponse(500), nil
}
if err := f.adjustWopiReference(ctx, &wopiContext, newLogger); err != nil {
return nil, nil, err
return nil, err
}
wopiSrcURL, err := f.generateWOPISrc(ctx, wopiContext, newLogger)
if err != nil {
newLogger.Error().Err(err).Msg("PutRelativeFileRelative: error generating the WOPISrc parameter")
return nil, nil, err
}
// send the info
result := &PutRelativeResponse{
Name: target,
Url: wopiSrcURL.String(),
return nil, err
}
newLogger.Debug().Msg("PutRelativeFileRelative: success")
return result, nil, nil
return NewResponseSuccessBodyNameUrl(target, wopiSrcURL.String()), nil
}
// DeleteFile will delete the requested file
@@ -804,10 +772,10 @@ func (f *FileConnector) PutRelativeFileRelative(ctx context.Context, ccs Content
//
// Note that this method isn't required and it's likely used just for the
// WOPI validator
func (f *FileConnector) DeleteFile(ctx context.Context, lockID string) (string, error) {
func (f *FileConnector) DeleteFile(ctx context.Context, lockID string) (*ConnectorResponse, error) {
wopiContext, err := middleware.WopiContextFromCtx(ctx)
if err != nil {
return "", err
return nil, err
}
logger := zerolog.Ctx(ctx).With().
@@ -825,7 +793,7 @@ func (f *FileConnector) DeleteFile(ctx context.Context, lockID string) (string,
deleteRes, err = f.gwc.Delete(ctx, deleteReq)
if err != nil {
logger.Error().Err(err).Msg("DeleteFile: stat failed")
return "", err
return nil, err
}
if deleteRes.GetStatus().GetCode() == rpcv1beta1.Code_CODE_TOO_EARLY {
@@ -856,7 +824,7 @@ func (f *FileConnector) DeleteFile(ctx context.Context, lockID string) (string,
if deleteRes.GetStatus().GetCode() == rpcv1beta1.Code_CODE_NOT_FOUND {
// don't bother to check for locks of a missing file
logger.Error().Msg("DeleteFile: tried to delete a missing file")
return "", NewConnectorError(404, deleteRes.GetStatus().GetCode().String()+" "+deleteRes.GetStatus().GetMessage())
return NewResponse(404), nil
}
// check if the file is locked to return a proper lockID
@@ -867,7 +835,7 @@ func (f *FileConnector) DeleteFile(ctx context.Context, lockID string) (string,
resp, err2 := f.gwc.GetLock(ctx, req)
if err2 != nil {
logger.Error().Err(err2).Msg("DeleteFile: GetLock failed")
return "", err2
return nil, err2
}
if resp.GetStatus().GetCode() != rpcv1beta1.Code_CODE_OK {
@@ -875,22 +843,22 @@ func (f *FileConnector) DeleteFile(ctx context.Context, lockID string) (string,
Str("StatusCode", resp.GetStatus().GetCode().String()).
Str("StatusMsg", resp.GetStatus().GetMessage()).
Msg("DeleteFile: GetLock failed with unexpected status")
return "", NewConnectorError(500, resp.GetStatus().GetCode().String()+" "+resp.GetStatus().GetMessage())
return NewResponse(500), nil
}
if resp.GetLock() != nil {
logger.Error().
Str("LockID", resp.GetLock().GetLockId()).
Msg("DeleteFile: file is locked")
return resp.GetLock().GetLockId(), NewConnectorError(409, "file is locked")
return NewResponseWithLock(409, resp.GetLock().GetLockId()), nil
} else {
// return the original error since the file isn't locked
logger.Error().Msg("DeleteFile: delete failed on unlocked file")
return "", NewConnectorError(500, deleteRes.GetStatus().GetCode().String()+" "+deleteRes.GetStatus().GetMessage())
return NewResponse(500), nil
}
}
logger.Debug().Msg("DeleteFile: success")
return "", nil
return NewResponse(200), nil
}
// RenameFile will rename the requested file
@@ -907,10 +875,10 @@ func (f *FileConnector) DeleteFile(ctx context.Context, lockID string) (string,
// is just a suggestion, so it could have changed) and the actual lockId in
// case of conflict as second return value, otherwise the returned lockId will
// be empty.
func (f *FileConnector) RenameFile(ctx context.Context, lockID, target string) (*RenameResponse, string, error) {
func (f *FileConnector) RenameFile(ctx context.Context, lockID, target string) (*ConnectorResponse, error) {
wopiContext, err := middleware.WopiContextFromCtx(ctx)
if err != nil {
return nil, "", err
return nil, err
}
logger := zerolog.Ctx(ctx).With().
@@ -924,19 +892,19 @@ func (f *FileConnector) RenameFile(ctx context.Context, lockID, target string) (
})
if err != nil {
logger.Error().Err(err).Msg("RenameFile: stat failed")
return nil, "", err
return nil, err
}
if oldStatRes.GetStatus().GetCode() != rpcv1beta1.Code_CODE_OK {
if oldStatRes.GetStatus().GetCode() == rpcv1beta1.Code_CODE_NOT_FOUND {
logger.Error().Msg("RenameFile: file not found")
return nil, "", NewConnectorError(404, oldStatRes.GetStatus().GetCode().String()+" "+oldStatRes.GetStatus().GetMessage())
return NewResponse(404), nil
} else {
logger.Error().
Str("StatusCode", oldStatRes.GetStatus().GetCode().String()).
Str("StatusMsg", oldStatRes.GetStatus().GetMessage()).
Msg("RenameFile: stat failed with unexpected status")
return nil, "", NewConnectorError(500, oldStatRes.GetStatus().GetCode().String()+" "+oldStatRes.GetStatus().GetMessage())
return NewResponse(500), nil
}
}
@@ -962,7 +930,7 @@ func (f *FileConnector) RenameFile(ctx context.Context, lockID, target string) (
})
if err != nil {
newLogger.Error().Err(err).Msg("RenameFile: move failed")
return nil, "", err
return nil, err
}
if moveRes.GetStatus().GetCode() != rpcv1beta1.Code_CODE_OK {
if moveRes.GetStatus().GetCode() == rpcv1beta1.Code_CODE_LOCKED || moveRes.GetStatus().GetCode() == rpcv1beta1.Code_CODE_ABORTED {
@@ -975,7 +943,7 @@ func (f *FileConnector) RenameFile(ctx context.Context, lockID, target string) (
Str("StatusCode", moveRes.GetStatus().GetCode().String()).
Str("StatusMsg", moveRes.GetStatus().GetMessage()).
Msg("RenameFile: conflict")
return nil, currentLockID, NewConnectorError(409, "file is locked")
return NewResponseWithLock(409, currentLockID), nil
}
if moveRes.GetStatus().GetCode() == rpcv1beta1.Code_CODE_ALREADY_EXISTS {
@@ -990,7 +958,7 @@ func (f *FileConnector) RenameFile(ctx context.Context, lockID, target string) (
Str("StatusMsg", moveRes.GetStatus().GetMessage()).
Msg("RenameFile: move failed with unexpected status")
return nil, "", NewConnectorError(500, moveRes.GetStatus().GetCode().String()+" "+moveRes.GetStatus().GetMessage())
return NewResponse(500), nil
}
} else {
// if the put is successful, exit the loop and move on
@@ -1000,10 +968,8 @@ func (f *FileConnector) RenameFile(ctx context.Context, lockID, target string) (
}
logger.Debug().Msg("RenameFile: success")
return &RenameResponse{
Name: strings.TrimSuffix(path.Base(finalTarget), path.Ext(finalTarget)), // return the final filename without extension
}, "", nil
// return the final filename without extension
return NewResponseSuccessBodyName(strings.TrimSuffix(path.Base(finalTarget), path.Ext(finalTarget))), nil
}
// CheckFileInfo returns information about the requested file and capabilities of the wopi server
@@ -1015,7 +981,7 @@ func (f *FileConnector) RenameFile(ctx context.Context, lockID, target string) (
//
// If the operation is successful, a "FileInfo" instance will be returned,
// otherwise the "FileInfo" will be empty and an error will be returned.
func (f *FileConnector) CheckFileInfo(ctx context.Context) (fileinfo.FileInfo, error) {
func (f *FileConnector) CheckFileInfo(ctx context.Context) (*ConnectorResponse, error) {
wopiContext, err := middleware.WopiContextFromCtx(ctx)
if err != nil {
return nil, err
@@ -1036,7 +1002,7 @@ func (f *FileConnector) CheckFileInfo(ctx context.Context) (fileinfo.FileInfo, e
Str("StatusCode", statRes.GetStatus().GetCode().String()).
Str("StatusMsg", statRes.GetStatus().GetMessage()).
Msg("CheckFileInfo: stat failed with unexpected status")
return nil, NewConnectorError(500, statRes.GetStatus().GetCode().String()+" "+statRes.GetStatus().GetMessage())
return NewResponse(500), nil
}
// If a not known app name is used, consider "Microsoft" as default.
@@ -1124,7 +1090,7 @@ func (f *FileConnector) CheckFileInfo(ctx context.Context) (fileinfo.FileInfo, e
info.SetProperties(infoMap)
logger.Debug().Interface("FileInfo", info).Msg("CheckFileInfo: success")
return info, nil
return NewResponseSuccessBody(info), nil
}
func (f *FileConnector) watermarkText(user *userv1beta1.User) string {

File diff suppressed because it is too large Load Diff

View File

@@ -72,19 +72,14 @@ func NewHttpAdapterWithConnector(con ConnectorService, l locks.LockParser) *Http
// the headers according to the spec
func (h *HttpAdapter) GetLock(w http.ResponseWriter, r *http.Request) {
fileCon := h.con.GetFileConnector()
response, err := fileCon.GetLock(r.Context())
lockID, err := fileCon.GetLock(r.Context())
if err != nil {
var conError *ConnectorError
if errors.As(err, &conError) {
http.Error(w, http.StatusText(conError.HttpCodeOut), conError.HttpCodeOut)
} else {
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
w.Header().Set(HeaderWopiLock, lockID)
w.WriteHeader(http.StatusOK)
h.writeConnectorResponse(w, r, response)
}
// Lock adapts the "Lock" and "UnlockAndRelock" operations for WOPI.
@@ -98,20 +93,14 @@ func (h *HttpAdapter) Lock(w http.ResponseWriter, r *http.Request) {
lockID := h.locks.ParseLock(r.Header.Get(HeaderWopiLock))
fileCon := h.con.GetFileConnector()
newLockID, err := fileCon.Lock(r.Context(), lockID, oldLockID)
response, err := fileCon.Lock(r.Context(), lockID, oldLockID)
if err != nil {
var conError *ConnectorError
if errors.As(err, &conError) {
if conError.HttpCodeOut == 409 {
w.Header().Set(HeaderWopiLock, newLockID)
}
http.Error(w, http.StatusText(conError.HttpCodeOut), conError.HttpCodeOut)
} else {
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
h.writeConnectorResponse(w, r, response)
}
// RefreshLock adapts the "RefreshLock" operation for WOPI
@@ -125,20 +114,14 @@ func (h *HttpAdapter) RefreshLock(w http.ResponseWriter, r *http.Request) {
lockID := h.locks.ParseLock(r.Header.Get(HeaderWopiLock))
fileCon := h.con.GetFileConnector()
newLockID, err := fileCon.RefreshLock(r.Context(), lockID)
response, err := fileCon.RefreshLock(r.Context(), lockID)
if err != nil {
var conError *ConnectorError
if errors.As(err, &conError) {
if conError.HttpCodeOut == 409 {
w.Header().Set(HeaderWopiLock, newLockID)
}
http.Error(w, http.StatusText(conError.HttpCodeOut), conError.HttpCodeOut)
} else {
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
h.writeConnectorResponse(w, r, response)
}
// UnLock adapts the "Unlock" operation for WOPI
@@ -150,20 +133,14 @@ func (h *HttpAdapter) UnLock(w http.ResponseWriter, r *http.Request) {
lockID := h.locks.ParseLock(r.Header.Get(HeaderWopiLock))
fileCon := h.con.GetFileConnector()
newLockID, err := fileCon.UnLock(r.Context(), lockID)
response, err := fileCon.UnLock(r.Context(), lockID)
if err != nil {
var conError *ConnectorError
if errors.As(err, &conError) {
if conError.HttpCodeOut == 409 {
w.Header().Set(HeaderWopiLock, newLockID)
}
http.Error(w, http.StatusText(conError.HttpCodeOut), conError.HttpCodeOut)
} else {
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
h.writeConnectorResponse(w, r, response)
}
// CheckFileInfo will retrieve the information of the file in json format
@@ -172,41 +149,14 @@ func (h *HttpAdapter) UnLock(w http.ResponseWriter, r *http.Request) {
// the headers according to the spec
func (h *HttpAdapter) CheckFileInfo(w http.ResponseWriter, r *http.Request) {
fileCon := h.con.GetFileConnector()
response, err := fileCon.CheckFileInfo(r.Context())
w.Header().Set(HeaderContentType, "application/json")
w.Header().Set(HeaderContentLength, "0")
fileInfo, err := fileCon.CheckFileInfo(r.Context())
if err != nil {
var conError *ConnectorError
if errors.As(err, &conError) {
http.Error(w, http.StatusText(conError.HttpCodeOut), conError.HttpCodeOut)
} else {
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
return
}
logger := zerolog.Ctx(r.Context())
jsonFileInfo, err := json.Marshal(fileInfo)
if err != nil {
logger.Error().Err(err).Msg("CheckFileInfo: failed to marshal fileinfo")
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
w.Header().Set(HeaderContentLength, strconv.Itoa(len(jsonFileInfo)))
w.WriteHeader(http.StatusOK)
bytes, err := w.Write(jsonFileInfo)
if err != nil {
logger.Error().
Err(err).
Int("TotalBytes", len(jsonFileInfo)).
Int("WrittenBytes", bytes).
Msg("CheckFileInfo: failed to write contents in the HTTP response")
}
h.writeConnectorResponse(w, r, response)
}
// GetFile will download the file
@@ -237,20 +187,14 @@ func (h *HttpAdapter) PutFile(w http.ResponseWriter, r *http.Request) {
lockID := h.locks.ParseLock(r.Header.Get(HeaderWopiLock))
contentCon := h.con.GetContentConnector()
newLockID, err := contentCon.PutFile(r.Context(), r.Body, r.ContentLength, lockID)
response, err := contentCon.PutFile(r.Context(), r.Body, r.ContentLength, lockID)
if err != nil {
var conError *ConnectorError
if errors.As(err, &conError) {
if conError.HttpCodeOut == 409 {
w.Header().Set(HeaderWopiLock, newLockID)
}
http.Error(w, http.StatusText(conError.HttpCodeOut), conError.HttpCodeOut)
} else {
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
h.writeConnectorResponse(w, r, response)
}
// PutRelativeFile will upload the file with a specific name. The name might be
@@ -267,17 +211,13 @@ func (h *HttpAdapter) PutRelativeFile(w http.ResponseWriter, r *http.Request) {
relativeTarget := r.Header.Get(HeaderWopiRT)
suggestedTarget := r.Header.Get(HeaderWopiST)
w.Header().Set(HeaderContentType, "application/json")
w.Header().Set(HeaderContentLength, "0")
if relativeTarget != "" && suggestedTarget != "" {
// headers are mutually exclusive
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
return
}
var response *PutRelativeResponse
var headers *PutRelativeHeaders
var response *ConnectorResponse
var putErr error
fileCon := h.con.GetFileConnector()
@@ -296,43 +236,15 @@ func (h *HttpAdapter) PutRelativeFile(w http.ResponseWriter, r *http.Request) {
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
return
}
response, headers, putErr = fileCon.PutRelativeFileRelative(r.Context(), h.con.GetContentConnector(), r.Body, r.ContentLength, utf8Target)
response, putErr = fileCon.PutRelativeFileRelative(r.Context(), h.con.GetContentConnector(), r.Body, r.ContentLength, utf8Target)
}
var conError *ConnectorError
if putErr != nil && !errors.As(putErr, &conError) {
if putErr != nil {
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
logger := zerolog.Ctx(r.Context())
jsonFileInfo, err := json.Marshal(response)
if err != nil {
logger.Error().Err(err).Msg("PutRelativeFile: failed to marshal response")
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
w.Header().Set(HeaderContentLength, strconv.Itoa(len(jsonFileInfo)))
if conError != nil {
if headers != nil {
w.Header().Set(HeaderWopiValidRT, utf7.EncodeString(headers.ValidTarget))
w.Header().Set(HeaderWopiLock, headers.LockID)
}
w.WriteHeader(conError.HttpCodeOut)
} else {
w.WriteHeader(http.StatusOK)
}
bytes, err := w.Write(jsonFileInfo)
if err != nil {
logger.Error().
Err(err).
Int("TotalBytes", len(jsonFileInfo)).
Int("WrittenBytes", bytes).
Msg("PutRelativeFile: failed to write contents in the HTTP response")
}
h.writeConnectorResponse(w, r, response)
}
// DeleteFile will delete the provided file. If the file is locked and can't
@@ -342,20 +254,14 @@ func (h *HttpAdapter) DeleteFile(w http.ResponseWriter, r *http.Request) {
lockID := r.Header.Get(HeaderWopiLock)
fileCon := h.con.GetFileConnector()
newLockID, err := fileCon.DeleteFile(r.Context(), lockID)
response, err := fileCon.DeleteFile(r.Context(), lockID)
if err != nil {
var conError *ConnectorError
if errors.As(err, &conError) {
if conError.HttpCodeOut == 409 {
w.Header().Set(HeaderWopiLock, newLockID)
}
http.Error(w, http.StatusText(conError.HttpCodeOut), conError.HttpCodeOut)
} else {
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
h.writeConnectorResponse(w, r, response)
}
// RenameFile will rename the file. The name might be automatically adjusted.
@@ -377,39 +283,43 @@ func (h *HttpAdapter) RenameFile(w http.ResponseWriter, r *http.Request) {
}
fileCon := h.con.GetFileConnector()
response, newLockID, err := fileCon.RenameFile(r.Context(), lockID, utf8Target)
response, err := fileCon.RenameFile(r.Context(), lockID, utf8Target)
if err != nil {
var conError *ConnectorError
if errors.As(err, &conError) {
if conError.HttpCodeOut == 409 {
w.Header().Set(HeaderWopiLock, newLockID)
}
http.Error(w, http.StatusText(conError.HttpCodeOut), conError.HttpCodeOut)
} else {
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
return
}
// need to return a JSON response with the name if this is successful
logger := zerolog.Ctx(r.Context())
jsonFileInfo, err := json.Marshal(response)
if err != nil {
logger.Error().Err(err).Msg("RenameFile: failed to marshal response")
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
w.Header().Set(HeaderContentLength, strconv.Itoa(len(jsonFileInfo)))
w.WriteHeader(http.StatusOK)
bytes, err := w.Write(jsonFileInfo)
h.writeConnectorResponse(w, r, response)
}
func (h *HttpAdapter) writeConnectorResponse(w http.ResponseWriter, r *http.Request, response *ConnectorResponse) {
jsonBody := []byte{}
if response.Body != nil {
var err error
jsonBody, err = json.Marshal(response.Body)
if err != nil {
logger := zerolog.Ctx(r.Context())
logger.Error().Err(err).Msg("failed to marshal response")
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
w.Header().Set(HeaderContentType, "application/json")
w.Header().Set(HeaderContentLength, strconv.Itoa(len(jsonBody)))
}
for key, value := range response.Headers {
w.Header().Set(key, value)
}
w.WriteHeader(response.Status)
bytes, err := w.Write(jsonBody)
if err != nil {
logger := zerolog.Ctx(r.Context())
logger.Error().
Err(err).
Int("TotalBytes", len(jsonFileInfo)).
Int("TotalBytes", len(jsonBody)).
Int("WrittenBytes", bytes).
Msg("RenameFile: failed to write contents in the HTTP response")
Msg("failed to write contents in the HTTP response")
}
}

View File

@@ -47,7 +47,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("GetLock", mock.Anything).Times(1).Return("", errors.New("Something happened"))
fc.On("GetLock", mock.Anything).Times(1).Return(nil, errors.New("Something happened"))
httpAdapter.GetLock(w, req)
resp := w.Result()
@@ -60,7 +60,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("GetLock", mock.Anything).Times(1).Return("", connector.NewConnectorError(404, "Couldn't get the file"))
fc.On("GetLock", mock.Anything).Times(1).Return(connector.NewResponse(404), nil)
httpAdapter.GetLock(w, req)
resp := w.Result()
@@ -73,7 +73,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("GetLock", mock.Anything).Times(1).Return("zzz111", nil)
fc.On("GetLock", mock.Anything).Times(1).Return(connector.NewResponseWithLock(200, "zzz111"), nil)
httpAdapter.GetLock(w, req)
resp := w.Result()
@@ -87,7 +87,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("GetLock", mock.Anything).Times(1).Return("", nil)
fc.On("GetLock", mock.Anything).Times(1).Return(connector.NewResponseWithLock(200, ""), nil)
httpAdapter.GetLock(w, req)
resp := w.Result()
@@ -105,7 +105,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("Lock", mock.Anything, "abc123", "").Times(1).Return("", errors.New("Something happened"))
fc.On("Lock", mock.Anything, "abc123", "").Times(1).Return(nil, errors.New("Something happened"))
httpAdapter.Lock(w, req)
resp := w.Result()
@@ -119,7 +119,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("Lock", mock.Anything, "", "").Times(1).Return("", connector.NewConnectorError(400, "No lockId"))
fc.On("Lock", mock.Anything, "", "").Times(1).Return(connector.NewResponse(400), nil)
httpAdapter.Lock(w, req)
resp := w.Result()
@@ -133,7 +133,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("Lock", mock.Anything, "abc123", "").Times(1).Return("zzz111", connector.NewConnectorError(409, "Lock conflict"))
fc.On("Lock", mock.Anything, "abc123", "").Times(1).Return(connector.NewResponseWithLock(409, "zzz111"), nil)
httpAdapter.Lock(w, req)
resp := w.Result()
@@ -148,7 +148,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("Lock", mock.Anything, "abc123", "").Times(1).Return("", nil)
fc.On("Lock", mock.Anything, "abc123", "").Times(1).Return(connector.NewResponse(200), nil)
httpAdapter.Lock(w, req)
resp := w.Result()
@@ -165,7 +165,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("Lock", mock.Anything, "abc123", "qwerty").Times(1).Return("", errors.New("Something happened"))
fc.On("Lock", mock.Anything, "abc123", "qwerty").Times(1).Return(nil, errors.New("Something happened"))
httpAdapter.Lock(w, req)
resp := w.Result()
@@ -180,7 +180,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("Lock", mock.Anything, "", "").Times(1).Return("", connector.NewConnectorError(400, "No lockId"))
fc.On("Lock", mock.Anything, "", "").Times(1).Return(connector.NewResponse(400), nil)
httpAdapter.Lock(w, req)
resp := w.Result()
@@ -195,7 +195,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("Lock", mock.Anything, "abc123", "qwerty").Times(1).Return("zzz111", connector.NewConnectorError(409, "Lock conflict"))
fc.On("Lock", mock.Anything, "abc123", "qwerty").Times(1).Return(connector.NewResponseWithLock(409, "zzz111"), nil)
httpAdapter.Lock(w, req)
resp := w.Result()
@@ -211,7 +211,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("Lock", mock.Anything, "abc123", "qwerty").Times(1).Return("", nil)
fc.On("Lock", mock.Anything, "abc123", "qwerty").Times(1).Return(connector.NewResponse(200), nil)
httpAdapter.Lock(w, req)
resp := w.Result()
@@ -228,7 +228,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("RefreshLock", mock.Anything, "abc123").Times(1).Return("", errors.New("Something happened"))
fc.On("RefreshLock", mock.Anything, "abc123").Times(1).Return(nil, errors.New("Something happened"))
httpAdapter.RefreshLock(w, req)
resp := w.Result()
@@ -242,7 +242,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("RefreshLock", mock.Anything, "").Times(1).Return("", connector.NewConnectorError(400, "No lockId"))
fc.On("RefreshLock", mock.Anything, "").Times(1).Return(connector.NewResponse(400), nil)
httpAdapter.RefreshLock(w, req)
resp := w.Result()
@@ -256,7 +256,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("RefreshLock", mock.Anything, "abc123").Times(1).Return("zzz111", connector.NewConnectorError(409, "Lock conflict"))
fc.On("RefreshLock", mock.Anything, "abc123").Times(1).Return(connector.NewResponseWithLock(409, "zzz111"), nil)
httpAdapter.RefreshLock(w, req)
resp := w.Result()
@@ -271,7 +271,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("RefreshLock", mock.Anything, "abc123").Times(1).Return("", nil)
fc.On("RefreshLock", mock.Anything, "abc123").Times(1).Return(connector.NewResponse(200), nil)
httpAdapter.RefreshLock(w, req)
resp := w.Result()
@@ -287,7 +287,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("UnLock", mock.Anything, "abc123").Times(1).Return("", errors.New("Something happened"))
fc.On("UnLock", mock.Anything, "abc123").Times(1).Return(nil, errors.New("Something happened"))
httpAdapter.UnLock(w, req)
resp := w.Result()
@@ -301,7 +301,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("UnLock", mock.Anything, "").Times(1).Return("", connector.NewConnectorError(400, "No lockId"))
fc.On("UnLock", mock.Anything, "").Times(1).Return(connector.NewResponse(400), nil)
httpAdapter.UnLock(w, req)
resp := w.Result()
@@ -315,7 +315,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("UnLock", mock.Anything, "abc123").Times(1).Return("zzz111", connector.NewConnectorError(409, "Lock conflict"))
fc.On("UnLock", mock.Anything, "abc123").Times(1).Return(connector.NewResponseWithLock(409, "zzz111"), nil)
httpAdapter.UnLock(w, req)
resp := w.Result()
@@ -330,7 +330,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("UnLock", mock.Anything, "abc123").Times(1).Return("", nil)
fc.On("UnLock", mock.Anything, "abc123").Times(1).Return(connector.NewResponse(200), nil)
httpAdapter.UnLock(w, req)
resp := w.Result()
@@ -344,7 +344,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("CheckFileInfo", mock.Anything).Times(1).Return(&fileinfo.Microsoft{}, errors.New("Something happened"))
fc.On("CheckFileInfo", mock.Anything).Times(1).Return(nil, errors.New("Something happened"))
httpAdapter.CheckFileInfo(w, req)
resp := w.Result()
@@ -358,7 +358,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
fc.On("CheckFileInfo", mock.Anything).Times(1).Return(&fileinfo.Microsoft{}, connector.NewConnectorError(404, "Not found"))
fc.On("CheckFileInfo", mock.Anything).Times(1).Return(connector.NewResponse(404), nil)
httpAdapter.CheckFileInfo(w, req)
resp := w.Result()
@@ -375,7 +375,7 @@ var _ = Describe("HttpAdapter", func() {
Size: 123456789,
BreadcrumbDocName: "testy.docx",
}
fc.On("CheckFileInfo", mock.Anything).Times(1).Return(finfo, nil)
fc.On("CheckFileInfo", mock.Anything).Times(1).Return(connector.NewResponseSuccessBody(finfo), nil)
httpAdapter.CheckFileInfo(w, req)
resp := w.Result()
@@ -444,7 +444,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
cc.On("PutFile", mock.Anything, mock.Anything, int64(len(contentBody)), "abc123").Times(1).Return("", errors.New("Something happened"))
cc.On("PutFile", mock.Anything, mock.Anything, int64(len(contentBody)), "abc123").Times(1).Return(nil, errors.New("Something happened"))
httpAdapter.PutFile(w, req)
resp := w.Result()
@@ -458,7 +458,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
cc.On("PutFile", mock.Anything, mock.Anything, int64(len(contentBody)), "abc123").Times(1).Return("zzz111", connector.NewConnectorError(409, "Lock conflict"))
cc.On("PutFile", mock.Anything, mock.Anything, int64(len(contentBody)), "abc123").Times(1).Return(connector.NewResponseWithLock(409, "zzz111"), nil)
httpAdapter.PutFile(w, req)
resp := w.Result()
@@ -473,7 +473,7 @@ var _ = Describe("HttpAdapter", func() {
w := httptest.NewRecorder()
cc.On("PutFile", mock.Anything, mock.Anything, int64(len(contentBody)), "abc123").Times(1).Return("", nil)
cc.On("PutFile", mock.Anything, mock.Anything, int64(len(contentBody)), "abc123").Times(1).Return(connector.NewResponse(200), nil)
httpAdapter.PutFile(w, req)
resp := w.Result()

View File

@@ -7,7 +7,7 @@ import (
. "github.com/onsi/gomega"
)
func TestGraph(t *testing.T) {
func TestHelpers(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Helpers Suite")
}