SECURITY: Ensure the invite JSON API matches the UX

Anonymous users could query the invite json and see counts and
summaries which is not allowed in the UX of Discourse.

This commit has those endpoints return a 403 unless the user is
allowed to invite.
This commit is contained in:
Robin Ward 2020-03-04 11:10:23 -05:00
parent 2246fe8015
commit 20a8a2f396
2 changed files with 52 additions and 13 deletions

View File

@ -274,6 +274,8 @@ class UsersController < ApplicationController
end
def invited
guardian.ensure_can_invite_to_forum!
inviter = fetch_user_from_params(include_inactive: current_user.try(:staff?) || (current_user && SiteSetting.show_inactive_accounts))
offset = params[:offset].to_i || 0
filter_by = params[:filter]
@ -290,6 +292,8 @@ class UsersController < ApplicationController
end
def invited_count
guardian.ensure_can_invite_to_forum!
inviter = fetch_user_from_params(include_inactive: current_user.try(:staff?) || (current_user && SiteSetting.show_inactive_accounts))
pending_count = Invite.find_pending_invites_count(inviter)

View File

@ -1429,16 +1429,47 @@ describe UsersController do
end
end
describe '#invited' do
it 'returns success' do
describe "#invited_count" do
it "fails for anonymous users" do
user = Fabricate(:user)
get "/u/#{user.username}/invited_count.json"
expect(response.status).to eq(403)
end
it "works for users who can see invites" do
inviter = Fabricate(:user, trust_level: 2)
sign_in(inviter)
invitee = Fabricate(:user)
invite = Fabricate(:invite, invited_by: inviter, user: invitee)
get "/u/#{user.username}/invited_count.json"
expect(response.status).to eq(200)
json = JSON.parse(response.body)
expect(json).to be_present
expect(json['counts']).to be_present
end
end
describe '#invited' do
it 'fails for anonymous users' do
user = Fabricate(:user)
get "/u/#{user.username}/invited.json", params: { username: user.username }
expect(response.status).to eq(403)
end
it 'returns success' do
user = Fabricate(:user, trust_level: 2)
sign_in(user)
get "/u/#{user.username}/invited.json", params: { username: user.username }
expect(response.status).to eq(200)
end
it 'filters by email' do
inviter = Fabricate(:user)
inviter = Fabricate(:user, trust_level: 2)
sign_in(inviter)
invitee = Fabricate(:user)
Fabricate(
:invite,
@ -1454,6 +1485,7 @@ describe UsersController do
)
get "/u/#{inviter.username}/invited.json", params: { search: 'billybob' }
expect(response.status).to eq(200)
invites = JSON.parse(response.body)['invites']
expect(invites.size).to eq(1)
@ -1461,7 +1493,9 @@ describe UsersController do
end
it 'filters by username' do
inviter = Fabricate(:user)
inviter = Fabricate(:user, trust_level: 2)
sign_in(inviter)
invitee = Fabricate(:user, username: 'billybob')
_invite = Fabricate(
:invite,
@ -1476,6 +1510,7 @@ describe UsersController do
)
get "/u/#{inviter.username}/invited.json", params: { search: 'billybob' }
expect(response.status).to eq(200)
invites = JSON.parse(response.body)['invites']
expect(invites.size).to eq(1)
@ -1489,19 +1524,19 @@ describe UsersController do
Fabricate(:invite, invited_by: inviter)
get "/u/#{user.username}/invited/pending.json"
invites = JSON.parse(response.body)['invites']
expect(invites).to be_empty
expect(response.status).to eq(403)
end
end
context 'with redeemed invites' do
it 'returns invites' do
inviter = Fabricate(:user)
inviter = Fabricate(:user, trust_level: 2)
sign_in(inviter)
invitee = Fabricate(:user)
invite = Fabricate(:invite, invited_by: inviter, user: invitee)
get "/u/#{inviter.username}/invited.json"
expect(response.status).to eq(200)
invites = JSON.parse(response.body)['invites']
expect(invites.size).to eq(1)
@ -1514,11 +1549,12 @@ describe UsersController do
context 'with pending invites' do
context 'with permission to see pending invites' do
it 'returns invites' do
inviter = Fabricate(:user)
inviter = Fabricate(:user, trust_level: 2)
invite = Fabricate(:invite, invited_by: inviter)
sign_in(inviter)
get "/u/#{inviter.username}/invited/pending.json"
expect(response.status).to eq(200)
invites = JSON.parse(response.body)['invites']
expect(invites.size).to eq(1)
@ -1538,21 +1574,20 @@ describe UsersController do
end
get "/u/#{inviter.username}/invited/pending.json"
json = JSON.parse(response.body)['invites']
expect(json).to be_empty
expect(response.status).to eq(403)
end
end
end
context 'with redeemed invites' do
it 'returns invites' do
_user = sign_in(Fabricate(:user))
sign_in(Fabricate(:user, trust_level: 2))
inviter = Fabricate(:user)
invitee = Fabricate(:user)
invite = Fabricate(:invite, invited_by: inviter, user: invitee)
get "/u/#{inviter.username}/invited.json"
expect(response.status).to eq(200)
invites = JSON.parse(response.body)['invites']
expect(invites.size).to eq(1)