How do I invoke a controller action from the adapter?

If an 401 Authorization response is received, I would like to generate an error message and invoke the logout action, thereby redirecting the user back to the login page.

This is the same action I can trigger from the main page using <a href="#" {{action 'logout'}}>Logout</a> from within the application.hbs template.

I’ve defined the logout action In my application controller as follows:

// app/controllers/application.js
export default Ember.Controller.extend({
    ...
    actions: {
        logout: function() {
            this.controllerFor('sessions').reset();
            this.transitionToRoute('sessions');
        }
    }
});

In my application RESTAdapter, I handle calls to ajaxError like this:

// app/adapters/application.js
export default DS.RESTAdapter.extend({
    ...
    ajaxError: function(jqXHR) {
        var err = this._super(jqXHR);
        if (jqXHR && jqXHR.status === 401) {
            // TODO: How can I invoke the logout action in the application controller?
            alert('Unauthorized error, please logout and login again.');
        }
        return err;
    }
});

What is the proper manner to handle these kind of network errors in a uniform and generic way?

1 Like

I’m sure there are other ways to do this but I believe one way would be to handle this in the router. Ember simple auth uses a mixin into routers that require authorization that checks if the session is present and redirect if not. They also use a mixin for the application route the function of which I can’t recall, but I could imagine has something to do with handling actions bubbled up from other controllers/routers. I believe they also utilize embers dependency injection system to provide session access to controllers and routers.

I recommend you look a little closer at GitHub - simplabs/ember-simple-auth: A library for implementing authentication/authorization in Ember.js applications. and adapt their architecture to your needs.

Hopefully that is of some use

Thanks @varblob, coincidentally I have used some of the ember-simple-auth concepts for dealing with session-handling stuff. Basically it does the following:

function ajaxError(event, jqXHR, setting, exception) {
  if (!!jqXHR.__simple_auth_authorized__ && jqXHR.status === 401) {
    ajaxError.session.trigger('authorizationFailed');
  }
}

However, my situation is slightly different so I need another way to handle this.

You could always do some instrumentation. It’s a way to keep them decoupled I suppose. You would subscribe in you application route to the events, and instrument/emit them from the adapter.

Read about it here Ember - 4.6 - Ember API Documentation