diff --git a/README.md b/README.md index 099ceb16..442f8311 100644 --- a/README.md +++ b/README.md @@ -22,23 +22,25 @@ These instructions will get you a copy of the project up and running on your loc >Create a new directory and initialize git ``` -$ mkdir Pinterest-Clone -$ cd Pinterest-Clone -$ git init +mkdir Pinterest-Clone +cd Pinterest-Clone +git init ``` >Pull from github and install packages ``` -$ git pull https://github.com/Dereje1/Pinterest-Clone.git -$ npm install +git pull https://github.com/Dereje1/Pinterest-Clone.git + +npm install ``` >To run mongoDB locally with docker : In the root folder run -`docker-compose up mongodb` and then use `mongodb://root:123456@localhost:27017` for `MONGOLAB_URI` -in your `.env `file below, alternatively, you can get a connection string from mongodb Atlas after setting up your own db. - +``` +docker-compose up mongodb +``` +Alternatively, you can get a connection string from mongodb Atlas after setting up your own db. >create .env files @@ -46,7 +48,7 @@ In the root of the project create a .env file with the following contents ``` SESSION_SECRET= -MONGOLAB_URI= +MONGOLAB_URI=mongodb://root:123456@localhost:27017 TWITTER_CONSUMER_KEY=< Get from Twitter Developer API > TWITTER_CONSUMER_SECRET=< Get from Twitter Developer API > TWITTER_CALLBACK=http://localhost:8080/auth/twitter/redirect @@ -60,10 +62,12 @@ AWS_ACCESS_KEY_ID=< Get from AWS > AWS_SECRET_KEY=< Get from AWS > S3_BUCKET_NAME=< s3 bucket name for uploaded pins> NODE_ENV= +DEBUG=Pinterest-Clone:server +DEBUG_COLORS=1 ``` -Run development environment +Run the development environment ``` -$ npm run dev +npm run dev ``` You can now go to `http://localhost:8080/` and see the project running in dev mode. diff --git a/bin/www.ts b/bin/www.ts index fa322916..d1521ed5 100644 --- a/bin/www.ts +++ b/bin/www.ts @@ -9,13 +9,11 @@ require('dotenv').config(); import http from 'http'; import debugg from 'debug'; -process.env.DEBUG = 'Pinterest-Clone:server'; const debug = debugg('Pinterest-Clone:server'); -// const http = require('http'); - const appPath = process.env.NODE_ENV === 'development' ? '../server/app' : '../app'; // eslint-disable-next-line import/no-dynamic-require const app = require(appPath).default; + /** * Normalize a port into a number, string, or false. */ @@ -81,12 +79,10 @@ const onError = (error: {syscall: string, code: string}) => { const onListening = () => { const addr = server.address(); - if (addr) { - const bind = typeof addr === 'string' - ? `pipe ${addr}` - : `port ${addr.port}`; - debug(`Listening on ${bind}`); - } + const bind = typeof addr === 'string' + ? `pipe ${addr}` + : `port ${addr?.port}`; + debug(`Listening on ${bind}`); }; /** diff --git a/server/controllers/delete.ts b/server/controllers/delete.ts index e471c761..9db6f8c8 100644 --- a/server/controllers/delete.ts +++ b/server/controllers/delete.ts @@ -1,4 +1,5 @@ import { Request } from 'express'; +import debugg from 'debug'; import { genericResponseType } from '../interfaces'; import { getUserProfile, @@ -7,21 +8,25 @@ import pins from '../models/pins'; import { UserType } from '../models/user'; import pinLinks from '../models/pinlinks'; +const debug = debugg('Pinterest-Clone:server'); + const deletePin = async (req: Request, res: genericResponseType) => { const { userId, displayName, isAdmin } = getUserProfile(req.user as UserType); const query = { _id: req.params._id }; const pinID = req.params._id; + debug(`Deleting pin -> ${pinID} by userId -> ${userId}`); try { const pin = await pins.findById(pinID).exec(); if (!pin) return res.end(); if (userId === pin.owner.toString() || isAdmin) { const removedPin = await pins.findOneAndRemove(query).exec(); await pinLinks.findOneAndRemove({ pin_id: pinID }).exec(); - console.log(`${displayName} deleted pin ${removedPin && removedPin.imgDescription}`); + debug(`${displayName} deleted pin ${removedPin && removedPin.imgDescription}`); return res.json(removedPin); } throw new Error(`Pin ID: ${pinID} is not owned by user ID: ${userId} - delete operation cancelled!`); } catch (error) { + debug(`Error deleting pin -> ${pinID} by userId -> ${userId}`); return res.json(error); } }; diff --git a/server/controllers/get.ts b/server/controllers/get.ts index 5a369fc5..c23a2d50 100644 --- a/server/controllers/get.ts +++ b/server/controllers/get.ts @@ -1,5 +1,6 @@ import { Request } from 'express'; import mongoose from 'mongoose'; +import debugg from 'debug'; import { genericResponseType } from '../interfaces'; import { getUserProfile, filterPins, @@ -8,14 +9,18 @@ import pins from '../models/pins'; import users, { UserType } from '../models/user'; import savedTags from '../models/tags'; +const debug = debugg('Pinterest-Clone:server'); + export const getPins = async (req: Request, res: genericResponseType) => { const { userId, isAdmin } = getUserProfile(req.user as UserType); + debug(`Getting all pins for userId -> ${userId}`); try { const allPins = await pins.find({ isBroken: false }) .populate(['owner', 'savedBy', 'comments.user']) .exec(); res.json(filterPins({ rawPins: allPins, userId, isAdmin })); } catch (error) { + debug(`Error getting all pins for userId -> ${userId}`); res.json(error); } }; @@ -23,6 +28,7 @@ export const getPins = async (req: Request, res: genericResponseType) => { export const getUserPins = async (req: Request, res: genericResponseType) => { const { userId, isAdmin } = getUserProfile(req.user as UserType); const mongooseUserId = mongoose.Types.ObjectId(userId); + debug(`Getting user pins for userId -> ${userId}`); try { if (isAdmin) { const allPins = await pins.find({ isBroken: false }).populate(['owner', 'savedBy', 'comments.user']).exec(); @@ -35,6 +41,7 @@ export const getUserPins = async (req: Request, res: genericResponseType) => { .exec(); return res.json({ profilePins: filterPins({ rawPins: profilePins, userId, isAdmin }) }); } catch (error) { + debug(`Error getting user pins for userId -> ${userId}`); return res.json(error); } }; @@ -46,6 +53,7 @@ export const getProfilePins = async ( const userId = req.params.userid; const mongooseUserId = mongoose.Types.ObjectId(userId); const { userId: loggedInUserid } = getUserProfile(req.user as UserType); + debug(`Getting profile pins for profile -> ${userId} by user -> ${loggedInUserid}`); try { const user = await users.findById(userId).exec(); if (!user) { @@ -69,6 +77,7 @@ export const getProfilePins = async ( }, }); } catch (error) { + debug(`Error etting profile pins for profile -> ${userId} by user -> ${loggedInUserid}`); // mongoose errors out on invalid ObjectIds sent -> redirect also in that case return res.json({ redirect: '/' }); } @@ -76,9 +85,11 @@ export const getProfilePins = async ( export const getTags = async (req: Request, res: genericResponseType) => { try { + debug('Getting all distinct tags'); const tags = await savedTags.find().distinct('tag').exec(); res.json(tags); } catch (error) { + debug('Error getting all distinct tags'); res.json(error); } }; diff --git a/server/controllers/post.ts b/server/controllers/post.ts index d965894a..9febca0f 100644 --- a/server/controllers/post.ts +++ b/server/controllers/post.ts @@ -1,5 +1,6 @@ import { Request } from 'express'; import mongoose from 'mongoose'; +import debugg from 'debug'; import { genericResponseType } from '../interfaces'; import { getUserProfile, uploadImageToS3, @@ -8,9 +9,12 @@ import pins from '../models/pins'; import { UserType } from '../models/user'; import pinLinks from '../models/pinlinks'; +const debug = debugg('Pinterest-Clone:server'); + export const addPin = async (req: Request, res: genericResponseType) => { const { displayName, userId, service } = getUserProfile(req.user as UserType); const { imgLink: originalImgLink } = req.body; + debug(`Creating new pin for userId -> ${userId}`); try { const newImgLink = await uploadImageToS3({ originalImgLink, userId, displayName, service, @@ -29,9 +33,10 @@ export const addPin = async (req: Request, res: genericResponseType) => { originalImgLink: addedpin.originalImgLink, cloudFrontLink: newImgLink ? `https://d1ttxrulihk8wq.cloudfront.net/${newImgLink.split('/')[4]}` : '', }); - console.log(`${displayName} added pin ${addedpin.imgDescription}`); + debug(`${displayName} added pin ${addedpin.imgDescription}`); res.json(addedpin); } catch (error) { + debug(`Error creating new pin for userId -> ${userId}`); res.json(error); } }; @@ -48,6 +53,7 @@ export const getDuplicateError = async (req: Request, res: genericResponseType) }).exec(); return res.json({ duplicateError: Boolean(duplicateFound) }); } catch (error) { + debug('Error looking for duplicates'); return res.json(error); } }; diff --git a/server/controllers/put.ts b/server/controllers/put.ts index bc6ea7b9..ef519d2c 100644 --- a/server/controllers/put.ts +++ b/server/controllers/put.ts @@ -1,5 +1,6 @@ import { Request } from 'express'; import mongoose from 'mongoose'; +import debugg from 'debug'; import { genericResponseType } from '../interfaces'; import { getUserProfile, filterPins, @@ -8,12 +9,14 @@ import pins from '../models/pins'; import users, { UserType } from '../models/user'; import savedTags from '../models/tags'; +const debug = debugg('Pinterest-Clone:server'); + export const pinImage = async (req: Request, res: genericResponseType) => { const pinID = req.params._id; const { userId, displayName, isAdmin, } = getUserProfile(req.user as UserType); - + debug(`Pinning image with id -> ${pinID} by userId -> ${userId}`); try { const pin = await pins.findById(pinID).exec(); if (!pin) return res.end(); @@ -27,12 +30,13 @@ export const pinImage = async (req: Request, res: genericResponseType) => { .exec(); if (!updatedPin) return res.end(); const [filteredAndUpdatedPin] = filterPins({ rawPins: [updatedPin], userId, isAdmin }); - console.log(`${displayName} pinned ${updatedPin.imgDescription}`); + debug(`${displayName} pinned ${updatedPin.imgDescription}`); return res.json(filteredAndUpdatedPin); } - console.log(`${displayName} has the pin - ${pin.imgDescription} already saved`); + debug(`${displayName} has the pin - ${pin.imgDescription} already saved`); return res.end(); } catch (error) { + debug(`Error pinning image with id -> ${pinID} by userId -> ${userId}`); return res.json(error); } }; @@ -40,6 +44,7 @@ export const pinImage = async (req: Request, res: genericResponseType) => { export const unpin = async (req: Request, res: genericResponseType) => { const { userId, displayName, isAdmin } = getUserProfile(req.user as UserType); const pinID = req.params._id; + debug(`Unpinning image with id -> ${pinID} by userId -> ${userId}`); try { const pin = await pins.findById(pinID).exec(); if (!pin) return res.end(); @@ -51,9 +56,10 @@ export const unpin = async (req: Request, res: genericResponseType) => { .exec(); if (!updatedPin) return res.end(); const [filteredAndUpdatedPin] = filterPins({ rawPins: [updatedPin], userId, isAdmin }); - console.log(`${displayName} unpinned ${updatedPin.imgDescription}`); + debug(`${displayName} unpinned ${updatedPin.imgDescription}`); return res.json(filteredAndUpdatedPin); } catch (error) { + debug(`Error unpinning image with id -> ${pinID} by userId -> ${userId}`); return res.json(error); } }; @@ -64,6 +70,7 @@ export const addComment = async (req: Request, res: genericResponseType) => { } = getUserProfile(req.user as UserType); const pinID = req.params._id; const { comment } = req.body; + debug(`Adding comment for pin with id -> ${pinID} by userId -> ${userId}`); try { const update = { $push: { comments: { comment, user: mongoose.Types.ObjectId(userId) } } }; const modified = { new: true }; @@ -72,9 +79,10 @@ export const addComment = async (req: Request, res: genericResponseType) => { .exec(); if (!updatedPin) return res.end(); const [filteredAndUpdatedPin] = filterPins({ rawPins: [updatedPin], userId, isAdmin }); - console.log(`${displayName} commented on ${updatedPin.imgDescription}`); + debug(`${displayName} commented on ${updatedPin.imgDescription}`); return res.json(filteredAndUpdatedPin); } catch (error) { + debug(`Error adding comment for pin with id -> ${pinID} by userId -> ${userId}`); return res.json(error); } }; @@ -84,6 +92,7 @@ export const updateTags = async (req: Request, res: genericResponseType) => { userId, displayName, isAdmin, } = getUserProfile(req.user as UserType); const { pinID, tag, deleteId } = req.query; + debug(`Updating tags for pin with id -> ${pinID} by userId -> ${userId}`); try { const pin = await pins.findById(pinID).exec(); if (!pin) return res.end(); @@ -101,9 +110,10 @@ export const updateTags = async (req: Request, res: genericResponseType) => { .exec(); if (!updatedPin) return res.end(); const [filteredAndUpdatedPin] = filterPins({ rawPins: [updatedPin], userId, isAdmin }); - console.log(`${displayName} ${deleteId ? 'deleted' : `added ${tag}`} tag on ${updatedPin.imgDescription}`); + debug(`${displayName} ${deleteId ? 'deleted' : `added ${tag}`} tag on ${updatedPin.imgDescription}`); return res.json(filteredAndUpdatedPin); } catch (error) { + debug(`Error updating tags for pin with id -> ${pinID} by userId -> ${userId}`); return res.json(error); } }; @@ -113,13 +123,15 @@ export const updateDisplayName = async (req: Request, res: genericResponseType) userId, displayName, } = getUserProfile(req.user as UserType); const { newDisplayName } = req.body; + debug(`Updating Display name for userId -> ${userId}`); try { const user = await users.findById(userId).exec(); const update = { $set: { displayName: newDisplayName } }; await user?.updateOne(update); - console.log(`${displayName} changed to ${newDisplayName}`); + debug(`${displayName} changed to ${newDisplayName}`); return res.end(); } catch (error) { + debug(`Error updating Display name for userId -> ${userId}`); return res.json(error); } };