Express.js

Node.js - Twitter Clone Coding // Login System

selene park 2021. 3. 30. 07:19

1. Middleware : Redirecting the user it not logged in 

 

 

 

middleware.js

exports.requireLogin=(req,res, next) =>{
    if(req.session && req.session.user){
        return next();
    }else{
        return res.redirect('/login');
    }
}

app.js

const express = require('express');
const app = express();
const port = 3003;
const middleware = require('./middleware');//it means that current folder is equal .



const server = app.listen(port, ()=>{//callback 함수 
    console.log("Server listening on port" + port);
});

//서버에 알려주기
app.set("view engine", "pug");
app.set("views", "views");


//get(1,2,3) -> 1,2,3... 순서대로 execute
app.get("/", middleware.requireLogin, (req, res, next)=>{//it means that / is equal views 
    var payload={
        pageTitle:"Home"
    }
    res.status(200).render("home",payload); // 이게 views/home.pug 
})

 

2. Adding the login route

 

loginRoutes.js

const express = require('express');
const app = express();
const router = express.Router();

//서버에 알려주기
app.set("view engine", "pug");
app.set("views", "views");


//get(1,2,3) -> 1,2,3... 순서대로 execute
router.get("/", (req, res, next)=>{//it means that / is equal views, top level 
   
    res.status(200).render("login"); // 이게 views/home.pug 
})

module.exports = router;

app.js

const express = require('express');
const app = express();
const port = 3003;
const middleware = require('./middleware');//it means that current folder is equal .



const server = app.listen(port, ()=>{//callback 함수 
    console.log("Server listening on port" + port);
});

//서버에 알려주기
app.set("view engine", "pug");
app.set("views", "views");


// Routes
const loginRoute = require('./routes/loginRoutes');

app.use("/login", loginRoute);



//get(1,2,3) -> 1,2,3... 순서대로 execute
app.get("/", middleware.requireLogin, (req, res, next)=>{//it means that / is equal views 
    var payload={
        pageTitle:"Home"
    }
    res.status(200).render("home",payload); // 이게 views/home.pug 
})

3. Creating the login page

 

 

login-layout.png

<!doctype html>
html(lang="en")
    head
        meta(charset="UTF-8")
        meta(http-equiv="X-UA-Compatible", content="IE=edge")
        meta(name="viewport", content="width=device-width, initial-scale=1.0")
        title Login Page
    body 
        .wrapper 
            block content 
            

login.pug

extends layouts/login-layout.pug 

block content 
    .loginContainer 
        h1 Login 
        form(action="post")
            input(type="text", name="logUsername", placeholder ="Username or email", required="") 
            input(type="password", name="logPassword", placeholder ="Password", required="") 
            input(type="submit", value="Login")
        a(href="/register") Need an account? Register here! 

 

 

4. Adding Bootstrap

getbootstrap.com/docs/4.4/getting-started/introduction/

 

Introduction

Get started with Bootstrap, the world’s most popular framework for building responsive, mobile-first sites, with BootstrapCDN and a template starter page.

getbootstrap.com

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

pughtml.com/

 

PugHtml - Pug and HTML online converter in realtime

Online Pug and HTML converter. Easy to switch between HTML and Pug (Jade) with options to minify or beautify your code. Test render with Bootstrap 5.0.0-beta1 & Fontawesome 4.7.

pughtml.com

이것 쓰기

link(rel='stylesheet', href='https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css', integrity='sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh', crossorigin='anonymous')

code.jquery.com/

 

jQuery CDN

The integrity and crossorigin attributes are used for Subresource Integrity (SRI) checking. This allows browsers to ensure that resources hosted on third-party servers have not been tampered with. Use of SRI is recommended as a best-practice, whenever libr

code.jquery.com

 

<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

이것 쓰기

script(src='https://code.jquery.com/jquery-3.6.0.min.js', integrity='sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=', crossorigin='anonymous')
script(src='https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js', integrity='sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo', crossorigin='anonymous')
script(src='https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js', integrity='sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6', crossorigin='anonymous')

login-layout.pug

