forked from SeifYounis/Medical-Imaging-Website
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlti_controller.js
More file actions
144 lines (115 loc) · 4.98 KB
/
lti_controller.js
File metadata and controls
144 lines (115 loc) · 4.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/**
* Primary reference for IMS LTI implementation: https://github.com/js-kyle/nodejs-lti-provider
* Other important references:
* https://community.canvaslms.com/t5/Canvas-Developers-Group/Hire-an-LTI-Consultant-Freelancer/td-p/136029
* https://community.canvaslms.com/t5/Canvas-Developers-Group/SameSite-Cookies-and-Canvas/ba-p/257967
* https://github.com/instructure/ims-lti
*
*/
/**
* Assessments are accessed via Canvas assignments. These assignments
* have a launch URL that must be redirected to the appropriate assessment URL.
* This code acts as middleware for that launch route. The request sent to
* the launch URL contains important information about the assigment and the
* student accessing it. With this info, we can configure the assessment
* to be opened, track students, and post grades.
*/
const lti = require('ims-lti');
const nonceStore = new lti.Stores.MemoryStore();
// If app is configured with correct consumer key, proceed to process launch parameters
const getSecret = (consumerKey, callback) => {
const actualKey = process.env.CONSUMER_KEY;
if (consumerKey === actualKey) {
return callback(null, process.env.CONSUMER_SECRET);
}
let err = new Error(`Unknown consumer ${consumerKey}`);
err.status = 403;
return callback(err);
};
/**
* Check that app was configured correctly, process launch parameters and display page corresponding with certain info in request params
*/
exports.handleLaunch = (req, res, next) => {
if (!req.body) {
let err = new Error('Expected a body');
err.status = 400;
return next(err);
}
// Ensure request body contains oauth consumer key obtained from launch URL
const consumerKey = req.body.oauth_consumer_key;
if (!consumerKey) {
let err = new Error('Expected a consumer');
err.status = 422;
return next(err);
}
getSecret(consumerKey, (err, consumerSecret) => {
if (err) {
return next(err);
}
// Create new Provider object enabling us to process request params from launch URL
const provider = new lti.Provider(consumerKey, consumerSecret, nonceStore, lti.HMAC_SHA1);
provider.valid_request(req, req.body, (err, isValid) => {
if (err) {
return next(err);
}
if (isValid) {
// res.cookie("canvas_lti_launch_params", provider.body, {
// maxAge: 1000 * 60 * 60 * 6, // Cookie lasts 6 hours, after which time the assignment must be relaunched
// secure: false,
// httpOnly: true,
// sameSite: 'none', // This property is absolutely necessary to ensure launch URL can save these params in a cookie
// });
// Check if app was launched by an instructor
if (provider.body.roles[0] === 'Instructor') {
return res.redirect('/admin')
}
// Check if app was launched as an assignment by a student
if (provider.outcome_service) {
// Save Canvas launch parameters to session so grades can be set later, as
// well as student ID
req.session.canvas_lti_launch_params = provider.body;
req.session.student_id = provider.body.user_id
// Determine appropriate assessment to launch by matching assessment name to assignment title
let route = "";
if (provider.body.custom_canvas_assignment_title.includes("Reader Study Login")) {
route += '/login'
}
if (provider.body.custom_canvas_assignment_title.includes("Testing Part 1")) {
route += '/testing1';
}
if (provider.body.custom_canvas_assignment_title.includes("Testing Part 2")) {
route += '/testing2';
}
if (provider.body.custom_canvas_assignment_title.includes("Training")) {
route += '/training';
}
if (provider.body.custom_canvas_assignment_title.includes("Rating")) {
route += '/rating';
}
if (provider.body.custom_canvas_assignment_title.includes("Two Alternative Forced Choice")) {
route += '/alternative-choice';
}
// If name of course user is taking includes the words "Self Study", load self-study version of these assessments
if (provider.body.context_title.includes('Self Study') && !route.includes('login')) {
route += '-solo'
}
return res.redirect(route)
}
return res.send(`It looks like this LTI wasn't launched as an assignment`);
} else {
return next(err);
}
});
});
};
// Post grade to student's gradebook
exports.postGrade = (req, res, next) => {
const provider = new lti.Provider(process.env.CONSUMER_KEY, process.env.CONSUMER_SECRET, nonceStore, lti.HMAC_SHA1);
provider.valid_request(req, req.session.canvas_lti_launch_params, (_err, _isValid) => {
let score = parseFloat(req.body.score);
provider.outcome_service.send_replace_result(score, (_err, _result) => {
console.log("Graded")
return res.status(200).send("Grade successfully posted")
})
});
}