Merge in master.
Этот коммит содержится в:
@@ -139,20 +139,22 @@ func changeSubscription(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
changedProduct, err := c.App.Cloud().GetCloudProduct(userId, changedSub.ProductID)
|
product, err := c.App.Cloud().GetCloudProduct(c.AppContext.Session().UserId, subscriptionChange.ProductID)
|
||||||
if err != nil {
|
if err != nil || product == nil {
|
||||||
c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
c.Logger.Error("Error finding the new cloud product", mlog.Err(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
starterSku := fmt.Sprintf("%s-%s", model.SubscriptionFamilyCloud, model.ProductSkuStarter)
|
starterSku := fmt.Sprintf("%s-%s", model.SubscriptionFamilyCloud, model.ProductSkuStarter)
|
||||||
if changedProduct.SKU != starterSku {
|
if product.SKU != starterSku {
|
||||||
w.Write(json)
|
w.Write(json)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isYearly := product.IsYearly()
|
||||||
|
|
||||||
// Log failures for purchase confirmation email, but don't show an error to the user so as not to confuse them
|
// Log failures for purchase confirmation email, but don't show an error to the user so as not to confuse them
|
||||||
// At this point, the upgrade is complete.
|
// At this point, the upgrade is complete.
|
||||||
if appErr := c.App.SendUpgradeConfirmationEmail(); appErr != nil {
|
if appErr := c.App.SendUpgradeConfirmationEmail(isYearly); appErr != nil {
|
||||||
c.Logger.Error("Error sending purchase confirmation email", mlog.Err(appErr))
|
c.Logger.Error("Error sending purchase confirmation email", mlog.Err(appErr))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -650,7 +652,26 @@ func handleCWSWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
case model.EventTypeSendUpgradeConfirmationEmail:
|
case model.EventTypeSendUpgradeConfirmationEmail:
|
||||||
if nErr := c.App.SendUpgradeConfirmationEmail(); nErr != nil {
|
|
||||||
|
// isYearly determines whether to send the yearly or monthly Upgrade email
|
||||||
|
isYearly := false
|
||||||
|
if event.Subscription != nil && event.CloudWorkspaceOwner != nil {
|
||||||
|
user, appErr := c.App.GetUserByUsername(event.CloudWorkspaceOwner.UserName)
|
||||||
|
if appErr != nil {
|
||||||
|
c.Err = model.NewAppError("Api4.handleCWSWebhook", appErr.Id, nil, appErr.Error(), appErr.StatusCode)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current cloud product to determine whether it's a monthly or yearly product
|
||||||
|
product, err := c.App.Cloud().GetCloudProduct(user.Id, event.Subscription.ProductID)
|
||||||
|
if err != nil {
|
||||||
|
c.Err = model.NewAppError("Api4.handleCWSWebhook", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
isYearly = product.IsYearly()
|
||||||
|
}
|
||||||
|
|
||||||
|
if nErr := c.App.SendUpgradeConfirmationEmail(isYearly); nErr != nil {
|
||||||
c.Err = nErr
|
c.Err = nErr
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ func connectWebSocket(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wc := c.App.Srv().Platform().NewWebConn(cfg, c.App, c.App.Srv().Channels().GetPluginsEnvironment)
|
wc := c.App.Srv().Platform().NewWebConn(cfg, c.App, c.App.Srv().Channels())
|
||||||
if c.AppContext.Session().UserId != "" {
|
if c.AppContext.Session().UserId != "" {
|
||||||
c.App.Srv().Platform().HubRegister(wc)
|
c.App.Srv().Platform().HubRegister(wc)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1038,7 +1038,7 @@ type AppIface interface {
|
|||||||
SendPasswordReset(email string, siteURL string) (bool, *model.AppError)
|
SendPasswordReset(email string, siteURL string) (bool, *model.AppError)
|
||||||
SendPaymentFailedEmail(failedPayment *model.FailedPayment) *model.AppError
|
SendPaymentFailedEmail(failedPayment *model.FailedPayment) *model.AppError
|
||||||
SendTestPushNotification(deviceID string) string
|
SendTestPushNotification(deviceID string) string
|
||||||
SendUpgradeConfirmationEmail() *model.AppError
|
SendUpgradeConfirmationEmail(isYearly bool) *model.AppError
|
||||||
ServeInterPluginRequest(w http.ResponseWriter, r *http.Request, sourcePluginId, destinationPluginId string)
|
ServeInterPluginRequest(w http.ResponseWriter, r *http.Request, sourcePluginId, destinationPluginId string)
|
||||||
SessionHasPermissionTo(session model.Session, permission *model.Permission) bool
|
SessionHasPermissionTo(session model.Session, permission *model.Permission) bool
|
||||||
SessionHasPermissionToAny(session model.Session, permissions []*model.Permission) bool
|
SessionHasPermissionToAny(session model.Session, permissions []*model.Permission) bool
|
||||||
|
|||||||
@@ -346,7 +346,7 @@ func (a *App) CreateChannel(c request.CTX, channel *model.Channel, addMember boo
|
|||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.ChannelHasBeenCreated(pluginContext, sc)
|
hooks.ChannelHasBeenCreated(pluginContext, sc)
|
||||||
return true
|
return true
|
||||||
}, plugin.ChannelHasBeenCreatedID)
|
}, plugin.ChannelHasBeenCreatedID)
|
||||||
@@ -432,7 +432,7 @@ func (a *App) handleCreationEvent(c request.CTX, userID, otherUserID string, cha
|
|||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.ChannelHasBeenCreated(pluginContext, channel)
|
hooks.ChannelHasBeenCreated(pluginContext, channel)
|
||||||
return true
|
return true
|
||||||
}, plugin.ChannelHasBeenCreatedID)
|
}, plugin.ChannelHasBeenCreatedID)
|
||||||
@@ -1602,7 +1602,7 @@ func (a *App) AddChannelMember(c request.CTX, userID string, channel *model.Chan
|
|||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.UserHasJoinedChannel(pluginContext, cm, userRequestor)
|
hooks.UserHasJoinedChannel(pluginContext, cm, userRequestor)
|
||||||
return true
|
return true
|
||||||
}, plugin.UserHasJoinedChannelID)
|
}, plugin.UserHasJoinedChannelID)
|
||||||
@@ -2180,7 +2180,7 @@ func (a *App) JoinChannel(c request.CTX, channel *model.Channel, userID string)
|
|||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.UserHasJoinedChannel(pluginContext, cm, nil)
|
hooks.UserHasJoinedChannel(pluginContext, cm, nil)
|
||||||
return true
|
return true
|
||||||
}, plugin.UserHasJoinedChannelID)
|
}, plugin.UserHasJoinedChannelID)
|
||||||
@@ -2492,7 +2492,7 @@ func (a *App) removeUserFromChannel(c request.CTX, userIDToRemove string, remove
|
|||||||
|
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.UserHasLeftChannel(pluginContext, cm, actorUser)
|
hooks.UserHasLeftChannel(pluginContext, cm, actorUser)
|
||||||
return true
|
return true
|
||||||
}, plugin.UserHasLeftChannelID)
|
}, plugin.UserHasLeftChannelID)
|
||||||
|
|||||||
@@ -322,5 +322,33 @@ func (s *hooksService) RegisterHooks(productID string, hooks any) error {
|
|||||||
return errors.New("could not find plugins environment")
|
return errors.New("could not find plugins environment")
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.ch.pluginsEnvironment.AddProduct(productID, hooks)
|
return s.ch.srv.hooksManager.AddProduct(productID, hooks)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch *Channels) RunMultiHook(hookRunnerFunc func(hooks plugin.Hooks) bool, hookId int) {
|
||||||
|
if env := ch.pluginsEnvironment; env != nil {
|
||||||
|
env.RunMultiPluginHook(hookRunnerFunc, hookId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// run hook for the products
|
||||||
|
ch.srv.hooksManager.RunMultiHook(hookRunnerFunc, hookId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch *Channels) HooksForPluginOrProduct(id string) (plugin.Hooks, error) {
|
||||||
|
var hooks plugin.Hooks
|
||||||
|
if env := ch.pluginsEnvironment; 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hooks = ch.srv.hooksManager.HooksForProduct(id)
|
||||||
|
if hooks != nil {
|
||||||
|
return hooks, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("could not find hooks for id %s", id)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ func getNextBillingDateString() string {
|
|||||||
return fmt.Sprintf("%s %d, %d", t.Month(), t.Day(), t.Year())
|
return fmt.Sprintf("%s %d, %d", t.Month(), t.Day(), t.Year())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) SendUpgradeConfirmationEmail() *model.AppError {
|
func (a *App) SendUpgradeConfirmationEmail(isYearly bool) *model.AppError {
|
||||||
sysAdmins, e := a.getSysAdminsEmailRecipients()
|
sysAdmins, e := a.getSysAdminsEmailRecipients()
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return e
|
return e
|
||||||
@@ -200,7 +200,7 @@ func (a *App) SendUpgradeConfirmationEmail() *model.AppError {
|
|||||||
name = admin.Username
|
name = admin.Username
|
||||||
}
|
}
|
||||||
|
|
||||||
err := a.Srv().EmailService.SendCloudUpgradeConfirmationEmail(admin.Email, name, billingDate, admin.Locale, *a.Config().ServiceSettings.SiteURL, subscription.GetWorkSpaceNameFromDNS())
|
err := a.Srv().EmailService.SendCloudUpgradeConfirmationEmail(admin.Email, name, billingDate, admin.Locale, *a.Config().ServiceSettings.SiteURL, subscription.GetWorkSpaceNameFromDNS(), isYearly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.Log().Error("Error sending trial ended email to", mlog.String("email", admin.Email), mlog.Err(err))
|
a.Log().Error("Error sending trial ended email to", mlog.String("email", admin.Email), mlog.Err(err))
|
||||||
countNotOks++
|
countNotOks++
|
||||||
|
|||||||
@@ -28,10 +28,6 @@ func (s *Server) clusterRemovePluginHandler(msg *model.ClusterMessage) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) clusterPluginEventHandler(msg *model.ClusterMessage) {
|
func (s *Server) clusterPluginEventHandler(msg *model.ClusterMessage) {
|
||||||
env := s.Channels().GetPluginsEnvironment()
|
|
||||||
if env == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if msg.Props == nil {
|
if msg.Props == nil {
|
||||||
mlog.Warn("ClusterMessage.Props for plugin event should not be nil")
|
mlog.Warn("ClusterMessage.Props for plugin event should not be nil")
|
||||||
return
|
return
|
||||||
@@ -48,7 +44,12 @@ func (s *Server) clusterPluginEventHandler(msg *model.ClusterMessage) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hooks, err := env.HooksForPlugin(pluginID)
|
channels, ok := s.products["channels"].(*Channels)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
hooks, err := channels.HooksForPluginOrProduct(pluginID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mlog.Warn("Getting hooks for plugin failed", mlog.String("plugin_id", pluginID), mlog.Err(err))
|
mlog.Warn("Getting hooks for plugin failed", mlog.String("plugin_id", pluginID), mlog.Err(err))
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -233,13 +233,13 @@ func (es *Service) SendWelcomeEmail(userID string, email string, verified bool,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *Service) SendCloudUpgradeConfirmationEmail(userEmail, name, date, locale, siteURL, workspaceName string) error {
|
func (es *Service) SendCloudUpgradeConfirmationEmail(userEmail, name, date, locale, siteURL, workspaceName string, isYearly bool) error {
|
||||||
T := i18n.GetUserTranslations(locale)
|
T := i18n.GetUserTranslations(locale)
|
||||||
subject := T("api.templates.cloud_upgrade_confirmation.subject")
|
subject := T("api.templates.cloud_upgrade_confirmation.subject")
|
||||||
|
|
||||||
data := es.NewEmailTemplateData(locale)
|
data := es.NewEmailTemplateData(locale)
|
||||||
data.Props["Title"] = T("api.templates.cloud_upgrade_confirmation.title")
|
data.Props["Title"] = T("api.templates.cloud_upgrade_confirmation.title")
|
||||||
data.Props["SubTitle"] = T("api.templates.cloud_upgrade_confirmation.subtitle", map[string]any{"WorkspaceName": workspaceName, "Date": date})
|
data.Props["SubTitle"] = T("api.templates.cloud_upgrade_confirmation_monthly.subtitle", map[string]any{"WorkspaceName": workspaceName, "Date": date})
|
||||||
data.Props["SiteURL"] = siteURL
|
data.Props["SiteURL"] = siteURL
|
||||||
data.Props["ButtonURL"] = siteURL
|
data.Props["ButtonURL"] = siteURL
|
||||||
data.Props["Button"] = T("api.templates.cloud_welcome_email.button")
|
data.Props["Button"] = T("api.templates.cloud_welcome_email.button")
|
||||||
@@ -247,6 +247,12 @@ func (es *Service) SendCloudUpgradeConfirmationEmail(userEmail, name, date, loca
|
|||||||
data.Props["QuestionInfo"] = T("api.templates.questions_footer.info")
|
data.Props["QuestionInfo"] = T("api.templates.questions_footer.info")
|
||||||
data.Props["SupportEmail"] = *es.config().SupportSettings.SupportEmail
|
data.Props["SupportEmail"] = *es.config().SupportSettings.SupportEmail
|
||||||
|
|
||||||
|
if isYearly {
|
||||||
|
data.Props["SubTitle"] = T("api.templates.cloud_upgrade_confirmation_yearly.subtitle", map[string]any{"WorkspaceName": workspaceName})
|
||||||
|
data.Props["ButtonURL"] = siteURL + "/admin_console/billing/billing_history"
|
||||||
|
data.Props["Button"] = T("api.templates.cloud_welcome_email.yearly_plan_button")
|
||||||
|
}
|
||||||
|
|
||||||
body, err := es.templatesContainer.RenderToString("cloud_upgrade_confirmation", data)
|
body, err := es.templatesContainer.RenderToString("cloud_upgrade_confirmation", data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ func TestSendCloudUpgradedEmail(t *testing.T) {
|
|||||||
emailTo := "testclouduser@example.com"
|
emailTo := "testclouduser@example.com"
|
||||||
emailToUsername := strings.Split(emailTo, "@")[0]
|
emailToUsername := strings.Split(emailTo, "@")[0]
|
||||||
|
|
||||||
t.Run("SendCloudUpgradedEmail", func(t *testing.T) {
|
t.Run("SendCloudMonthlyUpgradedEmail", func(t *testing.T) {
|
||||||
verifyMailbox := func(t *testing.T) {
|
verifyMailbox := func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
@@ -278,10 +278,44 @@ func TestSendCloudUpgradedEmail(t *testing.T) {
|
|||||||
require.NoError(t, err, "Could not get message from mailbox")
|
require.NoError(t, err, "Could not get message from mailbox")
|
||||||
require.Contains(t, resultsEmail.Body.Text, "You are now upgraded!", "Wrong received message %s", resultsEmail.Body.Text)
|
require.Contains(t, resultsEmail.Body.Text, "You are now upgraded!", "Wrong received message %s", resultsEmail.Body.Text)
|
||||||
require.Contains(t, resultsEmail.Body.Text, "SomeName workspace has now been upgraded", "Wrong received message %s", resultsEmail.Body.Text)
|
require.Contains(t, resultsEmail.Body.Text, "SomeName workspace has now been upgraded", "Wrong received message %s", resultsEmail.Body.Text)
|
||||||
|
require.Contains(t, resultsEmail.Body.Text, "You'll be billed from", "Wrong received message %s", resultsEmail.Body.Text)
|
||||||
|
require.Contains(t, resultsEmail.Body.Text, "Open Mattermost", "Wrong received message %s", resultsEmail.Body.Text)
|
||||||
}
|
}
|
||||||
mail.DeleteMailBox(emailTo)
|
mail.DeleteMailBox(emailTo)
|
||||||
|
|
||||||
err := th.service.SendCloudUpgradeConfirmationEmail(emailTo, emailToUsername, "June 23, 2200", th.BasicUser.Locale, "https://example.com", "SomeName")
|
// Send Update to Monthly Plan email
|
||||||
|
err := th.service.SendCloudUpgradeConfirmationEmail(emailTo, emailToUsername, "June 23, 2200", th.BasicUser.Locale, "https://example.com", "SomeName", false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
verifyMailbox(t)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("SendCloudYearlyUpgradedEmail", func(t *testing.T) {
|
||||||
|
verifyMailbox := func(t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
var resultsMailbox mail.JSONMessageHeaderInbucket
|
||||||
|
err2 := mail.RetryInbucket(5, func() error {
|
||||||
|
var err error
|
||||||
|
resultsMailbox, err = mail.GetMailBox(emailTo)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err2 != nil {
|
||||||
|
t.Skipf("No email was received, maybe due load on the server: %v", err2)
|
||||||
|
}
|
||||||
|
|
||||||
|
require.Len(t, resultsMailbox, 1)
|
||||||
|
require.Contains(t, resultsMailbox[0].To[0], emailTo, "Wrong To: recipient")
|
||||||
|
resultsEmail, err := mail.GetMessageFromMailbox(emailTo, resultsMailbox[0].ID)
|
||||||
|
require.NoError(t, err, "Could not get message from mailbox")
|
||||||
|
require.Contains(t, resultsEmail.Body.Text, "You are now upgraded!", "Wrong received message %s", resultsEmail.Body.Text)
|
||||||
|
require.Contains(t, resultsEmail.Body.Text, "SomeName workspace has now been upgraded", "Wrong received message %s", resultsEmail.Body.Text)
|
||||||
|
require.Contains(t, resultsEmail.Body.Text, "View your invoice", "Wrong received message %s", resultsEmail.Body.Text)
|
||||||
|
}
|
||||||
|
mail.DeleteMailBox(emailTo)
|
||||||
|
|
||||||
|
// Send Update to Monthly Plan email
|
||||||
|
err := th.service.SendCloudUpgradeConfirmationEmail(emailTo, emailToUsername, "June 23, 2200", th.BasicUser.Locale, "https://example.com", "SomeName", true)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
verifyMailbox(t)
|
verifyMailbox(t)
|
||||||
|
|||||||
@@ -125,13 +125,13 @@ func (_m *ServiceInterface) SendChangeUsernameEmail(newUsername string, _a1 stri
|
|||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendCloudUpgradeConfirmationEmail provides a mock function with given fields: userEmail, name, trialEndDate, locale, siteURL, workspaceName
|
// SendCloudUpgradeConfirmationEmail provides a mock function with given fields: userEmail, name, trialEndDate, locale, siteURL, workspaceName, isYearly
|
||||||
func (_m *ServiceInterface) SendCloudUpgradeConfirmationEmail(userEmail string, name string, trialEndDate string, locale string, siteURL string, workspaceName string) error {
|
func (_m *ServiceInterface) SendCloudUpgradeConfirmationEmail(userEmail string, name string, trialEndDate string, locale string, siteURL string, workspaceName string, isYearly bool) error {
|
||||||
ret := _m.Called(userEmail, name, trialEndDate, locale, siteURL, workspaceName)
|
ret := _m.Called(userEmail, name, trialEndDate, locale, siteURL, workspaceName, isYearly)
|
||||||
|
|
||||||
var r0 error
|
var r0 error
|
||||||
if rf, ok := ret.Get(0).(func(string, string, string, string, string, string) error); ok {
|
if rf, ok := ret.Get(0).(func(string, string, string, string, string, string, bool) error); ok {
|
||||||
r0 = rf(userEmail, name, trialEndDate, locale, siteURL, workspaceName)
|
r0 = rf(userEmail, name, trialEndDate, locale, siteURL, workspaceName, isYearly)
|
||||||
} else {
|
} else {
|
||||||
r0 = ret.Error(0)
|
r0 = ret.Error(0)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ type ServiceInterface interface {
|
|||||||
SendVerifyEmail(userEmail, locale, siteURL, token, redirect string) error
|
SendVerifyEmail(userEmail, locale, siteURL, token, redirect string) error
|
||||||
SendSignInChangeEmail(email, method, locale, siteURL string) error
|
SendSignInChangeEmail(email, method, locale, siteURL string) error
|
||||||
SendWelcomeEmail(userID string, email string, verified bool, disableWelcomeEmail bool, locale, siteURL, redirect string) error
|
SendWelcomeEmail(userID string, email string, verified bool, disableWelcomeEmail bool, locale, siteURL, redirect string) error
|
||||||
SendCloudUpgradeConfirmationEmail(userEmail, name, trialEndDate, locale, siteURL, workspaceName string) error
|
SendCloudUpgradeConfirmationEmail(userEmail, name, trialEndDate, locale, siteURL, workspaceName string, isYearly bool) error
|
||||||
SendCloudWelcomeEmail(userEmail, locale, teamInviteID, workSpaceName, dns, siteURL string) error
|
SendCloudWelcomeEmail(userEmail, locale, teamInviteID, workSpaceName, dns, siteURL string) error
|
||||||
SendPasswordChangeEmail(email, method, locale, siteURL string) error
|
SendPasswordChangeEmail(email, method, locale, siteURL string) error
|
||||||
SendUserAccessTokenAddedEmail(email, locale, siteURL string) error
|
SendUserAccessTokenAddedEmail(email, locale, siteURL string) error
|
||||||
|
|||||||
@@ -898,7 +898,7 @@ func (a *App) DoUploadFileExpectModification(c request.CTX, now time.Time, rawTe
|
|||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
var rejectionError *model.AppError
|
var rejectionError *model.AppError
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
var newBytes bytes.Buffer
|
var newBytes bytes.Buffer
|
||||||
replacementInfo, rejectionReason := hooks.FileWillBeUploaded(pluginContext, info, bytes.NewReader(data), &newBytes)
|
replacementInfo, rejectionReason := hooks.FileWillBeUploaded(pluginContext, info, bytes.NewReader(data), &newBytes)
|
||||||
if rejectionReason != "" {
|
if rejectionReason != "" {
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ func (a *App) DoLogin(c *request.Context, w http.ResponseWriter, r *http.Request
|
|||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
var rejectionReason string
|
var rejectionReason string
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
rejectionReason = hooks.UserWillLogIn(pluginContext, user)
|
rejectionReason = hooks.UserWillLogIn(pluginContext, user)
|
||||||
return rejectionReason == ""
|
return rejectionReason == ""
|
||||||
}, plugin.UserWillLogInID)
|
}, plugin.UserWillLogInID)
|
||||||
@@ -229,7 +229,7 @@ func (a *App) DoLogin(c *request.Context, w http.ResponseWriter, r *http.Request
|
|||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.UserHasLoggedIn(pluginContext, user)
|
hooks.UserHasLoggedIn(pluginContext, user)
|
||||||
return true
|
return true
|
||||||
}, plugin.UserHasLoggedInID)
|
}, plugin.UserHasLoggedInID)
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ func (a *App) CompleteOnboarding(c *request.Context, request *model.CompleteOnbo
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hooks, err := pluginsEnvironment.HooksForPlugin(id)
|
hooks, err := a.ch.HooksForPluginOrProduct(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mlog.Warn("Getting hooks for plugin failed", mlog.String("plugin_id", id), mlog.Err(err))
|
mlog.Warn("Getting hooks for plugin failed", mlog.String("plugin_id", id), mlog.Err(err))
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -15546,7 +15546,7 @@ func (a *OpenTracingAppLayer) SendTestPushNotification(deviceID string) string {
|
|||||||
return resultVar0
|
return resultVar0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) SendUpgradeConfirmationEmail() *model.AppError {
|
func (a *OpenTracingAppLayer) SendUpgradeConfirmationEmail(isYearly bool) *model.AppError {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SendUpgradeConfirmationEmail")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SendUpgradeConfirmationEmail")
|
||||||
|
|
||||||
@@ -15558,7 +15558,7 @@ func (a *OpenTracingAppLayer) SendUpgradeConfirmationEmail() *model.AppError {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
resultVar0 := a.app.SendUpgradeConfirmationEmail()
|
resultVar0 := a.app.SendUpgradeConfirmationEmail(isYearly)
|
||||||
|
|
||||||
if resultVar0 != nil {
|
if resultVar0 != nil {
|
||||||
span.LogFields(spanlog.Error(resultVar0))
|
span.LogFields(spanlog.Error(resultVar0))
|
||||||
|
|||||||
@@ -95,7 +95,12 @@ type PlatformService struct {
|
|||||||
additionalClusterHandlers map[model.ClusterEvent]einterfaces.ClusterMessageHandler
|
additionalClusterHandlers map[model.ClusterEvent]einterfaces.ClusterMessageHandler
|
||||||
sharedChannelService SharedChannelServiceIFace
|
sharedChannelService SharedChannelServiceIFace
|
||||||
|
|
||||||
pluginEnv *plugin.Environment
|
pluginEnv HookRunner
|
||||||
|
}
|
||||||
|
|
||||||
|
type HookRunner interface {
|
||||||
|
RunMultiHook(hookRunnerFunc func(hooks plugin.Hooks) bool, hookId int)
|
||||||
|
GetPluginsEnvironment() *plugin.Environment
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new PlatformService.
|
// New creates a new PlatformService.
|
||||||
@@ -426,17 +431,17 @@ func (ps *PlatformService) SetSharedChannelService(s SharedChannelServiceIFace)
|
|||||||
ps.sharedChannelService = s
|
ps.sharedChannelService = s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ps *PlatformService) SetPluginsEnvironment(env *plugin.Environment) {
|
func (ps *PlatformService) SetPluginsEnvironment(runner HookRunner) {
|
||||||
ps.pluginEnv = env
|
ps.pluginEnv = runner
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPluginStatuses meant to be used by cluster implementation
|
// GetPluginStatuses meant to be used by cluster implementation
|
||||||
func (ps *PlatformService) GetPluginStatuses() (model.PluginStatuses, *model.AppError) {
|
func (ps *PlatformService) GetPluginStatuses() (model.PluginStatuses, *model.AppError) {
|
||||||
if ps.pluginEnv == nil {
|
if ps.pluginEnv == nil || ps.pluginEnv.GetPluginsEnvironment() == nil {
|
||||||
return nil, model.NewAppError("GetPluginStatuses", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
|
return nil, model.NewAppError("GetPluginStatuses", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginStatuses, err := ps.pluginEnv.Statuses()
|
pluginStatuses, err := ps.pluginEnv.GetPluginsEnvironment().Statuses()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, model.NewAppError("GetPluginStatuses", "app.plugin.get_statuses.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
return nil, model.NewAppError("GetPluginStatuses", "app.plugin.get_statuses.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,15 +72,15 @@ type WebConnConfig struct {
|
|||||||
// It contains all the necessary state to manage sending/receiving data to/from
|
// It contains all the necessary state to manage sending/receiving data to/from
|
||||||
// a websocket.
|
// a websocket.
|
||||||
type WebConn struct {
|
type WebConn struct {
|
||||||
sessionExpiresAt int64 // This should stay at the top for 64-bit alignment of 64-bit words accessed atomically
|
sessionExpiresAt int64 // This should stay at the top for 64-bit alignment of 64-bit words accessed atomically
|
||||||
Platform *PlatformService
|
Platform *PlatformService
|
||||||
Suite SuiteIFace
|
Suite SuiteIFace
|
||||||
PluginsEnvironment func() *plugin.Environment
|
HookRunner HookRunner
|
||||||
WebSocket *websocket.Conn
|
WebSocket *websocket.Conn
|
||||||
T i18n.TranslateFunc
|
T i18n.TranslateFunc
|
||||||
Locale string
|
Locale string
|
||||||
Sequence int64
|
Sequence int64
|
||||||
UserId string
|
UserId string
|
||||||
|
|
||||||
allChannelMembers map[string]string
|
allChannelMembers map[string]string
|
||||||
lastAllChannelMembersTime int64
|
lastAllChannelMembersTime int64
|
||||||
@@ -162,7 +162,7 @@ func (ps *PlatformService) PopulateWebConnConfig(s *model.Session, cfg *WebConnC
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewWebConn returns a new WebConn instance.
|
// NewWebConn returns a new WebConn instance.
|
||||||
func (ps *PlatformService) NewWebConn(cfg *WebConnConfig, suite SuiteIFace, envFn func() *plugin.Environment) *WebConn {
|
func (ps *PlatformService) NewWebConn(cfg *WebConnConfig, suite SuiteIFace, runner HookRunner) *WebConn {
|
||||||
if cfg.Session.UserId != "" {
|
if cfg.Session.UserId != "" {
|
||||||
ps.Go(func() {
|
ps.Go(func() {
|
||||||
suite.SetStatusOnline(cfg.Session.UserId, false)
|
suite.SetStatusOnline(cfg.Session.UserId, false)
|
||||||
@@ -200,7 +200,7 @@ func (ps *PlatformService) NewWebConn(cfg *WebConnConfig, suite SuiteIFace, envF
|
|||||||
wc := &WebConn{
|
wc := &WebConn{
|
||||||
Platform: ps,
|
Platform: ps,
|
||||||
Suite: suite,
|
Suite: suite,
|
||||||
PluginsEnvironment: envFn,
|
HookRunner: runner,
|
||||||
send: cfg.activeQueue,
|
send: cfg.activeQueue,
|
||||||
deadQueue: cfg.deadQueue,
|
deadQueue: cfg.deadQueue,
|
||||||
deadQueuePointer: cfg.deadQueuePointer,
|
deadQueuePointer: cfg.deadQueuePointer,
|
||||||
@@ -222,14 +222,12 @@ func (ps *PlatformService) NewWebConn(cfg *WebConnConfig, suite SuiteIFace, envF
|
|||||||
wc.SetSessionExpiresAt(cfg.Session.ExpiresAt)
|
wc.SetSessionExpiresAt(cfg.Session.ExpiresAt)
|
||||||
wc.SetConnectionID(cfg.ConnectionID)
|
wc.SetConnectionID(cfg.ConnectionID)
|
||||||
|
|
||||||
if pluginsEnvironment := wc.PluginsEnvironment(); pluginsEnvironment != nil {
|
wc.Platform.Go(func() {
|
||||||
wc.Platform.Go(func() {
|
wc.HookRunner.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
hooks.OnWebSocketConnect(wc.GetConnectionID(), wc.UserId)
|
||||||
hooks.OnWebSocketConnect(wc.GetConnectionID(), wc.UserId)
|
return true
|
||||||
return true
|
}, plugin.OnWebSocketConnectID)
|
||||||
}, plugin.OnWebSocketConnectID)
|
})
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return wc
|
return wc
|
||||||
}
|
}
|
||||||
@@ -238,12 +236,10 @@ func (wc *WebConn) pluginPostedConsumer(wg *sync.WaitGroup) {
|
|||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
for msg := range wc.pluginPosted {
|
for msg := range wc.pluginPosted {
|
||||||
if pluginsEnvironment := wc.PluginsEnvironment(); pluginsEnvironment != nil {
|
wc.HookRunner.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
hooks.WebSocketMessageHasBeenPosted(msg.connectionID, msg.userID, msg.req)
|
||||||
hooks.WebSocketMessageHasBeenPosted(msg.connectionID, msg.userID, msg.req)
|
return true
|
||||||
return true
|
}, plugin.WebSocketMessageHasBeenPostedID)
|
||||||
}, plugin.WebSocketMessageHasBeenPostedID)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,14 +324,12 @@ func (wc *WebConn) Pump() {
|
|||||||
wc.Platform.HubUnregister(wc)
|
wc.Platform.HubUnregister(wc)
|
||||||
close(wc.pumpFinished)
|
close(wc.pumpFinished)
|
||||||
|
|
||||||
if pluginsEnvironment := wc.PluginsEnvironment(); pluginsEnvironment != nil {
|
wc.Platform.Go(func() {
|
||||||
wc.Platform.Go(func() {
|
wc.HookRunner.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
hooks.OnWebSocketDisconnect(wc.GetConnectionID(), wc.UserId)
|
||||||
hooks.OnWebSocketDisconnect(wc.GetConnectionID(), wc.UserId)
|
return true
|
||||||
return true
|
}, plugin.OnWebSocketDisconnectID)
|
||||||
}, plugin.OnWebSocketDisconnectID)
|
})
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wc *WebConn) readPump() {
|
func (wc *WebConn) readPump() {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package platform
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
@@ -18,13 +19,27 @@ import (
|
|||||||
"github.com/mattermost/mattermost-server/v6/plugin"
|
"github.com/mattermost/mattermost-server/v6/plugin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type hookRunner struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *hookRunner) RunMultiHook(hookRunnerFunc func(hooks plugin.Hooks) bool, hookId int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
func (h *hookRunner) HooksForPlugin(id string) (plugin.Hooks, error) {
|
||||||
|
return nil, errors.New("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *hookRunner) GetPluginsEnvironment() *plugin.Environment {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestWebConnAddDeadQueue(t *testing.T) {
|
func TestWebConnAddDeadQueue(t *testing.T) {
|
||||||
th := Setup(t)
|
th := Setup(t)
|
||||||
defer th.TearDown()
|
defer th.TearDown()
|
||||||
|
|
||||||
wc := th.Service.NewWebConn(&WebConnConfig{
|
wc := th.Service.NewWebConn(&WebConnConfig{
|
||||||
WebSocket: &websocket.Conn{},
|
WebSocket: &websocket.Conn{},
|
||||||
}, th.Suite, func() *plugin.Environment { return nil })
|
}, th.Suite, &hookRunner{})
|
||||||
|
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
msg := &model.WebSocketEvent{}
|
msg := &model.WebSocketEvent{}
|
||||||
@@ -53,7 +68,7 @@ func TestWebConnIsInDeadQueue(t *testing.T) {
|
|||||||
|
|
||||||
wc := th.Service.NewWebConn(&WebConnConfig{
|
wc := th.Service.NewWebConn(&WebConnConfig{
|
||||||
WebSocket: &websocket.Conn{},
|
WebSocket: &websocket.Conn{},
|
||||||
}, th.Suite, func() *plugin.Environment { return nil })
|
}, th.Suite, &hookRunner{})
|
||||||
|
|
||||||
var i int
|
var i int
|
||||||
for ; i < 2; i++ {
|
for ; i < 2; i++ {
|
||||||
@@ -114,7 +129,7 @@ func TestWebConnClearDeadQueue(t *testing.T) {
|
|||||||
|
|
||||||
wc := th.Service.NewWebConn(&WebConnConfig{
|
wc := th.Service.NewWebConn(&WebConnConfig{
|
||||||
WebSocket: &websocket.Conn{},
|
WebSocket: &websocket.Conn{},
|
||||||
}, th.Suite, func() *plugin.Environment { return nil })
|
}, th.Suite, &hookRunner{})
|
||||||
|
|
||||||
var i int
|
var i int
|
||||||
for ; i < 2; i++ {
|
for ; i < 2; i++ {
|
||||||
@@ -140,7 +155,7 @@ func TestWebConnDrainDeadQueue(t *testing.T) {
|
|||||||
cfg := &WebConnConfig{
|
cfg := &WebConnConfig{
|
||||||
WebSocket: c,
|
WebSocket: c,
|
||||||
}
|
}
|
||||||
return th.Service.NewWebConn(cfg, th.Suite, func() *plugin.Environment { return nil })
|
return th.Service.NewWebConn(cfg, th.Suite, &hookRunner{})
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Empty Queue", func(t *testing.T) {
|
t.Run("Empty Queue", func(t *testing.T) {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import (
|
|||||||
|
|
||||||
platform_mocks "github.com/mattermost/mattermost-server/v6/app/platform/mocks"
|
platform_mocks "github.com/mattermost/mattermost-server/v6/app/platform/mocks"
|
||||||
"github.com/mattermost/mattermost-server/v6/model"
|
"github.com/mattermost/mattermost-server/v6/model"
|
||||||
"github.com/mattermost/mattermost-server/v6/plugin"
|
|
||||||
"github.com/mattermost/mattermost-server/v6/shared/i18n"
|
"github.com/mattermost/mattermost-server/v6/shared/i18n"
|
||||||
"github.com/mattermost/mattermost-server/v6/store/storetest/mocks"
|
"github.com/mattermost/mattermost-server/v6/store/storetest/mocks"
|
||||||
"github.com/mattermost/mattermost-server/v6/testlib"
|
"github.com/mattermost/mattermost-server/v6/testlib"
|
||||||
@@ -50,7 +49,7 @@ func registerDummyWebConn(t *testing.T, th *TestHelper, addr net.Addr, session *
|
|||||||
TFunc: i18n.IdentityTfunc(),
|
TFunc: i18n.IdentityTfunc(),
|
||||||
Locale: "en",
|
Locale: "en",
|
||||||
}
|
}
|
||||||
wc := th.Service.NewWebConn(cfg, th.Suite, func() *plugin.Environment { return nil })
|
wc := th.Service.NewWebConn(cfg, th.Suite, &hookRunner{})
|
||||||
th.Service.HubRegister(wc)
|
th.Service.HubRegister(wc)
|
||||||
go wc.Pump()
|
go wc.Pump()
|
||||||
return wc
|
return wc
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ func (ch *Channels) SetPluginsEnvironment(pluginsEnvironment *plugin.Environment
|
|||||||
defer ch.pluginsLock.Unlock()
|
defer ch.pluginsLock.Unlock()
|
||||||
|
|
||||||
ch.pluginsEnvironment = pluginsEnvironment
|
ch.pluginsEnvironment = pluginsEnvironment
|
||||||
ch.srv.Platform().SetPluginsEnvironment(pluginsEnvironment)
|
ch.srv.Platform().SetPluginsEnvironment(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch *Channels) syncPluginsActiveState() {
|
func (ch *Channels) syncPluginsActiveState() {
|
||||||
@@ -213,7 +213,7 @@ func (a *App) InitPlugins(c *request.Context, pluginDir, webappPluginDir string)
|
|||||||
func (ch *Channels) initPlugins(c *request.Context, pluginDir, webappPluginDir string) {
|
func (ch *Channels) initPlugins(c *request.Context, pluginDir, webappPluginDir string) {
|
||||||
// Acquiring lock manually, as plugins might be disabled. See GetPluginsEnvironment.
|
// Acquiring lock manually, as plugins might be disabled. See GetPluginsEnvironment.
|
||||||
defer func() {
|
defer func() {
|
||||||
ch.srv.Platform().SetPluginsEnvironment(ch.pluginsEnvironment)
|
ch.srv.Platform().SetPluginsEnvironment(ch)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
ch.pluginsLock.RLock()
|
ch.pluginsLock.RLock()
|
||||||
@@ -279,7 +279,7 @@ func (ch *Channels) initPlugins(c *request.Context, pluginDir, webappPluginDir s
|
|||||||
ch.syncPluginsActiveState()
|
ch.syncPluginsActiveState()
|
||||||
}
|
}
|
||||||
if pluginsEnvironment := ch.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := ch.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
if err := hooks.OnConfigurationChange(); err != nil {
|
if err := hooks.OnConfigurationChange(); err != nil {
|
||||||
ch.srv.Log().Error("Plugin OnConfigurationChange hook failed", mlog.Err(err))
|
ch.srv.Log().Error("Plugin OnConfigurationChange hook failed", mlog.Err(err))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1234,7 +1234,7 @@ func TestHookRunDataRetention(t *testing.T) {
|
|||||||
require.True(t, th.App.GetPluginsEnvironment().IsActive(pluginID))
|
require.True(t, th.App.GetPluginsEnvironment().IsActive(pluginID))
|
||||||
|
|
||||||
hookCalled := false
|
hookCalled := false
|
||||||
th.App.GetPluginsEnvironment().RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
th.App.Channels().RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
n, _ := hooks.RunDataRetention(0, 0)
|
n, _ := hooks.RunDataRetention(0, 0)
|
||||||
// Ensure return it correct
|
// Ensure return it correct
|
||||||
assert.Equal(t, int64(100), n)
|
assert.Equal(t, int64(100), n)
|
||||||
@@ -1278,7 +1278,7 @@ func TestHookOnSendDailyTelemetry(t *testing.T) {
|
|||||||
require.True(t, th.App.GetPluginsEnvironment().IsActive(pluginID))
|
require.True(t, th.App.GetPluginsEnvironment().IsActive(pluginID))
|
||||||
|
|
||||||
hookCalled := false
|
hookCalled := false
|
||||||
th.App.GetPluginsEnvironment().RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
th.App.Channels().RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.OnSendDailyTelemetry()
|
hooks.OnSendDailyTelemetry()
|
||||||
|
|
||||||
hookCalled = true
|
hookCalled = true
|
||||||
@@ -1322,7 +1322,7 @@ func TestHookOnCloudLimitsUpdated(t *testing.T) {
|
|||||||
require.True(t, th.App.GetPluginsEnvironment().IsActive(pluginID))
|
require.True(t, th.App.GetPluginsEnvironment().IsActive(pluginID))
|
||||||
|
|
||||||
hookCalled := false
|
hookCalled := false
|
||||||
th.App.GetPluginsEnvironment().RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
th.App.Channels().RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.OnCloudLimitsUpdated(nil)
|
hooks.OnCloudLimitsUpdated(nil)
|
||||||
|
|
||||||
hookCalled = true
|
hookCalled = true
|
||||||
|
|||||||
@@ -270,7 +270,7 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel
|
|||||||
}
|
}
|
||||||
var rejectionError *model.AppError
|
var rejectionError *model.AppError
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
replacementPost, rejectionReason := hooks.MessageWillBePosted(pluginContext, post.ForPlugin())
|
replacementPost, rejectionReason := hooks.MessageWillBePosted(pluginContext, post.ForPlugin())
|
||||||
if rejectionReason != "" {
|
if rejectionReason != "" {
|
||||||
id := "Post rejected by plugin. " + rejectionReason
|
id := "Post rejected by plugin. " + rejectionReason
|
||||||
@@ -332,7 +332,7 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel
|
|||||||
pluginPost := rpost.ForPlugin()
|
pluginPost := rpost.ForPlugin()
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.MessageHasBeenPosted(pluginContext, pluginPost)
|
hooks.MessageHasBeenPosted(pluginContext, pluginPost)
|
||||||
return true
|
return true
|
||||||
}, plugin.MessageHasBeenPostedID)
|
}, plugin.MessageHasBeenPostedID)
|
||||||
@@ -661,7 +661,7 @@ func (a *App) UpdatePost(c *request.Context, post *model.Post, safeUpdate bool)
|
|||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
var rejectionReason string
|
var rejectionReason string
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
newPost, rejectionReason = hooks.MessageWillBeUpdated(pluginContext, newPost.ForPlugin(), oldPost.ForPlugin())
|
newPost, rejectionReason = hooks.MessageWillBeUpdated(pluginContext, newPost.ForPlugin(), oldPost.ForPlugin())
|
||||||
return post != nil
|
return post != nil
|
||||||
}, plugin.MessageWillBeUpdatedID)
|
}, plugin.MessageWillBeUpdatedID)
|
||||||
@@ -689,7 +689,7 @@ func (a *App) UpdatePost(c *request.Context, post *model.Post, safeUpdate bool)
|
|||||||
pluginNewPost := newPost.ForPlugin()
|
pluginNewPost := newPost.ForPlugin()
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.MessageHasBeenUpdated(pluginContext, pluginNewPost, pluginOldPost)
|
hooks.MessageHasBeenUpdated(pluginContext, pluginNewPost, pluginOldPost)
|
||||||
return true
|
return true
|
||||||
}, plugin.MessageHasBeenUpdatedID)
|
}, plugin.MessageHasBeenUpdatedID)
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ func (a *App) SaveReactionForPost(c *request.Context, reaction *model.Reaction)
|
|||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.ReactionHasBeenAdded(pluginContext, reaction)
|
hooks.ReactionHasBeenAdded(pluginContext, reaction)
|
||||||
return true
|
return true
|
||||||
}, plugin.ReactionHasBeenAddedID)
|
}, plugin.ReactionHasBeenAddedID)
|
||||||
@@ -145,7 +145,7 @@ func (a *App) DeleteReactionForPost(c *request.Context, reaction *model.Reaction
|
|||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.ReactionHasBeenRemoved(pluginContext, reaction)
|
hooks.ReactionHasBeenRemoved(pluginContext, reaction)
|
||||||
return true
|
return true
|
||||||
}, plugin.ReactionHasBeenRemovedID)
|
}, plugin.ReactionHasBeenRemovedID)
|
||||||
|
|||||||
@@ -161,6 +161,8 @@ type Server struct {
|
|||||||
tracer *tracing.Tracer
|
tracer *tracing.Tracer
|
||||||
|
|
||||||
products map[string]Product
|
products map[string]Product
|
||||||
|
|
||||||
|
hooksManager *product.HooksManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Store() store.Store {
|
func (s *Server) Store() store.Store {
|
||||||
@@ -255,6 +257,8 @@ func NewServer(options ...Option) (*Server, error) {
|
|||||||
return nil, errors.Wrapf(err, "unable to create teams service")
|
return nil, errors.Wrapf(err, "unable to create teams service")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.hooksManager = product.NewHooksManager(s.GetMetrics())
|
||||||
|
|
||||||
// ensure app implements `product.UserService`
|
// ensure app implements `product.UserService`
|
||||||
var _ product.UserService = (*App)(nil)
|
var _ product.UserService = (*App)(nil)
|
||||||
|
|
||||||
|
|||||||
@@ -854,7 +854,7 @@ func (a *App) JoinUserToTeam(c request.CTX, team *model.Team, user *model.User,
|
|||||||
|
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.UserHasJoinedTeam(pluginContext, teamMember, actor)
|
hooks.UserHasJoinedTeam(pluginContext, teamMember, actor)
|
||||||
return true
|
return true
|
||||||
}, plugin.UserHasJoinedTeamID)
|
}, plugin.UserHasJoinedTeamID)
|
||||||
@@ -1228,7 +1228,7 @@ func (a *App) postProcessTeamMemberLeave(c request.CTX, teamMember *model.TeamMe
|
|||||||
|
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.UserHasLeftTeam(pluginContext, teamMember, actor)
|
hooks.UserHasLeftTeam(pluginContext, teamMember, actor)
|
||||||
return true
|
return true
|
||||||
}, plugin.UserHasLeftTeamID)
|
}, plugin.UserHasLeftTeamID)
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ func (a *App) runPluginsHook(c *request.Context, info *model.FileInfo, file io.R
|
|||||||
var rejErr *model.AppError
|
var rejErr *model.AppError
|
||||||
var once sync.Once
|
var once sync.Once
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
hookHasRunCh <- struct{}{}
|
hookHasRunCh <- struct{}{}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -311,7 +311,7 @@ func (a *App) createUserOrGuest(c request.CTX, user *model.User, guest bool) (*m
|
|||||||
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
pluginContext := pluginContext(c)
|
pluginContext := pluginContext(c)
|
||||||
pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
a.ch.RunMultiHook(func(hooks plugin.Hooks) bool {
|
||||||
hooks.UserHasBeenCreated(pluginContext, ruser)
|
hooks.UserHasBeenCreated(pluginContext, ruser)
|
||||||
return true
|
return true
|
||||||
}, plugin.UserHasBeenCreatedID)
|
}, plugin.UserHasBeenCreatedID)
|
||||||
|
|||||||
@@ -16,5 +16,5 @@ func (a *App) PopulateWebConnConfig(s *model.Session, cfg *platform.WebConnConfi
|
|||||||
|
|
||||||
// NewWebConn returns a new WebConn instance.
|
// NewWebConn returns a new WebConn instance.
|
||||||
func (a *App) NewWebConn(cfg *platform.WebConnConfig) *platform.WebConn {
|
func (a *App) NewWebConn(cfg *platform.WebConnConfig) *platform.WebConn {
|
||||||
return a.Srv().Platform().NewWebConn(cfg, a, a.ch.GetPluginsEnvironment)
|
return a.Srv().Platform().NewWebConn(cfg, a, a.ch)
|
||||||
}
|
}
|
||||||
|
|||||||
14
i18n/en.json
14
i18n/en.json
@@ -3164,12 +3164,16 @@
|
|||||||
"translation": "Mattermost Upgrade Confirmation"
|
"translation": "Mattermost Upgrade Confirmation"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.templates.cloud_upgrade_confirmation.subtitle",
|
"id": "api.templates.cloud_upgrade_confirmation.title",
|
||||||
|
"translation": "You are now upgraded!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "api.templates.cloud_upgrade_confirmation_monthly.subtitle",
|
||||||
"translation": "Your {{.WorkspaceName}} workspace has now been upgraded. You'll be billed from {{.Date}}"
|
"translation": "Your {{.WorkspaceName}} workspace has now been upgraded. You'll be billed from {{.Date}}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.templates.cloud_upgrade_confirmation.title",
|
"id": "api.templates.cloud_upgrade_confirmation_yearly.subtitle",
|
||||||
"translation": "You are now upgraded!"
|
"translation": "Your {{.WorkspaceName}} workspace has now been upgraded."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "api.templates.cloud_welcome_email.add_apps_info",
|
"id": "api.templates.cloud_welcome_email.add_apps_info",
|
||||||
@@ -3239,6 +3243,10 @@
|
|||||||
"id": "api.templates.cloud_welcome_email.title",
|
"id": "api.templates.cloud_welcome_email.title",
|
||||||
"translation": "Your workspace is ready to go!"
|
"translation": "Your workspace is ready to go!"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "api.templates.cloud_welcome_email.yearly_plan_button",
|
||||||
|
"translation": "View your invoice"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "api.templates.copyright",
|
"id": "api.templates.copyright",
|
||||||
"translation": "© 2021 Mattermost, Inc. 530 Lytton Avenue, Second floor, Palo Alto, CA, 94301"
|
"translation": "© 2021 Mattermost, Inc. 530 Lytton Avenue, Second floor, Palo Alto, CA, 94301"
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ type PrepackagedPlugin struct {
|
|||||||
// of active plugins.
|
// of active plugins.
|
||||||
type Environment struct {
|
type Environment struct {
|
||||||
registeredPlugins sync.Map
|
registeredPlugins sync.Map
|
||||||
registeredProducts sync.Map
|
|
||||||
pluginHealthCheckJob *PluginHealthCheckJob
|
pluginHealthCheckJob *PluginHealthCheckJob
|
||||||
logger *mlog.Logger
|
logger *mlog.Logger
|
||||||
metrics einterfaces.MetricsInterface
|
metrics einterfaces.MetricsInterface
|
||||||
@@ -326,26 +325,6 @@ func (env *Environment) Activate(id string) (manifest *model.Manifest, activated
|
|||||||
return pluginInfo.Manifest, true, nil
|
return pluginInfo.Manifest, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (env *Environment) AddProduct(productID string, hooks any) error {
|
|
||||||
prod, err := newAdapter(hooks)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
rp := ®isteredProduct{
|
|
||||||
productID: productID,
|
|
||||||
adapter: prod,
|
|
||||||
}
|
|
||||||
|
|
||||||
env.registeredProducts.Store(productID, rp)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *Environment) RemoveProduct(productID string) {
|
|
||||||
env.registeredProducts.Delete(productID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *Environment) RemovePlugin(id string) {
|
func (env *Environment) RemovePlugin(id string) {
|
||||||
if _, ok := env.registeredPlugins.Load(id); ok {
|
if _, ok := env.registeredPlugins.Load(id); ok {
|
||||||
env.registeredPlugins.Delete(id)
|
env.registeredPlugins.Delete(id)
|
||||||
@@ -499,12 +478,6 @@ func (env *Environment) HooksForPlugin(id string) (Hooks, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if p, ok := env.registeredProducts.Load(id); ok {
|
|
||||||
rp := p.(*registeredProduct)
|
|
||||||
|
|
||||||
return rp.adapter, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("plugin not found: %v", id)
|
return nil, fmt.Errorf("plugin not found: %v", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,24 +506,6 @@ func (env *Environment) RunMultiPluginHook(hookRunnerFunc func(hooks Hooks) bool
|
|||||||
return result
|
return result
|
||||||
})
|
})
|
||||||
|
|
||||||
env.registeredProducts.Range(func(key, value any) bool {
|
|
||||||
rp := value.(*registeredProduct)
|
|
||||||
|
|
||||||
if !rp.Implements(hookId) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
hookStartTime := time.Now()
|
|
||||||
result := hookRunnerFunc(rp.adapter)
|
|
||||||
|
|
||||||
if env.metrics != nil {
|
|
||||||
elapsedTime := float64(time.Since(hookStartTime)) / float64(time.Second)
|
|
||||||
env.metrics.ObservePluginMultiHookIterationDuration(rp.productID, elapsedTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
})
|
|
||||||
|
|
||||||
if env.metrics != nil {
|
if env.metrics != nil {
|
||||||
elapsedTime := float64(time.Since(startTime)) / float64(time.Second)
|
elapsedTime := float64(time.Since(startTime)) / float64(time.Second)
|
||||||
env.metrics.ObservePluginMultiHookDuration(elapsedTime)
|
env.metrics.ObservePluginMultiHookDuration(elapsedTime)
|
||||||
|
|||||||
@@ -399,13 +399,13 @@ type {{.Name}}IFace interface {
|
|||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
type hooksAdapter struct {
|
type HooksAdapter struct {
|
||||||
implemented map[int]struct{}
|
implemented map[int]struct{}
|
||||||
productHooks any
|
productHooks any
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAdapter(productHooks any) (*hooksAdapter, error) {
|
func NewAdapter(productHooks any) (*HooksAdapter, error) {
|
||||||
a := &hooksAdapter{
|
a := &HooksAdapter{
|
||||||
implemented: make(map[int]struct{}),
|
implemented: make(map[int]struct{}),
|
||||||
productHooks: productHooks,
|
productHooks: productHooks,
|
||||||
}
|
}
|
||||||
@@ -427,7 +427,7 @@ func newAdapter(productHooks any) (*hooksAdapter, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{{range .HooksMethods}}
|
{{range .HooksMethods}}
|
||||||
func (a *hooksAdapter) {{.Name}}{{funcStyle .Params}} {{funcStyle .Return}} {
|
func (a *HooksAdapter) {{.Name}}{{funcStyle .Params}} {{funcStyle .Return}} {
|
||||||
if _, ok := a.implemented[{{.Name}}ID]; !ok {
|
if _, ok := a.implemented[{{.Name}}ID]; !ok {
|
||||||
panic("product hooks must implement {{.Name}}")
|
panic("product hooks must implement {{.Name}}")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type registeredProduct struct {
|
type RegisteredProduct struct {
|
||||||
productID string
|
ProductID string
|
||||||
adapter Hooks
|
Adapter Hooks
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rp *registeredProduct) Implements(hookId int) bool {
|
func (rp *RegisteredProduct) Implements(hookId int) bool {
|
||||||
adapter, ok := rp.adapter.(*hooksAdapter)
|
adapter, ok := rp.Adapter.(*HooksAdapter)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -23,19 +23,19 @@ func (rp *registeredProduct) Implements(hookId int) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implemented method is overridden intentionally to prevent calling it from outside.
|
// Implemented method is overridden intentionally to prevent calling it from outside.
|
||||||
func (a *hooksAdapter) Implemented() ([]string, error) {
|
func (a *HooksAdapter) Implemented() ([]string, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnActivate is overridden intentionally as product should not call it.
|
// OnActivate is overridden intentionally as product should not call it.
|
||||||
func (a *hooksAdapter) OnActivate() error {
|
func (a *HooksAdapter) OnActivate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnDeactivate is overridden intentionally as product should not call it.
|
// OnDeactivate is overridden intentionally as product should not call it.
|
||||||
func (a *hooksAdapter) OnDeactivate() error {
|
func (a *HooksAdapter) OnDeactivate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeHTTP is overridden intentionally as product should not call it.
|
// ServeHTTP is overridden intentionally as product should not call it.
|
||||||
func (a *hooksAdapter) ServeHTTP(c *Context, w http.ResponseWriter, r *http.Request) {}
|
func (a *HooksAdapter) ServeHTTP(c *Context, w http.ResponseWriter, r *http.Request) {}
|
||||||
|
|||||||
@@ -138,13 +138,13 @@ type GetTopicMetadataByIdsIFace interface {
|
|||||||
GetTopicMetadataByIds(c *Context, topicType string, topicIds []string) (map[string]*model.TopicMetadata, error)
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAdapter(productHooks any) (*hooksAdapter, error) {
|
func NewAdapter(productHooks any) (*HooksAdapter, error) {
|
||||||
a := &hooksAdapter{
|
a := &HooksAdapter{
|
||||||
implemented: make(map[int]struct{}),
|
implemented: make(map[int]struct{}),
|
||||||
productHooks: productHooks,
|
productHooks: productHooks,
|
||||||
}
|
}
|
||||||
@@ -433,7 +433,7 @@ func newAdapter(productHooks any) (*hooksAdapter, error) {
|
|||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) OnConfigurationChange() error {
|
func (a *HooksAdapter) OnConfigurationChange() error {
|
||||||
if _, ok := a.implemented[OnConfigurationChangeID]; !ok {
|
if _, ok := a.implemented[OnConfigurationChangeID]; !ok {
|
||||||
panic("product hooks must implement OnConfigurationChange")
|
panic("product hooks must implement OnConfigurationChange")
|
||||||
}
|
}
|
||||||
@@ -442,7 +442,7 @@ func (a *hooksAdapter) OnConfigurationChange() error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) ExecuteCommand(c *Context, args *model.CommandArgs) (*model.CommandResponse, *model.AppError) {
|
func (a *HooksAdapter) ExecuteCommand(c *Context, args *model.CommandArgs) (*model.CommandResponse, *model.AppError) {
|
||||||
if _, ok := a.implemented[ExecuteCommandID]; !ok {
|
if _, ok := a.implemented[ExecuteCommandID]; !ok {
|
||||||
panic("product hooks must implement ExecuteCommand")
|
panic("product hooks must implement ExecuteCommand")
|
||||||
}
|
}
|
||||||
@@ -451,7 +451,7 @@ func (a *hooksAdapter) ExecuteCommand(c *Context, args *model.CommandArgs) (*mod
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) UserHasBeenCreated(c *Context, user *model.User) {
|
func (a *HooksAdapter) UserHasBeenCreated(c *Context, user *model.User) {
|
||||||
if _, ok := a.implemented[UserHasBeenCreatedID]; !ok {
|
if _, ok := a.implemented[UserHasBeenCreatedID]; !ok {
|
||||||
panic("product hooks must implement UserHasBeenCreated")
|
panic("product hooks must implement UserHasBeenCreated")
|
||||||
}
|
}
|
||||||
@@ -460,7 +460,7 @@ func (a *hooksAdapter) UserHasBeenCreated(c *Context, user *model.User) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) UserWillLogIn(c *Context, user *model.User) string {
|
func (a *HooksAdapter) UserWillLogIn(c *Context, user *model.User) string {
|
||||||
if _, ok := a.implemented[UserWillLogInID]; !ok {
|
if _, ok := a.implemented[UserWillLogInID]; !ok {
|
||||||
panic("product hooks must implement UserWillLogIn")
|
panic("product hooks must implement UserWillLogIn")
|
||||||
}
|
}
|
||||||
@@ -469,7 +469,7 @@ func (a *hooksAdapter) UserWillLogIn(c *Context, user *model.User) string {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) UserHasLoggedIn(c *Context, user *model.User) {
|
func (a *HooksAdapter) UserHasLoggedIn(c *Context, user *model.User) {
|
||||||
if _, ok := a.implemented[UserHasLoggedInID]; !ok {
|
if _, ok := a.implemented[UserHasLoggedInID]; !ok {
|
||||||
panic("product hooks must implement UserHasLoggedIn")
|
panic("product hooks must implement UserHasLoggedIn")
|
||||||
}
|
}
|
||||||
@@ -478,7 +478,7 @@ func (a *hooksAdapter) UserHasLoggedIn(c *Context, user *model.User) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) MessageWillBePosted(c *Context, post *model.Post) (*model.Post, string) {
|
func (a *HooksAdapter) MessageWillBePosted(c *Context, post *model.Post) (*model.Post, string) {
|
||||||
if _, ok := a.implemented[MessageWillBePostedID]; !ok {
|
if _, ok := a.implemented[MessageWillBePostedID]; !ok {
|
||||||
panic("product hooks must implement MessageWillBePosted")
|
panic("product hooks must implement MessageWillBePosted")
|
||||||
}
|
}
|
||||||
@@ -487,7 +487,7 @@ func (a *hooksAdapter) MessageWillBePosted(c *Context, post *model.Post) (*model
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) MessageWillBeUpdated(c *Context, newPost, oldPost *model.Post) (*model.Post, string) {
|
func (a *HooksAdapter) MessageWillBeUpdated(c *Context, newPost, oldPost *model.Post) (*model.Post, string) {
|
||||||
if _, ok := a.implemented[MessageWillBeUpdatedID]; !ok {
|
if _, ok := a.implemented[MessageWillBeUpdatedID]; !ok {
|
||||||
panic("product hooks must implement MessageWillBeUpdated")
|
panic("product hooks must implement MessageWillBeUpdated")
|
||||||
}
|
}
|
||||||
@@ -496,7 +496,7 @@ func (a *hooksAdapter) MessageWillBeUpdated(c *Context, newPost, oldPost *model.
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) MessageHasBeenPosted(c *Context, post *model.Post) {
|
func (a *HooksAdapter) MessageHasBeenPosted(c *Context, post *model.Post) {
|
||||||
if _, ok := a.implemented[MessageHasBeenPostedID]; !ok {
|
if _, ok := a.implemented[MessageHasBeenPostedID]; !ok {
|
||||||
panic("product hooks must implement MessageHasBeenPosted")
|
panic("product hooks must implement MessageHasBeenPosted")
|
||||||
}
|
}
|
||||||
@@ -505,7 +505,7 @@ func (a *hooksAdapter) MessageHasBeenPosted(c *Context, post *model.Post) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) MessageHasBeenUpdated(c *Context, newPost, oldPost *model.Post) {
|
func (a *HooksAdapter) MessageHasBeenUpdated(c *Context, newPost, oldPost *model.Post) {
|
||||||
if _, ok := a.implemented[MessageHasBeenUpdatedID]; !ok {
|
if _, ok := a.implemented[MessageHasBeenUpdatedID]; !ok {
|
||||||
panic("product hooks must implement MessageHasBeenUpdated")
|
panic("product hooks must implement MessageHasBeenUpdated")
|
||||||
}
|
}
|
||||||
@@ -514,7 +514,7 @@ func (a *hooksAdapter) MessageHasBeenUpdated(c *Context, newPost, oldPost *model
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) ChannelHasBeenCreated(c *Context, channel *model.Channel) {
|
func (a *HooksAdapter) ChannelHasBeenCreated(c *Context, channel *model.Channel) {
|
||||||
if _, ok := a.implemented[ChannelHasBeenCreatedID]; !ok {
|
if _, ok := a.implemented[ChannelHasBeenCreatedID]; !ok {
|
||||||
panic("product hooks must implement ChannelHasBeenCreated")
|
panic("product hooks must implement ChannelHasBeenCreated")
|
||||||
}
|
}
|
||||||
@@ -523,7 +523,7 @@ func (a *hooksAdapter) ChannelHasBeenCreated(c *Context, channel *model.Channel)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) UserHasJoinedChannel(c *Context, channelMember *model.ChannelMember, actor *model.User) {
|
func (a *HooksAdapter) UserHasJoinedChannel(c *Context, channelMember *model.ChannelMember, actor *model.User) {
|
||||||
if _, ok := a.implemented[UserHasJoinedChannelID]; !ok {
|
if _, ok := a.implemented[UserHasJoinedChannelID]; !ok {
|
||||||
panic("product hooks must implement UserHasJoinedChannel")
|
panic("product hooks must implement UserHasJoinedChannel")
|
||||||
}
|
}
|
||||||
@@ -532,7 +532,7 @@ func (a *hooksAdapter) UserHasJoinedChannel(c *Context, channelMember *model.Cha
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) UserHasLeftChannel(c *Context, channelMember *model.ChannelMember, actor *model.User) {
|
func (a *HooksAdapter) UserHasLeftChannel(c *Context, channelMember *model.ChannelMember, actor *model.User) {
|
||||||
if _, ok := a.implemented[UserHasLeftChannelID]; !ok {
|
if _, ok := a.implemented[UserHasLeftChannelID]; !ok {
|
||||||
panic("product hooks must implement UserHasLeftChannel")
|
panic("product hooks must implement UserHasLeftChannel")
|
||||||
}
|
}
|
||||||
@@ -541,7 +541,7 @@ func (a *hooksAdapter) UserHasLeftChannel(c *Context, channelMember *model.Chann
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) UserHasJoinedTeam(c *Context, teamMember *model.TeamMember, actor *model.User) {
|
func (a *HooksAdapter) UserHasJoinedTeam(c *Context, teamMember *model.TeamMember, actor *model.User) {
|
||||||
if _, ok := a.implemented[UserHasJoinedTeamID]; !ok {
|
if _, ok := a.implemented[UserHasJoinedTeamID]; !ok {
|
||||||
panic("product hooks must implement UserHasJoinedTeam")
|
panic("product hooks must implement UserHasJoinedTeam")
|
||||||
}
|
}
|
||||||
@@ -550,7 +550,7 @@ func (a *hooksAdapter) UserHasJoinedTeam(c *Context, teamMember *model.TeamMembe
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) UserHasLeftTeam(c *Context, teamMember *model.TeamMember, actor *model.User) {
|
func (a *HooksAdapter) UserHasLeftTeam(c *Context, teamMember *model.TeamMember, actor *model.User) {
|
||||||
if _, ok := a.implemented[UserHasLeftTeamID]; !ok {
|
if _, ok := a.implemented[UserHasLeftTeamID]; !ok {
|
||||||
panic("product hooks must implement UserHasLeftTeam")
|
panic("product hooks must implement UserHasLeftTeam")
|
||||||
}
|
}
|
||||||
@@ -559,7 +559,7 @@ func (a *hooksAdapter) UserHasLeftTeam(c *Context, teamMember *model.TeamMember,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) FileWillBeUploaded(c *Context, info *model.FileInfo, file io.Reader, output io.Writer) (*model.FileInfo, string) {
|
func (a *HooksAdapter) FileWillBeUploaded(c *Context, info *model.FileInfo, file io.Reader, output io.Writer) (*model.FileInfo, string) {
|
||||||
if _, ok := a.implemented[FileWillBeUploadedID]; !ok {
|
if _, ok := a.implemented[FileWillBeUploadedID]; !ok {
|
||||||
panic("product hooks must implement FileWillBeUploaded")
|
panic("product hooks must implement FileWillBeUploaded")
|
||||||
}
|
}
|
||||||
@@ -568,7 +568,7 @@ func (a *hooksAdapter) FileWillBeUploaded(c *Context, info *model.FileInfo, file
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) ReactionHasBeenAdded(c *Context, reaction *model.Reaction) {
|
func (a *HooksAdapter) ReactionHasBeenAdded(c *Context, reaction *model.Reaction) {
|
||||||
if _, ok := a.implemented[ReactionHasBeenAddedID]; !ok {
|
if _, ok := a.implemented[ReactionHasBeenAddedID]; !ok {
|
||||||
panic("product hooks must implement ReactionHasBeenAdded")
|
panic("product hooks must implement ReactionHasBeenAdded")
|
||||||
}
|
}
|
||||||
@@ -577,7 +577,7 @@ func (a *hooksAdapter) ReactionHasBeenAdded(c *Context, reaction *model.Reaction
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) ReactionHasBeenRemoved(c *Context, reaction *model.Reaction) {
|
func (a *HooksAdapter) ReactionHasBeenRemoved(c *Context, reaction *model.Reaction) {
|
||||||
if _, ok := a.implemented[ReactionHasBeenRemovedID]; !ok {
|
if _, ok := a.implemented[ReactionHasBeenRemovedID]; !ok {
|
||||||
panic("product hooks must implement ReactionHasBeenRemoved")
|
panic("product hooks must implement ReactionHasBeenRemoved")
|
||||||
}
|
}
|
||||||
@@ -586,7 +586,7 @@ func (a *hooksAdapter) ReactionHasBeenRemoved(c *Context, reaction *model.Reacti
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) OnPluginClusterEvent(c *Context, ev model.PluginClusterEvent) {
|
func (a *HooksAdapter) OnPluginClusterEvent(c *Context, ev model.PluginClusterEvent) {
|
||||||
if _, ok := a.implemented[OnPluginClusterEventID]; !ok {
|
if _, ok := a.implemented[OnPluginClusterEventID]; !ok {
|
||||||
panic("product hooks must implement OnPluginClusterEvent")
|
panic("product hooks must implement OnPluginClusterEvent")
|
||||||
}
|
}
|
||||||
@@ -595,7 +595,7 @@ func (a *hooksAdapter) OnPluginClusterEvent(c *Context, ev model.PluginClusterEv
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) OnWebSocketConnect(webConnID, userID string) {
|
func (a *HooksAdapter) OnWebSocketConnect(webConnID, userID string) {
|
||||||
if _, ok := a.implemented[OnWebSocketConnectID]; !ok {
|
if _, ok := a.implemented[OnWebSocketConnectID]; !ok {
|
||||||
panic("product hooks must implement OnWebSocketConnect")
|
panic("product hooks must implement OnWebSocketConnect")
|
||||||
}
|
}
|
||||||
@@ -604,7 +604,7 @@ func (a *hooksAdapter) OnWebSocketConnect(webConnID, userID string) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) OnWebSocketDisconnect(webConnID, userID string) {
|
func (a *HooksAdapter) OnWebSocketDisconnect(webConnID, userID string) {
|
||||||
if _, ok := a.implemented[OnWebSocketDisconnectID]; !ok {
|
if _, ok := a.implemented[OnWebSocketDisconnectID]; !ok {
|
||||||
panic("product hooks must implement OnWebSocketDisconnect")
|
panic("product hooks must implement OnWebSocketDisconnect")
|
||||||
}
|
}
|
||||||
@@ -613,7 +613,7 @@ func (a *hooksAdapter) OnWebSocketDisconnect(webConnID, userID string) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) WebSocketMessageHasBeenPosted(webConnID, userID string, req *model.WebSocketRequest) {
|
func (a *HooksAdapter) WebSocketMessageHasBeenPosted(webConnID, userID string, req *model.WebSocketRequest) {
|
||||||
if _, ok := a.implemented[WebSocketMessageHasBeenPostedID]; !ok {
|
if _, ok := a.implemented[WebSocketMessageHasBeenPostedID]; !ok {
|
||||||
panic("product hooks must implement WebSocketMessageHasBeenPosted")
|
panic("product hooks must implement WebSocketMessageHasBeenPosted")
|
||||||
}
|
}
|
||||||
@@ -622,7 +622,7 @@ func (a *hooksAdapter) WebSocketMessageHasBeenPosted(webConnID, userID string, r
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) RunDataRetention(nowTime, batchSize int64) (int64, error) {
|
func (a *HooksAdapter) RunDataRetention(nowTime, batchSize int64) (int64, error) {
|
||||||
if _, ok := a.implemented[RunDataRetentionID]; !ok {
|
if _, ok := a.implemented[RunDataRetentionID]; !ok {
|
||||||
panic("product hooks must implement RunDataRetention")
|
panic("product hooks must implement RunDataRetention")
|
||||||
}
|
}
|
||||||
@@ -631,7 +631,7 @@ func (a *hooksAdapter) RunDataRetention(nowTime, batchSize int64) (int64, error)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) OnInstall(c *Context, event model.OnInstallEvent) error {
|
func (a *HooksAdapter) OnInstall(c *Context, event model.OnInstallEvent) error {
|
||||||
if _, ok := a.implemented[OnInstallID]; !ok {
|
if _, ok := a.implemented[OnInstallID]; !ok {
|
||||||
panic("product hooks must implement OnInstall")
|
panic("product hooks must implement OnInstall")
|
||||||
}
|
}
|
||||||
@@ -640,7 +640,7 @@ func (a *hooksAdapter) OnInstall(c *Context, event model.OnInstallEvent) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) OnSendDailyTelemetry() {
|
func (a *HooksAdapter) OnSendDailyTelemetry() {
|
||||||
if _, ok := a.implemented[OnSendDailyTelemetryID]; !ok {
|
if _, ok := a.implemented[OnSendDailyTelemetryID]; !ok {
|
||||||
panic("product hooks must implement OnSendDailyTelemetry")
|
panic("product hooks must implement OnSendDailyTelemetry")
|
||||||
}
|
}
|
||||||
@@ -649,7 +649,7 @@ func (a *hooksAdapter) OnSendDailyTelemetry() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) OnCloudLimitsUpdated(limits *model.ProductLimits) {
|
func (a *HooksAdapter) OnCloudLimitsUpdated(limits *model.ProductLimits) {
|
||||||
if _, ok := a.implemented[OnCloudLimitsUpdatedID]; !ok {
|
if _, ok := a.implemented[OnCloudLimitsUpdatedID]; !ok {
|
||||||
panic("product hooks must implement OnCloudLimitsUpdated")
|
panic("product hooks must implement OnCloudLimitsUpdated")
|
||||||
}
|
}
|
||||||
@@ -658,7 +658,7 @@ func (a *hooksAdapter) OnCloudLimitsUpdated(limits *model.ProductLimits) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) UserHasPermissionToCollection(c *Context, userID string, collectionType, collectionId string, permission *model.Permission) (bool, error) {
|
func (a *HooksAdapter) UserHasPermissionToCollection(c *Context, userID string, collectionType, collectionId string, permission *model.Permission) (bool, error) {
|
||||||
if _, ok := a.implemented[UserHasPermissionToCollectionID]; !ok {
|
if _, ok := a.implemented[UserHasPermissionToCollectionID]; !ok {
|
||||||
panic("product hooks must implement UserHasPermissionToCollection")
|
panic("product hooks must implement UserHasPermissionToCollection")
|
||||||
}
|
}
|
||||||
@@ -667,7 +667,7 @@ func (a *hooksAdapter) UserHasPermissionToCollection(c *Context, userID string,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) GetAllCollectionIDsForUser(c *Context, userID, collectionType string) ([]string, error) {
|
func (a *HooksAdapter) GetAllCollectionIDsForUser(c *Context, userID, collectionType string) ([]string, error) {
|
||||||
if _, ok := a.implemented[GetAllCollectionIDsForUserID]; !ok {
|
if _, ok := a.implemented[GetAllCollectionIDsForUserID]; !ok {
|
||||||
panic("product hooks must implement GetAllCollectionIDsForUser")
|
panic("product hooks must implement GetAllCollectionIDsForUser")
|
||||||
}
|
}
|
||||||
@@ -676,7 +676,7 @@ func (a *hooksAdapter) GetAllCollectionIDsForUser(c *Context, userID, collection
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) GetAllUserIdsForCollection(c *Context, collectionType, collectionID string) ([]string, error) {
|
func (a *HooksAdapter) GetAllUserIdsForCollection(c *Context, collectionType, collectionID string) ([]string, error) {
|
||||||
if _, ok := a.implemented[GetAllUserIdsForCollectionID]; !ok {
|
if _, ok := a.implemented[GetAllUserIdsForCollectionID]; !ok {
|
||||||
panic("product hooks must implement GetAllUserIdsForCollection")
|
panic("product hooks must implement GetAllUserIdsForCollection")
|
||||||
}
|
}
|
||||||
@@ -685,7 +685,7 @@ func (a *hooksAdapter) GetAllUserIdsForCollection(c *Context, collectionType, co
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) GetTopicRedirect(c *Context, topicType, topicID string) (string, error) {
|
func (a *HooksAdapter) GetTopicRedirect(c *Context, topicType, topicID string) (string, error) {
|
||||||
if _, ok := a.implemented[GetTopicRedirectID]; !ok {
|
if _, ok := a.implemented[GetTopicRedirectID]; !ok {
|
||||||
panic("product hooks must implement GetTopicRedirect")
|
panic("product hooks must implement GetTopicRedirect")
|
||||||
}
|
}
|
||||||
@@ -694,7 +694,7 @@ func (a *hooksAdapter) GetTopicRedirect(c *Context, topicType, topicID string) (
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) GetCollectionMetadataByIds(c *Context, collectionType string, collectionIds []string) (map[string]*model.CollectionMetadata, error) {
|
func (a *HooksAdapter) GetCollectionMetadataByIds(c *Context, collectionType string, collectionIds []string) (map[string]*model.CollectionMetadata, error) {
|
||||||
if _, ok := a.implemented[GetCollectionMetadataByIdsID]; !ok {
|
if _, ok := a.implemented[GetCollectionMetadataByIdsID]; !ok {
|
||||||
panic("product hooks must implement GetCollectionMetadataByIds")
|
panic("product hooks must implement GetCollectionMetadataByIds")
|
||||||
}
|
}
|
||||||
@@ -703,7 +703,7 @@ func (a *hooksAdapter) GetCollectionMetadataByIds(c *Context, collectionType str
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *hooksAdapter) GetTopicMetadataByIds(c *Context, topicType string, topicIds []string) (map[string]*model.TopicMetadata, error) {
|
func (a *HooksAdapter) GetTopicMetadataByIds(c *Context, topicType string, topicIds []string) (map[string]*model.TopicMetadata, error) {
|
||||||
if _, ok := a.implemented[GetTopicMetadataByIdsID]; !ok {
|
if _, ok := a.implemented[GetTopicMetadataByIdsID]; !ok {
|
||||||
panic("product hooks must implement GetTopicMetadataByIds")
|
panic("product hooks must implement GetTopicMetadataByIds")
|
||||||
}
|
}
|
||||||
|
|||||||
79
product/hooks.go
Обычный файл
79
product/hooks.go
Обычный файл
@@ -0,0 +1,79 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
package product
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost-server/v6/einterfaces"
|
||||||
|
"github.com/mattermost/mattermost-server/v6/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HooksManager struct {
|
||||||
|
registeredProducts sync.Map
|
||||||
|
metrics einterfaces.MetricsInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHooksManager(metrics einterfaces.MetricsInterface) *HooksManager {
|
||||||
|
return &HooksManager{
|
||||||
|
metrics: metrics,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *HooksManager) AddProduct(productID string, hooks any) error {
|
||||||
|
prod, err := plugin.NewAdapter(hooks)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rp := &plugin.RegisteredProduct{
|
||||||
|
ProductID: productID,
|
||||||
|
Adapter: prod,
|
||||||
|
}
|
||||||
|
|
||||||
|
m.registeredProducts.Store(productID, rp)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *HooksManager) RemoveProduct(productID string) {
|
||||||
|
m.registeredProducts.Delete(productID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *HooksManager) RunMultiHook(hookRunnerFunc func(hooks plugin.Hooks) bool, hookId int) {
|
||||||
|
startTime := time.Now()
|
||||||
|
|
||||||
|
m.registeredProducts.Range(func(key, value any) bool {
|
||||||
|
rp := value.(*plugin.RegisteredProduct)
|
||||||
|
|
||||||
|
if !rp.Implements(hookId) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
hookStartTime := time.Now()
|
||||||
|
result := hookRunnerFunc(rp.Adapter)
|
||||||
|
|
||||||
|
if m.metrics != nil {
|
||||||
|
elapsedTime := float64(time.Since(hookStartTime)) / float64(time.Second)
|
||||||
|
m.metrics.ObservePluginMultiHookIterationDuration(rp.ProductID, elapsedTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
|
||||||
|
if m.metrics != nil {
|
||||||
|
elapsedTime := float64(time.Since(startTime)) / float64(time.Second)
|
||||||
|
m.metrics.ObservePluginMultiHookDuration(elapsedTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *HooksManager) HooksForProduct(id string) plugin.Hooks {
|
||||||
|
if value, ok := m.registeredProducts.Load(id); ok {
|
||||||
|
rp := value.(*plugin.RegisteredProduct)
|
||||||
|
return rp.Adapter
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Ссылка в новой задаче
Block a user