mirror of
https://github.com/discourse/discourse.git
synced 2025-06-04 11:11:13 +08:00
Discourse-presence improvements
- Added guardian checks to endpoint - Added security to messagebus publishing - Added specs for security measures - Moved all logic into component - Stop sending ‘keepAlive’ messages if the user stops editing for more then 2 minutes - Enable plugin by default
This commit is contained in:
@ -10,9 +10,14 @@ describe ::Presence::PresencesController, type: :request do
|
||||
let(:user2) { Fabricate(:user) }
|
||||
let(:user3) { Fabricate(:user) }
|
||||
|
||||
let(:post1) { Fabricate(:post) }
|
||||
let(:post2) { Fabricate(:post) }
|
||||
|
||||
after(:each) do
|
||||
$redis.del('presence:post:22')
|
||||
$redis.del('presence:post:11')
|
||||
$redis.del("presence:topic:#{post1.topic.id}")
|
||||
$redis.del("presence:topic:#{post2.topic.id}")
|
||||
$redis.del("presence:post:#{post1.id}")
|
||||
$redis.del("presence:post:#{post2.id}")
|
||||
end
|
||||
|
||||
context 'when not logged in' do
|
||||
@ -30,23 +35,38 @@ describe ::Presence::PresencesController, type: :request do
|
||||
expect { post '/presence/publish.json' }.not_to raise_error
|
||||
end
|
||||
|
||||
it "uses guardian to secure endpoint" do
|
||||
# Private message
|
||||
private_post = Fabricate(:private_message_post)
|
||||
post '/presence/publish.json', current: { action: 'edit', post_id: private_post.id }
|
||||
expect(response.code.to_i).to eq(403)
|
||||
|
||||
# Secure category
|
||||
group = Fabricate(:group)
|
||||
category = Fabricate(:private_category, group: group)
|
||||
private_topic = Fabricate(:topic, category: category)
|
||||
|
||||
post '/presence/publish.json', current: { action: 'edit', topic_id: private_topic.id }
|
||||
expect(response.code.to_i).to eq(403)
|
||||
end
|
||||
|
||||
it "returns a response when requested" do
|
||||
messages = MessageBus.track_publish do
|
||||
post '/presence/publish.json', current: { compose_state: 'open', action: 'edit', post_id: 22 }, response_needed: true
|
||||
post '/presence/publish.json', current: { compose_state: 'open', action: 'edit', post_id: post1.id }, response_needed: true
|
||||
end
|
||||
|
||||
expect(messages.count).to eq (1)
|
||||
|
||||
data = JSON.parse(response.body)
|
||||
|
||||
expect(data['messagebus_channel']).to eq('/presence/post/22')
|
||||
expect(data['messagebus_id']).to eq(MessageBus.last_id('/presence/post/22'))
|
||||
expect(data['messagebus_channel']).to eq("/presence/post/#{post1.id}")
|
||||
expect(data['messagebus_id']).to eq(MessageBus.last_id("/presence/post/#{post1.id}"))
|
||||
expect(data['users'][0]["id"]).to eq(user1.id)
|
||||
end
|
||||
|
||||
it "doesn't return a response when not requested" do
|
||||
messages = MessageBus.track_publish do
|
||||
post '/presence/publish.json', current: { compose_state: 'open', action: 'edit', post_id: 22 }
|
||||
post '/presence/publish.json', current: { compose_state: 'open', action: 'edit', post_id: post1.id }
|
||||
end
|
||||
|
||||
expect(messages.count).to eq (1)
|
||||
@ -57,20 +77,20 @@ describe ::Presence::PresencesController, type: :request do
|
||||
|
||||
it "doesn't send duplicate messagebus messages" do
|
||||
messages = MessageBus.track_publish do
|
||||
post '/presence/publish.json', current: { compose_state: 'open', action: 'edit', post_id: 22 }
|
||||
post '/presence/publish.json', current: { compose_state: 'open', action: 'edit', post_id: post1.id }
|
||||
end
|
||||
expect(messages.count).to eq (1)
|
||||
|
||||
messages = MessageBus.track_publish do
|
||||
post '/presence/publish.json', current: { compose_state: 'open', action: 'edit', post_id: 22 }
|
||||
post '/presence/publish.json', current: { compose_state: 'open', action: 'edit', post_id: post1.id }
|
||||
end
|
||||
expect(messages.count).to eq (0)
|
||||
end
|
||||
|
||||
it "clears 'previous' state when supplied" do
|
||||
messages = MessageBus.track_publish do
|
||||
post '/presence/publish.json', current: { compose_state: 'open', action: 'edit', post_id: 22 }
|
||||
post '/presence/publish.json', current: { compose_state: 'open', action: 'edit', post_id: 11 }, previous: { compose_state: 'open', action: 'edit', post_id: 22 }
|
||||
post '/presence/publish.json', current: { compose_state: 'open', action: 'edit', post_id: post1.id }
|
||||
post '/presence/publish.json', current: { compose_state: 'open', action: 'edit', post_id: post2.id }, previous: { compose_state: 'open', action: 'edit', post_id: post1.id }
|
||||
end
|
||||
expect(messages.count).to eq (3)
|
||||
end
|
||||
|
@ -7,58 +7,100 @@ describe ::Presence::PresenceManager do
|
||||
let(:user3) { Fabricate(:user) }
|
||||
let(:manager) { ::Presence::PresenceManager }
|
||||
|
||||
let(:post1) { Fabricate(:post) }
|
||||
let(:post2) { Fabricate(:post) }
|
||||
|
||||
after(:each) do
|
||||
$redis.del('presence:post:22')
|
||||
$redis.del('presence:post:11')
|
||||
$redis.del("presence:topic:#{post1.topic.id}")
|
||||
$redis.del("presence:topic:#{post2.topic.id}")
|
||||
$redis.del("presence:post:#{post1.id}")
|
||||
$redis.del("presence:post:#{post2.id}")
|
||||
end
|
||||
|
||||
it 'adds, removes and lists users correctly' do
|
||||
expect(manager.get_users('post', 22).count).to eq(0)
|
||||
expect(manager.get_users('post', post1.id).count).to eq(0)
|
||||
|
||||
expect(manager.add('post', 22, user1.id)).to be true
|
||||
expect(manager.add('post', 22, user2.id)).to be true
|
||||
expect(manager.add('post', 11, user3.id)).to be true
|
||||
expect(manager.add('post', post1.id, user1.id)).to be true
|
||||
expect(manager.add('post', post1.id, user2.id)).to be true
|
||||
expect(manager.add('post', post2.id, user3.id)).to be true
|
||||
|
||||
expect(manager.get_users('post', 22).count).to eq(2)
|
||||
expect(manager.get_users('post', 11).count).to eq(1)
|
||||
expect(manager.get_users('post', post1.id).count).to eq(2)
|
||||
expect(manager.get_users('post', post2.id).count).to eq(1)
|
||||
|
||||
expect(manager.get_users('post', 22)).to contain_exactly(user1, user2)
|
||||
expect(manager.get_users('post', 11)).to contain_exactly(user3)
|
||||
expect(manager.get_users('post', post1.id)).to contain_exactly(user1, user2)
|
||||
expect(manager.get_users('post', post2.id)).to contain_exactly(user3)
|
||||
|
||||
expect(manager.remove('post', 22, user1.id)).to be true
|
||||
expect(manager.get_users('post', 22).count).to eq(1)
|
||||
expect(manager.get_users('post', 22)).to contain_exactly(user2)
|
||||
expect(manager.remove('post', post1.id, user1.id)).to be true
|
||||
expect(manager.get_users('post', post1.id).count).to eq(1)
|
||||
expect(manager.get_users('post', post1.id)).to contain_exactly(user2)
|
||||
end
|
||||
|
||||
it 'publishes correctly' do
|
||||
expect(manager.get_users('post', 22).count).to eq(0)
|
||||
expect(manager.get_users('post', post1.id).count).to eq(0)
|
||||
|
||||
manager.add('post', 22, user1.id)
|
||||
manager.add('post', 22, user2.id)
|
||||
manager.add('post', post1.id, user1.id)
|
||||
manager.add('post', post1.id, user2.id)
|
||||
|
||||
messages = MessageBus.track_publish do
|
||||
manager.publish('post', 22)
|
||||
manager.publish('post', post1.id)
|
||||
end
|
||||
|
||||
expect(messages.count).to eq (1)
|
||||
message = messages.first
|
||||
|
||||
expect(message.channel).to eq('/presence/post/22')
|
||||
expect(message.channel).to eq("/presence/post/#{post1.id}")
|
||||
|
||||
expect(message.data["users"].map { |u| u[:id] }).to contain_exactly(user1.id, user2.id)
|
||||
end
|
||||
|
||||
it 'publishes private message securely' do
|
||||
private_post = Fabricate(:private_message_post)
|
||||
manager.add('post', private_post.id, user2.id)
|
||||
|
||||
messages = MessageBus.track_publish do
|
||||
manager.publish('post', private_post.id)
|
||||
end
|
||||
|
||||
expect(messages.count).to eq (1)
|
||||
message = messages.first
|
||||
|
||||
expect(message.channel).to eq("/presence/post/#{private_post.id}")
|
||||
|
||||
user_ids = User.where('admin or moderator').pluck(:id)
|
||||
user_ids += private_post.topic.allowed_users.pluck(:id)
|
||||
expect(message.user_ids).to contain_exactly(*user_ids)
|
||||
end
|
||||
|
||||
it 'publishes private category securely' do
|
||||
group = Fabricate(:group)
|
||||
category = Fabricate(:private_category, group: group)
|
||||
private_topic = Fabricate(:topic, category: category)
|
||||
|
||||
manager.add('topic', private_topic.id, user2.id)
|
||||
|
||||
messages = MessageBus.track_publish do
|
||||
manager.publish('topic', private_topic.id)
|
||||
end
|
||||
|
||||
expect(messages.count).to eq (1)
|
||||
message = messages.first
|
||||
|
||||
expect(message.channel).to eq("/presence/topic/#{private_topic.id}")
|
||||
|
||||
expect(message.group_ids).to contain_exactly(*private_topic.secure_group_ids)
|
||||
end
|
||||
|
||||
it 'cleans up correctly' do
|
||||
freeze_time Time.zone.now do
|
||||
expect(manager.add('post', 22, user1.id)).to be true
|
||||
expect(manager.cleanup('post', 22)).to be false # Nothing to cleanup
|
||||
expect(manager.get_users('post', 22).count).to eq(1)
|
||||
expect(manager.add('post', post1.id, user1.id)).to be true
|
||||
expect(manager.cleanup('post', post1.id)).to be false # Nothing to cleanup
|
||||
expect(manager.get_users('post', post1.id).count).to eq(1)
|
||||
end
|
||||
|
||||
# Anything older than 20 seconds should be cleaned up
|
||||
freeze_time 30.seconds.from_now do
|
||||
expect(manager.cleanup('post', 22)).to be true
|
||||
expect(manager.get_users('post', 22).count).to eq(0)
|
||||
expect(manager.cleanup('post', post1.id)).to be true
|
||||
expect(manager.get_users('post', post1.id).count).to eq(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user