0

I am creating an upload page in my Angular (ui-router) & Firebase app and would like the upload page to only be available to users who are signed in. The idea is that if an anonymous (logged out/unregistered) user tries to access the upload URL example.com/upload, they will be sent to example.com/posts.

I tried to accomplish this by writing an if statement in my upload.ctrl.js controller that checks to see if a user is logged out and if the user is indeed logged out, I have Angular's $location service change the path to /posts which is the root url of my app like so:

if(Auth.logout) {
    $location.path('/posts');

    // Added the following line for feedback in console
    console.log('Auth.logout is true');
}

But if a user is logs in and navigates to /upload, the upload.tpl.html template will load fine but, the URL will be switched to /posts instead of /upload. This action is only supposed to happen if the user is logged out but, it is happening even if the user is logged in.

I see a clue in the line I added to the if statement which is console.log('Auth.logout is true');. I am not sure why but it gets called twice whenever I attempt to navigate to /upload while logged in or logged out. It seems that Auth.logout is always true and that is why the URL always is at /posts when I try to go to /upload.

I have created a Plunker that demonstrates this problem here

http://plnkr.co/edit/jx7xuyqxs3dPfQqTms6C?p=preview

You can launch it in a separate window to see the URL changes (or non-changes in this case).

To sign in you can use:

  1. email: a@a.com
  2. password: 1111

Any ideas on how to fix this issue? Thanks in advance.

NOTE:

To manually change the URL to end in /upload copy and paste http://run.plnkr.co/ZzrkWWeRl32wZsQ2/#/posts into a new browser tab when the Plunkr is running (the separate window they build for you does not allow you to change the URL) Once you have it running in a new tab you can manually change the URL to http://run.plnkr.co/ZzrkWWeRl32wZsQ2/#/upload (while logged in or logged out) to see how the URL will change back to http://run.plnkr.co/ZzrkWWeRl32wZsQ2/#/posts

UPDATE

I was able to solve this by changing the if statement condition like so

if(!Auth.user) {
    $location.path('/posts');
}

If Auth.user exists and is true then the user is authentic.


Files

upload.ctrl.js

app.controller('UploadCtrl', function ($scope, $stateParams, $location, Auth) {

        $scope.signedIn = Auth.signedIn;
        $scope.logout = Auth.logout;

        if(Auth.logout) {
            $location.path('/posts');
            console.log('Auth.logout is true');
        }
    });

auth.serv.js

app.factory('Auth', function ($firebaseSimpleLogin, FIREBASE_URL, $rootScope, $firebase) {
        var ref = new Firebase(FIREBASE_URL);
        var auth = $firebaseSimpleLogin(ref);

        var Auth = {
            login: function (user) {
                return auth.$login('password', user);
            },
            logout: function () {
                auth.$logout();
            },
            resolveUser: function() {
                return auth.$getCurrentUser();
            },
            signedIn: function() {
                return !!Auth.user.provider;
            },
            user: {}
        };

        $rootScope.$on('$firebaseSimpleLogin:login', function(e, user) {
            angular.copy(user, Auth.user);
            Auth.user.profile = $firebase(ref.child('profile').child(Auth.user.uid)).$asObject();

            console.log(Auth.user);
        });
        $rootScope.$on('$firebaseSimpleLogin:logout', function() {
            console.log('logged out');

            if(Auth.user && Auth.user.profile) {
                Auth.user.profile.$destroy();
            }
            angular.copy({}, Auth.user);
        });

        return Auth;
    });

1 Answers1

1

There is updated working plunker

This was upload.ctrl.js before

if(Auth.logout) {
   // this is reason why it goes to posts
   $location.path('/posts');
   console.log('Auth.logout is true');
}

As we can see, the check is if(Auth.logout). And because logout is a function, this statement always returns true. And that means, that we always go to $location.path('/posts');

This is updated version, see the () at the end of logout: in the if(Auth.logout())

if(Auth.logout()) { // function call
   $location.path('/posts');
   console.log('Auth.logout is true');
}

Check it here

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • Thanks. Well the url turns to `/upload` but the user gets logged out. How to make it so the user does not get logged out? –  Nov 28 '14 at 14:47
  • Well honestly, it is yours code. So you should keep some Auth.isAuthenticated proeprty... and evaluate this property. On Logout set it to false, on login set it to true... Does it help? Other words, I did not investigate WHY you call Auth.Logout() - thought you know why. I just explained why it was not working... – Radim Köhler Nov 28 '14 at 14:54
  • Ok I see what you are saying. Calling `Auth.logout()` is not what I should be doing. What I am trying to do in the if statement's condition is just check if the user is signed in. If the user is signed in then execute `$location.path('/posts');`. Do you know what I mean? –  Nov 28 '14 at 15:54
  • 1
    I understand 100%! Exactly this is my suggestion: try to keep some setting `IsAuthenticated`, e.g. as a property on the `Auth`. Set it to true on Login and set it to false on LogOut... just a draft. Here I created some example of LOGIN functionality... http://stackoverflow.com/a/26702638/1679310 maybe it could help to get some ideas – Radim Köhler Nov 28 '14 at 15:55
  • Right on. Well my code is actually all from the Thinkster tutorial https://thinkster.io/angulartutorial/learn-to-build-realtime-webapps/ and I realized I can just use `(!Auth.user)` for the condition of the if statement. That did it :) –  Nov 30 '14 at 21:21