Ember-simple-auth cant get currentUser after reload


#1

Hi, Anybody can help me with this?

I have a simple Ember app (repo) with authentication using ember-simple-auth (i followed this article https://medium.com/@benhansen/token-based-authentication-with-jwt-ember-and-rails-af54b03fe237). After logging in I have access to currentUser in my routes, controllers and templates. However, if I navigate to any route besides my ApplicationRoute and reload the browser, I can no longer access currentUser in that route, but it’s available in the template. If I navigate back to application route and navigate to different one again, then I can access the currentUser. How can I fix this, i.e. I want to be able to access currentUser in any route even after reload?

ApplicationRoute:

import Ember from 'ember';
import ApplicationRouteMixin from 'ember-simple-auth/mixins/application-route-mixin';

export default Ember.Route.extend(ApplicationRouteMixin, {
  sessionAccount: Ember.inject.service(),
  beforeModel() {
    this.get('sessionAccount').loadCurrentUser();
  }
});

SessionAccount service:

import Ember from 'ember';

const { inject: { service }, RSVP } = Ember;

export default Ember.Service.extend({
  session: service('session'),
  store: service(),


  loadCurrentUser() {
    if (this.get('session.isAuthenticated')) {
      this.get('store')
      .queryRecord('user', { me: true })
      .then((user) => {
        this.set('currentUser', user);
      });
    } else {
      return RSVP.resolve();
    }
  }
});

Bookings route - the ‘other’ route:

import Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';

export default Ember.Route.extend(AuthenticatedRouteMixin, {
  sessionAccount: Ember.inject.service(),

  model() {
    const currentUser = this.get('sessionAccount.currentUser');

    return this.get('store').query('booking', {
      filter: {
        'user_id': currentUser.id
      },
      include: 'rental,rental.rental-ratings'
    });
  }
});

#2

Hi @SimonBo I think the problem may be that you’re sidestepping the Ember Router here for your async data fetch and that can be difficult to debug and lead to unexpected results. I think what’s happening is that when you refresh on one of those other routes, for example, is the application route is loaded, starting with beforeModel which kicks off the async request in your service but nothing is blocking/waiting for this to complete so then your app loads the ‘other’ route, and since that model hook is dependent on something that doesn’t necessarily exist yet, it doesn’t know what to do.

There are probably a couple ways to solve this but my recommendation would be to move the queryRecord('user', {me:true}) call into the application route model hook:

import Ember from 'ember';
import ApplicationRouteMixin from 'ember-simple-auth/mixins/application-route-mixin';

export default Ember.Route.extend(ApplicationRouteMixin, {
  sessionAccount: Ember.inject.service(),
  model() {
    return RSVP.hash({
      me: this.get('store').queryRecord('user', { me: true })
    });
  }
});

Then in the application route, probably in setupController, or in the application controller, take the record in model.me or model.get('me') and say: this.get('sessionAccount').set('currentUser', model.get('me'));

Another approach you could take is making the loadCurrentUser() method return a proper promise, and then using that method in the model hook of your application route (not the beforeModel hook). Either way, this is using the Ember Router to do all the necessary waiting for async data. As a general rule of thumb, you should try and use the Router as much as possible for async data fetching. Async logic is difficult and can cause a lot of problems, and the Router has been carefully designed to make that stuff a lot easier. Of course there are some situations where using the Router just doesn’t fit your use case. For many of those circumstances I’d recommend giving ember-concurrency a look. It’s a great addon that can really help with async tasks.


#3

@dknutsen thx for help. I ended up following the tutorial form Ember simple auth github repo. Who would have thought this would work:) Had to change code in app/routes/application.js, also changed the name of my service from ‘sessionAccount’ to ‘currentUser’:

// app/routes/application.js
import Ember from 'ember';
import ApplicationRouteMixin from 'ember-simple-auth/mixins/application-route-mixin';

const { service } = Ember.inject;

export default Ember.Route.extend(ApplicationRouteMixin, {
  currentUser: service(),

  beforeModel() {
    return this._loadCurrentUser();
  },

  sessionAuthenticated() {
    this._super(...arguments);
    this._loadCurrentUser();
  },

  _loadCurrentUser() {
    return this.get('currentUser').load().catch(() => this.get('session').invalidate());
  }
});