Search code examples
javascriptarraysangularjsgoogle-apigoogle-contacts-api

Google contacts API using angularjs


I am trying to fetch Google contacts of a user. I am using this code to implement auth2.

Here is my services.js

**Services.js** : ....
.service('googleService', ['$http', '$rootScope', '$q', function ($http, $rootScope, $q) {
var clientId = 'MY_CLIENT_ID',
apiKey = 'MY_API_KEY',
scopes = 'https://www.googleapis.com/auth/userinfo.email https://www.google.com/m8/feeds/contacts/default/full',
domain = '{OPTIONAL DOMAIN}',
deferred = $q.defer();

this.login = function () {
    console.log("Inside login()");
    gapi.auth.authorize({ 
        client_id: clientId, 
        scope: scopes, 
        immediate: false,
        approval_prompt: "force"
    }, this.handleAuthResult);
    return deferred.promise;
}

this.handleClientLoad = function () {
    console.log("Inside handleClientLoad()");
    gapi.client.setApiKey(apiKey);
    gapi.auth.init(function () { });
    window.setTimeout(checkAuth, 1);
};

this.checkAuth = function() {
    console.log("Inside checkAuth()");
    gapi.auth.authorize({ 
        client_id: clientId, 
        scope: scopes, 
        immediate: true, 
    }, this.handleAuthResult);
};

this.handleAuthResult = function(authResult) {
    console.log("Inside handleResult()");
    if (authResult && !authResult.error) {
        var data = [];
        gapi.client.load('oauth2', 'v2', function () {
            var request = gapi.client.oauth2.userinfo.get();
            request.execute(function (resp) {
                data.push(resp.email);
                data.push(authResult.access_token);
                deferred.resolve(data);
            });
        });
        
    } else {
        deferred.reject('error');
    }
};

this.handleAuthClick = function() {
    console.log("Inside handleAuthClick()");
    gapi.auth.authorize({ 
        client_id: clientId, 
        scope: scopes,
        immediate: false,
        approval_prompt: "force"
    }, this.handleAuthResult);
    return false;
};

this.makeContactList = function(root){
    var plist = [];
    var contactsList = root.feed.entry;     
    if (contactsList != null && contactsList.length > 0) {
        for (var i = 0; i < contactsList.length; i++) {
            var contact = contactsList[i];
            var fname = "";
            var l = contact.gd$email;
            var address = null;
            var emailArr = [];
            if (l != null && l.length > 0) {
                var el = l[0];
                if (el != null) {
                    address = el.address;
                }
                if (l.length > 1) {
                    for (var k = 1; k < l.length; k++) {
                        var e = l[k];
                        if (e != null) {
                            emailArr[k - 1] = e.address;
                        }
                    }
                }
            }
            var lname = "";
            var dispName = contact.title.$t;
            if (dispName != null) {
                var sarr = dispName.split(' ');
                if (sarr.length > 0) {
                    if (sarr.length >= 1) {
                        fname = sarr[0];
                    }
                    if (sarr.length >= 2) {
                        for (var k = 1; k < sarr.length; k++) {
                            lname = lname +" "+sarr[k];
                        }
                        lname = lname.trim();
                    }
                }
            }
            var id = contact.id.$t;

            if (address != null && address.length > 0) {
                var p = {
                        firstName : "",
                        lastname : "",
                        email : "",
                        displayName : "",
                        otherEmails : [],
                        id : ""
                }
                p.firstName = fname;
                p.lastName = lname;
                p.email = address;
                p.displayName = dispName;
                p.otherEmails = emailArr;
                p.id = id;
                plist.push(p);
            }
        }
    } else {
        console.log("No contacts were obtained from the feed");
    }
    return plist;
};
this.disconnectUser = function(access_token){
    var revokeUrl = 'https://accounts.google.com/o/oauth2/revoke?token=' +access_token;
    $.ajax({
        type : 'GET',
        url : revokeUrl,
        async : false,
        contentType : "application/json",
        dataType : 'jsonp',
        success : function(nullResponse){
            console.log("Successfully disconnected access_token");
        },
        error : function(e){
            console.log("Failed to isconnect access_token");
            window.location.reload();
        }
    });
}
}]);

and controller.js

.controller('ContactsController',  ['$scope','$window','$modal','$http', 'ContactsFactory','googleService','ImportFactory','NotifyFactory', function($scope, $window, $modal, $http, ContactsFactory, googleService, ImportFactory, NotifyFactory) {

$scope.login = function () {
    var promise =  googleService.login()
    promise.then(function (data) {
        if(angular.isObject(data) && data[0]!== undefined && data[1]!== undefined){
            console.log(data[0]);
            console.log(data[1]);
            $http.get("https://www.google.com/m8/feeds/contacts/"+data[0]+"/full?alt=json&access_token=" + data[1] + "&max-results=1000&v=3.0")
            .success(function(data, status, headers, config) {
                console.log("In success");
                var contactList = googleService.makeContactList(data);
                var response = MyFactory.post(contactList);
                response.$promise.then(function(data){
                    console.log(data);
                    NotifyFactory.success("Successfully synched with your google contacts!");
                    googleService.disconnectUser(access_token);
                    //$route.reload();
                    window.location.reload();
                });
            })
            .error(function(data, status, headers, config) {
                console.log("In error");
                console.log(data);
                NotifyFactory.error("Something went wrong. Please try again.11111111111");
            });
        }else{
            NotifyFactory.error("Something went wrong. Please try again.2222222222222");
        }
    }
    , function (err) {
        console.log('Failed: ' + err);
        NotifyFactory.error("Something went wrong. Please try again.333333333333");
    });
};

The $scope.login() is called when a user presses "Get Contacts" button. This works fine in the sense that I some how get the contacts of the logged in google account.

When I press the button ,google's login screen pop up appear. I enter password of abc@gmail.com and press 'Accept', then googleService.Login() returns an empty object and the error message is shown.

Then I press the Get contacts button again, the contacts of abc@gmail.com are fetched even before I press 'Accept' on the consent screen ( I have given an extra parameter in auth to force consent every time).I press 'Accept' on the consent screen

A third time I press the Get contacts button, contacts of abc@gmail.com are fetched again before I press Accept. I change the email on the consent screen to xyz@gmail.com and press accept.

Then I press the Get Contacts button a again and on the consent screen, concnt for abc@gmail.com is asked and not for xyz@gmail.com, I change it to xyz@gmail.com. Still the contacts of abc@gmail.com are being fetched on all subsequent presses of the Get Contacts Button.

I really dont understand the follow of control in the service or why my 'get contacts' thing is doing crazy things. Please help me.


Solution

  • I don't know if this fixes all your erros, but I'm pretty sure you should call deferred.resolve(data); in your request.executes success handler, after data has been added to your data array:

    this.handleAuthResult = function(authResult) {
        console.log("Inside handleResult()");
        if (authResult && !authResult.error) {
            var data = [];
            gapi.client.load('oauth2', 'v2', function () {
                var request = gapi.client.oauth2.userinfo.get();
                request.execute(function (resp) {
                    data.push(resp.email);
                    data.push(authResult.access_token);
                    deferred.resolve(data);
                });
            });
        } else {
            deferred.reject('error');
        }
    };
    

    Otherwise your login promise continues when the user is logged in but with the data array still being empty, what leads to an error.