Skip to content

Commit

Permalink
MM-55060 - Calls: Add PushTypeCalls for calls-specific push notificat…
Browse files Browse the repository at this point in the history
…ions (#561)

* go.mod changes

go.mod changes after rebase conflict w/ master

* add pushProxyVersion to activate; mlog compatability change;
need to update MM hash still

* update go.mod

* add mocking framework, tests

* simplify simpleclient

* setPushProxyVersion -> loadPushProxyVersion

* remove mocking; simplify client + testing
  • Loading branch information
cpoile authored Nov 14, 2023
1 parent 56d5ec0 commit 47cd7a7
Show file tree
Hide file tree
Showing 9 changed files with 274 additions and 16 deletions.
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ require (
github.com/mattermost/calls-recorder v0.4.2
github.com/mattermost/logr/v2 v2.0.16
github.com/mattermost/mattermost-plugin-calls/server/public v0.0.1
github.com/mattermost/mattermost/server/public v0.0.9-0.20230824163353-69c11cfe1403
github.com/mattermost/mattermost/server/public v0.0.10-0.20231109142142-8ffda2b73ea8
github.com/mattermost/rtcd v0.12.0
github.com/mattermost/squirrel v0.2.0
github.com/pion/interceptor v0.1.25
Expand Down Expand Up @@ -47,7 +47,6 @@ require (
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/uuid v1.4.0 // indirect
github.com/grafana/pyroscope-go/godeltaprof v0.1.4 // indirect
github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a // indirect
github.com/hashicorp/go-hclog v1.5.0 // indirect
github.com/hashicorp/go-plugin v1.4.10 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
Expand Down
13 changes: 2 additions & 11 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,6 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
Expand Down Expand Up @@ -184,7 +181,6 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
Expand Down Expand Up @@ -221,8 +217,6 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grafana/pyroscope-go/godeltaprof v0.1.4 h1:mDsJ3ngul7UfrHibGQpV66PbZ3q1T8glz/tK3bQKKEk=
github.com/grafana/pyroscope-go/godeltaprof v0.1.4/go.mod h1:1HSPtjU8vLG0jE9JrTdzjgFqdJ/VgN7fvxBNq3luJko=
github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a h1:i0+Se9S+2zL5CBxJouqn2Ej6UQMwH1c57ZB6DVnqck4=
github.com/graph-gophers/graphql-go v1.5.1-0.20230110080634-edea822f558a/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
Expand Down Expand Up @@ -301,8 +295,8 @@ github.com/mattermost/ldap v3.0.4+incompatible h1:SOeNnz+JNR+foQ3yHkYqijb9MLPhXN
github.com/mattermost/ldap v3.0.4+incompatible/go.mod h1:b4reDCcGpBxJ4WX0f224KFY+OR0npin7or7EFpeIko4=
github.com/mattermost/logr/v2 v2.0.16 h1:jnePX4cPskC3WDFvUardh/xZfxNdsFXbEERJQ1kUEDE=
github.com/mattermost/logr/v2 v2.0.16/go.mod h1:1dm/YhTpozsqANXxo5Pi5zYLBsal2xY0pX+JZNbzYJY=
github.com/mattermost/mattermost/server/public v0.0.9-0.20230824163353-69c11cfe1403 h1:/rxsEaisu+Rb5mWfoIEnbFqscJeKVkspj+BWzchUAfs=
github.com/mattermost/mattermost/server/public v0.0.9-0.20230824163353-69c11cfe1403/go.mod h1:sgXQrYzs+IJy51mB8E8OBljagk2u3YwQRoYlBH5goiw=
github.com/mattermost/mattermost/server/public v0.0.10-0.20231109142142-8ffda2b73ea8 h1:tZhcvX1k526YLHeO8lQpFa8J2Ejr7sHEYdzst5xrIjA=
github.com/mattermost/mattermost/server/public v0.0.10-0.20231109142142-8ffda2b73ea8/go.mod h1:AMuKlAabVFnLvf5bXg+69EdvtLIfty4ahFossB34LM4=
github.com/mattermost/rtcd v0.12.0 h1:T/07JYExpwMmWq58QIp8KU08FWOzVmmatzLaEOIMP4A=
github.com/mattermost/rtcd v0.12.0/go.mod h1:s0J7u93n2e2YPATEWCiiJ19iQf2TTHJapXQR2POE8KA=
github.com/mattermost/squirrel v0.2.0 h1:8ZWeyf+MWQ2cL7hu9REZgLtz2IJi51qqZEovI3T3TT8=
Expand Down Expand Up @@ -353,7 +347,6 @@ github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
Expand Down Expand Up @@ -570,8 +563,6 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/otel v1.6.3/go.mod h1:7BgNga5fNlF/iZjG06hM3yofffp0ofKCDwSXx1GC4dI=
go.opentelemetry.io/otel/trace v1.6.3/go.mod h1:GNJQusJlUgZl9/TQBPKU/Y/ty+0iVB5fjhKeJGZPGFs=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
Expand Down
2 changes: 2 additions & 0 deletions server/activate.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ func (p *Plugin) OnActivate() error {
}()
}

p.loadPushProxyVersion()

if rtcdURL := cfg.getRTCDURL(); rtcdURL != "" && p.licenseChecker.RTCDAllowed() {
rtcdManager, err := p.newRTCDClientManager(rtcdURL)
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions server/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,7 @@ func (l *logger) IsLevelEnabled(_ logr.Level) bool {
func (l *logger) With(_ ...logr.Field) *mlog.Logger {
return nil
}

func (l *logger) Sugar(_ ...mlog.Field) mlog.Sugar {
return mlog.Sugar{}
}
3 changes: 3 additions & 0 deletions server/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ type Plugin struct {
// Database handle to the writer DB node
wDB *sql.DB
driverName string

// Push-proxy's version, refreshed when the plugin activates
pushProxyVersion string
}

func (p *Plugin) startSession(us *session, senderID string) {
Expand Down
17 changes: 15 additions & 2 deletions server/push_notifications.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"github.com/mattermost/mattermost/server/public/model"
)

const minPushProxyVersionWithCalls = "5.27.0"

func (p *Plugin) NotificationWillBePushed(notification *model.PushNotification, userID string) (*model.PushNotification, string) {
// We will use our own notifications if:
// 1. This is a call start post
Expand Down Expand Up @@ -38,6 +40,10 @@ func (p *Plugin) NotificationWillBePushed(notification *model.PushNotification,
}

func (p *Plugin) sendPushNotifications(channelID, createdPostID, threadID string, sender *model.User, config *model.Config) {
if err := p.canSendPushNotifications(config, p.API.GetLicense()); err != nil {
return
}

channel, appErr := p.API.GetChannel(channelID)
if appErr != nil {
p.LogError("failed to get channel", "error", appErr.Error())
Expand All @@ -54,14 +60,19 @@ func (p *Plugin) sendPushNotifications(channelID, createdPostID, threadID string
return
}

pushType := model.PushTypeMessage
if err := checkMinVersion(minPushProxyVersionWithCalls, p.pushProxyVersion); err == nil {
pushType = model.PushTypeCalls
}

for _, member := range members {
if member.Id == sender.Id {
continue
}

msg := &model.PushNotification{
Version: model.PushMessageV2,
Type: model.PushTypeMessage,
Type: pushType,
TeamId: channel.TeamId,
ChannelId: channelID,
PostId: createdPostID,
Expand All @@ -71,7 +82,9 @@ func (p *Plugin) sendPushNotifications(channelID, createdPostID, threadID string
Message: buildGenericPushNotificationMessage(),
}

// This is ugly.
// This is ugly because it's a little complicated. We need to special case IdLoaded notifications (don't expose
// any details of the push notification on the wire). Otherwise, we can send more information, unless the server
// has set GenericNoChannel.
if *config.EmailSettings.PushNotificationContents == model.IdLoadedNotification {
msg.IsIdLoaded = p.checkLicenseForIDLoaded()
} else {
Expand Down
80 changes: 80 additions & 0 deletions server/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ package main
import (
"bytes"
"compress/zlib"
"encoding/json"
"errors"
"fmt"
"github.com/mattermost/mattermost/server/public/model"
"io"
Expand Down Expand Up @@ -63,6 +65,76 @@ func (p *Plugin) getNotificationNameFormat(userID string) string {
return *config.TeamSettings.TeammateNameDisplay
}

func (p *Plugin) loadPushProxyVersion() {
config := p.API.GetConfig()
if err := p.canSendPushNotifications(config, p.API.GetLicense()); err != nil {
p.LogWarn(err.Error())
return
}

client := NewClient()
var err error
p.pushProxyVersion, err = getPushProxyVersion(client, config)
if err != nil {
p.LogError(err.Error())
}
}

// getPushProxyVersion will return the version if the push proxy is reachable and version >= 5.27.0
// which is when the "/version" endpoint was added. Otherwise it will return "" for lower versions and for
// failed attempts to get the version (which could mean only that the push proxy was unavailable temporarily)
func getPushProxyVersion(client *http.Client, config *model.Config) (string, error) {
if config == nil ||
config.EmailSettings.PushNotificationServer == nil ||
*config.EmailSettings.PushNotificationServer == "" {
return "", nil
}
serverURL := strings.TrimRight(*config.EmailSettings.PushNotificationServer, "/") + "/version"
req, err := http.NewRequest("GET", serverURL, nil)
if err != nil {
return "", fmt.Errorf("failed to build request, err: %w", err)
}

resp, err := client.Do(req)
if err != nil {
return "", fmt.Errorf("http request failed, err: %w", err)
}
defer resp.Body.Close()

if resp.StatusCode == http.StatusOK {
var respData = struct {
Version string
Hash string
}{}
if err := json.NewDecoder(resp.Body).Decode(&respData); err != nil {
return "", fmt.Errorf("failed to decode http response, err: %w", err)
}

return respData.Version, nil
}

// Must not be newer version of push proxy
return "", nil
}

func (p *Plugin) canSendPushNotifications(config *model.Config, license *model.License) error {
if config == nil ||
config.EmailSettings.SendPushNotifications == nil ||
!*config.EmailSettings.SendPushNotifications {
return nil
}

if config.EmailSettings.PushNotificationServer == nil {
return nil
}
pushServer := *config.EmailSettings.PushNotificationServer
if pushServer == model.MHPNS && (license == nil || !*license.Features.MHPNS) {
return errors.New("push notifications have been disabled. Update your license or go to System Console > Environment > Push Notification Server to use a different server")
}

return nil
}

func getChannelNameForNotification(channel *model.Channel, sender *model.User, users []*model.User, nameFormat, excludeID string) string {
switch channel.Type {
case model.ChannelTypeDirect:
Expand Down Expand Up @@ -176,3 +248,11 @@ func mapKeys[K comparable, V any](m map[K]V) []K {
}
return keys
}

// NewClient creates a SimpleClient intended for one-off requests, like getPushProxyVersion.
// If we end up needing something more long term, we should consider storing it.
func NewClient() *http.Client {
return &http.Client{
Timeout: 10 * time.Second,
}
}
Loading

0 comments on commit 47cd7a7

Please sign in to comment.