[MM-53156] Remove Multi-Product architecture (#25669)

Этот коммит содержится в:
Ben Schumacher
2024-02-15 13:01:44 +01:00
коммит произвёл GitHub
родитель d3b799eaa5
Коммит de3e5aab25
42 изменённых файлов: 86 добавлений и 2240 удалений

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

@@ -4,7 +4,6 @@
package app
import (
"fmt"
"runtime"
"strings"
"sync"
@@ -16,31 +15,26 @@ import (
"github.com/mattermost/mattermost/server/public/shared/mlog"
"github.com/mattermost/mattermost/server/public/shared/request"
"github.com/mattermost/mattermost/server/v8/channels/app/imaging"
"github.com/mattermost/mattermost/server/v8/channels/product"
"github.com/mattermost/mattermost/server/v8/config"
"github.com/mattermost/mattermost/server/v8/einterfaces"
"github.com/mattermost/mattermost/server/v8/platform/services/imageproxy"
"github.com/mattermost/mattermost/server/v8/platform/shared/filestore"
)
const ServerKey product.ServiceKey = "server"
// licenseSvc is added to act as a starting point for future integrated products.
// It has the same signature and functionality with the license related APIs of the plugin-api.
type licenseSvc interface {
GetLicense() *model.License
RequestTrialLicense(requesterID string, users int, termsAccepted bool, receiveEmailsAccepted bool) *model.AppError
RequestTrialLicenseWithExtraFields(requesterID string, trialRequest *model.TrialLicenseRequest) *model.AppError
type configService interface {
Config() *model.Config
AddConfigListener(listener func(*model.Config, *model.Config)) string
RemoveConfigListener(id string)
UpdateConfig(f func(*model.Config))
SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) (*model.Config, *model.Config, *model.AppError)
}
// Channels contains all channels related state.
type Channels struct {
srv *Server
cfgSvc product.ConfigService
cfgSvc configService
filestore filestore.FileBackend
exportFilestore filestore.FileBackend
licenseSvc licenseSvc
routerSvc *routerService
postActionCookieSecret []byte
@@ -84,76 +78,16 @@ type Channels struct {
postReminderTask *model.ScheduledTask
}
func init() {
product.RegisterProduct("channels", product.Manifest{
Initializer: func(services map[product.ServiceKey]any) (product.Product, error) {
return NewChannels(services)
},
Dependencies: map[product.ServiceKey]struct{}{
ServerKey: {},
product.ConfigKey: {},
product.LicenseKey: {},
product.FilestoreKey: {},
product.ExportFilestoreKey: {},
},
})
}
func NewChannels(services map[product.ServiceKey]any) (*Channels, error) {
s, ok := services[ServerKey].(*Server)
if !ok {
return nil, errors.New("server not passed")
}
func NewChannels(s *Server) (*Channels, error) {
ch := &Channels{
srv: s,
imageProxy: imageproxy.MakeImageProxy(s.platform, s.httpService, s.Log()),
uploadLockMap: map[string]bool{},
srv: s,
imageProxy: imageproxy.MakeImageProxy(s.platform, s.httpService, s.Log()),
uploadLockMap: map[string]bool{},
filestore: s.FileBackend(),
exportFilestore: s.ExportFileBackend(),
cfgSvc: s.Platform(),
}
// To get another service:
// 1. Prepare the service interface
// 2. Add the field to *Channels
// 3. Add the service key to the slice.
// 4. Add a new case in the switch statement.
requiredServices := []product.ServiceKey{
product.ConfigKey,
product.LicenseKey,
product.FilestoreKey,
product.ExportFilestoreKey,
}
for _, svcKey := range requiredServices {
svc, ok := services[svcKey]
if !ok {
return nil, fmt.Errorf("Service %s not passed", svcKey)
}
switch svcKey {
// Keep adding more services here
case product.ConfigKey:
cfgSvc, ok := svc.(product.ConfigService)
if !ok {
return nil, errors.New("Config service did not satisfy ConfigSvc interface")
}
ch.cfgSvc = cfgSvc
case product.FilestoreKey:
filestore, ok := svc.(filestore.FileBackend)
if !ok {
return nil, errors.New("Filestore service did not satisfy FileBackend interface")
}
ch.filestore = filestore
case product.ExportFilestoreKey:
exportFilestore, ok := svc.(filestore.FileBackend)
if !ok {
return nil, errors.New("Export filestore service did not satisfy FileBackend interface")
}
ch.exportFilestore = exportFilestore
case product.LicenseKey:
svc, ok := svc.(licenseSvc)
if !ok {
return nil, errors.New("License service did not satisfy licenseSvc interface")
}
ch.licenseSvc = svc
}
}
// We are passing a partially filled Channels struct so that the enterprise
// methods can have access to app methods.
// Otherwise, passing server would mean it has to call s.Channels(),
@@ -207,45 +141,12 @@ func NewChannels(services map[product.ServiceKey]any) (*Channels, error) {
return nil, errors.Wrap(imgErr, "failed to create image encoder")
}
ch.routerSvc = newRouterService()
services[product.RouterKey] = ch.routerSvc
// Setup routes.
pluginsRoute := ch.srv.Router.PathPrefix("/plugins/{plugin_id:[A-Za-z0-9\\_\\-\\.]+}").Subrouter()
pluginsRoute.HandleFunc("", ch.ServePluginRequest)
pluginsRoute.HandleFunc("/public/{public_file:.*}", ch.ServePluginPublicRequest)
pluginsRoute.HandleFunc("/{anything:.*}", ch.ServePluginRequest)
services[product.ChannelKey] = &channelsWrapper{
app: &App{ch: ch},
}
services[product.PostKey] = &postServiceWrapper{
app: &App{ch: ch},
}
services[product.PermissionsKey] = &permissionsServiceWrapper{
app: &App{ch: ch},
}
services[product.TeamKey] = &teamServiceWrapper{
app: &App{ch: ch},
}
services[product.BotKey] = &botServiceWrapper{
app: &App{ch: ch},
}
services[product.UserKey] = &App{ch: ch}
services[product.PreferencesKey] = &preferencesServiceWrapper{
app: &App{ch: ch},
}
services[product.CommandKey] = &App{ch: ch}
services[product.ThreadsKey] = &App{ch: ch}
return ch, nil
}
@@ -314,35 +215,22 @@ func (ch *Channels) RemoveConfigListener(id string) {
ch.cfgSvc.RemoveConfigListener(id)
}
func (ch *Channels) License() *model.License {
return ch.licenseSvc.GetLicense()
}
func (ch *Channels) RequestTrialLicenseWithExtraFields(requesterID string, trialRequest *model.TrialLicenseRequest) *model.AppError {
return ch.licenseSvc.RequestTrialLicenseWithExtraFields(requesterID, trialRequest)
}
func (ch *Channels) RequestTrialLicense(requesterID string, users int, termsAccepted bool, receiveEmailsAccepted bool) *model.AppError {
return ch.licenseSvc.RequestTrialLicense(requesterID, users, termsAccepted,
receiveEmailsAccepted)
}
func (ch *Channels) RunMultiHook(hookRunnerFunc func(hooks plugin.Hooks) bool, hookId int) {
if env := ch.GetPluginsEnvironment(); env != nil {
env.RunMultiPluginHook(hookRunnerFunc, hookId)
}
}
func (ch *Channels) HooksForPluginOrProduct(id string) (plugin.Hooks, error) {
var hooks plugin.Hooks
if env := ch.GetPluginsEnvironment(); env != nil {
// we intentionally ignore the error here, because the id can be a product id
// we are going to check if we have the hooks or not
hooks, _ = env.HooksForPlugin(id)
if hooks != nil {
return hooks, nil
}
func (ch *Channels) HooksForPlugin(id string) (plugin.Hooks, error) {
env := ch.GetPluginsEnvironment()
if env == nil {
return nil, errors.New("plugins are not initialized")
}
return nil, fmt.Errorf("could not find hooks for id %s", id)
hooks, err := env.HooksForPlugin(id)
if err != nil {
return nil, err
}
return hooks, nil
}