message_bus 2.2.3 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of message_bus might be problematic. Click here for more details.

Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +9 -1
  3. data/.travis.yml +1 -1
  4. data/CHANGELOG +30 -0
  5. data/Gemfile +8 -3
  6. data/Guardfile +1 -0
  7. data/README.md +62 -11
  8. data/Rakefile +1 -0
  9. data/assets/message-bus.js +64 -78
  10. data/examples/bench/config.ru +1 -0
  11. data/examples/bench/puma.rb +1 -0
  12. data/examples/bench/unicorn.conf.rb +1 -0
  13. data/examples/chat/Gemfile +1 -0
  14. data/examples/chat/chat.rb +2 -0
  15. data/examples/chat/config.ru +2 -0
  16. data/examples/diagnostics/Gemfile +1 -0
  17. data/examples/diagnostics/config.ru +1 -0
  18. data/examples/minimal/Gemfile +1 -0
  19. data/examples/minimal/config.ru +1 -0
  20. data/lib/message_bus.rb +33 -0
  21. data/lib/message_bus/client.rb +36 -8
  22. data/lib/message_bus/diagnostics.rb +1 -1
  23. data/lib/message_bus/em_ext.rb +1 -0
  24. data/lib/message_bus/http_client.rb +2 -1
  25. data/lib/message_bus/http_client/channel.rb +1 -0
  26. data/lib/message_bus/rack/diagnostics.rb +5 -4
  27. data/lib/message_bus/rack/middleware.rb +8 -4
  28. data/lib/message_bus/rails/railtie.rb +15 -13
  29. data/lib/message_bus/version.rb +1 -1
  30. data/package.json +20 -0
  31. data/spec/assets/message-bus.spec.js +0 -9
  32. data/spec/assets/support/jasmine_helper.rb +1 -0
  33. data/spec/fixtures/test/Gemfile +1 -0
  34. data/spec/fixtures/test/config.ru +1 -0
  35. data/spec/helpers.rb +1 -0
  36. data/spec/integration/http_client_spec.rb +2 -0
  37. data/spec/lib/fake_async_middleware.rb +3 -2
  38. data/spec/lib/message_bus/assets/asset_encoding_spec.rb +1 -0
  39. data/spec/lib/message_bus/backend_spec.rb +2 -0
  40. data/spec/lib/message_bus/client_spec.rb +208 -23
  41. data/spec/lib/message_bus/connection_manager_spec.rb +3 -1
  42. data/spec/lib/message_bus/distributed_cache_spec.rb +2 -0
  43. data/spec/lib/message_bus/multi_process_spec.rb +2 -0
  44. data/spec/lib/message_bus/rack/middleware_spec.rb +63 -0
  45. data/spec/lib/message_bus/timer_thread_spec.rb +2 -0
  46. data/spec/lib/message_bus_spec.rb +34 -0
  47. data/spec/performance/publish.rb +2 -0
  48. data/spec/spec_helper.rb +3 -1
  49. metadata +3 -2
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  $LOAD_PATH.unshift File.expand_path('../../../lib', __FILE__)
2
3
 
3
4
  require 'message_bus'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'message_bus'
2
3
  on_worker_boot do
3
4
  MessageBus.after_fork
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'message_bus'
2
3
  after_fork do |_server, _worker|
3
4
  MessageBus.after_fork
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  gem 'puma'
2
3
  gem 'redis'
3
4
  gem 'sinatra'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  $LOAD_PATH.unshift File.expand_path('../../../lib', __FILE__)
2
4
  require 'message_bus'
3
5
  require 'sinatra'
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require './chat'
2
4
  run Chat
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  source 'https://rubygems.org'
2
3
 
3
4
  gem 'message_bus', path: '../..'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'message_bus'
2
3
 
3
4
  MessageBus.configure(backend: :redis, url: ENV['REDISURL'])
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  source 'https://rubygems.org'
2
3
 
3
4
  gem 'message_bus'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'message_bus'
2
3
 
3
4
  # MessageBus.long_polling_interval = 1000 * 2
