2013-06-23 31 views
6

Tôi đang tìm một cách chắc chắn để có 'id người dùng hiện tại' trong tất cả các trình điều khiển của tôi có sẵn. Sử dụng: Firebase Đăng nhập Đơn giản: Xác thực Email/Mật khẩuNHÀ MÁY: lấy user.id hiện tại cho Đăng nhập Đơn giản Firebase (Email/Mật khẩu)

Ida của tôi: Tôi cần một 'Nhà máy' mà tôi có thể đưa vào bộ điều khiển, để luôn có 'id người dùng hiện tại'.

tôi đã đưa ra với mã này:

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; 
     } 
]); 

điều khiển đơn giản nhất của tôi trông giống như:

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

Trong HTML (partials góc) i có:

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

=> id , email, nhà cung cấp là 'không xác định'. Trong giao diện điều khiển, tôi thấy 'NHÀ MÁY: Người dùng: Đăng nhập thành công:' với đúng đối tượng - Đối tượng.

=> Tải không đồng bộ về vấn đề dữ liệu?

Tôi cũng đã thử nghiệm (không có may mắn):

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

một NHÀ MÁY như vậy sẽ rất hữu ích! Cảm ơn bạn đã chỉ cho tôi đúng hướng!

Sửa 1.1: Bây giờ, với $ rootscope Hack

=> Cùng tác - MyController là quá nhanh - nhà máy chậm lại.

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 cho bất kỳ đề xuất hữu ích nào! Wonderin cách người khác giải quyết chuyện này!

+0

Tôi đã tạo một hệ thống đăng nhập vững chắc với những thứ lửa này tôi sẽ đăng khi tôi về nhà sau một lát. Nó có thể là hoàn hảo cho những gì bạn đang cố gắng làm ở đây. – jaredwilli

Trả lời

14

Vì vậy, đây là giải pháp của tôi cho vấn đề chính xác này. Tôi đang sử dụng Firebase, FirebaseAuthClient và angularFire cho ứng dụng Góc của tôi. Tôi chạy vào tình huống tương tự cho hệ thống đăng nhập của tôi, nơi bạn không thể tiêm phạm vi $ vào nhà máy và do đó tôi đã tạo ra một bộ điều khiển sử dụng một nhà máy cho các phương pháp để truy xuất, thêm, cập nhật và xóa mọi thứ. Và trong bộ điều khiển, tôi có nội dung firebaseAuth đang diễn ra, cài đặt của giá trị Người dùng và số tham chiếu mà tôi gán cho phạm vi đó. Sau khi người dùng đăng nhập, họ được chuyển hướng đến một vị trí khác, tại thời điểm đó tệp app.js sẽ tiếp quản với bộ điều khiển con khi ở vị trí địa chỉ đó.

Đăng nhập của tôi cũng sử dụng localStorage, vì vậy thông tin đăng nhập sẽ tiếp tục, bạn có thể làm mới và không phải tiếp tục đăng nhập và bạn có thể thay đổi thành cookie hoặc sessionStorage dễ dàng.

Điều này sẽ cần phải được điều chỉnh cho nhu cầu của bạn một cách cụ thể nếu bạn chọn sử dụng phương pháp này, nó khá phức tạp không có vấn đề gì, nhưng điều này là rất vững chắc đối với tôi và tôi không còn cần phải lo lắng về firebaseAuth hoặc Bây giờ các công cụ của tôi đã được thiết lập để truyền dữ liệu qua lại. Tôi chỉ đang thực hiện công cụ angularJS chủ yếu với các chỉ thị. Đây là mã của tôi.

LƯU Ý: Điều này sẽ cần sửa đổi và một số thứ sẽ được giả hoặc mở để bạn tìm ra nhu cầu của mình.

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('/'); 
    }; 
} 

]);

Và bây giờ cho nhà máy đẹp và đơn giản nhưng khá tái sử dụng. Bạn cần đặt đường dẫn Firebase cho ứng dụng của mình để biến baseUrl hoạt động.

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); 
     } 
    }; 
} 

]);

Thông tin

