From 61bff266cf48318073e7db26de625d28a21cc05e Mon Sep 17 00:00:00 2001 From: Giuseppe Lo Presti Date: Fri, 17 Sep 2021 11:03:26 +0200 Subject: [PATCH] Adding the /app/new endpoint --- .../grpc/services/appprovider/appprovider.go | 18 ++++++++ internal/grpc/services/gateway/appprovider.go | 44 +++++++++++++++++++ .../http/services/appprovider/appprovider.go | 44 +++++++++++++++++++ pkg/app/app.go | 3 +- pkg/app/provider/demo/demo.go | 6 +++ pkg/app/provider/wopi/wopi.go | 8 +++- 6 files changed, 121 insertions(+), 2 deletions(-) diff --git a/internal/grpc/services/appprovider/appprovider.go b/internal/grpc/services/appprovider/appprovider.go index 8dd446d704c..adbf4760d15 100644 --- a/internal/grpc/services/appprovider/appprovider.go +++ b/internal/grpc/services/appprovider/appprovider.go @@ -142,6 +142,24 @@ func getProvider(c *config) (app.Provider, error) { return nil, errtypes.NotFound("driver not found: " + c.Driver) } +func (s *service) CreateFileForApp(ctx context.Context, req *providerpb.CreateFileForAppRequest) (*providerpb.CreateFileForAppResponse, error) { + fileInfo, err := s.provider.CreateFile(ctx, req.Ref, req.Filename) + if err != nil { + err := errors.Wrap(err, "appprovider: error calling CreateFile") + res := &providerpb.CreateFileForAppResponse{ + Status: status.NewInternal(ctx, err, "error creating file"), + } + return res, nil + } + + res := &providerpb.OpenInAppResponse{ + Status: status.NewOK(ctx), + ResourceInfo: fileInfo, + } + return res, nil + +} + func (s *service) OpenInApp(ctx context.Context, req *providerpb.OpenInAppRequest) (*providerpb.OpenInAppResponse, error) { appURL, err := s.provider.GetAppURL(ctx, req.ResourceInfo, req.ViewMode, req.AccessToken) if err != nil { diff --git a/internal/grpc/services/gateway/appprovider.go b/internal/grpc/services/gateway/appprovider.go index b834968ced5..8c555f6c9cf 100644 --- a/internal/grpc/services/gateway/appprovider.go +++ b/internal/grpc/services/gateway/appprovider.go @@ -42,6 +42,50 @@ import ( "google.golang.org/grpc/metadata" ) +func (s *svc) CreateFileForApp(ctx context.Context, req *providerpb.CreateFileForAppRequest) (*providerpb.CreateFileForAppResponse, error) { + p, st := s.getPath(ctx, req.Ref) + if st.Code != rpc.Code_CODE_OK { + if st.Code == rpc.Code_CODE_NOT_FOUND { + return &providerpb.CreateFileForAppResponse{ + Status: status.NewNotFound(ctx, "gateway: container resource not found:"+req.Ref.String()), + }, nil + } + return &providerpb.CreateFileForAppResponse{ + Status: st, + }, nil + } + + // TODO identify app provider, not like this + provider, err := s.findAppProvider(ctx, ri, app) + if err != nil { + err = errors.Wrap(err, "gateway: error calling findAppProvider") + var st *rpc.Status + if _, ok := err.(errtypes.IsNotFound); ok { + st = status.NewNotFound(ctx, "app provider not found") + } else { + st = status.NewInternal(ctx, err, "error searching for app provider") + } + return &providerpb.CreateFileForAppResponse{ + Status: st, + }, nil + } + + appProviderClient, err := pool.GetAppProviderClient(provider.Address) + if err != nil { + err = errors.Wrap(err, "gateway: error calling GetAppProviderClient") + return &providerpb.CreateFileForAppResponse{ + Status: status.NewInternal(ctx, err, "error getting appprovider client"), + }, nil + } + + res, err := appProviderClient.CreateFileForApp(ctx, req) + if err != nil { + return nil, errors.Wrap(err, "gateway: error calling CreateFileForApp") + } + + return res, nil +} + func (s *svc) OpenInApp(ctx context.Context, req *gateway.OpenInAppRequest) (*providerpb.OpenInAppResponse, error) { p, st := s.getPath(ctx, req.Ref) if st.Code != rpc.Code_CODE_OK { diff --git a/internal/http/services/appprovider/appprovider.go b/internal/http/services/appprovider/appprovider.go index a632f50d154..a1d09a0c8a5 100644 --- a/internal/http/services/appprovider/appprovider.go +++ b/internal/http/services/appprovider/appprovider.go @@ -102,6 +102,8 @@ func (s *svc) Handler() http.Handler { s.handleList(w, r) case "open": s.handleOpen(w, r) + case "new": + s.handleNew(w, r) } }) } @@ -182,6 +184,48 @@ func (s *svc) handleOpen(w http.ResponseWriter, r *http.Request) { } } +func (s *svc) handleNew(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + client, err := pool.GetGatewayServiceClient(s.conf.GatewaySvc) + if err != nil { + ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error getting grpc gateway client", err) + return + } + + info, errCode, err := s.getStatInfo(ctx, r.URL.Query().Get("container"), client) + if err != nil { + ocmd.WriteError(w, r, errCode, "error statting container", err) + return + } + + createReq := gateway.CreateFileForAppRequest{ + Ref: &provider.Reference{ResourceId: info.Id}, + Filename: r.URL.Query().Get("filename"), + } + createRes, err := client.CreateFileForApp(ctx, &createReq) + if err != nil { + ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error opening resource", err) + return + } + if createRes.Status.Code != rpc.Code_CODE_OK { + ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error opening resource information", status.NewErrorFromCode(openRes.Status.Code, "appprovider")) + return + } + + js, err := json.Marshal(createRes.resourceInfo.info) + if err != nil { + ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error marshalling JSON response", err) + return + } + + w.Header().Set("Content-Type", "application/json") + if _, err = w.Write(js); err != nil { + ocmd.WriteError(w, r, ocmd.APIErrorServerError, "error writing JSON response", err) + return + } +} + func filterAppsByUserAgent(mimeTypes *appregistry.MimeTypeList, userAgent string) { ua := ua.Parse(userAgent) res := []*appregistry.MimeTypeInfo{} diff --git a/pkg/app/app.go b/pkg/app/app.go index f99dcef71f9..f248881f173 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -38,8 +38,9 @@ type Registry interface { } // Provider is the interface that application providers implement -// for providing the URL of the app which will serve the requested resource. +// for interacting with external apps that serve the requested resource. type Provider interface { + CreateFile(ctx context.Context, ref *provider.Reference, filename string) (*provider.ResourceInfo, error) GetAppURL(ctx context.Context, resource *provider.ResourceInfo, viewMode appprovider.OpenInAppRequest_ViewMode, token string) (*appprovider.OpenInAppURL, error) GetAppProviderInfo(ctx context.Context) (*registry.ProviderInfo, error) } diff --git a/pkg/app/provider/demo/demo.go b/pkg/app/provider/demo/demo.go index 254dd868ae9..ccf77cfa3c1 100644 --- a/pkg/app/provider/demo/demo.go +++ b/pkg/app/provider/demo/demo.go @@ -39,6 +39,12 @@ type demoProvider struct { iframeUIProvider string } +func (p *demoProvider) CreateFile(ctx context.Context, ref *provider.Reference, filename string) (*provider.ResourceInfo, error) + return &provider.ResourceInfo{ + ... + }, nil +} + func (p *demoProvider) GetAppURL(ctx context.Context, resource *provider.ResourceInfo, viewMode appprovider.OpenInAppRequest_ViewMode, token string) (*appprovider.OpenInAppURL, error) { url := fmt.Sprintf("