@@ -149,6 +149,19 @@ module MessageBus::Implementation
149
149
  @config[:long_polling_interval] || 25 * 1000
150
150
  end
151
151
 
152
+ # @param [String] route Message bus will listen to requests on this route.
153
+ # @return [void]
154
+ def base_route=(route)
155
+ configure(base_route: route.gsub(Regexp.new('\A(?!/)|(?<!/)\Z|//+'), "/"))
156
+ end
157
+
158
+ # @return [String] the route that message bus will respond to. If not
159
+ # explicitly set, defaults to "/". Requests to "#{base_route}message-bus/*" will be handled
160
+ # by the message bus server.
161
+ def base_route
162
+ @config[:base_route] || "/"
163
+ end
164
+
152
165
  # @return [Boolean] whether the bus is disabled or not
153
166
  def off?
154
167
  @off
@@ -554,6 +567,26 @@ module MessageBus::Implementation
554
567
  @config[:keepalive_interval] || 60
555
568
  end
556
569
 
570
+ # Registers a client message filter that allows messages to be filtered from the client.
571
+ #
572
+ # @param [String,Regexp] channel_prefix channel prefix to match against a message's channel
573
+ #
574
+ # @yieldparam [MessageBus::Message] message published to the channel that matched the prefix provided
575
+ # @yieldreturn [Boolean] whether the message should be published to the client
576
+ # @return [void]
577
+ def register_client_message_filter(channel_prefix, &blk)
578
+ if blk
579
+ configure(client_message_filters: []) if !@config[:client_message_filters]
580
+ @config[:client_message_filters] << [channel_prefix, blk]
581
+ end
582
+ end
583
+
584
+ # @return [Array] returns a hash of message filters that have been registered
585
+ def client_message_filters
586
+ configure(client_message_filters: []) if !@config[:client_message_filters]
587
+ @config[:client_message_filters]
588
+ end
589
+
557
590
  private
558
591
 
559
592
  ENCODE_SITE_TOKEN = "$|$"
@@ -128,15 +128,43 @@ class MessageBus::Client
128
128
  # @return [Boolean] whether or not the client has permission to receive the
129
129
  # passed message
130
130
  def allowed?(msg)
