fix horribly broken invite code, could lead to inviting the wrong person to a conversation

This commit is contained in:
Sam 2013-06-19 10:31:19 +10:00
parent 66c18a0bec
commit 799b402778
7 changed files with 52 additions and 26 deletions

View File

@ -3,7 +3,7 @@ class Admin::ImpersonateController < Admin::AdminController
def create def create
params.require(:username_or_email) params.require(:username_or_email)
user = User.find_by_username_or_email(params[:username_or_email]).first user = User.find_by_username_or_email(params[:username_or_email])
raise Discourse::NotFound if user.blank? raise Discourse::NotFound if user.blank?

View File

@ -153,7 +153,7 @@ class TopicsController < ApplicationController
guardian.ensure_can_invite_to!(topic) guardian.ensure_can_invite_to!(topic)
if topic.invite(current_user, params[:user]) if topic.invite(current_user, params[:user])
user = User.find_by_username_or_email(params[:user]).first user = User.find_by_username_or_email(params[:user])
if user if user
render_json_dump BasicUserSerializer.new(user, scope: guardian, root: 'user') render_json_dump BasicUserSerializer.new(user, scope: guardian, root: 'user')
else else

View File

@ -381,9 +381,9 @@ class Topic < ActiveRecord::Base
def invite(invited_by, username_or_email) def invite(invited_by, username_or_email)
if private_message? if private_message?
# If the user exists, add them to the topic. # If the user exists, add them to the topic.
user = User.find_by_username_or_email(username_or_email).first user = User.find_by_username_or_email(username_or_email)
if user.present? if user && topic_allowed_users.create!(user_id: user.id)
if topic_allowed_users.create!(user_id: user.id)
# Notify the user they've been invited # Notify the user they've been invited
user.notifications.create(notification_type: Notification.types[:invited_to_private_message], user.notifications.create(notification_type: Notification.types[:invited_to_private_message],
topic_id: id, topic_id: id,
@ -392,17 +392,15 @@ class Topic < ActiveRecord::Base
display_username: invited_by.username }.to_json) display_username: invited_by.username }.to_json)
return true return true
end end
elsif username_or_email =~ /^.+@.+$/
# If the user doesn't exist, but it looks like an email, invite the user by email.
return invite_by_email(invited_by, username_or_email)
end
else
# Success is whether the invite was created
return invite_by_email(invited_by, username_or_email).present?
end end
if username_or_email =~ /^.+@.+$/
# NOTE callers expect an invite object if an invite was sent via email
invite_by_email(invited_by, username_or_email)
else
false false
end end
end
# Invite a user by email and return the invite. Return the previously existing invite # Invite a user by email and return the invite. Return the previously existing invite
# if already exists. Returns nil if the invite can't be created. # if already exists. Returns nil if the invite can't be created.

View File

@ -133,7 +133,22 @@ class User < ActiveRecord::Base
def self.find_by_username_or_email(username_or_email) def self.find_by_username_or_email(username_or_email)
lower_user = username_or_email.downcase lower_user = username_or_email.downcase
lower_email = Email.downcase(username_or_email) lower_email = Email.downcase(username_or_email)
where("username_lower = :user or lower(username) = :user or email = :email or lower(name) = :user", user: lower_user, email: lower_email)
users =
if username_or_email.include?('@')
User.where(email: lower_email)
else
User.where(username_lower: lower_user)
end
.to_a
if users.count > 1
raise Discourse::TooManyMatches
elsif users.count == 1
users[0]
else
nil
end
end end
def enqueue_welcome_message(message_type) def enqueue_welcome_message(message_type)

View File

@ -2,6 +2,9 @@ require 'cache'
module Discourse module Discourse
# Expected less matches than what we got in a find
class TooManyMatches < Exception; end
# When they try to do something they should be logged in for # When they try to do something they should be logged in for
class NotLoggedIn < Exception; end class NotLoggedIn < Exception; end

View File

@ -52,11 +52,6 @@ describe Admin::ImpersonateController do
session[:current_user_id].should == user.id session[:current_user_id].should == user.id
end end
it "also works with a name" do
xhr :post, :create, username_or_email: user.name
session[:current_user_id].should == user.id
end
end end
end end

View File

@ -847,4 +847,19 @@ describe User do
end end
end end
describe '#find_by_username_or_email' do
it 'works correctly' do
bob = Fabricate(:user, username: 'bob', name: 'bobs', email: 'bob@bob.com')
bob2 = Fabricate(:user, username: 'bob2', name: 'bobs', email: 'bob2@bob.com')
expect(User.find_by_username_or_email('bob22@bob.com')).to eq(nil)
expect(User.find_by_username_or_email('bobs')).to eq(nil)
expect(User.find_by_username_or_email('bob2')).to eq(bob2)
expect(User.find_by_username_or_email('bob2@BOB.com')).to eq(bob2)
expect(User.find_by_username_or_email('bob')).to eq(bob)
expect(User.find_by_username_or_email('bob@BOB.com')).to eq(bob)
end
end
end end