blob: 12f1ec61b9c95877f7a31a253e6c467a1ff865b8 [file] [log] [blame]
Valentin Valchev516c8e52014-11-18 08:37:37 +00001/*
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
18jQuery.curCSS = jQuery.css;
Valentin Valcheveddfbc42012-08-21 20:06:24 +000019
20var userTree = false;
21var selectedRole = false;
Valentin Valchev85030562015-01-13 08:23:56 +000022var selectedParent = false;
Valentin Valcheveddfbc42012-08-21 20:06:24 +000023var newDialogRole = false;
24var roleDetails = false;
25var roleDetailsHelp = false;
26var roleDetailsTable = false;
27var roleDetailsBody = false;
28var roleDetailsTemplate = false;
29var roleDetailsTemplateP = false;
30var roleDetailsTemplateC = false;
31
32function roleObj(node) {
33 node = node && node.attr ? node.attr('role') : false;
34 return node ? JSON.parse(node) : false;
35}
36
37var treeSettings = {
Valentin Valchev85030562015-01-13 08:23:56 +000038 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 Valcheveddfbc42012-08-21 20:06:24 +000057 },
Valentin Valchev85030562015-01-13 08:23:56 +000058 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
67function 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 Valcheveddfbc42012-08-21 20:06:24 +000098 } else {
99 roleDetailsHelp.removeClass('ui-helper-hidden');
100 roleDetailsTable.addClass('ui-helper-hidden');
101 }
Valentin Valchev85030562015-01-13 08:23:56 +0000102 })
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 Valcheveddfbc42012-08-21 20:06:24 +0000113 }
Valentin Valchev85030562015-01-13 08:23:56 +0000114 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 Valcheveddfbc42012-08-21 20:06:24 +0000123
Valentin Valchev85030562015-01-13 08:23:56 +0000124 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 Valcheveddfbc42012-08-21 20:06:24 +0000136
Valentin Valchev85030562015-01-13 08:23:56 +0000137 }).jstree(treeSettings);
Valentin Valcheveddfbc42012-08-21 20:06:24 +0000138}
139
140$(function() {
Valentin Valchev516c8e52014-11-18 08:37:37 +0000141 // 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 Valcheveddfbc42012-08-21 20:06:24 +0000156 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 Valchev85030562015-01-13 08:23:56 +0000203 $('#toggleRequiredRole').click( function() {
204 if (selectedRole && selectedParent)
205 $.post(pluginRoot, { action: 'toggleMembership', role: selectedRole, group: selectedParent }, function() {
206 $('#reload').click()
207 });
208 });
Valentin Valcheveddfbc42012-08-21 20:06:24 +0000209
210 // top-frame buttons
211 $('#newRole').click( function() {
212 newDialogRole.dialog('open');
213 return false;
214 });
215 $('#reload').click( function() {
Valentin Valchev85030562015-01-13 08:23:56 +0000216 $.post(pluginRoot, {'action': 'list'} , initTree, 'json');
Valentin Valcheveddfbc42012-08-21 20:06:24 +0000217 return false;
218 }).click();
219});
220
Valentin Valchev516c8e52014-11-18 08:37:37 +0000221function digest(val, alg) {
222 var _ret = false;
223 $.ajax({
224 type : "POST",
225 url : pluginRoot,
226 async : false,
227 data : {
Valentin Valchev85030562015-01-13 08:23:56 +0000228 'action': 'digest',
229 'data' : val,
Valentin Valchev516c8e52014-11-18 08:37:37 +0000230 'algorithm' : alg
231 },
232 dataType: 'json',
233 success : function(data) {
234 _ret = data['encoded'];
235 }
236 });
237 return _ret;
238}
Valentin Valcheveddfbc42012-08-21 20:06:24 +0000239function 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}
251function 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}
259function 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}
265function 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 Valchev85030562015-01-13 08:23:56 +0000281
Valentin Valcheveddfbc42012-08-21 20:06:24 +0000282 if (t.indexOf('password-') == 0) {
Valentin Valchev516c8e52014-11-18 08:37:37 +0000283 var hash = digest(v, t.substring(9));
Valentin Valchev516c8e52014-11-18 08:37:37 +0000284 v = hash;
Valentin Valcheveddfbc42012-08-21 20:06:24 +0000285 } else if (t == 'byte[]') {
286 v = strToArray(v);
287 }
Valentin Valchev85030562015-01-13 08:23:56 +0000288
Valentin Valcheveddfbc42012-08-21 20:06:24 +0000289 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
296function isInMemberArray(role, g) {
297 if(g) for(var i in g) if (g[i].name == role.name) return true;
298 return false;
299}
300
301function 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
308function buildTree(sortedGroups) {
309 var treeRoot = {
Valentin Valchev85030562015-01-13 08:23:56 +0000310 text : i18n.root,
311 id : 'root',
312 type : 'root',
313 state: { opened : true },
Valentin Valcheveddfbc42012-08-21 20:06:24 +0000314 children: []
315 };
316 var treeNode = function(name, role, parent, req) {
317 if (!role) return;
318 if (!parent) parent = treeRoot.children;
319 var node = {
Valentin Valchev85030562015-01-13 08:23:56 +0000320 'text' : role.name,
321 'type' : 't' + role.type,
322 'role' : role,
Valentin Valcheveddfbc42012-08-21 20:06:24 +0000323 }
Valentin Valchev85030562015-01-13 08:23:56 +0000324 if (req) node.li_attr = { 'class' : 'required' };
Valentin Valcheveddfbc42012-08-21 20:06:24 +0000325 parent.push(node);
326 if (role.type == 2) {
327 node['children'] = [];
328 node = node['children'];
Valentin Valchev85030562015-01-13 08:23:56 +0000329 if (role.members) $.each(role.members, function(idx, xrole) {
330 treeNode(xrole.name, xrole, node, 0);
Valentin Valcheveddfbc42012-08-21 20:06:24 +0000331 });
Valentin Valchev85030562015-01-13 08:23:56 +0000332 if (role.rmembers) $.each(role.rmembers, function(idx, xrole) {
333 treeNode(xrole.name, xrole, node, 1);
Valentin Valcheveddfbc42012-08-21 20:06:24 +0000334 });
335 }
336 }
337
338 $.each(sortedGroups, treeNode);
339 return treeRoot;
340}
341
342function 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 Valchev85030562015-01-13 08:23:56 +0000387function onSelectNode(role, parent) {
388 if (parent) {
389 $('#toggleRequiredRole').removeClass('ui-state-disabled');
390 } else {
391 $('#toggleRequiredRole').addClass('ui-state-disabled')
392 }
393
Valentin Valcheveddfbc42012-08-21 20:06:24 +0000394 $.post(pluginRoot, {'action': 'get', 'role' : role} , function(data) {
395 selectedRole = role;
Valentin Valchev85030562015-01-13 08:23:56 +0000396 selectedParent = parent;
Valentin Valcheveddfbc42012-08-21 20:06:24 +0000397 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