2022-07-18 19:21:57 +02:00
|
|
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
|
|
// See LICENSE.txt for license information.
|
|
|
|
|
|
|
|
package product
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/mattermost/focalboard/mattermost-plugin/server/boards"
|
2022-08-19 19:16:18 +02:00
|
|
|
"github.com/mattermost/focalboard/server/model"
|
2022-07-18 19:21:57 +02:00
|
|
|
|
|
|
|
"github.com/mattermost/mattermost-server/v6/app"
|
|
|
|
mm_model "github.com/mattermost/mattermost-server/v6/model"
|
|
|
|
"github.com/mattermost/mattermost-server/v6/plugin"
|
|
|
|
"github.com/mattermost/mattermost-server/v6/product"
|
|
|
|
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
boardsProductName = "boards"
|
|
|
|
boardsProductID = "com.mattermost.boards"
|
|
|
|
)
|
|
|
|
|
|
|
|
var errServiceTypeAssert = errors.New("type assertion failed")
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
app.RegisterProduct("boards", app.ProductManifest{
|
|
|
|
Initializer: newBoardsProduct,
|
|
|
|
Dependencies: map[app.ServiceKey]struct{}{
|
|
|
|
app.TeamKey: {},
|
|
|
|
app.ChannelKey: {},
|
|
|
|
app.UserKey: {},
|
|
|
|
app.PostKey: {},
|
|
|
|
app.BotKey: {},
|
|
|
|
app.ClusterKey: {},
|
|
|
|
app.ConfigKey: {},
|
|
|
|
app.LogKey: {},
|
|
|
|
app.LicenseKey: {},
|
|
|
|
app.FilestoreKey: {},
|
|
|
|
app.FileInfoStoreKey: {},
|
|
|
|
app.RouterKey: {},
|
|
|
|
app.CloudKey: {},
|
|
|
|
app.KVStoreKey: {},
|
|
|
|
app.StoreKey: {},
|
|
|
|
app.SystemKey: {},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
type boardsProduct struct {
|
|
|
|
teamService product.TeamService
|
|
|
|
channelService product.ChannelService
|
|
|
|
userService product.UserService
|
|
|
|
postService product.PostService
|
|
|
|
permissionsService product.PermissionService
|
|
|
|
botService product.BotService
|
|
|
|
clusterService product.ClusterService
|
|
|
|
configService product.ConfigService
|
|
|
|
logger mlog.LoggerIFace
|
|
|
|
licenseService product.LicenseService
|
|
|
|
filestoreService product.FilestoreService
|
|
|
|
fileInfoStoreService product.FileInfoStoreService
|
|
|
|
routerService product.RouterService
|
|
|
|
cloudService product.CloudService
|
|
|
|
kvStoreService product.KVStoreService
|
|
|
|
storeService product.StoreService
|
|
|
|
systemService product.SystemService
|
|
|
|
|
|
|
|
boardsApp *boards.BoardsApp
|
|
|
|
}
|
|
|
|
|
2022-08-23 20:01:51 +02:00
|
|
|
//nolint:gocyclo,exhaustive
|
2022-07-19 17:26:01 +02:00
|
|
|
func newBoardsProduct(_ *app.Server, services map[app.ServiceKey]interface{}) (app.Product, error) {
|
2022-07-18 19:21:57 +02:00
|
|
|
boards := &boardsProduct{}
|
|
|
|
|
|
|
|
for key, service := range services {
|
|
|
|
switch key {
|
|
|
|
case app.TeamKey:
|
|
|
|
teamService, ok := service.(product.TeamService)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
|
|
|
}
|
|
|
|
boards.teamService = teamService
|
|
|
|
case app.ChannelKey:
|
|
|
|
channelService, ok := service.(product.ChannelService)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
|
|
|
}
|
|
|
|
boards.channelService = channelService
|
|
|
|
case app.UserKey:
|
|
|
|
userService, ok := service.(product.UserService)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
|
|
|
}
|
|
|
|
boards.userService = userService
|
|
|
|
case app.PostKey:
|
|
|
|
postService, ok := service.(product.PostService)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
|
|
|
}
|
|
|
|
boards.postService = postService
|
|
|
|
case app.PermissionsKey:
|
|
|
|
permissionsService, ok := service.(product.PermissionService)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
|
|
|
}
|
|
|
|
boards.permissionsService = permissionsService
|
|
|
|
case app.BotKey:
|
|
|
|
botService, ok := service.(product.BotService)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
|
|
|
}
|
|
|
|
boards.botService = botService
|
|
|
|
case app.ClusterKey:
|
|
|
|
clusterService, ok := service.(product.ClusterService)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
|
|
|
}
|
|
|
|
boards.clusterService = clusterService
|
|
|
|
case app.ConfigKey:
|
|
|
|
configService, ok := service.(product.ConfigService)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
|
|
|
}
|
|
|
|
boards.configService = configService
|
|
|
|
case app.LogKey:
|
|
|
|
logger, ok := service.(mlog.LoggerIFace)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
|
|
|
}
|
|
|
|
boards.logger = logger.With(mlog.String("product", boardsProductName))
|
|
|
|
case app.LicenseKey:
|
|
|
|
licenseService, ok := service.(product.LicenseService)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
|
|
|
}
|
|
|
|
boards.licenseService = licenseService
|
|
|
|
case app.FilestoreKey:
|
|
|
|
filestoreService, ok := service.(product.FilestoreService)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
|
|
|
}
|
|
|
|
boards.filestoreService = filestoreService
|
|
|
|
case app.FileInfoStoreKey:
|
|
|
|
fileInfoStoreService, ok := service.(product.FileInfoStoreService)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
|
|
|
}
|
|
|
|
boards.fileInfoStoreService = fileInfoStoreService
|
|
|
|
case app.RouterKey:
|
|
|
|
routerService, ok := service.(product.RouterService)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
|
|
|
}
|
|
|
|
boards.routerService = routerService
|
|
|
|
case app.CloudKey:
|
|
|
|
cloudService, ok := service.(product.CloudService)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
|
|
|
}
|
|
|
|
boards.cloudService = cloudService
|
|
|
|
case app.KVStoreKey:
|
|
|
|
kvStoreService, ok := service.(product.KVStoreService)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
|
|
|
}
|
|
|
|
boards.kvStoreService = kvStoreService
|
|
|
|
case app.StoreKey:
|
|
|
|
storeService, ok := service.(product.StoreService)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
|
|
|
}
|
|
|
|
boards.storeService = storeService
|
|
|
|
case app.SystemKey:
|
|
|
|
systemService, ok := service.(product.SystemService)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("invalid service key '%s': %w", key, errServiceTypeAssert)
|
|
|
|
}
|
|
|
|
boards.systemService = systemService
|
|
|
|
case app.HooksKey: // not needed
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return boards, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bp *boardsProduct) Start() error {
|
|
|
|
if !bp.configService.Config().FeatureFlags.BoardsProduct {
|
|
|
|
bp.logger.Info("Boards product disabled via feature flag")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
bp.logger.Info("Starting boards service")
|
|
|
|
|
|
|
|
adapter := newServiceAPIAdapter(bp)
|
|
|
|
boardsApp, err := boards.NewBoardsApp(adapter)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to create Boards service: %w", err)
|
|
|
|
}
|
|
|
|
|
2022-08-19 19:16:18 +02:00
|
|
|
model.LogServerInfo(bp.logger)
|
|
|
|
|
2022-07-18 19:21:57 +02:00
|
|
|
bp.boardsApp = boardsApp
|
|
|
|
if err := bp.boardsApp.Start(); err != nil {
|
|
|
|
return fmt.Errorf("failed to start Boards service: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bp *boardsProduct) Stop() error {
|
|
|
|
bp.logger.Info("Stopping boards service")
|
|
|
|
|
|
|
|
if bp.boardsApp == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := bp.boardsApp.Stop(); err != nil {
|
|
|
|
return fmt.Errorf("error while stopping Boards service: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// These callbacks are called by the suite automatically
|
|
|
|
//
|
|
|
|
|
|
|
|
func (bp *boardsProduct) OnConfigurationChange() error {
|
|
|
|
if bp.boardsApp == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return bp.boardsApp.OnConfigurationChange()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bp *boardsProduct) OnWebSocketConnect(webConnID, userID string) {
|
|
|
|
if bp.boardsApp == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
bp.boardsApp.OnWebSocketConnect(webConnID, userID)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bp *boardsProduct) OnWebSocketDisconnect(webConnID, userID string) {
|
|
|
|
if bp.boardsApp == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
bp.boardsApp.OnWebSocketDisconnect(webConnID, userID)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bp *boardsProduct) WebSocketMessageHasBeenPosted(webConnID, userID string, req *mm_model.WebSocketRequest) {
|
|
|
|
if bp.boardsApp == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
bp.boardsApp.WebSocketMessageHasBeenPosted(webConnID, userID, req)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bp *boardsProduct) OnPluginClusterEvent(ctx *plugin.Context, ev mm_model.PluginClusterEvent) {
|
|
|
|
if bp.boardsApp == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
bp.boardsApp.OnPluginClusterEvent(ctx, ev)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bp *boardsProduct) MessageWillBePosted(ctx *plugin.Context, post *mm_model.Post) (*mm_model.Post, string) {
|
|
|
|
if bp.boardsApp == nil {
|
|
|
|
return post, ""
|
|
|
|
}
|
|
|
|
return bp.boardsApp.MessageWillBePosted(ctx, post)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bp *boardsProduct) MessageWillBeUpdated(ctx *plugin.Context, newPost, oldPost *mm_model.Post) (*mm_model.Post, string) {
|
|
|
|
if bp.boardsApp == nil {
|
|
|
|
return newPost, ""
|
|
|
|
}
|
|
|
|
return bp.boardsApp.MessageWillBeUpdated(ctx, newPost, oldPost)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bp *boardsProduct) OnCloudLimitsUpdated(limits *mm_model.ProductLimits) {
|
|
|
|
if bp.boardsApp == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
bp.boardsApp.OnCloudLimitsUpdated(limits)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bp *boardsProduct) RunDataRetention(nowTime, batchSize int64) (int64, error) {
|
|
|
|
if bp.boardsApp == nil {
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
return bp.boardsApp.RunDataRetention(nowTime, batchSize)
|
|
|
|
}
|