MM-53358: Revert Threads Everywhere (#23882)

Remove changes related to the unshipped threads everywhere feature, including commits b8da473da7 and 9f9e19e05d.

Since a version of Playbooks shipped calling this experimental API, keep a `nil` implementation to avoid breaking compatibility. We remove the hooks altogether, but keep the numbering again to avoid breaking compatbility.

Fixes: https://mattermost.atlassian.net/browse/MM-53358
This commit is contained in:
Jesse Hallam
2023-06-30 15:31:25 -03:00
committed by GitHub
parent c506e01a97
commit 8abc8ed65c
16 changed files with 42 additions and 859 deletions

View File

@@ -971,7 +971,6 @@ type AppIface interface {
RegenOutgoingWebhookToken(hook *model.OutgoingWebhook) (*model.OutgoingWebhook, *model.AppError)
RegenerateOAuthAppSecret(app *model.OAuthApp) (*model.OAuthApp, *model.AppError)
RegenerateTeamInviteId(teamID string) (*model.Team, *model.AppError)
RegisterCollectionAndTopic(pluginID, collectionType, topicType string) error
RegisterPluginCommand(pluginID string, command *model.Command) error
RegisterProductCommand(ProductID string, command *model.Command) error
ReloadConfig() error

View File

@@ -83,12 +83,6 @@ type Channels struct {
postReminderMut sync.Mutex
postReminderTask *model.ScheduledTask
// collectionTypes maps from collection types to the registering plugin id
collectionTypes map[string]string
// topicTypes maps from topic types to collection types
topicTypes map[string]string
collectionAndTopicTypesMut sync.Mutex
}
func init() {
@@ -111,11 +105,9 @@ func NewChannels(services map[product.ServiceKey]any) (*Channels, error) {
return nil, errors.New("server not passed")
}
ch := &Channels{
srv: s,
imageProxy: imageproxy.MakeImageProxy(s.platform, s.httpService, s.Log()),
uploadLockMap: map[string]bool{},
collectionTypes: map[string]string{},
topicTypes: map[string]string{},
srv: s,
imageProxy: imageproxy.MakeImageProxy(s.platform, s.httpService, s.Log()),
uploadLockMap: map[string]bool{},
}
// To get another service:

View File

@@ -1,35 +0,0 @@
// 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/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
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
existingPluginID, ok := a.ch.collectionTypes[collectionType]
if ok && existingPluginID != pluginID {
return model.NewAppError("registerCollectionAndTopic", "app.collection.add_collection.exists.app_error", nil, "", http.StatusBadRequest)
}
// check if topicType was already registered to other collection
existingCollectionType, ok := a.ch.topicTypes[topicType]
if ok && existingCollectionType != collectionType {
return model.NewAppError("registerCollectionAndTopic", "app.collection.add_topic.exists.app_error", nil, "", http.StatusBadRequest)
}
a.ch.collectionTypes[collectionType] = pluginID
a.ch.topicTypes[topicType] = collectionType
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
}

View File

@@ -13782,28 +13782,6 @@ func (a *OpenTracingAppLayer) RegenerateTeamInviteId(teamID string) (*model.Team
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) RegisterCollectionAndTopic(pluginID string, collectionType string, topicType string) error {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.RegisterCollectionAndTopic")
a.ctx = newCtx
a.app.Srv().Store().SetContext(newCtx)
defer func() {
a.app.Srv().Store().SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0 := a.app.RegisterCollectionAndTopic(pluginID, collectionType, topicType)
if resultVar0 != nil {
span.LogFields(spanlog.Error(resultVar0))
ext.Error.Set(span, true)
}
return resultVar0
}
func (a *OpenTracingAppLayer) RegisterPluginCommand(pluginID string, command *model.Command) error {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.RegisterPluginCommand")

View File

@@ -462,20 +462,6 @@ func (a *App) DisablePlugin(id string) *model.AppError {
}
func (ch *Channels) disablePlugin(id string) *model.AppError {
// find all collectionTypes registered by plugin
for collectionTypeToRemove, existingPluginId := range ch.collectionTypes {
if existingPluginId != id {
continue
}
// find all topicTypes for existing collectionType
for topicTypeToRemove, existingCollectionType := range ch.topicTypes {
if existingCollectionType == collectionTypeToRemove {
delete(ch.topicTypes, topicTypeToRemove)
}
}
delete(ch.collectionTypes, collectionTypeToRemove)
}
pluginsEnvironment := ch.GetPluginsEnvironment()
if pluginsEnvironment == nil {
return model.NewAppError("DisablePlugin", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)

View File

@@ -1232,10 +1232,9 @@ func (api *PluginAPI) GetCloudLimits() (*model.ProductLimits, error) {
return limits, err
}
// RegisterCollectionAndTopic informs the server that this plugin handles
// the given collection and topic types.
// RegisterCollectionAndTopic is no longer supported.
func (api *PluginAPI) RegisterCollectionAndTopic(collectionType, topicType string) error {
return api.app.RegisterCollectionAndTopic(api.id, collectionType, topicType)
return nil
}
func (api *PluginAPI) CreateUploadSession(us *model.UploadSession) (*model.UploadSession, error) {

View File

@@ -2019,89 +2019,6 @@ func TestPluginAPIIsEnterpriseReady(t *testing.T) {
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/public/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)
}
func TestPluginUploadsAPI(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()

View File

@@ -4931,14 +4931,6 @@
"id": "app.cloud.upgrade_plan_bot_message_single",
"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",
"translation": "Unable to save the command."

View File

@@ -1,20 +0,0 @@
// 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"`
}

View File

@@ -55,8 +55,6 @@ type FeatureFlags struct {
PeopleProduct bool
ThreadsEverywhere bool
GlobalDrafts bool
OnboardingTourTips bool
@@ -82,7 +80,6 @@ func (f *FeatureFlags) SetDefaults() {
f.CallsEnabled = true
f.PostPriority = true
f.PeopleProduct = false
f.ThreadsEverywhere = false
f.GlobalDrafts = true
f.DeprecateCloudFree = false
f.WysiwygEditor = false

View File

@@ -1158,13 +1158,7 @@ type API interface {
// Minimum server version: 7.1
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.
// RegisterCollectionAndTopic is no longer supported.
//
// Minimum server version: 7.6
RegisterCollectionAndTopic(collectionType, topicType string) error

View File

@@ -807,236 +807,6 @@ func (s *hooksRPCServer) OnCloudLimitsUpdated(args *Z_OnCloudLimitsUpdatedArgs,
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
}
func init() {
hookNameToId["ConfigurationWillBeSaved"] = ConfigurationWillBeSavedID
}

View File

@@ -15,42 +15,42 @@ import (
// Feel free to add more, but do not change existing assignments. Follow the naming convention of
// <HookName>ID as the autogenerated glue code depends on that.
const (
OnActivateID = 0
OnDeactivateID = 1
ServeHTTPID = 2
OnConfigurationChangeID = 3
ExecuteCommandID = 4
MessageWillBePostedID = 5
MessageWillBeUpdatedID = 6
MessageHasBeenPostedID = 7
MessageHasBeenUpdatedID = 8
UserHasJoinedChannelID = 9
UserHasLeftChannelID = 10
UserHasJoinedTeamID = 11
UserHasLeftTeamID = 12
ChannelHasBeenCreatedID = 13
FileWillBeUploadedID = 14
UserWillLogInID = 15
UserHasLoggedInID = 16
UserHasBeenCreatedID = 17
ReactionHasBeenAddedID = 18
ReactionHasBeenRemovedID = 19
OnPluginClusterEventID = 20
OnWebSocketConnectID = 21
OnWebSocketDisconnectID = 22
WebSocketMessageHasBeenPostedID = 23
RunDataRetentionID = 24
OnInstallID = 25
OnSendDailyTelemetryID = 26
OnCloudLimitsUpdatedID = 27
UserHasPermissionToCollectionID = 28
GetAllUserIdsForCollectionID = 29
GetAllCollectionIDsForUserID = 30
GetTopicRedirectID = 31
GetCollectionMetadataByIdsID = 32
GetTopicMetadataByIdsID = 33
ConfigurationWillBeSavedID = 34
TotalHooksID = iota
OnActivateID = 0
OnDeactivateID = 1
ServeHTTPID = 2
OnConfigurationChangeID = 3
ExecuteCommandID = 4
MessageWillBePostedID = 5
MessageWillBeUpdatedID = 6
MessageHasBeenPostedID = 7
MessageHasBeenUpdatedID = 8
UserHasJoinedChannelID = 9
UserHasLeftChannelID = 10
UserHasJoinedTeamID = 11
UserHasLeftTeamID = 12
ChannelHasBeenCreatedID = 13
FileWillBeUploadedID = 14
UserWillLogInID = 15
UserHasLoggedInID = 16
UserHasBeenCreatedID = 17
ReactionHasBeenAddedID = 18
ReactionHasBeenRemovedID = 19
OnPluginClusterEventID = 20
OnWebSocketConnectID = 21
OnWebSocketDisconnectID = 22
WebSocketMessageHasBeenPostedID = 23
RunDataRetentionID = 24
OnInstallID = 25
OnSendDailyTelemetryID = 26
OnCloudLimitsUpdatedID = 27
deprecatedUserHasPermissionToCollectionID = 28
deprecatedGetAllUserIdsForCollectionID = 29
deprecatedGetAllCollectionIDsForUserID = 30
deprecatedGetTopicRedirectID = 31
deprecatedGetCollectionMetadataByIdsID = 32
deprecatedGetTopicMetadataByIdsID = 33
ConfigurationWillBeSavedID = 34
TotalHooksID = iota
)
const (
@@ -278,66 +278,6 @@ type Hooks interface {
// Minimum server version: 7.0
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)
// ConfigurationWillBeSaved is invoked before saving the configuration to the
// backing store.
// An error can be returned to reject the operation. Additionally, a new

View File

@@ -212,48 +212,6 @@ func (hooks *hooksTimerLayer) OnCloudLimitsUpdated(limits *model.ProductLimits)
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
}
func (hooks *hooksTimerLayer) ConfigurationWillBeSaved(newCfg *model.Config) (*model.Config, error) {
startTime := timePkg.Now()
_returnsA, _returnsB := hooks.hooksImpl.ConfigurationWillBeSaved(newCfg)

View File

@@ -105,134 +105,6 @@ func (_m *Hooks) FileWillBeUploaded(c *plugin.Context, info *model.FileInfo, fil
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
var r1 error
if rf, ok := ret.Get(0).(func(*plugin.Context, string, string) ([]string, error)); ok {
return rf(c, userID, collectionType)
}
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)
}
}
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
var r1 error
if rf, ok := ret.Get(0).(func(*plugin.Context, string, string) ([]string, error)); ok {
return rf(c, collectionType, collectionID)
}
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)
}
}
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
var r1 error
if rf, ok := ret.Get(0).(func(*plugin.Context, string, []string) (map[string]*model.CollectionMetadata, error)); ok {
return rf(c, collectionType, collectionIds)
}
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)
}
}
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
var r1 error
if rf, ok := ret.Get(0).(func(*plugin.Context, string, []string) (map[string]*model.TopicMetadata, error)); ok {
return rf(c, topicType, topicIds)
}
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)
}
}
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
var r1 error
if rf, ok := ret.Get(0).(func(*plugin.Context, string, string) (string, error)); ok {
return rf(c, topicType, topicID)
}
if rf, ok := ret.Get(0).(func(*plugin.Context, string, string) string); ok {
r0 = rf(c, topicType, topicID)
} else {
r0 = ret.Get(0).(string)
}
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:
func (_m *Hooks) Implemented() ([]string, error) {
ret := _m.Called()
@@ -471,30 +343,6 @@ func (_m *Hooks) UserHasLoggedIn(c *plugin.Context, user *model.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
var r1 error
if rf, ok := ret.Get(0).(func(*plugin.Context, string, string, string, *model.Permission) (bool, error)); ok {
return rf(c, userID, collectionType, collectionId, permission)
}
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)
}
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
func (_m *Hooks) UserWillLogIn(c *plugin.Context, user *model.User) string {
ret := _m.Called(c, user)

View File

@@ -114,30 +114,6 @@ type OnCloudLimitsUpdatedIFace interface {
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 ConfigurationWillBeSavedIFace interface {
ConfigurationWillBeSaved(newCfg *model.Config) (*model.Config, error)
}
@@ -380,60 +356,6 @@ func NewAdapter(productHooks any) (*HooksAdapter, error) {
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")
}
// Assessing the type of the productHooks if it individually implements ConfigurationWillBeSaved interface.
tt = reflect.TypeOf((*ConfigurationWillBeSavedIFace)(nil)).Elem()
@@ -671,60 +593,6 @@ func (a *HooksAdapter) OnCloudLimitsUpdated(limits *model.ProductLimits) {
}
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)
}
func (a *HooksAdapter) ConfigurationWillBeSaved(newCfg *model.Config) (*model.Config, error) {
if _, ok := a.implemented[ConfigurationWillBeSavedID]; !ok {
panic("product hooks must implement ConfigurationWillBeSaved")