Merge pull request #2 from Braeden57/editor
Add Editor page to edit accounts (currently Student only)
This commit is contained in:
11 files changed
+370
-62
No files matched your search
@@ -1,13 +1,12 @@
|
||||
// Import required libraries
|
||||
const express = require('express');
|
||||
const expressLayouts = require('express-ejs-layouts');
|
||||
const mongoose = require('mongoose');
|
||||
const passport = require('passport');
|
||||
const flash = require('connect-flash');
|
||||
const session = require('express-session');
|
||||
const fs = require('fs');
|
||||
const bodyParser = require('body-parser');
|
||||
const path = require('path');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
require('dotenv/config');
|
||||
|
||||
const app = express();
|
||||
@@ -19,9 +18,10 @@ require('./config/passport')(passport);
|
||||
const db = require('./config/keys').mongoURI;
|
||||
|
||||
// Connect to MongoDB
|
||||
mongoose.connect(
|
||||
mongoose
|
||||
.connect(
|
||||
db,
|
||||
{ useNewUrlParser: true ,useUnifiedTopology: true}
|
||||
{ useNewUrlParser: true, useUnifiedTopology: true}
|
||||
)
|
||||
.then(() => console.log('MongoDB Connected'))
|
||||
.catch(err => console.log(err));
|
||||
@@ -30,7 +30,7 @@ mongoose.connect(
|
||||
app.use(expressLayouts);
|
||||
app.set('view engine', 'ejs');
|
||||
|
||||
// Body parser
|
||||
// Body Parser
|
||||
app.use(bodyParser.urlencoded({ extended: false }))
|
||||
app.use(bodyParser.json())
|
||||
|
||||
@@ -64,5 +64,4 @@ app.use('/users', require('./routes/users.js'));
|
||||
|
||||
const PORT = process.env.PORT || 5000;
|
||||
|
||||
// Start Server
|
||||
app.listen(PORT, console.log(`Server started on port ${PORT}`));
|
||||
@@ -0,0 +1,11 @@
|
||||
const fs = require('fs');
|
||||
const path = require('../routes/users.js').path;
|
||||
|
||||
let image = {
|
||||
data: fs.readFileSync(path),
|
||||
contentType: "image/png"
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
defaultImage: image
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
+276
-37
@@ -3,23 +3,27 @@ const express = require('express');
|
||||
const router = express.Router();
|
||||
const bcrypt = require('bcryptjs');
|
||||
const passport = require('passport');
|
||||
const ObjectID = require('mongodb').ObjectID;
|
||||
const MongoClient = require('mongodb').MongoClient;
|
||||
const ObjectId = require('mongodb').ObjectId;
|
||||
// Load User model
|
||||
const User = require('../models/User');
|
||||
const { forwardAuthenticated } = require('../config/auth');
|
||||
|
||||
// DB Config
|
||||
const db = require('../config/keys').mongoURI;
|
||||
|
||||
// Loads libraries for uploading img functions
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const multer = require('multer');
|
||||
let fs = require('fs');
|
||||
let path = require('path');
|
||||
let multer = require('multer');
|
||||
|
||||
let storage = multer.diskStorage({
|
||||
destination: (req, file, cb) => {
|
||||
cb(null, 'routes/uploads')
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
cb(null, file.fieldname + '-' + Date.now())
|
||||
}
|
||||
destination: (req, file, cb) => {
|
||||
cb(null, 'routes/uploads')
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
cb(null, file.fieldname + '-' + Date.now())
|
||||
}
|
||||
});
|
||||
|
||||
let upload = multer({ storage: storage });
|
||||
@@ -30,8 +34,211 @@ router.get('/login', forwardAuthenticated, (req, res) => res.render('login'));
|
||||
// Register Page
|
||||
router.get('/register', forwardAuthenticated, (req, res) => res.render('register'));
|
||||
|
||||
// Edit page
|
||||
router.get('/edit', (req, res) => res.render('edit'));
|
||||
|
||||
// Edit
|
||||
router.post('/edit', upload.single('image'), (req, res, next) => {
|
||||
// Passes image path to defaultImage Model
|
||||
imagePath = __dirname + '/uploads/image-1606947471396';
|
||||
module.exports = {
|
||||
path: imagePath
|
||||
}
|
||||
|
||||
// Gets inputs
|
||||
const { _id, name, newPassword, newPassword2 } = req.body;
|
||||
let errors = [];
|
||||
let useName = true;
|
||||
let useNewPassword = true;
|
||||
|
||||
if (!name) {
|
||||
useName = false;
|
||||
}
|
||||
|
||||
if (!newPassword) {
|
||||
if (newPassword2.length > 0) {
|
||||
errors.push({ msg: 'You need to enter your new password' })
|
||||
}
|
||||
|
||||
if (!newPassword2) {
|
||||
useNewPassword = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (newPassword.length > 0) {
|
||||
if (!newPassword2) {
|
||||
errors.push({ msg: 'Confirm new Password' })
|
||||
}
|
||||
|
||||
// Checks if new password & new password confirm match
|
||||
if (newPassword != newPassword2) {
|
||||
errors.push({ msg: 'New Passwords do not match' });
|
||||
}
|
||||
|
||||
// Validates new password is required lenght
|
||||
if (newPassword.length < 6) {
|
||||
errors.push({ msg: 'Password must be at least 6 characters' });
|
||||
}
|
||||
}
|
||||
|
||||
// Error Handling
|
||||
if (errors.length > 0) {
|
||||
// Redirects to edit page with errors
|
||||
res.render('edit', {
|
||||
errors,
|
||||
name,
|
||||
currPassword,
|
||||
newPassword,
|
||||
newPassword2
|
||||
});
|
||||
} else {
|
||||
let hashPass;
|
||||
let updated;
|
||||
let defaultImage = require('../models/defaultImage').defaultImage;
|
||||
|
||||
try {
|
||||
if (useName && useNewPassword) {
|
||||
// Encrypts password
|
||||
bcrypt.genSalt(10, (err, salt) => {
|
||||
bcrypt.hash(newPassword, salt, (err, hash) => {
|
||||
if (err) throw err;
|
||||
hashPass = hash;
|
||||
});
|
||||
});
|
||||
|
||||
console.log(newPassword);
|
||||
console.log(hashPass);
|
||||
|
||||
//creates updated image object
|
||||
updated = {
|
||||
name: name,
|
||||
image: {
|
||||
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
|
||||
contentType: 'image/png'
|
||||
},
|
||||
password: hashPass
|
||||
}
|
||||
}
|
||||
|
||||
if (useName) {
|
||||
//creates updated image object
|
||||
updated = {
|
||||
name: name,
|
||||
image: {
|
||||
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
|
||||
contentType: 'image/png'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useNewPassword) {
|
||||
//creates updated image object
|
||||
updated = {
|
||||
image: {
|
||||
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
|
||||
contentType: 'image/png'
|
||||
},
|
||||
password: hashPass
|
||||
}
|
||||
}
|
||||
|
||||
if (!useName && !useNewPassword) {
|
||||
//creates updated image object
|
||||
updated = {
|
||||
image: {
|
||||
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
|
||||
contentType: 'image/png'
|
||||
}
|
||||
}
|
||||
}
|
||||
//Updates user and redirects to dashboard
|
||||
MongoClient.connect(db, {
|
||||
useUnifiedTopology: true,
|
||||
useNewUrlParser: true}, function(err, db) {
|
||||
if (err) throw err;
|
||||
let dbo = db.db("XPmockDB");
|
||||
dbo.collection('users').updateOne({ _id: ObjectId(_id) }, { $set: updated }, { upsert: true }, function(err, res) {
|
||||
if (err) throw err;
|
||||
console.log('1 Document Updated');
|
||||
console.log('With customImage');
|
||||
db.close()
|
||||
});
|
||||
res.redirect('/users/login');
|
||||
}
|
||||
);
|
||||
}
|
||||
catch(err) {
|
||||
console.log(err);
|
||||
if (useName && useNewPassword) {
|
||||
// Encrypts password
|
||||
bcrypt.genSalt(10, (err, salt) => {
|
||||
bcrypt.hash(newPassword, salt, (err, hash) => {
|
||||
if (err) throw err;
|
||||
hashPass = hash;
|
||||
});
|
||||
});
|
||||
|
||||
console.log(newPassword);
|
||||
console.log(hashPass);
|
||||
|
||||
//creates updated image object
|
||||
updated = {
|
||||
name: name,
|
||||
image: defaultImage,
|
||||
password: hashPass
|
||||
}
|
||||
}
|
||||
|
||||
if (useName) {
|
||||
//creates updated image object
|
||||
updated = {
|
||||
name: name,
|
||||
image: defaultImage
|
||||
}
|
||||
}
|
||||
|
||||
if (useNewPassword) {
|
||||
//creates updated image object
|
||||
updated = {
|
||||
image: defaultImage,
|
||||
password: hashPass
|
||||
}
|
||||
}
|
||||
|
||||
if (!useName && !useNewPassword) {
|
||||
//creates updated image object
|
||||
updated = {
|
||||
image: defaultImage
|
||||
}
|
||||
}
|
||||
//Updates user and redirects to dashboard
|
||||
MongoClient.connect(db, {
|
||||
useUnifiedTopology: true,
|
||||
useNewUrlParser: true}, function(err, db) {
|
||||
if (err) throw err;
|
||||
let dbo = db.db("XPmockDB");
|
||||
dbo.collection('users').updateOne({ _id: ObjectId(_id) }, { $set: updated }, { upsert: true }, function(err, res) {
|
||||
if (err) throw err;
|
||||
console.log('1 Document Updated');
|
||||
console.log('With defaultImage');
|
||||
db.close()
|
||||
});
|
||||
res.flash('Success')
|
||||
res.redirect('/users/login');
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Register
|
||||
router.post('/register', upload.single('image'), (req, res, next) => {
|
||||
// Passes image path to defaultImage Model
|
||||
path = __dirname + '/uploads/image-1606947471396';
|
||||
module.exports = {
|
||||
path: path
|
||||
}
|
||||
|
||||
// Collects input
|
||||
const { name, email, password, password2 } = req.body;
|
||||
let errors = [];
|
||||
@@ -75,35 +282,67 @@ router.post('/register', upload.single('image'), (req, res, next) => {
|
||||
password2
|
||||
});
|
||||
} else {
|
||||
// Creates new User Object
|
||||
const newUser = new User({
|
||||
name,
|
||||
image: {
|
||||
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
|
||||
contentType: 'image/png'
|
||||
},
|
||||
email,
|
||||
password,
|
||||
});
|
||||
|
||||
// Encrypts password
|
||||
bcrypt.genSalt(10, (err, salt) => {
|
||||
bcrypt.hash(newUser.password, salt, (err, hash) => {
|
||||
if (err) throw err;
|
||||
newUser.password = hash;
|
||||
newUser
|
||||
.save()
|
||||
.then(user => {
|
||||
req.flash(
|
||||
'success_msg',
|
||||
'You are now registered and can log in'
|
||||
);
|
||||
// Takes to login page on success
|
||||
res.redirect('/users/login');
|
||||
})
|
||||
.catch(err => console.log(err));
|
||||
try {
|
||||
// Creates new User Object
|
||||
const newUser = new User({
|
||||
name,
|
||||
email,
|
||||
password,
|
||||
image: {
|
||||
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
|
||||
contentType: 'image/png'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Encrypts password
|
||||
bcrypt.genSalt(10, (err, salt) => {
|
||||
bcrypt.hash(newUser.password, salt, (err, hash) => {
|
||||
if (err) throw err;
|
||||
newUser.password = hash;
|
||||
newUser
|
||||
.save()
|
||||
.then(user => {
|
||||
req.flash(
|
||||
'success_msg',
|
||||
'You are now registered and can log in'
|
||||
);
|
||||
// Takes to login page on success
|
||||
res.redirect('/users/login');
|
||||
})
|
||||
.catch(err => console.log(err));
|
||||
});
|
||||
});
|
||||
}
|
||||
catch(err) {
|
||||
const defaultImage = require('../models/defaultImage').defaultImage;
|
||||
// Creates new User Object
|
||||
const newUser = new User({
|
||||
name,
|
||||
email,
|
||||
password,
|
||||
image: defaultImage
|
||||
});
|
||||
|
||||
// Encrypts password
|
||||
bcrypt.genSalt(10, (err, salt) => {
|
||||
bcrypt.hash(newUser.password, salt, (err, hash) => {
|
||||
if (err) throw err;
|
||||
newUser.password = hash;
|
||||
newUser
|
||||
.save()
|
||||
.then(user => {
|
||||
req.flash(
|
||||
'success_msg',
|
||||
'You are now registered and can log in'
|
||||
);
|
||||
// Takes to login page on success
|
||||
res.redirect('/users/login');
|
||||
})
|
||||
.catch(err => console.log(err));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
<div class="row mt-5">
|
||||
<div class="col-md-6 m-auto">
|
||||
<div class="card card-body">
|
||||
<h1 class="text-center mb-3">
|
||||
<i class="fas fa-user-plus"></i> Edit Account
|
||||
</h1>
|
||||
<% include ./partials/messages %>
|
||||
<form action="/users/edit" method="POST" enctype="multipart/form-data">
|
||||
|
||||
<!-- Catching _id -->
|
||||
<script>
|
||||
window.onload = function () {
|
||||
var url = document.location.href,
|
||||
params = url.split('?')[1].split('&'),
|
||||
data = {}, tmp;
|
||||
for (var i = 0, l = params.length; i < l; i++) {
|
||||
tmp = params[i].split('=');
|
||||
data[tmp[0]] = tmp[1];
|
||||
}
|
||||
document.getElementById('_id').value = data.name;
|
||||
}
|
||||
</script>
|
||||
<input id='_id' type='text' name='_id' value='' style='display: none'></input>
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
<input
|
||||
type="name"
|
||||
id="name"
|
||||
name="name"
|
||||
class="form-control"
|
||||
placeholder="Enter Name"
|
||||
value="<%= typeof name != 'undefined' ? name : '' %>"
|
||||
/>
|
||||
</div>
|
||||
<div class='form-group'>
|
||||
<label for='image'>Upload Profile Picture</label>
|
||||
<input class='form-control' type="file" id="image" name="image" value="">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password2">New Password</label>
|
||||
<input
|
||||
type="password"
|
||||
id="newPassword"
|
||||
name="newPassword"
|
||||
class="form-control"
|
||||
placeholder="New Password"
|
||||
value="<%= typeof password2 != 'undefined' ? password2 : '' %>"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password2">Confirm New Password</label>
|
||||
<input
|
||||
type="password"
|
||||
id="newPassword2"
|
||||
name="newPassword2"
|
||||
class="form-control"
|
||||
placeholder="Confirm New Password"
|
||||
value="<%= typeof password2 != 'undefined' ? password2 : '' %>"
|
||||
/>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-block">
|
||||
Save Changes
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -21,6 +21,10 @@
|
||||
<label for='image'>Upload Profile Picture</label>
|
||||
<input class='form-control' type="file" id="image" name="image" value="" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for='image'>Upload Profile Picture</label>
|
||||
<input class="form-control-file" type="file" id="image" name="image" value="">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email">Email</label>
|
||||
<input
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
|
||||
#pro-pic {
|
||||
position: absolute;
|
||||
top: 24px;
|
||||
left: 24px;
|
||||
width: 100px;
|
||||
margin: 27px;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
display: block;
|
||||
border-radius: 50px;
|
||||
}
|
||||
@@ -52,6 +52,7 @@
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<a href="/users/logout" class="btn btn-secondary">Logout</a>
|
||||
<button onClick='passData()' class='btn btn-secondary'>Edit</button>
|
||||
|
||||
<!-- Passing user _id to edit page script -->
|
||||
<script>
|
||||
|
||||
@@ -4,15 +4,12 @@
|
||||
width: 230px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.head {
|
||||
margin-bottom: 100px;
|
||||
}
|
||||
|
||||
#teacher-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#pro-pic {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
@@ -23,18 +20,17 @@
|
||||
border: 1px solid black;
|
||||
margin:5px;
|
||||
}
|
||||
|
||||
#user-pro-pic {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 150px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
display: block;
|
||||
border-radius: 50px;
|
||||
border: 1px solid black;
|
||||
margin:5px;
|
||||
}
|
||||
|
||||
#logout-btn {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
@@ -45,41 +41,34 @@
|
||||
left: 115px;
|
||||
top: 60px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font: 350 35px/1.5 Helvetica, Verdana, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
font: 200 20px/1.5 Helvetica, Verdana, sans-serif;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
li:last-child {
|
||||
border: none;
|
||||
}
|
||||
|
||||
li a {
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
display: block;
|
||||
width: 200px;
|
||||
|
||||
-webkit-transition: font-size 0.3s ease, background-color 0.3s ease;
|
||||
-moz-transition: font-size 0.3s ease, background-color 0.3s ease;
|
||||
-o-transition: font-size 0.3s ease, background-color 0.3s ease;
|
||||
-ms-transition: font-size 0.3s ease, background-color 0.3s ease;
|
||||
transition: font-size 0.3s ease, background-color 0.3s ease;
|
||||
}
|
||||
|
||||
li a:hover {
|
||||
font-size: 30px;
|
||||
background: #f6f6f6;
|
||||
@@ -139,7 +128,7 @@
|
||||
<% if (member.role == "Student") { %>
|
||||
<!-- Creates User Button link -->
|
||||
<li><button class='btn btn-link mt-2' onclick='openProfile("<%= member.id %>")'><%= member.name %></button></li>
|
||||
|
||||
|
||||
<!-- Creates hidden Div with user specific Data -->
|
||||
<div style='display: none; position: relative;' data-role='page' id='<%= member._id %>'>
|
||||
<img id='user-pro-pic' src='data:image/<%=member.image.contentType%>;base64,<%=member.image.data.toString('base64')%>'>
|
||||
@@ -156,7 +145,6 @@
|
||||
<!-- Calculates user specific Rank -->
|
||||
<script>
|
||||
xp = <%= member.xp %>;
|
||||
|
||||
// Get current rank
|
||||
if (xp == 0) {
|
||||
currRank = 'Digital Noob';
|
||||
@@ -181,7 +169,6 @@
|
||||
|
||||
// Display Rank
|
||||
document.getElementById('userRank-<%= member.id %>').innerHTML = currRank;
|
||||
|
||||
</script>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
Reference in new issue
Block a user