<!DOCTYPE html>
html(lang="en")
    head
        meta(charset="UTF-8")
        meta(http-equiv="X-UA-Compatible", content="IE=edge")
        meta(name="viewport", content="width=device-width, initial-scale=1.0")
        title Login Page

        link(rel='stylesheet', href='https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css', integrity='sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh', crossorigin='anonymous')

    body 
        .wrapper 
            block content 
            script(src='https://code.jquery.com/jquery-3.6.0.min.js', integrity='sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=', crossorigin='anonymous')
            script(src='https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js', integrity='sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo', crossorigin='anonymous')
            script(src='https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js', integrity='sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6', crossorigin='anonymous')

main-layout.pug

doctype html
html(lang="en")
    head
        meta(charset="UTF-8")
        meta(http-equiv="X-UA-Compatible", content="IE=edge")
        meta(name="viewport", content="width=device-width, initial-scale=1.0")
        title #{pageTitle}
        link(rel='stylesheet', href='https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css', integrity='sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh', crossorigin='anonymous')

    body content 
    
    script(src='https://code.jquery.com/jquery-3.6.0.min.js', integrity='sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=', crossorigin='anonymous')
    script(src='https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js', integrity='sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo', crossorigin='anonymous')
    script(src='https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js', integrity='sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6', crossorigin='anonymous')

 

 

 

 

 

5. Serving static files

login-layout.pug

<!DOCTYPE html>
html(lang="en")
    head
        meta(charset="UTF-8")
        meta(http-equiv="X-UA-Compatible", content="IE=edge")
        meta(name="viewport", content="width=device-width, initial-scale=1.0")
        title Login Page

        link(rel='stylesheet', href='https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css', integrity='sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh', crossorigin='anonymous')
        link(rel="stylesheet", type='text/css', href="/css/login.css")
    body 
        .wrapper 
            block content 
            script(src='https://code.jquery.com/jquery-3.6.0.min.js', integrity='sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=', crossorigin='anonymous')
            script(src='https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js', integrity='sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo', crossorigin='anonymous')
            script(src='https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js', integrity='sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6', crossorigin='anonymous')

login.css

* {
    color: red;
}

app.js

const express = require('express');
const app = express();
const port = 3003;
const middleware = require('./middleware');//it means that current folder is equal .
//css파일 알려주기
const path = require('path');



const server = app.listen(port, ()=>{//callback 함수 
    console.log("Server listening on port" + port);
});

//서버에 알려주기
app.set("view engine", "pug");
app.set("views", "views");

//정적파일(css) 알려주기
app.use(express.static(path.join(__dirname, '/public'))); 

// Routes
const loginRoute = require('./routes/loginRoutes');

app.use("/login", loginRoute);



//get(1,2,3) -> 1,2,3... 순서대로 execute
app.get("/", middleware.requireLogin, (req, res, next)=>{//it means that / is equal views 
    var payload={
        pageTitle:"Home"
    }
    res.status(200).render("home",payload); // 이게 views/home.pug 
});

 

 

 

 

6. Login CSS

 

 

login.css

body{
    background-color:#0099ff;
}

.wrapper{
    display: flex;
    justify-content: center;
    margin-top: 20px;
}

.loginContainer{
    padding:20px;
    width : 80%;
    max-width:500px;
    border:1px solid #dedede;
    background-color:#fff;
    text-align : center;
    box-shadow:0 1px 4px rgba(0,0,0,0.3);
    -webkit-box-shadow:0 1px 4px rgba(0,0,0,0.3);
    -moz-box-shadow:0 1px 4px rgba(0,0,0,0.3);
}

form{
    display: flex;
    flex-direction: column;
}

input[type="text"],
input[type="email"],
input[type="password"]{
    margin-bottom: 20px;
    padding:5px 10px;
    border-radius: 2px;
    border: 1px solid #dedede;
    background-color: #f2f2f2;
}

input[type = "submit"]{
    background-color: #0099ff;
    color: #fff;
    border: none;
    border-radius: 2px;
    margin-bottom: 10px;
}
.wrapper {
    display: flex;
    justify-content: center;
    margin-top: 20px;
}

7. Creating the register page

 

 

register.pug

extends layouts/login-layout.pug 

block content 
    .loginContainer 
        h1 Register 
        form(action="post")

            input(type="text", name="firstName", placeholder ="First Name", required="") 
            input(type="text", name="lastName", placeholder ="Last Name", required="") 
            input(type="text", name="userName", placeholder ="User Name", required="") 
            input(type="email", name="email", placeholder ="Email", required="") 
            input(type="password", name="password", placeholder ="Password", required="") 
            input(type="password", name="passwordConf", placeholder ="Confirm password", required="") 
            input(type="submit", value="Login")


           
        a(href="/login") Already have an account? Login here! 

 

