chaplinjs/chaplin

Access control checks on Controller#beforeAction

DanieleO-Fenix opened this issue · 3 comments

Good morning everyone,

i would like to thank you for your project. I would like to implement a very basic access control system on my ChaplinJs-based application performing some check on the beforeAction method as suggested by the library authors.

The use case is very simple: in the moment I want to access to a specific page (call it 'page' that corresponds to the route 'page#show' ), the page controller is instantiated, the beforeAction() is invoked, if a certain condition is satisfied the normal flow takes place ( the show() method is invoked ) otherwise the controller should not invoke the show() method because the pre-condictions of the execution of that method are not satisfied and the user should be redirected to another page,

At the moment the condition raises an event in case the user is not allowed to see the page content, the main Application object listens to this event and as callback the Chaplin.utils.redirectTo() method is invoked.

in the controleller:
beforeAction: function () {

        if (!this.userIsAllowrd()) {
            Chaplin.mediator.publish('REDIRECTME');
            return;
        }
    }

in the app object
Chaplin.mediator.subscribe('REDIRECTME', function () {

            Chaplin.utils.redirectTo('error#show');
        });

the problem is that even if the before action ask for the redirect through the event, the 'page#show' show() method is invoked and the code fails. Would you suggest me a way to stop manually the normal flow or any alternative way to handle the situation?

best regards

We are having the same challenge at the moment. Have you ever found an elegant solution for this problem? The ideal way is to return bool value in beforeAction() that would instruct the controller to halt normal flow.

In order to cancel the normal flow, we need to know that a redirect happened in the before action. The preferred way of initiating a redirect is the Controller#redirectTo method (see http://docs.chaplinjs.org/chaplin.controller.html). It sets a redirected = true flag on the controller:

https://github.com/chaplinjs/chaplin/blob/master/src/chaplin/controllers/controller.coffee#L52-L55

We’re checking for the redirected flag in the Dispatcher:

https://github.com/chaplinjs/chaplin/blob/master/src/chaplin/dispatcher.coffee#L133

In your cases you’re not using Controller#redirectTo, but the redirect is triggered somewhere else. this is totally fine, but the redirected flag is not set. As far as I can see, you can set this flag manually in your before action. This should stop the normal action from being called.

beforeAction: ->
  unless loggedIn()
    @redirected = true
    mediator.publish('event that eventually triggers a redirect')

Thanks @molily, this helps. It seems my problem was in using Chaplin utility utils.redirectTo() method in beforeAction() instead of Controller.redirectTo() that sets redirected flag.