add lti option to prefer sis email

fixes PLAT-2324

test plan:

output to test:
 the lti message parameters :
   `lis_person_contact_email_primary`
  variable expansions:
   `Person.email.primary`
   `vnd.Canvas.Person.email.sis`

- test that the above outputs behaviour hasn't changed
- add <lticm:property name="prefer_sis_email">true</lticm:property>
to the extension settings portion of the xml config
- make sure you don't have an sis email
- the behavior shouldn't change
- set an sis email address
- you should now get the sis email for
`lis_person_contact_email_primary`

- test that the behaviour of `vnd.Canvas.Person.email.sis` hasn't
changed

Change-Id: Iaca2e036170ed1173309fd4596a4d6e1b016b6dd
Reviewed-on: https://gerrit.instructure.com/103195
Tested-by: Jenkins
Reviewed-by: Weston Dransfield <wdransfield@instructure.com>
Reviewed-by: Matthew Wheeler <mwheeler@instructure.com>
QA-Review: August Thornton <august@instructure.com>
Product-Review: Nathan Mills <nathanm@instructure.com>
This commit is contained in:
Nathan Mills 2017-02-24 13:02:00 -07:00
parent bbd5fba14b
commit 4ecc648078
7 changed files with 120 additions and 14 deletions

View File

@ -98,6 +98,7 @@ class ContextExternalTool < ActiveRecord::Base
:icon_svg_path_64,
:icon_url,
:message_type,
:prefer_sis_email,
:selection_height,
:selection_width,
:text,

View File

@ -14,17 +14,18 @@ module Lti
def initialize(canvas_user, canvas_root_account, canvas_tool, canvas_context)
@canvas_user = canvas_user
@canvas_root_account = canvas_root_account
@canvas_tool = canvas_tool
@canvas_context = canvas_context
@opaque_identifier = canvas_tool.opaque_identifier_for(@canvas_user)
@opaque_identifier = @canvas_tool.opaque_identifier_for(@canvas_user)
@pseudonym = false
end
def convert
lti_helper = Lti::SubstitutionsHelper.new(@canvas_context, @canvas_root_account, @canvas_user, @canvas_tool)
user = ::LtiOutbound::LTIUser.new
user.id = @canvas_user.id
user.avatar_url = @canvas_user.avatar_url
user.email = @canvas_user.email
user.email = lti_helper.email
user.first_name = @canvas_user.first_name
user.last_name = @canvas_user.last_name
user.name = @canvas_user.name
@ -36,8 +37,6 @@ module Lti
user.login_id = -> { pseudonym ? pseudonym.unique_id : nil }
user.sis_source_id = -> { pseudonym ? pseudonym.sis_user_id : nil }
user.current_observee_ids = -> { current_course_observee_lti_context_ids() }
lti_helper = Lti::SubstitutionsHelper.new(@canvas_context, @canvas_root_account, @canvas_user)
user.current_roles = lti_helper.current_lis_roles.split(',')
user

View File

