Initial QSfera import
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
package connector
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
)
|
||||
|
||||
// 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 any
|
||||
}
|
||||
|
||||
// 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,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NewResponseLockConflict creates a new ConnectorResponse with the status 409
|
||||
// and the "X-WOPI-Lock" header having the value in the lockID parameter.
|
||||
//
|
||||
// This is 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)
|
||||
// The lockFailureReason parameter will be included in the "X-WOPI-LockFailureReason".
|
||||
func NewResponseLockConflict(lockID string, lockFailureReason string) *ConnectorResponse {
|
||||
return &ConnectorResponse{
|
||||
Status: 409,
|
||||
Headers: map[string]string{
|
||||
HeaderWopiLock: lockID,
|
||||
HeaderWopiLockFailureReason: lockFailureReason,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NewResponseWithVersion creates a new ConnectorResponse with the specified status
|
||||
// and the "X-WOPI-ItemVersion" header having the value in the mtime parameter.
|
||||
func NewResponseWithVersion(mtime *types.Timestamp) *ConnectorResponse {
|
||||
return &ConnectorResponse{
|
||||
Status: 200,
|
||||
Headers: map[string]string{
|
||||
HeaderWopiVersion: getVersion(mtime),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NewResponseWithVersionAndLock creates a new ConnectorResponse with the specified status
|
||||
// and the "X-WOPI-ItemVersion" header and the "X-WOPI-Lock" header
|
||||
// having the values in the mtime and lockID parameters.
|
||||
func NewResponseWithVersionAndLock(status int, mtime *types.Timestamp, lockID string) *ConnectorResponse {
|
||||
r := &ConnectorResponse{
|
||||
Status: status,
|
||||
Headers: map[string]string{
|
||||
HeaderWopiVersion: getVersion(mtime),
|
||||
HeaderWopiLock: lockID,
|
||||
},
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// 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 any) *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]any{
|
||||
"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, hostEditURL string, hostViewURL string) *ConnectorResponse {
|
||||
return &ConnectorResponse{
|
||||
Status: 200,
|
||||
Body: map[string]any{
|
||||
"Name": name,
|
||||
"Url": url,
|
||||
"HostEditUrl": hostEditURL,
|
||||
"HostViewUrl": hostViewURL,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
// the connector shouldn't know anything about HTTP.
|
||||
type ConnectorError struct {
|
||||
HttpCodeOut int
|
||||
Msg string
|
||||
}
|
||||
|
||||
// Error gets the error message
|
||||
func (e *ConnectorError) Error() string {
|
||||
return e.Msg
|
||||
}
|
||||
|
||||
// NewConnectorError creates a new connector error using the provided parameters
|
||||
func NewConnectorError(code int, msg string) *ConnectorError {
|
||||
return &ConnectorError{
|
||||
HttpCodeOut: code,
|
||||
Msg: msg,
|
||||
}
|
||||
}
|
||||
|
||||
// ConnectorService is the interface to implement the WOPI operations. They're
|
||||
// divided into multiple endpoints.
|
||||
// The IFileConnector will implement the "File" endpoint
|
||||
// The IContentConnector will implement the "File content" endpoint
|
||||
type ConnectorService interface {
|
||||
GetFileConnector() FileConnectorService
|
||||
GetContentConnector() ContentConnectorService
|
||||
}
|
||||
|
||||
// Connector will implement the WOPI operations.
|
||||
// For convenience, the connector splits the operations based on the
|
||||
// WOPI endpoints, so you'll need to get the specific connector first.
|
||||
//
|
||||
// Available endpoints:
|
||||
// * "Files" -> GetFileConnector()
|
||||
// * "File contents" -> GetContentConnector()
|
||||
//
|
||||
// Other endpoints aren't available for now.
|
||||
type Connector struct {
|
||||
fileConnector FileConnectorService
|
||||
contentConnector ContentConnectorService
|
||||
}
|
||||
|
||||
// NewConnector creates a new connector
|
||||
func NewConnector(fc FileConnectorService, cc ContentConnectorService) *Connector {
|
||||
return &Connector{
|
||||
fileConnector: fc,
|
||||
contentConnector: cc,
|
||||
}
|
||||
}
|
||||
|
||||
// GetFileConnector gets the file connector service associated to this connector
|
||||
func (c *Connector) GetFileConnector() FileConnectorService {
|
||||
return c.fileConnector
|
||||
}
|
||||
|
||||
// GetContentConnector gets the content connector service associated to this connector
|
||||
func (c *Connector) GetContentConnector() ContentConnectorService {
|
||||
return c.contentConnector
|
||||
}
|
||||
|
||||
// getVersion returns a string representation of the timestamp
|
||||
func getVersion(timestamp *types.Timestamp) string {
|
||||
return "v" + strconv.FormatUint(timestamp.GetSeconds(), 10) +
|
||||
strconv.FormatUint(uint64(timestamp.GetNanos()), 10)
|
||||
}
|
||||
Reference in New Issue
Block a user