From 57b50c858734f9af20a9e408beb0d56dc92c5e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pablo=20Villaf=C3=A1=C3=B1ez?= Date: Wed, 17 Apr 2024 15:23:37 +0200 Subject: [PATCH] docs: add missing documentation to functions --- .../collaboration/pkg/connector/connector.go | 5 +++ .../pkg/connector/contentconnector.go | 1 + .../pkg/connector/fileconnector.go | 4 +++ .../pkg/connector/httpadapter.go | 34 +++++++++++++++++++ .../collaboration/pkg/helpers/discovery.go | 4 +++ .../collaboration/pkg/middleware/claims.go | 1 + .../collaboration/pkg/middleware/crypto.go | 9 +++++ .../pkg/middleware/wopicontext.go | 12 +++++++ .../collaboration/pkg/server/http/server.go | 1 + .../pkg/service/grpc/v0/option.go | 1 + .../pkg/service/grpc/v0/service.go | 1 + 11 files changed, 73 insertions(+) diff --git a/services/collaboration/pkg/connector/connector.go b/services/collaboration/pkg/connector/connector.go index b38eb73370..c4224ba740 100644 --- a/services/collaboration/pkg/connector/connector.go +++ b/services/collaboration/pkg/connector/connector.go @@ -9,10 +9,12 @@ type ConnectorError struct { 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, @@ -43,6 +45,7 @@ type Connector struct { contentConnector ContentConnectorService } +// NewConnector creates a new connector func NewConnector(fc FileConnectorService, cc ContentConnectorService) *Connector { return &Connector{ fileConnector: fc, @@ -50,10 +53,12 @@ func NewConnector(fc FileConnectorService, cc ContentConnectorService) *Connecto } } +// 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 } diff --git a/services/collaboration/pkg/connector/contentconnector.go b/services/collaboration/pkg/connector/contentconnector.go index 5153e821d4..7ce1a8977b 100644 --- a/services/collaboration/pkg/connector/contentconnector.go +++ b/services/collaboration/pkg/connector/contentconnector.go @@ -42,6 +42,7 @@ type ContentConnector struct { cfg *config.Config } +// NewContentConnector creates a new content connector func NewContentConnector(gwc gatewayv1beta1.GatewayAPIClient, cfg *config.Config) *ContentConnector { return &ContentConnector{ gwc: gwc, diff --git a/services/collaboration/pkg/connector/fileconnector.go b/services/collaboration/pkg/connector/fileconnector.go index c16b117fb1..f8fe28d2c1 100644 --- a/services/collaboration/pkg/connector/fileconnector.go +++ b/services/collaboration/pkg/connector/fileconnector.go @@ -51,11 +51,15 @@ type FileConnectorService interface { CheckFileInfo(ctx context.Context) (FileInfo, error) } +// FileConnector implements the "File" endpoint. +// Currently, it handles file locks and getting the file info. +// Note that operations might return any kind of error, not just ConnectorError type FileConnector struct { gwc gatewayv1beta1.GatewayAPIClient cfg *config.Config } +// NewFileConnector creates a new file connector func NewFileConnector(gwc gatewayv1beta1.GatewayAPIClient, cfg *config.Config) *FileConnector { return &FileConnector{ gwc: gwc, diff --git a/services/collaboration/pkg/connector/httpadapter.go b/services/collaboration/pkg/connector/httpadapter.go index 075c3d3d8c..201ee769ec 100644 --- a/services/collaboration/pkg/connector/httpadapter.go +++ b/services/collaboration/pkg/connector/httpadapter.go @@ -47,6 +47,10 @@ func NewHttpAdapterWithConnector(con ConnectorService) *HttpAdapter { } } +// GetLock adapts the "GetLock" operation for WOPI. +// Only the request's context is needed in order to extract the WOPI context. +// The operation's response will be sent through the response writer and +// the headers according to the spec func (h *HttpAdapter) GetLock(w http.ResponseWriter, r *http.Request) { fileCon := h.con.GetFileConnector() @@ -63,6 +67,12 @@ func (h *HttpAdapter) GetLock(w http.ResponseWriter, r *http.Request) { w.Header().Set(HeaderWopiLock, lockID) } +// Lock adapts the "Lock" and "UnlockAndRelock" operations for WOPI. +// The request's context is needed in order to extract the WOPI context. In +// addition, the "X-WOPI-Lock" and "X-WOPI-OldLock" headers might be needed" +// (check spec) +// The operation's response will be sent through the response writer and +// the headers according to the spec func (h *HttpAdapter) Lock(w http.ResponseWriter, r *http.Request) { oldLockID := r.Header.Get(HeaderWopiOldLock) lockID := r.Header.Get(HeaderWopiLock) @@ -85,6 +95,13 @@ func (h *HttpAdapter) Lock(w http.ResponseWriter, r *http.Request) { // X-WOPI-Lock header isn't needed on HTTP 200 } +// RefreshLock adapts the "RefreshLock" operation for WOPI +// The request's context is needed in order to extract the WOPI context. In +// addition, the "X-WOPI-Lock" header is needed (check spec). +// The lock will be refreshed to last another 30 minutes. The value is +// hardcoded +// The operation's response will be sent through the response writer and +// the headers according to the spec func (h *HttpAdapter) RefreshLock(w http.ResponseWriter, r *http.Request) { lockID := r.Header.Get(HeaderWopiLock) @@ -106,6 +123,11 @@ func (h *HttpAdapter) RefreshLock(w http.ResponseWriter, r *http.Request) { // X-WOPI-Lock header isn't needed on HTTP 200 } +// UnLock adapts the "Unlock" operation for WOPI +// The request's context is needed in order to extract the WOPI context. In +// addition, the "X-WOPI-Lock" header is needed (check spec). +// The operation's response will be sent through the response writer and +// the headers according to the spec func (h *HttpAdapter) UnLock(w http.ResponseWriter, r *http.Request) { lockID := r.Header.Get(HeaderWopiLock) @@ -127,6 +149,10 @@ func (h *HttpAdapter) UnLock(w http.ResponseWriter, r *http.Request) { // X-WOPI-Lock header isn't needed on HTTP 200 } +// CheckFileInfo will retrieve the information of the file in json format +// Only the request's context is needed in order to extract the WOPI context. +// The operation's response will be sent through the response writer and +// the headers according to the spec func (h *HttpAdapter) CheckFileInfo(w http.ResponseWriter, r *http.Request) { fileCon := h.con.GetFileConnector() @@ -165,6 +191,9 @@ func (h *HttpAdapter) CheckFileInfo(w http.ResponseWriter, r *http.Request) { } } +// GetFile will download the file +// Only the request's context is needed in order to extract the WOPI context. +// The file's content will be written in the response writer func (h *HttpAdapter) GetFile(w http.ResponseWriter, r *http.Request) { contentCon := h.con.GetContentConnector() err := contentCon.GetFile(r.Context(), w) @@ -178,6 +207,11 @@ func (h *HttpAdapter) GetFile(w http.ResponseWriter, r *http.Request) { } } +// PutFile will upload the file +// The request's context and its body are needed (content length is also +// needed) +// The operation's response will be sent through the response writer and +// the headers according to the spec func (h *HttpAdapter) PutFile(w http.ResponseWriter, r *http.Request) { lockID := r.Header.Get(HeaderWopiLock) diff --git a/services/collaboration/pkg/helpers/discovery.go b/services/collaboration/pkg/helpers/discovery.go index 1af71c0854..893ca75685 100644 --- a/services/collaboration/pkg/helpers/discovery.go +++ b/services/collaboration/pkg/helpers/discovery.go @@ -13,6 +13,9 @@ import ( "github.com/pkg/errors" ) +// GetAppURLs gets the edit and view urls for different file types from the +// target WOPI app (onlyoffice, collabora, etc) via their "/hosting/discovery" +// endpoint. func GetAppURLs(cfg *config.Config, logger log.Logger) (map[string]map[string]string, error) { wopiAppUrl := cfg.WopiApp.Addr + "/hosting/discovery" @@ -58,6 +61,7 @@ func GetAppURLs(cfg *config.Config, logger log.Logger) (map[string]map[string]st return appURLs, nil } +// parseWopiDiscovery parses the response of the "/hosting/discovery" endpoint func parseWopiDiscovery(body io.Reader) (map[string]map[string]string, error) { appURLs := make(map[string]map[string]string) diff --git a/services/collaboration/pkg/middleware/claims.go b/services/collaboration/pkg/middleware/claims.go index 1e2b9adf62..893e19e940 100644 --- a/services/collaboration/pkg/middleware/claims.go +++ b/services/collaboration/pkg/middleware/claims.go @@ -2,6 +2,7 @@ package middleware import "github.com/golang-jwt/jwt/v4" +// Claims contains the jwt registered claims plus the used WOPI context type Claims struct { WopiContext WopiContext `json:"WopiContext"` jwt.RegisteredClaims diff --git a/services/collaboration/pkg/middleware/crypto.go b/services/collaboration/pkg/middleware/crypto.go index 8ab61a2730..c626aa677f 100644 --- a/services/collaboration/pkg/middleware/crypto.go +++ b/services/collaboration/pkg/middleware/crypto.go @@ -9,6 +9,9 @@ import ( "io" ) +// keyPadding will add the required zero padding to the provided key. +// The resulting key will have a length of either 16, 24 or 32 bytes. +// If the key has more than 32 bytes, only the first 32 bytes will be returned. func keyPadding(key []byte) []byte { switch length := len(key); { case length < 16: @@ -29,6 +32,9 @@ func keyPadding(key []byte) []byte { return []byte{} } +// EncryptAES encrypts the provided plainText using the provided key. +// AES CFB will be used as cryptographic method. +// Use DecryptAES to decrypt the resulting string func EncryptAES(key []byte, plainText string) (string, error) { src := []byte(plainText) @@ -49,6 +55,9 @@ func EncryptAES(key []byte, plainText string) (string, error) { return base64.URLEncoding.EncodeToString(cipherText), nil } +// DecryptAES decrypts the provided string using the provided key. +// The provided string must have been encrypted with AES CFB. +// This method will decrypt the result from the EncryptAES method func DecryptAES(key []byte, securemess string) (string, error) { cipherText, err := base64.URLEncoding.DecodeString(securemess) if err != nil { diff --git a/services/collaboration/pkg/middleware/wopicontext.go b/services/collaboration/pkg/middleware/wopicontext.go index 39134a0fa4..14d86c9303 100644 --- a/services/collaboration/pkg/middleware/wopicontext.go +++ b/services/collaboration/pkg/middleware/wopicontext.go @@ -21,6 +21,7 @@ const ( wopiContextKey key = iota ) +// WopiContext wraps all the information we need for WOPI type WopiContext struct { AccessToken string FileReference providerv1beta1.Reference @@ -30,6 +31,17 @@ type WopiContext struct { ViewAppUrl string } +// WopiContextAuthMiddleware will prepare an HTTP handler to be used as +// middleware. The handler will create a WopiContext by parsing the +// access_token (which must be provided as part of the URL query). +// The access_token is required. +// +// This middleware will add the following to the request's context: +// * The access token as metadata for outgoing requests (for the +// authentication against the CS3 API, the "x-access-token" header). +// * The created WopiContext for the request +// * A contextual zerologger containing information about the request +// and the WopiContext func WopiContextAuthMiddleware(jwtSecret string, next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { accessToken := r.URL.Query().Get("access_token") diff --git a/services/collaboration/pkg/server/http/server.go b/services/collaboration/pkg/server/http/server.go index e7ce3db96d..160c39bef4 100644 --- a/services/collaboration/pkg/server/http/server.go +++ b/services/collaboration/pkg/server/http/server.go @@ -86,6 +86,7 @@ func Server(opts ...Option) (http.Service, error) { return service, nil } +// prepareRoutes will prepare all the implemented routes func prepareRoutes(r *chi.Mux, options Options) { adapter := options.Adapter logger := options.Logger diff --git a/services/collaboration/pkg/service/grpc/v0/option.go b/services/collaboration/pkg/service/grpc/v0/option.go index 977ca05a94..3b89ec725b 100644 --- a/services/collaboration/pkg/service/grpc/v0/option.go +++ b/services/collaboration/pkg/service/grpc/v0/option.go @@ -17,6 +17,7 @@ type Options struct { Gwc gatewayv1beta1.GatewayAPIClient } +// newOptions initializes the available default options. func newOptions(opts ...Option) Options { opt := Options{} diff --git a/services/collaboration/pkg/service/grpc/v0/service.go b/services/collaboration/pkg/service/grpc/v0/service.go index 0083dad501..28d27b47fd 100644 --- a/services/collaboration/pkg/service/grpc/v0/service.go +++ b/services/collaboration/pkg/service/grpc/v0/service.go @@ -53,6 +53,7 @@ type Service struct { gwc gatewayv1beta1.GatewayAPIClient } +// OpenInApp will implement the OpenInApp interface of the app provider func (s *Service) OpenInApp( ctx context.Context, req *appproviderv1beta1.OpenInAppRequest,