create pseudonyms in the target account when merging temporary users
refs #6177, #6199 test plan: (only relevant with a plugin that changes the behavior of Pseudonym#works_for_account?; otherwise behavior should be unchanged) enable open registration, invite a user that already exists, but doesn't have a pseudonym in the account you're inviting them to. accept as the existing user. they should now have a pseudonym in the target account, copied from another account (preferentially the default account) Change-Id: Ia86888524a5132387bb120df3262d7205d8e04d1 Reviewed-on: https://gerrit.instructure.com/6983 Tested-by: Hudson <hudson@instructure.com> Reviewed-by: JT Olds <jt@instructure.com>
This commit is contained in:
parent
310ebfccd4
commit
1546835901
|
@ -89,6 +89,8 @@ class CommunicationChannelsController < ApplicationController
|
|||
merge_users << @current_user if @current_user && !@user.registered? && !merge_users.include?(@current_user)
|
||||
User.send(:preload_associations, merge_users, { :pseudonyms => :account })
|
||||
merge_users.reject! { |u| u != @current_user && u.pseudonyms.all? { |p| p.deleted? } }
|
||||
# remove users that don't have a pseudonym for this account, or one can't be created
|
||||
merge_users = merge_users.select { |u| u.pseudonym_for_account(@root_account, @domain_root_account) }
|
||||
@merge_opportunities = []
|
||||
merge_users.each do |user|
|
||||
account_to_pseudonyms_hash = {}
|
||||
|
@ -109,6 +111,9 @@ class CommunicationChannelsController < ApplicationController
|
|||
cc.confirm
|
||||
@enrollment.accept if @enrollment
|
||||
@user.move_to_user(@current_user) if @user != @current_user
|
||||
# create a new pseudonym if necessary and possible
|
||||
pseudonym = @current_user.pseudonym_for_account(@root_account, @domain_root_account)
|
||||
pseudonym.save! if pseudonym && pseudonym.new_record?
|
||||
elsif @current_user && @current_user != @user && @enrollment && @user.registered?
|
||||
if params[:transfer_enrollment].present?
|
||||
cc.active? || cc.confirm
|
||||
|
|
|
@ -2125,4 +2125,35 @@ class User < ActiveRecord::Base
|
|||
end
|
||||
h
|
||||
end
|
||||
|
||||
# account = the account that you want a pseudonym for
|
||||
# preferred_template_account = true-ish to create a pseudonym for the specified account if one doesn't exist (and it's possible)
|
||||
# pass in an actual account if you have a preference for which account the new pseudonym gets copied from
|
||||
# this may not be able to find a suitable pseudonym to copy, so would still return nil
|
||||
# if a pseudonym is created, it is *not* saved, and *not* added to the pseudonyms collection
|
||||
def pseudonym_for_account(account, preferred_template_account = nil)
|
||||
pseudonym = self.pseudonyms.detect { |p| p.active? && p.works_for_account?(account) }
|
||||
if !pseudonym && preferred_template_account
|
||||
# list of copyable pseudonyms
|
||||
active_pseudonyms = self.pseudonyms.select { |p| p.active? && !p.password_auto_generated? && !p.account.delegated_authentication? }
|
||||
templates = []
|
||||
# re-arrange in the order we prefer
|
||||
templates.concat active_pseudonyms.select { |p| p.account_id == preferred_template_account.id } if preferred_template_account.is_a?(Account)
|
||||
templates.concat active_pseudonyms.select { |p| p.account_id == Account.site_admin.id }
|
||||
templates.concat active_pseudonyms.select { |p| p.account_id == Account.default.id }
|
||||
templates.concat active_pseudonyms
|
||||
templates.uniq!
|
||||
|
||||
template = templates.detect { |template| !account.pseudonyms.find_by_unique_id(template.unique_id) }
|
||||
if template
|
||||
# creating this not attached to the user's pseudonyms is intentional
|
||||
pseudonym = account.pseudonyms.build
|
||||
pseudonym.user = self
|
||||
pseudonym.unique_id = template.unique_id
|
||||
pseudonym.password_salt = template.password_salt
|
||||
pseudonym.crypted_password = template.crypted_password
|
||||
end
|
||||
end
|
||||
pseudonym
|
||||
end
|
||||
end
|
||||
|
|
|
@ -378,6 +378,48 @@ describe CommunicationChannelsController do
|
|||
response.should render_template('confirm')
|
||||
assigns[:merge_opportunities].should == [[@user1, [@user1.pseudonym]]]
|
||||
end
|
||||
|
||||
it "should not show users that can't have a pseudonym created for the correct account" do
|
||||
Pseudonym.any_instance.stubs(:works_for_account?).returns(false)
|
||||
@account1 = Account.create!
|
||||
@account1.account_authorization_configs.create!(:auth_type => 'cas')
|
||||
user_with_pseudonym(:active_all => 1, :account => @account1, :username => 'jt@instructure.com')
|
||||
|
||||
@account2 = Account.create!
|
||||
course(:active_all => 1, :account => @account2)
|
||||
user
|
||||
@user.update_attribute(:workflow_state, 'creation_pending')
|
||||
@cc = @user.communication_channels.create!(:path => 'jt@instructure.com')
|
||||
@enrollment = @course.enroll_user(@user)
|
||||
|
||||
get 'confirm', :nonce => @cc.confirmation_code, :enrollment => @enrollment.uuid
|
||||
response.should render_template('confirm')
|
||||
assigns[:merge_opportunities].should == []
|
||||
end
|
||||
|
||||
it "should create a pseudonym in the target account by copying an existing pseudonym when merging" do
|
||||
Pseudonym.any_instance.stubs(:works_for_account?).returns(false)
|
||||
user_with_pseudonym(:active_all => 1, :username => 'jt@instructure.com')
|
||||
@old_user = @user
|
||||
|
||||
@account2 = Account.create!
|
||||
course(:active_all => 1, :account => @account2)
|
||||
user
|
||||
@user.update_attribute(:workflow_state, 'creation_pending')
|
||||
@cc = @user.communication_channels.create!(:path => 'jt@instructure.com')
|
||||
@enrollment = @course.enroll_user(@user)
|
||||
user_session(@old_user, @old_user.pseudonym)
|
||||
|
||||
get 'confirm', :nonce => @cc.confirmation_code, :enrollment => @enrollment.uuid, :confirm => 1
|
||||
response.should redirect_to(course_url(@course))
|
||||
@old_user.reload
|
||||
@user.reload
|
||||
@user.should be_deleted
|
||||
@enrollment.reload
|
||||
@enrollment.user.should == @old_user
|
||||
@old_user.pseudonyms.length.should == 2
|
||||
@old_user.pseudonyms.detect { |p| p.account == @account2 }.unique_id.should == 'jt@instructure.com'
|
||||
end
|
||||
end
|
||||
|
||||
describe "invitations" do
|
||||
|
|
|
@ -972,4 +972,98 @@ describe User do
|
|||
@user1.cached_current_enrollments.should == [@enrollment]
|
||||
end
|
||||
end
|
||||
|
||||
describe "pseudonym_for_account" do
|
||||
before do
|
||||
@account2 = Account.create!
|
||||
@account3 = Account.create!
|
||||
Pseudonym.any_instance.stubs(:works_for_account?).returns(false)
|
||||
Pseudonym.any_instance.stubs(:works_for_account?).with(Account.default).returns(true)
|
||||
end
|
||||
|
||||
it "should return an active pseudonym" do
|
||||
user_with_pseudonym(:active_all => 1)
|
||||
@user.pseudonym_for_account(Account.default).should == @pseudonym
|
||||
end
|
||||
|
||||
it "should return a trusted pseudonym" do
|
||||
user_with_pseudonym(:active_all => 1, :account => @account2)
|
||||
@user.pseudonym_for_account(Account.default).should == @pseudonym
|
||||
end
|
||||
|
||||
it "should return nil if none work" do
|
||||
user_with_pseudonym(:active_all => 1)
|
||||
@user.pseudonym_for_account(@account2).should == nil
|
||||
end
|
||||
|
||||
it "should create a copy of an existing pseudonym" do
|
||||
@account1 = Account.create!
|
||||
@account2 = Account.create!
|
||||
@account3 = Account.create!
|
||||
|
||||
# from unrelated account
|
||||
user_with_pseudonym(:active_all => 1, :account => @account2, :username => 'unrelated@example.com', :password => 'abcdef')
|
||||
new_pseudonym = @user.pseudonym_for_account(@account1, true)
|
||||
new_pseudonym.should_not be_nil
|
||||
new_pseudonym.should be_new_record
|
||||
new_pseudonym.unique_id.should == 'unrelated@example.com'
|
||||
|
||||
# from default account
|
||||
@user.pseudonyms.create!(:unique_id => 'default@example.com', :password => 'abcdef', :password_confirmation => 'abcdef')
|
||||
@user.pseudonyms.create!(:account => @account3, :unique_id => 'preferred@example.com', :password => 'abcdef', :password_confirmation => 'abcdef')
|
||||
new_pseudonym = @user.pseudonym_for_account(@account1, true)
|
||||
new_pseudonym.should_not be_nil
|
||||
new_pseudonym.should be_new_record
|
||||
new_pseudonym.unique_id.should == 'default@example.com'
|
||||
|
||||
# from site admin account
|
||||
@user.pseudonyms.create!(:account => Account.site_admin, :unique_id => 'siteadmin@example.com', :password => 'abcdef', :password_confirmation => 'abcdef')
|
||||
new_pseudonym = @user.pseudonym_for_account(@account1, true)
|
||||
new_pseudonym.should_not be_nil
|
||||
new_pseudonym.should be_new_record
|
||||
new_pseudonym.unique_id.should == 'siteadmin@example.com'
|
||||
|
||||
# from preferred account
|
||||
new_pseudonym = @user.pseudonym_for_account(@account1, @account3)
|
||||
new_pseudonym.should_not be_nil
|
||||
new_pseudonym.should be_new_record
|
||||
new_pseudonym.unique_id.should == 'preferred@example.com'
|
||||
|
||||
# from unrelated account, if other options are not viable
|
||||
@account1.pseudonyms.create!(:unique_id => 'preferred@example.com', :password => 'abcdef', :password_confirmation => 'abcdef')
|
||||
@user.pseudonyms.detect { |p| p.account == Account.site_admin }.update_attribute(:password_auto_generated, true)
|
||||
Account.default.account_authorization_configs.create!(:auth_type => 'cas')
|
||||
new_pseudonym = @user.pseudonym_for_account(@account1, @account3)
|
||||
new_pseudonym.should_not be_nil
|
||||
new_pseudonym.should be_new_record
|
||||
new_pseudonym.unique_id.should == 'unrelated@example.com'
|
||||
new_pseudonym.save!
|
||||
new_pseudonym.valid_password?('abcdef').should be_true
|
||||
end
|
||||
|
||||
it "should not create a new one when there are no viable candidates" do
|
||||
@account1 = Account.create!
|
||||
# no pseudonyms
|
||||
user
|
||||
@user.pseudonym_for_account(@account1, true).should be_nil
|
||||
|
||||
# auto-generated password
|
||||
@account2 = Account.create!
|
||||
@user.pseudonyms.create!(:account => @account2, :unique_id => 'bracken@instructure.com')
|
||||
@user.pseudonym_for_account(@account1, true).should be_nil
|
||||
|
||||
# delegated auth
|
||||
@account3 = Account.create!
|
||||
@account3.account_authorization_configs.create!(:auth_type => 'cas')
|
||||
@account3.should be_delegated_authentication
|
||||
@user.pseudonyms.create!(:account => @account3, :unique_id => 'jacob@instructure.com', :password => 'abcdef', :password_confirmation => 'abcdef')
|
||||
@user.pseudonym_for_account(@account1, true).should be_nil
|
||||
|
||||
# conflict
|
||||
@user2 = User.create! { |u| u.workflow_state = 'registered' }
|
||||
@user2.pseudonyms.create!(:account => @account1, :unique_id => 'jt@instructure.com', :password => 'abcdef', :password_confirmation => 'abcdef')
|
||||
@user.pseudonyms.create!(:unique_id => 'jt@instructure.com', :password => 'ghijkl', :password_confirmation => 'ghijkl')
|
||||
@user.pseudonym_for_account(@account1, true).should be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue