2013-06-23 60 views
6

我正在寻找一种可靠的方法来使所有控制器中的“当前用户标识”可用。 使用:火力地堡简单登录:电子邮件/密码认证FACTORY:获取当前user.id Firebase简单登录(电子邮件/密码)

我IDA:我需要一个“工厂”至极,我可以注入我的控制器, 有“当前用户ID”始终可用。

我想出了这个代码:

app.factory('User', ['angularFire', 

    //Get Current UserID 

    function(angularFire){ 

     console.log ('FACTORY: User'); 
      var currentUser = {}; 
      var ReturnStr = ''; 
     var ref = new Firebase("https://myFIREBASE.firebaseio.com/"); 
     var authClient = new FirebaseAuthClient(ref, function (err, user) { 

      if (err) { 
        ReturnStr = 'FACTORY: User Error: ' + err; 
       console.log (ReturnStr); 
         //var User = ReturnStr; 
      } else if (user) { 
       console.log ('FACTORY: User: Login successfully:'); 
       console.log (user); 
       currentUser = user; 
      } else { 
       //console.log ('-----------User: Logged Out ---------------'); 
        ReturnStr = 'FACTORY: Logged out: Redirect to Login'; 
       console.log (ReturnStr); 
       window.location.href = "/login.php"; 
      } 
     }); 

    return currentUser; 
     } 
]); 

我简单的控制器看起来像:

function ToDoCtrl($scope, User) { 
    $scope.MyUser = User; 
    $scope.MyUser.test = 'Test'; 
} 

在HTML(角谐音)我有:

<h2>{{MyUser.id}}</h2> 
<h2>{{MyUser.email}}</h2> 
<h2>{{MyUser.provider}}</h2> 
<h2>{{MyUser.test}}</h2> 

=> ID ,电子邮件,提供者是'未定义'。在控制台中,我看到了'FACTORY:User:Login successfully:'和正确的user - Object。

=>异步加载数据的问题?

