A simple cyber security tool that enables IT admins to test their users' suseptibility to phishing attacks.
- If not installed already, install NodeJS.
https://nodejs.org/en/download/package-manager/current - Git clone the project onto your local machine.
https://github.com/RyanEskridge/SmellsPhishy.git - Open it in VSCode or the editor of your choice.
- Run
npm installfrom the project directory to install the project's dependencies. - To start the app run
node app.js. Alternatively,nodemonif it is installed. - Open a browser and navigate to
localhost:8080and the site should be running locally.
Note: Files with sample data can be found in the presentation folder.
- Node.js - Runtime environment
- Express.js - Minimal JS app framework
- Handlebars.js - JS templating language
- Mailgun.js - Mail API
- Clerk.js - Authentication
- Cloudflare - DNS
Cloudflare: You'll need to add your IP address to the whitelist. You can find it here: Security > WAF > Custom Rules > IP Whitelist > Add your IP to the value box
Clerk: All pages are authenticated other than those in the public folder namely the login and signup pages.
A route defines a path within the application. This path correlates with a specific URL pattern.
Simple routes that don't have children or require additional logic are located in app.js.
Routes which have children or require greater functionality are initialized in app.js and further defined in routes/{specificRoute}.js
// File: app.js
/* Routers for crucial parts of the app
that have children or require additional logic. */
const campaignsRouter = require('./routes/campaigns');
const templatesRouter = require('./routes/templates')
const usersRouter = require('./routes/users');
const clickRouter = require('./routes/click');
// Set base routes
app.use('/campaigns', campaignsRouter);
app.use('/templates', templatesRouter);
app.use('/users', usersRouter);
app.use('/click', clickRouter);
...
// Simple route example
app.get('/settings', (req, res) => {
res.render('settings', {
title: 'Settings',
description: 'Adjust your settings here.',
});
});Now, lets look further into one of the more involved routes.
// File: app.js
// The template router is initialized in app.js
const templatesRouter = require('./routes/templates')
app.use('/templates', templatesRouter);
---
// File: routes/templates.js
/* And individual routes are further defined
in routes/templates.js */
router.get('/new', (req, res) => {
res.render('templates_new', {
title: 'Create New Template',
description: 'Create a new template here.',
});
});Note: You can see that /templates is implied and not included, because it is within the templates router.
Layouts are a base template for pages.
Layouts include parts of the application that don't change from one page to the next. Navigation menu, footer, etc.
Views extend layouts.
Views are where content changes from page-to-page, usually within the body of the page.
Handlebars.js is the templating language we're using. It uses the .hbs extension.
Most pages within the application will use the base layout layouts/main.hbs
Inside of the layouts/main.hbs file you'll notice the handlebars syntax {{ body }} within the opening and closing body HTML tags.
The contents of {{ body }} will vary depending on which view is defined in our routes.
// File: routes/templates.js
router.get('/new', (req, res) => {
res.render('templates_new', {
title: 'Create New Template',
description: 'Create a new template here.',
});
});The contents of {{ body }} in this case are what is contained in our views\templates_new.hbs file.
You can see that title and description are also passed from the server. The first argument given to the res.render() function is the name of our templates_new view, which is served when /templates/new is requested.
// File: views/templates_new.hbs
<h1>{{title}}</h1>
<p>{{description}}</p>In conclusion: The user requests /templates/new. Express.js grabs the main.hbs layout, injects the contents of views/templates_new.hbs into the body, and then serves it to the user.
Utility functions should have a more general use-case. They are functions that can be re-used across the entirety of the app.
Helper functions should have a very narrow use-case. They are functions that are used to complete a specific task.