├── .gitignore ├── .gitpod.yml ├── README.md ├── connection.js ├── freeCodeCamp └── fcctesting.js ├── nodemon.json ├── package-lock.json ├── package.json ├── public ├── client.js └── style.css ├── sample.env ├── server.js └── views └── pug ├── chat.pug ├── index.pug └── profile.pug /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | image: gitpod/workspace-node-lts 2 | 3 | ports: 4 | - port: 3000 5 | onOpen: open-preview 6 | visibility: public 7 | 8 | tasks: 9 | - init: npm install 10 | command: npm run start 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Advanced Node and Express 2 | 3 | This is the boilerplate for the Advanced Node and Express lessons. Instructions for the lessons start at https://www.freecodecamp.org/learn/quality-assurance/advanced-node-and-express/ 4 | -------------------------------------------------------------------------------- /connection.js: -------------------------------------------------------------------------------- 1 | // Do not change this file 2 | require('dotenv').config(); 3 | const { MongoClient } = require('mongodb'); 4 | 5 | async function main(callback) { 6 | const URI = process.env.MONGO_URI; // Declare MONGO_URI in your .env file 7 | const client = new MongoClient(URI, { useNewUrlParser: true, useUnifiedTopology: true }); 8 | 9 | try { 10 | // Connect to the MongoDB cluster 11 | await client.connect(); 12 | 13 | // Make the appropriate DB calls 14 | await callback(client); 15 | 16 | } catch (e) { 17 | // Catch any errors 18 | console.error(e); 19 | throw new Error('Unable to Connect to Database') 20 | } 21 | } 22 | 23 | module.exports = main; -------------------------------------------------------------------------------- /freeCodeCamp/fcctesting.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * 5 | * 6 | * 7 | * 8 | * 9 | * 10 | * 11 | * 12 | * 13 | * DO NOT EDIT THIS FILE 14 | * For FCC testing purposes! 15 | * 16 | * 17 | * 18 | * 19 | * 20 | * 21 | * 22 | * 23 | * 24 | * 25 | * 26 | */ 27 | 28 | /* 29 | * THIS FILE IS FOR freeCodeCamp TO BE ABLE TO TEST YOUR CODE PROPERLY 30 | * 31 | * ~DO NOT EDIT!~ 32 | * 33 | */ 34 | 35 | "use strict"; 36 | 37 | const fs = require("fs"); 38 | 39 | const allowedOrigins = [ 40 | /^https?:\/\/([\w-]+\.)*freecodecamp.org/, 41 | /^https?:\/\/([\w-]+\.)*freecodecamp.dev/, 42 | /^https:\/\/([\w-]+\.)*gitpod.io/, 43 | /^https:\/\/([\w-]+\.)*github.dev/, 44 | /^http:\/\/localhost:\d+/, 45 | ]; 46 | 47 | module.exports = function (app) { 48 | app.use(function (req, res, next) { 49 | const origin = req.get("origin"); 50 | if (allowedOrigins.some((regex) => regex.test(origin))) { 51 | res.setHeader("Access-Control-Allow-Origin", origin); 52 | console.log(origin); 53 | } 54 | 55 | res.setHeader("Access-Control-Allow-Credentials", true); 56 | next(); 57 | }); 58 | 59 | app.route("/_api/app").get((req, res) => { 60 | console.log("requested"); 61 | const appClone = { ...app }; 62 | res.json(appClone); 63 | }); 64 | 65 | app.route("/_api/server.js").get(function (req, res, next) { 66 | console.log("requested"); 67 | fs.readFile(process.cwd() + "/server.js", function (err, data) { 68 | if (err) return next(err); 69 | res.send(data.toString()); 70 | }); 71 | }); 72 | 73 | app.route("/_api/routes.js").get(function (req, res, next) { 74 | console.log("requested"); 75 | fs.readFile(process.cwd() + "/routes.js", function (err, data) { 76 | if (err) return next(err); 77 | res.send(data.toString()); 78 | }); 79 | }); 80 | 81 | app.route("/_api/auth.js").get(function (req, res, next) { 82 | console.log("requested"); 83 | fs.readFile(process.cwd() + "/auth.js", function (err, data) { 84 | if (err) return next(err); 85 | res.send(data.toString()); 86 | }); 87 | }); 88 | 89 | app.route("/_api/package.json").get(function (req, res, next) { 90 | console.log("requested"); 91 | fs.readFile(process.cwd() + "/package.json", "utf-8", function (err, data) { 92 | if (err) return next(err); 93 | res.json(JSON.parse(data)); 94 | }); 95 | }); 96 | 97 | app.get("/_api/app-info", function (req, res) { 98 | var hs = Object.keys(res._headers).filter( 99 | (h) => !h.match(/^access-control-\w+/) 100 | ); 101 | var hObj = {}; 102 | hs.forEach((h) => { 103 | hObj[h] = res._headers[h]; 104 | }); 105 | delete res._headers["strict-transport-security"]; 106 | res.json({ headers: hObj }); 107 | }); 108 | 109 | app.get("/_api/app-stack", (req, res) => { 110 | console.log("requested"); 111 | const stack = app._router.stack; 112 | res.json(JSON.stringify(stack)); 113 | }); 114 | }; 115 | -------------------------------------------------------------------------------- /nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "restartable": "rs", 3 | "ignore": [ 4 | ".git", 5 | "node_modules/**/node_modules" 6 | ], 7 | "verbose": true, 8 | "watch": [ 9 | "./views/pug/*", 10 | "./server.js", 11 | "./auth.js", 12 | "./routes.js", 13 | "./public/*" 14 | ], 15 | "env": { 16 | "NODE_ENV": "development" 17 | }, 18 | "ext": "js,json,pug,css" 19 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fcc-advanced-node-and-express", 3 | "author": "http://github.com/JosephLivengood", 4 | "version": "0.0.1", 5 | "description": "What am I about?", 6 | "main": "server.js", 7 | "scripts": { 8 | "start": "node server.js", 9 | "dev": "nodemon server.js" 10 | }, 11 | "dependencies": { 12 | "bcrypt": "~5.0.0", 13 | "connect-mongo": "~3.2.0", 14 | "cookie-parser": "~1.4.5", 15 | "dotenv": "^8.2.0", 16 | "express": "^4.16.1", 17 | "express-session": "~1.17.1", 18 | "mongodb": "^3.6.1", 19 | "passport": "^0.4.1", 20 | "passport-github": "~1.1.0", 21 | "passport-local": "~1.0.0", 22 | "passport.socketio": "~3.7.0", 23 | "pug": "~3.0.0", 24 | "socket.io": "~2.3.0" 25 | }, 26 | "keywords": [ 27 | "node", 28 | "express", 29 | "pug", 30 | "passport", 31 | "socketio" 32 | ], 33 | "license": "MIT", 34 | "devDependencies": { 35 | "nodemon": "^2.0.4" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /public/client.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | // Form submittion with new message in field with id 'm' 3 | $('form').submit(function () { 4 | var messageToSend = $('#m').val(); 5 | 6 | $('#m').val(''); 7 | return false; // prevent form submit from refreshing page 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /public/style.css: -------------------------------------------------------------------------------- 1 | .border { 2 | border-style: inset; 3 | border-width: 1px; 4 | margin: 10px; 5 | } 6 | 7 | .center { 8 | text-align: center; 9 | margin-left: auto; 10 | margin-right: auto; 11 | } 12 | 13 | div > input { 14 | margin: 0.5rem; 15 | } 16 | 17 | .login { 18 | border: solid 2px #777; 19 | width: 50%; 20 | background-color: aliceblue; 21 | } 22 | 23 | a.text { 24 | text-decoration: none; 25 | font-weight: 700; 26 | } 27 | 28 | form { 29 | padding: 3px; 30 | width: 500px; 31 | } 32 | 33 | form input { 34 | background-color: #eee; 35 | border: green solid 2px; 36 | padding: 10px; 37 | width: 90%; 38 | margin-right: .5%; 39 | } 40 | 41 | form button { 42 | width: 9%; 43 | background: rgb(130, 224, 255); 44 | border: none; 45 | padding: 10px; 46 | } 47 | 48 | #messages { 49 | list-style-type: none; 50 | text-align: left; 51 | margin: 0; 52 | padding: 0; 53 | height: 20em; 54 | overflow: scroll; 55 | overflow-x: hidden; 56 | } 57 | 58 | #messages li { 59 | padding: 5px 10px; 60 | } 61 | 62 | #messages li:nth-child(odd) { 63 | background: #eee; 64 | } -------------------------------------------------------------------------------- /sample.env: -------------------------------------------------------------------------------- 1 | PORT=8080 2 | NODE_ENV=development 3 | MONGO_URI='' -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | require('dotenv').config(); 3 | const express = require('express'); 4 | const myDB = require('./connection'); 5 | const fccTesting = require('./freeCodeCamp/fcctesting.js'); 6 | 7 | const app = express(); 8 | 9 | fccTesting(app); //For FCC testing purposes 10 | app.use('/public', express.static(process.cwd() + '/public')); 11 | app.use(express.json()); 12 | app.use(express.urlencoded({ extended: true })); 13 | 14 | app.route('/').get((req, res) => { 15 | 16 | }); 17 | 18 | const PORT = process.env.PORT || 3000; 19 | app.listen(PORT, () => { 20 | console.log('Listening on port ' + PORT); 21 | }); 22 | -------------------------------------------------------------------------------- /views/pug/chat.pug: -------------------------------------------------------------------------------- 1 | html 2 | head 3 | title FCC Advanced Node and Express 4 | meta(name='description', content='Home page') 5 | meta(charset='utf-8') 6 | meta(http-equiv='X-UA-Compatible', content='IE=edge') 7 | meta(name='viewport', content='width=device-width, initial-scale=1') 8 | link(rel='stylesheet', href='/public/style.css') 9 | body 10 | h1.border.center FCC Advanced Node and Express 11 | h2.center Socket.IO Chat Room 12 | .chat.center 13 | p#num-users 14 | .chat-box 15 | ul#messages 16 | form(action='') 17 | input#m(autocomplete='off') 18 | button Send 19 | a#logout(href='/logout') Logout 20 | script(src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js', integrity='sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=', crossorigin='anonymous') 21 | 22 | script(async, defer, src='/public/client.js') -------------------------------------------------------------------------------- /views/pug/index.pug: -------------------------------------------------------------------------------- 1 | html 2 | head 3 | title FCC Advanced Node and Express 4 | meta(name='description', content='Home page') 5 | meta(charset='utf-8') 6 | meta(http-equiv='X-UA-Compatible', content='IE=edge') 7 | meta(name='viewport', content='width=device-width, initial-scale=1') 8 | link(rel='stylesheet', href='/public/style.css') 9 | body 10 | h1.border.center FCC Advanced Node and Express 11 | h2.center#pug-success-message 12 | | Looks like this page is being rendered from Pug into HTML! 13 | | #{title} 14 | p#pug-variable=message 15 | 16 | 17 | 18 | if showLogin 19 | hr 20 | h2.center Login Form 21 | form(action='/login', method='post').center 22 | div 23 | label Username: 24 | input(type='text', name='username') 25 | div 26 | label Password: 27 | input(type='password', name='password') 28 | div 29 | input(type='submit', value='Log In') 30 | 31 | if showRegistration 32 | hr 33 | h2.center Registration Form 34 | form(action='/register', method='post').center 35 | div 36 | label Username: 37 | input(type='text', name='username') 38 | div 39 | label Password: 40 | input(type='password', name='password') 41 | div 42 | input(type='submit', value='Register') 43 | 44 | if showSocialAuth 45 | hr 46 | h2.center Social Login 47 | .login.center 48 | a(href='/auth/github').text Login with Github! -------------------------------------------------------------------------------- /views/pug/profile.pug: -------------------------------------------------------------------------------- 1 | html 2 | head 3 | title FCC Advanced Node and Express 4 | meta(name='description', content='Profile') 5 | meta(charset='utf-8') 6 | meta(http-equiv='X-UA-Compatible', content='IE=edge') 7 | meta(name='viewport', content='width=device-width, initial-scale=1') 8 | link(rel='stylesheet', href='/public/style.css') 9 | body 10 | h1.border.center FCC Advanced Node and Express Profile 11 | --------------------------------------------------------------------------------