### Quick Start Setup Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Example of setting up the LTIJS Provider with MongoDB, configuring routes, and registering a platform. ```APIDOC ## Quick start > Setting up Ltijs ```javascript const path = require('path') // Require Provider const lti = require('ltijs').Provider // Setup provider lti.setup('LTIKEY', // Key used to sign cookies and tokens { // Database configuration url: 'mongodb://localhost/database', connection: { user: 'user', pass: 'password' } }, { // Options appRoute: '/', loginRoute: '/login', // Optionally, specify some of the reserved routes cookies: { secure: false, // Set secure to true if the testing platform is in a different domain and https is being used sameSite: '' // Set sameSite to 'None' if the testing platform is in a different domain and https is being used }, devMode: true // Set DevMode to false if running in a production environment with https } ) // Set lti launch callback lti.onConnect((token, req, res) => { console.log(token) return res.send('It\'s alive!') }) const setup = async () => { // Deploy server and open connection to the database await lti.deploy({ port: 3000 }) // Specifying port. Defaults to 3000 // Register platform await lti.registerPlatform({ url: 'https://platform.url', name: 'Platform Name', clientId: 'TOOLCLIENTID', authenticationEndpoint: 'https://platform.url/auth', accesstokenEndpoint: 'https://platform.url/token', authConfig: { method: 'JWK_SET', key: 'https://platform.url/keyset' } }) } setup() ``` ``` -------------------------------- ### Initialize Provider with setup method Source: https://github.com/cvmcosta/ltijs/blob/master/docs/migration.md Replaces the previous constructor-based initialization with the setup method to support singleton behavior. ```javascript // Require Provider const Lti = require('ltijs').Provider // Setup provider using contructor const lti = new Lti('LTIKEY', // Key used to sign cookies and tokens { url: 'mongodb://localhost/database' }, // Database configuration { appUrl: '/', loginUrl: '/login' }) // Optionally, specify some of the reserved routes ``` ```javascript // Require Provider const lti = require('ltijs').Provider // Setup provider using setup method lti.setup('LTIKEY', // Key used to sign cookies and tokens { url: 'mongodb://localhost/database' }, // Database configuration { appRoute: '/', loginRoute: '/login' }) // Optionally, specify some of the reserved routes ``` -------------------------------- ### Installation Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Install the ltijs package using npm. ```APIDOC ## Installation ### Installing the package ```shell $ npm install ltijs ``` ``` -------------------------------- ### Provider.deploy(options) Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Starts listening to a given port for LTI requests and opens connection to the configured database. ```APIDOC ## async Provider.deploy(options) ### Description Starts listening to a given port for LTIĀ® requests and opens connection to the configured database. ### Parameters #### Request Body - **encryptionkey** (String) - Required - Secret used to sign cookies and encrypt data. - **database** (Object) - Required - Database configuration. - **url** (String) - Required - Database url (Ex: mongodb://localhost/applicationdb). - **connection** (Object) - Optional - MongoDB database connection options. - **connection.user** (String) - Optional - Database user for authentication. - **connection.pass** (String) - Optional - Database pass for authentication. - **debug** (Boolean) - Optional - If set to true, enables mongoose debug mode. Default: false. - **plugin** (Object) - Optional - If set, uses the given database plugin instead of the default MongoDB. - **options** (Object) - Optional - LTI Provider options. - **appRoute** (String) - Optional - Lti Provider main url. Default: '/'. - **loginRoute** (String) - Optional - Lti Provider login url. Default: '/login'. - **keysetRoute** (String) - Optional - Lti Provider public jwk keyset route. Default: '/keys'. - **dynRegRoute** (String) - Optional - Dynamic registration route. Default: '/register'. - **https** (Boolean) - Optional - Set this as true in development if you are not using any web server to redirect to your tool. Default: false. - **ssl** (Object) - Optional - SSL certificate and key to be used if https flag is enabled. - **ssl.key** (String) - Optional - SSL key. - **ssl.cert** (String) - Optional - SSL certificate. - **staticPath** (String) - Optional - The path for the static files your application might serve. - **cors** (Boolean) - Optional - If set to false, disables cors. Default: true. - **serverAddon** (Function) - Optional - Allows the execution of a method inside of the server contructor. - **cookies** (Object) - Optional - Cookie configuration. - **cookies.secure** (Boolean) - Optional - Cookie secure parameter. Default: false. - **cookies.sameSite** (String) - Optional - Cookie sameSite parameter. Default: Lax. - **tokenMaxAge** (String) - Optional - Sets the idToken max age allowed in seconds. Default: 10. - **devMode** (Boolean) - Optional - If true, does not require state and session cookies to be present. Default: false. - **ltiaas** (Boolean) - Optional - If set to true, disables the creation and validation of the session cookies. Default: false. - **dynReg** (Object) - Optional - Setup for the Dynamic Registration Service. - **dynReg.url** (String) - Required - Tool Provider main URL. - **dynReg.name** (String) - Required - Tool Provider name. - **dynReg.logo** (String) - Optional - Tool Provider logo. - **dynReg.description** (String) - Optional - Tool Provider description. - **dynReg.redirectUris** (Array) - Optional - Additional redirect URIs. - **dynReg.customParameters** (Object) - Optional - Custom parameters object. - **dynReg.autoActivate** (Boolean) - Optional - Platform auto activation flag. Default: false. ``` -------------------------------- ### Basic Members Route Example Source: https://github.com/cvmcosta/ltijs/blob/master/docs/namesandroles.md A basic example of an Express.js route to fetch and send all members of a context. Ensure 'res.locals.token' is populated. ```javascript // Members route lti.app.get('/members', async (req, res) => { const members = await lti.NamesAndRoles.getMembers(res.locals.token) // Gets context members res.send(members) }) ``` -------------------------------- ### Install ltijs Package Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Use npm to install the ltijs package. This is the first step to integrating LTI functionality into your project. ```shell $ npm install ltijs ``` -------------------------------- ### Example ContextToken Object Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md A sample JSON structure of a contexttoken object for a Moodle platform. ```json // Example contexttoken for a Moodle platform { "contextId": "http%3A%2F%2Flocalhost%2FmoodlewTtQU3zWHvVeCUf12_57", "path": "/", "user": "2", "roles": [ "http://purl.imsglobal.org/vocab/lis/v2/institution/person#Administrator", "http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor", "http://purl.imsglobal.org/vocab/lis/v2/system/person#Administrator" ], "targetLinkUri": "http://localhost:3000", "context": { "id": "2", "label": "course", "title": "Course", "type": [ "CourseSection" ] }, "resource": { "title": "Ltijs Demo", "id": "57" }, "custom": { "system_setting_url": "http://localhost/moodle/mod/lti/services.php/tool/1/custom", "context_setting_url": "http://localhost/moodle/mod/lti/services.php/CourseSection/2/bindings/tool/1/custom", "link_setting_url": "http://localhost/moodle/mod/lti/services.php/links/{link_id}/custom" }, "lis": { "person_sourcedid": "", "course_section_sourcedid": "" }, "endpoint": { "scope": [ "https://purl.imsglobal.org/spec/lti-ags/scope/lineitem", "https://purl.imsglobal.org/spec/lti-ags/scope/lineitem.readonly", "https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly", "https://purl.imsglobal.org/spec/lti-ags/scope/score" ], "lineitems": "http://localhost/moodle/mod/lti/services.php/2/lineitems?type_id=1", "lineitem": "http://localhost/moodle/mod/lti/services.php/2/lineitems/26/lineitem?type_id=1" }, "namesRoles": { "context_memberships_url": "http://localhost/moodle/mod/lti/services.php/CourseSection/2/bindings/1/memberships", "service_versions": [ "1.0", "2.0" ] }, "launchPresentation": { "locale": "en", "document_target": "iframe", "return_url": "http://localhost/moodle/mod/lti/return.php?course=2&launch_container=3&instanceid=57&sesskey=6b5H1MF8yp" }, "messageType": "LtiResourceLinkRequest", "version": "1.3.0" } ``` -------------------------------- ### Retrieve Platform in onConnect Source: https://github.com/cvmcosta/ltijs/blob/master/docs/migration.md Example of using the IdToken's issuer and clientId to retrieve a platform during an LTI launch. ```javascript lti.onConnect((token, request, response, next) => { const plat = await lti.getPlatform(token.iss, token.clientId) } ) ``` -------------------------------- ### Install ltijs Package Source: https://github.com/cvmcosta/ltijs/blob/master/README.md Use npm to install the ltijs package. This is the first step to integrating LTIĀ® 1.3 functionality into your web application. ```shell npm install ltijs ``` -------------------------------- ### Setup Dynamic Registration with Ltijs Provider Source: https://github.com/cvmcosta/ltijs/blob/master/docs/dynamicregistration.md Configure the Ltijs Provider to enable dynamic registration. This requires setting the 'dynRegRoute' and 'dynReg' options in the Provider.setup method. Ensure all required fields within 'dynReg' are provided. ```javascript const lti = require('ltijs').Provider lti.setup('LTIKEY', { url: 'mongodb://localhost/database', connection: { user: 'user', pass: 'password' } }, { appRoute: '/', loginRoute: '/login', cookies: { secure: false, sameSite: '' }, devMode: true, dynRegRoute: '/register', dynReg: { url: 'http://tool.example.com', name: 'Tool Provider', logo: 'http://tool.example.com/assets/logo.svg', description: 'Tool Description', redirectUris: ['http://tool.example.com/launch'], customParameters: { key: 'value' }, autoActivate: false } } ) ``` -------------------------------- ### IdToken Object Structure Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Example of the IdToken object containing platform and user information. ```javascript { "iss": "http://localhost/moodle", "clientId": "CLIENTID", "deploymentId": "1", "platformId": "60b1fce753c875193d71b611e895f03d" "platformInfo": { "product_family_code": "moodle", "version": "2020042400", "guid": "localhost", "name": "moodle", "description": "Local Moodle" }, "user": "2", "userInfo": { "given_name": "Admin", "family_name": "User", "name": "Admin User", "email": "local@moodle.com" } } ``` -------------------------------- ### LTIjs Redirection URI Strategy Example Source: https://github.com/cvmcosta/ltijs/blob/master/docs/redirectionuris.md Illustrates how LTIjs manages URL parameters during the LTI launch flow. It shows the received target_link_uri, how parameters are stored in the state, the cleaned redirect_uri, and the final reapplication of parameters. ```javascript https://tool.com?resource=123 ``` ```javascript { state: "12uy3g8asd7123vasdjhv123876asd", query: { resource: "123" } } ``` ```javascript https://tool.com ``` ```javascript https://tool.com?resource=123 ``` -------------------------------- ### Example Member Object Structure Source: https://github.com/cvmcosta/ltijs/blob/master/docs/namesandroles.md Illustrates the structure of a single member object returned by the getMembers method, including status, names, email, user ID, and roles. ```json { "id" : "https://lms.example.com/sections/2923/memberships", "context": { "id": "2923-abc", "label": "CPS 435", "title": "CPS 435 Learning Analytics", }, "members" : [ { "status" : "Active", "name": "Jane Q. Public", "picture" : "https://platform.example.edu/jane.jpg", "given_name" : "Jane", "family_name" : "Doe", "middle_name" : "Marie", "email": "jane@platform.example.edu", "user_id" : "0ae836b9-7fc9-4060-006f-27b2066ac545", "lis_person_sourcedid": "59254-6782-12ab", "roles": [ "http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor" ] } ] } ``` -------------------------------- ### Names and Roles standard response structure Source: https://github.com/cvmcosta/ltijs/blob/master/docs/namesandroles.md Example of the JSON structure returned by the getMembers method. ```javascript { "id" : "https://lms.example.com/sections/2923/memberships", "context": { "id": "2923-abc", "label": "CPS 435", "title": "CPS 435 Learning Analytics", }, "members" : [ { "status" : "Active", "name": "Jane Q. Public", "picture" : "https://platform.example.edu/jane.jpg", "given_name" : "Jane", "family_name" : "Doe", "middle_name" : "Marie", "email": "jane@platform.example.edu", "user_id" : "0ae836b9-7fc9-4060-006f-27b2066ac545", "lis_person_sourcedid": "59254-6782-12ab", "roles": [ "http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor" ] } ] } ``` -------------------------------- ### Setup LTIjs Provider with Dynamic Registration Source: https://context7.com/cvmcosta/ltijs/llms.txt Configure the LTIjs provider with dynamic registration enabled. This includes setting up the database connection and defining dynamic registration parameters such as the registration endpoint, tool details, and custom parameters. ```javascript const lti = require('ltijs').Provider // Setup with dynamic registration enabled lti.setup('LTIKEY', { url: 'mongodb://localhost/database' }, { dynRegRoute: '/register', dynReg: { url: 'https://tool.example.com', name: 'My Learning Tool', logo: 'https://tool.example.com/logo.png', description: 'An awesome learning tool', redirectUris: [ 'https://tool.example.com/', 'https://tool.example.com/launch' ], customParameters: { tool_id: 'my_tool', version: '1.0' }, autoActivate: false, // Require manual activation useDeepLinking: true } } ) ``` -------------------------------- ### Deploy Ltijs Provider - Standard and Serverless Source: https://context7.com/cvmcosta/ltijs/llms.txt Deploy the Ltijs Provider, either as a standard Express server on a specified port or in serverless mode to be used as middleware. Includes setup for graceful shutdown. ```javascript const lti = require('ltijs').Provider lti.setup('LTIKEY', { url: 'mongodb://localhost/database' }) // Standard deployment const setup = async () => { await lti.deploy({ port: 3000, silent: false }) console.log('LTI Provider running on port 3000') } setup() // Serverless mode - use as middleware const express = require('express') const app = express() const setupServerless = async () => { await lti.deploy({ serverless: true }) app.use('/lti', lti.app) // Mount Ltijs at /lti prefix app.listen(3000) } setupServerless() // Graceful shutdown process.on('SIGTERM', async () => { await lti.close({ silent: false }) process.exit(0) }) ``` -------------------------------- ### Deploy Ltijs Application Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Deploys the Ltijs application by establishing a database connection and starting the Express server. It can be configured with options for port, silent mode, and serverless deployment. ```APIDOC ## Deploy Ltijs Application ### Description Initiates the deployment of the Ltijs application, which includes connecting to the configured database and starting the Express server. This method can be customized with various options. ### Method `await lti.deploy([options])` ### Parameters #### Options Object - **port** (number) - Optional - The port for the Express server. Defaults to 3000. - **silent** (boolean) - Optional - Suppresses deployment messages if true. Defaults to false. - **serverless** (boolean) - Optional - If true, Ltijs will not start the Express server, allowing integration with other servers. Defaults to false. ### Request Example (Default) ```javascript await lti.deploy() ``` ### Request Example (Customized) ```javascript await lti.deploy({ port: 3030, silent: false }) ``` ### Serverless Deployment Example ```javascript const app = express() lti.setup('EXAMPLEKEY', { url: 'mongodb://localhost/database' }) // Start LTI provider in serverless mode await lti.deploy({ serverless: true }) // Mount Ltijs express app into preexisting express app with /lti prefix app.use('/lti', lti.app) ``` ``` -------------------------------- ### Deploy Ltijs Application Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Deploys the Ltijs application, establishing a database connection and starting the Express server. Options include port, silent mode, and serverless deployment. ```javascript await lti.deploy() ``` ```javascript await lti.deploy({ port: 3030, silent: false }) ``` -------------------------------- ### lti.setup() Configuration Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Configures the LTI provider with encryption key, database settings, and options. ```APIDOC ## POST /setup ### Description Sets up the LTI provider configuration. ### Method POST ### Endpoint /setup ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **encryptionKey** (String) - Required. Secret key for signing cookies and encrypting sensitive data. - **database** (Object) - Required. Database configuration. - **url** (String) - Required. Database connection URL. - **connection** (Object) - Optional. MongoDB Driver connection options (e.g., user, pass). - **debug** (Boolean) - Optional. Enables Mongoose's debug mode. - **plugin** (Object) - Optional. Database plugin (e.g., ltijs-sequelize). - **options** (Object) - Optional. Additional provider configuration. - **appRoute** (String) - Optional. Route for successful launch requests. Default: '/'. - **loginRoute** (String) - Optional. Route for OIDC login flow. Default: '/login'. - **keysetRoute** (String) - Optional. Route to serve JWK keyset. Default: '/keys'. - **dynRegRoute** (String) - Optional. Route for Dynamic Registration requests. Default: '/register'. - **cookies** (Object) - Optional. Cookie configuration. - **secure** (Boolean) - Optional. If true, cookies are only sent through https. Default: false. - **sameSite** (String) - Optional. Determines if cookie can be sent cross domain. Default: 'Lax'. - **domain** (String) - Optional. Cookie domain. ### Request Example ```json { "encryptionKey": "EXAMPLEKEY", "database": { "url": "mongodb://localhost/database", "connection": { "user": "user", "pass": "pass" } }, "options": { "appRoute": "/app", "loginRoute": "/loginroute", "keysetRoute": "/keyset", "dynRegRoute": "/register", "cookies": { "secure": true, "sameSite": "None", "domain": ".domain.com" } } } ``` ### Response #### Success Response (200) None (Setup is performed) #### Response Example None ``` -------------------------------- ### Configure Ltijs in main application file Source: https://github.com/cvmcosta/ltijs/blob/master/docs/migration.md Demonstrates initializing the singleton provider and deploying the application in a primary entry file. ```javascript // a.js // Require Provider const lti = require('ltijs').Provider // Require b.js const routes = require('./b') // Setup method can be called only once lti.setup('LTIKEY', { url: 'mongodb://localhost/database' }, { appRoute: '/', loginRoute: '/login' }) // Setting up routes lti.app.use(routes) lti.deploy() ``` -------------------------------- ### Configuring the Ltijs Provider Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md The lti.setup() method is required to initialize the provider with an encryption key, database connection, and optional configuration settings. ```javascript // Require Ltijs package const lti = require('ltijs').Provider // Setup provider example lti.setup('EXAMPLEKEY', { url: 'mongodb://localhost/database',// Database url connection:{ user:'user', pass: 'pass'}// Database configuration }, { appRoute: '/app',// Scpecifying main app route loginRoute: '/login', // Specifying login route cookies: { secure: true, // Cookies will only be passed through https. sameSite: 'None' // Cookies can be set across domains. } }) ``` ```javascript // Setup provider example lti.setup('EXAMPLEKEY', { url: 'mongodb://localhost/database',// Database url connection:{ user:'user', pass: 'pass'}// Database configuration }, { appRoute: '/app',// Scpecifying main app route loginRoute: '/loginroute', // Specifying login route keysetRoute: '/keyset', // Specifying keyset route dynRegRoute: '/register' // Specifying Dynamic registration route }) ``` ```javascript // Setup provider example lti.setup('EXAMPLEKEY', { url: 'mongodb://localhost/database',// Database url connection:{ user:'user', pass: 'pass'}// Database configuration }, { cookies: { // Cookie configuration secure: true, sameSite: 'None', domain: '.domain.com' } }) ``` -------------------------------- ### Implement a full LTI 1.3 provider application Source: https://context7.com/cvmcosta/ltijs/llms.txt This script initializes the LTI provider, handles standard and deep linking launches, manages course data, and performs grade submissions. Ensure the database connection string and encryption keys are configured correctly for your environment. ```javascript const lti = require('ltijs').Provider const path = require('path') // Setup lti.setup('MY_ENCRYPTION_KEY', { url: 'mongodb://localhost/lti_app' }, { cookies: { secure: true, sameSite: 'None' }, dynReg: { url: 'https://tool.example.com', name: 'Complete LTI Tool', logo: 'https://tool.example.com/logo.png', description: 'Full-featured LTI 1.3 tool', autoActivate: false } } ) // Whitelist public routes lti.whitelist('/health', '/public') // Main launch lti.onConnect(async (token, req, res) => { const context = token.platformContext return res.send(`

