4

I've been trying to figure out how to correctly implement firebase's simpleLogin in my ember.js app from this blog post and this source code to no avail.

The blog post example uses github as the authentication provider, but I need to use the email & password option. What I have so far successfully adds the user to the registered users of the firebase in question and can spit back a user.id and user.email, but I'm unable to login with the user because it's not adding the user to the firebase users/ path.

AuthController.js

App.AuthController = Ember.Controller.extend({
    authed: false,
    currentUser: null,

    init: function() {
        this.authClient = new FirebaseSimpleLogin(dbRef, function(error, user) {
            if (error) {
                alert('Authentication failed: ' + error);
            } else if (user) {
                this.set('authed', true);
                var userRef = new Firebase(usersPath + '/simplelogin:' + user.id);
                var controller = this;
                var properties = {
                    id: user.id,
                    email: user.email
                };
                userRef.once('value', function(snapshot) {
                    var user = App.User.create({ ref: userRef });
                    user.setProperties(properties);
                    controller.set('currentUser', user);
                });
            } else {
                this.set('authed', false);
            }
        }.bind(this));
    },

    login: function() {
        this.authClient.login('password', {
            email: this.get("email"),
            password: this.get("password"),
            rememberMe: this.get("remember")
        });
    },

    logout: function() {
        this.authClient.logout();
    },

    createUser: function() {
        var email = createEmail.value;
        var password = createPassword.value;
        this.authClient.createUser(email, password, function(error, user) {
            if (!error) {
                console.log('User Id: ' + user.id + ', Email: ' + user.email);
            }
        }
    )}
});

Create User Template

<form {{action createUser on='submit'}} class="form-horizontal" role='form'>
    <div class='form-group'>
        <label class="col-sm-5 control-label" for='createEmail'><p class='lead'>What's your email?</p></label>
        <div class="col-sm-7">
            {{input type="email" classNames="form-control" value=createEmail id="createEmail" placeholder="Don't worry, we won't spam you..."}}
        </div>
    </div>
    <div class='form-group'>
        <label class="col-sm-5 control-label" for='createPassword'><p class='lead'>Choose a password...</p></label>
        <div class="col-sm-7">
            {{input type="password" classNames="form-control" value=createPassword id="createPassword" placeholder="Make it super hard to guess!"}}
        </div>
    </div>
    <div class='form-group'>
        <label class="col-sm-5 control-label" for='confirm'><p class='lead'>And confirm it</p></label>
        <div class="col-sm-7">
            {{input type="password" classNames="form-control" value=confirm id="confirm" placeholder="Make sure you know what you typed..."}}
        </div>
    </div>
    <button type='submit'>Submit</button>
</form>

Just let me know if you need to see more of my code and I'll throw it up here. Thanks!

@kingpin2k Do you have any thoughts?

Answer as provided by @mike-pugh :

My AuthController now looks like this:

App.AuthController = Ember.Controller.extend({
  authed: false,
  currentUser: null,

  init: function() {
    this.authClient = new FirebaseSimpleLogin(dbRef, function(error, user) {
      if (error) {
        alert('Authentication failed: ' + error);
      } else if (user) {
        this.set('authed', true);
        var userRef = new Firebase(usersPath + '/simplelogin:' + user.id);
        var controller = this;
        var properties = {
            id: user.id,
            email: user.email
        };
        userRef.once('value', function(snapshot) {
            var data = snapshot.val();
            var user = App.User.create({ ref: data});
            user.setProperties(properties);
            controller.set('currentUser', user);
        });
      } else {
        this.set('authed', false);
      }
    }.bind(this));
  },

    login: function() {
        console.log('made it inside login');
        console.log(email.value);       
        console.log(password.value);
        console.log(remember.value);
        this.authClient.login('password', {
            email: email.value,
            password: password.value,
            rememberMe: remember.value
        });
    },

    logout: function() {
        this.authClient.logout();
    },

    createUser: function() {
        console.log('made it inside createUser');
        var email = createEmail.value;
        console.log(email);
        var password = createPassword.value;
        console.log(password);
        this.authClient.createUser(email, password, function(error, user) {
            if (!error) {
                console.log('User Id: ' + user.id + ', Email: ' + user.email);
                var userRef = new Firebase(usersPath + '/simplelogin:' + user.id);
                userRef.set({
                    email: user.email,
                    id: user.id
                });
            }
        }
    )}
});

I also had to add an empty UserModel:

App.User = EmberFire.Object.extend({

});

That's it!! Now I can authenticate and then pull up the currentUser data.

OgdenIT
  • 55
  • 7

1 Answers1

2

The Firebase Simple Login functions don't add users to your users/ path within your forge. It stores the users in some system defined area. If you want to store data about your users within a users/ path then you'll need to create that information.

For example:

createUser: function() {
        var that = this;
        var email = createEmail.value;
        var password = createPassword.value;
        this.authClient.createUser(email, password, function(error, user) {
            if (!error) {
                console.log('User Id: ' + user.id + ', Email: ' + user.email);
                var userRef = new Firebase(usersPath + '/simplelogin:' + user.id);
                userRef.set({email: user.email}); // This is where you'd add Display Name, phone #, whatever

                that.authClient.login('password', email, password);
            }
        }
    )}

Your login code appears to correctly call the Firebase Simple Login code, which upon login should trigger the callback you specified in the constructor. Within that callback, I think you'll want to change your userRef.once() method to:

userRef.once('value', function(snapshot) {
                    var data = snapshot.val();
                    var user = App.User.create({ ref: data});
                    user.setProperties(properties);
                    controller.set('currentUser', user);
                });

The once() success callback provides you the snapshot of the data at that path, so you'd want to bind to that information instead of the userRef object itself which is just a Firebase reference.

Mike Pugh
  • 6,637
  • 2
  • 25
  • 25
  • That seems to do the trick. Only thing is I get the following error in console: ```Uncaught TypeError: Cannot call method 'create' of undefined AuthController.js:18``` That line in AuthController is ```var data = snapshot.val();``` followed by ```var user = App.User.create({ ref: data});```Have any ideas why @mike-pugh – OgdenIT Jan 14 '14 at 01:03
  • So now I just have to figure out why it's saying that the var data is undefined... Until that point, I won't be able to set the currentUser and won't be able to filter data by the user id or email... Any thoughts? – OgdenIT Jan 14 '14 at 01:17
  • 1
    @OgdenIT - looks like App.User is undefined. You'll need to make sure you've instantiated your User object with something like: App.User = Ember.Object.extend({ .. some methods? ..}); Then you should be able to call create and pass in your data. – Mike Pugh Jan 14 '14 at 01:22
  • I thought because I had no methods or computed values in mind that I could just leave it out and ember would generate a default like it does for other things. After I added an empty App.User it worked like a charm! Thank you sir! – OgdenIT Jan 14 '14 at 13:49
  • I have a related question. How would I correctly implement logging in a user within the create user action? I realize that you have to wait till the user is created and you get the callback, but I'm not quite sure how to implement that. – OgdenIT Jan 16 '14 at 19:08
  • @OgdenIT - I've updated the answer to show one way to login after account creation. Ideally you'd actually set your email/password such that you can just refer to the login() method you created in your controller. – Mike Pugh Jan 17 '14 at 04:02
  • I'm running into the following error in console ```Cannot call method 'login' of undefined``` This is confusing because the user definitely exists when ```this.authClient.login('password', email, password);``` is called. – OgdenIT Jan 17 '14 at 14:10
  • The context of 'this' isn't what you think it is – Mike Pugh Jan 18 '14 at 13:07