-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathangular-google-endpoints.js
218 lines (180 loc) · 5.72 KB
/
angular-google-endpoints.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/*!
* Angular Material Design
* https://github.com/angular/material
* @license MIT
* v0.5.0
*/
function google_endpoints_init() {
var $injector = angular.element(document.body).injector();
var $googleEndpoints = $injector.get('$googleEndpoints');
$googleEndpoints._init();
}
(function() {
angular.module('ngGoogleEndpoints', [ "ng" ]);
angular.module('ngGoogleEndpoints').factory('$googleEndpoints', [ "$q", function($q) {
/*
* Internal state
*/
var state = {
// Options set by the client
clientId: null, /* Client ID configured on Google AppEngine */
requiresOAuth2: false, /* Option to enable OAuth2 authentication */
apis: new Array(), /* Set of registered APIs */
currentUser: null /* Current user in case OAuth2 is required */
}
/*
* Init method called once Client script is loaded. Loads the required APIs, performs authentication if needed and setup of
* API delegates.
*/
function _init() {
// Loads the OAuth and helloworld APIs asynchronously, and triggers init
// when they have completed.
var apisToLoad = state.apis.length;
var callback = function() {
if (--apisToLoad == 0) {
if (state.requiresOAuth2) {
// Handle OAuth callback and resolve deferreds once done.
signin(false, userAuthed);
} else {
// No Auth needed, apis are loaded, so setup API client methods.
resolveDefereds();
}
}
}
if (state.requiresOAuth2) {
apisToLoad++;
gapi.client.load('oauth2', 'v2', callback);
}
for (var i = 0 ; i < state.apis.length; i++) {
var api = state.apis[i];
gapi.client.load(api.apiName, api.apiVersion, callback, api.apiRoot);
}
}
function userAuthed() {
var request = gapi.client.oauth2.userinfo.get().execute(function(resp) {
/*
* Verified_email flag does not need to be checked. See: http://stackoverflow.com/questions/10893029/authenticating-with-google-with-oauth-2-0-and-userinfo-api-what-does-it-mean-fo
*/
if (!resp.code) {
// User is signed in, resolve deferreds.
state.currentUser = resp;
resolveDefereds();
} else {
// User not authenticated, reject defereds.
rejectDefereds(resp);
}
});
}
function signin(mode, authorizeCallback) {
gapi.auth.authorize({
client_id : state.clientId,
scope : "https://www.googleapis.com/auth/userinfo.email",
immediate : mode
}, authorizeCallback);
}
function resolveDefereds() {
for (var i = 0; i < state.apis.length; i++) {
state.apis[i].defered.resolve();
}
}
function rejectDefereds(resp) {
for (var i = 0; i < state.apis.length; i++) {
state.apis[i].defered.reject(resp);
}
}
/*
* Setup API Methods based on GAPI interface definition.
*/
function setupApiMethods(api) {
var namespace = gapi.client[api.apiName];
traverseNamespace(api.service, namespace, new Array(), api);
}
function traverseNamespace(context, namespace, path, api) {
for (var property in namespace) {
if (namespace.hasOwnProperty(property) && property != "kB") {
var value = namespace[property];
// Create child context and traverse
if (typeof value == "object") {
var childContext = {};
var childPath = path.slice(0)
childPath.push(property);
context[property] = childContext;
traverseNamespace(childContext, value, childPath, api);
}
// Create function to call.
if (typeof value == "function") {
var gapiContext = gapi.client[api.apiName];
for (var i = 0; i < path.length; i++) {
var segment = path[i];
gapiContext = gapiContext[segment];
}
var gapiFunc = gapiContext[property];
// Create delegate function using promises to handle async interaction with Google Endpoints.
context[property] = function() {
var delegateFunc = gapiFunc;
return function() {
var defered = $q.defer();
delegateFunc.apply(null, arguments).execute(function(resp) {
if (resp.code) {
defered.reject(resp);
} else {
defered.resolve(resp);
}
});
return defered.promise;
};
}();
}
}
}
}
/*
* API Functions
*/
function initClientId(clientId) {
state.clientId = clientId;
}
function requireOAuth2() {
state.requiresOAuth2 = true;
}
function createApiClient(apiName, apiVersion, apiRoot) {
var onceLoaded = $q.defer();
var api = {
apiName: apiName,
apiVersion: apiVersion,
apiRoot: (typeof apiRoot == "undefined") ? '//' + window.location.host + '/_ah/api' : apiRoot,
defered: $q.defer(),
service: {
loaded: false,
failed: false,
onceLoaded: onceLoaded.promise
}
};
// Once loaded setup the API in the service object
api.defered.promise.then(function() {
setupApiMethods(api);
api.service.loaded = true;
api.service.currentUser = state.currentUser;
onceLoaded.resolve();
}, function() {
api.service.failed = true;
onceLoaded.reject();
})
state.apis.push(api);
// Return the service object which represents the client.
return api.service;
}
// Add Google client script
var clientScript = document.createElement("SCRIPT");
clientScript.src = "https://apis.google.com/js/client.js?onload=google_endpoints_init";
document.body.appendChild(clientScript);
// Return API object
return {
initClientId: initClientId,
requireOAuth2: requireOAuth2,
createApiClient: createApiClient,
// Internal method
_init : _init,
}
} ]);
})();