aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/index.ts16
-rw-r--r--src/public/js/form.js9
-rw-r--r--src/routes/api.ts (renamed from src/routes/pendulum.ts)8
-rw-r--r--src/routes/middleware/saml.ts13
4 files changed, 35 insertions, 11 deletions
diff --git a/src/index.ts b/src/index.ts
index 117f0f1..c4b346a 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -5,7 +5,12 @@ import rateLimit from 'express-rate-limit';
import helmet from 'helmet';
import path from 'path';
import { env } from 'process';
-import api from './routes/pendulum';
+import api from './routes/api.js';
+import saml from './routes/middleware/saml.js';
+import { dirname } from 'path';
+import { fileURLToPath } from 'url';
+
+const __dirname = dirname(fileURLToPath(import.meta.url));
const app = express();
@@ -21,7 +26,7 @@ const csrf = csurf({ cookie: true });
// Rate limiting
const rateLimiter = rateLimit({
windowMs: 1 * 60 * 1000, // 1 minute
- max: 40, // Limit each IP to 40 requests per `window` (here, per 1 minutes)
+ max: 40, // Limit each IP to 40 requests per `window` (here, per 1 minute)
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
});
@@ -33,7 +38,7 @@ app.use('/api/v1/', api);
/* RENDERING */
app.set('view engine', 'ejs'); // Add ejs as view engine
-app.set('views', path.join(__dirname, 'views/pages')); // Set views directory (where the ejs lies)
+app.set('views', path.join(__dirname, 'views/pages')); // Set views directory (where the ejs is)
app.use('/public', express.static(path.join(__dirname, 'public'))); // Set static directory (where the static CSS/JS/images lie)
/* ROUTING */
@@ -41,9 +46,12 @@ app.use('/public', express.static(path.join(__dirname, 'public'))); // Set stati
app.get('/', csrf, (req: Request, res: Response) => {
res.render('index', { csrfToken: req.csrfToken() });
});
-app.get('/about', csrf, (req: Request, res: Response) => {
+app.get('/about', csrf, saml, (req: Request, res: Response) => {
res.render('about');
});
+app.all('/login', csrf, (req: Request, res: Response) => {
+ res.redirect('/api/v1/login');
+});
// Start the server
const port = env.PORT || 2000;
diff --git a/src/public/js/form.js b/src/public/js/form.js
index 1e9eaca..9823dcf 100644
--- a/src/public/js/form.js
+++ b/src/public/js/form.js
@@ -15,7 +15,7 @@ document.getElementById('upload').onsubmit = function () {
document.getElementById('download-link').innerText = '';
// Make AJAX request
let xhr = new XMLHttpRequest();
- xhr.open('POST', '/api/v1/upload');
+ xhr.open('POST', '/api/v1/pendulum/upload');
let formData = new FormData(this);
xhr.send(formData);
xhr.onreadystatechange = function () {
@@ -43,7 +43,7 @@ document.getElementById('upload').onsubmit = function () {
//
function actuate(file) {
let xhr = new XMLHttpRequest();
- xhr.open('POST', '/api/v1/actuate');
+ xhr.open('POST', '/api/v1/pendulum/actuate');
let data = {
file: file.file,
};
@@ -72,7 +72,10 @@ function createDownload(response) {
const tempName = response.filename;
const downloadName = response.name.split('.')[0];
const downloadLink = document.createElement('a');
- downloadLink.setAttribute('href', `/api/v1/download/?filename=${tempName}`);
+ downloadLink.setAttribute(
+ 'href',
+ `/api/v1/pendulum/download/?filename=${tempName}`
+ );
downloadLink.setAttribute('download', `${downloadName}.csv`);
downloadLink.innerText = 'Download CSV of results here.';
document.getElementById('download-link').appendChild(downloadLink);
diff --git a/src/routes/pendulum.ts b/src/routes/api.ts
index 66ad594..6cb804c 100644
--- a/src/routes/pendulum.ts
+++ b/src/routes/api.ts
@@ -222,13 +222,13 @@ api
/**
* Verify that the file exists and is a regular file so it can be sent to the user
- * @param file The path to the file
- * @param res The Express response object, used if the file is not accessible
- * @returns `true` if the file exists and is a regular file,`false` otherwise
+ * @param {string} file The path to the file
+ * @param {Response} res The Express response object, used if the file is not accessible
+ * @returns {Promise<boolean>} `true` if the file exists and is a regular file,`false` otherwise
*
* `AFTER THIS POINT, THE API HAS ALREADY SENT A RESPONSE, SO THE FUNCTION THAT CALLED IT SHOULD NOT RETURN ANOTHER RESPONSE `
*/
-async function verifyFile(file: string, res: Response) {
+async function verifyFile(file: string, res: Response): Promise<boolean> {
// Make sure the file being requested to run exists
try {
await access(file);
diff --git a/src/routes/middleware/saml.ts b/src/routes/middleware/saml.ts
new file mode 100644
index 0000000..ad9d50d
--- /dev/null
+++ b/src/routes/middleware/saml.ts
@@ -0,0 +1,13 @@
+import BasicAuthenticator from 'umn-shib-nodejs';
+import { Request, Response, NextFunction } from 'express';
+
+const saml = function (req: Request, res: Response, next: NextFunction): void {
+ const authenticator = new BasicAuthenticator(req, res);
+ if (!authenticator.hasSession()) {
+ authenticator.redirectToLogin();
+ next();
+ }
+ next();
+};
+
+export default saml;