diff --git a/spec/system/streaming/channel_subscriptions_spec.rb b/spec/system/streaming/channel_subscriptions_spec.rb index 54e125c29..447ea64f2 100644 --- a/spec/system/streaming/channel_subscriptions_spec.rb +++ b/spec/system/streaming/channel_subscriptions_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'debug' RSpec.describe 'Channel Subscriptions', :inline_jobs, :streaming do let(:application) { Fabricate(:application, confidential: false) } @@ -15,6 +14,25 @@ RSpec.describe 'Channel Subscriptions', :inline_jobs, :streaming do streaming_client.close end + context 'when the access token has insufficient scope to read statuses' do + let(:scopes) { 'profile' } + + it 'cannot subscribe to the public:local channel' do + streaming_client.authenticate(access_token.token) + + streaming_client.connect + streaming_client.subscribe('public:local') + + # Receive the error back from the subscription attempt: + message = streaming_client.wait_for_message + + expect(message).to include( + error: 'Access token does not have the required scopes', + status: 401 + ) + end + end + context 'when the access token has read scope' do let(:scopes) { 'read' } @@ -39,11 +57,52 @@ RSpec.describe 'Channel Subscriptions', :inline_jobs, :streaming do ) ) end + + it 'can subscribing to the user:notifications channel' do + streaming_client.authenticate(access_token.token) + + streaming_client.connect + streaming_client.subscribe('user:notification') + + # We need to perform an action that triggers a notification as there is + # no positive acknowledgement of subscriptions: + first_status = PostStatusService.new.call(user_account, text: 'Test') + ReblogService.new.call(bob_account, first_status) + + message = streaming_client.wait_for_message + + expect(message).to include( + event: 'notification', + stream: ['user:notification'] + ) + end end - context 'when the access token cannot read notifications' do + context 'when the access token has read:statuses scope' do let(:scopes) { 'read:statuses' } + it 'can subscribing to the public:local channel' do + streaming_client.authenticate(access_token.token) + + streaming_client.connect + streaming_client.subscribe('public:local') + + # We need to publish a status as there is no positive acknowledgement of + # subscriptions: + status = PostStatusService.new.call(bob_account, text: 'Hello @alice') + + # And then we want to receive that status: + message = streaming_client.wait_for_message + + expect(message).to include( + stream: be_an(Array).and(contain_exactly('public:local')), + event: 'update', + payload: include( + id: status.id.to_s + ) + ) + end + it 'cannot subscribing to the user:notifications channel' do streaming_client.authenticate(access_token.token) @@ -59,4 +118,27 @@ RSpec.describe 'Channel Subscriptions', :inline_jobs, :streaming do ) end end + + context 'when the access token has read:notifications scope' do + let(:scopes) { 'read:notifications' } + + it 'can subscribing to the user:notifications channel' do + streaming_client.authenticate(access_token.token) + + streaming_client.connect + streaming_client.subscribe('user:notification') + + # We need to perform an action that triggers a notification as there is + # no positive acknowledgement of subscriptions: + first_status = PostStatusService.new.call(user_account, text: 'Test') + ReblogService.new.call(bob_account, first_status) + + message = streaming_client.wait_for_message + + expect(message).to include( + event: 'notification', + stream: ['user:notification'] + ) + end + end end diff --git a/streaming/index.js b/streaming/index.js index 84806acd1..e618e3e53 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -78,17 +78,6 @@ const parseJSON = (json, req) => { } }; -const PUBLIC_CHANNELS = [ - 'public', - 'public:media', - 'public:local', - 'public:local:media', - 'public:remote', - 'public:remote:media', - 'hashtag', - 'hashtag:local', -]; - // Used for priming the counters/gauges for the various metrics that are // per-channel const CHANNEL_NAMES = [ @@ -97,7 +86,14 @@ const CHANNEL_NAMES = [ 'user:notification', 'list', 'direct', - ...PUBLIC_CHANNELS + 'public', + 'public:media', + 'public:local', + 'public:local:media', + 'public:remote', + 'public:remote:media', + 'hashtag', + 'hashtag:local', ]; const startServer = async () => { @@ -434,12 +430,6 @@ const startServer = async () => { const checkScopes = (req, logger, channelName) => new Promise((resolve, reject) => { logger.debug(`Checking OAuth scopes for ${channelName}`); - // When accessing public channels, no scopes are needed - if (channelName && PUBLIC_CHANNELS.includes(channelName)) { - resolve(); - return; - } - // The `read` scope has the highest priority, if the token has it // then it can access all streams const requiredScopes = ['read'];