-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
66 changed files
with
2,707 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
const path = require('path'); | ||
|
||
const express = require('express'); | ||
const bodyParser = require('body-parser'); | ||
const mongoose = require('mongoose'); | ||
const multer = require('multer'); | ||
|
||
const feedRoutes = require('./routes/feed'); | ||
const authRoutes = require('./routes/auth'); | ||
|
||
const app = express(); | ||
/** SOCKET-IO CONFIGURATION */ | ||
const http = require('http'); | ||
const server = http.createServer(app); | ||
/** ======================= */ | ||
|
||
const fileStorage = multer.diskStorage({ | ||
destination: (req, file, cb) => { | ||
cb(null, 'images'); | ||
}, | ||
filename: (req, file, cb) => { | ||
/** DON'T USE .toISOString() on windows */ | ||
cb(null, Date.now() + '-' + file.originalname); | ||
}, | ||
}); | ||
|
||
const fileFilter = (req, file, cb) => { | ||
if ( | ||
file.mimetype === 'image/png' || | ||
file.mimetype === 'image/jpg' || | ||
file.mimetype === 'image/jpeg' | ||
) { | ||
cb(null, true); | ||
} else { | ||
cb(null, false); | ||
} | ||
}; | ||
|
||
// app.use(bodyParser.urlEncoded()); // x-www-form-urlencoded <form> | ||
app.use(bodyParser.json()); // application/json | ||
app.use( | ||
multer({ storage: fileStorage, fileFilter: fileFilter }).single('image') | ||
); | ||
app.use('/images', express.static(path.join(__dirname, 'images'))); | ||
|
||
app.use((req, res, next) => { | ||
res.setHeader('Access-Control-Allow-Origin', '*'); | ||
res.setHeader( | ||
'Access-Control-Allow-Methods', | ||
'OPTIONS, GET, POST, PUT, PATCH, DELETE' | ||
); | ||
res.setHeader( | ||
'Access-Control-Allow-Headers', | ||
'Content-Type, Authorization' | ||
); | ||
next(); | ||
}); | ||
|
||
app.use('/feed', feedRoutes); | ||
app.use('/auth', authRoutes); | ||
|
||
app.use((error, req, res, next) => { | ||
console.log(error); | ||
const status = error.statusCode; | ||
const message = error.message; | ||
const data = error.data; | ||
res.status(status).json({ message: message, data: data }); | ||
}); | ||
|
||
/** REPLACE CONNECTION STRING IF USING ATLAS | ||
* "mongodb+srv://<username>:<password>@<cluster-id>.mongodb.net/<dbName>?retryWrites=true&authSource=admin" | ||
*/ | ||
mongoose | ||
.connect( | ||
'mongodb://127.0.0.1:27017/messages?retryWrites=true&authSource=admin' | ||
) | ||
.then(() => { | ||
/** SEE LINES 12-15 -- UPDATED CONFIGURATION */ | ||
const io = require('./socket').init(server); | ||
io.on('connection', (socket) => { | ||
console.log('Client connected.'); | ||
}); | ||
/** ======================================== */ | ||
/** LISTEN TO CUSTOM SERVER INSTANCE */ | ||
server.listen(8080); | ||
}) | ||
.catch((err) => console.log(err)); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
const { validationResult } = require('express-validator'); | ||
const bcrypt = require('bcryptjs'); | ||
const jwt = require('jsonwebtoken'); | ||
|
||
const User = require('../models/user'); | ||
|
||
exports.signup = async (req, res, next) => { | ||
const errors = validationResult(req); | ||
if (!errors.isEmpty()) { | ||
const error = new Error('Validation failed.'); | ||
error.statusCode = 422; | ||
error.data = errors.array(); | ||
throw error; | ||
} | ||
const email = req.body.email; | ||
const name = req.body.name; | ||
const password = req.body.password; | ||
try { | ||
const hashedPw = await bcrypt.hash(password, 12); | ||
|
||
const user = new User({ | ||
email: email, | ||
password: hashedPw, | ||
name: name, | ||
}); | ||
const result = await user.save(); | ||
res.status(201).json({ | ||
message: 'User created!', | ||
userId: result._id, | ||
}); | ||
} catch (err) { | ||
if (!err.statusCode) { | ||
err.statusCode = 500; | ||
} | ||
next(err); | ||
} | ||
}; | ||
|
||
exports.login = async (req, res, next) => { | ||
const email = req.body.email; | ||
const password = req.body.password; | ||
let loadedUser; | ||
try { | ||
const user = await User.findOne({ email: email }); | ||
if (!user) { | ||
const error = new Error( | ||
'A user with this email could not be found.' | ||
); | ||
error.statusCode = 401; | ||
throw error; | ||
} | ||
loadedUser = user; | ||
const isEqual = await bcrypt.compare(password, user.password); | ||
if (!isEqual) { | ||
const error = new Error('Wrong password!'); | ||
error.statusCode = 401; | ||
throw error; | ||
} | ||
const token = jwt.sign( | ||
{ email: loadedUser.email, userId: loadedUser._id.toString() }, | ||
'somesupersecretsecret', | ||
{ expiresIn: '1h' } | ||
); | ||
res.status(200).json({ | ||
token: token, | ||
userId: loadedUser._id.toString(), | ||
}); | ||
} catch (err) { | ||
if (!err.statusCode) { | ||
err.statusCode = 500; | ||
} | ||
next(err); | ||
} | ||
}; | ||
|
||
exports.getUserStatus = async (req, res, next) => { | ||
try { | ||
const user = await User.findById(req.userId); | ||
if (!user) { | ||
const error = new Error('User not found.'); | ||
error.statusCode = 404; | ||
throw error; | ||
} | ||
res.status(200).json({ status: user.status }); | ||
} catch (err) { | ||
if (!err.statusCode) { | ||
err.statusCode = 500; | ||
} | ||
next(err); | ||
} | ||
}; | ||
|
||
exports.updateUserStatus = async (req, res, next) => { | ||
const newStatus = req.body.status; | ||
try { | ||
const user = await User.findById(req.userId); | ||
if (!user) { | ||
const error = new Error('User not found.'); | ||
error.statusCode = 404; | ||
throw error; | ||
} | ||
user.status = newStatus; | ||
await user.save(); | ||
res.status(200).json({ message: 'User updated.' }); | ||
} catch (err) { | ||
if (!err.statusCode) { | ||
err.statusCode = 500; | ||
} | ||
next(err); | ||
} | ||
}; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
|
||
const { validationResult } = require('express-validator'); | ||
|
||
const io = require('../socket'); | ||
const Post = require('../models/post'); | ||
const User = require('../models/user'); | ||
|
||
exports.getPosts = async (req, res, next) => { | ||
const currentPage = req.query.page || 1; | ||
const perPage = 2; | ||
try { | ||
const totalItems = await Post.find().countDocuments(); | ||
const posts = await Post.find() | ||
.populate('creator') | ||
.sort({ createdAt: -1 }) | ||
.skip((currentPage - 1) * perPage) | ||
.limit(perPage); | ||
res.status(200).json({ | ||
message: 'Fetched posts successfully.', | ||
posts: posts, | ||
totalItems: totalItems, | ||
}); | ||
} catch (err) { | ||
if (!err.statusCode) { | ||
err.statusCode = 500; | ||
} | ||
next(err); | ||
} | ||
}; | ||
|
||
exports.createPost = async (req, res, next) => { | ||
const errors = validationResult(req); | ||
if (!errors.isEmpty()) { | ||
const error = new Error( | ||
'Validation failed, entered data is incorrect.' | ||
); | ||
error.statusCode = 422; | ||
throw error; | ||
} | ||
if (!req.file) { | ||
const error = new Error('No image provided.'); | ||
error.statusCode = 422; | ||
throw error; | ||
} | ||
/** REPLACE ALL '\' WITH '/' */ | ||
const imageUrl = req.file.path.replace(/\\/g, '/'); | ||
const title = req.body.title; | ||
const content = req.body.content; | ||
const post = new Post({ | ||
title: title, | ||
content: content, | ||
imageUrl: imageUrl, | ||
creator: req.userId, | ||
}); | ||
try { | ||
await post.save(); | ||
const user = await User.findById(req.userId); | ||
user.posts.push(post); | ||
await user.save(); | ||
io.getIO().emit('posts', { | ||
action: 'create', | ||
post: { | ||
...post._doc, | ||
creator: { _id: req.userId, name: user.name }, | ||
}, | ||
}); | ||
res.status(201).json({ | ||
message: 'Post created successfully!', | ||
post: post, | ||
creator: { | ||
_id: user._id, | ||
name: user.name, | ||
}, | ||
}); | ||
} catch (err) { | ||
if (!err.statusCode) { | ||
err.statusCode = 500; | ||
} | ||
next(err); | ||
} | ||
}; | ||
|
||
exports.getPost = async (req, res, next) => { | ||
const postId = req.params.postId; | ||
try { | ||
const post = await Post.findById(postId); | ||
if (!post) { | ||
const error = new Error('Could not find post.'); | ||
error.statusCode = 404; | ||
throw error; | ||
} | ||
res.status(200).json({ | ||
message: 'Post fetched.', | ||
post: post, | ||
}); | ||
} catch (err) { | ||
if (!err.statusCode) { | ||
err.statusCode = 500; | ||
} | ||
next(err); | ||
} | ||
}; | ||
|
||
exports.updatePost = async (req, res, next) => { | ||
const postId = req.params.postId; | ||
const errors = validationResult(req); | ||
if (!errors.isEmpty()) { | ||
const error = new Error( | ||
'Validation failed, entered data is incorrect.' | ||
); | ||
error.statusCode = 422; | ||
throw error; | ||
} | ||
const title = req.body.title; | ||
const content = req.body.content; | ||
let imageUrl = req.body.image; | ||
if (req.file) { | ||
/** REPLACE ALL '\' WITH '/' */ | ||
imageUrl = req.file.path.replace(/\\/g, '/'); | ||
} | ||
if (!imageUrl) { | ||
const error = new Error('No file picked.'); | ||
error.statusCode = 422; | ||
throw error; | ||
} | ||
try { | ||
const post = await Post.findById(postId).populate('creator'); | ||
if (!post) { | ||
const error = new Error('Could not find post.'); | ||
error.statusCode = 404; | ||
throw error; | ||
} | ||
if (post.creator._id.toString() !== req.userId) { | ||
const error = new Error('Not authorized.'); | ||
error.statusCode = 403; | ||
throw error; | ||
} | ||
if (imageUrl !== post.imageUrl) { | ||
clearImage(post.imageUrl); | ||
} | ||
post.title = title; | ||
post.imageUrl = imageUrl; | ||
post.content = content; | ||
const result = await post.save(); | ||
io.getIO().emit('posts', { action: 'update', post: result }); | ||
res.status(200).json({ message: 'Post updated!', post: result }); | ||
} catch (err) { | ||
if (!err.statusCode) { | ||
err.statusCode = 500; | ||
} | ||
next(err); | ||
} | ||
}; | ||
|
||
exports.deletePost = async (req, res, next) => { | ||
const postId = req.params.postId; | ||
try { | ||
const post = await Post.findById(postId); | ||
|
||
if (!post) { | ||
const error = new Error('Could not find post.'); | ||
error.statusCode = 404; | ||
throw error; | ||
} | ||
if (post.creator.toString() !== req.userId) { | ||
const error = new Error('Not authorized.'); | ||
error.statusCode = 403; | ||
throw error; | ||
} | ||
// Check logged in user | ||
clearImage(post.imageUrl); | ||
/** .findByIdAndRemove -- REMOVED */ | ||
await Post.findByIdAndDelete(postId); | ||
|
||
const user = await User.findById(req.userId); | ||
user.posts.pull(postId); | ||
await user.save(); | ||
io.getIO().emit('posts', { | ||
action: 'delete', | ||
post: postId, | ||
}); | ||
res.status(200).json({ message: 'Deleted post.' }); | ||
} catch (err) { | ||
if (!err.statusCode) { | ||
err.statusCode = 500; | ||
} | ||
next(err); | ||
} | ||
}; | ||
|
||
const clearImage = (filePath) => { | ||
filePath = path.join(__dirname, '..', filePath); | ||
fs.unlink(filePath, (err) => console.log(err)); | ||
}; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.