简体   繁体   中英

Restrict access to specific routes in Ember.js (Ember.Router)

I'm currently testing Ember.Router and I'm wondering how I could restrict access to some specific routes when matching a certain criteria. In my example I'm playing with a checkout process where the billing address must be set before the user can proceed to the billing method and so on (for example: the billing method view needs to know the billing country to provide its allowed payment methods).

In my attempt I'm trying to validate the model (serialize : function () or maybe enter : function () ?) and when the given value isn't set, the router should redirect to a previous state (had to do this with a little timeout, otherwise the hash won't get updated correctly).

Here's a fiddle with my example code

http://jsfiddle.net/mediastuttgart/uMKGt/

EDIT:

Found some words by tom dale, though not related to this question but still a good answer: "The entire point of states is to avoid situations like this ... It is the responsibility of the current state to handle them.".

cf. http://github.com/emberjs/ember.js/issues/745

Well this makes sense.

EDIT2:

Though this makes sense while the location method is set to 'null'. When using 'hash' or 'history' to handle location states and the user reloads the page on a deeper route than /index - the current route must validate the values and then eventually redirect to a previous one if a certain criteria does not match (while indeed the validation belongs to the previous route).

To cut a long story short, the current route validation should depend on the previous one and should redirect to a state when all conditions are met.

Reverse order:

  • delivery method? (/#/delivery/method) nope ->
  • billing method? (/#/billing/method) nope ->
  • delivery address? (/#/delivery/address) nope ->
  • billing address - (/#/billing/address) please start here.

Looking forward to see some EmberJS folks to clear things up :)

I've been working on same. I think you're on the right track, that quote from Tom about the entire point of states really gets to the heart of it. The router is changing fast so not sure there are established patterns here, but I can share what I've learned so far.

To summarize the general issue: The Ember router uses url to serialize/deserialize app state. Other than knowing the requested route, it is stateless. The end user has complete control over this state, and can reload app in any state by entering a url. So all apps will have a common problem of when/how to verify that the requested state is 'valid' given user permissions and the current state of the model.

Coming from Rails, my first instinct is to protect routes like we would in a before filter. This is tricky in Ember - since data load is async, it is not available during initial descent into the route hierarchy. Have not gotten this approach working myself, but other's have. Typical approaches seem to be

  • use sproutcore statechart, which allows concurrent states (SinisterMinister)
  • pause state transition midstream, waiting for data to load (suggested by lukemelia)
  • in earlier versions of Ember router you could use mark transition as async but that's been removed

Given what Tom said about states, I'm trying to avoid this situation whenever possible. Instead of trying to 'protect' a route, use a mix of routes + states to ensure that user cannot reach an invalid state in the first place. In your example, you'd change to:

  • a single "routable" state at '/billing'
  • 2 "substates" named 'method' and 'address' (these should extend Ember.State instead of Ember.Router and don't set a route)
  • the initialState of '/billing' route would be 'address'
  • router.send('billingAddressUpdated') when BillingAddressModel changes (either via user action or async data load)
  • billingAddressUpdated event transitions between 'method' and 'address' substates as appropriate

BTW You'll need to use HEAD ember for this approach, as substates without routes were broken until a recent commit.

Very curious to learn how others approach this problem. Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM