summaryrefslogtreecommitdiffstats
path: root/api/web_team_hub.go
blob: 9d1c56f153e8607f26409ed7f2327e1bac32140e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.

package api

import (
	l4g "github.com/alecthomas/log4go"
	"github.com/mattermost/platform/model"
	"github.com/mattermost/platform/utils"
)

type TeamHub struct {
	connections map[*WebConn]bool
	broadcast   chan *model.Message
	register    chan *WebConn
	unregister  chan *WebConn
	stop        chan bool
	teamId      string
}

func NewTeamHub(teamId string) *TeamHub {
	return &TeamHub{
		broadcast:   make(chan *model.Message),
		register:    make(chan *WebConn),
		unregister:  make(chan *WebConn),
		connections: make(map[*WebConn]bool),
		stop:        make(chan bool),
		teamId:      teamId,
	}
}

func (h *TeamHub) Register(webConn *WebConn) {
	h.register <- webConn
}

func (h *TeamHub) Unregister(webConn *WebConn) {
	h.unregister <- webConn
}

func (h *TeamHub) Stop() {
	h.stop <- true
}

func (h *TeamHub) Start() {
	go func() {
		for {
			select {
			case webCon := <-h.register:
				h.connections[webCon] = true
			case webCon := <-h.unregister:
				if _, ok := h.connections[webCon]; ok {
					delete(h.connections, webCon)
					close(webCon.Send)
				}
			case msg := <-h.broadcast:
				for webCon := range h.connections {
					if ShouldSendEvent(webCon, msg) {
						select {
						case webCon.Send <- msg:
						default:
							close(webCon.Send)
							delete(h.connections, webCon)
						}
					}
				}
			case s := <-h.stop:
				if s {

					l4g.Debug(utils.T("api.web_team_hun.start.debug"), h.teamId)

					for webCon := range h.connections {
						webCon.WebSocket.Close()
					}

					return
				}
			}
		}
	}()
}

func (h *TeamHub) UpdateChannelAccessCache(userId string, channelId string) {
	for webCon := range h.connections {
		if webCon.UserId == userId {
			webCon.updateChannelAccessCache(channelId)
			break
		}
	}
}

func ShouldSendEvent(webCon *WebConn, msg *model.Message) bool {

	if webCon.UserId == msg.UserId {
		// Don't need to tell the user they are typing
		if msg.Action == model.ACTION_TYPING {
			return false
		}
	} else {
		// Don't share a user's view or preference events with other users
		if msg.Action == model.ACTION_CHANNEL_VIEWED {
			return false
		} else if msg.Action == model.ACTION_PREFERENCE_CHANGED {
			return false
		} else if msg.Action == model.ACTION_EPHEMERAL_MESSAGE {
			// For now, ephemeral messages are sent directly to individual users
			return false
		}

		// Only report events to a user who is the subject of the event, or is in the channel of the event
		if len(msg.ChannelId) > 0 {
			allowed, ok := webCon.ChannelAccessCache[msg.ChannelId]
			if !ok {
				allowed = webCon.updateChannelAccessCache(msg.ChannelId)
			}

			if !allowed {
				return false
			}
		}
	}

	return true
}