registerRoutes.js

const express = require('express');
const app = express();
const router = express.Router();

//서버에 알려주기
app.set("view engine", "pug");
app.set("views", "views");//root = views


//get(1,2,3) -> 1,2,3... 순서대로 execute
router.get("/", (req, res, next)=>{//it means that / is equal views, top level 
   
    res.status(200).render("register"); // register.pug
})

module.exports = router;

 

app.js

const express = require('express');
const app = express();
const port = 3003;
const middleware = require('./middleware');//it means that current folder is equal .
//css파일 알려주기
const path = require('path');



const server = app.listen(port, ()=>{//callback 함수 
    console.log("Server listening on port" + port);
});

//서버에 알려주기
app.set("view engine", "pug");
app.set("views", "views");

//정적파일(css) 알려주기
app.use(express.static(path.join(__dirname, '/public'))); 

// Routes
const loginRoute = require('./routes/loginRoutes');
const registerRoute = require('./routes/registerRoutes');



app.use("/login", loginRoute);//
app.use("/register", registerRoute);//re


//get(1,2,3) -> 1,2,3... 순서대로 execute
app.get("/", middleware.requireLogin, (req, res, next)=>{//it means that / is equal views 
    var payload={
        pageTitle:"Home"
    }
    res.status(200).render("home",payload); // 이게 views/home.pug 
});

8. Checking that the passwords match

 

register.pug

extends layouts/login-layout.pug 

block content 
    .loginContainer 
        h1 Register 
        form#registerForm(action="post", onsubmit="event.preventDefault(); validateForm();")

            input(type="text", name="firstName", placeholder ="First Name", required="") 
            input(type="text", name="lastName", placeholder ="Last Name", required="") 
            input(type="text", name="userName", placeholder ="User Name", required="") 
            input(type="email", name="email", placeholder ="Email", required="") 
            input#password(type="password", name="password", placeholder ="Password", required="") 
            input#passwordConf(type="password", name="passwordConf", placeholder ="Confirm password", required="") 
            input(type="submit", value="Register")


           
        a(href="/login") Already have an account? Login here! 
    
    script.  
        var passwordField = document.getElementById("password")
        var passwordConfirmField = document.getElementById("passwordConf")
        var form = document.getElementById("registerForm")

        function validateForm(){
            if(passwordField.value !=passwordConfirmField.value){
                alert("Passwords do not match. Please try again")
            } else{
                form.submit();
            }
        }

 

9. Adding body parser

 

npm install body-parser // 설치하기

register.pug

extends layouts/login-layout.pug 

block content 
    .loginContainer 
        h1 Register 
        form#registerForm(method="post", onsubmit="event.preventDefault(); validateForm();")

            input(type="text", name="firstName", placeholder ="First Name", required="") 
            input(type="text", name="lastName", placeholder ="Last Name", required="") 
            input(type="text", name="userName", placeholder ="User Name", required="") 
            input(type="email", name="email", placeholder ="Email", required="") 
            input#password(type="password", name="password", placeholder ="Password", required="") 
            input#passwordConf(type="password", name="passwordConf", placeholder ="Confirm password", required="") 
            input(type="submit", value="Register")


           
        a(href="/login") Already have an account? Login here! 
    
    script.  
        var passwordField = document.getElementById("password")
        var passwordConfirmField = document.getElementById("passwordConf")
        var form = document.getElementById("registerForm")

        function validateForm(){
            if(passwordField.value !=passwordConfirmField.value){
                alert("Passwords do not match. Please try again")
            } else{
                form.submit();
            }
        }

registerRoutes.js

const express = require('express');
const app = express();
const router = express.Router();
const bodyParser = require("body-parser");

//서버에 알려주기
app.set("view engine", "pug");
app.set("views", "views");//root = views

app.use(bodyParser.urlencoded({ extended:false}));


//get(1,2,3) -> 1,2,3... 순서대로 execute
router.get("/", (req, res, next)=>{//it means that / is equal views, top level 
   
    res.status(200).render("register"); // register.pug
})

router.post("/", (req, res, next)=>{//it means that / is equal views, top level 
    console.log(req.body);
    res.status(200).render("register"); // register.pug
})

module.exports = router;

app.js

