[MM-47542] Extend Plugin API (#21446)
* Extend Plugin API * Use Error, NoError in tests * Address suggestions * Simplify code * Add new line * Add featureflag and GetCollectionMetadataByIds hook * Add enter at the end of file * make build-templates * Fix test * Fix GetCollectionMetadataByIds ret type * Add GetTopicMetadataByIds hook * Add log * Extract i18n * Add experimental notice on hooks * Update model/feature_flags.go * Swap user to userId * Change userId to userID Co-authored-by: Jesse Hallam <jesse.hallam@gmail.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
cc69c917f2
Коммит
b8da473da7
@@ -77,6 +77,12 @@ type Channels struct {
|
|||||||
|
|
||||||
postReminderMut sync.Mutex
|
postReminderMut sync.Mutex
|
||||||
postReminderTask *model.ScheduledTask
|
postReminderTask *model.ScheduledTask
|
||||||
|
|
||||||
|
// collectionTypes maps collection types array to the registering plugin
|
||||||
|
collectionTypes map[string][]string
|
||||||
|
// topicTypes maps topic types array to collection types
|
||||||
|
topicTypes map[string][]string
|
||||||
|
collectionAndTopicTypesMut sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -94,9 +100,11 @@ func init() {
|
|||||||
|
|
||||||
func NewChannels(s *Server, services map[ServiceKey]any) (*Channels, error) {
|
func NewChannels(s *Server, services map[ServiceKey]any) (*Channels, error) {
|
||||||
ch := &Channels{
|
ch := &Channels{
|
||||||
srv: s,
|
srv: s,
|
||||||
imageProxy: imageproxy.MakeImageProxy(s.platform, s.httpService, s.Log()),
|
imageProxy: imageproxy.MakeImageProxy(s.platform, s.httpService, s.Log()),
|
||||||
uploadLockMap: map[string]bool{},
|
uploadLockMap: map[string]bool{},
|
||||||
|
collectionTypes: map[string][]string{},
|
||||||
|
topicTypes: map[string][]string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// To get another service:
|
// To get another service:
|
||||||
|
|||||||
45
app/collection.go
Обычный файл
45
app/collection.go
Обычный файл
@@ -0,0 +1,45 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost-server/v6/model"
|
||||||
|
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||||
|
"github.com/mattermost/mattermost-server/v6/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *App) registerCollectionAndTopic(pluginID, collectionType, topicType string) error {
|
||||||
|
// we have a race condition due to multiple plugins calling this method
|
||||||
|
a.ch.collectionAndTopicTypesMut.Lock()
|
||||||
|
defer a.ch.collectionAndTopicTypesMut.Unlock()
|
||||||
|
|
||||||
|
// check if collectionType was already registered by other plugin
|
||||||
|
for existingPluginID, existingCollectionTypes := range a.ch.collectionTypes {
|
||||||
|
if existingPluginID != pluginID && utils.StringInSlice(collectionType, existingCollectionTypes) {
|
||||||
|
return model.NewAppError("registerCollectionAndTopic", "app.collection.add_collection.exists.app_error", nil, "", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if topicType was already registered to other collection
|
||||||
|
for existingCollectionType, existingTopicTypes := range a.ch.topicTypes {
|
||||||
|
if existingCollectionType != collectionType && utils.StringInSlice(topicType, existingTopicTypes) {
|
||||||
|
return model.NewAppError("registerCollectionAndTopic", "app.collection.add_topic.exists.app_error", nil, "", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a.ch.collectionTypes[pluginID] = appendIfUnique(a.ch.collectionTypes[pluginID], collectionType)
|
||||||
|
a.ch.topicTypes[collectionType] = appendIfUnique(a.ch.topicTypes[collectionType], topicType)
|
||||||
|
|
||||||
|
a.ch.srv.Log().Info("registered collection and topic type", mlog.String("plugin_id", pluginID), mlog.String("collection_type", collectionType), mlog.String("topic_type", topicType))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendIfUnique(slice []string, a string) []string {
|
||||||
|
if utils.StringInSlice(a, slice) {
|
||||||
|
return slice
|
||||||
|
}
|
||||||
|
return append(slice, a)
|
||||||
|
}
|
||||||
@@ -486,6 +486,11 @@ func (a *App) DisablePlugin(id string) *model.AppError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ch *Channels) disablePlugin(id string) *model.AppError {
|
func (ch *Channels) disablePlugin(id string) *model.AppError {
|
||||||
|
for _, collectionType := range ch.collectionTypes[id] {
|
||||||
|
delete(ch.topicTypes, collectionType)
|
||||||
|
}
|
||||||
|
delete(ch.collectionTypes, id)
|
||||||
|
|
||||||
pluginsEnvironment := ch.GetPluginsEnvironment()
|
pluginsEnvironment := ch.GetPluginsEnvironment()
|
||||||
if pluginsEnvironment == nil {
|
if pluginsEnvironment == nil {
|
||||||
return model.NewAppError("DisablePlugin", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
|
return model.NewAppError("DisablePlugin", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
|
||||||
|
|||||||
@@ -1231,3 +1231,9 @@ func (api *PluginAPI) GetCloudLimits() (*model.ProductLimits, error) {
|
|||||||
limits, err := api.app.Cloud().GetCloudLimits("")
|
limits, err := api.app.Cloud().GetCloudLimits("")
|
||||||
return limits, err
|
return limits, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RegisterCollectionAndTopic informs the server that this plugin handles
|
||||||
|
// the given collection and topic types.
|
||||||
|
func (api *PluginAPI) RegisterCollectionAndTopic(collectionType, topicType string) error {
|
||||||
|
return api.app.registerCollectionAndTopic(api.id, collectionType, topicType)
|
||||||
|
}
|
||||||
|
|||||||
@@ -2017,3 +2017,86 @@ func TestPluginAPIIsEnterpriseReady(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(t, true, api.IsEnterpriseReady())
|
assert.Equal(t, true, api.IsEnterpriseReady())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRegisterCollectionAndTopic(t *testing.T) {
|
||||||
|
os.Setenv("MM_FEATUREFLAGS_THREADSEVERYWHERE", "true")
|
||||||
|
defer os.Unsetenv("MM_FEATUREFLAGS_THREADSEVERYWHERE")
|
||||||
|
th := Setup(t)
|
||||||
|
defer th.TearDown()
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||||
|
cfg.FeatureFlags.ThreadsEverywhere = true
|
||||||
|
})
|
||||||
|
api := th.SetupPluginAPI()
|
||||||
|
|
||||||
|
err := api.RegisterCollectionAndTopic("collection1", "topic1")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = api.RegisterCollectionAndTopic("collection1", "topic1")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = api.RegisterCollectionAndTopic("collection1", "topic2")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = api.RegisterCollectionAndTopic("collection2", "topic3")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = api.RegisterCollectionAndTopic("collection2", "topic1")
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
pluginCode := `
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/mattermost/mattermost-server/v6/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MyPlugin struct {
|
||||||
|
plugin.MattermostPlugin
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *MyPlugin) OnActivate() error {
|
||||||
|
if err := p.API.RegisterCollectionAndTopic("collectionTypeToBeRepeated", "some topic"); err != nil {
|
||||||
|
return errors.Wrap(err, "cannot register collection")
|
||||||
|
}
|
||||||
|
if err := p.API.RegisterCollectionAndTopic("some collection", "topicToBeRepeated"); err != nil {
|
||||||
|
return errors.Wrap(err, "cannot register collection")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
plugin.ClientMain(&MyPlugin{})
|
||||||
|
}
|
||||||
|
`
|
||||||
|
pluginDir, err := os.MkdirTemp("", "")
|
||||||
|
require.NoError(t, err)
|
||||||
|
webappPluginDir, err := os.MkdirTemp("", "")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||||
|
*cfg.PluginSettings.Directory = pluginDir
|
||||||
|
*cfg.PluginSettings.ClientDirectory = webappPluginDir
|
||||||
|
})
|
||||||
|
|
||||||
|
newPluginAPI := func(manifest *model.Manifest) plugin.API {
|
||||||
|
return th.App.NewPluginAPI(th.Context, manifest)
|
||||||
|
}
|
||||||
|
|
||||||
|
env, err := plugin.NewEnvironment(newPluginAPI, NewDriverImpl(th.App.Srv()), pluginDir, webappPluginDir, th.App.Log(), nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
th.App.ch.SetPluginsEnvironment(env)
|
||||||
|
|
||||||
|
pluginID := "testplugin"
|
||||||
|
pluginManifest := `{"id": "testplugin", "server": {"executable": "backend.exe"}}`
|
||||||
|
backend := filepath.Join(pluginDir, pluginID, "backend.exe")
|
||||||
|
utils.CompileGo(t, pluginCode, backend)
|
||||||
|
|
||||||
|
os.WriteFile(filepath.Join(pluginDir, pluginID, "plugin.json"), []byte(pluginManifest), 0600)
|
||||||
|
manifest, activated, reterr := env.Activate(pluginID)
|
||||||
|
require.NoError(t, reterr)
|
||||||
|
require.NotNil(t, manifest)
|
||||||
|
require.True(t, activated)
|
||||||
|
|
||||||
|
err = api.RegisterCollectionAndTopic("collectionTypeToBeRepeated", "some other topic")
|
||||||
|
assert.Error(t, err)
|
||||||
|
err = api.RegisterCollectionAndTopic("some other collection", "topicToBeRepeated")
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|||||||
@@ -4815,6 +4815,14 @@
|
|||||||
"id": "app.cloud.upgrade_plan_bot_message_single",
|
"id": "app.cloud.upgrade_plan_bot_message_single",
|
||||||
"translation": "{{.UsersNum}} member of the {{.WorkspaceName}} workspace has requested a workspace upgrade for: "
|
"translation": "{{.UsersNum}} member of the {{.WorkspaceName}} workspace has requested a workspace upgrade for: "
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "app.collection.add_collection.exists.app_error",
|
||||||
|
"translation": "Collection type already exists."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "app.collection.add_topic.exists.app_error",
|
||||||
|
"translation": "Topic type already exists."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "app.command.createcommand.internal_error",
|
"id": "app.command.createcommand.internal_error",
|
||||||
"translation": "Unable to save the command."
|
"translation": "Unable to save the command."
|
||||||
|
|||||||
20
model/collection.go
Обычный файл
20
model/collection.go
Обычный файл
@@ -0,0 +1,20 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
package model
|
||||||
|
|
||||||
|
type CollectionMetadata struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
TeamId string `json:"team_id"`
|
||||||
|
CollectionType string `json:"collection_type"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
RelativeURL string `json:"relative_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TopicMetadata struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
TeamId string `json:"team_id"`
|
||||||
|
TopicType string `json:"topic_type"`
|
||||||
|
CollectionType string `json:"collection_type"`
|
||||||
|
CollectionId string `json:"collection_id"`
|
||||||
|
}
|
||||||
@@ -81,6 +81,8 @@ type FeatureFlags struct {
|
|||||||
|
|
||||||
// A/B Test on reduced onboarding task list item
|
// A/B Test on reduced onboarding task list item
|
||||||
ReduceOnBoardingTaskList bool
|
ReduceOnBoardingTaskList bool
|
||||||
|
|
||||||
|
ThreadsEverywhere bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FeatureFlags) SetDefaults() {
|
func (f *FeatureFlags) SetDefaults() {
|
||||||
@@ -111,6 +113,7 @@ func (f *FeatureFlags) SetDefaults() {
|
|||||||
f.PeopleProduct = false
|
f.PeopleProduct = false
|
||||||
f.AnnualSubscription = false
|
f.AnnualSubscription = false
|
||||||
f.ReduceOnBoardingTaskList = false
|
f.ReduceOnBoardingTaskList = false
|
||||||
|
f.ThreadsEverywhere = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FeatureFlags) Plugins() map[string]string {
|
func (f *FeatureFlags) Plugins() map[string]string {
|
||||||
|
|||||||
@@ -1157,6 +1157,17 @@ type API interface {
|
|||||||
//
|
//
|
||||||
// Minimum server version: 7.1
|
// Minimum server version: 7.1
|
||||||
EnsureBotUser(bot *model.Bot) (string, error)
|
EnsureBotUser(bot *model.Bot) (string, error)
|
||||||
|
|
||||||
|
// RegisterCollectionAndTopic informs the server that this plugin handles
|
||||||
|
// the given collection and topic types.
|
||||||
|
//
|
||||||
|
// It is an error for different plugins to register the same pair of types,
|
||||||
|
// or even to register a new topic against another plugin's collection.
|
||||||
|
//
|
||||||
|
// EXPERIMENTAL: This API is experimental and can be changed without advance notice.
|
||||||
|
//
|
||||||
|
// Minimum server version: 7.6
|
||||||
|
RegisterCollectionAndTopic(collectionType, topicType string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
var handshake = plugin.HandshakeConfig{
|
var handshake = plugin.HandshakeConfig{
|
||||||
|
|||||||
@@ -1239,3 +1239,10 @@ func (api *apiTimerLayer) EnsureBotUser(bot *model.Bot) (string, error) {
|
|||||||
api.recordTime(startTime, "EnsureBotUser", _returnsB == nil)
|
api.recordTime(startTime, "EnsureBotUser", _returnsB == nil)
|
||||||
return _returnsA, _returnsB
|
return _returnsA, _returnsB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *apiTimerLayer) RegisterCollectionAndTopic(collectionType, topicType string) error {
|
||||||
|
startTime := timePkg.Now()
|
||||||
|
_returnsA := api.apiImpl.RegisterCollectionAndTopic(collectionType, topicType)
|
||||||
|
api.recordTime(startTime, "RegisterCollectionAndTopic", _returnsA == nil)
|
||||||
|
return _returnsA
|
||||||
|
}
|
||||||
|
|||||||
@@ -807,6 +807,236 @@ func (s *hooksRPCServer) OnCloudLimitsUpdated(args *Z_OnCloudLimitsUpdatedArgs,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
hookNameToId["UserHasPermissionToCollection"] = UserHasPermissionToCollectionID
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_UserHasPermissionToCollectionArgs struct {
|
||||||
|
A *Context
|
||||||
|
B string
|
||||||
|
C string
|
||||||
|
D string
|
||||||
|
E *model.Permission
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_UserHasPermissionToCollectionReturns struct {
|
||||||
|
A bool
|
||||||
|
B error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *hooksRPCClient) UserHasPermissionToCollection(c *Context, userID string, collectionType, collectionId string, permission *model.Permission) (bool, error) {
|
||||||
|
_args := &Z_UserHasPermissionToCollectionArgs{c, userID, collectionType, collectionId, permission}
|
||||||
|
_returns := &Z_UserHasPermissionToCollectionReturns{}
|
||||||
|
if g.implemented[UserHasPermissionToCollectionID] {
|
||||||
|
if err := g.client.Call("Plugin.UserHasPermissionToCollection", _args, _returns); err != nil {
|
||||||
|
g.log.Error("RPC call UserHasPermissionToCollection to plugin failed.", mlog.Err(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _returns.A, _returns.B
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hooksRPCServer) UserHasPermissionToCollection(args *Z_UserHasPermissionToCollectionArgs, returns *Z_UserHasPermissionToCollectionReturns) error {
|
||||||
|
if hook, ok := s.impl.(interface {
|
||||||
|
UserHasPermissionToCollection(c *Context, userID string, collectionType, collectionId string, permission *model.Permission) (bool, error)
|
||||||
|
}); ok {
|
||||||
|
returns.A, returns.B = hook.UserHasPermissionToCollection(args.A, args.B, args.C, args.D, args.E)
|
||||||
|
returns.B = encodableError(returns.B)
|
||||||
|
} else {
|
||||||
|
return encodableError(fmt.Errorf("Hook UserHasPermissionToCollection called but not implemented."))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
hookNameToId["GetAllCollectionIDsForUser"] = GetAllCollectionIDsForUserID
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_GetAllCollectionIDsForUserArgs struct {
|
||||||
|
A *Context
|
||||||
|
B string
|
||||||
|
C string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_GetAllCollectionIDsForUserReturns struct {
|
||||||
|
A []string
|
||||||
|
B error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *hooksRPCClient) GetAllCollectionIDsForUser(c *Context, userID, collectionType string) ([]string, error) {
|
||||||
|
_args := &Z_GetAllCollectionIDsForUserArgs{c, userID, collectionType}
|
||||||
|
_returns := &Z_GetAllCollectionIDsForUserReturns{}
|
||||||
|
if g.implemented[GetAllCollectionIDsForUserID] {
|
||||||
|
if err := g.client.Call("Plugin.GetAllCollectionIDsForUser", _args, _returns); err != nil {
|
||||||
|
g.log.Error("RPC call GetAllCollectionIDsForUser to plugin failed.", mlog.Err(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _returns.A, _returns.B
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hooksRPCServer) GetAllCollectionIDsForUser(args *Z_GetAllCollectionIDsForUserArgs, returns *Z_GetAllCollectionIDsForUserReturns) error {
|
||||||
|
if hook, ok := s.impl.(interface {
|
||||||
|
GetAllCollectionIDsForUser(c *Context, userID, collectionType string) ([]string, error)
|
||||||
|
}); ok {
|
||||||
|
returns.A, returns.B = hook.GetAllCollectionIDsForUser(args.A, args.B, args.C)
|
||||||
|
returns.B = encodableError(returns.B)
|
||||||
|
} else {
|
||||||
|
return encodableError(fmt.Errorf("Hook GetAllCollectionIDsForUser called but not implemented."))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
hookNameToId["GetAllUserIdsForCollection"] = GetAllUserIdsForCollectionID
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_GetAllUserIdsForCollectionArgs struct {
|
||||||
|
A *Context
|
||||||
|
B string
|
||||||
|
C string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_GetAllUserIdsForCollectionReturns struct {
|
||||||
|
A []string
|
||||||
|
B error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *hooksRPCClient) GetAllUserIdsForCollection(c *Context, collectionType, collectionID string) ([]string, error) {
|
||||||
|
_args := &Z_GetAllUserIdsForCollectionArgs{c, collectionType, collectionID}
|
||||||
|
_returns := &Z_GetAllUserIdsForCollectionReturns{}
|
||||||
|
if g.implemented[GetAllUserIdsForCollectionID] {
|
||||||
|
if err := g.client.Call("Plugin.GetAllUserIdsForCollection", _args, _returns); err != nil {
|
||||||
|
g.log.Error("RPC call GetAllUserIdsForCollection to plugin failed.", mlog.Err(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _returns.A, _returns.B
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hooksRPCServer) GetAllUserIdsForCollection(args *Z_GetAllUserIdsForCollectionArgs, returns *Z_GetAllUserIdsForCollectionReturns) error {
|
||||||
|
if hook, ok := s.impl.(interface {
|
||||||
|
GetAllUserIdsForCollection(c *Context, collectionType, collectionID string) ([]string, error)
|
||||||
|
}); ok {
|
||||||
|
returns.A, returns.B = hook.GetAllUserIdsForCollection(args.A, args.B, args.C)
|
||||||
|
returns.B = encodableError(returns.B)
|
||||||
|
} else {
|
||||||
|
return encodableError(fmt.Errorf("Hook GetAllUserIdsForCollection called but not implemented."))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
hookNameToId["GetTopicRedirect"] = GetTopicRedirectID
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_GetTopicRedirectArgs struct {
|
||||||
|
A *Context
|
||||||
|
B string
|
||||||
|
C string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_GetTopicRedirectReturns struct {
|
||||||
|
A string
|
||||||
|
B error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *hooksRPCClient) GetTopicRedirect(c *Context, topicType, topicID string) (string, error) {
|
||||||
|
_args := &Z_GetTopicRedirectArgs{c, topicType, topicID}
|
||||||
|
_returns := &Z_GetTopicRedirectReturns{}
|
||||||
|
if g.implemented[GetTopicRedirectID] {
|
||||||
|
if err := g.client.Call("Plugin.GetTopicRedirect", _args, _returns); err != nil {
|
||||||
|
g.log.Error("RPC call GetTopicRedirect to plugin failed.", mlog.Err(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _returns.A, _returns.B
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hooksRPCServer) GetTopicRedirect(args *Z_GetTopicRedirectArgs, returns *Z_GetTopicRedirectReturns) error {
|
||||||
|
if hook, ok := s.impl.(interface {
|
||||||
|
GetTopicRedirect(c *Context, topicType, topicID string) (string, error)
|
||||||
|
}); ok {
|
||||||
|
returns.A, returns.B = hook.GetTopicRedirect(args.A, args.B, args.C)
|
||||||
|
returns.B = encodableError(returns.B)
|
||||||
|
} else {
|
||||||
|
return encodableError(fmt.Errorf("Hook GetTopicRedirect called but not implemented."))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
hookNameToId["GetCollectionMetadataByIds"] = GetCollectionMetadataByIdsID
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_GetCollectionMetadataByIdsArgs struct {
|
||||||
|
A *Context
|
||||||
|
B string
|
||||||
|
C []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_GetCollectionMetadataByIdsReturns struct {
|
||||||
|
A map[string]*model.CollectionMetadata
|
||||||
|
B error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *hooksRPCClient) GetCollectionMetadataByIds(c *Context, collectionType string, collectionIds []string) (map[string]*model.CollectionMetadata, error) {
|
||||||
|
_args := &Z_GetCollectionMetadataByIdsArgs{c, collectionType, collectionIds}
|
||||||
|
_returns := &Z_GetCollectionMetadataByIdsReturns{}
|
||||||
|
if g.implemented[GetCollectionMetadataByIdsID] {
|
||||||
|
if err := g.client.Call("Plugin.GetCollectionMetadataByIds", _args, _returns); err != nil {
|
||||||
|
g.log.Error("RPC call GetCollectionMetadataByIds to plugin failed.", mlog.Err(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _returns.A, _returns.B
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hooksRPCServer) GetCollectionMetadataByIds(args *Z_GetCollectionMetadataByIdsArgs, returns *Z_GetCollectionMetadataByIdsReturns) error {
|
||||||
|
if hook, ok := s.impl.(interface {
|
||||||
|
GetCollectionMetadataByIds(c *Context, collectionType string, collectionIds []string) (map[string]*model.CollectionMetadata, error)
|
||||||
|
}); ok {
|
||||||
|
returns.A, returns.B = hook.GetCollectionMetadataByIds(args.A, args.B, args.C)
|
||||||
|
returns.B = encodableError(returns.B)
|
||||||
|
} else {
|
||||||
|
return encodableError(fmt.Errorf("Hook GetCollectionMetadataByIds called but not implemented."))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
hookNameToId["GetTopicMetadataByIds"] = GetTopicMetadataByIdsID
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_GetTopicMetadataByIdsArgs struct {
|
||||||
|
A *Context
|
||||||
|
B string
|
||||||
|
C []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_GetTopicMetadataByIdsReturns struct {
|
||||||
|
A map[string]*model.TopicMetadata
|
||||||
|
B error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *hooksRPCClient) GetTopicMetadataByIds(c *Context, topicType string, topicIds []string) (map[string]*model.TopicMetadata, error) {
|
||||||
|
_args := &Z_GetTopicMetadataByIdsArgs{c, topicType, topicIds}
|
||||||
|
_returns := &Z_GetTopicMetadataByIdsReturns{}
|
||||||
|
if g.implemented[GetTopicMetadataByIdsID] {
|
||||||
|
if err := g.client.Call("Plugin.GetTopicMetadataByIds", _args, _returns); err != nil {
|
||||||
|
g.log.Error("RPC call GetTopicMetadataByIds to plugin failed.", mlog.Err(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _returns.A, _returns.B
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hooksRPCServer) GetTopicMetadataByIds(args *Z_GetTopicMetadataByIdsArgs, returns *Z_GetTopicMetadataByIdsReturns) error {
|
||||||
|
if hook, ok := s.impl.(interface {
|
||||||
|
GetTopicMetadataByIds(c *Context, topicType string, topicIds []string) (map[string]*model.TopicMetadata, error)
|
||||||
|
}); ok {
|
||||||
|
returns.A, returns.B = hook.GetTopicMetadataByIds(args.A, args.B, args.C)
|
||||||
|
returns.B = encodableError(returns.B)
|
||||||
|
} else {
|
||||||
|
return encodableError(fmt.Errorf("Hook GetTopicMetadataByIds called but not implemented."))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type Z_RegisterCommandArgs struct {
|
type Z_RegisterCommandArgs struct {
|
||||||
A *model.Command
|
A *model.Command
|
||||||
}
|
}
|
||||||
@@ -5708,3 +5938,33 @@ func (s *apiRPCServer) EnsureBotUser(args *Z_EnsureBotUserArgs, returns *Z_Ensur
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Z_RegisterCollectionAndTopicArgs struct {
|
||||||
|
A string
|
||||||
|
B string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_RegisterCollectionAndTopicReturns struct {
|
||||||
|
A error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *apiRPCClient) RegisterCollectionAndTopic(collectionType, topicType string) error {
|
||||||
|
_args := &Z_RegisterCollectionAndTopicArgs{collectionType, topicType}
|
||||||
|
_returns := &Z_RegisterCollectionAndTopicReturns{}
|
||||||
|
if err := g.client.Call("Plugin.RegisterCollectionAndTopic", _args, _returns); err != nil {
|
||||||
|
log.Printf("RPC call to RegisterCollectionAndTopic API failed: %s", err.Error())
|
||||||
|
}
|
||||||
|
return _returns.A
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *apiRPCServer) RegisterCollectionAndTopic(args *Z_RegisterCollectionAndTopicArgs, returns *Z_RegisterCollectionAndTopicReturns) error {
|
||||||
|
if hook, ok := s.impl.(interface {
|
||||||
|
RegisterCollectionAndTopic(collectionType, topicType string) error
|
||||||
|
}); ok {
|
||||||
|
returns.A = hook.RegisterCollectionAndTopic(args.A, args.B)
|
||||||
|
returns.A = encodableError(returns.A)
|
||||||
|
} else {
|
||||||
|
return encodableError(fmt.Errorf("API RegisterCollectionAndTopic called but not implemented."))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -43,6 +43,12 @@ const (
|
|||||||
OnInstallID = 25
|
OnInstallID = 25
|
||||||
OnSendDailyTelemetryID = 26
|
OnSendDailyTelemetryID = 26
|
||||||
OnCloudLimitsUpdatedID = 27
|
OnCloudLimitsUpdatedID = 27
|
||||||
|
UserHasPermissionToCollectionID = 28
|
||||||
|
GetAllUserIdsForCollectionID = 29
|
||||||
|
GetAllCollectionIDsForUserID = 30
|
||||||
|
GetTopicRedirectID = 31
|
||||||
|
GetCollectionMetadataByIdsID = 32
|
||||||
|
GetTopicMetadataByIdsID = 33
|
||||||
TotalHooksID = iota
|
TotalHooksID = iota
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -270,4 +276,64 @@ type Hooks interface {
|
|||||||
//
|
//
|
||||||
// Minimum server version: 7.0
|
// Minimum server version: 7.0
|
||||||
OnCloudLimitsUpdated(limits *model.ProductLimits)
|
OnCloudLimitsUpdated(limits *model.ProductLimits)
|
||||||
|
|
||||||
|
// UserHasPermissionToCollection determines if the given user has access to
|
||||||
|
// the given collection. Plugins are only expected to handle their own
|
||||||
|
// collections, and should return an error for unknown collections.
|
||||||
|
//
|
||||||
|
// For Threads Everywhere, products are expected to support at least the
|
||||||
|
// following permissions: create_post, edit_post, delete_post,
|
||||||
|
// edit_others_posts, and delete_others_posts.
|
||||||
|
//
|
||||||
|
// EXPERIMENTAL: This hook is experimental and can be changed without advance notice.
|
||||||
|
//
|
||||||
|
// Minimum server version: 7.6
|
||||||
|
UserHasPermissionToCollection(c *Context, userID string, collectionType, collectionId string, permission *model.Permission) (bool, error)
|
||||||
|
|
||||||
|
// GetAllCollectionIDsForUser returns the set of collection ids to which
|
||||||
|
// the given user has access. Plugins are only expected to handle their
|
||||||
|
// own collections, and should return an error unknown types.
|
||||||
|
//
|
||||||
|
// EXPERIMENTAL: This hook is experimental and can be changed without advance notice.
|
||||||
|
//
|
||||||
|
// Minimum server version: 7.6
|
||||||
|
GetAllCollectionIDsForUser(c *Context, userID, collectionType string) ([]string, error)
|
||||||
|
|
||||||
|
// GetAllCollectionIDsForUser returns the set of collection ids to which
|
||||||
|
// the given user has access. Plugins are only expected to handle their
|
||||||
|
// own collections, and should return an error for unknown types.
|
||||||
|
//
|
||||||
|
// EXPERIMENTAL: This hook is experimental and can be changed without advance notice.
|
||||||
|
//
|
||||||
|
// Minimum server version: 7.6
|
||||||
|
GetAllUserIdsForCollection(c *Context, collectionType, collectionID string) ([]string, error)
|
||||||
|
|
||||||
|
// GetTopicRedirect returns a relative URL to which to redirect a user
|
||||||
|
// following a topic permalink. Plugins are only expected to handle their
|
||||||
|
// own topic types, and should return an empty string and error for unknown // types.
|
||||||
|
//
|
||||||
|
// EXPERIMENTAL: This hook is experimental and can be changed without advance notice.
|
||||||
|
//
|
||||||
|
// Minimum server version: 7.6
|
||||||
|
GetTopicRedirect(c *Context, topicType, topicID string) (string, error)
|
||||||
|
|
||||||
|
// GetCollectionMetadataByIds returns collection metadata for the passed ids.
|
||||||
|
// Returned type is a map with keys of collectionId and value CollectionMetadata.
|
||||||
|
// Plugins are only expected to handle their own collections, and should
|
||||||
|
// return an error for unknown types.
|
||||||
|
//
|
||||||
|
// EXPERIMENTAL: This hook is experimental and can be changed without advance notice.
|
||||||
|
//
|
||||||
|
// Minimum server version: 7.6
|
||||||
|
GetCollectionMetadataByIds(c *Context, collectionType string, collectionIds []string) (map[string]*model.CollectionMetadata, error)
|
||||||
|
|
||||||
|
// GetTopicMetadataByIds returns topic metadata for the passed ids.
|
||||||
|
// Returned type is a map with keys of topicId and value CollectionMetadata.
|
||||||
|
// Plugins are only expected to handle their own topics, and should
|
||||||
|
// return an error for unknown types.
|
||||||
|
//
|
||||||
|
// EXPERIMENTAL: This hook is experimental and can be changed without advance notice.
|
||||||
|
//
|
||||||
|
// Minimum server version: 7.6
|
||||||
|
GetTopicMetadataByIds(c *Context, topicType string, topicIds []string) (map[string]*model.TopicMetadata, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -212,3 +212,45 @@ func (hooks *hooksTimerLayer) OnCloudLimitsUpdated(limits *model.ProductLimits)
|
|||||||
hooks.hooksImpl.OnCloudLimitsUpdated(limits)
|
hooks.hooksImpl.OnCloudLimitsUpdated(limits)
|
||||||
hooks.recordTime(startTime, "OnCloudLimitsUpdated", true)
|
hooks.recordTime(startTime, "OnCloudLimitsUpdated", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hooks *hooksTimerLayer) UserHasPermissionToCollection(c *Context, userID string, collectionType, collectionId string, permission *model.Permission) (bool, error) {
|
||||||
|
startTime := timePkg.Now()
|
||||||
|
_returnsA, _returnsB := hooks.hooksImpl.UserHasPermissionToCollection(c, userID, collectionType, collectionId, permission)
|
||||||
|
hooks.recordTime(startTime, "UserHasPermissionToCollection", _returnsB == nil)
|
||||||
|
return _returnsA, _returnsB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hooks *hooksTimerLayer) GetAllCollectionIDsForUser(c *Context, userID, collectionType string) ([]string, error) {
|
||||||
|
startTime := timePkg.Now()
|
||||||
|
_returnsA, _returnsB := hooks.hooksImpl.GetAllCollectionIDsForUser(c, userID, collectionType)
|
||||||
|
hooks.recordTime(startTime, "GetAllCollectionIDsForUser", _returnsB == nil)
|
||||||
|
return _returnsA, _returnsB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hooks *hooksTimerLayer) GetAllUserIdsForCollection(c *Context, collectionType, collectionID string) ([]string, error) {
|
||||||
|
startTime := timePkg.Now()
|
||||||
|
_returnsA, _returnsB := hooks.hooksImpl.GetAllUserIdsForCollection(c, collectionType, collectionID)
|
||||||
|
hooks.recordTime(startTime, "GetAllUserIdsForCollection", _returnsB == nil)
|
||||||
|
return _returnsA, _returnsB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hooks *hooksTimerLayer) GetTopicRedirect(c *Context, topicType, topicID string) (string, error) {
|
||||||
|
startTime := timePkg.Now()
|
||||||
|
_returnsA, _returnsB := hooks.hooksImpl.GetTopicRedirect(c, topicType, topicID)
|
||||||
|
hooks.recordTime(startTime, "GetTopicRedirect", _returnsB == nil)
|
||||||
|
return _returnsA, _returnsB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hooks *hooksTimerLayer) GetCollectionMetadataByIds(c *Context, collectionType string, collectionIds []string) (map[string]*model.CollectionMetadata, error) {
|
||||||
|
startTime := timePkg.Now()
|
||||||
|
_returnsA, _returnsB := hooks.hooksImpl.GetCollectionMetadataByIds(c, collectionType, collectionIds)
|
||||||
|
hooks.recordTime(startTime, "GetCollectionMetadataByIds", _returnsB == nil)
|
||||||
|
return _returnsA, _returnsB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hooks *hooksTimerLayer) GetTopicMetadataByIds(c *Context, topicType string, topicIds []string) (map[string]*model.TopicMetadata, error) {
|
||||||
|
startTime := timePkg.Now()
|
||||||
|
_returnsA, _returnsB := hooks.hooksImpl.GetTopicMetadataByIds(c, topicType, topicIds)
|
||||||
|
hooks.recordTime(startTime, "GetTopicMetadataByIds", _returnsB == nil)
|
||||||
|
return _returnsA, _returnsB
|
||||||
|
}
|
||||||
|
|||||||
@@ -2941,6 +2941,20 @@ func (_m *API) ReadFile(path string) ([]byte, *model.AppError) {
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RegisterCollectionAndTopic provides a mock function with given fields: collectionType, topicType
|
||||||
|
func (_m *API) RegisterCollectionAndTopic(collectionType string, topicType string) error {
|
||||||
|
ret := _m.Called(collectionType, topicType)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(string, string) error); ok {
|
||||||
|
r0 = rf(collectionType, topicType)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterCommand provides a mock function with given fields: command
|
// RegisterCommand provides a mock function with given fields: command
|
||||||
func (_m *API) RegisterCommand(command *model.Command) error {
|
func (_m *API) RegisterCommand(command *model.Command) error {
|
||||||
ret := _m.Called(command)
|
ret := _m.Called(command)
|
||||||
|
|||||||
@@ -73,6 +73,119 @@ func (_m *Hooks) FileWillBeUploaded(c *plugin.Context, info *model.FileInfo, fil
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAllCollectionIDsForUser provides a mock function with given fields: c, userID, collectionType
|
||||||
|
func (_m *Hooks) GetAllCollectionIDsForUser(c *plugin.Context, userID string, collectionType string) ([]string, error) {
|
||||||
|
ret := _m.Called(c, userID, collectionType)
|
||||||
|
|
||||||
|
var r0 []string
|
||||||
|
if rf, ok := ret.Get(0).(func(*plugin.Context, string, string) []string); ok {
|
||||||
|
r0 = rf(c, userID, collectionType)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(*plugin.Context, string, string) error); ok {
|
||||||
|
r1 = rf(c, userID, collectionType)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAllUserIdsForCollection provides a mock function with given fields: c, collectionType, collectionID
|
||||||
|
func (_m *Hooks) GetAllUserIdsForCollection(c *plugin.Context, collectionType string, collectionID string) ([]string, error) {
|
||||||
|
ret := _m.Called(c, collectionType, collectionID)
|
||||||
|
|
||||||
|
var r0 []string
|
||||||
|
if rf, ok := ret.Get(0).(func(*plugin.Context, string, string) []string); ok {
|
||||||
|
r0 = rf(c, collectionType, collectionID)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(*plugin.Context, string, string) error); ok {
|
||||||
|
r1 = rf(c, collectionType, collectionID)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCollectionMetadataByIds provides a mock function with given fields: c, collectionType, collectionIds
|
||||||
|
func (_m *Hooks) GetCollectionMetadataByIds(c *plugin.Context, collectionType string, collectionIds []string) (map[string]*model.CollectionMetadata, error) {
|
||||||
|
ret := _m.Called(c, collectionType, collectionIds)
|
||||||
|
|
||||||
|
var r0 map[string]*model.CollectionMetadata
|
||||||
|
if rf, ok := ret.Get(0).(func(*plugin.Context, string, []string) map[string]*model.CollectionMetadata); ok {
|
||||||
|
r0 = rf(c, collectionType, collectionIds)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(map[string]*model.CollectionMetadata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(*plugin.Context, string, []string) error); ok {
|
||||||
|
r1 = rf(c, collectionType, collectionIds)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTopicMetadataByIds provides a mock function with given fields: c, topicType, topicIds
|
||||||
|
func (_m *Hooks) GetTopicMetadataByIds(c *plugin.Context, topicType string, topicIds []string) (map[string]*model.TopicMetadata, error) {
|
||||||
|
ret := _m.Called(c, topicType, topicIds)
|
||||||
|
|
||||||
|
var r0 map[string]*model.TopicMetadata
|
||||||
|
if rf, ok := ret.Get(0).(func(*plugin.Context, string, []string) map[string]*model.TopicMetadata); ok {
|
||||||
|
r0 = rf(c, topicType, topicIds)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(map[string]*model.TopicMetadata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(*plugin.Context, string, []string) error); ok {
|
||||||
|
r1 = rf(c, topicType, topicIds)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTopicRedirect provides a mock function with given fields: c, topicType, topicID
|
||||||
|
func (_m *Hooks) GetTopicRedirect(c *plugin.Context, topicType string, topicID string) (string, error) {
|
||||||
|
ret := _m.Called(c, topicType, topicID)
|
||||||
|
|
||||||
|
var r0 string
|
||||||
|
if rf, ok := ret.Get(0).(func(*plugin.Context, string, string) string); ok {
|
||||||
|
r0 = rf(c, topicType, topicID)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(*plugin.Context, string, string) error); ok {
|
||||||
|
r1 = rf(c, topicType, topicID)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
// Implemented provides a mock function with given fields:
|
// Implemented provides a mock function with given fields:
|
||||||
func (_m *Hooks) Implemented() ([]string, error) {
|
func (_m *Hooks) Implemented() ([]string, error) {
|
||||||
ret := _m.Called()
|
ret := _m.Called()
|
||||||
@@ -299,6 +412,27 @@ func (_m *Hooks) UserHasLoggedIn(c *plugin.Context, user *model.User) {
|
|||||||
_m.Called(c, user)
|
_m.Called(c, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UserHasPermissionToCollection provides a mock function with given fields: c, userID, collectionType, collectionId, permission
|
||||||
|
func (_m *Hooks) UserHasPermissionToCollection(c *plugin.Context, userID string, collectionType string, collectionId string, permission *model.Permission) (bool, error) {
|
||||||
|
ret := _m.Called(c, userID, collectionType, collectionId, permission)
|
||||||
|
|
||||||
|
var r0 bool
|
||||||
|
if rf, ok := ret.Get(0).(func(*plugin.Context, string, string, string, *model.Permission) bool); ok {
|
||||||
|
r0 = rf(c, userID, collectionType, collectionId, permission)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(*plugin.Context, string, string, string, *model.Permission) error); ok {
|
||||||
|
r1 = rf(c, userID, collectionType, collectionId, permission)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
// UserWillLogIn provides a mock function with given fields: c, user
|
// UserWillLogIn provides a mock function with given fields: c, user
|
||||||
func (_m *Hooks) UserWillLogIn(c *plugin.Context, user *model.User) string {
|
func (_m *Hooks) UserWillLogIn(c *plugin.Context, user *model.User) string {
|
||||||
ret := _m.Called(c, user)
|
ret := _m.Called(c, user)
|
||||||
|
|||||||
@@ -114,6 +114,30 @@ type OnCloudLimitsUpdatedIFace interface {
|
|||||||
OnCloudLimitsUpdated(limits *model.ProductLimits)
|
OnCloudLimitsUpdated(limits *model.ProductLimits)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserHasPermissionToCollectionIFace interface {
|
||||||
|
UserHasPermissionToCollection(c *Context, userID string, collectionType, collectionId string, permission *model.Permission) (bool, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetAllCollectionIDsForUserIFace interface {
|
||||||
|
GetAllCollectionIDsForUser(c *Context, userID, collectionType string) ([]string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetAllUserIdsForCollectionIFace interface {
|
||||||
|
GetAllUserIdsForCollection(c *Context, collectionType, collectionID string) ([]string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetTopicRedirectIFace interface {
|
||||||
|
GetTopicRedirect(c *Context, topicType, topicID string) (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetCollectionMetadataByIdsIFace interface {
|
||||||
|
GetCollectionMetadataByIds(c *Context, collectionType string, collectionIds []string) (map[string]*model.CollectionMetadata, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetTopicMetadataByIdsIFace interface {
|
||||||
|
GetTopicMetadataByIds(c *Context, topicType string, topicIds []string) (map[string]*model.TopicMetadata, error)
|
||||||
|
}
|
||||||
|
|
||||||
type hooksAdapter struct {
|
type hooksAdapter struct {
|
||||||
implemented map[int]struct{}
|
implemented map[int]struct{}
|
||||||
productHooks any
|
productHooks any
|
||||||
@@ -352,6 +376,60 @@ func newAdapter(productHooks any) (*hooksAdapter, error) {
|
|||||||
return nil, errors.New("hook has OnCloudLimitsUpdated method but does not implement plugin.OnCloudLimitsUpdated interface")
|
return nil, errors.New("hook has OnCloudLimitsUpdated method but does not implement plugin.OnCloudLimitsUpdated interface")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assessing the type of the productHooks if it individually implements UserHasPermissionToCollection interface.
|
||||||
|
tt = reflect.TypeOf((*UserHasPermissionToCollectionIFace)(nil)).Elem()
|
||||||
|
|
||||||
|
if ft.Implements(tt) {
|
||||||
|
a.implemented[UserHasPermissionToCollectionID] = struct{}{}
|
||||||
|
} else if _, ok := ft.MethodByName("UserHasPermissionToCollection"); ok {
|
||||||
|
return nil, errors.New("hook has UserHasPermissionToCollection method but does not implement plugin.UserHasPermissionToCollection interface")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assessing the type of the productHooks if it individually implements GetAllCollectionIDsForUser interface.
|
||||||
|
tt = reflect.TypeOf((*GetAllCollectionIDsForUserIFace)(nil)).Elem()
|
||||||
|
|
||||||
|
if ft.Implements(tt) {
|
||||||
|
a.implemented[GetAllCollectionIDsForUserID] = struct{}{}
|
||||||
|
} else if _, ok := ft.MethodByName("GetAllCollectionIDsForUser"); ok {
|
||||||
|
return nil, errors.New("hook has GetAllCollectionIDsForUser method but does not implement plugin.GetAllCollectionIDsForUser interface")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assessing the type of the productHooks if it individually implements GetAllUserIdsForCollection interface.
|
||||||
|
tt = reflect.TypeOf((*GetAllUserIdsForCollectionIFace)(nil)).Elem()
|
||||||
|
|
||||||
|
if ft.Implements(tt) {
|
||||||
|
a.implemented[GetAllUserIdsForCollectionID] = struct{}{}
|
||||||
|
} else if _, ok := ft.MethodByName("GetAllUserIdsForCollection"); ok {
|
||||||
|
return nil, errors.New("hook has GetAllUserIdsForCollection method but does not implement plugin.GetAllUserIdsForCollection interface")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assessing the type of the productHooks if it individually implements GetTopicRedirect interface.
|
||||||
|
tt = reflect.TypeOf((*GetTopicRedirectIFace)(nil)).Elem()
|
||||||
|
|
||||||
|
if ft.Implements(tt) {
|
||||||
|
a.implemented[GetTopicRedirectID] = struct{}{}
|
||||||
|
} else if _, ok := ft.MethodByName("GetTopicRedirect"); ok {
|
||||||
|
return nil, errors.New("hook has GetTopicRedirect method but does not implement plugin.GetTopicRedirect interface")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assessing the type of the productHooks if it individually implements GetCollectionMetadataByIds interface.
|
||||||
|
tt = reflect.TypeOf((*GetCollectionMetadataByIdsIFace)(nil)).Elem()
|
||||||
|
|
||||||
|
if ft.Implements(tt) {
|
||||||
|
a.implemented[GetCollectionMetadataByIdsID] = struct{}{}
|
||||||
|
} else if _, ok := ft.MethodByName("GetCollectionMetadataByIds"); ok {
|
||||||
|
return nil, errors.New("hook has GetCollectionMetadataByIds method but does not implement plugin.GetCollectionMetadataByIds interface")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assessing the type of the productHooks if it individually implements GetTopicMetadataByIds interface.
|
||||||
|
tt = reflect.TypeOf((*GetTopicMetadataByIdsIFace)(nil)).Elem()
|
||||||
|
|
||||||
|
if ft.Implements(tt) {
|
||||||
|
a.implemented[GetTopicMetadataByIdsID] = struct{}{}
|
||||||
|
} else if _, ok := ft.MethodByName("GetTopicMetadataByIds"); ok {
|
||||||
|
return nil, errors.New("hook has GetTopicMetadataByIds method but does not implement plugin.GetTopicMetadataByIds interface")
|
||||||
|
}
|
||||||
|
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -579,3 +657,57 @@ func (a *hooksAdapter) OnCloudLimitsUpdated(limits *model.ProductLimits) {
|
|||||||
a.productHooks.(OnCloudLimitsUpdatedIFace).OnCloudLimitsUpdated(limits)
|
a.productHooks.(OnCloudLimitsUpdatedIFace).OnCloudLimitsUpdated(limits)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *hooksAdapter) UserHasPermissionToCollection(c *Context, userID string, collectionType, collectionId string, permission *model.Permission) (bool, error) {
|
||||||
|
if _, ok := a.implemented[UserHasPermissionToCollectionID]; !ok {
|
||||||
|
panic("product hooks must implement UserHasPermissionToCollection")
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.productHooks.(UserHasPermissionToCollectionIFace).UserHasPermissionToCollection(c, userID, collectionType, collectionId, permission)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *hooksAdapter) GetAllCollectionIDsForUser(c *Context, userID, collectionType string) ([]string, error) {
|
||||||
|
if _, ok := a.implemented[GetAllCollectionIDsForUserID]; !ok {
|
||||||
|
panic("product hooks must implement GetAllCollectionIDsForUser")
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.productHooks.(GetAllCollectionIDsForUserIFace).GetAllCollectionIDsForUser(c, userID, collectionType)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *hooksAdapter) GetAllUserIdsForCollection(c *Context, collectionType, collectionID string) ([]string, error) {
|
||||||
|
if _, ok := a.implemented[GetAllUserIdsForCollectionID]; !ok {
|
||||||
|
panic("product hooks must implement GetAllUserIdsForCollection")
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.productHooks.(GetAllUserIdsForCollectionIFace).GetAllUserIdsForCollection(c, collectionType, collectionID)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *hooksAdapter) GetTopicRedirect(c *Context, topicType, topicID string) (string, error) {
|
||||||
|
if _, ok := a.implemented[GetTopicRedirectID]; !ok {
|
||||||
|
panic("product hooks must implement GetTopicRedirect")
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.productHooks.(GetTopicRedirectIFace).GetTopicRedirect(c, topicType, topicID)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *hooksAdapter) GetCollectionMetadataByIds(c *Context, collectionType string, collectionIds []string) (map[string]*model.CollectionMetadata, error) {
|
||||||
|
if _, ok := a.implemented[GetCollectionMetadataByIdsID]; !ok {
|
||||||
|
panic("product hooks must implement GetCollectionMetadataByIds")
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.productHooks.(GetCollectionMetadataByIdsIFace).GetCollectionMetadataByIds(c, collectionType, collectionIds)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *hooksAdapter) GetTopicMetadataByIds(c *Context, topicType string, topicIds []string) (map[string]*model.TopicMetadata, error) {
|
||||||
|
if _, ok := a.implemented[GetTopicMetadataByIdsID]; !ok {
|
||||||
|
panic("product hooks must implement GetTopicMetadataByIds")
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.productHooks.(GetTopicMetadataByIdsIFace).GetTopicMetadataByIds(c, topicType, topicIds)
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user