我也尝试(没有运气):

 $timeout(function() { 
     currentUser = user; 
     } 

这样的工厂将是非常有用的! 谢谢你指点我在正确的方向!

编辑1.1:现在,$ rootscope破解

=>效果相同 - 是myController的太快 - 工厂放缓。

app.factory('User', ['$rootScope', '$timeout', 'angularFire', 

    //Aktueller Benutzer auslesen 

    function($rootScope, $timeout, angularFire){ 

     console.log ('FACTORY: User'); 
      var currentUser = {}; 
      var ReturnStr = ''; 
     var ref = new Firebase("https://openpsychotherapy.firebaseio.com/"); 
     var authClient = new FirebaseAuthClient(ref, function (err, user) { 

      if (err) { 
        ReturnStr = 'FACTORY: User Error: ' + err; 
       console.log (ReturnStr); 
         //var User = ReturnStr; 
      } else if (user) { 
       console.log ('FACTORY: User: Login successfully:'); 
         //currentUser = user; 

      $timeout(function() { 
         ReturnStr = 'FACTORY: Inside timout'; 
        console.log (ReturnStr); 

          currentUser = user; 
        console.log (currentUser); 

       $rootScope.myUser = user; 
       $rootScope.myUserID = user.id; 
       $rootScope.loggedIn = true; 
          $rootScope.$apply(); 

        return currentUser; 
      }); 


      } else { 
       //console.log ('-----------User: Logged Out ---------------'); 
        ReturnStr = 'FACTORY: Logged out: Redirect to Login'; 
       console.log (ReturnStr); 
         //var User = ReturnStr; 
       window.location.href = "/login.php"; 
      } 
     }); 

    return currentUser; 
     } 
]); 

TAHNKS对于任何有帮助的建议!知道别人怎么解决这个问题!

+0

我做了一个坚实的登录系统,当我回到家时,我会发布这些火的东西。这对你在这里尝试做的事情可能是完美的。 – jaredwilli

回答

14

所以这里是我对这个确切问题的解决方案。我正在为我的Angular应用使用Firebase,FirebaseAuthClient和angularFire。我遇到了与我的登录系统相同的情况,无法将$ scope注入到工厂中,因此我想出了一个控制器,它使用工厂的方法来检索,添加,更新和删除事物。在控制器中,我有我的firebaseAuth的东西,用户值的设置,以及我分配给这个范围的引用。一旦用户登录,他们被重定向到另一个位置,此时app.js文件将在该地址位置处接管子控制器。

我的登录也使用本地存储,所以登录将持续存在,你可以刷新,而不必保留登录,您可以更改它是饼干或sessionStorage的很容易的。

这需要根据您的需求进行调整,特别是如果您选择使用此方法,则无论如何这都相当复杂,但这对我来说非常稳固,我不再需要担心firebaseAuth或angularFire的东西,现在我的工厂都设置为来回传递数据。我只是用指令来做angularJS的东西。所以这是我的代码。

注:这将需要修改,有些事情会是伪或者开放式的为你找出适合您的需求。

AuthCtrl.js

'use strict'; 

angular.module('YOUR_APP', []). 
controller('AuthCtrl', [ 
'$scope', 
'$location', 
'angularFire', 
'fireFactory', 

function AuthCtrl($scope, $location, angularFire, fireFactory) { 
    // FirebaseAuth callback 
    $scope.authCallback = function(error, user) { 
     if (error) { 
      console.log('error: ', error.code); 
      /*if (error.code === 'EXPIRED_TOKEN') { 
       $location.path('/'); 
      }*/ 
     } else if (user) { 
      console.log('Logged In', $scope); 
      // Store the auth token 
      localStorage.setItem('token', user.firebaseAuthToken); 
      $scope.isLoggedIn = true; 

      $scope.userId = user.id; 

      // Set the userRef and add user child refs once 
      $scope.userRef = fireFactory.firebaseRef('users').child(user.id); 
      $scope.userRef.once('value', function(data) { 
       // Set the userRef children if this is first login 
       var val = data.val(); 
       var info = { 
        userId: user.id, 
        name: user.name 
       }; 
       // Use snapshot value if not first login 
       if (val) { 
        info = val; 
       } 
       $scope.userRef.set(info); // set user child data once 
      }); 

      $location.path('/user/' + $scope.userRef.name()); 
     } else { 
      localStorage.clear(); 
      $scope.isLoggedIn = false; 
      $location.path('/'); 
     } 
    }; 

    var authClient = new FirebaseAuthClient(fireFactory.firebaseRef('users'), $scope.authCallback); 

    $scope.login = function(provider) { 
     $scope.token = localStorage.getItem('token'); 
     var options = { 
      'rememberMe': true 
     }; 
     provider = 'twitter'; 

     if ($scope.token) { 
      console.log('login with token', $scope.token); 
      fireFactory.firebaseRef('users').auth($scope.token, $scope.authCallback); 
     } else { 
      console.log('login with authClient'); 
      authClient.login(provider, options); 
     } 
    }; 

    $scope.logout = function() { 
     localStorage.clear(); 
     authClient.logout(); 
     $location.path('/'); 
    }; 
} 

]);

现在为漂亮,简单但相当可重用的工厂。您需要为您的应用程序设置Firebase路径,以便baseUrl变量运行。

fireFactory.js

'use strict'; 
angular.module('YOUR_APP'). 
factory('fireFactory', [ 
function fireFactory() { 
    return { 
     firebaseRef: function(path) { 
      var baseUrl = 'https://YOUR_FIREBASE_PATH.firebaseio.com'; 
      path = (path !== '') ? baseUrl + '/' + path : baseUrl; 
      return new Firebase(path); 
     } 
    }; 
} 

]);

信息

你给工厂只是一块路径参考的,如将被用作完整路径裁判要存储用户数据的一部分“用户”。

fireFactory.firebaseRef('users') 

一旦你有一个用户设置的基准,他们不会需要设置再次它只是利用现有的数据和.auth()把它。另外,如果localStorage中存在一个'token',它也会使用它来授权()用户。

,否则会登录()的用户和流行打开的Oauth窗户他们这样做使用任何选项,则提供给他们。

我花了很多时间,很多很多时间天是甚至几个月寻找比这更好的东西,当涉及到火力地堡/ FirebaseAuthClient和angularFire。随着Firebase API和FireAuth API的使用方式,在无论如何将它们与angularFire一起使用时,让它们相互之间很好地发挥作用是非常烦人的。这是非常令人沮丧的,但我终于得到了它。

如果你想看看我的应用程序的代码,看看我如何更完整地完成这些事情,你可以在this branch of my Webernote github repo找到它。

随意分叉它,在本地安装和运行它,或者即使你喜欢它,也可以对其进行贡献。我可以自己使用一些帮助:)

