Series: User Auth

Session Service

Published on Oct 16, 2015

To keep track of personalized data, we need a user. To keep track of the current user, we need a session. A service is the perfect structure for making a session.

In this video we create a session service and use it to (insecurely) login and logout users. We then use that session to create customized teams for each user, and discover the power of a service with a good API.


Links

Code

The session service

//services/session.js

export default Ember.Service.extend({
  currentUser: null,
  login(user){
    this.set('currentUser', user)
  },
  logout(){
    this.set('currentUser', null)
  }
});

Display current user and logout link

//controllers/application.js

export default Ember.Controller.extend({
  session: Ember.inject.service(),
  actions: {
    logout(){
      this.get("session").logout()
      this.transitionToRoute('users')
    }
  }
})
//templates/application.hbs

<div class="container">
  <div class="pull-right">
    {{#if session.currentUser}}
      <span {{action 'logout'}} style="cursor: pointer;">Logout {{session.currentUser.email}}</span>
    {{else}}
      {{#link-to 'users'}}Login{{/link-to}}
    {{/if}}
    ---
    {{#link-to 'monsters'}}Monsters{{/link-to}}
  </div>

  {{outlet}}
</div>

Login link is temporarily in /users

//controllers/users.js

export default Ember.Controller.extend({
  session: Ember.inject.service(),
  actions: {
    login(user){
      this.get("session").login(user)
      this.transitionToRoute("monsters")
    }
  }
})
//templates/users.hbs

<h1>Users</h1>
{{#each model as |user|}}
  <button {{action 'login' user}}>Log in</button>{{user.name}}--- {{user.email}}
  <br>
{{/each}}

Transcript

In the last episode, we created an app where we could sort through monsters and add them to our team. However, when we reloaded the page, they were all gone because they were just stored within the application. They weren’t persisted to anything, like a server. However, if you just have one current team that you persist to the server, then everyone’s going to have the same current team and that’s not good. That’s why we need sessions. That’s why we need users.

So I’ve created some users. They have a name and an e-mail address. And I’ve created two of them.

Our session is going to keep track of which user we’re currently signed in as, as well as take care of the signing in and signing out for us.

We’ll start by generating an Ember.Service and we’ll call that service session.

This session service will have a currentUser property. It’ll also have two functions, login and logout, which set the currentUser to a user or null respectively.

Our first use of this service will be to create login buttons for both of these users. We’re not really concerned with security at the moment. We’ll be covering that in later screencasts.

So here we’ll add a button that has the action login,

and then in our users controller, we’ll inject the session service. And then in the login action, we’ll call the login method on the session. And of course after we login, we’ll want to display that status to the user, and what better way than in our navbar.

So let’s go to the application controller and we’ll go ahead and inject the service,

then in the handlebars template for the application, we’ll go ahead and create a span that’s pulled to the right, and that will display the current user’s e-mail. We are of course able to access the currentUser because we’re injecting the session.

We’ll see this in action. We’ll hit ‘Log in’ and it shows the e-mail address over on the right.

Now that we have the basic ‘Log in’, let’s go ahead and make this navbar a little bit more full-featured.

So first we’ll use an if statement to check where the currentUser exists. If it does exist, we’ll keep displaying the e-mail. If it doesn’t exist, then we’ll provide a link to the users page, and we’ll call this link login. Later this will link to an actual ‘Log in’ page.

Then let’s go ahead and edit this stuff within the currentUser block as well. So we’ll add a link to the monsters page since you’ll probably want to edit your monsters.

And then we’ll add a logout action around the e-mail.

Then, in the application controller, we want to add the logout action, which will call the logout action on session, on our session service, and then we’ll go ahead and transition to the users route, since after you logout that’s where you’ll want to be.

And while we’re at it for convenience sake, let’s go ahead and add a transition to the monsters route to the login.

We’ll see this in action. We’ll hit log in. It logs us in, takes us to the monsters route,

and then we can log out and it’ll take us back to the users route.

So that’s the bare bones of the session service that we use to keep track of which user is currently signed in.

Now we’ll see how having the user can help us assemble the current team and have that team be saved between sessions.

So we’ll see that the user in addition to having a name and an e-mail, they also have many teamMemberships,

and team-membership belongs to a monster and a user,

and a monster of course has many team memberships. So what we’ll have to do is find a way to connect the monster and the current user using team memberships. The answer is in the currentTeam service.

So we’ll just change the currentTeam service, so instead of working with the stand alone list of monsters, we’ll work with the list of monsters calculated from the team memberships of the currently signed in user.

Then when you’re adding a monster to the team, you must create the team membership record, and then save it.

Also notice that store, it’s a service. We’ll go ahead and inject it. You can inject the store into any ember object.

Then to remove a monster from a team, we must get the team memberships from the current user, and then filter it out so we find the one that contains that monster, and because of how we’re doing this it’ll be an array, so we’ll do a forEach on this, even though it’ll just be a length of one, and then destroy that record.

Finally, we’ll have to change the includes method. How we’ll have to change it is we’ll have to map to get the content, and I’m not really happy with having to do this, so if you have any better solutions, please tell me in the comments.

Now we’ll try this out. We’ll login as Jeffrey and then we’ll add stuff to the team,

and then when we reload, well we’re not logged in again. But we log back in as Jeffrey, it’ll keep our current team.

And then when we log in as someone else, it’ll have a different team.

Now there’s something that I want you to notice. Even though there was a lot of churn within the current-team service, we didn’t actually change any of the places that are calling the current-team service.

So in the monster model, onTeam calls the currentTeam list of monsters. It stays the same. It also calls includes. This has stayed the same.

team-lineup, this has stayed the same.

And the monster controller, these have once again stayed the same.

So this shows the power of a well-designed service with a stable API. You can change almost everything else about it, and as long as the API stays the same, nothing else in your app has to change.

So to review, in this episode we created a session service, a very basic one. It’s non-persistent and completely insecure. But it’s the basic bare bones and we’ll be expanding on this in coming episodes.

Then we used that session service to create a navbar,

and then finally we used the user and currentUser that this session service provides in order to make our current team persist to the database. And as a special bonus, we saw that store is actually a service now, so we can inject it onto any ember object we want.

And that’s it for today. I’m so glad you chose to learn with me today, and I hope to see you next time when we talk more about user authentication authorization.

User Auth

Subscribe to our mailing list