mirror of
https://github.com/discourse/discourse.git
synced 2024-11-23 01:16:38 -06:00
SECURITY: Remove disposable invite feature
This commit is contained in:
parent
9fb180f839
commit
f1a6449e4b
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user