希望这可以帮助你!

+0

这真的帮了我一个类似的问题,感谢分享。 –

+0

乐意帮忙。我很高兴你发现它很有用。 :) – jaredwilli

+0

感谢您分享代码 – Iladarsda

0

这很可能是由于调用的异步性质。要解决它,你将不得不

  • 进样$scope进厂功能(类似于angularFire依赖)
  • 使用$scope.$apply()的分配新建分配FY currentUser = user;
+0

谢谢!是的,这是一个异步问题。现在我有这个:错误:未知的提供者:$ scopeProvider < - $ scope < - 用户我目前的工厂看起来像:检查编辑1 –

+0

现在我必须问:如何将$ scope注入工厂函数?谢谢你的帮助! –

+1

=>工厂无权访问当前控制器/指令范围,因为没有一个。他们确实可以访问应用程序的根目录,这就是$ rootScope可用的原因。 (http://stackoverflow.com/questions/14056874/how-to-emit-events-from-a-factory)=>使用$ rootscope –

1

这里是我做到这一点了。

首先,我有我的firebase身份验证服务(我没有使用Angularfire),呼吁Singly处理登录。当用户状态改变时,$广播一个事件。

p4pApp.factory('firebaseAuth', function($rootScope, singlyAuth) { 
var auth = {}, 
    FBref = new Firebase(p4pApp.FIREBASEPATH); 

auth.login = function(service) { 
    singlyAuth.login(service); 
}; 

auth.logout = function() { 
    FBref.unauth(); 
    auth.user = null; 
    auth.broadcastAuthEvent(); 
}; 

auth.broadcastAuthEvent = function() { 
    $rootScope.$broadcast('authEvent'); 
}; 

auth.authWithToken = function(token) { 
    if (token !== undefined) { 
     FBref.auth(token, function(error, authData) { 
      if(!error) { 
       auth.user = authData.auth.account; 
       auth.broadcastAuthEvent(); 
      } else { 
       auth.user = null; 
       auth.broadcastAuthEvent(); 
      } 
     }, function(error) { 
      auth.user = null; 
      auth.broadcastAuthEvent(); 
     }); 
    } 
}; 

return auth; 
}); 

然后我有一个'顶级'控制器,照顾授权状态。

var AuthCtrl = function($scope, firebaseAuth, singlyAuth, firebase, user) { 
$scope.user = null; 

$scope.logout = function() { 
    firebaseAuth.logout(); 
}; 

$scope.isLoggedIn = function() { 
    return !!$scope.user; 
}; 

// src: Alex Vanston (https://coderwall.com/p/ngisma) 
$scope.safeApply = function(fn) { 
    var phase = this.$root.$$phase; 
    if (phase == '$apply' || phase == '$digest') { 
     if(fn && (typeof(fn) === 'function')) { 
      fn(); 
     } 
    } else { 
     this.$apply(fn); 
    } 
}; 

$scope.$on('authEvent', function() { 
    $scope.safeApply(function() { 
     $scope.user = firebaseAuth.user; 
    }); 

    user.setID(firebaseAuth.user); 

    if (firebaseAuth.user) { 
     firebase.fetch(['users', firebaseAuth.user], function(results) { 
      if (results) { 
       user.setData(results); 
      } else { 
       results = {}; 
       results.createdAt = DateTimeStamp(); 
      } 

      results.lastLogin = DateTimeStamp(); 

      firebase.set('users', firebaseAuth.user, results); 
     });  
    } else { 
     user.clearData(); 
    } 
}); 
}; 

最后,我使用专用用户服务来维护用户状态。(它仍在开发中)

p4pApp.factory('user', function() { 
var userService = {}, user={}; 

user.data = {}; 

userService.setID = function(id) { 
    user.id = id; 
}; 

userService.getID = function() { 
    return user.id; 
}; 

userService.setData = function(data) { 
    user.data = data || {}; 
}; 

userService.getData = function() { 
    return user.data; 
}; 

userService.clearData = function() { 
    user.data = {}; 
}; 

userService.setDataField = function(field, data) { 
    user.data[field] = data; 
}; 

userService.clearDataField = function(field) { 
    delete user.data[field]; 
}; 

userService.pushData = function(key, data) { 
    if (typeof(key) === 'string') { 
     user.data[key] = data; 
    } else { 
     _.reduce(key, function(obj, child, index, list) { 
      obj[child] = obj[child] || {}; 

      if (index == list.length-1) { 
       obj[child] = data; 
      } 

      return obj[child]; 
     }, user.data);   
    } 
}; 

userService.deleteData = function(key) { 
    if (typeof(key) === 'string') { 
     delete user.data[key]; 
    } else { 
     _.reduce(key, function(obj, child, index, list) { 
      obj[child] = obj[child] || {}; 

      if (index == list.length-1) { 
       delete obj[child]; 
       return; 
      } 

      return obj[child]; 
     }, user.data);   
    } 
}; 

return userService; 
}); 
0

为我的作品的另一个解决方案:

account.service.js

(function() { 
    'use strict'; 

    angular 
     .module('app.account') 
     .factory('Account', Account); 

    Account.$inject = [ 
     '$firebaseAuth', 
     '$firebaseObject' 
    ]; 

    /* @ngInject */ 
    function Account(
     $firebaseAuth, 
     $firebaseObject, 
    ) { 
     var firebaseRef = new Firebase('https://<<-- MY_FIREBASE -->>.firebaseio.com'); 
     var authObj = $firebaseAuth(firebaseRef); 
     var service = { 
      userInfo: null 
     }; 
     activate(); 
     return service; 

     //////////////// 

     function activate() { 
      // Add listeners for authentication state changes 
      authObj.$onAuth(function(authData) { 
       if (authData) { 
        // Load the userInfo 
        loadUserInfo(authData); 
       } else { 
        // Destroy the userInfo Object if one exists 
        if (service.userInfo) { 
         service.userInfo.$destroy(); 
         service.userInfo = null; 
        } 
       } 
      }); 
     } 

     function loadUserInfo(authData) { 
      var userRef = firebaseRef.child('users').child(authData.uid); 
      var loadedInfo = $firebaseObject(userRef); 

      loadedInfo.$loaded() 
      .then(function() { 
       service.userInfo = loadedInfo; 
      }) 
      .catch(function(error) { 
       switch (error.code) { 
        case 'PERMISSION_DENIED': 
         alert('You don\'t have the permission to see that data.'); 
         break; 
        default: 
         alert('Couldn\'t load the user info.'); 
       } 
      }); 
     } 
    } 
})(); 

一些-component.controller.js

(function() { 
    'use strict'; 

    angular 
     .module('app') 
     .controller('SomeController', SomeController); 

    SomeController.$inject = [ 
     'Account' 
    ]; 

    /* @ngInject */ 
    function SomeController(
     Account 
    ) { 
     var vm = this; 

     vm.userInfo  = userInfo; 

     //////////////// 

     function userInfo() { 
      return Account.userInfo; 
     } 

     ... 
    } 
})(); 

一些分量。 html

... 
<div class="user-id"> 
    {{vm.userInfo().id}} 
<div> 
... 
相关问题