Protecting a route using Firebase Simple Login

纵饮孤独 提交于 2019-12-01 07:54:20

问题


I'm trying to implement the following sequence of events in an Ember app that uses Firebase Simple Login and ember-cli.

  1. Check if the user is authenticated before allowing entry to any route. All routes need to be authenticated.
  2. If the user is not authenticated, redirect to LoginRoute. If the user is authenticated, allow them to enter the route.

In order to accomplish step 1, I reopen Ember.Route in an initializer and implement a beforeModel hook.

`import LoginController from "tracking/controllers/login"`

AuthInitializer =
  name: 'authInitializer'

  initialize: (container, application) ->
    # Register LoginController with all controllers/routes
    application.register 'main:auth', LoginController
    application.inject 'route', 'auth', 'main:auth'
    application.inject 'controller', 'auth', 'main:auth'
    application.inject 'main:auth', 'store', 'store:main'

    # Ensure user is logged in before allowing entry
    Ember.Route.reopen
      beforeModel: (transition) ->
        @transitionTo 'login' if !@get('auth.isAuthed')

`export default AuthInitializer`

The above code does indeed redirect to login if the user is not currently logged in.

LoginController simply instantiates a new FirebaseSimpleLogin object and registers the appropriate callback function.

LoginController = Ember.ObjectController.extend
  # Some of the controller is omitted for brevity...

  auth: null
  isAuthed: false

  init: ->
    dbRef = new Firebase('https://dawnbreaker.firebaseio.com')
    @set('auth', new FirebaseSimpleLogin(dbRef, @authCompleted.bind(@)))
    @_super()

  authCompleted: (error, user) ->
    if error
      # Handle invalid login attempt..
    else if user
      # Handle successful login..
      unless @get('isAuthed')
        @set('currentUserId', user.id)
        @set('isAuthed', true)
        @transitionToRoute('index')
    else
      # Handle logout..
      @set('currentUserId', null)
      @set('isAuthed', false)

`export default LoginController`

There is two problems with my implementation.

  • When LoginController first initializes, isAuthed is set to false. Therefore, when authCompleted finishes, the app will always redirect to index.
  • The beforeModel hook executes before the authCompleted callback finishes, causing the hook to redirect to login.

What results from a page refresh is

  1. The login template flashes for a second.
  2. The app transitions to index.

This causes every page refresh to lose its current location (redirecting to the index route).

The question is, how can I protect a route using Ember and Firebase Simple Login? Any help would be appreciated.


回答1:


Totally my opinion, but I like making the auth part of the resource tree. It doesn't need to be part of the url, but can be. Using this way, it can still use a global controller (it will be hooked up based on what's returned from the call, or some other hookup if you fetch it in the login).

App.Router.map(function() {
  this.resource('auth', {path:''}, function(){
    this.resource('foo');
    this.resource('bar', function(){
      this.route('baz')
    });
  });
  this.route('login');
});

App.AuthRoute = Em.Route.extend({
  model: function(params, transition){
    var self = this;
    // you can skip calling back with a local property
    return $.getJSON('/auth').then(function(result){
      if(!result.good){
        self.transitionTo('login');
      }
      return result;
    });
  }
}); 

http://emberjs.jsbin.com/OxIDiVU/668/edit

In the case of a non-promise callback, you can create your own promise, and resolve that when appropriate.

model: function(){
  var defer = Ember.RSVP.defer(),
      firebase = new Firebase('https://dawnbreaker.firebaseio.com'),
      fbLogin = new FirebaseSimpleLogin(firebase, this.authCompleted.bind(this));


  this.setProperties({
      defer: defer, 
      firebase: firebase,
      fbLogin: fbLogin
  });

  return defer.promise.then(function(result){
    // maybe redirect if authed etc...
  });
},
authCompleted: function(error, user){
  var defer = this.get('defer');
  //if authenticated
  defer.resolve({auth:true});      
  //else authenticated
  defer.resolve({auth:false});      
}


来源:https://stackoverflow.com/questions/24234810/protecting-a-route-using-firebase-simple-login

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!