5

I am trying to set up ember-simple-auth with a django-rest-framework backend, but I'm running into some trouble saving the user to the session. I have to be able to do something like this in my templates:

<h2>Welcome back, {{session.user}}</h2>

So following several guides I found, I have got the authentication and authorization working so that I can get a valid token and use is in requests. To get the user on the session, I have modified App.CustomAuthenticator.authenticate so that when the token is returned, the username is also stored to the session:

authenticate: function(credentials) {
    var _this = this;
    return new Ember.RSVP.Promise(function(resolve, reject) {
        Ember.$.ajax({
            url: _this.tokenEndpoint,
            type: 'POST',
            data: JSON.stringify({username: credentials.identification, password: credentials.password }),
            contentType: 'application/json'
        }).then(function(response) {
            Ember.run(function() {
                resolve({
                    token: response.token,
                    username: credentials.identification
                });
            });
        }, function(xhr, status, error) {
            var response = JSON.parse(xhr.responseText);
            Ember.run(function() {
                reject(response.error);
            });
        });
    });
},

I then modified Application.intializer to give session a user property:

Ember.Application.initializer({
    name: 'authentication',
    before: 'simple-auth',
    initialize: function(container, application) {
        // register the custom authenticator and authorizer so Ember Simple Auth can find them
        container.register('authenticator:custom', App.CustomAuthenticator);
        container.register('authorizer:custom', App.CustomAuthorizer);
        SimpleAuth.Session.reopen({
            user: function() {
              var username = this.get('username');
              if (!Ember.isEmpty(username)) {
                return container.lookup('store:main').find('user', {username: username});
              }
            }.property('username')
        });
    }
});

However, when {{session.user.username}} is rendered it is just an empty string. My questions are:

  1. Is this really the best way to assigning a user to the session? It seems clumsy to me but I can't see anything better.
  2. I assume that the empty string is because a Promise is returned rather than a User object, so how to I resolve it?
aquavitae
  • 17,414
  • 11
  • 63
  • 106
  • For now that's the way to do it actually. With the next release of Ember Simple Auth this will get easier as you can then specify your own session class and don't have to reopen the existing session anymore. – marcoow Jul 23 '14 at 08:22
  • Ok, so then how do I get an actual `User` out? – aquavitae Jul 23 '14 at 08:40
  • checkout the example in the repo that does exactly what you want: https://github.com/simplabs/ember-simple-auth/blob/master/examples/4-authenticated-account.html – marcoow Jul 23 '14 at 09:01
  • I looked at it already - that is where I got the idea from. However, in the example, `find` is given an id. In my case it's used to search, i.e. `.find('user', {username: username})`. – aquavitae Jul 23 '14 at 09:07
  • That should be the same thing - only results in 2 different requests to the REST API. The only thing that might be different is that your `.find` might return an array whereas the `.find` with an id in the example returns the record directly. Just an assumption though - didn't try that. – marcoow Jul 23 '14 at 09:24

2 Answers2

14

To tag off of @marcoow's response, here's how to implement it in Ember CLI:

index.html:

window.ENV['simple-auth'] = {
  authorizer: 'simple-auth-authorizer:devise',
  session: 'session:withCurrentUser'
};

initializers/customize-session.js:

import Session from 'simple-auth/session';

var SessionWithCurrentUser = Session.extend({
  currentUser: function() {
    var userId = this.get('user_id');
    if (!Ember.isEmpty(userId)) {
      return this.container.lookup('store:main').find('user', userId);
    }
  }.property('user_id')
});

export default {
  name: 'customize-session',
  initialize: function(container) {
    container.register('session:withCurrentUser', SessionWithCurrentUser);
  }
};
michael
  • 2,977
  • 3
  • 20
  • 26
  • Thanks for providing the final implementation. I had exactly the same situation. Thanks a lot. – Tushar Patel Sep 05 '14 at 06:10
  • This might help today: http://stackoverflow.com/questions/30872684/ember-simple-auth-injecting-current-user-into-every-route – Toni Aug 03 '15 at 12:56
4

With the 0.6.4 release you can now specify a custom session class without having to reopen, see release note here: https://github.com/simplabs/ember-simple-auth/releases/tag/0.6.4. This is how it works:

App.CustomSession = SimpleAuth.Session.extend({
  account: function() {
    var accountId = this.get('account_id');
    if (!Ember.isEmpty(accountId)) {
      return this.container.lookup('store:main').find('account', accountId);
    }
  }.property('account_id')
});
…
container.register('session:custom', App.CustomSession);
…
window.ENV['simple-auth'] = {
  session: 'session:custom',
}
Rimian
  • 36,864
  • 16
  • 117
  • 117
marcoow
  • 4,062
  • 1
  • 14
  • 21