SECURITY: Remove disposable invite feature

This commit is contained in:
Robin Ward 2017-07-07 20:24:39 -04:00
parent 9fb180f839
commit f1a6449e4b
6 changed files with 4 additions and 192 deletions

View File

@ -7,8 +7,8 @@ class InvitesController < ApplicationController
skip_before_filter :redirect_to_login_if_required
before_filter :ensure_logged_in, only: [:destroy, :create, :create_invite_link, :rescind_all_invites, :resend_invite, :resend_all_invites, :upload_csv]
before_filter :ensure_new_registrations_allowed, only: [:show, :perform_accept_invitation, :redeem_disposable_invite]
before_filter :ensure_not_logged_in, only: [:show, :perform_accept_invitation, :redeem_disposable_invite]
before_filter :ensure_new_registrations_allowed, only: [:show, :perform_accept_invitation]
before_filter :ensure_not_logged_in, only: [:show, :perform_accept_invitation]
def show
expires_now
@ -104,42 +104,6 @@ class InvitesController < ApplicationController
end
end
def create_disposable_invite
guardian.ensure_can_create_disposable_invite!(current_user)
params.permit(:username, :email, :quantity, :group_names)
username_or_email = params[:username] ? fetch_username : fetch_email
user = User.find_by_username_or_email(username_or_email)
# generate invite tokens
invite_tokens = Invite.generate_disposable_tokens(user, params[:quantity], params[:group_names])
render_json_dump(invite_tokens)
end
def redeem_disposable_invite
params.require(:email)
params.permit(:username, :name, :topic)
params[:email] = params[:email].split(' ').join('+')
invite = Invite.find_by(invite_key: params[:token])
if invite.present?
user = Invite.redeem_from_token(params[:token], params[:email], params[:username], params[:name], params[:topic].to_i)
if user.present?
log_on_user(user)
post_process_invite(user)
topic = invite.topics.first
if topic.present?
redirect_to path("#{topic.relative_url}")
return
end
end
end
redirect_to path("/")
end
def destroy
params.require(:email)

View File

@ -150,24 +150,6 @@ class Invite < ActiveRecord::Base
invite
end
# generate invite tokens without email
def self.generate_disposable_tokens(invited_by, quantity=nil, group_names=nil)
invite_tokens = []
quantity ||= 1
group_ids = get_group_ids(group_names)
quantity.to_i.times do
invite = Invite.create!(invited_by: invited_by)
group_ids = group_ids - invite.invited_groups.pluck(:group_id)
group_ids.each do |group_id|
invite.invited_groups.create!(group_id: group_id)
end
invite_tokens.push(invite.invite_key)
end
invite_tokens
end
def self.get_group_ids(group_names)
group_ids = []
if group_names

View File

@ -650,8 +650,6 @@ Discourse::Application.routes.draw do
post "invites/reinvite" => "invites#resend_invite"
post "invites/reinvite-all" => "invites#resend_all_invites"
post "invites/link" => "invites#create_invite_link"
post "invites/disposable" => "invites#create_disposable_invite"
get "invites/redeem/:token" => "invites#redeem_disposable_invite"
delete "invites" => "invites#destroy"
put "invites/show/:id" => "invites#perform_accept_invitation", as: 'perform_accept_invite'

View File

@ -271,10 +271,6 @@ class Guardian
user.admin?
end
def can_create_disposable_invite?(user)
user.admin?
end
def can_send_multiple_invites?(user)
user.staff?
end

View File

@ -48,20 +48,5 @@ describe "Discobot welcome post" do
end
end
context 'when user redeems a disposable invite' do
it 'should delay the welcome post until the user logs in' do
token = Invite.generate_disposable_tokens(user).first
expect do
xhr :get, "/invites/redeem/#{token}",
email: 'testing@gmail.com',
username: 'somename',
name: 'testing',
password: 'asodaasdaosdhq'
end.to change { User.count }.by(1)
expect(Jobs::NarrativeInit.jobs.first["args"].first["user_id"]).to eq(User.last.id)
end
end
end
end

View File

@ -138,8 +138,8 @@ describe InvitesController do
end
it "allows multiple group invite" do
group_1 = Fabricate(:group, name: "security")
group_2 = Fabricate(:group, name: "support")
Fabricate(:group, name: "security")
Fabricate(:group, name: "support")
log_in(:admin)
post :create_invite_link, email: email, group_names: "security,support"
expect(response).to be_success
@ -303,119 +303,6 @@ describe InvitesController do
end
end
context '.create_disposable_invite' do
it 'requires you to be logged in' do
expect {
post :create, email: 'jake@adventuretime.ooo'
}.to raise_error(Discourse::NotLoggedIn)
end
context 'while logged in as normal user' do
let(:user) { Fabricate(:user) }
it "does not create disposable invitation" do
log_in
post :create_disposable_invite, email: user.email
expect(response).not_to be_success
end
end
context 'while logged in as admin' do
before do
log_in(:admin)
end
let(:user) { Fabricate(:user) }
it "creates disposable invitation" do
post :create_disposable_invite, email: user.email
expect(response).to be_success
expect(Invite.where(invited_by_id: user.id).count).to eq(1)
end
it "creates multiple disposable invitations" do
post :create_disposable_invite, email: user.email, quantity: 10
expect(response).to be_success
expect(Invite.where(invited_by_id: user.id).count).to eq(10)
end
it "allows group invite" do
group = Fabricate(:group)
post :create_disposable_invite, email: user.email, group_names: group.name
expect(response).to be_success
expect(Invite.find_by(invited_by_id: user.id).invited_groups.count).to eq(1)
end
it "allows multiple group invite" do
group_1 = Fabricate(:group, name: "security")
group_2 = Fabricate(:group, name: "support")
post :create_disposable_invite, email: user.email, group_names: "security,support"
expect(response).to be_success
expect(Invite.find_by(invited_by_id: user.id).invited_groups.count).to eq(2)
end
end
end
context '.redeem_disposable_invite' do
context 'with an invalid invite token' do
before do
get :redeem_disposable_invite, email: "name@example.com", token: "doesn't exist"
end
it "redirects to the root" do
expect(response).to redirect_to("/")
end
it "should not change the session" do
expect(session[:current_user_id]).to be_blank
end
end
context 'with a valid invite token' do
let(:topic) { Fabricate(:topic) }
let(:invitee) { Fabricate(:user) }
let(:invite) { Invite.create!(invited_by: invitee) }
it 'converts "space" to "+" in email parameter' do
Invite.expects(:redeem_from_token).with(invite.invite_key, "fname+lname@example.com", nil, nil, topic.id)
get :redeem_disposable_invite, email: "fname lname@example.com", token: invite.invite_key, topic: topic.id
end
it 'redeems the invite' do
Invite.expects(:redeem_from_token).with(invite.invite_key, "name@example.com", nil, nil, topic.id)
get :redeem_disposable_invite, email: "name@example.com", token: invite.invite_key, topic: topic.id
end
context 'when redeem returns a user' do
let(:user) { Fabricate(:user) }
before do
Invite.expects(:redeem_from_token).with(invite.invite_key, user.email, nil, nil, topic.id).returns(user)
end
it 'logs in user' do
events = DiscourseEvent.track_events do
get :redeem_disposable_invite,
email: user.email,
token: invite.invite_key,
topic: topic.id
end
expect(events.map { |event| event[:event_name] }).to include(
:user_logged_in, :user_first_logged_in
)
expect(session[:current_user_id]).to eq(user.id)
end
end
end
end
context '.resend_invite' do
it 'requires you to be logged in' do