|
|
@ -6,6 +6,7 @@ import ( |
|
|
|
model "github.com/cloudreve/Cloudreve/v3/models" |
|
|
|
"github.com/cloudreve/Cloudreve/v3/pkg/cache" |
|
|
|
"github.com/cloudreve/Cloudreve/v3/pkg/request" |
|
|
|
"github.com/cloudreve/Cloudreve/v3/pkg/util" |
|
|
|
"net/url" |
|
|
|
"path" |
|
|
|
"strings" |
|
|
@ -13,11 +14,18 @@ import ( |
|
|
|
) |
|
|
|
|
|
|
|
type Client interface { |
|
|
|
// NewSession creates a new document session with access token.
|
|
|
|
NewSession(user *model.User, file *model.File, action ActonType) (*Session, error) |
|
|
|
// AvailableExts returns a list of file extensions that are supported by WOPI.
|
|
|
|
AvailableExts() []string |
|
|
|
} |
|
|
|
|
|
|
|
var ( |
|
|
|
ErrActionNotSupported = errors.New("action not supported by current wopi endpoint") |
|
|
|
|
|
|
|
Default Client |
|
|
|
DefaultMu sync.Mutex |
|
|
|
|
|
|
|
queryPlaceholders = map[string]string{ |
|
|
|
"BUSINESS_USER": "", |
|
|
|
"DC_LLCC": "lng", |
|
|
@ -38,6 +46,24 @@ const ( |
|
|
|
wopiSrcPlaceholder = "WOPI_SOURCE" |
|
|
|
) |
|
|
|
|
|
|
|
// Init initializes a new global WOPI client.
|
|
|
|
func Init() { |
|
|
|
settings := model.GetSettingByNames("wopi_endpoint", "wopi_enabled") |
|
|
|
if !model.IsTrueVal(settings["wopi_enabled"]) { |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
wopiClient, err := NewClient(settings["wopi_endpoint"], cache.Store, request.NewClient()) |
|
|
|
if err != nil { |
|
|
|
util.Log().Error("Failed to initialize WOPI client: %s", err) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
DefaultMu.Lock() |
|
|
|
Default = wopiClient |
|
|
|
DefaultMu.Unlock() |
|
|
|
} |
|
|
|
|
|
|
|
type client struct { |
|
|
|
cache cache.Driver |
|
|
|
http request.Client |
|
|
@ -53,6 +79,21 @@ type config struct { |
|
|
|
discoveryEndpoint *url.URL |
|
|
|
} |
|
|
|
|
|
|
|
func NewClient(endpoint string, cache cache.Driver, http request.Client) (Client, error) { |
|
|
|
endpointUrl, err := url.Parse(endpoint) |
|
|
|
if err != nil { |
|
|
|
return nil, fmt.Errorf("failed to parse WOPI endpoint: %s", err) |
|
|
|
} |
|
|
|
|
|
|
|
return &client{ |
|
|
|
cache: cache, |
|
|
|
http: http, |
|
|
|
config: config{ |
|
|
|
discoveryEndpoint: endpointUrl, |
|
|
|
}, |
|
|
|
}, nil |
|
|
|
} |
|
|
|
|
|
|
|
func (c *client) NewSession(user *model.User, file *model.File, action ActonType) (*Session, error) { |
|
|
|
if err := c.checkDiscovery(); err != nil { |
|
|
|
return nil, err |
|
|
@ -79,6 +120,8 @@ func (c *client) NewSession(user *model.User, file *model.File, action ActonType |
|
|
|
return nil, nil |
|
|
|
} |
|
|
|
|
|
|
|
// Replace query parameters in action URL template. Some placeholders need to be replaced
|
|
|
|
// at the frontend, e.g. `THEME_ID`.
|
|
|
|
func generateActionUrl(src string, fileSrc string) (*url.URL, error) { |
|
|
|
src = strings.ReplaceAll(src, "<", "") |
|
|
|
src = strings.ReplaceAll(src, ">", "") |
|
|
|