diff --git a/config/passport.js b/config/passport.js
index f1e16e7..42cc58c 100644
--- a/config/passport.js
+++ b/config/passport.js
@@ -33,7 +33,25 @@ passport.use(
console.log("user:", user);
profile["dn"] = user.dn;
profile["memberOf"] = user.memberOf;
- return done(null, profile);
+ // Is this user a student or a parent?
+ profile["userType"] = directory.getUserTypeFromDN(profile["dn"]);
+ let user_type = profile["userType"];
+ // If the user is a student, query the student's primary parent
+ // and store the parent's UPN in the session
+ if (user_type === directory.USER_TYPE.STUDENT) {
+ let student = await directory.queryUser(username, ["primaryParent"]);
+ profile["primaryParent"] = student.primaryParent;
+ }
+ // If the user is a parent, query the parent's students
+ // and store the students' UPNs in the session
+ else if (user_type === directory.USER_TYPE.PARENT) {
+ let students = await directory.listStudents(username);
+ profile["students"] = students;
+ } else {
+ console.log("Unknown user type");
+ }
+ return done(null, profile); // Return the user's profile
+
}
)
);
diff --git a/directory.js b/directory.js
index fe226e5..3e886e3 100644
--- a/directory.js
+++ b/directory.js
@@ -67,10 +67,19 @@ const USER_TYPE = {
// Determine the type of user
// Student is in OU=Students,OU=Users,DC=ad,DC=satitm,DC=chula,DC=ac,DC=th
// Parent is in OU=Parents,OU=Users,DC=ad,DC=satitm,DC=chula,DC=ac,DC=th
-function getUserType(req, res) {
+function getUserType(req) {
// The user's DN is present in the session as req.user.dn
+ if (req.user) {
+ return getUserTypeFromDN(req.user.dn);
+ }
+ else {
+ return USER_TYPE.UNKNOWN;
+ }
+}
+
+function getUserTypeFromDN(dn) {
// To convert DN to OU, remove from first CN= to first ,
- let ou = req.user.dn.substring(req.user.dn.indexOf(',') + 1);
+ let ou = dn.substring(dn.indexOf(',') + 1);
console.log('OU:', ou);
if (ou === 'OU=Students,DC=ad,DC=satitm,DC=chula,DC=ac,DC=th') {
return USER_TYPE.STUDENT;
@@ -96,9 +105,38 @@ async function getPrimaryParent(student_upn) {
}
}
+async function listStudents(upn) {
+ // Search for students with the parent's UPN in their primaryParent attribute
+ let opts = {
+ filter: `(primaryParent=${upn})`,
+ scope: 'sub',
+ attributes: ['userPrincipalName']
+ };
+ let students = [];
+ return new Promise((resolve, reject) => {
+ satitm_directory.search('DC=ad,DC=satitm,DC=chula,DC=ac,DC=th', opts, function(err, ldapRes) {
+ ldapRes.on('searchEntry', function(entry) {
+ console.log('entry: ' + JSON.stringify(entry.object));
+ students.push(entry.object.userPrincipalName);
+ });
+ ldapRes.on('error', function(err) {
+ console.error('error: ' + err.message);
+ reject(err);
+ });
+ ldapRes.on('end', function(result) {
+ console.log('status: ' + result.status);
+ resolve(students);
+ });
+ });
+ });
+}
+
module.exports = {
queryUser: queryUser,
getUserType: getUserType,
+ getUserTypeFromDN: getUserTypeFromDN,
setPrimaryParent: setPrimaryParent,
+ listStudents: listStudents,
+ getPrimaryParent: getPrimaryParent,
USER_TYPE: USER_TYPE
};
\ No newline at end of file
diff --git a/index.js b/index.js
index 42d16c9..9e82223 100644
--- a/index.js
+++ b/index.js
@@ -20,6 +20,14 @@ app.use(passport.session());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
+app.get('/selfservice/api/whoami', function (req, res) {
+ if (!req.isAuthenticated()) {
+ return res.status(401).send('Unauthorized');
+ }
+ // Send user type and upn in json format
+ res.send({ userType: req.user.userType, upn: req.user.username });
+});
+
let authRoutes = require('./routes/auth.js');
app.use('/', authRoutes);
let psRelationStudentRoutes = require('./routes/ps_relation_student.js');
@@ -27,6 +35,9 @@ app.use('/selfservice/api', psRelationStudentRoutes);
let psRelationParentRoutes = require('./routes/ps_relation_parent.js');
app.use('/selfservice/api', psRelationParentRoutes);
+// Serve Static Files
+app.use("/",express.static('statics'));
+
let server = https.createServer(http_config.options, app);
server.listen(3000, function () {
console.log('Listening on port 3000');
diff --git a/routes/auth.js b/routes/auth.js
index 9af0756..24ba195 100644
--- a/routes/auth.js
+++ b/routes/auth.js
@@ -14,6 +14,14 @@ router.get('/selfservice/api', function (req, res) {
response += 'Username: ' + req.user.username + '
';
response += 'First Name: ' + req.user.first_name + '
';
response += 'Last Name: ' + req.user.last_name + '
';
+ usertype_map = ['Unknown', 'Student', 'Parent'];
+ response += 'User Type: ' + usertype_map[req.user.userType] + '
';
+ if (req.user.userType === directory.USER_TYPE.STUDENT) {
+ response += 'Primary Parent: ' + req.user.primaryParent + '
';
+ }
+ else if (req.user.userType === directory.USER_TYPE.PARENT) {
+ response += 'Students: ' + req.user.students + '
';
+ }
response += 'Logout';
res.send(response);
}
@@ -25,7 +33,7 @@ router.get('/selfservice/api', function (req, res) {
router.get('/selfservice/api/logout', function (req, res) {
req.logout();
- res.redirect('/selfservice/api');
+ res.redirect('/selfservice');
});
router.get('/selfservice/api/login',
@@ -42,7 +50,7 @@ router.get('/selfservice/api', function (req, res) {
});
router.post('/selfservice/api/login/postResponse',
- passport.authenticate('saml', { failureRedirect: '/selfservice/api',successRedirect: '/selfservice/api', failureFlash: true }),
+ passport.authenticate('saml', { failureRedirect: '/selfservice',successRedirect: '/selfservice', failureFlash: true }),
function (req, res) {
console.log('SAML authentication successful');
res.redirect('/selfservice');
diff --git a/routes/ps_relation_parent.js b/routes/ps_relation_parent.js
index 940a3e0..c2d377f 100644
--- a/routes/ps_relation_parent.js
+++ b/routes/ps_relation_parent.js
@@ -39,6 +39,18 @@ router.get('/parent/:parent_upn/add-student', async function (req, res) {
if(!req.isAuthenticated()) {
return res.status(401).send('Unauthorized');
}
+ if (!req.query.pairing_code) {
+ return res.status(400).send('Pairing code not provided');
+ }
+ if (!req.params.parent_upn) {
+ return res.status(400).send('Parent UPN not provided');
+ }
+ if (req.user.username !== req.params.parent_upn) {
+ return res.status(403).send('Forbidden, UPN mismatch');
+ }
+ if (req.user.userType !== directory.USER_TYPE.PARENT) {
+ return res.status(403).send('Forbidden, not a parent');
+ }
let parent_upn = req.params.parent_upn;
// Is the logged in user a parent with the same UPN as the one in the URL?
// If not, return a 403 Forbidden response
@@ -63,10 +75,16 @@ router.get('/parent/:parent_upn/add-student', async function (req, res) {
res.send('Student added');
});
-router.get('/parent/:parent_upn', function (req, res) {
+router.get('/parent/:parent_upn', async function (req, res) {
if(!req.isAuthenticated()) {
return res.status(401).send('Unauthorized');
}
+ if (req.user.username !== req.params.parent_upn) {
+ return res.status(403).send('Forbidden, UPN mismatch');
+ }
+ if (req.user.userType !== directory.USER_TYPE.PARENT) {
+ return res.status(403).send('Forbidden, not a parent');
+ }
let parent_upn = req.params.parent_upn;
// Is the logged in user a parent with the same UPN as the one in the URL?
// If not, return a 403 Forbidden response
diff --git a/routes/ps_relation_student.js b/routes/ps_relation_student.js
index b83704e..22ed922 100644
--- a/routes/ps_relation_student.js
+++ b/routes/ps_relation_student.js
@@ -3,6 +3,7 @@
let express = require('express');
let router = express.Router();
let passport = require('passport');
+let directory = require('../directory.js');
let database = require('../config/database.js');
let uuid = require('uuid');
@@ -24,6 +25,9 @@ router.get('/student/:upn/pairing-code', function (req, res) {
if(!req.isAuthenticated()) {
return res.status(401).send('Unauthorized');
}
+ if (req.user.userType !== directory.USER_TYPE.STUDENT) {
+ return res.status(403).send('Forbidden, not a student');
+ }
let upn = req.params.upn;
// Is the logged in user a student with the same UPN as the one in the URL?
// If not, return a 403 Forbidden response
@@ -45,6 +49,9 @@ router.get('/student/:upn', function (req, res) {
if(!req.isAuthenticated()) {
return res.status(401).send('Unauthorized');
}
+ if (req.user.userType !== directory.USER_TYPE.STUDENT) {
+ return res.status(403).send('Forbidden, not a student');
+ }
let upn = req.params.upn;
// Is the logged in user a student with the same UPN as the one in the URL?
// If not, return a 403 Forbidden response
diff --git a/statics/selfservice/index.html b/statics/selfservice/index.html
new file mode 100644
index 0000000..644a792
--- /dev/null
+++ b/statics/selfservice/index.html
@@ -0,0 +1,71 @@
+
+
+