Фабрика: получить текущего пользователя.id для Firebase простой логин (Email / пароль)

Я ищу надежный способ иметь "текущий идентификатор пользователя"во всех моих контроллерах. Использование: Firebase Простой Логин: Email / Пароль Аутентификации

My ida: мне нужна "фабрика" , которую я могу ввести в свои контроллеры, чтобы всегда был доступен "текущий идентификатор пользователя".

Я придумал этот код:

    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 hack

=> такой же эффект-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 для любых полезных предложений! Интересно, как другие решают это!

4 ответов


Итак, вот мое решение этой точной проблемы. Я использую Firebase, FirebaseAuthClient и angularFire для моего углового приложения. Я столкнулся с той же ситуацией для моей системы входа в систему, где вы не можете ввести $scope в фабрику, и поэтому я придумал сделать контроллер, который использовал фабрику для своих методов для извлечения, добавления, обновления и удаления вещей. И в контроллере у меня есть мой материал firebaseAuth, настройка пользовательских значений и ссылок, которые я назначаю масштабы этого. После того, как пользователь вошел в систему, они будут перенаправлены в другое место, в котором.JS-файл берет на себя дочерний контроллер, когда в этом месте адреса.

мой логин также использует localStorage, поэтому логины будут сохраняться, вы можете обновить и не нужно продолжать вход в систему, и вы можете изменить его на cookies или 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);
        }
    };
}

]);

Info

вы даете фабрике только часть ссылки на путь, такую как "пользователи", которая будет использоваться как часть полного пути ref, где вы хотите сохранить свои пользовательские данные.

fireFactory.firebaseRef('users')

как только у вас есть набор ссылок для пользователя, их не нужно будет устанавливать снова, он будет просто использовать существующие данные и .авт() к нему. Кроме того, если в localStorage есть существующий "токен", он будет использовать его для аутентификации() пользователя.

В противном случае он войдет в систему() и откроет окна Oauth для них, чтобы сделать это, используя любую опцию, которую вы им предоставляете.

Я провел много времени, много-много часов дней и даже месяцев в поисках чего-то лучшего, чем это, когда дело доходит до Firebase/FirebaseAuthClient и angularFire. С тем, как Firebase API и FireAuth API, очень раздражает, чтобы они хорошо играли друг с другом при использовании их с angularFire в любом случае. Это очень расстраивает, но я наконец-то прошел через это.

Если вы хотите, чтобы проверить код в мое приложение и посмотреть, как я делаю эти вещи, вы можете найти его в эта ветвь моего вебернота GitHub repo.

не стесняйтесь вилять его, устанавливать и запускать его локально или вносить в него свой вклад, даже если вам нравится. Я мог бы использовать некоторую помощь себе:)

надеюсь, это поможет вам!!


вот как я это делаю.

прежде всего, у меня есть служба аутентификации firebase (я не использую Angularfire), которая вызывает по отдельности для обработки Логинов. Когда состояние пользователя изменяется, он $транслирует событие.

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

это, скорее всего, связано с асинхронным характером вызова. Чтобы исправить это вам придется

  • Inject $scope в заводскую функцию (аналогично angularFire зависимость)
  • использовать $scope.$apply() после распайка currentUser = user;

другое решение, которое работает для меня: