[CLAMP-1] Initial ONAP CLAMP seed code commit
[clamp.git] / src / main / resources / META-INF / resources / icd / lib / swagger-oauth.js
1 var appName;
2 var popupMask;
3 var popupDialog;
4 var clientId;
5 var realm;
6 var redirect_uri;
7 var clientSecret;
8 var scopeSeparator;
9 var additionalQueryStringParams;
10
11 function handleLogin() {
12   var scopes = [];
13
14   var auths = window.swaggerUi.api.authSchemes || window.swaggerUi.api.securityDefinitions;
15   if(auths) {
16     var key;
17     var defs = auths;
18     for(key in defs) {
19       var auth = defs[key];
20       if(auth.type === 'oauth2' && auth.scopes) {
21         var scope;
22         if(Array.isArray(auth.scopes)) {
23           // 1.2 support
24           var i;
25           for(i = 0; i < auth.scopes.length; i++) {
26             scopes.push(auth.scopes[i]);
27           }
28         }
29         else {
30           // 2.0 support
31           for(scope in auth.scopes) {
32             scopes.push({scope: scope, description: auth.scopes[scope], OAuthSchemeKey: key});
33           }
34         }
35       }
36     }
37   }
38
39   if(window.swaggerUi.api
40     && window.swaggerUi.api.info) {
41     appName = window.swaggerUi.api.info.title;
42   }
43
44   $('.api-popup-dialog').remove(); 
45   popupDialog = $(
46     [
47       '<div class="api-popup-dialog">',
48       '<div class="api-popup-title">Select OAuth2.0 Scopes</div>',
49       '<div class="api-popup-content">',
50         '<p>Scopes are used to grant an application different levels of access to data on behalf of the end user. Each API may declare one or more scopes.',
51           '<a href="#">Learn how to use</a>',
52         '</p>',
53         '<p><strong>' + appName + '</strong> API requires the following scopes. Select which ones you want to grant to Swagger UI.</p>',
54         '<ul class="api-popup-scopes">',
55         '</ul>',
56         '<p class="error-msg"></p>',
57         '<div class="api-popup-actions"><button class="api-popup-authbtn api-button green" type="button">Authorize</button><button class="api-popup-cancel api-button gray" type="button">Cancel</button></div>',
58       '</div>',
59       '</div>'].join(''));
60   $(document.body).append(popupDialog);
61
62   //TODO: only display applicable scopes (will need to pass them into handleLogin)
63   popup = popupDialog.find('ul.api-popup-scopes').empty();
64   for (i = 0; i < scopes.length; i ++) {
65     scope = scopes[i];
66     str = '<li><input type="checkbox" id="scope_' + i + '" scope="' + scope.scope + '"' +'" oauthtype="' + scope.OAuthSchemeKey +'"/>' + '<label for="scope_' + i + '">' + scope.scope ;
67     if (scope.description) {
68       if ($.map(auths, function(n, i) { return i; }).length > 1) //if we have more than one scheme, display schemes
69             str += '<br/><span class="api-scope-desc">' + scope.description + ' ('+ scope.OAuthSchemeKey+')' +'</span>';
70           else
71             str += '<br/><span class="api-scope-desc">' + scope.description + '</span>';
72     }
73     str += '</label></li>';
74     popup.append(str);
75   }
76
77   var $win = $(window),
78     dw = $win.width(),
79     dh = $win.height(),
80     st = $win.scrollTop(),
81     dlgWd = popupDialog.outerWidth(),
82     dlgHt = popupDialog.outerHeight(),
83     top = (dh -dlgHt)/2 + st,
84     left = (dw - dlgWd)/2;
85
86   popupDialog.css({
87     top: (top < 0? 0 : top) + 'px',
88     left: (left < 0? 0 : left) + 'px'
89   });
90
91   popupDialog.find('button.api-popup-cancel').click(function() {
92     popupMask.hide();
93     popupDialog.hide();
94     popupDialog.empty();
95     popupDialog = [];
96   });
97
98   $('button.api-popup-authbtn').unbind();
99   popupDialog.find('button.api-popup-authbtn').click(function() {
100     popupMask.hide();
101     popupDialog.hide();
102
103     var authSchemes = window.swaggerUi.api.authSchemes;
104     var host = window.location;
105     var pathname = location.pathname.substring(0, location.pathname.lastIndexOf("/"));
106     var defaultRedirectUrl = host.protocol + '//' + host.host + pathname + '/o2c.html';
107     var redirectUrl = window.oAuthRedirectUrl || defaultRedirectUrl;
108     var url = null;
109     var scopes = []
110     var o = popup.find('input:checked'); 
111     var OAuthSchemeKeys = [];
112     var state;
113     for(k =0; k < o.length; k++) {
114       var scope = $(o[k]).attr('scope');
115       if (scopes.indexOf(scope) === -1)
116         scopes.push(scope);
117       var OAuthSchemeKey = $(o[k]).attr('oauthtype');      
118       if (OAuthSchemeKeys.indexOf(OAuthSchemeKey) === -1)
119           OAuthSchemeKeys.push(OAuthSchemeKey);
120     }
121     
122     //TODO: merge not replace if scheme is different from any existing 
123     //(needs to be aware of schemes to do so correctly)
124     window.enabledScopes=scopes;    
125     
126     for (var key in authSchemes) { 
127       if (authSchemes.hasOwnProperty(key) && OAuthSchemeKeys.indexOf(key) != -1) { //only look at keys that match this scope.
128         var flow = authSchemes[key].flow;
129
130         if(authSchemes[key].type === 'oauth2' && flow && (flow === 'implicit' || flow === 'accessCode')) {
131           var dets = authSchemes[key];
132           url = dets.authorizationUrl + '?response_type=' + (flow === 'implicit' ? 'token' : 'code');
133           window.swaggerUi.tokenName = dets.tokenName || 'access_token';
134           window.swaggerUi.tokenUrl = (flow === 'accessCode' ? dets.tokenUrl : null);
135           state = key;
136         }
137         else if(authSchemes[key].type === 'oauth2' && flow && (flow === 'application')) {
138             var dets = authSchemes[key];
139             window.swaggerUi.tokenName = dets.tokenName || 'access_token';
140             clientCredentialsFlow(scopes, dets.tokenUrl, key);
141             return;
142         }        
143         else if(authSchemes[key].grantTypes) {
144           // 1.2 support
145           var o = authSchemes[key].grantTypes;
146           for(var t in o) {
147             if(o.hasOwnProperty(t) && t === 'implicit') {
148               var dets = o[t];
149               var ep = dets.loginEndpoint.url;
150               url = dets.loginEndpoint.url + '?response_type=token';
151               window.swaggerUi.tokenName = dets.tokenName;
152             }
153             else if (o.hasOwnProperty(t) && t === 'accessCode') {
154               var dets = o[t];
155               var ep = dets.tokenRequestEndpoint.url;
156               url = dets.tokenRequestEndpoint.url + '?response_type=code';
157               window.swaggerUi.tokenName = dets.tokenName;
158             }
159           }
160         }
161       }
162     }
163
164     redirect_uri = redirectUrl;
165
166     url += '&redirect_uri=' + encodeURIComponent(redirectUrl);
167     url += '&realm=' + encodeURIComponent(realm);
168     url += '&client_id=' + encodeURIComponent(clientId);
169     url += '&scope=' + encodeURIComponent(scopes.join(scopeSeparator));
170     url += '&state=' + encodeURIComponent(state);
171     for (var key in additionalQueryStringParams) {
172         url += '&' + key + '=' + encodeURIComponent(additionalQueryStringParams[key]);
173     }
174
175     window.open(url);
176   });
177
178   popupMask.show();
179   popupDialog.show();
180   return;
181 }
182
183
184 function handleLogout() {
185   for(key in window.swaggerUi.api.clientAuthorizations.authz){
186     window.swaggerUi.api.clientAuthorizations.remove(key)
187   }
188   window.enabledScopes = null;
189   $('.api-ic.ic-on').addClass('ic-off');
190   $('.api-ic.ic-on').removeClass('ic-on');
191
192   // set the info box
193   $('.api-ic.ic-warning').addClass('ic-error');
194   $('.api-ic.ic-warning').removeClass('ic-warning');
195 }
196
197 function initOAuth(opts) {
198   var o = (opts||{});
199   var errors = [];
200
201   appName = (o.appName||errors.push('missing appName'));
202   popupMask = (o.popupMask||$('#api-common-mask'));
203   popupDialog = (o.popupDialog||$('.api-popup-dialog'));
204   clientId = (o.clientId||errors.push('missing client id'));
205   clientSecret = (o.clientSecret||null);
206   realm = (o.realm||errors.push('missing realm'));
207   scopeSeparator = (o.scopeSeparator||' ');
208   additionalQueryStringParams = (o.additionalQueryStringParams||{});
209
210   if(errors.length > 0){
211     log('auth unable initialize oauth: ' + errors);
212     return;
213   }
214
215   $('pre code').each(function(i, e) {hljs.highlightBlock(e)});
216   $('.api-ic').unbind();
217   $('.api-ic').click(function(s) {
218     if($(s.target).hasClass('ic-off'))
219       handleLogin();
220     else {
221       handleLogout();
222     }
223     false;
224   });
225 }
226
227 function clientCredentialsFlow(scopes, tokenUrl, OAuthSchemeKey) {
228     var params = {
229       'client_id': clientId,
230       'client_secret': clientSecret,
231       'scope': scopes.join(' '),
232       'grant_type': 'client_credentials'
233     }
234     $.ajax(
235     {
236       url : tokenUrl,
237       type: "POST",
238       data: params,
239       success:function(data, textStatus, jqXHR)
240       {
241         onOAuthComplete(data,OAuthSchemeKey);
242       },
243       error: function(jqXHR, textStatus, errorThrown)
244       {
245         onOAuthComplete("");
246       }
247     });
248     
249   }
250
251 window.processOAuthCode = function processOAuthCode(data) {
252   var OAuthSchemeKey = data.state;
253   var params = {
254     'client_id': clientId,
255     'code': data.code,
256     'grant_type': 'authorization_code',
257     'redirect_uri': redirect_uri
258   };
259
260   if (clientSecret) {
261     params.client_secret = clientSecret;
262   }
263
264   $.ajax(
265   {
266     url : window.swaggerUi.tokenUrl,
267     type: "POST",
268     data: params,
269     success:function(data, textStatus, jqXHR)
270     {
271       onOAuthComplete(data, OAuthSchemeKey);
272     },
273     error: function(jqXHR, textStatus, errorThrown)
274     {
275       onOAuthComplete("");
276     }
277   });
278 };
279
280 window.onOAuthComplete = function onOAuthComplete(token,OAuthSchemeKey) {
281   if(token) {
282     if(token.error) {
283       var checkbox = $('input[type=checkbox],.secured')
284       checkbox.each(function(pos){
285         checkbox[pos].checked = false;
286       });
287       alert(token.error);
288     }
289     else {
290       var b = token[window.swaggerUi.tokenName];      
291       if (!OAuthSchemeKey){
292           OAuthSchemeKey = token.state;
293       }
294       if(b){
295         // if all roles are satisfied
296         var o = null;
297         $.each($('.auth .api-ic .api_information_panel'), function(k, v) { 
298           var children = v;
299           if(children && children.childNodes) {
300             var requiredScopes = [];
301             $.each((children.childNodes), function (k1, v1){
302               var inner = v1.innerHTML;
303               if(inner)
304                 requiredScopes.push(inner);
305             });
306             var diff = [];
307             for(var i=0; i < requiredScopes.length; i++) {
308               var s = requiredScopes[i];
309               if(window.enabledScopes && window.enabledScopes.indexOf(s) == -1) {
310                 diff.push(s);
311               }
312             }
313             if(diff.length > 0){
314               o = v.parentNode.parentNode;
315               $(o.parentNode).find('.api-ic.ic-on').addClass('ic-off');
316               $(o.parentNode).find('.api-ic.ic-on').removeClass('ic-on');
317
318               // sorry, not all scopes are satisfied
319               $(o).find('.api-ic').addClass('ic-warning');
320               $(o).find('.api-ic').removeClass('ic-error');
321             }
322             else {
323               o = v.parentNode.parentNode;
324               $(o.parentNode).find('.api-ic.ic-off').addClass('ic-on');
325               $(o.parentNode).find('.api-ic.ic-off').removeClass('ic-off');
326
327               // all scopes are satisfied
328               $(o).find('.api-ic').addClass('ic-info');
329               $(o).find('.api-ic').removeClass('ic-warning');
330               $(o).find('.api-ic').removeClass('ic-error');
331             }
332           }
333         });
334         window.swaggerUi.api.clientAuthorizations.add(window.OAuthSchemeKey, new SwaggerClient.ApiKeyAuthorization('Authorization', 'Bearer ' + b, 'header'));
335         window.swaggerUi.load();
336       }
337     }
338   }
339 };