Files
freeCodeCamp/curriculum/challenges/english/06-quality-assurance/advanced-node-and-express/registration-of-new-users.english.md
Shaun Hamilton e3cfe80f88 fix(curriculum): advanced node express changes for new boilerplate (#39080)
* fix: add tests and steps

* add necessary changes

* edit for new boilerplate

* fix: adjust content for boilerplate merge

* add 4 passing 1 failing socketio

* fix: add socketio changes

* fix: update wording and http test

Co-authored-by: Kristofer Koishigawa <scissorsneedfoodtoo@gmail.com>

* fix: replace glitch remix urls with repl.it urls

* integrate steps between lessons 4 and 5

* add mongodb altas link

* edit test to not require db deletion

* correct register routing and formatting

* fix typos and formatting

* fix: typos, standardize spacing, and remove unnecessary hr elements

* fix: add/update links

Add or update Gist solution links at the bottom of each challenge. Also add a missing link/text to the top of one of the challenges.

* fix: remove Repl.it/boilerplate repo links from all but first challenge

* fix: add target='_blank' to links in challenges

* add note about PIP browser issues

* move PIP note to end of instructions

Co-authored-by: Kristofer Koishigawa <scissorsneedfoodtoo@gmail.com>
2020-09-04 08:50:03 -05:00

6.3 KiB

id, title, challengeType, forumTopicId
id title challengeType forumTopicId
58966a17f9fc0f352b528e6d Registration of New Users 2 301561

Description

Now we need to allow a new user on our site to register an account. On the res.render for the home page add a new variable to the object passed along- showRegistration: true. When you refresh your page, you should then see the registration form that was already created in your index.pug file! This form is set up to POST on /register so this is where we should set up to accept the POST and create the user object in the database.

The logic of the registration route should be as follows: Register the new user > Authenticate the new user > Redirect to /profile

The logic of step 1, registering the new user, should be as follows: Query database with a findOne command > if user is returned then it exists and redirect back to home OR if user is undefined and no error occurs then 'insertOne' into the database with the username and password, and, as long as no errors occur, call next to go to step 2, authenticating the new user, which we've already written the logic for in our POST /login route.

app.route('/register')
  .post((req, res, next) => {
    myDataBase.findOne({ username: req.body.username }, function(err, user) {
      if (err) {
        next(err);
      } else if (user) {
        res.redirect('/');
      } else {
        myDataBase.insertOne({
          username: req.body.username,
          password: req.body.password
        },
          (err, doc) => {
            if (err) {
              res.redirect('/');
            } else {
              // The inserted document is held within
              // the ops property of the doc
              next(null, doc.ops[0]);
            }
          }
        )
      }
    })
  },
    passport.authenticate('local', { failureRedirect: '/' }),
    (req, res, next) => {
      res.redirect('/profile');
    }
  );

Submit your page when you think you've got it right. If you're running into errors, you can check out the project completed up to this point here.

NOTE: From this point onwards, issues can arise relating to the use of the picture-in-picture browser. If you are using an online IDE which offers a preview of the app within the editor, it is recommended to open this preview in a new tab.

Instructions

Tests

tests:
  - text: You should register route and display on home.
    testString: "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /showRegistration:( |)true/gi, 'You should be passing the variable showRegistration as true to your render function for the homepage'); assert.match(data, /register[^]*post[^]*findOne[^]*username:( |)req.body.username/gi, 'You should have a route accepted a post request on register that querys the db with findone and the query being username: req.body.username'); }, xhr => { throw new Error(xhr.statusText); })"
  - text: Registering should work.
    testString: "async getUserInput => {
      const url = getUserInput('url');
      const user = `freeCodeCampTester${Date.now()}`;
      const xhttp=new XMLHttpRequest();
      xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
          test(this);
        } else {
          throw new Error(`${this.status} ${this.statusText}`);
        }
      };
      xhttp.open('POST', url+'/register', true);
      xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
      xhttp.send(`username=${user}&password=${user}`);  

      function test(xhttpRes) {
        const data = xhttpRes.responseText;
        assert.match(data, /Profile/gi, 'Register should work, and redirect successfully to the profile.');
      }
    }
    "
  - text: Login should work.
    testString: "async getUserInput => {
      const url = getUserInput('url');
      const user = `freeCodeCampTester${Date.now()}`;
      const xhttpReg = new XMLHttpRequest();
      xhttpReg.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
          login();
        } else {
          throw new Error(`${this.status} ${this.statusText}`);
        }
      };
      xhttpReg.open('POST', url+'/register', true);
      xhttpReg.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
      xhttpReg.send(`username=${user}&password=${user}`);

      function login() {
        const xhttp=new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
          if (this.readyState == 4 && this.status == 200) {
            test(this);
          } else {
            throw new Error(`${this.status} ${this.statusText}`);
          }
        };
        xhttp.open('POST', url+'/login', true);
        xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        xhttp.send(`username=${user}&password=${user}`);  
      }
      function test(xhttpRes) {
        const data = xhttpRes.responseText;
        assert.match(data, /Profile/gi, 'Login should work if previous test was done successfully and redirect successfully to the profile.');
        assert.match(data, new RegExp(user, 'g'), 'The profile should properly display the welcome to the user logged in');
      }
    }
    "
  - text: Logout should work.
    testString: "getUserInput => $.ajax({url: getUserInput('url')+ '/logout', type: 'GET', xhrFields: { withCredentials: true }}) .then(data => { assert.match(data, /Home/gi, 'Logout should redirect to home'); }, xhr => { throw new Error(xhr.statusText); })"
  - text: Profile should no longer work after logout.
    testString: "getUserInput => $.ajax({url: getUserInput('url')+ '/profile', type: 'GET', crossDomain: true, xhrFields: { withCredentials: true }}) .then(data => { assert.match(data, /Home/gi, 'Profile should redirect to home when we are logged out now again'); }, xhr => { throw new Error(xhr.statusText); })"

Challenge Seed

Solution

/**
  Backend challenges don't need solutions, 
  because they would need to be tested against a full working project. 
  Please check our contributing guidelines to learn more.
*/