Lesson 22. Adding sessions and flash messages

In this lesson, you clean up the flow between CRUD functions by passing messages between pages to find out whether the server operations were successful or certain types of errors occurred. Currently, error messages are logged to the console, and users of the application have no way to know what they could do differently. You use sessions and cookies alongside the connect-flash package to deliver these messages to your views. By the end of the lesson, you’ll have an application that gives you a visual description of the success or failure of operations.

This lesson covers

  • Setting up sessions and cookies
  • Creating flash messages in your controller actions
  • Setting up validation middleware on incoming data
Consider this

Your recipe application is starting to collect data through the view forms you created in unit 4. Users are beginning to get frustrated, though, because they don’t know what validations you have in place, and if they fail to meet your validator expectations, they’re redirected to a different page without notice.

With some helpful packages, you can incorporate flash messaging into your application to inform your users of specific errors that occur in your application.

22.1. Setting up flash message modules

Flash messages are semipermanent data used to display information to users of an application. These messages originate in your application server and travel to your users’ browsers as part of a session. Sessions contain data about the most recent interaction between a user and the application, such as the current logged-in user, length of time before a page times out, or messages intended to be displayed once.

You have many ways to incorporate flash messages into your application. In this lesson, you use the connect-flash middleware module by typing npm i connect-flash -S in terminal to install its package to your application as a dependency.

Note

Sessions used to be a dependency of Express.js, but because not everyone uses every Express.js dependency and because it’s difficult to keep dependencies up to date with the main package, independent packages cookie-parser and express-session must be installed.

Now you need to install two more packages by running npm i cookie-parser express-session -S in terminal. Then require these three modules—connect-flash, cookie-parser, and express-session—in your main.js file, along with some code to use the modules (listing 22.1).

You need the express-session module to pass messages between your application and the client. These messages persist on the user’s browser but are ultimately stored in the server. express-session allows you to store your messages in a few ways on the user’s browser. Cookies are one form of session storage, so you need the cookie-parser package to indicate that you want to use cookies and that you want your sessions to be able to parse (or decode) cookie data sent back to the server from the browser.

Use the connect-flash package to create your flash messages. This package is dependent on sessions and cookies to pass flash messages between requests. You tell your Express.js application to use cookie-parser as middleware and to use some secret passcode you choose. cookie-parser uses this code to encrypt your data in cookies sent to the browser, so choose something that’s hard to guess. Next, you have your application use sessions by telling express-session to use cookie-parser as its storage method and to expire cookies after about an hour.

You also need to provide a secret key to encrypt your session data. Specify that you don’t want to send a cookie to the user if no messages are added to the session by setting saveUninitialized to false. Also specify that you don’t want to update existing session data on the server if nothing has changed in the existing session. Last, have the application use connect-flash as middleware.

Note

In this example, the secret key is shown in plain text in your application server file. I don’t recommend displaying your secret key here, however, because it opens your application to security vulnerabilities. Instead, store your secret key in an environment variable, and access that variable with process.env. I discuss this topic further in unit 8.

Listing 22.1. Requiring flash messaging in main.js
const expressSession = require("express-session"),      1
  cookieParser = require("cookie-parser"),
  connectFlash = require("connect-flash");
router.use(cookieParser("secret_passcode"));            2
router.use(expressSession({
  secret: "secret_passcode",
  cookie: {
    maxAge: 4000000
  },
  resave: false,
  saveUninitialized: false
}));                                                    3
router.use(connectFlash());                             4

  • 1 Require the three modules.
  • 2 Configure your Express.js application to use cookie-parser as middleware.
  • 3 Configure express-session to use cookie-parser.
  • 4 Configure your application to use connect-flash as middleware.

All together, these three packages provide middleware to help you process incoming requests and outgoing responses with necessary cookie data.

Cookie parsing

With each request and response made between the server and client, an HTTP header is bundled with the data sent across the internet. This header contains a lot of useful information about the data being transferred, such as the size of the data, the type of data, and the browser the data is being sent from.

Another important element in the request header is the cookies. Cookies are small files of data sent from the server to the user’s browser, containing information about the interaction between the user and the application. A cookie might indicate which user accessed the application last, whether the user logged in successfully, and even what requests the user made, such as whether he successfully, created an account or made multiple failed attempts.

In this application, you use encrypted cookies with a secret passcode encryption key to store information about each user’s activity on the application and whether the user is still logged in, as well as short messages to display in the user’s browser to let them know if any errors occurred on their most recent request.

Note

Because requests are independent of one another, if one request to create a new user fails and you’re redirected to the home page, that redirect is another request, and nothing is sent in the response to the user to let them know that their attempt to create an account failed. Cookies prove to be helpful in this case.

As you create your custom secret keys, remember to make them a bit more difficult for someone else to guess. Next, you use these added modules by setting up flash messaging on your controller actions.

Quick check 22.1

Q1:

How does a cookie’s secret key change the way that data is sent and stored on a browser?

QC 22.1 answer

1:

The secret key used with cookies allows data to have some encryption. Encryption is important for securing the data sent over the internet and for making sure that the data living in the user’s browser isn’t exposed to modifications.

 

22.2. Adding flash messages to controller actions

To get flash messages working, you need to attach them to the request made before you render a view to the user. Generally, when a user makes a GET request for a page—say, to load the home page—you don’t need to send a flash message.

