Valentin Valchev | 516c8e5 | 2014-11-18 08:37:37 +0000 | [diff] [blame] | 1 | /*
|
| 2 | * Licensed to the Apache Software Foundation (ASF) under one or more
|
| 3 | * contributor license agreements. See the NOTICE file distributed with
|
| 4 | * this work for additional information regarding copyright ownership.
|
| 5 | * The ASF licenses this file to You under the Apache License, Version 2.0
|
| 6 | * (the "License"); you may not use this file except in compliance with
|
| 7 | * the License. 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 | // fix for jQuery tree to work with this version of jQuery
|
| 18 | jQuery.curCSS = jQuery.css;
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 19 |
|
| 20 | var userTree = false;
|
| 21 | var selectedRole = false;
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 22 | var selectedParent = false;
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 23 | var newDialogRole = false;
|
| 24 | var roleDetails = false;
|
| 25 | var roleDetailsHelp = false;
|
| 26 | var roleDetailsTable = false;
|
| 27 | var roleDetailsBody = false;
|
| 28 | var roleDetailsTemplate = false;
|
| 29 | var roleDetailsTemplateP = false;
|
| 30 | var roleDetailsTemplateC = false;
|
| 31 |
|
| 32 | function roleObj(node) {
|
| 33 | node = node && node.attr ? node.attr('role') : false;
|
| 34 | return node ? JSON.parse(node) : false;
|
| 35 | }
|
| 36 |
|
| 37 | var treeSettings = {
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 38 | core : {
|
| 39 | data : [], // will be set on load
|
| 40 | multiple : false,
|
| 41 | themes : { stripes : true },
|
| 42 | check_callback : function (operation, node, node_parent, node_position, more) {
|
| 43 | // disable copy to root node
|
| 44 | if ('#' === node_parent.id) return false;
|
| 45 | if (operation === 'copy_node' && 'root' === node_parent.id) return false;
|
| 46 |
|
| 47 | if (operation === 'move_node' || operation === 'copy_node') {
|
| 48 | // don't copy/move things around the same/root level
|
| 49 | if (node.parent === node_parent.id) return false;
|
| 50 |
|
| 51 | // don't copy/move if target alreay contains the same member
|
| 52 | var target = node_parent.original.role;
|
| 53 | if (target && isMember(node.original.role, target)) return false;
|
| 54 | }
|
| 55 | return true;
|
| 56 | }
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 57 | },
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 58 | plugins : [ 'dnd', 'types', 'sort' ],
|
| 59 | types : {
|
| 60 | root : { valid_children: ['t0', 't1', 't2'], icon : pluginRoot + '/res/book-2.png' },
|
| 61 | t2 : { valid_children: ['t0', 't1', 't2'], icon : pluginRoot + '/res/group.png' },
|
| 62 | t1 : { valid_children: [], icon : pluginRoot + '/res/user.png' },
|
| 63 | t0 : { valid_children: [], icon : pluginRoot + '/res/role.png' }
|
| 64 | }
|
| 65 | }
|
| 66 |
|
| 67 | function initTree(data) {
|
| 68 | // show help message
|
| 69 | roleDetailsHelp.removeClass('ui-helper-hidden');
|
| 70 | roleDetailsTable.addClass('ui-helper-hidden');
|
| 71 |
|
| 72 | var openNodes = [];
|
| 73 |
|
| 74 | // recreate tree, because reload doesn't work
|
| 75 | var userTreeRef = $.jstree.reference('#userTree');
|
| 76 | if (userTreeRef) {
|
| 77 | userTreeRef.destroy();
|
| 78 |
|
| 79 | // save state
|
| 80 | $.each(userTreeRef.get_node('root').children_d, function(idx, child) {
|
| 81 | var node = userTreeRef.get_node(child);
|
| 82 | if ( node.state.opened ) openNodes.push(node.text);
|
| 83 | });
|
| 84 | }
|
| 85 |
|
| 86 | // prepare data
|
| 87 | var sortedGroups = sortGroups(data);
|
| 88 | treeSettings.core['data'] = buildTree(sortedGroups);
|
| 89 |
|
| 90 | // build tree
|
| 91 | userTree = $('#userTree')
|
| 92 | .on('select_node.jstree', function(e, data) {
|
| 93 | var role = data.node.original.role;
|
| 94 | if (role) {
|
| 95 | var parent = data.node.parent;
|
| 96 | var parent_name = parent === '#' || parent === 'root' ? false : data.instance.get_node(parent).text;
|
| 97 | onSelectNode(role.name, parent_name);
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 98 | } else {
|
| 99 | roleDetailsHelp.removeClass('ui-helper-hidden');
|
| 100 | roleDetailsTable.addClass('ui-helper-hidden');
|
| 101 | }
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 102 | })
|
| 103 | .on('move_node.jstree', function(e, data) {
|
| 104 | var role = data.node.original.role;
|
| 105 | var parent = data.parent;
|
| 106 | var parent_name = parent === '#' || parent === 'root' ? false : data.instance.get_node(parent).text;
|
| 107 | var old_parent = data.old_parent;
|
| 108 | var old_parent_name = old_parent === '#' || old_parent === 'root' ? false : data.instance.get_node(old_parent).text;
|
| 109 |
|
| 110 | if (parent_name) {
|
| 111 | //console.log('move: adding role', role, 'to group', parent);
|
| 112 | $.post(pluginRoot, {'action': 'addMember', 'role' : role.name, 'group' : parent_name});
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 113 | }
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 114 | if (old_parent_name) {
|
| 115 | //console.log('move: removed role', role, 'to group', old_parent);
|
| 116 | $.post(pluginRoot, {'action': 'removeMember', 'role' : role.name, 'group' : old_parent_name});
|
| 117 | }
|
| 118 | $('#reload').click();
|
| 119 | })
|
| 120 | .on('copy_node.jstree', function(e, data) {
|
| 121 | var role = data.original.original.role;
|
| 122 | var parent_name = data.instance.get_node(data.parent).text;
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 123 |
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 124 | if (parent_name) {
|
| 125 | //console.log('copy: copying role', role, 'to group', parent);
|
| 126 | $.post(pluginRoot, {'action': 'addMember', 'role' : role.name, 'group' : parent_name});
|
| 127 | }
|
| 128 | $('#reload').click();
|
| 129 | })
|
| 130 | .on('ready.jstree', function(e, data) { // restore state
|
| 131 | var _ = data.instance;
|
| 132 | if (openNodes.length) $.each(_.get_node('root').children_d, function(idx, child) {
|
| 133 | var node = _.get_node(child);
|
| 134 | if ($.inArray(node.text, openNodes) > -1) _.open_node(node, false, false);
|
| 135 | });
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 136 |
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 137 | }).jstree(treeSettings);
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 138 | }
|
| 139 |
|
| 140 | $(function() {
|
Valentin Valchev | 516c8e5 | 2014-11-18 08:37:37 +0000 | [diff] [blame] | 141 | // read the available digest algorithms
|
| 142 | $.ajax({
|
| 143 | type : "POST",
|
| 144 | url : pluginRoot,
|
| 145 | async : false,
|
| 146 | data : {'action': 'getDigestAlgorithms' },
|
| 147 | dataType: 'json',
|
| 148 | success : function(data) {
|
| 149 | var _select = $('select.propertyType');
|
| 150 | $.each(data, function(id, alg) {
|
| 151 | _select.append('<option value="password-{0}">{1} {2}</option>'.msgFormat(alg, i18n.paswd, alg));
|
| 152 | });
|
| 153 | }
|
| 154 | });
|
| 155 |
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 156 | roleDetails = $('#roleDetails');
|
| 157 | roleDetailsTable = roleDetails.find('table');
|
| 158 | roleDetailsHelp = roleDetails.find('#roleDetailsHelp');
|
| 159 | roleDetailsBody = roleDetailsTable.find('tbody');
|
| 160 | roleDetailsTemplateP = roleDetailsBody.find('tr:eq(0)');
|
| 161 | roleDetailsTemplateC = roleDetailsBody.find('tr:eq(1)');
|
| 162 | roleDetailsTemplate = roleDetailsBody.find('tr:eq(2)').clone();
|
| 163 | roleDetailsBody.find('tr').not('.header').remove();
|
| 164 |
|
| 165 | // add new property/credential code
|
| 166 | $('tr.header span.ui-icon-plus').click(function() {
|
| 167 | $(this).parent().parent().parent().parent().after(newProp());
|
| 168 | });
|
| 169 |
|
| 170 | // new role dialog
|
| 171 | var _buttons = {};
|
| 172 | _buttons[i18n.close] = function() {
|
| 173 | $(this).dialog('close');
|
| 174 | }
|
| 175 | _buttons[i18n.add] = function() {
|
| 176 | var _ = newDialogRole;
|
| 177 | var n = _.find('input');
|
| 178 | if (!n.val()) {
|
| 179 | n.addClass('ui-state-error');
|
| 180 | return false;
|
| 181 | } else n.removeClass('ui-state-error');
|
| 182 | var t = _.find('select').val();
|
| 183 | $.post(pluginRoot, {'action': 'set', 'data' : JSON.stringify({'name': n.val(), 'type': new Number(t)})} , function(data) {
|
| 184 | _.dialog('close');
|
| 185 | $('#reload').click();
|
| 186 | }, 'json');
|
| 187 | }
|
| 188 | newDialogRole = $("#newDialogRole").dialog({
|
| 189 | autoOpen : false,
|
| 190 | modal : true,
|
| 191 | open : function() { $(this).find('input').val('').removeClass('ui-state-error') },
|
| 192 | closeText: i18n.abort,
|
| 193 | buttons : _buttons
|
| 194 | });
|
| 195 |
|
| 196 | // role info buttons
|
| 197 | $('#delRole').click( function() {
|
| 198 | if (selectedRole) $.post(pluginRoot, {'action': 'del', 'role' : selectedRole}, function() {
|
| 199 | $('#reload').click();
|
| 200 | });
|
| 201 | });
|
| 202 | $('#savRole').click( doSaveRole );
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 203 | $('#toggleRequiredRole').click( function() {
|
| 204 | if (selectedRole && selectedParent)
|
| 205 | $.post(pluginRoot, { action: 'toggleMembership', role: selectedRole, group: selectedParent }, function() {
|
| 206 | $('#reload').click()
|
| 207 | });
|
| 208 | });
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 209 |
|
| 210 | // top-frame buttons
|
| 211 | $('#newRole').click( function() {
|
| 212 | newDialogRole.dialog('open');
|
| 213 | return false;
|
| 214 | });
|
| 215 | $('#reload').click( function() {
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 216 | $.post(pluginRoot, {'action': 'list'} , initTree, 'json');
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 217 | return false;
|
| 218 | }).click();
|
| 219 | });
|
| 220 |
|
Valentin Valchev | 516c8e5 | 2014-11-18 08:37:37 +0000 | [diff] [blame] | 221 | function digest(val, alg) {
|
| 222 | var _ret = false;
|
| 223 | $.ajax({
|
| 224 | type : "POST",
|
| 225 | url : pluginRoot,
|
| 226 | async : false,
|
| 227 | data : {
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 228 | 'action': 'digest',
|
| 229 | 'data' : val,
|
Valentin Valchev | 516c8e5 | 2014-11-18 08:37:37 +0000 | [diff] [blame] | 230 | 'algorithm' : alg
|
| 231 | },
|
| 232 | dataType: 'json',
|
| 233 | success : function(data) {
|
| 234 | _ret = data['encoded'];
|
| 235 | }
|
| 236 | });
|
| 237 | return _ret;
|
| 238 | }
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 239 | function newProp() {
|
| 240 | var tr = roleDetailsTemplate.clone()
|
| 241 | .find('li').click( function() {
|
| 242 | tr.remove();
|
| 243 | }).end()
|
| 244 | .find('select').change( function(evt) {
|
| 245 | tr.find('.v').replaceWith('<input class="v" '+ ($(this).val().indexOf('password') == 0 ? 'type="password"' : '') + '/>');
|
| 246 | initStaticWidgets(tr);
|
| 247 | }).end()
|
| 248 | initStaticWidgets(tr);
|
| 249 | return tr;
|
| 250 | }
|
| 251 | function hashToArray(s) {
|
| 252 | var r = [];
|
| 253 | while(s.length > 0) {
|
| 254 | r.push(parseInt(s.substring(0, 2), 16));
|
| 255 | s = s.substring(2);
|
| 256 | }
|
| 257 | return r;
|
| 258 | }
|
| 259 | function strToArray(s) {
|
| 260 | var r = [];
|
| 261 | var el = s.split(',');
|
| 262 | for(var i=0;i<el.length;i++) r.push( parseInt(el[i], 10) );
|
| 263 | return r;
|
| 264 | }
|
| 265 | function doSaveRole() {
|
| 266 | if (!selectedRole) return;
|
| 267 | var doProps = true;
|
| 268 | var data = {
|
| 269 | name : selectedRole,
|
| 270 | properties : {},
|
| 271 | credentials : {}
|
| 272 | };
|
| 273 | roleDetailsBody.find('tr').each( function() {
|
| 274 | var _ = $(this);
|
| 275 | if (_.hasClass('header-props')) doProps = true;
|
| 276 | else if (_.hasClass('header-cred')) doProps = false;
|
| 277 | else {
|
| 278 | var k = _.find('.k').val();
|
| 279 | var v = _.find('.v').val();
|
| 280 | var t = _.find('select').val();
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 281 |
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 282 | if (t.indexOf('password-') == 0) {
|
Valentin Valchev | 516c8e5 | 2014-11-18 08:37:37 +0000 | [diff] [blame] | 283 | var hash = digest(v, t.substring(9));
|
Valentin Valchev | 516c8e5 | 2014-11-18 08:37:37 +0000 | [diff] [blame] | 284 | v = hash;
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 285 | } else if (t == 'byte[]') {
|
| 286 | v = strToArray(v);
|
| 287 | }
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 288 |
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 289 | if (doProps) data.properties[k] = v;
|
| 290 | else data.credentials[k] = v;
|
| 291 | }
|
| 292 | });
|
| 293 | $.post(pluginRoot, {'action': 'set', 'data' : JSON.stringify(data)});
|
| 294 | }
|
| 295 |
|
| 296 | function isInMemberArray(role, g) {
|
| 297 | if(g) for(var i in g) if (g[i].name == role.name) return true;
|
| 298 | return false;
|
| 299 | }
|
| 300 |
|
| 301 | function isMember(role, group) {
|
| 302 | if (!role) return false;
|
| 303 | if (!group) return false;
|
| 304 | if (isInMemberArray(role, group.members)) return true;
|
| 305 | if (isInMemberArray(role, group.rmembers)) return true;
|
| 306 | }
|
| 307 |
|
| 308 | function buildTree(sortedGroups) {
|
| 309 | var treeRoot = {
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 310 | text : i18n.root,
|
| 311 | id : 'root',
|
| 312 | type : 'root',
|
| 313 | state: { opened : true },
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 314 | children: []
|
| 315 | };
|
| 316 | var treeNode = function(name, role, parent, req) {
|
| 317 | if (!role) return;
|
| 318 | if (!parent) parent = treeRoot.children;
|
| 319 | var node = {
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 320 | 'text' : role.name,
|
| 321 | 'type' : 't' + role.type,
|
| 322 | 'role' : role,
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 323 | }
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 324 | if (req) node.li_attr = { 'class' : 'required' };
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 325 | parent.push(node);
|
| 326 | if (role.type == 2) {
|
| 327 | node['children'] = [];
|
| 328 | node = node['children'];
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 329 | if (role.members) $.each(role.members, function(idx, xrole) {
|
| 330 | treeNode(xrole.name, xrole, node, 0);
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 331 | });
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 332 | if (role.rmembers) $.each(role.rmembers, function(idx, xrole) {
|
| 333 | treeNode(xrole.name, xrole, node, 1);
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 334 | });
|
| 335 | }
|
| 336 | }
|
| 337 |
|
| 338 | $.each(sortedGroups, treeNode);
|
| 339 | return treeRoot;
|
| 340 | }
|
| 341 |
|
| 342 | function sortGroups(data) {
|
| 343 | var rootGroups = {}; // only root groups - without parents
|
| 344 | var unassigned = {}; // non-groups, not assigned to any group
|
| 345 | var processed = {}; // all processed entries
|
| 346 | var u = 0;
|
| 347 | var g = 0;
|
| 348 | var r = 0;
|
| 349 |
|
| 350 | var _st = function(map, n, role) {
|
| 351 | if (typeof map[n] == 'undefined') { // not added - add
|
| 352 | map[n] = role;
|
| 353 | } else if (map[n] != false) { // already added
|
| 354 | map[n] = false; // mark for removal
|
| 355 | }
|
| 356 | }
|
| 357 |
|
| 358 | var groupF = function(i1, role) {
|
| 359 | var n = role.name;
|
| 360 | var t = role.type;
|
| 361 |
|
| 362 | if (t == 2) { // group
|
| 363 | // don't process twice
|
| 364 | if (processed[n]) {
|
| 365 | rootGroups[n] = false;
|
| 366 | return true;
|
| 367 | }
|
| 368 | processed[n]=role;
|
| 369 |
|
| 370 | _st(rootGroups, n, role);
|
| 371 |
|
| 372 | if (role.members) $.each(role.members, groupF);
|
| 373 | if (role.rmembers) $.each(role.rmembers, groupF);
|
| 374 | g++;
|
| 375 | } else { // role or user
|
| 376 | if (t == 1) u++; else r++;
|
| 377 | _st(unassigned, n, role);
|
| 378 | }
|
| 379 | }
|
| 380 |
|
| 381 | $.each(data, groupF);
|
| 382 | $('.statline').text( i18n.status.msgFormat(g,u,r) );
|
| 383 |
|
| 384 | return $.extend(rootGroups, unassigned);
|
| 385 | }
|
| 386 |
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 387 | function onSelectNode(role, parent) {
|
| 388 | if (parent) {
|
| 389 | $('#toggleRequiredRole').removeClass('ui-state-disabled');
|
| 390 | } else {
|
| 391 | $('#toggleRequiredRole').addClass('ui-state-disabled')
|
| 392 | }
|
| 393 |
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 394 | $.post(pluginRoot, {'action': 'get', 'role' : role} , function(data) {
|
| 395 | selectedRole = role;
|
Valentin Valchev | 8503056 | 2015-01-13 08:23:56 +0000 | [diff] [blame] | 396 | selectedParent = parent;
|
Valentin Valchev | eddfbc4 | 2012-08-21 20:06:24 +0000 | [diff] [blame] | 397 | roleDetailsHelp.addClass('ui-helper-hidden');
|
| 398 | roleDetailsTable.removeClass('ui-helper-hidden');
|
| 399 | roleDetailsBody.find('tr').not('.header').remove();
|
| 400 |
|
| 401 | var target = false;
|
| 402 | var _append = function(k,v) {
|
| 403 | var t = $.isArray(v) ? 'byte[]' : 'string';
|
| 404 | target.after(newProp()
|
| 405 | .data('k', k)
|
| 406 | .find('input.k').val(k).end()
|
| 407 | .find('input.v').val(v).end()
|
| 408 | .find('select').val(t).end()
|
| 409 | );
|
| 410 | }
|
| 411 | var x = data.properties;
|
| 412 | if (x) {
|
| 413 | target = roleDetailsTemplateP;
|
| 414 | $.each(x, _append);
|
| 415 | }
|
| 416 | x = data.credentials;
|
| 417 | if (x) {
|
| 418 | target = roleDetailsTemplateC;
|
| 419 | $.each(x, _append);
|
| 420 | }
|
| 421 | // show/user credentials view if user/or not (respectively)
|
| 422 | x = roleDetailsBody.find('.header-cred');
|
| 423 | if (data.type != 1) x.addClass('ui-helper-hidden');
|
| 424 | else x.removeClass('ui-helper-hidden');
|
| 425 | }, 'json')
|
| 426 | return false;
|
| 427 | }
|
| 428 |
|