PageRenderTime 26ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/uma-server-webapp/src/main/webapp/resources/js/policy.js

https://gitlab.com/jslee1/OpenID-Connect-Java-Spring-Server
JavaScript | 649 lines | 465 code | 146 blank | 38 comment | 36 complexity | 1e533db476b73f8c0f9d4a3b5f654f3b MD5 | raw file
  1. /*******************************************************************************
  2. * Copyright 2016 The MITRE Corporation
  3. * and the MIT Internet Trust Consortium
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *******************************************************************************/
  17. var ResourceSetModel = Backbone.Model.extend({
  18. urlRoot: 'api/resourceset'
  19. });
  20. var ResourceSetCollection = Backbone.Collection.extend({
  21. model: ResourceSetModel,
  22. url: 'api/resourceset'
  23. });
  24. var PolicyModel = Backbone.Model.extend({
  25. urlRoot: function() {
  26. return 'api/resourceset/' + this.options.rsid + '/policy/';
  27. },
  28. initialize: function(model, options) {
  29. this.options = options;
  30. }
  31. });
  32. var PolicyCollection = Backbone.Collection.extend({
  33. model: PolicyModel,
  34. url: function() {
  35. return 'api/resourceset/' + this.options.rsid + '/policy/';
  36. },
  37. initialize: function(models, options) {
  38. this.options = options;
  39. }
  40. });
  41. var ResourceSetListView = Backbone.View.extend({
  42. tagName: 'span',
  43. initialize:function (options) {
  44. this.options = options;
  45. },
  46. load:function(callback) {
  47. if (this.model.isFetched &&
  48. this.options.clientList.isFetched &&
  49. this.options.systemScopeList.isFetched) {
  50. callback();
  51. return;
  52. }
  53. $('#loadingbox').sheet('show');
  54. $('#loading').html(
  55. '<span class="label" id="loading-resourcesets">' + $.t('policy.resource-sets') + '</span> ' +
  56. '<span class="label" id="loading-clients">' + $.t('common.clients') + '</span> ' +
  57. '<span class="label" id="loading-scopes">' + $.t('common.scopes') + '</span> '
  58. );
  59. $.when(this.model.fetchIfNeeded({success:function(e) {$('#loading-resourcesets').addClass('label-success');}}),
  60. this.options.clientList.fetchIfNeeded({success:function(e) {$('#loading-clients').addClass('label-success');}}),
  61. this.options.systemScopeList.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}}))
  62. .done(function() {
  63. $('#loadingbox').sheet('hide');
  64. callback();
  65. });
  66. },
  67. events: {
  68. "click .refresh-table":"refreshTable"
  69. },
  70. render:function (eventName) {
  71. $(this.el).html($('#tmpl-resource-set-table').html());
  72. var _self = this;
  73. _.each(this.model.models, function (resourceSet) {
  74. // look up client
  75. var client = this.options.clientList.getByClientId(resourceSet.get('clientId'));
  76. // if there's no client ID, this is an error!
  77. if (client != null) {
  78. var view = new ResourceSetView({model: resourceSet, client: client, systemScopeList: _self.options.systemScopeList});
  79. view.parentView = _self;
  80. $('#resource-set-table', this.el).append(view.render().el);
  81. }
  82. }, this);
  83. this.togglePlaceholder();
  84. $(this.el).i18n();
  85. return this;
  86. },
  87. togglePlaceholder:function() {
  88. if (this.model.length > 0) {
  89. $('#resource-set-table', this.el).show();
  90. $('#resource-set-table-empty', this.el).hide();
  91. } else {
  92. $('#resource-set-table', this.el).hide();
  93. $('#resource-set-table-empty', this.el).show();
  94. }
  95. },
  96. refreshTable:function(e) {
  97. e.preventDefault();
  98. var _self = this;
  99. $('#loadingbox').sheet('show');
  100. $('#loading').html(
  101. '<span class="label" id="loading-resourcesets">' + $.t('policy.resource-sets') + '</span> ' +
  102. '<span class="label" id="loading-clients">' + $.t('common.clients') + '</span> ' +
  103. '<span class="label" id="loading-scopes">' + $.t('common.scopes') + '</span> '
  104. );
  105. $.when(this.model.fetch({success:function(e) {$('#loading-resourcesets').addClass('label-success');}}),
  106. this.options.clientList.fetch({success:function(e) {$('#loading-clients').addClass('label-success');}}),
  107. this.options.systemScopeList.fetch({success:function(e) {$('#loading-scopes').addClass('label-success');}}))
  108. .done(function() {
  109. $('#loadingbox').sheet('hide');
  110. _self.render();
  111. });
  112. }
  113. });
  114. var ResourceSetView = Backbone.View.extend({
  115. tagName: 'tr',
  116. initialize:function(options) {
  117. this.options = options;
  118. if (!this.template) {
  119. this.template = _.template($('#tmpl-resource-set').html());
  120. }
  121. if (!this.scopeTemplate) {
  122. this.scopeTemplate = _.template($('#tmpl-scope-list').html());
  123. }
  124. if (!this.moreInfoTemplate) {
  125. this.moreInfoTemplate = _.template($('#tmpl-client-more-info-block').html());
  126. }
  127. this.model.bind('change', this.render, this);
  128. },
  129. render:function(eventName) {
  130. var json = {rs: this.model.toJSON(), client: this.options.client.toJSON()};
  131. this.$el.html(this.template(json));
  132. $('.scope-list', this.el).html(this.scopeTemplate({scopes: this.model.get('scopes'), systemScopes: this.options.systemScopeList}));
  133. $('.client-more-info-block', this.el).html(this.moreInfoTemplate({client: this.options.client.toJSON()}));
  134. $(this.el).i18n();
  135. return this;
  136. },
  137. events:{
  138. 'click .btn-edit': 'editPolicies',
  139. 'click .btn-delete': 'deleteResourceSet',
  140. 'click .toggleMoreInformation': 'toggleMoreInformation'
  141. },
  142. editPolicies:function(e) {
  143. e.preventDefault();
  144. app.navigate('user/policy/' + this.model.get('id'), {trigger: true});
  145. },
  146. deleteResourceSet:function(e) {
  147. e.preventDefault();
  148. if (confirm($.t('policy.rs-table.confirm'))) {
  149. var _self = this;
  150. this.model.destroy({
  151. dataType: false, processData: false,
  152. success:function () {
  153. _self.$el.fadeTo("fast", 0.00, function () { //fade
  154. $(this).slideUp("fast", function () { //slide up
  155. $(this).remove(); //then remove from the DOM
  156. _self.parentView.togglePlaceholder();
  157. });
  158. });
  159. },
  160. error:function (error, response) {
  161. console.log("An error occurred when deleting a resource set");
  162. //Pull out the response text.
  163. var responseJson = JSON.parse(response.responseText);
  164. //Display an alert with an error message
  165. $('#modalAlert div.modal-header').html(responseJson.error);
  166. $('#modalAlert div.modal-body').html(responseJson.error_description);
  167. $("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
  168. "backdrop" : "static",
  169. "keyboard" : true,
  170. "show" : true // ensure the modal is shown immediately
  171. });
  172. }
  173. });
  174. _self.parentView.delegateEvents();
  175. }
  176. return false;
  177. },
  178. toggleMoreInformation:function(e) {
  179. e.preventDefault();
  180. if ($('.moreInformation', this.el).is(':visible')) {
  181. // hide it
  182. $('.moreInformation', this.el).hide('fast');
  183. $('.toggleMoreInformation i', this.el).attr('class', 'icon-chevron-right');
  184. $('.moreInformationContainer', this.el).removeClass('alert').removeClass('alert-info').addClass('muted');
  185. } else {
  186. // show it
  187. $('.moreInformation', this.el).show('fast');
  188. $('.toggleMoreInformation i', this.el).attr('class', 'icon-chevron-down');
  189. $('.moreInformationContainer', this.el).addClass('alert').addClass('alert-info').removeClass('muted');
  190. }
  191. },
  192. });
  193. var PolicyListView = Backbone.View.extend({
  194. tagName: 'span',
  195. initialize:function(options) {
  196. this.options = options;
  197. },
  198. load:function(callback) {
  199. if (this.model.isFetched &&
  200. this.options.rs.isFetched &&
  201. this.options.systemScopeList.isFetched) {
  202. callback();
  203. return;
  204. }
  205. $('#loadingbox').sheet('show');
  206. $('#loading').html(
  207. '<span class="label" id="loading-policies">' + $.t('policy.loading-policies') + '</span> ' +
  208. '<span class="label" id="loading-rs">' + $.t('policy.loading-rs') + '</span> ' +
  209. '<span class="label" id="loading-scopes">' + $.t("common.scopes") + '</span> '
  210. );
  211. $.when(this.model.fetchIfNeeded({success:function(e) {$('#loading-policies').addClass('label-success');}}),
  212. this.options.rs.fetchIfNeeded({success:function(e) {$('#loading-rs').addClass('label-success');}}),
  213. this.options.systemScopeList.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}}))
  214. .done(function() {
  215. $('#loadingbox').sheet('hide');
  216. callback();
  217. });
  218. },
  219. events:{
  220. 'click .btn-add':'addPolicy',
  221. 'click .btn-cancel':'cancel'
  222. },
  223. cancel:function(e) {
  224. e.preventDefault();
  225. app.navigate('user/policy', {trigger: true});
  226. },
  227. togglePlaceholder:function() {
  228. if (this.model.length > 0) {
  229. $('#policy-info', this.el).show();
  230. $('#policy-table', this.el).show();
  231. $('#policy-table-empty', this.el).hide();
  232. } else {
  233. $('#policy-info', this.el).hide();
  234. $('#policy-table', this.el).hide();
  235. $('#policy-table-empty', this.el).show();
  236. }
  237. },
  238. addPolicy:function(e) {
  239. e.preventDefault();
  240. app.navigate('user/policy/' + this.options.rs.get('id') +'/new', {trigger: true});
  241. },
  242. render:function (eventName) {
  243. $(this.el).html($('#tmpl-policy-table').html());
  244. var _self = this;
  245. _.each(this.model.models, function (policy) {
  246. var view = new PolicyView({model: policy, systemScopeList: _self.options.systemScopeList, rs: _self.options.rs});
  247. view.parentView = _self;
  248. $('#policy-table', this.el).append(view.render().el);
  249. }, this);
  250. this.togglePlaceholder();
  251. $(this.el).i18n();
  252. return this;
  253. }
  254. });
  255. var PolicyView = Backbone.View.extend({
  256. tagName: 'tr',
  257. initialize:function(options) {
  258. this.options = options;
  259. if (!this.template) {
  260. this.template = _.template($('#tmpl-policy').html());
  261. }
  262. if (!this.scopeTemplate) {
  263. this.scopeTemplate = _.template($('#tmpl-scope-list').html());
  264. }
  265. },
  266. events:{
  267. 'click .btn-edit':'editPolicy',
  268. 'click .btn-remove':'removePolicy'
  269. },
  270. editPolicy:function(e) {
  271. e.preventDefault();
  272. app.navigate('user/policy/' + this.options.rs.get("id") + '/' + this.model.get('id'), {trigger: true});
  273. },
  274. removePolicy:function(e) {
  275. e.preventDefault();
  276. if (confirm($.t('policy.policy-table.confirm'))) {
  277. var _self = this;
  278. this.model.destroy({
  279. dataType: false, processData: false,
  280. success:function () {
  281. _self.$el.fadeTo("fast", 0.00, function () { //fade
  282. $(this).slideUp("fast", function () { //slide up
  283. $(this).remove(); //then remove from the DOM
  284. _self.parentView.togglePlaceholder();
  285. });
  286. });
  287. },
  288. error:function (error, response) {
  289. console.log("An error occurred when deleting a client");
  290. //Pull out the response text.
  291. var responseJson = JSON.parse(response.responseText);
  292. //Display an alert with an error message
  293. $('#modalAlert div.modal-header').html(responseJson.error);
  294. $('#modalAlert div.modal-body').html(responseJson.error_description);
  295. $("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
  296. "backdrop" : "static",
  297. "keyboard" : true,
  298. "show" : true // ensure the modal is shown immediately
  299. });
  300. }
  301. });
  302. _self.parentView.delegateEvents();
  303. }
  304. },
  305. render:function (eventName) {
  306. var json = this.model.toJSON();
  307. this.$el.html(this.template(json));
  308. $('.scope-list', this.el).html(this.scopeTemplate({scopes: this.model.get('scopes'), systemScopes: this.options.systemScopeList}));
  309. $(this.el).i18n();
  310. return this;
  311. }
  312. });
  313. var PolicyFormView = Backbone.View.extend({
  314. tagName: 'div',
  315. initialize:function(options) {
  316. this.options = options;
  317. if (!this.template) {
  318. this.template = _.template($('#tmpl-policy-form').html());
  319. }
  320. this.issuerCollection = new Backbone.Collection();
  321. },
  322. events:{
  323. 'click .btn-share': 'addWebfingerClaim',
  324. 'click .btn-share-advanced': 'addAdvancedClaim',
  325. 'click .btn-clear': 'clearAllClaims',
  326. 'click .btn-save': 'savePolicy',
  327. 'click .btn-cancel': 'cancel'
  328. },
  329. load:function(callback) {
  330. if (this.model.isFetched &&
  331. this.options.rs.isFetched &&
  332. this.options.systemScopeList.isFetched) {
  333. callback();
  334. return;
  335. }
  336. $('#loadingbox').sheet('show');
  337. $('#loading').html(
  338. '<span class="label" id="loading-policies">' + $.t('policy.loading-policy') + '</span> ' +
  339. '<span class="label" id="loading-rs">' + $.t('policy.loading-rs') + '</span> ' +
  340. '<span class="label" id="loading-scopes">' + $.t("common.scopes") + '</span> '
  341. );
  342. $.when(this.model.fetchIfNeeded({success:function(e) {$('#loading-policies').addClass('label-success');}}),
  343. this.options.rs.fetchIfNeeded({success:function(e) {$('#loading-rs').addClass('label-success');}}),
  344. this.options.systemScopeList.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}}))
  345. .done(function() {
  346. $('#loadingbox').sheet('hide');
  347. callback();
  348. });
  349. },
  350. addWebfingerClaim:function(e) {
  351. e.preventDefault();
  352. // post to the webfinger helper and get the response back
  353. var _self = this;
  354. var email = $('#email', this.el).val();
  355. $('#loadingbox').sheet('show');
  356. $('#loading').html(
  357. 'Looking up identity provider...'
  358. );
  359. var base = $('base').attr('href');
  360. $.getJSON(base + '/api/emailsearch?' + $.param({'identifier': email}), function(data) {
  361. // grab the current state of the scopes checkboxes just in case
  362. var scopes = $('#scopes input[type="checkbox"]:checked').map(function(idx, elem) { return $(elem).val(); }).get();
  363. _self.model.set({
  364. scopes: scopes,
  365. claimsRequired: data
  366. }, {trigger: false});
  367. _self.render();
  368. $('#loadingbox').sheet('hide');
  369. }).error(function(jqXHR, textStatus, errorThrown) {
  370. console.log("An error occurred when doing a webfinger lookup", errorThrown);
  371. $('#loadingbox').sheet('hide');
  372. //Display an alert with an error message
  373. $('#modalAlert div.modal-header').html($.t('policy.webfinger-error'));
  374. $('#modalAlert div.modal-body').html($.t('policy.webfinger-error-description', {email: email}));
  375. $("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
  376. "backdrop" : "static",
  377. "keyboard" : true,
  378. "show" : true // ensure the modal is shown immediately
  379. });
  380. });
  381. },
  382. addAdvancedClaim:function(e) {
  383. e.preventDefault();
  384. var name = $('#name', this.el).val();
  385. var friendly = $('#friendly-name', this.el).val();
  386. var rawValue = $('#value', this.el).val();
  387. var valueType = $('#value-type', this.el).val();
  388. var value = null;
  389. if (valueType == 'number') {
  390. value = Number(rawValue);
  391. } else if (valueType == 'boolean') {
  392. value = (rawValue.toLowerCase() == 'true');
  393. } else if (valueType == 'json') {
  394. value = JSON.parse(rawValue);
  395. } else {
  396. // treat it as a string, the default
  397. value = rawValue;
  398. }
  399. var issuers = this.issuerCollection.pluck('item');
  400. console.log(name, friendly, rawValue, valueType, value, issuers);
  401. if (!_.isEmpty(issuers)
  402. && name
  403. && value) {
  404. // we've got a valid claim, add it to our set
  405. // grab the current state of the scopes checkboxes just in case
  406. var scopes = $('#scopes input[type="checkbox"]:checked').map(function(idx, elem) { return $(elem).val(); }).get();
  407. var claimsRequired = this.model.get('claimsRequired');
  408. if (!claimsRequired) {
  409. claimsRequired = [];
  410. }
  411. claimsRequired.push({
  412. name: name,
  413. friendlyName: friendly,
  414. value: value,
  415. issuer: issuers
  416. });
  417. this.model.set({
  418. scopes: scopes,
  419. claimsRequired: claimsRequired
  420. }, {trigger: false});
  421. $('#name', this.el).val('');
  422. $('#friendly-name', this.el).val('');
  423. $('#value', this.el).val('');
  424. $('#value-type', this.el).val('text');
  425. this.render();
  426. // re-select the advanced tab
  427. $('a[data-target="#policy-advanced-tab"]', this.el).tab('show')
  428. } else {
  429. // something is missing
  430. $('#loadingbox').sheet('hide');
  431. //Display an alert with an error message
  432. $('#modalAlert div.modal-header').html($.t('policy.advanced-error'));
  433. $('#modalAlert div.modal-body').html($.t('policy.advanced-error-description'));
  434. $("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
  435. "backdrop" : "static",
  436. "keyboard" : true,
  437. "show" : true // ensure the modal is shown immediately
  438. });
  439. }
  440. },
  441. clearAllClaims:function(e) {
  442. e.preventDefault();
  443. if (confirm($.t('policy.policy-form.clear-all-confirm'))) {
  444. var scopes = $('#scopes input[type="checkbox"]:checked').map(function(idx, elem) { return $(elem).val(); }).get();
  445. var claimsRequired = [];
  446. this.model.set({
  447. scopes: scopes,
  448. claimsRequired: claimsRequired
  449. }, {trigger: false});
  450. this.render();
  451. }
  452. },
  453. savePolicy:function(e) {
  454. e.preventDefault();
  455. // get all the scopes that are checked
  456. var scopes = $('#scopes input[type="checkbox"]:checked').map(function(idx, elem) { return $(elem).val(); }).get();
  457. var valid = this.model.set({
  458. scopes: scopes
  459. });
  460. if (valid) {
  461. var _self = this;
  462. this.model.save({}, {
  463. success:function() {
  464. app.systemScopeList.add(_self.model);
  465. // refresh the associated RS
  466. _self.options.rs.fetch({success: function() {
  467. app.navigate('user/policy/' + _self.options.rs.get('id'), {trigger: true});
  468. }});
  469. },
  470. error:function(error, response) {
  471. //Pull out the response text.
  472. var responseJson = JSON.parse(response.responseText);
  473. //Display an alert with an error message
  474. $('#modalAlert div.modal-header').html(responseJson.error);
  475. $('#modalAlert div.modal-body').html(responseJson.error_description);
  476. $("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog
  477. "backdrop" : "static",
  478. "keyboard" : true,
  479. "show" : true // ensure the modal is shown immediately
  480. });
  481. }
  482. });
  483. }
  484. return false;
  485. },
  486. cancel:function(e) {
  487. e.preventDefault();
  488. app.navigate('user/policy/' + this.options.rs.get('id'), {trigger: true});
  489. },
  490. render:function (eventName) {
  491. var json = this.model.toJSON();
  492. var rs = this.options.rs.toJSON();
  493. this.$el.html(this.template({policy: json, rs: rs}));
  494. // build and bind issuer view
  495. var issuerView = new ListWidgetView({
  496. placeholder: $.t('policy.policy-form.issuer-placeholder'),
  497. helpBlockText: $.t('policy.policy-form.issuer-help'),
  498. collection: this.issuerCollection});
  499. $("#issuers .controls",this.el).html(issuerView.render().el);
  500. $(this.el).i18n();
  501. return this;
  502. }
  503. });