Bạn cung cấp cho các nhà máy chỉ là một mảnh của đường dẫn tham chiếu như 'người sử dụng mà sẽ được sử dụng như là một phần của con đường ref đầy đủ đến nơi bạn muốn lưu trữ dữ liệu người dùng của bạn.

fireFactory.firebaseRef('users') 

Khi bạn đã đặt tham chiếu cho người dùng, họ sẽ không cần phải đặt lại nó sẽ chỉ sử dụng dữ liệu hiện có và .auth() cho nó. Ngoài ra nếu có một 'token' hiện có trong localStorage, nó cũng sẽ sử dụng nó để xác thực người dùng.

Nếu không, nó sẽ đăng nhập() người dùng và pop mở cửa sổ Oauth để họ làm như vậy bằng bất kỳ tùy chọn nào bạn cung cấp cho họ.

Tôi đã dành rất nhiều thời gian, nhiều giờ nhiều ngày và thậm chí cả tháng tìm kiếm điều gì đó tốt hơn điều này khi nói đến Firebase/FirebaseAuthClient và angularFire. Với cách API Firebase và API FireAuth, rất khó để làm cho chúng phát độc đáo với nhau khi sử dụng chúng với angularFire. Nó rất bực bội nhưng cuối cùng tôi đã vượt qua nó.

Nếu bạn muốn kiểm tra mã cho ứng dụng của tôi và xem cách tôi đang làm những việc này hoàn toàn hơn, bạn có thể tìm thấy nó trong this branch of my Webernote github repo.

Hãy thoải mái ngã ba, cài đặt và chạy nội bộ hoặc đóng góp ngay cả khi bạn muốn. Tôi có thể sử dụng một số trợ giúp cho bản thân mình :)

Hy vọng điều này sẽ giúp bạn !!

+0

Điều này thực sự đã giúp tôi cho một vấn đề tương tự, cảm ơn bạn đã chia sẻ. –

+0

Rất vui được trợ giúp. Tôi rất vui vì bạn thấy nó hữu ích. :) – jaredwilli

+0

cảm ơn bạn đã chia sẻ mã – Iladarsda

0

Điều này rất có thể là do tính chất không đồng bộ của cuộc gọi. Để khắc phục nó, bạn sẽ phải

  • Tiêm $scope vào chức năng nhà máy (tương tự như angularFire phụ thuộc)
  • Sử dụng $scope.$apply() sau assigment currentUser = user;
+0

Cảm ơn! Vâng, đó là một vấn đề không đồng bộ. Bây giờ tôi có điều này: Lỗi: Nhà cung cấp không xác định: $ scopeProvider <- $ scope <- Người dùng Nhà máy hiện tại của tôi trông giống như: Kiểm tra Edit1 –

+0

Bây giờ tôi phải hỏi: howto inject $ scope vào chức năng của nhà máy? Cảm ơn bạn đã giúp đỡ! –

+1

=> Nhà máy không có quyền truy cập vào phạm vi điều khiển/chỉ thị hiện tại vì không có. Họ có quyền truy cập vào thư mục gốc của ứng dụng và đó là lý do tại sao $ rootScope có sẵn. (http://stackoverflow.com/questions/14056874/how-to-emit-events-from-a-factory) => Thử nghiệm với $ rootscope –

1

Dưới đây là cách tôi làm điều đó.

Trước hết, tôi có dịch vụ autbase firebase của mình (Tôi không sử dụng Angularfire) gọi ra Singly để xử lý thông tin đăng nhập. Khi trạng thái người dùng thay đổi, nó sẽ phát sóng một sự kiện.

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; 
}); 

Sau đó, tôi có bộ điều khiển 'cấp cao nhất' trông sau trạng thái ủy quyền.

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(); 
    } 
}); 
}; 

Cuối cùng, tôi sử dụng dịch vụ người dùng chuyên dụng để duy trì trạng thái người dùng.(Nó vẫn đang được phát triển)

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

Một giải pháp mà làm việc cho tôi:

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.'); 
       } 
      }); 
     } 
    } 
})(); 

số-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; 
     } 

     ... 
    } 
})(); 

một số thành phần. html

... 
<div class="user-id"> 
    {{vm.userInfo().id}} 
<div> 
... 
Các vấn đề liên quan