UNPKG

@dinoboff/ims-lti

Version:

Module for building an LTI Tool Provider and accept LTI launch requests

151 lines (136 loc) 6.1 kB
// Generated by CoffeeScript 1.12.7 (function() { var HMAC_SHA1, MemoryNonceStore, Provider, errors, exports, extensions, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; HMAC_SHA1 = require('./hmac-sha1'); MemoryNonceStore = require('./memory-nonce-store'); errors = require('./errors'); extensions = require('./extensions'); Provider = (function() { function Provider(consumer_key, consumer_secret, optionsOrNonceStore, signature_method) { this.parse_request = bind(this.parse_request, this); this.valid_request = bind(this.valid_request, this); var nonceStore, options; if (typeof consumer_key === 'undefined' || consumer_key === null) { throw new errors.ConsumerError('Must specify consumer_key'); } if (typeof consumer_secret === 'undefined' || consumer_secret === null) { throw new errors.ConsumerError('Must specify consumer_secret'); } if (optionsOrNonceStore && (typeof optionsOrNonceStore.isNonceStore === "function" ? optionsOrNonceStore.isNonceStore() : void 0)) { options = {}; nonceStore = optionsOrNonceStore; } else { options = optionsOrNonceStore || {}; nonceStore = options.nonceStore || new MemoryNonceStore(); } if (!signature_method) { signature_method = options.signer || new HMAC_SHA1(options); } this.consumer_key = consumer_key; this.consumer_secret = consumer_secret; this.signer = signature_method; this.nonceStore = nonceStore; this.body = {}; } Provider.prototype.valid_request = function(req, body, callback) { if (!callback) { callback = body; body = void 0; } body = body || req.body || req.payload; callback = callback || function() {}; this.parse_request(req, body); if (!this._valid_parameters(body)) { return callback(new errors.ParameterError('Invalid LTI parameters'), false); } return this._valid_oauth(req, body, callback); }; Provider.prototype._valid_parameters = function(body) { var correct_version, has_resource_link_id, omits_content_item_params; if (!body) { return false; } correct_version = require('./ims-lti').supported_versions.indexOf(body.lti_version) !== -1; has_resource_link_id = body.resource_link_id != null; omits_content_item_params = (body.resource_link_id == null) && (body.resource_link_title == null) && (body.resource_link_description == null) && (body.launch_presentation_return_url == null) && (body.lis_result_sourcedid == null); return correct_version && (body.lti_message_type === 'basic-lti-launch-request' && has_resource_link_id) || (body.lti_message_type === 'ContentItemSelectionRequest' && omits_content_item_params); }; Provider.prototype._valid_oauth = function(req, body, callback) { var generated, valid_signature; generated = this.signer.build_signature(req, body, this.consumer_secret); valid_signature = generated === body.oauth_signature; if (!valid_signature) { return callback(new errors.SignatureError('Invalid Signature'), false); } return this.nonceStore.isNew(body.oauth_nonce, body.oauth_timestamp, function(err, valid) { if (!valid) { return callback(new errors.NonceError('Expired nonce'), false); } else { return callback(null, true); } }); }; Provider.prototype.parse_request = function(req, body) { var extension, extension_name, id, key, results, val; body = body || req.body || req.payload; for (key in body) { val = body[key]; if (key.match(/^oauth_/)) { continue; } this.body[key] = val; } if (typeof this.body.roles === 'string') { this.body.roles = this.body.roles.split(','); } this.admin = this.has_role('Administrator'); this.alumni = this.has_role('Alumni'); this.content_developer = this.has_role('ContentDeveloper'); this.guest = this.has_role('Guest'); this.instructor = this.has_role('Instructor') || this.has_role('Faculty') || this.has_role('Staff'); this.manager = this.has_role('Manager'); this.member = this.has_role('Member'); this.mentor = this.has_role('Mentor'); this.none = this.has_role('None'); this.observer = this.has_role('Observer'); this.other = this.has_role('Other'); this.prospective_student = this.has_role('ProspectiveStudent'); this.student = this.has_role('Learner') || this.has_role('Student'); this.ta = this.has_role('TeachingAssistant'); this.launch_request = this.body.lti_message_type === 'basic-lti-launch-request'; this.username = this.body.lis_person_name_given || this.body.lis_person_name_family || this.body.lis_person_name_full || ''; this.userId = this.body.user_id; if (typeof this.body.role_scope_mentor === 'string') { this.mentor_user_ids = (function() { var i, len, ref, results; ref = this.body.role_scope_mentor.split(','); results = []; for (i = 0, len = ref.length; i < len; i++) { id = ref[i]; results.push(decodeURIComponent(id)); } return results; }).call(this); } this.context_id = this.body.context_id; this.context_label = this.body.context_label; this.context_title = this.body.context_title; results = []; for (extension_name in extensions) { extension = extensions[extension_name]; results.push(extension.init(this)); } return results; }; Provider.prototype.has_role = function(role) { var regex; regex = new RegExp("^(urn:lti:(sys|inst)?role:ims/lis/)?" + role + "(/.+)?$", 'i'); return this.body.roles && this.body.roles.some(function(r) { return regex.test(r); }); }; return Provider; })(); exports = module.exports = Provider; }).call(this);