#!/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>