Flash messages are most useful when you want to notify the user of a successful or failed request, usually involving the database. On these requests, such as for user creation, you’re typically redirecting to another page, depending on the outcome. If a user is created, you redirect to the /users route; otherwise, you can redirect to /user/new. A flash message is no different from a local variable being made available to the view. For that reason, you need to set up another middleware configuration for express to treat your connectFlash messages like a local variable on the response, as shown in listing 22.2.

By adding this middleware function, you’re telling Express to pass a local object called flashMessages to the view. The value of that object is equal to the flash messages you create with the connect-flash module. In this process, you’re transferring the messages from the request object to the response.

Listing 22.2. Middleware to associate connectFlash to flashes on response
router.use((req, res, next) => {
  res.locals.flashMessages = req.flash();       1
  next();
});

  • 1 Assign flash messages to the local flashMessages variable on the response object.

With this middleware in place, you can add messages to req.flash at the controller level and access the messages in the view through flashMessages. Next, add a flash message to the create action in your usersController by changing the action’s code to match listing 22.3.

In this action, you’re modifying the way that you handle errors in the catch block. Instead of passing the error to the error-handler action, set the error flash message, and allow the redirectView action to display the user’s new.ejs page again. The first flash message is of type success and delivers the message that the user’s account was created. The flash message delivered when the account isn’t created is of type error.

Note

getUserParams has been borrowed from the last capstone exercise (lesson 21). This function is reused throughout the controller to organize user attributes in one object. You should create the same functions for your other model controllers.

Listing 22.3. Adding flash messages to the create action in usersController.js
create: (req, res, next) => {
  let userParams = getUserParams(req.body);
  User.create(userParams)
    .then(user => {
      req.flash("success", `${user.fullName}'s account created
 successfully!`);                                                   1
      res.locals.redirect = "/users";
      res.locals.user = user;
      next();
    })
    .catch(error => {
      console.log(`Error saving user: ${error.message}`);
      res.locals.redirect = "/users/new";
      req.flash(
        "error",
        `Failed to create user account because:  ${error.message}.` 2
      );
      next();
    });
},

  • 1 Respond with a success flash message.
  • 2 Respond with a failure flash message.
Note

Although you use the request object here to store the flash messages temporarily, because you connected these messages to a local variable on the response, the messages ultimately make it to the response object.

As soon as the page is redirected to /users or /users/new, your flash message is available to the view.

Note

error and success are two flash-message types that I made up. You can customize these types however you like. If you want a flash message of type superUrgent, you can use req.flash("superUrgent", "Read this message ASAP!"). Then superUrgent will be the key used to get whatever message you attach.

The last step in getting flash messages working is adding some code to the view to receive and display the messages. Because you want every view to show potential success or failures, add the code in listing 22.4 to layout.ejs. You may also want to add custom styles in your public/css folder so that the messages can be differentiated from normal view content.

First, check whether any flashMessages exist. If success messages exist, display the success messages in a div. If error messages exist, display those messages with a differently styled class.

Listing 22.4. Adding flash messages in layout.ejs
<div class="flashes">
  <% if (flashMessages) { %>                                        1
    <% if (flashMessages.success) { %>
      <div class="flash success"><%= flashMessages.success %></div> 2
    <% } else if (flashMessages.error) { %>
      <div class="flash error"><%= flashMessages.error %></div>     3
    <% } %>
  <% } %>
</div>

  • 1 Check whether flashMessages exist.
  • 2 Display success messages.
  • 3 Display error messages.
Tip

If you don’t see any messages on the screen at first, try removing all styling surrounding the message to get the plain-text message in the view.

Test the new code to display flash messages by starting the Node.js application, visiting /users/new, and filling out the form to create a new user. If you create a new user successfully, your page on redirect should look like figure 22.1.

Figure 22.1. Successful flash message shown on the /users page

If you try to create a new user with an existing email address, your redirect screen should resemble figure 22.2.

Figure 22.2. Error flash message shown on the home page

When you refresh the page or create any new request, this message disappears. Because you may choose to send multiple success or error messages, you may find it useful to loop through the messages on the view instead of displaying everything mapped to the error and success keys.

If you need to show a flash message on a view you’re rendering, pass the message directly as a local variable. The next listing shows how to add a success message to the user’s index page. When you pass the flashMessages object directly to the view, you don’t need to wait for a redirect or use connect-flash.

Listing 22.5. Adding a flash message to the rendered index view
res.render("users/index", {
  flashMessages: {
    success: "Loaded all users!"
  }
});                              1

  • 1 Pass the flash messages with a rendered view.
Quick check 22.2

Q1:

What two arguments are needed for the req.flash method?

QC 22.2 answer

1:

req.flash needs a flash-message type and a message.

 

Summary

In this lesson, you learned about sessions and cookies, and saw why they’re integral parts of how data is transferred between the server and client. You also set up connect-flash to use cookies and temporarily show success and failure messages on certain views. In lesson 23, you see how to encrypt more than cookie data by implementing encryption on user passwords.

Try this

Now that you have flash messaging set up, it’s time to add it to all your CRUD actions. You want your users to see whether their attempt to subscribe, create an account, delete an account, or update user information was successful. Add flash messages for each action involving your database for all three models.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.142.115