Permalink
Cannot retrieve contributors at this time
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?
File-Sharing-Website/index.js
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
397 lines (340 sloc)
10.9 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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}`) | |
}) |