Multiplayer blog background management day02

Time:2022-6-11

(2) Realization of project function – user management

Blog -- source code directory
 └ - Middleware
     └──loginGuard. JS login interception
 └ -- Model -- database operation
     ├── connect. JS -- database connection
     └── user. JS -- user management
 └ -- public -- static resources
     └ -- admin -- static resources of blog management page
           └── common. JS -- client authentication login form
└ - route
        └ - admin - blog management page
               ├──loginPage. JS login page rendering
               ├──logout. JS exit page function implementation
               ├──userPage. JS user page rendering
               └── login. JS login page function implementation

        └── admin. JS -- blog management page routing
 └ -- Views -- template
      └ - admin - blog management page art template
           └ - common module
                  └── header. Art common head module
           ├── login. Art -- login page
           └── error. Art -- error page
 ├── app. JS -- create a web service
 └──hash. JS -- Test code for bcrypt

1、connect.js

  • Linked database: introduce mongoose and linked database
//Introduce mongoose third-party module
const mongoose = require('mongoose');
//Import config module
const config = require('config');
console.log(config.get('db.host'))
//Connect to database
mongoose.connect(`mongodb://${config.get('db.user')}:${config.get('db.pwd')}@${config.get('db.host')}:${config.get('db.port')}/${config.get('db.name')}`, {useNewUrlParser: true })
    . then(() => console. Log ('Database connection succeeded '))
    . catch(() => console. Log ('Database connection failed '))

2.app.js

  • Database link: require connect
  • require(‘./model/user’);·//Create a user and comment it out after the user is created
  • The server receives the request parameters and verifies whether the user has filled in the login form:

    • Restart the server after downloading the third-party modulenpm install body-parser
    • app. JS introduces the body parser module to handle post request parameters
  • The login status is displayed. The login status needs to be saved: import the express session module,npm install express-sessionIntercept the request to determine the user login status,
  • Intercept the request to determine the user login status, and require loginguard
//Reference the express framework
const express = require('express');
//Processing path
const path = require('path');
//The body parser module is introduced to handle post request parameters
const bodyPaser = require('body-parser');
//Import express session module
const session = require('express-session');
//Create web server
const app = express();
//Database connection
require('./model/connect');
//Processing post request parameters
app.use(bodyPaser.urlencoded({extended: false}));
//Tell express where the framework template is located
app.set('views', path.join(__dirname, 'views'));
//Tell express what is the default suffix for the framework template
app.set('view engine', 'art');
//What is the template engine used when rendering a template with the suffix Art
app.engine('art', require('express-art-template'));
//Open static resource file
app.use(express.static(path.join(__dirname, 'public')));
//Introduction of routing module
const home = require('./route/home');
const admin = require('./route/admin');
//Intercept request to judge user login status
app.use('/admin', require('./middleware/loginGuard'));
//Match request path for route
app.use('/home', home);
app.use('/admin', admin);
//Listening port
app.listen(80);
console. Log ('Web server started successfully, please visit localhost')

3.user.js

  • Create a user collection and initialize users:Remember to delete the collection after it is created, otherwise an error will be reported for repeated creation, export the user collection as a module member
  • The bcrypt encryption method is used to import the bcrypt module,
//Create user collection
//Introduce mongoose third-party module
const mongoose = require('mongoose');
//Import bcrypt
const bcrypt = require('bcrypt');
//Create user collection规则
const userSchema = new mongoose.Schema({
    username: {
        ···
    },
    email: {
        ···
    }
···
});

//Create collection
async function createUser () {
    const salt = await bcrypt.genSalt(10);
    const pass = await bcrypt.hash('123456', salt);
    const user = await User.create({
        username: 'xx',
        email: 'xx',
        password: pass,
        role: 'admin',
        state: 0
    });
}
// createUser();
//Export user collections as module members
module.exports = {
    User
}

4.login.art

  • Set the request address, request method and form item name attribute for the login form item, and add the ID value for the form to facilitate obtaining the form
  • Prevent form submission if one of the mail and password is not entered
<body>
<div class="login">
                <form action="xx" method="post" id="loginForm">
···
 <input name= "email" type= "email" class= "XX" placeholder= "please enter email address" >
···
<script type="text/javascript">
        //Add a submit event to the form
        $('#loginForm').on('submit', function () {
            //Get the user input in the form
            var result = serializeToJson($(this))
            //If the user does not enter an email address
            if (result.email.trim().length == 0) {
                Alert ('Please enter email address');
                //Prevent program execution down
                return false;
            }
            //If the user does not enter a password
            if (result.password.trim().length == 0) {
                Alert ('Please enter password ')
                //Prevent program execution down
                return false;
            }
        });
    </script>
</body>

5.common.js

  • When the user clicks the login button, the client verifies whether the user has filled in the login form and adds it to the layout JS, so that each page can access
function serializeToJson(form) {
    var result = {};
    //[{name:'email', value:' user input '}]
    var f =  form.serializeArray();  
    f.forEach(function (item) {
        // result.email
        result[item.name] = item.value;
    });
    return result;
}

layout.js

<!DOCTYPE html>
<html lang="en">
<head>
 ···
 {{block 'link'}}{{/block}}
</head>
<body>
 {{block 'main'}} {{/block}}
 ···
 <script src="/admin/js/common.js"></script>
 {{block 'script'}} {{/block}}
</body>
</html>

