refactor: move components to setup the service into a helpers package
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
gatewayv1beta1 "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
|
||||
"github.com/owncloud/ocis/v2/services/collaboration/pkg/config"
|
||||
)
|
||||
|
||||
var commonCS3ApiClient gatewayv1beta1.GatewayAPIClient
|
||||
|
||||
func GetCS3apiClient(cfg *config.Config, forceNew bool) (gatewayv1beta1.GatewayAPIClient, error) {
|
||||
// establish a connection to the cs3 api endpoint
|
||||
// in this case a REVA gateway, started by oCIS
|
||||
if commonCS3ApiClient != nil && !forceNew {
|
||||
return commonCS3ApiClient, nil
|
||||
}
|
||||
|
||||
client, err := pool.GetGatewayServiceClient(cfg.CS3Api.Gateway.Name)
|
||||
if err == nil {
|
||||
commonCS3ApiClient = client
|
||||
}
|
||||
return client, err
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/beevik/etree"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
"github.com/owncloud/ocis/v2/services/collaboration/pkg/config"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func GetAppURLs(cfg *config.Config, logger log.Logger) (map[string]map[string]string, error) {
|
||||
wopiAppUrl := cfg.WopiApp.Addr + "/hosting/discovery"
|
||||
|
||||
httpClient := http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: cfg.WopiApp.Insecure,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
httpResp, err := httpClient.Get(wopiAppUrl)
|
||||
if err != nil {
|
||||
logger.Error().
|
||||
Err(err).
|
||||
Str("WopiAppUrl", wopiAppUrl).
|
||||
Msg("WopiDiscovery: failed to access wopi app url")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer httpResp.Body.Close()
|
||||
|
||||
if httpResp.StatusCode != http.StatusOK {
|
||||
logger.Error().
|
||||
Str("WopiAppUrl", wopiAppUrl).
|
||||
Int("HttpCode", httpResp.StatusCode).
|
||||
Msg("WopiDiscovery: wopi app url failed with unexpected code")
|
||||
return nil, errors.New("status code was not 200")
|
||||
}
|
||||
|
||||
var appURLs map[string]map[string]string
|
||||
|
||||
appURLs, err = parseWopiDiscovery(httpResp.Body)
|
||||
if err != nil {
|
||||
logger.Error().
|
||||
Err(err).
|
||||
Str("WopiAppUrl", wopiAppUrl).
|
||||
Msg("WopiDiscovery: failed to parse wopi discovery response")
|
||||
return nil, errors.Wrap(err, "error parsing wopi discovery response")
|
||||
}
|
||||
|
||||
// TODO: Log appUrls? not easy with the format
|
||||
// It's also a one-time call during service setup, so it's pointless
|
||||
// to use an "all-is-good" debug log
|
||||
return appURLs, nil
|
||||
}
|
||||
|
||||
func parseWopiDiscovery(body io.Reader) (map[string]map[string]string, error) {
|
||||
appURLs := make(map[string]map[string]string)
|
||||
|
||||
doc := etree.NewDocument()
|
||||
if _, err := doc.ReadFrom(body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
root := doc.SelectElement("wopi-discovery")
|
||||
|
||||
for _, netzone := range root.SelectElements("net-zone") {
|
||||
|
||||
if strings.Contains(netzone.SelectAttrValue("name", ""), "external") {
|
||||
for _, app := range netzone.SelectElements("app") {
|
||||
for _, action := range app.SelectElements("action") {
|
||||
access := action.SelectAttrValue("name", "")
|
||||
if access == "view" || access == "edit" {
|
||||
ext := action.SelectAttrValue("ext", "")
|
||||
urlString := action.SelectAttrValue("urlsrc", "")
|
||||
|
||||
if ext == "" || urlString == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
u, err := url.Parse(urlString)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// remove any malformed query parameter from discovery urls
|
||||
q := u.Query()
|
||||
for k := range q {
|
||||
if strings.Contains(k, "<") || strings.Contains(k, ">") {
|
||||
q.Del(k)
|
||||
}
|
||||
}
|
||||
|
||||
u.RawQuery = q.Encode()
|
||||
|
||||
if _, ok := appURLs[access]; !ok {
|
||||
appURLs[access] = make(map[string]string)
|
||||
}
|
||||
appURLs[access]["."+ext] = u.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return appURLs, nil
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
registryv1beta1 "github.com/cs3org/go-cs3apis/cs3/app/registry/v1beta1"
|
||||
gatewayv1beta1 "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
||||
"github.com/cs3org/reva/v2/pkg/mime"
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
|
||||
"github.com/owncloud/ocis/v2/services/collaboration/pkg/config"
|
||||
)
|
||||
|
||||
func RegisterOcisService(ctx context.Context, cfg *config.Config, logger log.Logger) error {
|
||||
svc := registry.BuildGRPCService(cfg.Service.Name, uuid.Must(uuid.NewV4()).String(), cfg.GRPC.Addr, "0.0.0")
|
||||
return registry.RegisterService(ctx, svc, logger)
|
||||
}
|
||||
|
||||
func RegisterAppProvider(
|
||||
ctx context.Context,
|
||||
cfg *config.Config,
|
||||
logger log.Logger,
|
||||
gwc gatewayv1beta1.GatewayAPIClient,
|
||||
appUrls map[string]map[string]string,
|
||||
) error {
|
||||
mimeTypesMap := make(map[string]bool)
|
||||
for _, extensions := range appUrls {
|
||||
for ext := range extensions {
|
||||
m := mime.Detect(false, ext)
|
||||
mimeTypesMap[m] = true
|
||||
}
|
||||
}
|
||||
|
||||
mimeTypes := make([]string, 0, len(mimeTypesMap))
|
||||
for m := range mimeTypesMap {
|
||||
mimeTypes = append(mimeTypes, m)
|
||||
}
|
||||
|
||||
logger.Debug().
|
||||
Str("AppName", cfg.App.Name).
|
||||
Strs("Mimetypes", mimeTypes).
|
||||
Msg("Registering mimetypes in the app provider")
|
||||
// TODO: REVA has way to filter supported mimetypes (do we need to implement it here or is it in the registry?)
|
||||
|
||||
// TODO: an added app provider shouldn't last forever. Instead the registry should use a TTL
|
||||
// and delete providers that didn't register again. If an app provider dies or get's disconnected,
|
||||
// the users will be no longer available to choose to open a file with it (currently, opening a file just fails)
|
||||
req := ®istryv1beta1.AddAppProviderRequest{
|
||||
Provider: ®istryv1beta1.ProviderInfo{
|
||||
Name: cfg.App.Name,
|
||||
Description: cfg.App.Description,
|
||||
Icon: cfg.App.Icon,
|
||||
Address: cfg.Service.Name,
|
||||
MimeTypes: mimeTypes,
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := gwc.AddAppProvider(ctx, req)
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("AddAppProvider failed")
|
||||
return err
|
||||
}
|
||||
|
||||
if resp.Status.Code != rpcv1beta1.Code_CODE_OK {
|
||||
logger.Error().Str("status_code", resp.Status.Code.String()).Msg("AddAppProvider failed")
|
||||
return errors.New("status code != CODE_OK")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user