Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Further work to be squashed to previous commit #150

Merged
merged 1 commit into from
Jun 29, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 68 additions & 29 deletions pkg/app/provider/wopi/wopi.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,10 @@ 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."`
MSOOURL string `mapstructure:"msoo_url" docs:";The MS Office Online URL."`
CodeURL string `mapstructure:"code_url" docs:";The Collabora Online URL."`
CodiMDURL string `mapstructure:"codimd_url" docs:";The CodiMD URL."`
CodiMDIntURL string `mapstructure:"codimd_int_url" docs:";The CodiMD internal URL."`
CodiMDApiKey string `mapstructure:"codimd_url" docs:";The CodiMD URL."`
AppName string `mapstructure:"app_name" docs:";The App user-friendly name."`
AppURL string `mapstructure:"app_url" docs:";The App URL."`
AppIntURL string `mapstructure:"app_int_url" docs:";The App internal URL in case of dockerized deployments. Defaults to AppURL"`
AppApiKey string `mapstructure:"app_apikey" docs:";The API key used by the App, if applicable."`
}

func parseConfig(m map[string]interface{}) (*config, error) {
Expand All @@ -66,9 +65,14 @@ type wopiProvider struct {
wopiClient *http.Client
}

func (p *wopiProvider) GetAppURL(ctx context.Context, resource *provider.ResourceInfo, viewMode appprovider.OpenInAppRequest_ViewMode, app, token string) (string, error) {
func (p *wopiProvider) GetAppURL(ctx context.Context, resource *provider.ResourceInfo, viewMode appprovider.OpenInAppRequest_ViewMode, app string, token string) (string, error) {
log := appctx.GetLogger(ctx)

if app != "" && app != p.conf.AppName {
// Sanity check
return "", errors.New("AppProvider for "+ p.conf.AppName +" cannot open in "+ app)
}

wopiurl, err := url.Parse(p.conf.WopiURL)
if err != nil {
return "", err
Expand All @@ -91,29 +95,20 @@ func (p *wopiProvider) GetAppURL(ctx context.Context, resource *provider.Resourc
q.Add("username", u.Username)
}
// else defaults to "Anonymous Guest"
if app == "" {
// Default behavior: look for the default app for this file's mimetype
// XXX TODO
app = "Collabora Online"
}
q.Add("appname", app)
if app == "CodiMD" {
// This is served by the WOPI bridge extensions
q.Add("appediturl", p.conf.CodiMDURL)
if p.conf.CodiMDIntURL != "" {
q.Add("appinturl", p.conf.CodiMDIntURL)
}
httpReq.Header.Set("ApiKey", p.conf.CodiMDApiKey)
} else {
// TODO get AppRegistry
//q.Add("appediturl", AppRegistry.get(app).getEditUrl())
//q.Add("appviewurl", AppRegistry.get(app).getViewUrl())
q.Add("appurl", p.conf.AppURL)
if p.conf.AppIntURL != "" {
q.Add("appinturl", p.conf.AppIntURL)
}
if p.conf.AppViewURL != "" {
q.Add("appviewurl", p.conf.AppViewURL)
}
if p.conf.ApiKey != "" {
httpReq.Header.Set("ApiKey", p.conf.AppApiKey)
}

if p.conf.IOPSecret == "" {
p.conf.IOPSecret = os.Getenv("REVA_APPPROVIDER_IOPSECRET")
}

httpReq.Header.Set("Authorization", "Bearer "+p.conf.IOPSecret)
httpReq.Header.Set("TokenHeader", token)

Expand All @@ -125,22 +120,66 @@ func (p *wopiProvider) GetAppURL(ctx context.Context, resource *provider.Resourc
defer openRes.Body.Close()

if openRes.StatusCode != http.StatusFound {
return "", errors.Wrap(err, "wopi: error performing open request to WOPI server, status: "+openRes.Status)
return "", errors.Wrap(err, "wopi: unexpected status from WOPI server: "+openRes.Status)
}
appURL := openRes.Header.Get("Location")
appFullURL := openRes.Header.Get("Location")

log.Info().Msg(fmt.Sprintf("wopi: returning app URL %s", appURL))
return appURL, nil
log.Info().Msg(fmt.Sprintf("wopi: returning app URL %s", appFullURL))
return appFullURL, nil
}

// New returns an implementation of the app.Provider interface that
// connects to an application in the backend.
func New(m map[string]interface{}) (app.Provider, error) {
func New(m map[string]interface{})() (app.Provider, error) {
c, err := parseConfig(m)
if err != nil {
return nil, err
}

// Initialize WOPI URLs by discovery
httpcl := rhttp.GetHTTPClient(
rhttp.Timeout(time.Duration(5 * int64(time.Second))),
)
if c.AppIntURL == "" {
c.AppIntURL = c.AppURL
}
appurl, err := url.Parse(c.AppIntURL)
if err != nil {
return nil, err
}
appurl.Path = path.Join(c.AppIntURL.Path, "/hosting/discovery")
discReq, err := rhttp.NewRequest(ctx, "GET", appurl, nil)
if err != nil {
return nil, err
}
discRes, err := httpcl.Do(discReq)
if err != nil {
return nil, err
}
defer discRes.Body.Close()
if discRes.StatusCode == http.StatusNotFound) {
// this may be a bridge-supported app, let's find out
discReq, err := rhttp.NewRequest(ctx, "GET", c.AppIntURL, nil)
if err != nil {
return nil, err
}
discRes, err := httpcl.Do(discReq)
if err != nil {
return nil, err
}
defer discRes.Body.Close()
// scrape app's home page to find the appname
if !discRes.Body.Find(c.AppName) {
// || (c.AppName != "CodiMD" && c.AppName != "Etherpad") {
return nil, errors.New("Application server at " + c.AppURL + " does not match this AppProvider for "+ c.AppName)
}
} else {
// TODO parse XML from discRes.Body
c.AppEditURL := "bla"
c.AppViewURL := "bla"
// TODO register all supported mimetypes in the AppRegistry
}

wopiClient := rhttp.GetHTTPClient(
rhttp.Timeout(time.Duration(5 * int64(time.Second))),
)
Expand Down