ltijs
Version:
Easily turn your web application into a LTI 1.3 Learning Tool.
120 lines (117 loc) • 6.02 kB
JavaScript
;
function _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }
function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
function _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }
function _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }
function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); }
/* Names and Roles Provisioning Service */
const got = require('../../Utils/Http');
const parseLink = require('parse-link-header');
const provNamesAndRolesServiceDebug = require('debug')('provider:namesAndRolesService');
var _getPlatform = /*#__PURE__*/new WeakMap();
var _ENCRYPTIONKEY = /*#__PURE__*/new WeakMap();
var _Database = /*#__PURE__*/new WeakMap();
class NamesAndRoles {
constructor(getPlatform, ENCRYPTIONKEY, Database) {
_classPrivateFieldInitSpec(this, _getPlatform, null);
_classPrivateFieldInitSpec(this, _ENCRYPTIONKEY, '');
_classPrivateFieldInitSpec(this, _Database, void 0);
_classPrivateFieldSet(_getPlatform, this, getPlatform);
_classPrivateFieldSet(_ENCRYPTIONKEY, this, ENCRYPTIONKEY);
_classPrivateFieldSet(_Database, this, Database);
}
/**
* @description Retrieves members from platform.
* @param {Object} idtoken - Idtoken for the user.
* @param {Object} options - Request options.
* @param {String} [options.role] - Filters based on the User role.
* @param {Number} [options.limit] - Sets a maximum number of memberships to be returned per page.
* @param {Number} [options.pages = 1] - Sets a maximum number of pages to be returned. Defaults to 1. If set to false retrieves every available page.
* @param {String} [options.url] - Retrieve memberships from a specific URL. Usually retrieved from the `next` link header of a previous request.
* @param {Boolean} [options.resourceLinkId = false] - If set to true, retrieves resource Link level memberships.
*/
async getMembers(idtoken, options) {
if (!idtoken) {
provNamesAndRolesServiceDebug('Missing IdToken object.');
throw new Error('MISSING_ID_TOKEN');
}
provNamesAndRolesServiceDebug('Attempting to retrieve memberships');
provNamesAndRolesServiceDebug('Target platform: ' + idtoken.iss);
const platform = await _classPrivateFieldGet(_getPlatform, this).call(this, idtoken.iss, idtoken.clientId, _classPrivateFieldGet(_ENCRYPTIONKEY, this), _classPrivateFieldGet(_Database, this));
if (!platform) {
provNamesAndRolesServiceDebug('Platform not found');
throw new Error('PLATFORM_NOT_FOUND');
}
const platformActive = await platform.platformActive();
if (!platformActive) throw new Error('PLATFORM_NOT_ACTIVATED');
provNamesAndRolesServiceDebug('Attempting to retrieve platform access_token for [' + idtoken.iss + ']');
const tokenRes = await platform.platformAccessToken('https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly');
provNamesAndRolesServiceDebug('Access_token retrieved for [' + idtoken.iss + ']');
let pages = 1; // Page limit
let query = [];
let next = idtoken.platformContext.namesRoles.context_memberships_url;
if (options) {
if (options.pages || options.pages === false) {
provNamesAndRolesServiceDebug('Maximum number of pages retrieved: ' + options.pages);
pages = options.pages;
}
if (options.url) {
next = options.url;
query = false;
} else {
if (options.role) {
provNamesAndRolesServiceDebug('Adding role parameter with value: ' + options.role);
query.push(['role', options.role]);
}
if (options.limit) {
provNamesAndRolesServiceDebug('Adding limit parameter with value: ' + options.limit);
query.push(['limit', options.limit]);
}
if (options.resourceLinkId) {
provNamesAndRolesServiceDebug('Adding rlid parameter with value: ' + idtoken.platformContext.resource.id);
query.push(['rlid', idtoken.platformContext.resource.id]);
}
}
}
if (query && query.length > 0) query = new URLSearchParams(query);else query = false;
let differences;
let result;
let curPage = 1;
do {
if (pages && curPage > pages) {
if (next) result.next = next;
break;
}
let response;
provNamesAndRolesServiceDebug('Member pages found: ', curPage);
provNamesAndRolesServiceDebug('Current member page: ', next);
if (query && curPage === 1) response = await got.get(next, {
searchParams: query,
headers: {
Authorization: tokenRes.token_type + ' ' + tokenRes.access_token,
Accept: 'application/vnd.ims.lti-nrps.v2.membershipcontainer+json'
}
});else response = await got.get(next, {
headers: {
Authorization: tokenRes.token_type + ' ' + tokenRes.access_token,
Accept: 'application/vnd.ims.lti-nrps.v2.membershipcontainer+json'
}
});
const headers = response.headers;
const body = JSON.parse(response.body);
if (!result) result = JSON.parse(JSON.stringify(body));else {
result.members = [...result.members, ...body.members];
}
const parsedLinks = parseLink(headers.link);
// Trying to find "rel=differences" header
if (parsedLinks && parsedLinks.differences) differences = parsedLinks.differences.url;
// Trying to find "rel=next" header, indicating additional pages
if (parsedLinks && parsedLinks.next) next = parsedLinks.next.url;else next = false;
curPage++;
} while (next);
if (differences) result.differences = differences;
provNamesAndRolesServiceDebug('Memberships retrieved');
return result;
}
}
module.exports = NamesAndRoles;