So far, we've created a backend user authentication service, a REST module, to access that service, a router module to handle routes related to logging in and out of the website, and changes in app.mjs to use those modules. We're almost ready, but we've got a number of outstanding changes to make in the templates. We're passing the req.user object to every template because each one must be changed to accommodate whether the user is logged in or not.
In partials/header.hbs, make the following additions:
...
{{#if user}}
<div class="collapse navbar-collapse"
id="navbarSupportedContent">
<span class="navbar-text text-dark col">{{ title }}</span>
<a class="btn btn-dark col-auto" href="/users/logout">
Log Out <span class="badge badge-light">{{ user.username }}
</span></a>
<a class="nav-item nav-link btn btn-dark col-auto"
href='/notes/add'>
ADD Note</a>
</div>
{{else}}
<div class="collapse navbar-collapse" id="navbarLogIn">
<a class="btn btn-primary" href="/users/login">Log in</a>
</div>
{{/if}}
...
What we're doing here is controlling which buttons to display at the top of the screen depending on whether the user is logged in or not. The earlier changes ensure that the user variable will be undefined if the user is logged out, otherwise it will have the user profile object. Therefore, it's sufficient to check the user variable as shown here to render different user interface elements.
A logged-out user doesn't get the ADD Note button, and gets a Log in button. Otherwise, the user gets an ADD Note button and a Log Out button. The Log in button takes the user to /users/login, while the Log Out button takes them to /users/logout. Both of those are handled in routes/users.js, and perform the expected function.
The Log Out button has a Bootstrap badge component displaying the username. This adds a little visual splotch, in which we'll put the username that's logged in. As we'll see later, it will serve as a visual cue to the user as to their identity.
We need to create views/login.hbs:
<div class="container-fluid">
<div class="row">
<div class="col-12 btn-group-vertical" role="group">
<form method='POST' action='/users/login'>
<div class="form-group">
<label for="username">User name:</label>
<input class="form-control" type='text' id='username'
name='username' value='' placeholder='User Name'/>
</div>
<div class="form-group">
<label for="password">Password:</label>
<input class="form-control" type='password' id='password'
name='password' value='' placeholder='Password'/>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
</div>
This is a simple form decorated with Bootstrap goodness to ask for the username and password. When submitted, it creates a POST request to /users/login, which invokes the desired handler to verify the login request. The handler for that URL will start the Passport's process to decide whether the user is authenticated or not.
In views/notedestroy.hbs, we want to display a message if the user is not logged in. Normally, the form to cause the note to be deleted is displayed, but if the user is not logged in, we want to explain the situation:
<form method='POST' action='/notes/destroy/confirm'>
<div class="container-fluid">
{{#if user}}
<input type='hidden' name='notekey' value='{{#if note}}{{notekey}}{{/if}}'>
<p class="form-text">Delete {{note.title}}?</p>
<div class="btn-group">
<button type="submit" value='DELETE'
class="btn btn-outline-dark">DELETE</button>
<a class="btn btn-outline-dark"
href="/notes/view?key={{#if note}}{{notekey}}{{/if}}"
role="button">Cancel</a>
</div>
{{else}}
{{> not-logged-in }}
{{/if}}
</div>
</form>
That's straightforward; if the user is logged in, display the form, otherwise display the message in partials/not-logged-in.hbs. We determine our approach based on the user variable.
We could put something like this in partials/not-logged-in.hbs:
<div class="jumbotron">
<h1>Not Logged In</h1>
<p>You are required to be logged in for this action, but you are not.
You should not see this message. It's a bug if this message appears.
</p>
<p><a class="btn btn-primary" href="/users/login">Log in</a></p>
</div>
In views/noteedit.hbs, we need a similar change:
..
<div class="row"><div class="col-xs-12">
{{#if user}}
..
{{else}}
{{> not-logged-in }}
{{/if}}
</div></div>
..
That is, at the bottom we add a segment that, for non-logged-in users, pulls in the not-logged-in partial.
The Bootstrap jumbotron component makes a nice and large text display that stands out nicely, and will catch the viewer's attention. However, the user should never see this because each of those templates is used only when we've preverified that the user is logged in.
A message such as this is useful as a check against bugs in your code. Suppose that we slipped up and failed to properly ensure that these forms were displayed only to logged-in users. Suppose that we had other bugs that didn't check the form submission to ensure it's requested only by a logged-in user. Fixing the template in this way is another layer of prevention against displaying forms to users who are not allowed to use that functionality.