pre async
This commit is contained in:
parent
f7824d67e5
commit
512a69319c
13 changed files with 633 additions and 362 deletions
23
config/database.js
Normal file
23
config/database.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
const mysql = require('mysql2');
|
||||
|
||||
// Create a connection pool
|
||||
const database = mysql.createPool({
|
||||
host: '192.168.0.236',
|
||||
user: 'cudnodejs',
|
||||
password: 'iDvuHQsPXF5AasESydypgu',
|
||||
database: 'cudnodejs',
|
||||
connectionLimit: 10
|
||||
});
|
||||
|
||||
database.getConnection((err, connection) => {
|
||||
if(err) {
|
||||
console.error('Error connecting to the database:', err);
|
||||
} else {
|
||||
console.log('Connected to the database');
|
||||
connection.release();
|
||||
}
|
||||
});
|
||||
|
||||
// Export the connection pool
|
||||
module.exports = database;
|
||||
32
config/http.js
Normal file
32
config/http.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
let fs = require('fs');
|
||||
|
||||
const options = {
|
||||
key: fs.readFileSync('adfs_connect/urn_satitm_sso_selfservice.key'),
|
||||
cert: fs.readFileSync('adfs_connect/urn_satitm_sso_selfservice.cert'),
|
||||
ciphers: [
|
||||
'ECDHE-RSA-AES128-GCM-SHA256',
|
||||
'ECDHE-ECDSA-AES128-GCM-SHA256',
|
||||
'ECDHE-RSA-AES256-GCM-SHA384',
|
||||
'ECDHE-ECDSA-AES256-GCM-SHA384',
|
||||
'DHE-RSA-AES128-GCM-SHA256',
|
||||
'ECDHE-RSA-AES128-SHA256',
|
||||
'DHE-RSA-AES128-SHA256',
|
||||
'ECDHE-RSA-AES256-SHA384',
|
||||
'DHE-RSA-AES256-SHA384',
|
||||
'ECDHE-RSA-AES256-SHA256',
|
||||
'DHE-RSA-AES256-SHA256',
|
||||
'HIGH',
|
||||
'!aNULL',
|
||||
'!eNULL',
|
||||
'!EXPORT',
|
||||
'!DES',
|
||||
'!RC4',
|
||||
'!MD5',
|
||||
'!PSK',
|
||||
'!SRP',
|
||||
'!CAMELLIA'
|
||||
].join(':'),
|
||||
honorCipherOrder: true
|
||||
};
|
||||
|
||||
module.exports.options = options;
|
||||
32
config/ldap.js
Normal file
32
config/ldap.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
let ldap = require('ldapjs');
|
||||
let fs = require('fs');
|
||||
let tls = require('tls');
|
||||
|
||||
let satitm_directory = ldap.createClient({
|
||||
url: 'ldaps://ad.satitm.chula.ac.th:636',
|
||||
tlsOptions: {
|
||||
rejectUnauthorized: false
|
||||
}
|
||||
});
|
||||
|
||||
// Save server's certificate to file for same-host verification
|
||||
satitm_directory.on('connect', function(socket) {
|
||||
socket.on('secureConnect', function() {
|
||||
if (socket.getPeerCertificate().raw) {
|
||||
fs.writeFileSync('certificate.pem', socket.getPeerCertificate().raw);
|
||||
satitm_directory.tlsOptions = {
|
||||
ca: [fs.readFileSync('certificate.pem')]
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
satitm_directory.bind('CN=SSOManager,OU=Service Accounts,DC=ad,DC=satitm,DC=chula,DC=ac,DC=th', '39BK5LCeU2NY2oG3beeBJH', function (err) {
|
||||
if (err) {
|
||||
console.log('Error:', err);
|
||||
} else {
|
||||
console.log('Connected to SATITM Active Directory');
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = satitm_directory;
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
let fs = require("fs"),
|
||||
passport = require("passport"),
|
||||
SamlStrategy = require("passport-saml").Strategy;
|
||||
let fs = require("fs");
|
||||
let passport = require("passport");
|
||||
let SamlStrategy = require("passport-saml").Strategy;
|
||||
let directory = require("../directory.js");
|
||||
|
||||
passport.serializeUser(function (user, done) {
|
||||
done(null, user);
|
||||
});
|
||||
|
|
@ -13,7 +15,7 @@ passport.use(
|
|||
{
|
||||
entryPoint: "https://sso.satitm.chula.ac.th/adfs/ls",
|
||||
issuer: "https://localhost:3000",
|
||||
callbackUrl: "https://localhost:3000/selfservice/activedirectory/postResponse",
|
||||
callbackUrl: "https://localhost:3000/selfservice/api/login/postResponse",
|
||||
privateKey: fs.readFileSync("adfs_connect/urn_satitm_sso_selfservice.key", "utf-8"),
|
||||
acceptedClockSkewMs: -1,
|
||||
identifierFormat: null,
|
||||
|
|
@ -21,13 +23,20 @@ passport.use(
|
|||
racComparison: "exact",
|
||||
},
|
||||
function (profile, done) {
|
||||
console.log("profile", profile);
|
||||
let user = profile["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"];
|
||||
return done(null, {
|
||||
username: profile["username"],
|
||||
first_name: profile["first_name"],
|
||||
last_name: profile["last_name"],
|
||||
org_unit: profile["org_unit"],
|
||||
// Query Active Directory for user details
|
||||
// username is the UPN
|
||||
// Store the user's group and DN in the session
|
||||
let username = profile["username"];
|
||||
attributes = ["dn", "memberOf"];
|
||||
directory.queryUser(username, attributes, function (err, user) {
|
||||
if (err) {
|
||||
console.log("Error:", err);
|
||||
} else {
|
||||
console.log("User:", user);
|
||||
profile["dn"] = user.dn;
|
||||
profile["memberOf"] = user.memberOf;
|
||||
return done(null, profile);
|
||||
}
|
||||
});
|
||||
}
|
||||
)
|
||||
|
|
|
|||
77
directory.js
Normal file
77
directory.js
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
let satitm_directory = require('./config/ldap.js');
|
||||
// Search for a user in the directory
|
||||
async function queryUser(upn, attributes) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let opts = {
|
||||
filter: `(userPrincipalName=${upn})`,
|
||||
scope: 'sub',
|
||||
attributes: attributes
|
||||
};
|
||||
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));
|
||||
resolve(entry.object);
|
||||
});
|
||||
ldapRes.on('error', function(err) {
|
||||
console.error('error: ' + err.message);
|
||||
reject(err);
|
||||
});
|
||||
ldapRes.on('end', function(result) {
|
||||
console.log('status: ' + result.status);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setAttribute(upn, attribute, value, callback) {
|
||||
// First, get DN of the user from the UPN
|
||||
let attributes = ['dn'];
|
||||
|
||||
}
|
||||
|
||||
// 0: Unkown, 1: Student, 2: Parent
|
||||
const USER_TYPE = {
|
||||
UNKNOWN: 0,
|
||||
STUDENT: 1,
|
||||
PARENT: 2
|
||||
};
|
||||
|
||||
// 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) {
|
||||
// The user's DN is present in the session as req.user.dn
|
||||
// To convert DN to OU, remove from first CN= to first ,
|
||||
let ou = req.user.dn.substring(req.user.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;
|
||||
}
|
||||
else if (ou === 'OU=Parents,DC=ad,DC=satitm,DC=chula,DC=ac,DC=th') {
|
||||
return USER_TYPE.PARENT;
|
||||
}
|
||||
else {
|
||||
return USER_TYPE.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
async function getPrimaryParent(student_upn, callback) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Query primaryParent attribute in the student's LDAP entry
|
||||
let attributes = ['primaryParent'];
|
||||
queryUser(student_upn, attributes, function(err, student) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
let primaryParent = student.primaryParent;
|
||||
resolve(primaryParent);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
queryUser: queryUser,
|
||||
getUserType: getUserType,
|
||||
USER_TYPE: USER_TYPE
|
||||
};
|
||||
129
index.js
129
index.js
|
|
@ -2,26 +2,13 @@ let passport = require('passport');
|
|||
let express = require('express');
|
||||
let https = require('https');
|
||||
let fs = require('fs');
|
||||
let ldap = require('ldapjs');
|
||||
|
||||
let directory = require('./directory.js');
|
||||
let http_config = require('./config/http.js');
|
||||
let app = express();
|
||||
require('./config/passport.js');
|
||||
let session = require('express-session');
|
||||
const { group } = require('console');
|
||||
|
||||
let satitm_directory = ldap.createClient({
|
||||
url: 'ldap://ad.satitm.chula.ac.th:389'
|
||||
});
|
||||
|
||||
satitm_directory.bind('CN=SSOManager,OU=Service Accounts,DC=ad,DC=satitm,DC=chula,DC=ac,DC=th', '39BK5LCeU2NY2oG3beeBJH', function (err) {
|
||||
if (err) {
|
||||
console.log('Error:', err);
|
||||
}
|
||||
else {
|
||||
console.log('Connected to SATITM Active Directory');
|
||||
}
|
||||
});
|
||||
|
||||
app.use(session({
|
||||
secret: 'RLCCDwstDuT6nMJf5kko7C',
|
||||
resave: false,
|
||||
|
|
@ -30,115 +17,17 @@ app.use(session({
|
|||
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.session());
|
||||
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
|
||||
app.get('/', function (req, res) {
|
||||
response = 'Hello World!<br>';
|
||||
console.log('User:', req.user);
|
||||
if (req.user) {
|
||||
// Query Active Directory for user details
|
||||
// username is the UPN
|
||||
let username = req.user.username;
|
||||
let opts = {
|
||||
filter: `(userPrincipalName=${username})`,// replace 'username' with the actual username
|
||||
scope: 'sub',
|
||||
attributes: ['dn', 'memberOf']
|
||||
};
|
||||
let groups = '';
|
||||
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));
|
||||
groups = entry.object.memberOf;
|
||||
});
|
||||
ldapRes.on('error', function(err) {
|
||||
console.error('error: ' + err.message);
|
||||
});
|
||||
ldapRes.on('end', function(result) {
|
||||
console.log('status: ' + result.status);
|
||||
console.log('User:', req.user);
|
||||
response += 'Username: ' + req.user.username + '<br>';
|
||||
response += 'First Name: ' + req.user.first_name + '<br>';
|
||||
response += 'Last Name: ' + req.user.last_name + '<br>';
|
||||
response += 'Group: ' + groups + '<br>';
|
||||
response += '<a href="/logout">Logout</a>';
|
||||
res.send(response);
|
||||
});
|
||||
});
|
||||
let authRoutes = require('./routes/auth.js');
|
||||
app.use('/', authRoutes);
|
||||
let psRelationStudentRoutes = require('./routes/ps_relation_student.js');
|
||||
app.use('/selfservice/api', psRelationStudentRoutes);
|
||||
let psRelationParentRoutes = require('./routes/ps_relation_parent.js');
|
||||
app.use('/selfservice/api', psRelationParentRoutes);
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
response += '<a href="/login">Login</a>';
|
||||
res.send(response);
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/logout', function (req, res) {
|
||||
req.logout();
|
||||
res.redirect('/');
|
||||
});
|
||||
|
||||
app.get('/login',
|
||||
passport.authenticate('saml', { failureRedirect: '/selfservice', failureFlash: true }),
|
||||
function (req, res) {
|
||||
res.redirect('https://localhost:3000/');
|
||||
}
|
||||
);
|
||||
|
||||
app.use(function(req, res, next) {
|
||||
console.log('Received request:', req.method, req.url);
|
||||
console.log('Data:', req.body);
|
||||
next();
|
||||
});
|
||||
|
||||
app.post('/selfservice/activedirectory/postResponse',
|
||||
passport.authenticate('saml', { failureRedirect: '/selfservice',successRedirect: '/', failureFlash: true }),
|
||||
function (req, res) {
|
||||
console.log('SAML authentication successful');
|
||||
res.redirect('https://localhost:3000/');
|
||||
}
|
||||
);
|
||||
//app.get('selfservice/secure', validUser, routes.secure);
|
||||
|
||||
function validUser(req, res, next) {
|
||||
if (!req.user) {
|
||||
res.redirect('https://localhost:3000/login');
|
||||
}
|
||||
next();
|
||||
}
|
||||
|
||||
const options = {
|
||||
key: fs.readFileSync('adfs_connect/urn_satitm_sso_selfservice.key'),
|
||||
cert: fs.readFileSync('adfs_connect/urn_satitm_sso_selfservice.cert'),
|
||||
ciphers: [
|
||||
'ECDHE-RSA-AES128-GCM-SHA256',
|
||||
'ECDHE-ECDSA-AES128-GCM-SHA256',
|
||||
'ECDHE-RSA-AES256-GCM-SHA384',
|
||||
'ECDHE-ECDSA-AES256-GCM-SHA384',
|
||||
'DHE-RSA-AES128-GCM-SHA256',
|
||||
'ECDHE-RSA-AES128-SHA256',
|
||||
'DHE-RSA-AES128-SHA256',
|
||||
'ECDHE-RSA-AES256-SHA384',
|
||||
'DHE-RSA-AES256-SHA384',
|
||||
'ECDHE-RSA-AES256-SHA256',
|
||||
'DHE-RSA-AES256-SHA256',
|
||||
'HIGH',
|
||||
'!aNULL',
|
||||
'!eNULL',
|
||||
'!EXPORT',
|
||||
'!DES',
|
||||
'!RC4',
|
||||
'!MD5',
|
||||
'!PSK',
|
||||
'!SRP',
|
||||
'!CAMELLIA'
|
||||
].join(':'),
|
||||
honorCipherOrder: true
|
||||
};
|
||||
|
||||
let server = https.createServer(options, app);
|
||||
let server = https.createServer(http_config.options, app);
|
||||
server.listen(3000, function () {
|
||||
console.log('Listening on port 3000');
|
||||
});
|
||||
228
login.html
228
login.html
|
|
@ -1,228 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=8; IE=EDGE">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style type="text/css">
|
||||
body {
|
||||
height: 100%;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
color: #6a6a6a;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: url(https://sso.satitm.chula.ac.th/img/bg_landscape.png) no-repeat;
|
||||
background-size: cover;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
|
||||
}
|
||||
|
||||
input[type=date],
|
||||
input[type=email],
|
||||
input[type=number],
|
||||
input[type=password],
|
||||
input[type=search],
|
||||
input[type=tel],
|
||||
input[type=text],
|
||||
input[type=time],
|
||||
input[type=url],
|
||||
select,
|
||||
textarea {
|
||||
color: #262626;
|
||||
vertical-align: baseline;
|
||||
margin: .2em;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: #a9a9a9;
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
padding: 2px .5em;
|
||||
appearance: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
border-color: #646464;
|
||||
box-shadow: 0 0 1px 0 #a2a2a2;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: .5em 1em;
|
||||
border: 1px solid;
|
||||
border-radius: 3px;
|
||||
min-width: 6em;
|
||||
font-weight: 400;
|
||||
font-size: .8em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button.primary {
|
||||
color: #fff;
|
||||
background-color: rgb(47, 113, 178);
|
||||
border-color: rgb(34, 103, 173);
|
||||
}
|
||||
|
||||
.form-body {
|
||||
display: flex;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.message-container {
|
||||
height: 1280px;
|
||||
width: 1280px;
|
||||
padding: 0;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 800px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
table {
|
||||
background-color: #fff;
|
||||
border-spacing: 0;
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
table>tbody>tr>td:first-of-type:not([colspan]) {
|
||||
white-space: nowrap;
|
||||
color: rgba(0, 0, 0, .5);
|
||||
}
|
||||
|
||||
table>tbody>tr>td:first-of-type {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table>tbody>tr>td {
|
||||
padding: .3em .3em;
|
||||
}
|
||||
|
||||
.field {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
.field> :first-child {
|
||||
display: table-cell;
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.field.single> :first-child {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.field> :not(:first-child) {
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
virtical-align: top;
|
||||
box-sizing: border-box;
|
||||
margin: .3em;
|
||||
}
|
||||
|
||||
.field> :not(:first-child)>input {
|
||||
width: 230px;
|
||||
}
|
||||
|
||||
.form-footer {
|
||||
display: inline-flex;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.form-footer>* {
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
.text-scrollable {
|
||||
overflow: auto;
|
||||
height: 150px;
|
||||
border: 1px solid rgb(200, 200, 200);
|
||||
padding: 5px;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.text-centered {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.text-container {
|
||||
margin: 1em 1.5em;
|
||||
}
|
||||
|
||||
.flex-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.flex-container.column {
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
<title>
|
||||
Firewall Authentication
|
||||
</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="message-container">
|
||||
<div class="logo">
|
||||
<div class="container">
|
||||
<div class="form-body">
|
||||
<div class="form-container">
|
||||
<h1 style="text-align: center; margin-top: 0;">
|
||||
SATITM SSO
|
||||
</h1>
|
||||
<form action="%%AUTH_POST_URL%%" method="post">
|
||||
<input type="hidden" name="%%REDIRID%%" value="%%PROTURI%%">
|
||||
<input type="hidden" name="%%MAGICID%%" value="%%MAGICVAL%%">
|
||||
<input type="hidden" name="%%METHODID%%" value="%%METHODVAL%%">
|
||||
<p>
|
||||
%%QUESTION%%
|
||||
</p>
|
||||
<div class="field">
|
||||
<label for="ft_un">
|
||||
Email
|
||||
</label>
|
||||
<div>
|
||||
<input name="%%USERNAMEID%%" id="ft_un" type="text" autocorrect="off" autocapitalize="off">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="ft_pd">
|
||||
Password
|
||||
</label>
|
||||
<div>
|
||||
<input name="%%PASSWORDID%%" id="ft_pd" type="password" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-footer">
|
||||
<button class="primary" type="submit" style="margin-bottom: 0;">
|
||||
Continue
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
107
node_modules/.package-lock.json
generated
vendored
107
node_modules/.package-lock.json
generated
vendored
|
|
@ -171,6 +171,14 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/denque": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
|
||||
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
|
|
@ -346,6 +354,14 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/generate-function": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
|
||||
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
|
||||
"dependencies": {
|
||||
"is-property": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
||||
|
|
@ -458,6 +474,11 @@
|
|||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/is-property": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||
"integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="
|
||||
},
|
||||
"node_modules/ldap-filter": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/ldap-filter/-/ldap-filter-0.3.3.tgz",
|
||||
|
|
@ -487,6 +508,19 @@
|
|||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/long": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
|
||||
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "8.0.5",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz",
|
||||
"integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==",
|
||||
"engines": {
|
||||
"node": ">=16.14"
|
||||
}
|
||||
},
|
||||
"node_modules/media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
|
|
@ -543,6 +577,54 @@
|
|||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"node_modules/mysql2": {
|
||||
"version": "3.9.7",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.9.7.tgz",
|
||||
"integrity": "sha512-KnJT8vYRcNAZv73uf9zpXqNbvBG7DJrs+1nACsjZP1HMJ1TgXEy8wnNilXAn/5i57JizXKtrUtwDB7HxT9DDpw==",
|
||||
"dependencies": {
|
||||
"denque": "^2.1.0",
|
||||
"generate-function": "^2.3.1",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"long": "^5.2.1",
|
||||
"lru-cache": "^8.0.0",
|
||||
"named-placeholders": "^1.1.3",
|
||||
"seq-queue": "^0.0.5",
|
||||
"sqlstring": "^2.3.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mysql2/node_modules/iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/named-placeholders": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz",
|
||||
"integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==",
|
||||
"dependencies": {
|
||||
"lru-cache": "^7.14.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/named-placeholders/node_modules/lru-cache": {
|
||||
"version": "7.18.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
|
||||
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
|
|
@ -792,6 +874,11 @@
|
|||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
},
|
||||
"node_modules/seq-queue": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
||||
"integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
|
||||
},
|
||||
"node_modules/serve-static": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
|
||||
|
|
@ -844,6 +931,14 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/sqlstring": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
|
||||
"integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
|
|
@ -899,6 +994,18 @@
|
|||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
|
|
|
|||
111
package-lock.json
generated
111
package-lock.json
generated
|
|
@ -12,8 +12,10 @@
|
|||
"express": "^4.17.1",
|
||||
"express-session": "^1.17.2",
|
||||
"ldapjs": "^2.2.3",
|
||||
"mysql2": "^3.9.7",
|
||||
"passport": "^0.4.1",
|
||||
"passport-saml": "^2.0.0"
|
||||
"passport-saml": "^2.0.0",
|
||||
"uuid": "^9.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@xmldom/xmldom": {
|
||||
|
|
@ -183,6 +185,14 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/denque": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
|
||||
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
|
|
@ -358,6 +368,14 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/generate-function": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
|
||||
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
|
||||
"dependencies": {
|
||||
"is-property": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
||||
|
|
@ -470,6 +488,11 @@
|
|||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/is-property": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||
"integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="
|
||||
},
|
||||
"node_modules/ldap-filter": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/ldap-filter/-/ldap-filter-0.3.3.tgz",
|
||||
|
|
@ -499,6 +522,19 @@
|
|||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/long": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
|
||||
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "8.0.5",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz",
|
||||
"integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==",
|
||||
"engines": {
|
||||
"node": ">=16.14"
|
||||
}
|
||||
},
|
||||
"node_modules/media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
|
|
@ -555,6 +591,54 @@
|
|||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"node_modules/mysql2": {
|
||||
"version": "3.9.7",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.9.7.tgz",
|
||||
"integrity": "sha512-KnJT8vYRcNAZv73uf9zpXqNbvBG7DJrs+1nACsjZP1HMJ1TgXEy8wnNilXAn/5i57JizXKtrUtwDB7HxT9DDpw==",
|
||||
"dependencies": {
|
||||
"denque": "^2.1.0",
|
||||
"generate-function": "^2.3.1",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"long": "^5.2.1",
|
||||
"lru-cache": "^8.0.0",
|
||||
"named-placeholders": "^1.1.3",
|
||||
"seq-queue": "^0.0.5",
|
||||
"sqlstring": "^2.3.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mysql2/node_modules/iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/named-placeholders": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz",
|
||||
"integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==",
|
||||
"dependencies": {
|
||||
"lru-cache": "^7.14.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/named-placeholders/node_modules/lru-cache": {
|
||||
"version": "7.18.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
|
||||
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
|
|
@ -804,6 +888,11 @@
|
|||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
},
|
||||
"node_modules/seq-queue": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
||||
"integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
|
||||
},
|
||||
"node_modules/serve-static": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
|
||||
|
|
@ -856,6 +945,14 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/sqlstring": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
|
||||
"integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
|
|
@ -911,6 +1008,18 @@
|
|||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
|
|
|
|||
|
|
@ -14,9 +14,11 @@
|
|||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"express": "^4.17.1",
|
||||
"express-session": "^1.17.2",
|
||||
"ldapjs": "^2.2.3",
|
||||
"mysql2": "^3.9.7",
|
||||
"passport": "^0.4.1",
|
||||
"passport-saml": "^2.0.0",
|
||||
"express-session": "^1.17.2",
|
||||
"ldapjs": "^2.2.3"
|
||||
"uuid": "^9.0.1"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
69
routes/auth.js
Normal file
69
routes/auth.js
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
let express = require('express');
|
||||
let router = express.Router();
|
||||
let passport = require('passport');
|
||||
let directory = require('../directory.js');
|
||||
|
||||
router.get('/selfservice/api', function (req, res) {
|
||||
response = 'Hello World!<br>';
|
||||
console.log('User:', req.user);
|
||||
if (req.user) {
|
||||
// Query Active Directory for user details
|
||||
// username is the UPN
|
||||
let username = req.user.username;
|
||||
attributes = ['dn', 'memberOf'];
|
||||
directory.queryUser(username, attributes, function(err, user) {
|
||||
if (err) {
|
||||
console.log('Error:', err);
|
||||
}
|
||||
else {
|
||||
console.log('User:', user);
|
||||
response += 'Username: ' + req.user.username + '<br>';
|
||||
response += 'First Name: ' + req.user.first_name + '<br>';
|
||||
response += 'Last Name: ' + req.user.last_name + '<br>';
|
||||
usertype_str_map = ['Unknown', 'Student', 'Parent'];
|
||||
response += 'User Type: ' + usertype_str_map[directory.getUserType(req, res)] + '<br>';
|
||||
response += '<a href="/selfservice/api/logout">Logout</a>';
|
||||
res.send(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
response += '<a href="/selfservice/api/login">Login</a>';
|
||||
res.send(response);
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/selfservice/api/logout', function (req, res) {
|
||||
req.logout();
|
||||
res.redirect('/selfservice/api');
|
||||
});
|
||||
|
||||
router.get('/selfservice/api/login',
|
||||
passport.authenticate('saml', { failureRedirect: '/selfservice/api', failureFlash: true }),
|
||||
function (req, res) {
|
||||
res.redirect(end);
|
||||
}
|
||||
);
|
||||
|
||||
router.use(function(req, res, next) {
|
||||
console.log('Received request:', req.method, req.url);
|
||||
console.log('Data:', req.body);
|
||||
next();
|
||||
});
|
||||
|
||||
router.post('/selfservice/api/login/postResponse',
|
||||
passport.authenticate('saml', { failureRedirect: '/selfservice/api',successRedirect: '/selfservice/api', failureFlash: true }),
|
||||
function (req, res) {
|
||||
console.log('SAML authentication successful');
|
||||
res.redirect('/selfservice');
|
||||
}
|
||||
);
|
||||
|
||||
function validUser(req, res, next) {
|
||||
if (!req.user) {
|
||||
res.redirect('/api/login');
|
||||
}
|
||||
next();
|
||||
}
|
||||
|
||||
module.exports = router;
|
||||
87
routes/ps_relation_parent.js
Normal file
87
routes/ps_relation_parent.js
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
// This file contains the routes for the the account linking process on the parent side.
|
||||
|
||||
let express = require('express');
|
||||
let router = express.Router();
|
||||
let passport = require('passport');
|
||||
let database = require('../config/database.js');
|
||||
|
||||
// Consume the pairing code
|
||||
// Return the student's UPN then delete the pairing code
|
||||
function consumePairingCode(pairing_code, callback) {
|
||||
let sql = 'SELECT upn FROM ps_pairing_codes WHERE pairing_code = ?';
|
||||
database.query(sql, pairing_code, function (err, result) {
|
||||
if (err) {
|
||||
console.log('Error:', err);
|
||||
return callback(err, null);
|
||||
} else {
|
||||
if (result.length === 0) {
|
||||
return callback(null, null);
|
||||
} else {
|
||||
let upn = result[0].upn;
|
||||
let sql = 'DELETE FROM ps_pairing_codes WHERE pairing_code = ?';
|
||||
database.query(sql, pairing_code, function (err, result) {
|
||||
if (err) {
|
||||
console.log('Error:', err);
|
||||
} else {
|
||||
console.log('Pairing code consumed');
|
||||
}
|
||||
});
|
||||
return callback(null, upn);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
router.get('/parent/:parent_upn/add-student', function (req, res) {
|
||||
if(!req.isAuthenticated()) {
|
||||
return res.status(401).send('Unauthorized');
|
||||
}
|
||||
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
|
||||
if (req.user.username !== parent_upn) {
|
||||
return res.status(403).send('Forbidden, UPN mismatch');
|
||||
}
|
||||
// Consume the pairing code, if it return null, return a 404 Not Found response
|
||||
// Don't update the parent's student list yet
|
||||
// Note that we won't return the student's details in this route
|
||||
// Just a success message
|
||||
let pairing_code = req.query.pairing_code;
|
||||
// Is the pairing code in the query string?
|
||||
if (!pairing_code) {
|
||||
return res.status(400).send('Bad Request, pairing_code missing');
|
||||
}
|
||||
let student_upn = '';
|
||||
consumePairingCode(pairing_code, function (err, upn) {
|
||||
if (err) {
|
||||
return res.status(500).send('Internal Server Error');
|
||||
}
|
||||
if (upn === null) {
|
||||
return res.status(404).send('Invalid pairing code');
|
||||
}
|
||||
student_upn = upn;
|
||||
res.send('Student added');
|
||||
// Set the LDAP attribute parent to the parent's UPN in the student's LDAP entry
|
||||
});
|
||||
});
|
||||
|
||||
router.get('/parent/:parent_upn', function (req, res) {
|
||||
if(!req.isAuthenticated()) {
|
||||
return res.status(401).send('Unauthorized');
|
||||
}
|
||||
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
|
||||
if (req.user.username !== parent_upn) {
|
||||
return res.status(403).send('Forbidden, UPN mismatch');
|
||||
}
|
||||
// Return the parent's details in the session in JSON format
|
||||
allowedAttributes = ['username', 'first_name', 'last_name'];
|
||||
let parent = {};
|
||||
allowedAttributes.forEach(function (attribute) {
|
||||
parent[attribute] = req.user[attribute];
|
||||
});
|
||||
res.json(parent);
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
63
routes/ps_relation_student.js
Normal file
63
routes/ps_relation_student.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
// This file contains the routes for the the account linking process on the student side.
|
||||
|
||||
let express = require('express');
|
||||
let router = express.Router();
|
||||
let passport = require('passport');
|
||||
let database = require('../config/database.js');
|
||||
let uuid = require('uuid');
|
||||
|
||||
function storePairingCode(upn, pairing_code) {
|
||||
// If a student-pairing_code pair already exists, update the pairing code
|
||||
// Else, insert a new student-pairing_code pair
|
||||
let sql = 'INSERT INTO ps_pairing_codes (upn, pairing_code) VALUES (?, ?) ON DUPLICATE KEY UPDATE pairing_code = ?';
|
||||
let values = [upn, pairing_code, pairing_code];
|
||||
database.query(sql, values, function (err, result) {
|
||||
if (err) {
|
||||
console.log('Error:', err);
|
||||
} else {
|
||||
console.log('Pairing code stored');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
router.get('/student/:upn/pairing-code', function (req, res) {
|
||||
if(!req.isAuthenticated()) {
|
||||
return res.status(401).send('Unauthorized');
|
||||
}
|
||||
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
|
||||
if (req.user.username !== upn) {
|
||||
console.log('UPN mismatch');
|
||||
console.log('req.user.upn:', req.user.upn);
|
||||
console.log('upn:', upn);
|
||||
return res.status(403).send('Forbidden, UPN mismatch');
|
||||
}
|
||||
// Generate a uuid (v4) as the pairing code
|
||||
let pairing_code = uuid.v4();
|
||||
// Store the pairing code in the database
|
||||
storePairingCode(upn, pairing_code);
|
||||
// Return the pairing code
|
||||
res.send(pairing_code);
|
||||
});
|
||||
|
||||
router.get('/student/:upn', function (req, res) {
|
||||
if(!req.isAuthenticated()) {
|
||||
return res.status(401).send('Unauthorized');
|
||||
}
|
||||
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
|
||||
if (req.user.username !== upn) {
|
||||
return res.status(403).send('Forbidden, UPN mismatch');
|
||||
}
|
||||
// Return the student's details in the response in JSON format
|
||||
allowedAttributes = ['username', 'first_name', 'last_name'];
|
||||
let student = {};
|
||||
allowedAttributes.forEach(function (attribute) {
|
||||
student[attribute] = req.user[attribute];
|
||||
});
|
||||
res.json(student);
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
Loading…
Add table
Add a link
Reference in a new issue