[MM-48523] Expose resumable uploads API to plugins (#21700)

* Expose resumable uploads API to plugins

* Update translations
Этот коммит содержится в:
Claudio Costa
2022-11-22 15:26:22 -06:00
коммит произвёл GitHub
родитель a1e16f7b02
Коммит 0509e78744
13 изменённых файлов: 362 добавлений и 19 удалений

Просмотреть файл

@@ -1168,6 +1168,24 @@ type API interface {
//
// Minimum server version: 7.6
RegisterCollectionAndTopic(collectionType, topicType string) error
// CreateUploadSession creates and returns a new (resumable) upload session.
//
// @tag Upload
// Minimum server version: 7.6
CreateUploadSession(us *model.UploadSession) (*model.UploadSession, error)
// UploadData uploads the data for a given upload session.
//
// @tag Upload
// Minimum server version: 7.6
UploadData(us *model.UploadSession, rd io.Reader) (*model.FileInfo, error)
// GetUploadSession returns the upload session for the provided id.
//
// @tag Upload
// Minimum server version: 7.6
GetUploadSession(uploadID string) (*model.UploadSession, error)
}
var handshake = plugin.HandshakeConfig{

Просмотреть файл

@@ -1246,3 +1246,24 @@ func (api *apiTimerLayer) RegisterCollectionAndTopic(collectionType, topicType s
api.recordTime(startTime, "RegisterCollectionAndTopic", _returnsA == nil)
return _returnsA
}
func (api *apiTimerLayer) CreateUploadSession(us *model.UploadSession) (*model.UploadSession, error) {
startTime := timePkg.Now()
_returnsA, _returnsB := api.apiImpl.CreateUploadSession(us)
api.recordTime(startTime, "CreateUploadSession", _returnsB == nil)
return _returnsA, _returnsB
}
func (api *apiTimerLayer) UploadData(us *model.UploadSession, rd io.Reader) (*model.FileInfo, error) {
startTime := timePkg.Now()
_returnsA, _returnsB := api.apiImpl.UploadData(us, rd)
api.recordTime(startTime, "UploadData", _returnsB == nil)
return _returnsA, _returnsB
}
func (api *apiTimerLayer) GetUploadSession(uploadID string) (*model.UploadSession, error) {
startTime := timePkg.Now()
_returnsA, _returnsB := api.apiImpl.GetUploadSession(uploadID)
api.recordTime(startTime, "GetUploadSession", _returnsB == nil)
return _returnsA, _returnsB
}

Просмотреть файл

@@ -866,3 +866,55 @@ func (s *apiRPCServer) InstallPlugin(args *Z_InstallPluginArgs, returns *Z_Insta
returns.A, returns.B = hook.InstallPlugin(pluginReader, args.B)
return nil
}
type Z_UploadDataArgs struct {
A *model.UploadSession
PluginStreamID uint32
}
type Z_UploadDataReturns struct {
A *model.FileInfo
B error
}
func (g *apiRPCClient) UploadData(us *model.UploadSession, rd io.Reader) (*model.FileInfo, error) {
pluginStreamID := g.muxBroker.NextId()
go func() {
pluginConnection, err := g.muxBroker.Accept(pluginStreamID)
if err != nil {
log.Print("Failed to upload data. MuxBroker could not Accept connection", mlog.Err(err))
return
}
defer pluginConnection.Close()
serveIOReader(rd, pluginConnection)
}()
_args := &Z_UploadDataArgs{us, pluginStreamID}
_returns := &Z_UploadDataReturns{}
if err := g.client.Call("Plugin.UploadData", _args, _returns); err != nil {
log.Print("RPC call UploadData to plugin failed.", mlog.Err(err))
}
return _returns.A, _returns.B
}
func (s *apiRPCServer) UploadData(args *Z_UploadDataArgs, returns *Z_UploadDataReturns) error {
hook, ok := s.impl.(interface {
UploadData(us *model.UploadSession, rd io.Reader) (*model.FileInfo, error)
})
if !ok {
return encodableError(fmt.Errorf("API UploadData called but not implemented"))
}
receivePluginConnection, err := s.muxBroker.Dial(args.PluginStreamID)
if err != nil {
fmt.Fprintf(os.Stderr, "[ERROR] Can't connect to remote plugin stream, error: %v", err.Error())
return err
}
pluginReader := connectIOReader(receivePluginConnection)
defer pluginReader.Close()
returns.A, returns.B = hook.UploadData(args.A, pluginReader)
return nil
}

Просмотреть файл

@@ -5968,3 +5968,63 @@ func (s *apiRPCServer) RegisterCollectionAndTopic(args *Z_RegisterCollectionAndT
}
return nil
}
type Z_CreateUploadSessionArgs struct {
A *model.UploadSession
}
type Z_CreateUploadSessionReturns struct {
A *model.UploadSession
B error
}
func (g *apiRPCClient) CreateUploadSession(us *model.UploadSession) (*model.UploadSession, error) {
_args := &Z_CreateUploadSessionArgs{us}
_returns := &Z_CreateUploadSessionReturns{}
if err := g.client.Call("Plugin.CreateUploadSession", _args, _returns); err != nil {
log.Printf("RPC call to CreateUploadSession API failed: %s", err.Error())
}
return _returns.A, _returns.B
}
func (s *apiRPCServer) CreateUploadSession(args *Z_CreateUploadSessionArgs, returns *Z_CreateUploadSessionReturns) error {
if hook, ok := s.impl.(interface {
CreateUploadSession(us *model.UploadSession) (*model.UploadSession, error)
}); ok {
returns.A, returns.B = hook.CreateUploadSession(args.A)
returns.B = encodableError(returns.B)
} else {
return encodableError(fmt.Errorf("API CreateUploadSession called but not implemented."))
}
return nil
}
type Z_GetUploadSessionArgs struct {
A string
}
type Z_GetUploadSessionReturns struct {
A *model.UploadSession
B error
}
func (g *apiRPCClient) GetUploadSession(uploadID string) (*model.UploadSession, error) {
_args := &Z_GetUploadSessionArgs{uploadID}
_returns := &Z_GetUploadSessionReturns{}
if err := g.client.Call("Plugin.GetUploadSession", _args, _returns); err != nil {
log.Printf("RPC call to GetUploadSession API failed: %s", err.Error())
}
return _returns.A, _returns.B
}
func (s *apiRPCServer) GetUploadSession(args *Z_GetUploadSessionArgs, returns *Z_GetUploadSessionReturns) error {
if hook, ok := s.impl.(interface {
GetUploadSession(uploadID string) (*model.UploadSession, error)
}); ok {
returns.A, returns.B = hook.GetUploadSession(args.A)
returns.B = encodableError(returns.B)
} else {
return encodableError(fmt.Errorf("API GetUploadSession called but not implemented."))
}
return nil
}

Просмотреть файл

@@ -35,6 +35,7 @@ var excludedPluginHooks = []string{
"OnActivate",
"PluginHTTP",
"ServeHTTP",
"UploadData",
}
var excludedProductHooks = []string{

Просмотреть файл

@@ -391,6 +391,29 @@ func (_m *API) CreateTeamMembersGracefully(teamID string, userIds []string, requ
return r0, r1
}
// CreateUploadSession provides a mock function with given fields: us
func (_m *API) CreateUploadSession(us *model.UploadSession) (*model.UploadSession, error) {
ret := _m.Called(us)
var r0 *model.UploadSession
if rf, ok := ret.Get(0).(func(*model.UploadSession) *model.UploadSession); ok {
r0 = rf(us)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.UploadSession)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(*model.UploadSession) error); ok {
r1 = rf(us)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// CreateUser provides a mock function with given fields: user
func (_m *API) CreateUser(user *model.User) (*model.User, *model.AppError) {
ret := _m.Called(user)
@@ -2181,6 +2204,29 @@ func (_m *API) GetUnsanitizedConfig() *model.Config {
return r0
}
// GetUploadSession provides a mock function with given fields: uploadID
func (_m *API) GetUploadSession(uploadID string) (*model.UploadSession, error) {
ret := _m.Called(uploadID)
var r0 *model.UploadSession
if rf, ok := ret.Get(0).(func(string) *model.UploadSession); ok {
r0 = rf(uploadID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.UploadSession)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(uploadID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetUser provides a mock function with given fields: userID
func (_m *API) GetUser(userID string) (*model.User, *model.AppError) {
ret := _m.Called(userID)
@@ -3717,6 +3763,29 @@ func (_m *API) UpdateUserStatus(userID string, status string) (*model.Status, *m
return r0, r1
}
// UploadData provides a mock function with given fields: us, rd
func (_m *API) UploadData(us *model.UploadSession, rd io.Reader) (*model.FileInfo, error) {
ret := _m.Called(us, rd)
var r0 *model.FileInfo
if rf, ok := ret.Get(0).(func(*model.UploadSession, io.Reader) *model.FileInfo); ok {
r0 = rf(us, rd)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.FileInfo)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(*model.UploadSession, io.Reader) error); ok {
r1 = rf(us, rd)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// UploadFile provides a mock function with given fields: data, channelId, filename
func (_m *API) UploadFile(data []byte, channelId string, filename string) (*model.FileInfo, *model.AppError) {
ret := _m.Called(data, channelId, filename)