Welcome ${token.userInfo?.name || 'User'}

Course: ${context.context?.title || 'Unknown'}

Role: ${context.roles?.join(', ')}

Go to Dashboard `) }) // Deep linking launch lti.onDeepLinking(async (token, req, res) => { return lti.redirect(res, '/select-content') }) // Dashboard with grades and members lti.app.get('/dashboard', async (req, res) => { const token = res.locals.token try { // Get course members const membersResponse = await lti.NamesAndRoles.getMembers(token) // Get line items const lineItemsResponse = await lti.Grade.getLineItems(token) return res.json({ user: token.userInfo, course: token.platformContext.context, members: membersResponse.members, lineItems: lineItemsResponse.lineItems }) } catch (err) { return res.status(500).json({ error: err.message }) } }) // Content selection for deep linking lti.app.get('/select-content', async (req, res) => { return res.send(`

Select Content

`) }) // Register deep linking content lti.app.post('/register-content', async (req, res) => { const token = res.locals.token const { title, resourceId } = req.body const items = [{ type: 'ltiResourceLink', title: title, url: `https://tool.example.com/resource/${resourceId}`, custom: { resourceId } }] const form = await lti.DeepLinking.createDeepLinkingForm(token, items, { message: 'Content added successfully!' }) return res.send(form) }) // Submit grade lti.app.post('/submit-grade', async (req, res) => { const token = res.locals.token const { score } = req.body let lineItemId = token.platformContext.endpoint?.lineitem if (!lineItemId) { const response = await lti.Grade.getLineItems(token, { resourceLinkId: true }) if (response.lineItems.length === 0) { const lineItem = await lti.Grade.createLineItem(token, { scoreMaximum: 100, label: 'Activity Score', resourceLinkId: token.platformContext.resource.id }) lineItemId = lineItem.id } else { lineItemId = response.lineItems[0].id } } await lti.Grade.submitScore(token, lineItemId, { userId: token.user, scoreGiven: parseFloat(score), scoreMaximum: 100, activityProgress: 'Completed', gradingProgress: 'FullyGraded' }) return res.json({ success: true }) }) // Health check (whitelisted) lti.app.get('/health', (req, res) => { res.json({ status: 'ok' }) }) // Deploy const start = async () => { await lti.deploy({ port: 3000 }) // Register initial platform if needed const platforms = await lti.getAllPlatforms() if (platforms.length === 0) { console.log('No platforms registered. Use dynamic registration or register manually.') } console.log('LTI Tool running on port 3000') console.log('Keyset URL: https://tool.example.com/keys') console.log('Login URL: https://tool.example.com/login') console.log('Launch URL: https://tool.example.com/') console.log('Registration URL: https://tool.example.com/register') } start() ``` -------------------------------- ### Provider Initialization and Closing Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Details on how to initialize the LTI Provider with options and how to properly close its connections. ```APIDOC ## Provider Initialization ### Description Initializes the LTI Provider with optional deployment settings. ### Method `Provider.Provider(options)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **options** (Object) - *Optional* - Deployment options. - **options.port** (Number) - *Optional* - The port the Provider should listen to. **Default: 3000**. - **options.silent** (Boolean) - *Optional* - If true, suppresses deployment messages. **Default: false**. - **options.serverless** (Boolean) - *Optional* - If true, Ltijs does not start an Express server instance. This allows usage as a middleware and with services like AWS. Ignores 'port' parameter. **Default: false**. ### Response - Promise that resolves `true` when connection to the database is established and the server starts listening. --- ## Provider.close() ### Description Closes the database connection and stops the server. ### Method `Provider.close(options)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **options** (Object) - *Optional* - Options. - **options.silent** (Boolean) - *Optional* - If true, disables shutdown messages. **Default: false**. ### Response - Promise that resolves `true` when the shutdown is complete. ``` -------------------------------- ### Register a Platform Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Registers a new platform configuration with the provider. ```javascript await lti.registerPlatform({ url: 'https://platform.url', name: 'Platform Name', clientId: 'TOOLCLIENTID', authenticationEndpoint: 'https://platform.url/auth', accesstokenEndpoint: 'https://platform.url/token', authConfig: { method: 'JWK_SET', key: 'https://platform.url/keyset' } }) ``` -------------------------------- ### Get Members by Role Source: https://github.com/cvmcosta/ltijs/blob/master/docs/namesandroles.md Retrieves members belonging to a specific role. Ensure the 'res.locals.token' is available. ```javascript const members = await lti.NamesAndRoles.getMembers(res.locals.token, { role: 'Learner' }) ``` -------------------------------- ### Get Resource Link Level Members Source: https://github.com/cvmcosta/ltijs/blob/master/docs/namesandroles.md Retrieves members specific to a Resource Link. This requires the current context to have a 'resourceLinkId'. ```javascript const result = await lti.NamesAndRoles.getMembers(res.locals.token, { resourceLinkId: true, role: 'Learner', limit: 10, pages: 2 }) ``` -------------------------------- ### Get Resource-Level Membership Source: https://context7.com/cvmcosta/ltijs/llms.txt Retrieves membership information for a specific resource (activity). Set 'resourceLinkId' to true and optionally filter by 'role'. ```javascript // Resource-level membership (specific activity) lti.app.get('/members/resource', async (req, res) => { const token = res.locals.token const response = await lti.NamesAndRoles.getMembers(token, { resourceLinkId: true, role: 'Learner' }) return res.json(response.members) }) ``` -------------------------------- ### Initialize and Deploy Ltijs Provider Source: https://github.com/cvmcosta/ltijs/blob/master/README.md Configures the LTI provider with database settings and registers a platform for LTI launches. ```javascript const path = require('path') // Require Provider const lti = require('ltijs').Provider // Setup provider lti.setup('LTIKEY', // Key used to sign cookies and tokens { // Database configuration url: 'mongodb://localhost/database', connection: { user: 'user', pass: 'password' } }, { // Options appRoute: '/', loginRoute: '/login', // Optionally, specify some of the reserved routes cookies: { secure: false, // Set secure to true if the testing platform is in a different domain and https is being used sameSite: '' // Set sameSite to 'None' if the testing platform is in a different domain and https is being used }, devMode: true // Set DevMode to false if running in a production environment with https } ) // Set lti launch callback lti.onConnect((token, req, res) => { console.log(token) return res.send('It\'s alive!') }) const setup = async () => { // Deploy server and open connection to the database await lti.deploy({ port: 3000 }) // Specifying port. Defaults to 3000 // Register platform await lti.registerPlatform({ url: 'https://platform.url', name: 'Platform Name', clientId: 'TOOLCLIENTID', authenticationEndpoint: 'https://platform.url/auth', accesstokenEndpoint: 'https://platform.url/token', authConfig: { method: 'JWK_SET', key: 'https://platform.url/keyset' } }) } setup() ``` -------------------------------- ### Get All Course Members Source: https://context7.com/cvmcosta/ltijs/llms.txt Retrieves all members of a course. The response includes user details and roles. Ensure the 'token' is available in res.locals. ```javascript const lti = require('ltijs').Provider // Get all course members lti.app.get('/members', async (req, res) => { const token = res.locals.token const response = await lti.NamesAndRoles.getMembers(token) // Response structure: // { // id: "https://platform.edu/memberships", // context: { id, label, title }, // members: [ // { // status: "Active", // name: "John Doe", // given_name: "John", // family_name: "Doe", // email: "john@school.edu", // user_id: "user123", // roles: ["http://purl.imsglobal.org/vocab/lis/v2/membership#Learner"] // } // ] // } return res.json(response) }) ``` -------------------------------- ### Resource Selection Page Source: https://context7.com/cvmcosta/ltijs/llms.txt Serves the HTML file for the resource picker. Ensure the 'public/resource-picker.html' file exists. ```javascript // Resource selection page lti.app.get('/deeplink/select', async (req, res) => { return res.sendFile(path.join(__dirname, 'public/resource-picker.html')) }) ``` -------------------------------- ### Get All Course Members (Unlimited Pages) Source: https://context7.com/cvmcosta/ltijs/llms.txt Retrieves all members from all available pages without any limit. Set 'pages' to 'false' to disable pagination. ```javascript // Get all members (unlimited pages) lti.app.get('/members/all', async (req, res) => { const token = res.locals.token const response = await lti.NamesAndRoles.getMembers(token, { pages: false // Retrieve all pages }) return res.json(response.members) }) ``` -------------------------------- ### Platform Class Methods Source: https://context7.com/cvmcosta/ltijs/llms.txt Methods available on the Platform instance to manage specific configuration settings, keys, and activation status. ```APIDOC ## Platform Class Methods ### Description Methods used to interact with an existing platform instance to update settings or retrieve security keys. ### Methods - **platformName(newName)** - Get or set the platform display name. - **platformAuthenticationEndpoint(newEndpoint)** - Get or set the authentication endpoint. - **platformAccessTokenEndpoint(newEndpoint)** - Get or set the access token endpoint. - **platformActive(status)** - Get or set the activation status (boolean). - **platformPublicKey()** - Retrieves the tool's public key for this platform. - **platformAccessToken(scopes)** - Retrieves an access token for making API calls to the platform. - **delete()** - Deletes the current platform instance. ``` -------------------------------- ### Send Grades to Platform Source: https://github.com/cvmcosta/ltijs/blob/master/docs/grading.md Example of an Express route handler to submit a user grade, including logic to retrieve or create a line item if necessary. ```javascript const lti = require('ltijs').Provider /** * sendGrade */ lti.app.post('/grade', async (req, res) => { try { const idtoken = res.locals.token // IdToken const score = req.body.grade // User numeric score sent in the body // Creating Grade object const gradeObj = { userId: idtoken.user, scoreGiven: score, scoreMaximum: 100, activityProgress: 'Completed', gradingProgress: 'FullyGraded' } // Selecting linetItem ID let lineItemId = idtoken.platformContext.endpoint.lineitem // Attempting to retrieve it from idtoken if (!lineItemId) { const response = await lti.Grade.getLineItems(idtoken, { resourceLinkId: true }) const lineItems = response.lineItems if (lineItems.length === 0) { // Creating line item if there is none console.log('Creating new line item') const newLineItem = { scoreMaximum: 100, label: 'Grade', tag: 'grade', resourceLinkId: idtoken.platformContext.resource.id } const lineItem = await lti.Grade.createLineItem(idtoken, newLineItem) lineItemId = lineItem.id } else lineItemId = lineItems[0].id } // Sending Grade const responseGrade = await lti.Grade.submitScore(idtoken, lineItemId, gradeObj) return res.send(responseGrade) } catch (err) { return res.status(500).send({ err: err.message }) } }) ``` -------------------------------- ### Deploy Ltijs as Middleware Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Use Ltijs as middleware in an existing Express application by deploying in serverless mode and mounting the Ltijs app. Requires prior setup. ```javascript const app = express() lti.setup('EXAMPLEKEY', { url: 'mongodb://localhost/database' }) // Start LTI provider in serverless mode await lti.deploy({ serverless: true }) // Mount Ltijs express app into preexisting express app with /lti prefix app.use('/lti', lti.app) ``` -------------------------------- ### Handle Deep Linking Callback Source: https://github.com/cvmcosta/ltijs/blob/master/docs/deeplinking.md Sets up a listener for deep linking events. When triggered, it returns a file to display the resource selection view. ```javascript // Deep Linking callback lti.onDeepLinking((token, req, res) => { // Displays the resource selection view return res.sendFile(path.join(__dirname, '/public/resources.html')) }) ``` -------------------------------- ### Handle Deep Linking Launch Source: https://context7.com/cvmcosta/ltijs/llms.txt Listens for deep linking requests and redirects to a resource selection view. Requires the ltijs module. ```javascript const lti = require('ltijs').Provider const path = require('path') // Handle deep linking launch lti.onDeepLinking(async (token, req, res) => { // Redirect to resource selection view return lti.redirect(res, '/deeplink/select') }) ``` -------------------------------- ### GET /api/members Source: https://github.com/cvmcosta/ltijs/blob/master/docs/namesandroles.md Retrieves members from the platform with optional filtering. The getMembers method allows specifying options such as role, limit, pages, resourceLinkId, and a URL for paginated results. ```APIDOC ## GET /api/members ### Description Retrieves members from the platform with optional filtering. The getMembers method allows specifying options such as role, limit, pages, resourceLinkId, and a URL for paginated results. ### Method GET ### Endpoint /api/members ### Parameters #### Query Parameters - **role** (String) - Optional - Specifies that only members part of a certain role should be included in the list. - **limit** (Number) - Optional - Specifies the number of members per page that should be returned per members page. By default only one members page is returned. - **pages** (Number) - Optional - Specifies the number of pages that should be returned. Defaults to 1. If set to false retrieves every available page. - **resourceLinkId** (Boolean) - Optional - Accesses the Platform's Resource Link level membership service. This parameter will only take effect if the current context has a `resourceLinkId`. - **url** (String) - Optional - In case not all members were retrieved when the page limit was reached, the returned object will contain a `next` field holding an url that can be used to retrieve the remaining members. This url can be passed through the `options.url` parameter. If the `options.url` parameter is present, the `limit`, `role` and `resourceLinkId` filters are ignored, instead, the filters applied on the initial request will be maintained. ### Request Example ```javascript // Example with role and limit const members = await lti.NamesAndRoles.getMembers(res.locals.token, { role: 'Learner', limit: 10 }) // Example with pagination using 'next' URL const result = await lti.NamesAndRoles.getMembers(res.locals.token, { role: 'Learner', limit: 10, pages: 2 }) const next = result.next const remaining = await lti.NamesAndRoles.getMembers(res.locals.token, { pages: 2, url: next }) // Example with differences URL const differencesUrl = result.differences const differences = await lti.NamesAndRoles.getMembers(res.locals.token, { url: differencesUrl }) ``` ### Response #### Success Response (200) - **id** (String) - The unique identifier for the membership endpoint. - **context** (Object) - Information about the context (e.g., course). - **id** (String) - The unique identifier for the context. - **label** (String) - The label for the context. - **title** (String) - The title of the context. - **members** (Array) - An array of member objects. - **status** (String) - The status of the member (e.g., 'Active'). - **name** (String) - The full name of the member. - **picture** (String) - URL to the member's profile picture. - **given_name** (String) - The member's given name. - **family_name** (String) - The member's family name. - **middle_name** (String) - The member's middle name. - **email** (String) - The member's email address. - **user_id** (String) - The unique identifier for the user. - **lis_person_sourcedid** (String) - The sourcedid for the person. - **roles** (Array) - An array of strings representing the member's roles. - **next** (String) - URL to the next page of members, if available. - **differences** (String) - URL to retrieve membership differences, if available. #### Response Example ```json { "id" : "https://lms.example.com/sections/2923/memberships", "context": { "id": "2923-abc", "label": "CPS 435", "title": "CPS 435 Learning Analytics" }, "members" : [ { "status" : "Active", "name": "Jane Q. Public", "picture" : "https://platform.example.edu/jane.jpg", "given_name" : "Jane", "family_name" : "Doe", "middle_name" : "Marie", "email": "jane@platform.example.edu", "user_id" : "0ae836b9-7fc9-4060-006f-27b2066ac545", "lis_person_sourcedid": "59254-6782-12ab", "roles": [ "http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor" ] } ], "next": "https://lms.example.com/sections/2923/memberships/page/2" } ``` ``` -------------------------------- ### Get Members with Pagination and Limit Source: https://github.com/cvmcosta/ltijs/blob/master/docs/namesandroles.md Retrieves a specified number of members per page across a set number of pages. Defaults to 1 page if 'pages' is not specified. ```javascript const result = await lti.NamesAndRoles.getMembers(res.locals.token, { role: 'Learner', limit: 10, pages: 2 }) ``` -------------------------------- ### Configure server addon for static files Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Uses a serverAddon to register custom middleware for serving static files via a specific route. ```javascript // Creating middleware registration const middleware = (app) => { app.use('/static', express.static(__dirname + '/public')); } //Configure provider lti.setup('EXAMPLEKEY', { url: 'mongodb://localhost/database', connection:{ user:'user', pass: 'pass'} }, { serverAddon: middleware // Setting addon method }) ```