Saving the login state to the session

A session is when a user logs in up to when the user logs out. Vibe.d provides a mechanism to uses a session.

When we want to retrieve a particular record from the database, we simply use the id field as the key to retrieve the record by passing the key to the next page. When we retrieve another record, we lose this key because we receive another key.

But when a user logs in, the log in state needs to be saved for the duration of the session so that the user can navigate from page to page without having to log in again and again.

If the user is logged in, we should save that state so that as the user navigates from page to page, the system can check if the user is already logged in and is authorized to access that particular page. We need a session for that.

A variable, such as a logged-in state, can be saved to this session facility. Vibe.d has the session store for this purpose, of which there are two kinds: MemorySessionStore and the database-based store. For this project, we will use MemorySessionStore.

Edit source\app.d:

import vibe.vibe;
import empcontrol;
void main()
{
  auto settings = new HTTPServerSettings;
  settings.port = 8080;
  settings.bindAddresses = ["::1", "127.0.0.1"];
  settings.sessionStore = new MemorySessionStore;
  auto router = new URLRouter;
  router.get("*", serveStaticFiles("public/"));
  router.registerWebInterface(new EmployeeController);
  auto listener = listenHTTP(settings, router);
  scope (exit) listener.stopListening();
 
  runApplication();
}

Edit source\empcontrol.d to add a User struct.

module empcontrol;
import vibe.vibe;
import empmodel;

struct User 
{
  bool loggedIn;
  string email;
}

class EmployeeController
{
  EmployeeModel empModel;
  string realm = "The Lorem Ipsum Company";
  private SessionVar!(User, "user") m_user;
  ...

And edit postLogin() to save the logged-in state to the session using the m_user variable.

  @errorDisplay!index
  void postLogin(string email, string password)
  {
    import vibe.http.auth.digest_auth;
   
    auto scrambled = createDigestPassword(realm, email, password);
    bool isAdmin = empModel.isAdmin(email, scrambled);
    enforce(isAdmin, "Email and password combination not found.");
    User user = m_user;
    user.loggedIn = true;
    user.email = email;
    m_user = user;
    redirect("all_employees");
  }

We created a User struct to hold the logged-in state

struct User 
{
  bool loggedIn;
  string email;
}

Then we declared a session variable named m_user of that struct type:

private SessionVar!(User, "user") m_user;

Then we changed the value of m_user inside postLogin() to save and start the session:

    User user = m_user;
    user.loggedIn = true;
    user.email = email;
    m_user = user;

Changing the value of m_user automatically starts the session.

We indicated that index() will be called and passed the error if postLogin() encounters an error:

  @errorDisplay!index
  void postLogin(string email, string password)
  {
    import vibe.http.auth.digest_auth;
...

Then we changed the index() method to accept an _error variable if postLogin() encounters an error.

  void index(string _error = null)
  {
    string error = _error;
    render!("index.dt", error);
  }

Edit views\index.dt to display the error, if there is any, returned by the enforce() function.

extends layout
block maincontent
  h2 The Lorem Ipsum Company
  -if(error)
    div.error-div
      span.error-message #{error}
  div.
    Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    Nam nec urna arcu. Quisque eleifend posuere vestibulum.
    In sed magna mauris. Phasellus bibendum ligula et placerat
    vulputate. In non suscipit lectus, a laoreet odio. Donec
    at sapien eu nisi porta condimentum. Morbi non varius ex,
    nec luctus nisl. Aenean varius dui quis arcu auctor luctus.
    Integer efficitur ornare massa, ac suscipit enim sagittis et.
    Proin vestibulum tellus in ipsum ultrices, sed imperdiet
    sapien euismod. Praesent vel facilisis mauris. Proin finibus
    congue tellus, non varius ante. Nullam tincidunt dolor felis.
    Pellentesque non luctus tellus. Curabitur et sapien at justo
    fringilla feugiat et a erat.
    <br /><br />

Compile, run and refresh the browser. Click on the Login menu item and input a non-existing admin user. If you get an error, that means the error-trapping mechanism is working.

Now let us make the other pages know about the login state.

Last updated