Skip to content

Instantly share code, notes, and snippets.

@marktriggs
Created August 20, 2018 04:09
Show Gist options
  • Save marktriggs/86269591789fe7cb936fa8cebaa86714 to your computer and use it in GitHub Desktop.
Save marktriggs/86269591789fe7cb936fa8cebaa86714 to your computer and use it in GitHub Desktop.
Fetch site memberships using LTI Context Memberships Service
#!/usr/bin/env ruby
require 'base64'
require 'net/http'
require 'openssl'
require 'securerandom'
# Standard Sakai URL for LTI services. Also available as the
# `ext_ims_lis_basic_outcome_url` parameter on an LTI launch.
#
BASE_URL = 'https://newclasses.nyu.edu/imsblis/service'
# Shared secrets...
#
LTI_KEY = 'THELAUNCHKEY'
LTI_SECRET = 'THELAUNCHSECRET'
# This string comes from the `ext_ims_lis_memberships_id` parameter of an LTI
# launch for the site. It's always the same for a given site, so once you've
# seen an LTI launch for one user, you've got the token needed to fetch that
# site's list of members.
#
EXT_IMS_LIS_MEMBERSHIPS_ID = 'c5418583a94e47849754dc6fce96d81782554e47c96b3be4030e0abde5e225c0:::admin:::content:5'
def encode(s)
URI.encode_www_form_component(s)
end
def oauth_signature(method, base_url, secret, params)
# https://oauth1.wp-api.org/docs/basics/Signing.html
base_string = [
method,
base_url,
params.sort.map {|k, v| "#{k}=#{encode(v)}"}.join('&')
].map {|s| encode(s)}.join('&')
Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'),
secret + '&',
base_string))
end
# Ultimately we're just sending a POST request with some params, but we need to
# sign the request with an OAuth signature. Most of this is just calculating
# that signature. Using an OAuth library would make life easier, but in the
# interest of being self-contained...
#
def main
uri = URI.parse(BASE_URL)
params = {
'lti_version' => 'LTI-1p0',
'lti_message_type' => 'basic-lis-readmembershipsforcontext',
'id' => EXT_IMS_LIS_MEMBERSHIPS_ID,
'oauth_consumer_key' => LTI_KEY,
'oauth_nonce' => SecureRandom.hex,
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => Time.now.to_i.to_s,
}
params['oauth_signature'] = oauth_signature('POST', BASE_URL, LTI_SECRET, params)
req = Net::HTTP::Post.new(uri)
req.set_form_data(params)
http = Net::HTTP.new(uri.host, uri.port)
response = http.request(req)
# Returns an XML payload like the one below
puts response.body
end
main
#######################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################
# Sample output:
#
# <?xml version="1.0" encoding="UTF-8" standalone="no"?>
# <message_response>
# <lti_message_type>basic-lis-readmembershipsforcontext</lti_message_type>
# <members>
# <member>
# <lis_result_sourcedid>36b38dd658afb519567353c24ad8a94b8099bc6daa5ad9667f361053a387ac31:::152ec024-7709-4baf-89ad-f31d695122db:::content:5</lis_result_sourcedid>
# <person_contact_email_primary>testuser@dishevelled.net</person_contact_email_primary>
# <person_name_family>User</person_name_family>
# <person_name_full>Test User</person_name_full>
# <person_name_given>Test</person_name_given>
# <person_sourcedid>student_dc91f532fd9e508ae0a77f1b88916ebf</person_sourcedid>
# <role>Learner</role>
# <roles>Learner</roles>
# <user_id>152ec024-7709-4baf-89ad-f31d695122db</user_id>
# </member>
# <member>
# <lis_result_sourcedid>8c79d87050c7797f28cea4978df8b34d11a0243f39c0586fb43dbd54c95da9aa:::fd697b66-c287-4295-8674-786c27c2e39f:::content:5</lis_result_sourcedid>
# <person_contact_email_primary>testuser@dishevelled.net</person_contact_email_primary>
# <person_name_family>User</person_name_family>
# <person_name_full>Test User</person_name_full>
# <person_name_given>Test</person_name_given>
# <person_sourcedid>student_e0c2566ff978e8fa6637a66e54fe7221</person_sourcedid>
# <role>Learner</role>
# <roles>Learner</roles>
# <user_id>fd697b66-c287-4295-8674-786c27c2e39f</user_id>
# </member>
# <member>
# <lis_result_sourcedid>a0e6c67e0aa65a09850868d594977bb858a80d57850cc42dd3f6a571ed262d85:::d93912fc-3ad1-4c8e-b056-fcd1b80ee81d:::content:5</lis_result_sourcedid>
# <person_contact_email_primary>testuser@dishevelled.net</person_contact_email_primary>
# <person_name_family>User</person_name_family>
# <person_name_full>Test User</person_name_full>
# <person_name_given>Test</person_name_given>
# <person_sourcedid>student_17b71a0c668e5c3ad8ee49fbda2b7d29</person_sourcedid>
# <role>Learner</role>
# <roles>Learner</roles>
# <user_id>d93912fc-3ad1-4c8e-b056-fcd1b80ee81d</user_id>
# </member>
# <member>
# <lis_result_sourcedid>52542acdb8b614bde8e3c1dbd841a3ff92f52e82a63dad90ea7d06436347bf6f:::42b3249a-a848-410a-8969-720a78e313c5:::content:5</lis_result_sourcedid>
# <person_contact_email_primary>testuser@dishevelled.net</person_contact_email_primary>
# <person_name_family>User</person_name_family>
# <person_name_full>Test User</person_name_full>
# <person_name_given>Test</person_name_given>
# <person_sourcedid>instructor_52f8777fbbfefe13749460f4dabe74a0</person_sourcedid>
# <role>Learner</role>
# <roles>Learner</roles>
# <user_id>42b3249a-a848-410a-8969-720a78e313c5</user_id>
# </member>
# <member>
# <lis_result_sourcedid>6e8712d8f59885b8e11e7a1f6e88e40bf918d7e67dbb3958a2c81290f6f3710e:::81cf0bfd-6bef-4829-ab8c-1c3c0f0f4fdc:::content:5</lis_result_sourcedid>
# <person_contact_email_primary>testuser@dishevelled.net</person_contact_email_primary>
# <person_name_family>User</person_name_family>
# <person_name_full>Test User</person_name_full>
# <person_name_given>Test</person_name_given>
# <person_sourcedid>student_113ce456fa21c7afc6acc7547eea6539</person_sourcedid>
# <role>Learner</role>
# <roles>Learner</roles>
# <user_id>81cf0bfd-6bef-4829-ab8c-1c3c0f0f4fdc</user_id>
# </member>
# <member>
# <lis_result_sourcedid>745b1353783df00f45e1f3d1494fd52d4a587aa9b6f1b1fd18c861025f92f65e:::e884af30-9939-4ad2-8faa-08207fed4448:::content:5</lis_result_sourcedid>
# <person_contact_email_primary>testuser@dishevelled.net</person_contact_email_primary>
# <person_name_family>User</person_name_family>
# <person_name_full>Test User</person_name_full>
# <person_name_given>Test</person_name_given>
# <person_sourcedid>student_68d71b779237e86e352b71adae250ee4</person_sourcedid>
# <role>Learner</role>
# <roles>Learner</roles>
# <user_id>e884af30-9939-4ad2-8faa-08207fed4448</user_id>
# </member>
# <member>
# <lis_result_sourcedid>c5418583a94e47849754dc6fce96d81782554e47c96b3be4030e0abde5e225c0:::admin:::content:5</lis_result_sourcedid>
# <person_contact_email_primary>administrator@dishevelled.net</person_contact_email_primary>
# <person_name_family>Administrator</person_name_family>
# <person_name_full>Sakai Administrator</person_name_full>
# <person_name_given>Sakai</person_name_given>
# <person_sourcedid>admin</person_sourcedid>
# <role>Instructor</role>
# <roles>Instructor</roles>
# <user_id>admin</user_id>
# </member>
# <member>
# <lis_result_sourcedid>69688666fa5567ca4d43e88bd4344aec1057cd285346a4f5186744d3b006f2de:::0c1d2a97-ac69-4f52-8234-8a00b29d082b:::content:5</lis_result_sourcedid>
# <person_contact_email_primary>testuser@dishevelled.net</person_contact_email_primary>
# <person_name_family>User</person_name_family>
# <person_name_full>Test User</person_name_full>
# <person_name_given>Test</person_name_given>
# <person_sourcedid>student_51d35d01c6b0333bdd01742df9fdef72</person_sourcedid>
# <role>Learner</role>
# <roles>Learner</roles>
# <user_id>0c1d2a97-ac69-4f52-8234-8a00b29d082b</user_id>
# </member>
# <member>
# <lis_result_sourcedid>4104f18b829d3685adfd91c1e44ad87ccc7bc8a9fc61573efe9ea9589669e2b0:::039e53be-d1fa-44b9-a5af-2122dafc8a73:::content:5</lis_result_sourcedid>
# <person_contact_email_primary>testuser@dishevelled.net</person_contact_email_primary>
# <person_name_family>User</person_name_family>
# <person_name_full>Test User</person_name_full>
# <person_name_given>Test</person_name_given>
# <person_sourcedid>student_fc762d1bacffecadc7a3706a46a2c153</person_sourcedid>
# <role>Learner</role>
# <roles>Learner</roles>
# <user_id>039e53be-d1fa-44b9-a5af-2122dafc8a73</user_id>
# </member>
# <member>
# <lis_result_sourcedid>a649144e446c9dbe1326d321ab5bca9d4720b2d1254838e6a8e1a250ef27d345:::2a0ed833-71ae-4497-b7bf-ec0208ab314c:::content:5</lis_result_sourcedid>
# <person_contact_email_primary>testuser@dishevelled.net</person_contact_email_primary>
# <person_name_family>User</person_name_family>
# <person_name_full>Test User</person_name_full>
# <person_name_given>Test</person_name_given>
# <person_sourcedid>student_c83e501f83f76a8855c0d2083e16bfe1</person_sourcedid>
# <role>Learner</role>
# <roles>Learner</roles>
# <user_id>2a0ed833-71ae-4497-b7bf-ec0208ab314c</user_id>
# </member>
# <member>
# <lis_result_sourcedid>f80031710ebf1280d7354fad609537692aa7e6bb44665dcfb6e4ae3fa4925093:::0108f0e1-c17d-4750-b9b2-3b3c1d2c4f87:::content:5</lis_result_sourcedid>
# <person_contact_email_primary>testuser@dishevelled.net</person_contact_email_primary>
# <person_name_family>User</person_name_family>
# <person_name_full>Test User</person_name_full>
# <person_name_given>Test</person_name_given>
# <person_sourcedid>student_c8a5f62d507607e4cf97af9fcd7d8f0b</person_sourcedid>
# <role>Learner</role>
# <roles>Learner</roles>
# <user_id>0108f0e1-c17d-4750-b9b2-3b3c1d2c4f87</user_id>
# </member>
# <member>
# <lis_result_sourcedid>18dd21df2d99f639538e58e8133eb1f614b433cf2e60e35287b6c4ce6dcaee27:::e405f4c8-6e00-4a07-b818-af6df05959ac:::content:5</lis_result_sourcedid>
# <person_contact_email_primary>testuser@dishevelled.net</person_contact_email_primary>
# <person_name_family>User</person_name_family>
# <person_name_full>Test User</person_name_full>
# <person_name_given>Test</person_name_given>
# <person_sourcedid>student_f3a9bdcea6175fab2826b650be473fa4</person_sourcedid>
# <role>Learner</role>
# <roles>Learner</roles>
# <user_id>e405f4c8-6e00-4a07-b818-af6df05959ac</user_id>
# </member>
# </members>
# <statusinfo>
# <codemajor>Success</codemajor>
# <codeminor>fullsuccess</codeminor>
# <severity>Status</severity>
# </statusinfo>
# </message_response>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment