Skip to content

Commit

Permalink
Merge branch 'antonioBranch'
Browse files Browse the repository at this point in the history
  • Loading branch information
airizarryOSU authored and airizarryOSU committed Aug 1, 2020
2 parents 03dbf93 + 843803c commit 3933de1
Show file tree
Hide file tree
Showing 8 changed files with 290 additions and 3 deletions.
6 changes: 4 additions & 2 deletions EC3_DDL.sql
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`password` varchar(500) DEFAULT NULL
`password` varchar(500) DEFAULT NULL,
`token` varchar(255) DEFAULT NULL,
`tokenExpiration` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `users`
Expand Down Expand Up @@ -77,4 +79,4 @@ INSERT INTO `tasks` (`project_id`, `name`, `assignee_id`, `due_date`, `status`,
(2, 'Create template files.', 2, '2020-07-10', 'To Do', 'Use stagehand.');

INSERT INTO `subtasks` (`project_id`, `task_id`, `name`, `assignee_id`, `due_date`, `status`, `description`) VALUES
(2, 1, 'sample subtask', 1, '2020-07-15', 'To Do', 'sample subtask description');
(2, 1, 'sample subtask', 1, '2020-07-15', 'To Do', 'sample subtask description');
156 changes: 156 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
var express = require('express');
var bodyParser = require('body-parser');
var CryptoJS = require("crypto-js");
var crypto = require("crypto");
var nodemailer = require('nodemailer');
var path = require('path');
var session = require('express-session');

Expand Down Expand Up @@ -83,6 +85,160 @@ app.get('/login', function(req, res, next) {
res.render('login', context);
});

app.get('/forgot', function(req, res, next) {
const context = { email: ''};
res.render('forgot', context);
});


function getToken(res, user, complete) {
crypto.randomBytes(20, function(err, buf) {
var token = buf.toString('hex');
user.resetPasswordToken = token;
complete();
});
}

function checkIfUserExists(email, res, user, complete) {
mysql.pool.query(
"SELECT id from users where email=" + mysql.pool.escape(email),
function(err, result) {
// if error, handle by outputting issue encountered
if (err) {
console.log(JSON.stringify(err));
res.write(JSON.stringify(err));
res.end();
}
// if id exists in the db, user already exists, don't proceed with sign up
else if (!result[0] || !result[0].id) {
console.log("Doesnt exist")
res.render('forgot', {
errors: 'Email address doesn\'t exist.',
});
}
else {
user.email = email;
user.id = result[0].id;
user.resetPasswordExpires = Date.now() + 3600000; // 1 hour
complete();
}
})
}

function updateUserTokens(res, user, complete) {
var sql = "UPDATE users SET token = ?, tokenExpiration = ? WHERE id = ?";
var inserts = [user.resetPasswordToken, user.resetPasswordExpires, user.id];
sql = mysql.pool.query(sql, inserts, function(error, results, fields){
if(error){
res.write(JSON.stringify(error));
res.status(400);
res.end();
}
complete();
})
}

app.post('/pass/reset', function(req, res, next) {
var callbackCount = 0;
var user = {};

getToken(res, user, complete);
function complete(){
callbackCount++;
if(callbackCount == 1){
checkIfUserExists(req.body.user_email, res, user, complete);
} else if (callbackCount == 2) {
updateUserTokens(res, user, complete);
} else if (callbackCount == 3) {

const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: '[email protected]',
pass: 'superlongstringtest123'
}
});

const mailOptions = {
from: '[email protected]',
to: user.email,
subject: 'Password Reset Requested',
text: 'You are receiving this because you (or someone else) have requested the reset of the password for your account.\n\n' +
'Please click on the following link, or paste this into your browser to complete the process:\n\n' +
'http://' + req.headers.host + '/reset/' + user.resetPasswordToken + '\n\n' +
'If you did not request this, please ignore this email and your password will remain unchanged.\n'
};

transporter.sendMail(mailOptions, function(error, info) {
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
res.render('forgot', {
info: 'An e-mail has been sent to ' + user.email + ' with further instructions.',
});
}
}
});


app.get('/reset/:token', function(req, res) {

var sql = "SELECT id, tokenExpiration from users WHERE token = ?";
var inserts = [req.params.token];
sql = mysql.pool.query(sql, inserts, function(error, result, fields){
if(error){
res.write(JSON.stringify(error));
res.status(400);
res.end();
}
else if (!result[0] || !result[0].id) {

res.render('reset', {
errors: 'Password reset token is invalid.',
link: 'http://' + req.headers.host + '/forgot'
});
}
else if (Date.now() > result[0].tokenExpiration) {
res.render('reset', {
errors: 'Password reset token is expired.',
link: 'http://' + req.headers.host + '/forgot'
});
}
else {
var context = {
id: result[0].id,
token: Date.now(),
showForm: true
};
res.render('reset', context)
}
})
});

app.post('/reset-password', function(req, res, next) {

var ciphertext = CryptoJS.AES.encrypt(req.body.password, config.cryptoSecret).toString();

var sql = "UPDATE users SET password = ?, tokenExpiration = ? WHERE id = ?";
var inserts = [ciphertext, req.body.token, req.body.id];

sql = mysql.pool.query(sql, inserts, function(error, result, fields){
if(error){
res.write(JSON.stringify(error));
res.status(400);
res.end();
}

res.render('reset', {
info: 'Password reset successfully.',
link: 'http://' + req.headers.host + '/login'
});
})
});

app.post('/add-new-user', function(req, res) {
mysql.pool.query(
"SELECT id from users where email=" + mysql.pool.escape(req.body.user_email),
Expand Down
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"express-handlebars": "^2.0.1",
"express-session": "^1.17.0",
"jsonwebtoken": "^8.5.1",
"mysql": "^2.8.0"
"mysql": "^2.8.0",
"nodemailer": "^6.4.11"
},
"bugs": {
"url": "https://github.com/sarahforest/cs361/issues"
Expand Down
68 changes: 68 additions & 0 deletions public/css/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,64 @@ body {
margin-bottom: 30px;
}

/* reset page CSS */
#reset-page #danger {
color: red;
}

#reset-page *, #forgot-page * {
box-sizing: border-box;
}

#reset-page, #forgot-page {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}

#reset-page .form-content, #forgot-page .form-content {
width: 50%;
max-width: 600px;
background-color: white;
border-radius: 3px;
border: 1px solid #808080;
padding: 2% 5%;
}

#reset-page label, #forgot-page label {
margin: 10px 0;
display: block;
}

#reset-page input, #forgot-page input {
background: none;
border: 1px solid #808080;
border-radius: 0px;
width: 100%;
padding: 10px;
}

#reset-page .button.button-block, #forgot-page .button.button-block {
display: block;
margin-top: 20px;
background: #fcbd01;
border-color: #fcbd01;
color: #fff;
font-size: 0.9em;
font-weight: 900;
letter-spacing: 1px;
}

#reset-page .button.button-block:hover, #forgot-page .button.button-block:hover {
background: #fcb101;
border-color: #fcb101;
}

#reset_form .input-group:last-of-type, #forgot-page .input-group:last-of-type {
margin-bottom: 30px;
}

/* buttons */

.btn.btn-primary {
Expand Down Expand Up @@ -226,3 +284,13 @@ body {
border-top: 4px solid #fcbd01;
}

#login-page .login-section {
color: #FFB703;
}

#login-page .login-section a, #forgot-page a, #reset-page a {
color: #FFB703 !important;
text-decoration: underline !important;
cursor: pointer !important;
}

27 changes: 27 additions & 0 deletions views/forgot.handlebars
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<div id="forgot-page">
<div class="form-content">
<h1>Enter Email Address</h1>
{{#if errors}}
<div id='danger'>{{errors}}</div>
{{/if}}
{{#if info}}
<div id='danger'>{{info}}</div>
{{else}}
<form action="/pass/reset" method="post" id="reset_form">
<div class="input-group">
<label>Email</label>
<input
name="user_email"
id="userEmail"
type="email"
{{#if email}} value={{email}} {{/if}}
required
/>
</div>
<div class="input-group">
<input class="button button-block" type="submit" value="Reset Password" />
</div>
</form>
{{/if}}
</div>
</div>
3 changes: 3 additions & 0 deletions views/login.handlebars
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,8 @@
<input class="button button-block" type="submit" value="Log In" />
</div>
</form>
<div class="login-section">
<h5>Forgot your password? <a href="/forgot">Reset</a></h5>
</div>
</div>
</div>
25 changes: 25 additions & 0 deletions views/reset.handlebars
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<div id="reset-page">
<div class="form-content">
<h1>Reset Password</h1>
<hr/>
{{#if errors}}
<div id='danger'>{{errors}} <a href={{link}}>Reset password.</a></div>
{{/if}}
{{#if info}}
<div id='danger'>{{info}} <a href={{link}}>Login.</a></div>
{{/if}}
{{#if showForm}}
<form action="/reset-password" method="post">
<div class="input-group">
<label>New Password</label>
<input name="password" type="password" required/>
<input name="id" type="hidden" value={{id}} />
<input name="token" type="hidden" value={{token}} />
</div>
<div class="input-group">
<input class="button button-block" type="submit" value="Submit" />
</div>
</form>
{{/if}}
</div>
</div>

0 comments on commit 3933de1

Please sign in to comment.