Skip to content

Commit

Permalink
Moved custom JSON parsing to the appprovider, and removed hardcoded c…
Browse files Browse the repository at this point in the history
…onfig
  • Loading branch information
glpatcern committed Oct 26, 2022
1 parent f7a8012 commit 238f346
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 80 deletions.
56 changes: 46 additions & 10 deletions internal/grpc/services/appprovider/appprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ package appprovider

import (
"context"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"strconv"
"time"
Expand All @@ -33,6 +36,7 @@ import (
"github.com/cs3org/reva/pkg/app/provider/registry"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/logger"
"github.com/cs3org/reva/pkg/mime"
"github.com/cs3org/reva/pkg/rgrpc"
"github.com/cs3org/reva/pkg/rgrpc/status"
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
Expand All @@ -52,13 +56,14 @@ type service struct {
}

type config struct {
Driver string `mapstructure:"driver"`
Drivers map[string]map[string]interface{} `mapstructure:"drivers"`
AppProviderURL string `mapstructure:"app_provider_url"`
GatewaySvc string `mapstructure:"gatewaysvc"`
MimeTypes []string `mapstructure:"mime_types"`
Priority uint64 `mapstructure:"priority"`
Language string `mapstructure:"language"`
Driver string `mapstructure:"driver"`
Drivers map[string]map[string]interface{} `mapstructure:"drivers"`
AppProviderURL string `mapstructure:"app_provider_url"`
GatewaySvc string `mapstructure:"gatewaysvc"`
MimeTypes []string `mapstructure:"mime_types" docs:"nil;A list of mime types supported by this app."`
CustomMimeTypesJSON string `mapstructure:"custom_mime_types_json" docs:"nil;An optional mapping file with the list of supported custom file extensions and corresponding mime types."`
Priority uint64 `mapstructure:"priority"`
Language string `mapstructure:"language"`
}

func (c *config) init() {
Expand All @@ -85,6 +90,12 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) {
return nil, err
}

// read and register custom mime types if configured
err = registerMimeTypes(c.CustomMimeTypesJSON)
if err != nil {
return nil, err
}

provider, err := getProvider(c)
if err != nil {
return nil, err
Expand All @@ -99,9 +110,31 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) {
return service, nil
}

func registerMimeTypes(mappingFile string) error {
// TODO(lopresti) this function also exists in the storage provider, to be seen if we want to factor it out, though a
// fileext <-> mimetype "service" would have to be served by the gateway for it to be accessible both by storage providers and app providers.
if mappingFile != "" {
f, err := ioutil.ReadFile(mappingFile)
if err != nil {
return fmt.Errorf("appprovider: error reading the custom mime types file: +%v", err)
}
mimeTypes := map[string]string{}
err = json.Unmarshal(f, &mimeTypes)
if err != nil {
return fmt.Errorf("appprovider: error unmarshalling the custom mime types file: +%v", err)
}
// register all mime types that were read
for e, m := range mimeTypes {
mime.RegisterMime(e, m)
}
}
return nil
}

func (s *service) registerProvider() {
// Give the appregistry service time to come up
time.Sleep(2 * time.Second)
// TODO(lopresti) we should register the appproviders after all other microservices
time.Sleep(3 * time.Second)

ctx := context.Background()
log := logger.New().With().Int("pid", os.Getpid()).Logger()
Expand All @@ -119,6 +152,7 @@ func (s *service) registerProvider() {
mimeTypes = append(mimeTypes, m.(string))
}
pInfo.MimeTypes = mimeTypes
log.Info().Msgf("appprovider: %s will support %+v", s.conf.AppProviderURL, mimeTypes)
}

client, err := pool.GetGatewayServiceClient(pool.Endpoint(s.conf.GatewaySvc))
Expand Down Expand Up @@ -165,7 +199,10 @@ func (s *service) Register(ss *grpc.Server) {

func getProvider(c *config) (app.Provider, error) {
if f, ok := registry.NewFuncs[c.Driver]; ok {
return f(c.Drivers[c.Driver])
driverConf := c.Drivers[c.Driver]
// share the mime_types config entry to the drivers
driverConf["mime_types"] = c.MimeTypes
return f(driverConf)
}
return nil, errtypes.NotFound("driver not found: " + c.Driver)
}
Expand All @@ -183,5 +220,4 @@ func (s *service) OpenInApp(ctx context.Context, req *providerpb.OpenInAppReques
AppUrl: appURL,
}
return res, nil

}
96 changes: 26 additions & 70 deletions pkg/app/provider/wopi/wopi.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,17 @@ func init() {
}

type config struct {
IOPSecret string `mapstructure:"iop_secret" docs:";The IOP secret used to connect to the wopiserver."`
WopiURL string `mapstructure:"wopi_url" docs:";The wopiserver's URL."`
AppName string `mapstructure:"app_name" docs:";The App user-friendly name."`
AppIconURI string `mapstructure:"app_icon_uri" docs:";A URI to a static asset which represents the app icon."`
AppURL string `mapstructure:"app_url" docs:";The App URL."`
AppIntURL string `mapstructure:"app_int_url" docs:";The internal app URL in case of dockerized deployments. Defaults to AppURL"`
AppAPIKey string `mapstructure:"app_api_key" docs:";The API key used by the app, if applicable."`
JWTSecret string `mapstructure:"jwt_secret" docs:";The JWT secret to be used to retrieve the token TTL."`
CustomMimeTypesJSON string `mapstructure:"custom_mime_types_json" docs:"nil;An optional mapping file with the list of supported custom file extensions and corresponding mime types."`
AppDesktopOnly bool `mapstructure:"app_desktop_only" docs:"false;Specifies if the app can be opened only on desktop."`
InsecureConnections bool `mapstructure:"insecure_connections"`
MimeTypes []string `mapstructure:"mime_types" docs:";Inherited from the appprovider."`
IOPSecret string `mapstructure:"iop_secret" docs:";The IOP secret used to connect to the wopiserver."`
WopiURL string `mapstructure:"wopi_url" docs:";The wopiserver's URL."`
AppName string `mapstructure:"app_name" docs:";The App user-friendly name."`
AppIconURI string `mapstructure:"app_icon_uri" docs:";A URI to a static asset which represents the app icon."`
AppURL string `mapstructure:"app_url" docs:";The App URL."`
AppIntURL string `mapstructure:"app_int_url" docs:";The internal app URL in case of dockerized deployments. Defaults to AppURL"`
AppAPIKey string `mapstructure:"app_api_key" docs:";The API key used by the app, if applicable."`
JWTSecret string `mapstructure:"jwt_secret" docs:";The JWT secret to be used to retrieve the token TTL."`
AppDesktopOnly bool `mapstructure:"app_desktop_only" docs:"false;Specifies if the app can be opened only on desktop."`
InsecureConnections bool `mapstructure:"insecure_connections"`
}

func parseConfig(m map[string]interface{}) (*config, error) {
Expand Down Expand Up @@ -112,12 +112,6 @@ func New(m map[string]interface{}) (app.Provider, error) {
return http.ErrUseLastResponse
}

// read and register custom mime types if configured
err = registerMimeTypes(c.CustomMimeTypesJSON)
if err != nil {
return nil, err
}

return &wopiProvider{
conf: c,
wopiClient: wopiClient,
Expand Down Expand Up @@ -265,7 +259,7 @@ func (p *wopiProvider) GetAppURL(ctx context.Context, resource *provider.Resourc
}
}

log.Info().Msg(fmt.Sprintf("wopi: returning app URL %s", appFullURL))
log.Info().Msgf("wopi: returning app URL %s", appFullURL)
return &appprovider.OpenInAppURL{
AppUrl: appFullURL,
Method: method,
Expand Down Expand Up @@ -296,27 +290,6 @@ func (p *wopiProvider) GetAppProviderInfo(ctx context.Context) (*appregistry.Pro
}, nil
}

func registerMimeTypes(mappingFile string) error {
// TODO(lopresti) this function also exists in the storage provider, to be seen if we want to factor it out, though a
// fileext <-> mimetype "service" would have to be served by the gateway for it to be accessible both by storage providers and app providers.
if mappingFile != "" {
f, err := ioutil.ReadFile(mappingFile)
if err != nil {
return fmt.Errorf("storageprovider: error reading the custom mime types file: +%v", err)
}
mimeTypes := map[string]string{}
err = json.Unmarshal(f, &mimeTypes)
if err != nil {
return fmt.Errorf("storageprovider: error unmarshalling the custom mime types file: +%v", err)
}
// register all mime types that were read
for e, m := range mimeTypes {
mime.RegisterMime(e, m)
}
}
return nil
}

func getAppURLs(c *config) (map[string]map[string]string, error) {
// Initialize WOPI URLs by discovery
httpcl := rhttp.GetHTTPClient(
Expand Down Expand Up @@ -370,15 +343,19 @@ func getAppURLs(c *config) (map[string]map[string]string, error) {
return nil, errors.New("Application server at " + c.AppURL + " does not match this AppProvider for " + c.AppName)
}

// register the supported mimetypes in the AppRegistry: this is hardcoded for the time being
// TODO(lopresti) move to config
switch c.AppName {
case "CodiMD":
appURLs = getCodimdExtensions(c.AppURL)
case "Etherpad":
appURLs = getEtherpadExtensions(c.AppURL)
default:
return nil, errors.New("Application server " + c.AppName + " running at " + c.AppURL + " is unsupported")
// TODO(lopresti) we don't know if the app is not supported/configured in WOPI
// return nil, errors.New("Application server " + c.AppName + " running at " + c.AppURL + " is unsupported")

// generate the map of supported extensions
appURLs = make(map[string]map[string]string)
appURLs["view"] = make(map[string]string)
appURLs["edit"] = make(map[string]string)
for _, m := range c.MimeTypes {
exts := mime.GetFileExt(m)
for _, e := range exts {
appURLs["view"]["."+e] = c.AppURL
appURLs["edit"]["."+e] = c.AppURL
}
}
}
return appURLs, nil
Expand All @@ -394,7 +371,7 @@ func (p *wopiProvider) getAccessTokenTTL(ctx context.Context) (string, error) {
}

if claims, ok := token.Claims.(*jwt.StandardClaims); ok && token.Valid {
// milliseconds since Jan 1, 1970 UTC as required in https://wopi.readthedocs.io/projects/wopirest/en/latest/concepts.html?highlight=access_token_ttl#term-access-token-ttl
// milliseconds since Jan 1, 1970 UTC as required in https://learn.microsoft.com/en-us/microsoft-365/cloud-storage-partner-program/rest/concepts#the-access_token_ttl-property
return strconv.FormatInt(claims.ExpiresAt*1000, 10), nil
}

Expand Down Expand Up @@ -456,24 +433,3 @@ func parseWopiDiscovery(body io.Reader) (map[string]map[string]string, error) {
}
return appURLs, nil
}

func getCodimdExtensions(appURL string) map[string]map[string]string {
// Register custom mime types
mime.RegisterMime(".zmd", "application/compressed-markdown")

appURLs := make(map[string]map[string]string)
appURLs["edit"] = map[string]string{
".txt": appURL,
".md": appURL,
".zmd": appURL,
}
return appURLs
}

func getEtherpadExtensions(appURL string) map[string]map[string]string {
appURLs := make(map[string]map[string]string)
appURLs["edit"] = map[string]string{
".epd": appURL,
}
return appURLs
}

0 comments on commit 238f346

Please sign in to comment.