131
- allowed = !msg.user_ids || msg.user_ids.include?(self.user_id)
132
- allowed &&= !msg.client_ids || msg.client_ids.include?(self.client_id)
133
- allowed && (
134
- msg.group_ids.nil? ||
135
- msg.group_ids.length == 0 ||
136
- (
137
- msg.group_ids - self.group_ids
131
+ client_allowed = !msg.client_ids || msg.client_ids.length == 0 || msg.client_ids.include?(self.client_id)
132
+
133
+ user_allowed = false
134
+ group_allowed = false
135
+
136
+ # this is an inconsistency we should fix anyway, publishing `user_ids: nil` should work same as groups
137
+ has_users = msg.user_ids && msg.user_ids.length > 0
138
+ has_groups = msg.group_ids && msg.group_ids.length > 0
139
+
140
+ if has_users
141
+ user_allowed = msg.user_ids.include?(self.user_id)
142
+ end
143
+
144
+ if has_groups
145
+ group_allowed = (
146
+ msg.group_ids - (self.group_ids || [])
138
147
  ).length < msg.group_ids.length
139
- )
148
+ end
149
+
150
+ has_permission = client_allowed && (user_allowed || group_allowed || (!has_users && !has_groups))
151
+
152
+ return has_permission if !has_permission
153
+
154
+ filters_allowed = true
155
+
156
+ len = @bus.client_message_filters.length
157
+ while len > 0
158
+ len -= 1
159
+ channel_prefix, blk = @bus.client_message_filters[len]
160
+
161
+ if msg.channel.start_with?(channel_prefix)
162
+ filters_allowed = blk.call(msg)
163
+ break if !filters_allowed
164
+ end
165
+ end
166
+
167
+ filters_allowed
140
168
  end
141
169
 
142
170
  # @return [Array<MessageBus::Message>] the set of messages the client is due
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # MessageBus diagnostics are used for troubleshooting the bus and optimising its configuration
2
3
  # @see MessageBus::Rack::Diagnostics
3
4
  class MessageBus::Diagnostics
@@ -14,7 +15,6 @@ class MessageBus::Diagnostics
14
15
  # process to process comms
15
16
  bus.subscribe('/_diagnostics/hup') do |msg|
16
17
  if Process.pid == msg.data["pid"] && hostname == msg.data["hostname"]
17
- $shutdown = true
18
18
  sleep 4
19
19
  Process.kill("HUP", $$)
20
20
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module EM
2
3
  def self.reactor_pid
3
4
  @reactor_pid
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'securerandom'
2
3
  require 'net/http'
3
4
  require 'json'
@@ -245,7 +246,7 @@ module MessageBus
245
246
  request.body = poll_payload
246
247
 
247
248
  if @enable_long_polling
248
- buffer = ''
249
+ buffer = +""
249
250
 
250
251
  http.request(request) do |response|
251
252
  response.read_body do |chunk|
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module MessageBus
2
3
  class HTTPClient
3
4
  # @private
@@ -16,9 +16,9 @@ class MessageBus::Rack::Diagnostics
16
16
  # Process an HTTP request from a subscriber client
17
17
  # @param [Rack::Request::Env] env the request environment
18
18
  def call(env)
19
- return @app.call(env) unless env['PATH_INFO'].start_with? '/message-bus/_diagnostics'
19
+ return @app.call(env) unless env['PATH_INFO'].start_with? "#{@bus.base_route}message-bus/_diagnostics"
20
20
 
21
- route = env['PATH_INFO'].split('/message-bus/_diagnostics')[1]
21
+ route = env['PATH_INFO'].split("#{@bus.base_route}message-bus/_diagnostics")[1]
22
22
 
23
23
  if @bus.is_admin_lookup.nil? || !@bus.is_admin_lookup.call(env)
24
24
  return [403, {}, ['not allowed']]
@@ -45,7 +45,7 @@ class MessageBus::Rack::Diagnostics
45
45
  return [200, { 'Content-Type' => 'application/javascript;charset=UTF-8' }, [content]]
46
46
  end
47
47
 
48
- return [404, {}, ['not found']]
48
+ [404, {}, ['not found']]
49
49
  end
50
50
 
51
51
  private
@@ -92,6 +92,7 @@ class MessageBus::Rack::Diagnostics
92
92
  </body>
93
93
  </html>
94
94
  HTML
95
- return [200, { "content-type" => "text/html;" }, [html]]
95
+
96
+ [200, { "content-type" => "text/html;" }, [html]]
96
97
  end
97
98
  end
@@ -39,6 +39,10 @@ class MessageBus::Rack::Middleware
39
39
  @bus = config[:message_bus] || MessageBus
40
40
  @connection_manager = MessageBus::ConnectionManager.new(@bus)
41
41
  @started_listener = false
42
+ @base_route = "#{@bus.base_route}message-bus/"
43
+ @base_route_length = @base_route.length
44
+ @diagnostics_route = "#{@base_route}_diagnostics"
45
+ @broadcast_route = "#{@base_route}broadcast"
42
46
  start_listener unless @bus.off?
43
47
  end
44
48
 
@@ -54,7 +58,7 @@ class MessageBus::Rack::Middleware
54
58
  # Process an HTTP request from a subscriber client
55
59
  # @param [Rack::Request::Env] env the request environment
56
60
  def call(env)
57
- return @app.call(env) unless env['PATH_INFO'] =~ /^\/message-bus\//
61
+ return @app.call(env) unless env['PATH_INFO'].start_with? @base_route
58
62
 
59
63
  handle_request(env)
60
64
  end
@@ -63,18 +67,18 @@ class MessageBus::Rack::Middleware
63
67
 
64
68
  def handle_request(env)
65
69
  # special debug/test route
66
- if @bus.allow_broadcast? && env['PATH_INFO'] == '/message-bus/broadcast'
70
+ if @bus.allow_broadcast? && env['PATH_INFO'] == @broadcast_route
67
71
  parsed = Rack::Request.new(env)
68
72
  @bus.publish parsed["channel"], parsed["data"]
69
73
  return [200, { "Content-Type" => "text/html" }, ["sent"]]
70
74
  end
71
75
 
72
- if env['PATH_INFO'].start_with? '/message-bus/_diagnostics'
76
+ if env['PATH_INFO'].start_with? @diagnostics_route
73
77
  diags = MessageBus::Rack::Diagnostics.new(@app, message_bus: @bus)
74
78
  return diags.call(env)
75
79
  end
76
80
 
77
- client_id = env['PATH_INFO'].split("/")[2]
81
+ client_id = env['PATH_INFO'][@base_route_length..-1].split("/")[0]
78
82
  return [404, {}, ["not found"]] unless client_id
79
83
 
80
84
  user_id = @bus.user_id_lookup.call(env) if @bus.user_id_lookup
@@ -11,27 +11,29 @@ class MessageBus::Rails::Railtie < ::Rails::Railtie
11
11
  # the Rails app is configured that might be ActionDispatch::Session::CookieStore, or potentially
12
12
  # ActionDispatch::Session::ActiveRecordStore.
13
13
  #
14
- # To handle either case, we insert it before ActionDispatch::Flash.
15
- #
16
- # For APIs or apps that have ActionDispatch::Flash deleted from the middleware
17
- # stack we just push MessageBus to the bottom.
18
- if api_only?(app.config) || flash_middleware_deleted?(app.middleware)
19
- app.middleware.use(MessageBus::Rack::Middleware)
20
- else
21
- app.middleware.insert_before(ActionDispatch::Flash, MessageBus::Rack::Middleware)
14
+ # given https://github.com/rails/rails/commit/fedde239dcee256b417dc9bcfe5fef603bf0d952#diff-533a9a9cc17a8a899cb830626089e5f9
15
+ # there is no way of walking the stack for operations
16
+ if !skip_middleware?(app.config)
17
+ if api_only?(app.config)
18
+ app.middleware.use(MessageBus::Rack::Middleware)
19
+ else
20
+ app.middleware.insert_before(ActionDispatch::Flash, MessageBus::Rack::Middleware)
21
+ end
22
22
  end
23
23
 
24
24
  MessageBus.logger = Rails.logger
25
25
  end
26
26
 
27
+ def skip_middleware?(config)
28
+ return false if !config.respond_to?(:skip_message_bus_middleware)
29
+
30
+ config.skip_message_bus_middleware
31
+ end
32
+
27
33
  def api_only?(config)
28
- return false unless config.respond_to?(:api_only)
34
+ return false if !config.respond_to?(:api_only)
29
35
 
30
36
  config.api_only
31
37
  end
32
38
 
33
- def flash_middleware_deleted?(middleware)
34
- ops = middleware.instance_variable_get(:@operations)
35
- ops.any? { |m| m[0] == :delete && m[1].include?(ActionDispatch::Flash) }
36
- end
37
39
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MessageBus
4
- VERSION = "2.2.3"
4
+ VERSION = "3.3.0"
5
5
  end
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "message-bus-client",
3
+ "version": "3.3.0",
4
+ "description": "A message bus client in Javascript",
5
+ "main": "assets/message-bus.js",
6
+ "keywords": "es6, modules",
7
+ "files": ["assets/message-bus.js"],
8
+ "jsnext:main": "assets/message-bus.js",
9
+ "module": "assets/message-bus.js",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/discourse/message_bus.git"
13
+ },
14
+ "author": "Sam Saffron, Robin Ward",
15
+ "license": "MIT",
16
+ "bugs": {
17
+ "url": "https://github.com/discourse/message_bus/issues"
18
+ },
19
+ "homepage": "https://github.com/discourse/message_bus#readme"
20
+ }
@@ -75,15 +75,6 @@ describe("Messagebus", function() {
75
75
  })