6.login.js

  • Realize the login function. If one of the items is not entered (trim() Length = = 0), respond to the client and prevent the program from executing downward
  • Query the user information according to the email address (import the user collection constructor). If the user does not exist (query with findone), respond to the client and prevent the program from executing downward
  • If the user exists, the user name and password (encrypted with bcrypt) are compared (bcrypt.compare (password, user.password)). The comparison succeeds, the user login succeeds, the comparison fails, and the user login fails

    Other environments on which bcrypt depends

    1. install Python and set Python to the environment variable
    2.node-gyp
    npm install node-gyp -g
    3.windows-build-tools

    Python 2 version:npm install --global --production windows-build-tools
    Python other versions:https://blog.csdn.net/weixin_…

  • Judge the user role, store the user role in the session object, if not admin to the login page, if yes, enter the user list page
  • req. app. Locals, req can obtain the app object, and select the locals attribute, which can avoid multiple rendering
  • Render (‘admin/error’) if the jump fails, render the error page
//Import user collection constructor
const { User } = require('../../model/user');
const bcrypt = require('bcrypt');

module.exports = async (req, res) => {
    //Receive request parameters
    const {email, password} = req.body;
    //If the user does not enter an email address
    // if (email.trim(). length == 0 || password. trim(). length == 0) return res.status(400). Send ('<h4> email address or password error </h4>');
    if (email.trim(). length == 0 || password. trim(). length == 0) return res.status(400). Render ('admin/error', {msg:' email address or password error '});
    //Query user information according to email address
    //If the value of the user variable is the object type, the user information is stored in the object
    //If no user is found, the user variable is empty
    let user = await User.findOne({email});
    //User queried
    if (user) {
        //Compare the password passed by the client with the password in the user information
        //True comparison succeeded
        //False comparison failed
        let isValid = await bcrypt.compare(password, user.password);
        //If the password comparison is successful
        if ( isValid ) {
            //Login successful
            //Store the user name in the request object
            req.session.username = user.username;
            //Store user roles in session objects
            req.session.role = user.role;
            //Res.send ('login succeeded ');
            req.app.locals.userInfo = user;
            //Judge the user's role
            if (user.role == 'admin') {
                //Redirect to user list page
                res.redirect('/admin/user');
            } else {
                //Redirect to blog home page
                res.redirect('/home/');
            }
            
        } else {
            //No user found
            res.status(400). Render ('admin/error', {msg:' email address or password error '})
        }
    } else {
        //No user found
        res.status(400). Render ('admin/error', {msg:' email address or password error '})
    }
}

7.header.art

  • {{userinfo & & userinfo.username}} determine whether userinfo exists to prevent error reporting due to non existence
<!--  Head -- >
<div class="header">
    <!--  User information -- >
    <div class="info">
        <div class="profile dropdown fr">
            <span class="btn dropdown-toggle" data-toggle="dropdown">
                {{userInfo && userInfo.username}}
                <span class="caret"></span>
            </span>
        </div>
    </div>
    <!-- / User information -- >
</div>

8.loginGuard.js

  • Realize the function of login interception: judge whether the page other than login is in login status (req.url! =’/login’& &! Req.session.username), and then judge whether the user attribute is an ordinary user or an administrator
onst guard = (req, res, next) => {
    //Determine whether the user is visiting the login page
    //Judge the user's login status
    //If the user is logged in, release will be requested
    //If the user is not logged in, redirect the request to the login page
    if (req.url != '/login' && !req.session.username) {
        res.redirect('/admin/login');
    } else {
        //If the user is logged in and is an ordinary user
        if (req.session.role == 'normal') {
            //Make it jump to the front page of the blog to prevent the program from executing downward
            return res.redirect('/home/')
        }
        //If the user is in login status, release will be requested
        next();
    }
}

module.exports = guard;

9.hash.js

//Import bcrypt
const bcrypt = require('bcrypt');


async function run () {
    //Generate random string
    //The gensalt method takes a value as a parameter
    //The larger the number, the higher the complexity of the generated random string
    //The smaller the number, the lower the complexity of the generated random string
    //The default value is 10
    //Returns the generated random string
    const salt = await bcrypt.genSalt(10);
    //Encrypt password
    // 1.  Plaintext to be encrypted
    // 2.  Random string
    //The return value is the encrypted password
    const result = await bcrypt.hash('123456', salt);
    console.log(salt);
    console.log(result);
}

run();

10.loginPage.js

  • Module separation function: rendering the login page
  • Realize code reuse through modularization, and finally export the routing object as a module member
  • Similarly, logout js userPage. js login. js
module.exports = (req, res) => {
    res.render('admin/login');
}

11.admin.js

  • Connect module members everywhere through require
  • Admin is also exported as a module member, and app JS access
//Reference the express framework
const express = require('express');
//Create blog presentation page route
const admin = express.Router();
//Render login page
admin.get('/login', require('./admin/loginPage'));

//Realize login function
admin.post('/login', require('./admin/login'));

//Create user list route
admin.get('/user', require('./admin/userPage'));

//Realize exit function
admin.get('/logout', require('./admin/logout'));
//Export routing objects as module members
module.exports = admin;

12、error.art

  • Optimization page: the error page will return to the login page three seconds later, based on the layout skeleton
{{extend './common/layout.art'}}

{{block 'main'}}
    <p class="bg-danger error">{{msg}}</p>
{{/block}}

{{block 'script'}}
    <script type="text/javascript">
        setTimeout(function () {
            location.href = '/admin/login';
        }, 3000)
    </script>
{{/block}}