const express = require('express');
const app = express();
const port = 3003;
const middleware = require('./middleware');//it means that current folder is equal .
//css파일 알려주기
const path = require('path');
const bodyParser = require("body-parser");


const server = app.listen(port, ()=>{//callback 함수 
    console.log("Server listening on port" + port);
});

//서버에 알려주기
app.set("view engine", "pug");
app.set("views", "views");


//바디파서 서버에게 알려주기
app.use(bodyParser.urlencoded({ extended:false}));
//정적파일(css) 서버에게 알려주기
app.use(express.static(path.join(__dirname, '/public'))); 

// Routes
const loginRoute = require('./routes/loginRoutes');
const registerRoute = require('./routes/registerRoutes');



app.use("/login", loginRoute);//
app.use("/register", registerRoute);//re


//get(1,2,3) -> 1,2,3... 순서대로 execute
app.get("/", middleware.requireLogin, (req, res, next)=>{//it means that / is equal views 
    var payload={
        pageTitle:"Home"
    }
    res.status(200).render("home",payload); // 이게 views/home.pug 
});

10. Checking for empty fields

 

register.pug

extends layouts/login-layout.pug 

block content 
    .loginContainer 
        h1 Register 
        form#registerForm(method="post", onsubmit="event.preventDefault(); validateForm();")

            p.errorMessage #{errorMessage}

            input(type="text", name="firstName", placeholder ="First Name", value=firstName, required="") 
            input(type="text", name="lastName", placeholder ="Last Name",value=lastName, required="") 
            input(type="text", name="userName", placeholder ="User Name", value=userName, required="") 
            input(type="email", name="email", placeholder ="Email",value=email, required="") 
            input#password(type="password", name="password", placeholder ="Password", required="") 
            input#passwordConf(type="password", name="passwordConf", placeholder ="Confirm password", required="") 
            input(type="submit", value="Register")


           
        a(href="/login") Already have an account? Login here! 
    
    script.  
        var passwordField = document.getElementById("password")
        var passwordConfirmField = document.getElementById("passwordConf")
        var form = document.getElementById("registerForm")

        function validateForm(){
            if(passwordField.value !=passwordConfirmField.value){
                alert("Passwords do not match. Please try again")
            } else{
                form.submit();
            }
        }

registerRoutes.js

const express = require('express');
const app = express();
const router = express.Router();
const bodyParser = require("body-parser");

//서버에 알려주기
app.set("view engine", "pug");
app.set("views", "views");//root = views

app.use(bodyParser.urlencoded({ extended:false}));


//get(1,2,3) -> 1,2,3... 순서대로 execute
router.get("/", (req, res, next)=>{//it means that / is equal views, top level 
   
    res.status(200).render("register"); // register.pug
})

router.post("/", (req, res, next)=>{//it means that / is equal views, top level 
    //console.log(req.body);
    var firstName = req.body.firstName.trim();
    var lastName = req.body.lastName.trim();
    var userName = req.body.userName.trim();
    var email = req.body.email.trim();
    var password = req.body.password;
    
    var payload = req.body;//payload pass to back!!

    if(firstName && lastName && userName && email && password){

    }else{
        payload.errorMessage ="Make sure each field has a valid value";
        res.status(200).render("register", payload); // register.pug
    }

    
})

module.exports = router;

app.js

const express = require('express');
const app = express();
const port = 3003;
const middleware = require('./middleware');//it means that current folder is equal .
//css파일 알려주기
const path = require('path');
const bodyParser = require("body-parser");


const server = app.listen(port, ()=>{//callback 함수 
    console.log("Server listening on port" + port);
});

//서버에 알려주기
app.set("view engine", "pug");
app.set("views", "views");


//바디파서 서버에게 알려주기
app.use(bodyParser.urlencoded({ extended:false}));
//정적파일(css) 서버에게 알려주기
app.use(express.static(path.join(__dirname, '/public'))); 

// Routes
const loginRoute = require('./routes/loginRoutes');
const registerRoute = require('./routes/registerRoutes');



app.use("/login", loginRoute);//
app.use("/register", registerRoute);//re


//get(1,2,3) -> 1,2,3... 순서대로 execute
app.get("/", middleware.requireLogin, (req, res, next)=>{//it means that / is equal views 
    var payload={
        pageTitle:"Home"
    }
    res.status(200).render("home",payload); // 이게 views/home.pug 
});