76
76
  });
77
77
 
78
- it('removes itself from root namespace when noConflict is called', function(){
79
- expect(window.MessageBus).not.toBeUndefined();
80
- var mb = window.MessageBus;
81
- expect(mb).toEqual(window.MessageBus.noConflict());
82
- expect(window.MessageBus).toBeUndefined();
83
- // reset it so afterEach has something to work on
84
- window.MessageBus = mb;
85
- });
86
-
87
78
  it('respects minPollInterval setting with defaults', function(){
88
79
  expect(MessageBus.minPollInterval).toEqual(100);
89
80
  MessageBus.minPollInterval = 1000;
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  Jasmine.configure do |_config|
2
3
  # patch for travis
3
4
  if ENV['TRAVIS']
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  source 'https://rubygems.org'
2
3
 
3
4
  gem 'message_bus'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'message_bus'
2
3
 
3
4
  MessageBus.config[:backend] = :memory
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  def wait_for(timeout_milliseconds = 2000)
2
3
  timeout = (timeout_milliseconds + 0.0) / 1000
3
4
  finish = Time.now + timeout
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../spec_helper'
2
4
  require 'message_bus/http_client'
3
5
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'http/parser'
2
3
  class FakeAsyncMiddleware
3
4
  def initialize(app, config = {})
@@ -53,7 +54,7 @@ class FakeAsyncMiddleware
53
54
 
54
55
  def translate_io_result(io)
55
56
  data = io.string
56
- body = ""
57
+ body = +""
57
58
 
58
59
  parser = Http::Parser.new
59
60
  parser.on_body = proc { |chunk| body << chunk }
@@ -112,7 +113,7 @@ class FakeAsyncMiddleware
112
113
  # more judo with deferrable body, at this point we just have headers
113
114
  r[2].callback do
114
115
  # even more judo cause rack test does not call each like the spec says
115
- body = ""
116
+ body = +""
116
117
  r[2].each do |m|
117
118
  body << m
118
119
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require_relative '../../../spec_helper'
2
3
  asset_directory = File.expand_path('../../../../../assets', __FILE__)
3
4
  asset_file_paths = Dir.glob(File.join(asset_directory, 'message-bus.js'))
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../../spec_helper'
2
4
  require 'message_bus'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../../spec_helper'
2
4
  require 'message_bus'
3
5
 
@@ -83,7 +85,7 @@ describe MessageBus::Client do
83
85
 
84
86
  data[-5..-1].must_equal "0\r\n\r\n"
85
87
 
86
- _, _, chunks = http_parse("HTTP/1.1 200 OK\r\n\r\n" << data)
88
+ _, _, chunks = http_parse(+"HTTP/1.1 200 OK\r\n\r\n" << data)
87
89
 
88
90
  chunks.length.must_equal 2
89
91
 
@@ -167,36 +169,219 @@ describe MessageBus::Client do
167
169
  log[0].data.must_equal 'world'
168
170
  end
169
171
 
170
- it "allows only client_id in list if message contains client_ids" do
171
- @message = MessageBus::Message.new(1, 2, '/test', 'hello')
172
- @message.client_ids = ["1", "2"]
173
- @client.client_id = "2"
174
- @client.allowed?(@message).must_equal true
172
+ describe '#allowed?' do
173
+ it "allows only client_id in list if message contains client_ids" do
174
+ @message = MessageBus::Message.new(1, 2, '/test', 'hello')
175
+ @message.client_ids = ["1", "2"]
176
+ @client.client_id = "2"
177
+ @client.allowed?(@message).must_equal true
175
178
 
176
- @client.client_id = "3"
177
- @client.allowed?(@message).must_equal false
178
- end
179
+ @client.client_id = "3"
180
+ @client.allowed?(@message).must_equal false
179
181
 
180
- describe "targetted at group" do
181
- before do
182
- @message = MessageBus::Message.new(1, 2, '/test', 'hello')
183
- @message.group_ids = [1, 2, 3]
182
+ @message.client_ids = []
183
+
184
+ @client.client_id = "3"
185
+ @client.allowed?(@message).must_equal true
186
+
187
+ @message.client_ids = nil
188
+
189
+ @client.client_id = "3"
190
+ @client.allowed?(@message).must_equal true
184
191
  end
185
192
 
186
- it "denies users that are not members of group" do
187
- @client.group_ids = [77, 0, 10]
188
- @client.allowed?(@message).must_equal false
193
+ describe 'targetted at user' do
194
+ before do
195
+ @message = MessageBus::Message.new(1, 2, '/test', 'hello')
196
+ @message.user_ids = [1, 2, 3]
197
+ end
198
+
199
+ it "allows client with user_id that is included in message's user_ids" do
200
+ @client.user_id = 1
201
+ @client.allowed?(@message).must_equal(true)
202
+ end
203
+
204
+ it "denies client with user_id that is not included in message's user_ids" do
205
+ @client.user_id = 4
206
+ @client.allowed?(@message).must_equal(false)
207
+ end
208
+
209
+ it "denies client with nil user_id" do
210
+ @client.user_id = nil
211
+
212
+ @client.allowed?(@message).must_equal(false)
213
+ end
214
+
215
+ it "allows client if message's user_ids is not set" do
216
+ @message.user_ids = nil
217
+ @client.user_id = 4
218
+ @client.allowed?(@message).must_equal(true)
219
+ end
220
+
221
+ it "allows client if message's user_ids is empty" do
222
+ @message.user_ids = []
223
+ @client.user_id = 4
224
+ @client.allowed?(@message).must_equal(true)
225
+ end
226
+
227
+ it "allows client with client_id that is included in message's client_ids" do
228
+ @message.client_ids = ["1", "2"]
229
+ @client.client_id = "1"
230
+ @client.user_id = 1
231
+
232
+ @client.allowed?(@message).must_equal(true)
233
+ end
234
+
235
+ it "denies client with client_id that is not included in message's client_ids" do
236
+ @message.client_ids = ["1", "2"]
237
+ @client.client_id = "3"
238
+ @client.user_id = 1
239
+
240
+ @client.allowed?(@message).must_equal(false)
241
+ end
189
242
  end
190
243
 
191
- it "allows users that are members of group" do
192
- @client.group_ids = [1, 2, 3]
193
- @client.allowed?(@message).must_equal true
244
+ describe "targetted at group" do
245
+ before do
246
+ @message = MessageBus::Message.new(1, 2, '/test', 'hello')
247
+ @message.group_ids = [1, 2, 3]
248
+ end
249
+
250
+ it "denies client that are not members of group" do
251
+ @client.group_ids = [77, 0, 10]
252
+ @client.allowed?(@message).must_equal false
253
+ end
254
+
255
+ it 'denies client with nil group_ids' do
256
+ @client.group_ids = nil
257
+ @client.allowed?(@message).must_equal false
258
+ end
259
+
260
+ it "allows client that are members of group" do
261
+ @client.group_ids = [1, 2, 3]
262
+ @client.allowed?(@message).must_equal true
263
+ end
264
+
265
+ it "allows any client if message's group_ids is not set" do
266
+ @message.group_ids = nil
267
+ @client.group_ids = [77, 0, 10]
268
+ @client.allowed?(@message).must_equal true
269
+ end
270
+
271
+ it "allows any client if message's group_ids is empty" do
272
+ @message.group_ids = []
273
+ @client.group_ids = [77, 0, 10]
274
+ @client.allowed?(@message).must_equal true
275
+ end
276
+
277
+ it "allows client with client_id that is included in message's client_ids" do
278
+ @message.client_ids = ["1", "2"]
279
+ @client.client_id = "1"
280
+ @client.group_ids = [1]
281
+
282
+ @client.allowed?(@message).must_equal(true)
283
+ end
284
+
285
+ it "denies client with client_id that is not included in message's client_ids" do
286
+ @message.client_ids = ["1", "2"]
287
+ @client.client_id = "3"
288
+ @client.group_ids = [1]
289
+
290
+ @client.allowed?(@message).must_equal(false)
291
+ end
194
292
  end
195
293
 
196
- it "allows all users if groups not set" do
197
- @message.group_ids = nil
198
- @client.group_ids = [77, 0, 10]
199
- @client.allowed?(@message).must_equal true
294
+ describe 'targetted at group and user' do
295
+ before do
296
+ @message = MessageBus::Message.new(1, 2, '/test', 'hello')
297
+ @message.group_ids = [1, 2, 3]
298
+ @message.user_ids = [4, 5, 6]
299
+ end
300
+
301
+ it "allows client with user_id that is included in message's user_ids" do
302
+ @client.user_id = 4
303
+ @client.allowed?(@message).must_equal(true)
304
+ end
305
+
306
+ it "denies client with user_id that is not included in message's user_ids" do
307
+ @client.user_id = 1
308
+ @client.allowed?(@message).must_equal(false)
309
+ end
310
+
311
+ it "allows client with group_ids that is included in message's group_ids" do
312
+ @client.group_ids = [1, 0, 3]
313
+ @client.allowed?(@message).must_equal(true)
314
+ end
315
+
316
+ it "denies client with group_ids that is not included in message's group_ids" do
317
+ @client.group_ids = [8, 9, 10]
318
+ @client.allowed?(@message).must_equal(false)
319
+ end
320
+
321
+ it "allows client with allowed client_id and user_id" do
322
+ @message.client_ids = ["1", "2"]
323
+ @client.user_id = 4
324
+ @client.client_id = "2"
325
+
326
+ @client.allowed?(@message).must_equal(true)
327
+ end
328
+
329
+ it "denies client with allowed client_id but disallowed user_id" do
330
+ @message.client_ids = ["1", "2"]
331
+ @client.user_id = 99
332
+ @client.client_id = "2"
333
+
334
+ @client.allowed?(@message).must_equal(false)
335
+ end
336
+
337
+ it "allows client with allowed client_id and group_id" do
338
+ @message.client_ids = ["1", "2"]
339
+ @client.group_ids = [1]
340
+ @client.client_id = "2"
341
+
342
+ @client.allowed?(@message).must_equal(true)
343
+ end
344
+
345
+ it "denies client with allowed client_id but disallowed group_id" do
346
+ @message.client_ids = ["1", "2"]
347
+ @client.group_ids = [99]
348
+ @client.client_id = "2"
349
+
350
+ @client.allowed?(@message).must_equal(false)
351
+ end
352
+ end
353
+
354
+ describe 'when MessageBus#client_message_filters has been configured' do
355
+
356
+ it 'filters messages correctly' do
357
+ message = MessageBus::Message.new(1, 2, '/test/5', 'hello')
358
+ @client.allowed?(message).must_equal(true)
359
+
360
+ @bus.register_client_message_filter('/test') do |m|
361
+ m.data != 'hello'
362
+ end
363
+
364
+ @client.allowed?(message).must_equal(false)
365
+ end
366
+
367
+ it 'filters messages correctly when multiple filters have been configured' do
368
+
369
+ bob_message = MessageBus::Message.new(1, 2, '/test/5', 'bob')
370
+ fred_message = MessageBus::Message.new(1, 2, '/test/5', 'fred')
371
+ random_message = MessageBus::Message.new(1, 2, '/test/77', 'random')
372
+
373
+ @bus.register_client_message_filter('/test') do |message|
374
+ message.data == 'bob' || message.data == 'fred'
375
+ end
376
+
377
+ @bus.register_client_message_filter('/test') do |message|
378
+ message.data == 'fred'
379
+ end
380
+
381
+ @client.allowed?(fred_message).must_equal(true)
382
+ @client.allowed?(bob_message).must_equal(false)
383
+ @client.allowed?(random_message).must_equal(false)
384
+ end
200
385
  end
201
386
  end
202
387
  end