diff --git a/.gitignore b/.gitignore index 5dc796a..41f2343 100755 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ node_modules .DS_Store .vscode ensemble-blog +.gitignore +.github \ No newline at end of file diff --git a/controllers/api-routes.js b/controllers/api-routes.js index 094adde..f72fc59 100755 --- a/controllers/api-routes.js +++ b/controllers/api-routes.js @@ -1,64 +1,64 @@ -const router = require('express').Router(); -const { User, Post, Comment } = require('../models'); +const router = require('express').Router(); // import express router (https://expressjs.com/en/4x/api.html#router) +const { User, Post, Comment } = require('../models'); // import models (https://sequelize.org/docs/v6/core-concepts/model-basics/) -// In one of the route files, like routes/authRoutes.js -// add new comments -router.post('/post/:id', async (req, res) => { +// In one of the route files, like routes/authRoutes.js we have an app.use() statement that calls app.use('/api', apiRoutes). This means that all the routes in apiRoutes will be added to the /api path. So, if we have a route in apiRoutes that looks like this: router.get('/users', (req, res) => { ... }), the full path to that route will be /api/users. +// In the same file, we have another app.use() statement that calls app.use('/auth', authRoutes). This means that all the routes in authRoutes will be added to the /auth path. So, if we have a route in authRoutes that looks like this: router.get('/login', (req, res) => { ... }), the full path to that route will be /auth/login. +router.post('/post/:id', async (req, res) => { // add comment to post (https://expressjs.com/en/4x/api.html#router.post) (https://sequelize.org/master/manual/model-querying-basics.html) try { - const newComment = { - content: req.body.content, - creator: req.session.username, - post_id: req.params.id, + const newComment = { // create new comment (https://sequelize.org/master/manual/model-querying-basics.html) (https://sequelize.org/master/manual/model-querying-basics.html) + content: req.body.content, // content from request body (https://expressjs.com/en/4x/api.html#req.body) + creator: req.session.username, // creator from session (https://expressjs.com/en/4x/api.html#req.session) (https://sequelize.org/master/manual/model-querying-basics.html) + post_id: req.params.id, // post id from request params (https://expressjs.com/en/4x/api.html#req.params) (https://sequelize.org/master/manual/model-querying-basics.html) } - await Comment.create(newComment); - res.redirect(`/post/${req.params.id}`); + await Comment.create(newComment); // create new comment (https://sequelize.org/master/manual/model-querying-basics.html) (https://sequelize.org/master/manual/model-querying-basics.html) + res.redirect(`/post/${req.params.id}`); // go back to post we just commented on (https://expressjs.com/en/4x/api.html#res.redirect) (https://sequelize.org/master/manual/model-querying-basics.html) } catch (err) { - res.status(500).send(err); + res.status(500).send(err); // send error status code (https://expressjs.com/en/4x/api.html#res.status) (https://sequelize.org/master/manual/model-querying-basics.html) } }); -// create new post -router.post('/dashboard', async (req, res) => { +// create new post (https://expressjs.com/en/4x/api.html#router.post) (https://sequelize.org/master/manual/model-querying-basics.html) for more information on how to use the create method +router.post('/dashboard', async (req, res) => { // create new post (https://expressjs.com/en/4x/api.html#router.post) (https://sequelize.org/master/manual/model-querying-basics.html) try { - const newPost = { - title: req.body.title, - content: req.body.content, - creator: req.session.username, + const newPost = { // create new post (https://sequelize.org/master/manual/model-querying-basics.html) (https://sequelize.org/master/manual/model-querying-basics.html) + title: req.body.title, // title from request body (https://expressjs.com/en/4x/api.html#req.body) + content: req.body.content, // content from request body (https://expressjs.com/en/4x/api.html#req.body) + creator: req.session.username, // creator from session (https://expressjs.com/en/4x/api.html#req.session) } - await Post.create(newPost); - res.redirect(`/dashboard`); - } catch (err) { - res.status(500).send(err); + await Post.create(newPost); // create new post (https://sequelize.org/master/manual/model-querying-basics.html) (https://sequelize.org/master/manual/model-querying-basics.html) + res.redirect(`/dashboard`); // go back to dashboard (https://expressjs.com/en/4x/api.html#res.redirect) (https://sequelize.org/master/manual/model-querying-basics.html) + } catch (err) { // send error status code (https://expressjs.com/en/4x/api.html#res.status) (https://sequelize.org/master/manual/model-querying-basics.html) + res.status(500).send(err); // send error status code (https://expressjs.com/en/4x/api.html#res.status) (https://sequelize.org/master/manual/model-querying-basics.html) } }); -// update post -router.put('/post/:id/edit', async (req, res) => { +// update post (https://expressjs.com/en/4x/api.html#router.put) (https://sequelize.org/master/manual/model-querying-basics.html) for more information on how to use the update method +router.put('/post/:id/edit', async (req, res) => { // update post (https://expressjs.com/en/4x/api.html#router.put) (https://sequelize.org/master/manual/model-querying-basics.html) try { - await Post.update( + await Post.update( // update post (https://sequelize.org/master/manual/model-querying-basics.html) (https://sequelize.org/master/manual/model-querying-basics.html) { - title: req.body.title, - content: req.body.content, + title: req.body.title, // title from request body (https://expressjs.com/en/4x/api.html#req.body) + content: req.body.content, // content from request body (https://expressjs.com/en/4x/api.html#req.body) (https://sequelize.org/master/manual/model-querying-basics.html) }, { - where: { - id: req.params.id, - creator: req.session.username, + where: { // where condition for post (https://sequelize.org/master/manual/model-querying-basics.html) (https://sequelize.org/master/manual/model-querying-basics.html) + id: req.params.id, // post id from request params (https://expressjs.com/en/4x/api.html#req.params) (https://sequelize.org/master/manual/model-querying-basics.html) + creator: req.session.username, // make sure user owns the post (https://sequelize.org/master/manual/model-querying-basics.html) (https://sequelize.org/master/manual/model-querying-basics.html) }, } ); - res.redirect(`/post/${req.params.id}`); // go back to post we just edited - } catch (err) { - res.status(500).json(err); + res.redirect(`/post/${req.params.id}`); // go back to post we just edited (https://expressjs.com/en/4x/api.html#res.redirect) (https://sequelize.org/master/manual/model-querying-basics.html) + } catch (err) { // send error status code (https://expressjs.com/en/4x/api.html#res.status) (https://sequelize.org/master/manual/model-querying-basics.html) (https://sequelize.org/master/manual/model-querying-basics.html) + res.status(500).json(err); // send error status code (https://expressjs.com/en/4x/api.html#res.status) (https://sequelize.org/master/manual/model-querying-basics.html) } }); -// delete post -router.delete('/post/:id/edit', async (req, res) => { - try { - await Post.destroy({ - where: { - id: req.params.id, +// delete post (https://expressjs.com/en/4x/api.html#router.delete) (https://sequelize.org/master/manual/model-querying-basics.html) for more information on how to use the destroy method +router.delete('/post/:id/edit', async (req, res) => { // delete post (https://expressjs.com/en/4x/api.html#router.delete) (https://sequelize.org/master/manual/model-querying-basics.html) + try { // delete post (https://sequelize.org/master/manual/model-querying-basics.html) (https://sequelize.org/master/manual/model-querying-basics.html) + await Post.destroy({ // destroy post (https://sequelize.org/master/manual/model-querying-basics.html) (https://sequelize.org/master/manual/model-querying-basics.html) + where: { // where condition for post (https://sequelize.org/master/manual/model-querying-basics.html) (https://sequelize.org/master/manual/model-querying-basics.html) + id: req.params.id, // post id from request params (https://expressjs.com/en/4x/api.html#req.params) (https://sequelize.org/master/manual/model-querying-basics.html) creator: req.session.username, // make sure user owns the post } }); diff --git a/controllers/html-routes.js b/controllers/html-routes.js index ecdb5e6..5cd5ddf 100755 --- a/controllers/html-routes.js +++ b/controllers/html-routes.js @@ -1,111 +1,111 @@ -const router = require('express').Router(); -const { Post, Comment } = require('../models'); +const router = require('express').Router(); // import express router (https://expressjs.com/en/4x/api.html#router) from 'express module' (https://www.npmjs.com/package/express) +const { Post, Comment } = require('../models'); // import Post and Comment models (https://sequelize.org/docs/v6/core-concepts/model-basics/) // render homepage - contains all user posts -router.get('/', async (req, res) => { - try { - const dbPostData = await Post.findAll({ - include: [ +router.get('/', async (req, res) => { // get method (https://expressjs.com/en/4x/api.html#router.get) + try { // try...catch statement (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch) + const dbPostData = await Post.findAll({ // findAll method (https://sequelize.org/docs/v6/core-concepts/model-basics/#findall) + include: [ // include option (https://sequelize.org/master/manual/eager-loading.html) { - model: Comment, + model: Comment, // include comments (https://sequelize.org/docs/v6/core-concepts/assocs/#one-to-many) }, ], }); - const posts = dbPostData.map((post) => { - const userPost = post.get({ plain: true }) - userPost.commentCount = userPost.comments.length; - return userPost; + const posts = dbPostData.map((post) => { // map method (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) + const userPost = post.get({ plain: true }) // get method (https://sequelize.org/docs/v6/core-concepts/model-basics/#get) + userPost.commentCount = userPost.comments.length; // count number of comments (https://sequelize.org/docs/v6/core-concepts/model-basics/#count) + return userPost; // return post with comment count added (https://sequelize.org/docs/v6/core-concepts/model-basics/#count) }); - posts.reverse(); // sort by most recent first - res.render('homepage', { - posts, - loggedIn: req.session.loggedIn, + posts.reverse(); // sort by most recent first (https://sequelize.org/docs/v6/core-concepts/model-basics/#order) + res.render('homepage', { // render homepage (https://expressjs.com/en/4x/api.html#res.render) with posts and loggedIn status + posts, // posts parameter (https://expressjs.com/en/4x/api.html#res.render) with posts and loggedIn status (https://expressjs.com/en/4x/api.html#res.render) + loggedIn: req.session.loggedIn, // loggedIn parameter (https://expressjs.com/en/4x/api.html#res.render) with posts and loggedIn status (https://expressjs.com/en/4x/api.html#res.render) }); - } catch (err) { - console.log(err); - res.status(500).json(err); + } catch (err) { // catch error (https://expressjs.com/en/4x/api.html#res.status) and render error page (https://expressjs.com/en/4x/api.html#res.render) with error message + console.log(err); // log error message (https://developer.mozilla.org/en-US/docs/Web/API/console/log) to console + res.status(500).json(err); // render error page (https://expressjs.com/en/4x/api.html#res.render) with error message } }); -// render dashboard - contains personal user posts -router.get('/dashboard', async (req, res) => { - if (!req.session.loggedIn) { - res.render('dashboard'); +// render dashboard - contains personal user posts and comments (https://expressjs.com/en/4x/api.html#res.render) +router.get('/dashboard', async (req, res) => { // get method (https://expressjs.com/en/4x/api.html#router.get) + if (!req.session.loggedIn) { // if user is not logged in (https://expressjs.com/en/4x/api.html#req.session) redirect to login page + res.render('dashboard'); // render dashboard (https://expressjs.com/en/4x/api.html#res.render) with loggedIn status (https://expressjs.com/en/4x/api.html#res.render) return; } - try { - const dbUserPostData = await Post.findAll({ - where: { - creator: req.session.username, // can't figure out getting username rn will edit later - }, - include: [ + try { // try...catch statement (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch) + const dbUserPostData = await Post.findAll({ // findAll method (https://sequelize.org/docs/v6/core-concepts/model-basics/#findall) with where clause (https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#simple-where-queries) + where: { // where clause (https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#simple-where-queries) + creator: req.session.username, // can't figure out getting username rn will edit later (https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#simple-where-queries) + }, // include option (https://sequelize.org/master/manual/eager-loading.html) + include: [ // include option (https://sequelize.org/master/manual/eager-loading.html) with comments (https://sequelize.org/docs/v6/core-concepts/assocs/#one-to-many) { - model: Comment, + model: Comment, // include comments (https://sequelize.org/docs/v6/core-concepts/assocs/#one-to-many) with where clause (https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#simple-where-queries) } ] }); - const posts = dbUserPostData.map((post) => { - const userPost = post.get({ plain: true }) - userPost.commentCount = userPost.comments.length; - return userPost; + const posts = dbUserPostData.map((post) => { // map method (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) with get method (https://sequelize.org/docs/v6/core-concepts/model-basics/#get) + const userPost = post.get({ plain: true }) // get method (https://sequelize.org/docs/v6/core-concepts/model-basics/#get) with plain option (https://sequelize.org/docs/v6/core-concepts/model-basics/#get) + userPost.commentCount = userPost.comments.length; // count number of comments (https://sequelize.org/docs/v6/core-concepts/model-basics/#count) with length property (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length) + return userPost; // return post with comment count added (https://sequelize.org/docs/v6/core-concepts/model-basics/#count) with plain option (https://sequelize.org/docs/v6/core-concepts/model-basics/#get) }); - posts.reverse(); - res.render('dashboard', { - posts, - username: req.session.username, - loggedIn: req.session.loggedIn + posts.reverse(); // sort by most recent first (https://sequelize.org/docs/v6/core-concepts/model-basics/#order) + res.render('dashboard', { // render dashboard (https://expressjs.com/en/4x/api.html#res.render) with posts and loggedIn status (https://expressjs.com/en/4x/api.html#res.render) + posts, // posts parameter (https://expressjs.com/en/4x/api.html#res.render) with posts and loggedIn status (https://expressjs.com/en/4x/api.html#res.render) + username: req.session.username, // loggedIn parameter (https://expressjs.com/en/4x/api.html#res.render) with posts and loggedIn status (https://expressjs.com/en/4x/api.html#res.render) + loggedIn: req.session.loggedIn // loggedIn parameter (https://expressjs.com/en/4x/api.html#res.render) with posts and loggedIn status (https://expressjs.com/en/4x/api.html#res.render) }); - } catch (err) { - console.log(err); - res.status(500).json(err); + } catch (err) { // catch statement (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/catch) + console.log(err); // log error to console + res.status(500).json(err); // send error status (https://expressjs.com/en/4x/api.html#res.status) } }); // render individual post page -router.get('/post/:id', async (req, res) => { - try { - const dbPostData = await Post.findByPk(req.params.id, { - include: [ +router.get('/post/:id', async (req, res) => { // get method (https://expressjs.com/en/4x/api.html#router.get) + try { // try...catch statement (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch) + const dbPostData = await Post.findByPk(req.params.id, { // findByPk method (https://sequelize.org/docs/v6/core-concepts/model-basics/#findbyid) with include option (https://sequelize.org/master/manual/eager-loading.html) + include: [ // include option (https://sequelize.org/master/manual/eager-loading.html) { - model: Comment, + model: Comment, // include comments (https://sequelize.org/docs/v6/core-concepts/assocs/#one-to-many) } ] }); - const post = dbPostData.get({ plain: true }); - res.render('post', { - post, - username: req.session.username, - loggedIn: req.session.loggedIn, + const post = dbPostData.get({ plain: true }); // get method (https://sequelize.org/docs/v6/core-concepts/model-basics/#get) with plain option (https://sequelize.org/docs/v6/core-concepts/model-basics/#get) + res.render('post', { // render post (https://expressjs.com/en/4x/api.html#res.render) with post and loggedIn status (https://expressjs.com/en/4x/api.html#res.render) + post, // post parameter (https://expressjs.com/en/4x/api.html#res.render) with post and loggedIn status (https://expressjs.com/en/4x/api.html#res.render) + username: req.session.username, // loggedIn parameter (https://expressjs.com/en/4x/api.html#res.render) with post and loggedIn status (https://expressjs.com/en/4x/api.html#res.render) + loggedIn: req.session.loggedIn, // loggedIn parameter (https://expressjs.com/en/4x/api.html#res.render) with post and loggedIn status (https://expressjs.com/en/4x/api.html#res.render) }); - } catch (err) { - res.status(500).json(err); + } catch (err) { // catch statement (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/catch) + res.status(500).json(err); // send error status (https://expressjs.com/en/4x/api.html#res.status) } }); -// render update page for posts -router.get('/post/:id/edit', async (req, res) => { - try { - const dbPostData = await Post.findByPk(req.params.id); - const post = dbPostData.get({ plain: true }); - if (post.creator !== req.session.username) { - res.redirect('/'); +// render update page for posts (https://expressjs.com/en/4x/api.html#res.render) with post and loggedIn status (https://expressjs.com/en/4x/api.html#res.render) +router.get('/post/:id/edit', async (req, res) => { // get method (https://expressjs.com/en/4x/api.html#router.get) + try { // try...catch statement (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch) + const dbPostData = await Post.findByPk(req.params.id); // findByPk method (https://sequelize.org/docs/v6/core-concepts/model-basics/#findbyid) + const post = dbPostData.get({ plain: true }); // get method (https://sequelize.org/docs/v6/core-concepts/model-basics/#get) with plain option (https://sequelize.org/docs/v6/core-concepts/model-basics/#get) + if (post.creator !== req.session.username) { // if statement (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if) with redirect (https://expressjs.com/en/4x/api.html#res.redirect) + res.redirect('/'); // redirect (https://expressjs.com/en/4x/api.html#res.redirect) } - res.render('update-post', { - post, - loggedIn: req.session.loggedIn + res.render('update-post', { // render update-post (https://expressjs.com/en/4x/api.html#res.render) with post and loggedIn status (https://expressjs.com/en/4x/api.html#res.render) + post, // post parameter (https://expressjs.com/en/4x/api.html#res.render) with post and loggedIn status (https://expressjs.com/en/4x/api.html#res.render) + loggedIn: req.session.loggedIn // loggedIn parameter (https://expressjs.com/en/4x/api.html#res.render) with post and loggedIn status (https://expressjs.com/en/4x/api.html#res.render) }); - } catch (err) { - res.status(500).json(err); + } catch (err) { // catch statement (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/catch) + res.status(500).json(err); // send error status (https://expressjs.com/en/4x/api.html#res.status) } }); -// renders login page -router.get('/login', (req, res) => { - if (req.session.loggedIn) { - res.redirect('/'); +// renders login page (https://expressjs.com/en/4x/api.html#res.render) with loggedIn status (https://expressjs.com/en/4x/api.html#res.render) if user is logged in (https://expressjs.com/en/4x/api.html#req.session) +router.get('/login', (req, res) => { // get method (https://expressjs.com/en/4x/api.html#router.get) with loggedIn status (https://expressjs.com/en/4x/api.html#res.render) + if (req.session.loggedIn) { // if statement (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if) with redirect (https://expressjs.com/en/4x/api.html#res.redirect) + res.redirect('/'); // redirect (https://expressjs.com/en/4x/api.html#res.redirect) with loggedIn status (https://expressjs.com/en/4x/api.html#res.render) return; } - res.render('login'); + res.render('login'); // render login (https://expressjs.com/en/4x/api.html#res.render) with loggedIn status (https://expressjs.com/en/4x/api.html#res.render) }); -module.exports = router; \ No newline at end of file +module.exports = router; // export router (https://expressjs.com/en/4x/api.html#router) with loggedIn status (https://expressjs.com/en/4x/api.html#res.render) with loggedOut status (https \ No newline at end of file diff --git a/controllers/index.js b/controllers/index.js index 3ee7806..79497d4 100755 --- a/controllers/index.js +++ b/controllers/index.js @@ -1,9 +1,9 @@ -const router = require('express').Router(); +const router = require('express').Router(); // import express router (https://expressjs.com/en/4x/api.html#router) -const apiRoutes = require('./api-routes'); -const htmlRoutes = require('./html-routes'); +const apiRoutes = require('./api-routes'); // import api routes (default is ./api-routes) +const htmlRoutes = require('./html-routes'); // import html routes (default is ./html-routes) -router.use(htmlRoutes); -router.use(apiRoutes); +router.use(htmlRoutes); // use html routes +router.use(apiRoutes); // use api routes -module.exports = router; \ No newline at end of file +module.exports = router; // export router (https://expressjs.com/en/4x/api.html#router) \ No newline at end of file diff --git a/db/schema.sql b/db/schema.sql index 8c792e1..3610e04 100755 --- a/db/schema.sql +++ b/db/schema.sql @@ -1,3 +1,3 @@ -DROP DATABASE IF EXISTS blog_db; +DROP DATABASE IF EXISTS blog_db; CREATE DATABASE blog_db; \ No newline at end of file diff --git a/models/Comment.js b/models/Comment.js index a781d10..e2cfd06 100755 --- a/models/Comment.js +++ b/models/Comment.js @@ -1,9 +1,9 @@ -const { Model, DataTypes } = require('sequelize'); -const sequelize = require('../config/connection'); +const { Model, DataTypes } = require('sequelize'); // import sequelize (https://sequelize.org/docs/v6/core-concepts/model-basics/) +const sequelize = require('../config/connection'); -class Comment extends Model {} +class Comment extends Model {} // Comment model (https://sequelize.org/docs/v6/core-concepts/model-basics/) -Comment.init( +Comment.init( { id: { type: DataTypes.INTEGER, @@ -27,20 +27,20 @@ Comment.init( allowNull: false, defaultValue: DataTypes.NOW, // records date/time at time of creation }, - post_id: { + post_id: { // foreign key for post id (https://sequelize.org/docs/v6/core-concepts/assocs/#foreign-keys) type: DataTypes.INTEGER, allowNull: false, - references: { + references: { model: 'post', - key: 'id', + key: 'id', // foreign key for post id } } }, { - sequelize, - freezeTableName: true, - underscored: true, - modelName: 'comment', + sequelize, // for connecting to db with sequelize (default is ./config/connection.js) + freezeTableName: true, // for connecting to db with sequelize (default is ./config/connection.js) + underscored: true, // for connecting to db with sequelize (default is ./config/connection.js) + modelName: 'comment', // for connecting to db with sequelize (default is ./config/connection.js) } ); diff --git a/models/Post.js b/models/Post.js index a305c7c..f695529 100755 --- a/models/Post.js +++ b/models/Post.js @@ -1,9 +1,9 @@ -const { Model, DataTypes } = require('sequelize'); -const sequelize = require('../config/connection'); +const { Model, DataTypes } = require('sequelize'); // import sequelize (https://sequelize.org/docs/v6/core-concepts/model-basics/) +const sequelize = require('../config/connection'); // import connection object from connection.js (https://sequelize.org/docs/v6/core-concepts/connections-and-transactions/) -class Post extends Model {} +class Post extends Model {} // Post model (https://sequelize.org/docs/v6/core-concepts/model-basics/) -Post.init( +Post.init( // Post model (https://sequelize.org/docs/v6/core-concepts/model-basics/) { id: { type: DataTypes.INTEGER, @@ -19,7 +19,7 @@ Post.init( type: DataTypes.STRING, allowNull: false, }, - creator: { + creator: { type: DataTypes.STRING, references: { model: 'user', diff --git a/models/User.js b/models/User.js index 1efe4a3..9a41a30 100755 --- a/models/User.js +++ b/models/User.js @@ -1,14 +1,14 @@ -const { Model, DataTypes } = require('sequelize'); -const sequelize = require('../config/connection'); -const bcrypt = require('bcrypt'); +const { Model, DataTypes } = require('sequelize'); // import sequelize (https://sequelize.org/docs/v6/core-concepts/model-basics/) +const sequelize = require('../config/connection'); // import connection object from connection.js (https://sequelize.org/docs/v6/core-concepts/connections-and-transactions/) +const bcrypt = require('bcrypt'); // import bcrypt (https://www.npmjs.com/package/bcrypt) -class User extends Model { - checkPassword(loginPw) { - return bcrypt.compareSync(loginPw, this.password); +class User extends Model { // User model (https://sequelize.org/docs/v6/core-concepts/model-basics/) + checkPassword(loginPw) { // checkPassword method (https://sequelize.org/docs/v6/core-concepts/model-basics/#custom-methods) + return bcrypt.compareSync(loginPw, this.password); // compareSync method (https://www.npmjs.com/package/bcrypt) } } -User.init( +User.init( // User model (https://sequelize.org/docs/v6/core-concepts/model-basics/) { id: { type: DataTypes.INTEGER, @@ -24,20 +24,20 @@ User.init( password: { type: DataTypes.TEXT, allowNull: false, - validate: { - len: [8], + validate: { // password validation (https://sequelize.org/docs/v6/core-concepts/model-basics/#validations) + len: [8], // password must be at least 8 characters long }, }, }, { - hooks: { - beforeCreate: async (newUserData) => { - newUserData.password = await bcrypt.hash(newUserData.password, 10); + hooks: { // hooks (https://sequelize.org/master/manual/hooks.html) + beforeCreate: async (newUserData) => { // beforeCreate hook (https://sequelize.org/master/manual/hooks.html) + newUserData.password = await bcrypt.hash(newUserData.password, 10); // hash password (https://www.npmjs.com/package/bcrypt) return newUserData; }, }, sequelize, - freezeTableName: true, + freezeTableName: true, underscored: true, modelName: 'user', } diff --git a/models/index.js b/models/index.js index 278e9ab..7897e61 100755 --- a/models/index.js +++ b/models/index.js @@ -1,21 +1,21 @@ -const User = require('./User'); -const Post = require('./Post'); -const Comment = require('./Comment'); +const User = require('./User'); // import User model (https://sequelize.org/docs/v6/core-concepts/model-basics/) +const Post = require('./Post'); // import Post model (https://sequelize.org/docs/v6/core-concepts/model-basics/) +const Comment = require('./Comment'); // import Comment model (https://sequelize.org/docs/v6/core-concepts/model-basics/) -User.hasMany(Post, { - foreignKey: 'username', +User.hasMany(Post, { // User has many Posts (https://sequelize.org/docs/v6/core-concepts/assocs/#one-to-many) + foreignKey: 'username', // foreign key for username (https://sequelize.org/docs/v6/core-concepts/assocs/#foreign-keys) }); -Post.belongsTo(User, { - foreignKey: 'username', +Post.belongsTo(User, { // Post belongs to User (https://sequelize.org/docs/v6/core-concepts/assocs/#one-to-many) + foreignKey: 'username', // foreign key for username (https://sequelize.org/docs/v6/core-concepts/assocs/#foreign-keys) }); -Comment.belongsTo(User, { - foreignKey: 'username', +Comment.belongsTo(User, { // Comment belongs to User (https://sequelize.org/docs/v6/core-concepts/assocs/#one-to-many) + foreignKey: 'username', // foreign key for username (https://sequelize.org/docs/v6/core-concepts/assocs/#foreign-keys) }); -Post.hasMany(Comment, { - foreignKey: 'post_id', +Post.hasMany(Comment, { // Post has many Comments (https://sequelize.org/docs/v6/core-concepts/assocs/#one-to-many) + foreignKey: 'post_id', // foreign key for post id (https://sequelize.org/docs/v6/core-concepts/assocs/#foreign-keys) }); -module.exports = { User, Post, Comment }; \ No newline at end of file +module.exports = { User, Post, Comment }; // export User, Post, and Comment models (https://sequelize.org/docs/v6/core-concepts/model-basics/) \ No newline at end of file diff --git a/public/css/bulma.css b/public/css/bulma.css index 1012e65..0ec7235 100755 --- a/public/css/bulma.css +++ b/public/css/bulma.css @@ -1 +1,5 @@ -@import "https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css" \ No newline at end of file + +/* import the bulma css */ +@import "https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css" + + diff --git a/public/css/style.css b/public/css/style.css index ce72d64..8f2f850 100755 --- a/public/css/style.css +++ b/public/css/style.css @@ -1,5 +1,5 @@ -html { - background-color: #5f76db; +html { + background-color: #5f76db; } main { @@ -45,4 +45,5 @@ main { font: inherit; cursor: pointer; outline: inherit; -} \ No newline at end of file +} + diff --git a/public/img/preview.png b/public/img/preview.png deleted file mode 100755 index 8fb75ab..0000000 Binary files a/public/img/preview.png and /dev/null differ diff --git a/public/js/app.js b/public/js/app.js index 61c06ed..dc6fbad 100755 --- a/public/js/app.js +++ b/public/js/app.js @@ -1,22 +1,28 @@ -const newPostButton = document.querySelector(".new-post-btn"); -const newPostForm = document.querySelector(".new-post-form"); -const cancelButton = document.createElement("button"); +// public\js\app.js file for new post button and new post form functionality for logged in users only -cancelButton.textContent = "cancel"; -cancelButton.classList.add("cancel-btn"); -cancelButton.classList.add("button"); -cancelButton.style.display = "none"; +const newPostButton = document.querySelector(".new-post-btn"); // select the new post button +const newPostForm = document.querySelector(".new-post-form"); // select the new post form +const cancelButton = document.createElement("button"); // create the cancel button -newPostButton.addEventListener("click", function() { - newPostButton.style.display = "none"; +cancelButton.textContent = "cancel"; // set the text of the cancel button +cancelButton.classList.add("cancel-btn"); // add the cancel button class +cancelButton.classList.add("button"); // add the button class +cancelButton.style.display = "none"; // hide the cancel button + +// show and hide new post form and cancel button +newPostButton.addEventListener("click", function() { + newPostButton.style.display = "none"; cancelButton.style.display = "block"; newPostForm.style.display = "block"; }); + +// show and hide new post form and cancel button cancelButton.addEventListener("click", function() { newPostButton.style.display = "block"; cancelButton.style.display = "none"; newPostForm.style.display = "none"; }); +// insert cancel button before new post button newPostButton.parentNode.insertBefore(cancelButton, newPostButton.nextSibling); \ No newline at end of file diff --git a/seeds/postData.json b/seeds/postData.json index 0eeb986..bdbae85 100755 --- a/seeds/postData.json +++ b/seeds/postData.json @@ -7,11 +7,11 @@ { "title": "ChatGPT!", "content": "Currently using open AI API to get information about traveling to the Seven Wonders of the World", - "creator": "coderco" + "creator": "coder" }, { "title": "The Solar Eclipse", "content": "Here is a link to a picture from Mazatlan Sinaloa", - "creator": "Coderco" + "creator": "Coder" } ] \ No newline at end of file diff --git a/seeds/seed.js b/seeds/seed.js index 5350156..62390e7 100755 --- a/seeds/seed.js +++ b/seeds/seed.js @@ -1,11 +1,12 @@ -const sequelize = require('../config/connection'); -const { User, Post, Comment } = require('../models'); +const sequelize = require('../config/connection'); // Import the connection object from config/connection.js +const { User, Post, Comment } = require('../models'); // Import the User, Post, and Comment models -const userData = require('./userData.json'); -const postData = require('./postData.json'); -const commentData = require('./commentData.json'); +const userData = require('./userData.json'); // Import the userData.json file +const postData = require('./postData.json'); // Import the postData.json file +const commentData = require('./commentData.json'); // Import the commentData.json file -const seedDatabase = async () => { +// seed database function +const seedDatabase = async () => { await sequelize.sync({ force: true }); await User.bulkCreate(userData, { diff --git a/server.js b/server.js index 98127e7..fee570c 100755 --- a/server.js +++ b/server.js @@ -1,83 +1,84 @@ -const path = require('path'); -const express = require('express'); -const session = require('express-session'); -const exphbs = require('express-handlebars'); +const path = require('path'); // for file paths +const express = require('express'); // for server +const session = require('express-session'); // for sessions +const exphbs = require('express-handlebars'); // for handlebars const methodOverride = require('method-override'); // for handling PUT requests // Initializes Sequelize with session store -const SequelizeStore = require('connect-session-sequelize')(session.Store); +const SequelizeStore = require('connect-session-sequelize')(session.Store); // for storing sessions in db store (sequelize) instead of memory store (cookie) -const app = express(); -const PORT = process.env.PORT || 3001; +const app = express(); // initializes express +const PORT = process.env.PORT || 3001; // sets port to 3001 if not set in environment -const routes = require('./controllers'); -const sequelize = require('./config/connection'); +const routes = require('./controllers'); // routes for server and client side files (default is ./controllers/index.js) +const sequelize = require('./config/connection'); // for connecting to db with sequelize (default is ./config/connection.js) -app.use(methodOverride('_method')); +app.use(methodOverride('_method')); // for handling PUT requests (method-override) // Sets up session and connect to our Sequelize db -const sess = { - secret: 'Super secret secret', - cookie: { - maxAge: 30 * 60 * 1000, // 30 minutes - httpOnly: true, - secure: false, - sameSite: 'strict', - }, - resave: false, - saveUninitialized: true, - expires: new Date(Date.now() + 30 * 60 * 1000), // 30 minutes - // Sets up session store - store: new SequelizeStore({ - db: sequelize, +const sess = { // session settings for server and client side files (default is ./controllers/index.js) + secret: 'Super secret secret', // secret key for session cookie + cookie: { // session cookie settings for server and client side files (default is ./controllers/index.js) + maxAge: 30 * 60 * 1000, // 30 minutes (default is 10 minutes) + httpOnly: true, // default is true (https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#HTTP_only) + secure: false, // default is true (https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_attribute) + sameSite: 'strict', // default is 'lax' (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) + }, // session cookie settings for server and client side files (default is ./controllers/index.js) + resave: false, // session cookie settings for server and client side files (default is ./controllers/index.js) + saveUninitialized: true, // session cookie settings for server and client side files (default is ./controllers/index.js) + expires: new Date(Date.now() + 30 * 60 * 1000), // 30 minutes (30 * 60 * 1000) = 30 minutes (default is 10 minutes) + // Sets up session store for server and client side files (default is ./controllers/index.js) + store: new SequelizeStore({ // session store settings for server and client side files (default is ./controllers/index.js) + db: sequelize, // for connecting to db with sequelize (default is ./config/connection.js) }), }; -app.use(session(sess)); +app.use(session(sess)); // session settings for server and client side files (default is ./controllers/index.js) -const hbs = exphbs.create(); +const hbs = exphbs.create(); // initializes handlebars -app.engine('handlebars', hbs.engine); -app.set('view engine', 'handlebars'); +app.engine('handlebars', hbs.engine); // engine for handlebars (default is ./controllers/index.js) +app.set('view engine', 'handlebars'); // view engine for handlebars (default is ./controllers/index.js) -app.use(express.json()); -app.use(express.urlencoded({ extended: false })); -app.use(express.static(path.join(__dirname, 'public'))); +app.use(express.json()); // for parsing json data (https://expressjs.com/en/api.html#express.json) +app.use(express.urlencoded({ extended: false })); // for parsing url encoded data (https://expressjs.com/en/api.html#express.urlencoded) +app.use(express.static(path.join(__dirname, 'public'))); // for serving static files (https://expressjs.com/en/starter/static-files.html) -app.use(routes); +app.use(routes); // routes for server and client side files (default is ./controllers/index.js) -app.use((req, res, next) => { +app.use((req, res, next) => { // middleware for checking if user is logged in or authenticated via session store (https://expressjs.com/en/guide/behind-proxies.html) // List of paths that do not require authentication - const authFreePaths = ['/login', '/signup', '/logout', '/css/', '/js/']; - if (!req.session.userId && !authFreePaths.some(path => req.path.startsWith(path))) { - return res.redirect('/login'); + const authFreePaths = ['/login', '/signup', '/logout', '/css/', '/js/']; // paths that do not require authentication (https://expressjs.com/en/guide/behind-proxies.html) + if (!req.session.userId && !authFreePaths.some(path => req.path.startsWith(path))) { // if user is not logged in and path is not in authFreePaths list then redirect to login + return res.redirect('/login'); // redirect to login page (https://expressjs.com/en/guide/behind-proxies.html) } - next(); + next(); // next middleware (https://expressjs.com/en/guide/behind-proxies.html) }); // middleware for checking if session has expired -app.use((req, res, next) => { - if (req.session.expires && Date.now() > req.session.expires) { - req.session.destroy(() => { - res.redirect('/login'); +app.use((req, res, next) => { // middleware for checking if session has expired (https://expressjs.com/en/guide/behind-proxies.html) + if (req.session.expires && Date.now() > req.session.expires) { // if session has expired then destroy session and redirect to login + req.session.destroy(() => { // destroy session and redirect to login page (https://expressjs.com/en/guide/behind-proxies.html) + res.redirect('/login'); // redirect to login page (https://expressjs.com/en/guide/behind-proxies.html) }); - } else { + } else { // if session has not expired then next middleware (https://expressjs.com/en/guide/behind-proxies.html) next(); } }); // refreshes expiration time so site doesn't log out active users -app.use((req, res, next) => { - if (req.session.expires) { - const extendedExpirationTime = new Date(Date.now() + 30 * 60 * 1000); - req.session.expires = extendedExpirationTime; +app.use((req, res, next) => { // middleware for checking if session has expired (https://expressjs.com/en/guide/behind-proxies.html) + if (req.session.expires) { + const extendedExpirationTime = new Date(Date.now() + 30 * 60 * 1000); // 30 minutes (30 * 60 * 1000) = 30 minutes (default is 10 minutes) + req.session.expires = extendedExpirationTime; // refreshes expiration time so site doesn't log out active users } - next(); + next(); // next middleware (https://expressjs.com/en/guide/behind-proxies.html) }); -sequelize.sync({ force: false }).then(() => { - app.listen(PORT, () => - console.log( + // middleware for checking if user is logged in or authenticated via session store (https://expressjs.com/en/guide/behind-proxies.html) +sequelize.sync({ force: false }).then(() => { // syncs sequelize with db (default is ./config/connection.js) + app.listen(PORT, () => // listens on port 3001 (default is 3001) + console.log( `\nServer running on port ${PORT}. Visit http://localhost:${PORT} and create an account!` ) ); diff --git a/views/update-post.handlebars b/views/update-post.handlebars index 7615d90..7a0306b 100755 --- a/views/update-post.handlebars +++ b/views/update-post.handlebars @@ -1,4 +1,4 @@ -
+