Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
#!/usr/bin/env node
/**
* Routes File
*/
'use strict'
/* MODULE IMPORTS */
const express = require('express')
const handlebars = require('express-handlebars').create({defaultLayout: 'main'})
const bodyParser = require('body-parser')
const app = express()
app.use(express.static('public'))
const fs = require('fs-extra')
//Necessary for file upload
const multer = require('multer')
//multerConfig: to store files in temporary server storage
const multerConfig = {
//Configure destination for the user's file
storage: multer.diskStorage({
destination: function(req, file, next){
next(null, './uploads');
},
//Give the file a unique name
filename: function(req, file, next){
const ext = file.mimetype.split('/')[1];
next(null, file.fieldname + '-' + Date.now() + '.'+ext);
}
})
}
//IMPORT CUSTOM MODULES
var fileRoute = require('./routes/file-upload');
//Set up body parsing middleware
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json())
//Initialize authentication packages required for passport
var passport = require('passport')
var LocalStrategy = require('passport-local').Strategy;
var flash=require("connect-flash");
//Run functions related to passport
app.use(flash());
app.use(require('serve-static')(__dirname + '/../../public'));
app.use(require('express-session')({
secret: 'keyboard cat',
resave: true,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
//Set up handlebars
app.engine('handlebars', handlebars.engine)
app.set('view engine', 'handlebars')
app.get('/', (req, res) => {
//Render with appropriate message
res.render('login', {message: req.flash('message')});
})
app.post('/', passport.authenticate
//login success: render upload page
//login failure: stay at menu
('local', {
successRedirect: '/upload',
failureRedirect: '/'
}));
const port = 8080
app.get('/upload', (req, res) => {
res.render('upload')
})
app.post('/uploaded', multer(multerConfig).single('file'), function(req, res) {
//Stop the user from uploading without importing a file
var username = req.body.username
if (req.file == undefined){
var message = 'Please choose a file to upload.'
message = {message: message}
res.render('upload', message)
}else{
/*If uploader input username, check if it exists in
the database, if not return the appropriate message*/
const sqlite3 = require('sqlite3').verbose();
let usersdb = new sqlite3.Database('./users.db', (err) => {
if (err){done(err)}
})
usersdb.get('SELECT user FROM Users WHERE user = ?', [username],
function(err, results, done){
if (err) {done(err)}
if (results === undefined && username.length > 0){
//username doesn't exist
var message = 'username does not exist in the database, please input a valid one'
message = {message: message}
res.render('upload', message)
}
if (results !== undefined || username.length === 0){
//username exists or user didn't input an username
//Use request http client to store uploaded file to aws s3 server
var fs = require('fs');
var request = require('request');
const path = require('path')
//Use callback function to read all files stored under uploads directory
const dir = './uploads';
var filename;
function getFiles(path, callback) {
fs.readdir(path, function (err, files) {
if (err) return callback(err)
callback(null, files)
})
}
getFiles(dir, function (err, files){
//Obtain file path and use it to upload the file to aws s3 server through postman api
filename = ((files[files.length - 1]));
const filepath = path.join(dir, filename)
var options = { method: 'POST',
url: 'http://localhost:8080/file-upload',
headers:
{ 'postman-token': '1b098a37-a9a1-a072-65f2-557aa1dd7fef',
'cache-control': 'no-cache',
'content-type': 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' },
formData:
{ file:
{ value: fs.createReadStream(filepath),
options: { filename: filename, contentType: null } } } };
request(options, function (error) {
if (error) throw new Error(error);
});
})
res.render('uploaded')
}
})
usersdb.close()
}
})
app.get('/download', (req, res) => {
const path = require("path")
const dir = './uploads';
function getFiles(path, callback) {
fs.readdir(path, function (err, files) {
if (err) return callback(err)
callback(null, files)
})
}
getFiles(dir, function (err, files) {
/*Extract updated file from the uploads folder and use it for
generating and sending the hash-included download link*/
var filename = ((files[files.length - 1]));
var AWS = require('aws-sdk');
AWS.config.update(
{
secretAccessKey: "086X4701/yjK6DgnBC52PfZqFOv6JIHuvQMBUR83",
accessKeyId: "AKIAIXXAXHIU44MFASTQ",
region: 'eu-west-2'
}
);
//Create an aws s3 object
const s3 = new AWS.S3()
const myBucket = '340ct-project-file-server'
const myKey = filename
const signedUrlExpireSeconds = 60 * 5 //Expiry time in seconds
var url = s3.getSignedUrl('getObject', {
Bucket: myBucket,
Key: myKey,
Expires: signedUrlExpireSeconds
})
//Read contents of uploads directory and clear it
fs.readdir(dir, (err, files) => {
if (err) throw err;
for (const file of files) {
fs.unlink(path.join(dir, file), err => {
if (err) throw err;
});
}
});
/*Use md5 to create hash string from everything after hostname/
in url for e.g. if url = 'http://www.google.com/filename?X-Am...', build hash from
filename?X-Am...'*/
var crypto = require('crypto')
var fileData = url.substring(url.lastIndexOf('/')+1);
console.log("filedata: "+fileData)
var hash = crypto.createHash('md5').update(fileData).digest('hex')
console.log("filedata hash: "+hash)
/*Access Denied error returned from clicking url link generated from
commented code, had to append hash to URL object instead
//Remove everything in url after hostname and replace with '/'+hash
----------------------------------
var newUrl = url.lastIndexOf('/')
url = url.substring(0, newUrl)
console.log("url: "+url+'/'+hash)
---------------------------------
*/
//Create URL object and include hash
const fileUrl = new URL(url)
fileUrl.hash = hash
console.log("fileUrl: "+fileUrl)
//Send fileUrl to the user's email through nodemailer
var nodemailer = require('nodemailer')
var smtpTransport = require('nodemailer-smtp-transport')
//Setup nodemailer transport (gain authentication for gmail)
var smtpTrans = nodemailer.createTransport(smtpTransport({
service: 'gmail',
// host:'smtp.gmail.com',
// port:465,
// secure:true,
auth: {
user: "s3fileshare@gmail.com",
pass: "datastore749"
},
tls: { rejectUnauthorized: false }
}));
//Retrieve user's email address
var userEmail = app.get('email')
//Configure mailing options
var mailOptions = {
from: "s3fileshare@gmail.com", // sender address
to: userEmail,
subject: "FileShare: Download Link For "+myKey,
html: "URL: "+fileUrl+"</br></br>"+"Use the above url to share your file!"// html body
};
//message to be displayed to the user
var message;
//sendMail function called to send the email
smtpTrans.sendMail(mailOptions, function(error){
if(error){
console.log(error);
message = "Error: Unable to send email containing the url for your file!";
}else{
console.log("Message successfully sent!");
message = "An email containing the url for your file has been sent to you!";
}
message = {message: message}
//Close transport
smtpTrans.close();
res.render('uploaded', message)
})
})
})
/**
* The secure home page.
*
* @name Home Page
* @authentication This route requires cookie-based authentication.
*/
app.get('/', (req, res) => {
res.render('login')
})
/**
* The user registration page.
*
* @name Register Page
*/
app.get('/register', (req, res) => {
res.render('register')
})
/**
* The script to process new user registrations.
*
* @name Register Script
*/
app.post('/register', (req, res) => {
//Used to Initialize the database
const sqlite3 = require('sqlite3').verbose();
//Get data from the form
const formData = JSON.stringify(req.body, null, 2)
const jsonObj = JSON.parse(formData)
//Initialize the database
let usersdb = new sqlite3.Database('./users.db', (err) => {
if (err){
return console.error(err.message);
}
console.log('Connected to Users database.');
})
//Insert users registration data into Users table
usersdb.run('INSERT INTO Users(fname, lname, user, pass, email) VALUES(?, ?, ?, ?, ?)',
[jsonObj.fname, jsonObj.lname, jsonObj.user, jsonObj.pass, jsonObj.email], (err) => {
if(err) {
return console.log(err.message);
}
console.log('The Users table has been updated.');
})
//Store the users details in the form of objects
const users_details = {
fname: jsonObj.fname,
lname: jsonObj.lname,
user: jsonObj.user,
pass: jsonObj.pass,
email: jsonObj.email
}
res.render('userdetails', users_details)
})
app.get('/about', (req, res) => {
res.render('about')
})
//Passport api used for validating login information
passport.use(new LocalStrategy({passReqToCallback : true},
function(req, username, password, done) {
const sqlite3 = require('sqlite3').verbose();
const usersdb = new sqlite3.Database('./users.db');
//Retrieve the user's password and email if username exists in the database
usersdb.get('SELECT pass, email FROM Users WHERE user = ?', [username],
function(err, results){
if (err) {done(err)};
if (results != undefined){
//Length of returned object is 0 therefore return to menu page
if (results.length === 0){
done(null, false)
}
/*Username exists in the database, so compare password input by the user
to password stored in the database that corresponds to the username, if
they match log the user in.*/
if (results.pass === password){
//log the user in and store the email
app.set('email', results.email)
return done(null, {username});
}else{
//Incorrect password therefore return to menu page
return done(null, false, req.flash('message', 'Invalid Password!'));
}
//Username doesn't exist in the database therefore return to menu page
}else{
done(null, false, req.flash('message', 'Invalid Username!'))
}
})
}
));
//Use file-upload.js
app.use(fileRoute)
module.exports = app.listen(port, 'localhost', async() => {
//Make sure we have a database with the correct schema
const sqlite3 = require('sqlite3').verbose();
let usersdb = new sqlite3.Database('./users.db', (err) => {
if (err){
return console.error(err.message);
}
console.log('Connected to Users database.');
})
usersdb.run('CREATE TABLE IF NOT EXISTS Users (fname TEXT, lname TEXT, user TEXT, pass TEXT, email TEXT);')
//Close database
usersdb.close()
console.log(`listening on port ${port}`)
})