@ -64,6 +64,27 @@ found below.
</cartridge_basiclti_link>
```
### Minimal configuration preferring SIS emails
```xml
<?xml version="1.0" encoding="UTF-8"?>
<cartridge_basiclti_link xmlns="http://www.imsglobal.org/xsd/imslticc_v1p0"
xmlns:blti = "http://www.imsglobal.org/xsd/imsbasiclti_v1p0"
xmlns:lticm ="http://www.imsglobal.org/xsd/imslticm_v1p0"
xmlns:lticp ="http://www.imsglobal.org/xsd/imslticp_v1p0"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.imsglobal.org/xsd/imslticc_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticc_v1p0.xsd
http://www.imsglobal.org/xsd/imsbasiclti_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imsbasiclti_v1p0.xsd
http://www.imsglobal.org/xsd/imslticm_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticm_v1p0.xsd
http://www.imsglobal.org/xsd/imslticp_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticp_v1p0.xsd">
<blti:launch_url>https://example.com/attendance</blti:launch_url>
<blti:title>Attendance</blti:title>
<blti:description>Provides an interactive seating chart and attendance tool</blti:description>
<blti:extensions platform="canvas.instructure.com">
<lticm:property name="prefer_sis_email">true</lticm:property>
</blti:extensions>
</cartridge_basiclti_link>
```
## Course Navigation External Tool Examples
### Minimal configuration

View File

@ -57,10 +57,11 @@ module Lti
LIS_V2_ROLE_NONE = 'http://purl.imsglobal.org/vocab/lis/v2/person#None'
def initialize(context, root_account, user)
def initialize(context, root_account, user, tool = nil)
@context = context
@root_account = root_account
@user = user
@tool = tool
end
def account
@ -164,6 +165,19 @@ module Lti
course_sections.map(&:sis_source_id).compact.uniq.sort.join(',')
end
def sis_email
if @user&.pseudonym&.sis_user_id
tablename = Pseudonym.quoted_table_name
query = "INNER JOIN #{tablename} ON communication_channels.id=pseudonyms.sis_communication_channel_id"
@user.communication_channels.joins(query).limit(1).pluck(:path).first
end
end
def email
prefer_sis_email = @tool&.extension_setting(nil, :prefer_sis_email)&.downcase == "true"
prefer_sis_email ? sis_email || @user.email : @user.email
end
private
def previous_course_ids_and_context_ids

View File

@ -66,7 +66,7 @@ module Lti
end
def lti_helper
@lti_helper ||= Lti::SubstitutionsHelper.new(@context, @root_account, @current_user)
@lti_helper ||= Lti::SubstitutionsHelper.new(@context, @root_account, @current_user, @tool)
end
def current_user=(current_user)
@ -435,7 +435,7 @@ module Lti
# john.doe@example.com
# ```
register_expansion 'Person.email.primary', [],
-> { @current_user.email },
-> { lti_helper.email },
USER_GUARD,
default_name: 'lis_person_contact_email_primary'
@ -446,10 +446,7 @@ module Lti
# john.doe@example.com
# ```
register_expansion 'vnd.Canvas.Person.email.sis', [],
-> { @current_user.communication_channels.joins(
"INNER JOIN #{Pseudonym.quoted_table_name}
ON communication_channels.id=pseudonyms.sis_communication_channel_id")
.limit(1).pluck(:path).first }, SIS_USER_GUARD
-> {lti_helper.sis_email}, SIS_USER_GUARD
# Returns the name of the timezone of the launching user. Only available when launched by a logged in user.
# @example

View File

@ -381,6 +381,79 @@ module Lti
end
end
context "email" do
let(:course) { Course.create!(root_account: root_account, account: account) }
let(:tool) do
ContextExternalTool.create!(
name: 'test tool',
context: course,
consumer_key: 'key',
shared_secret: 'secret',
url: 'http://exmaple.com/launch'
)
end
let(:substitution_helper) { SubstitutionsHelper.new(course, root_account, user, tool) }
let(:user) do
user = User.create!
user.email ='test@foo.com'
user.save!
user
end
describe "#email" do
it "returns the users email" do
expect(substitution_helper.email).to eq user.email
end
context "prefer_sis_email" do
before(:each) do
tool.settings[:prefer_sis_email] = "true"
tool.save!
end
it "returns the sis_email" do
sis_email = 'sis@example.com'
cc = user.communication_channels.email.create!(path: sis_email)
cc.user = user
cc.save!
pseudonym = cc.user.pseudonyms.build(:unique_id => cc.path, :account => Account.default)
pseudonym.sis_communication_channel_id=cc.id
pseudonym.communication_channel_id=cc.id
pseudonym.sis_user_id="some_sis_id"
pseudonym.save
expect(substitution_helper.email).to eq sis_email
end
it "returns the users email if there isn't an sis email" do
expect(substitution_helper.email).to eq user.email
end
end
end
describe "#sis_email" do
it "returns the sis email" do
sis_email = 'sis@example.com'
cc = user.communication_channels.email.create!(path: sis_email)
cc.user = user
cc.save!
pseudonym = cc.user.pseudonyms.build(:unique_id => cc.path, :account => Account.default)
pseudonym.sis_communication_channel_id=cc.id
pseudonym.communication_channel_id=cc.id
pseudonym.sis_user_id="some_sis_id"
pseudonym.save
expect(substitution_helper.sis_email).to eq sis_email
end
it "returns nil if there isn't an sis email" do
expect(substitution_helper.sis_email).to eq nil
end
end
end
end
end

View File

@ -40,6 +40,7 @@ module Lti
m = mock('tool')
m.stubs(:id).returns(1)
m.stubs(:context).returns(root_account)
m.stubs(:extension_setting).with(nil, :prefer_sis_email).returns(nil)
shard_mock = mock('shard')
shard_mock.stubs(:settings).returns({encription_key: 'abc'})
m.stubs(:shard).returns(shard_mock)
@ -732,8 +733,8 @@ module Lti
end
it 'has substitution for $Person.email.primary' do
user.save
user.email = 'someone@somewhere'
substitution_helper.stubs(:email).returns('someone@somewhere')
SubstitutionsHelper.stubs(:new).returns(substitution_helper)
exp_hash = {test: '$Person.email.primary'}
subject.expand_variables!(exp_hash)
expect(exp_hash[:test]).to eq 'someone@somewhere'