# AngularJS - Google logout directive

Our application needed a function to sign out of Google. Unfortunately, there is no such API and I was forced to use an iframe to: http://accounts.google.com/Logout and a polling mechanism to see when the operation is complete.

I had a lot of doubts whether to put this code in a directive or in a service.

On one hand it has DOM manipulation, so the instinct is to put it in a directive.

On the other hand:

• The directive is completely invisible. Most of the time it doesn't create any DOM, and only during logout it creates a hidden iframe.
• The usage of this directive, isn't by invoking an event in event in its template, since, as I said, it is invisible. The logout logic will be invoked in a logic in a controller/service so I will be basically calling a function inside the directive.

I would appreciate a code review regarding this points, and of course, anything else that comes to your mind:

// This directive allows a controller to log-out easily from Google
// Usage:
// The given parameter must be an object. This object, is assigned by a directive by a single "logout" function.
// When logout is needed, it can be invoked using this object, e.g in this case in the controller you would write:
//  $scope.googleLogoutControl.logout() // This function returns a promise. This promise gets resolved if logout was successful and rejected otherwise. // If the user isn't logged out in MAX_LOGOUT_TIME_SECONDS angular.module('codereview').directive('tgGoogleLogout', function () { 'use strict'; return { restrict: 'E', replace: true, template: '<iframe class="hidden" ng-if="showLogoutFrame" src="https://www.google.com/accounts/Logout"></iframe>', scope: { logoutControl: "=" }, controller: function ($scope, $q,$timeout, $log, googleAuthService) { var MAX_LOGOUT_TIME_SECONDS = 5;$scope.showLogoutFrame = false;

// Polls Google until user is completely logged out
// maxSecondsToWait - The maximum number of seconds for a logout to happen.
// Returns a promise. Resolves when logout is detected. Rejects if logout was not detected in time.
function waitUntilLogout(maxSecondsToWait) {
// Default - Time to try before giving up on logout
if (angular.isUndefined(maxSecondsToWait)) {
maxSecondsToWait = 5;
}

.then(function (email) {
$log.debug("getAuthorizedUserEmail - Got email: {0}".format(email)); if (email) { maxSecondsToWait--; if (maxSecondsToWait > 0) { // Retry after 1000ms. The actual function happens on the next "then". // NOTE: The total amount of seconds we will retry, is set by 'maxSecondsToLogout' // This controls only how often we try.$log.debug("getAuthorizedUserEmail - Retrying {0} seconds left".format(maxSecondsToWait));

return $timeout(function () { }, 1000).then(function () { return waitUntilLogout(maxSecondsToWait) }); } else { return$q.reject("Failed to logout");
}
}
});
}

if (!angular.isObject($scope.logoutControl)) { throw new Error("logoutControl - A control object is required to use this directive. It can be an empty object.") } if (angular.isDefined($scope.logoutControl.logout)) {
throw new Error("logoutControl - logout property must not be already defined - Overwrite risk")
}

// See directive docs for usage.
//noinspection JSPrimitiveTypeWrapperUsage
$scope.logoutControl.logout = function () { // Showing the frame starts the logout process$scope.showLogoutFrame = true;

return waitUntilLogout(MAX_LOGOUT_TIME_SECONDS)
.finally(function () {
// Hide the frame regardless of success/failure of logout
\$scope.showLogoutFrame = false;
});
}
}
};
});


• 'use strict' <- Good