blob: 214b5dae9b759779b0d166d89110e775230106af [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;
22var newDialogRole = false;
23var roleDetails = false;
24var roleDetailsHelp = false;
25var roleDetailsTable = false;
26var roleDetailsBody = false;
27var roleDetailsTemplate = false;
28var roleDetailsTemplateP = false;
29var roleDetailsTemplateC = false;
30
31function roleObj(node) {
32 node = node && node.attr ? node.attr('role') : false;
33 return node ? JSON.parse(node) : false;
34}
35
36var treeSettings = {
37 data : {
38 type : 'json',
39 opts : { 'static' : [] }
40 },
41 ui : { theme_name : 'themeroller' },
42 rules : { multiple : false, valid_children: ['root'] },
43 types : {
44 root : { valid_children: ['t0', 't1', 't2'] },
45 t2 : { valid_children: ['t0', 't1', 't2'] },
46 t1 : { valid_children: 'none' },
47 t0 : { valid_children: 'none' }
48 },
49 callback : {
50 onselect : function(node) {
51 var _role = $(node).attr('role');
52 if (_role) {
53 var role = JSON.parse( _role );
54 onSelectNode(role.name);
55 $(node).children('a').addClass('ui-priority-primary');
56 } else {
57 roleDetailsHelp.removeClass('ui-helper-hidden');
58 roleDetailsTable.addClass('ui-helper-hidden');
59 }
60 },
61 onparse : function (s, t) {
62 return $(s)
63 .find('li[rel=t2] > a > ins').addClass('ui-icon ui-icon-contact').end()
64 .find('li[rel=t1] > a > ins').addClass('ui-icon ui-icon-person').end()
65 .find('li[rel=t0] > a > ins').addClass('ui-icon ui-icon-bullet').end();
66 },
67 ondeselect : function(node) { $(node).children('a').removeClass('ui-priority-primary') },
68 ondblclk : function(node, tree_obj) {
69 var n = $(node);
70 var pp = tree_obj.parent(node);
71 var r = roleObj(n);
72 var g = roleObj(pp);
73 console.log(r, g);
74 if (r && g) {
75 if( isInMemberArray(r, g.members, 1) ) {
76 $.post(pluginRoot, { action: 'removeMember', role: r.name, group: g.name });
77 $.post(pluginRoot, { action: 'addRequiredMember', role: r.name, group: g.name }, function(data) {
78 pp.attr('role', JSON.stringify(data));
79 }, 'json');
80 n.addClass('required');
81 } else if( isInMemberArray(r, g.rmembers, 1) ) {
82 $.post(pluginRoot, { action: 'removeMember', role: r.name, group: g.name });
83 $.post(pluginRoot, { action: 'addMember', role: r.name, group: g.name }, function(data) {
84 pp.attr('role', JSON.stringify(data));
85 }, 'json');
86 n.removeClass('required');
87 }
88 }
89 },
90 beforemove : function(node, ref_node, type, tree_obj, is_copy) {
91 var _ = dragObj(node, ref_node, type, tree_obj);
92 // --- check if the move is valid:
93 // don't move things around the same/root level
94 if (_.to == false && _.from == false) return false;
95 // no copy to the root folder
96 if (is_copy && _.to == false) return false;
97 // no rearrange withing the folder
98 if (_.to != false && _.from != false && _.to.name == _.from.name) return false;
99 // already contains such a member
100 if (_.to != false && isMember(_.node, _.to)) return false;
101
102 // do copy-move
103 // unassign from the old group, if it is move
104 if (!is_copy && _.from) $.post(pluginRoot, {'action': 'removeMember', 'role' : _.node.name, 'group' : _.from.name} , function(data) {}, 'json');
105 // assign to the new group
106 if (_.to) $.post(pluginRoot, {'action': 'addMember', 'role' : _.node.name, 'group' : _.to.name} , function(data) {}, 'json');
107
108 return true;
109 }
110 }
111}
112
113$(function() {
Valentin Valchev516c8e52014-11-18 08:37:37 +0000114 // read the available digest algorithms
115 $.ajax({
116 type : "POST",
117 url : pluginRoot,
118 async : false,
119 data : {'action': 'getDigestAlgorithms' },
120 dataType: 'json',
121 success : function(data) {
122 var _select = $('select.propertyType');
123 $.each(data, function(id, alg) {
124 _select.append('<option value="password-{0}">{1} {2}</option>'.msgFormat(alg, i18n.paswd, alg));
125 });
126 }
127 });
128
Valentin Valcheveddfbc42012-08-21 20:06:24 +0000129 userTree = $('#userTree');
130 roleDetails = $('#roleDetails');
131 roleDetailsTable = roleDetails.find('table');
132 roleDetailsHelp = roleDetails.find('#roleDetailsHelp');
133 roleDetailsBody = roleDetailsTable.find('tbody');
134 roleDetailsTemplateP = roleDetailsBody.find('tr:eq(0)');
135 roleDetailsTemplateC = roleDetailsBody.find('tr:eq(1)');
136 roleDetailsTemplate = roleDetailsBody.find('tr:eq(2)').clone();
137 roleDetailsBody.find('tr').not('.header').remove();
138
139 // add new property/credential code
140 $('tr.header span.ui-icon-plus').click(function() {
141 $(this).parent().parent().parent().parent().after(newProp());
142 });
143
144 // new role dialog
145 var _buttons = {};
146 _buttons[i18n.close] = function() {
147 $(this).dialog('close');
148 }
149 _buttons[i18n.add] = function() {
150 var _ = newDialogRole;
151 var n = _.find('input');
152 if (!n.val()) {
153 n.addClass('ui-state-error');
154 return false;
155 } else n.removeClass('ui-state-error');
156 var t = _.find('select').val();
157 $.post(pluginRoot, {'action': 'set', 'data' : JSON.stringify({'name': n.val(), 'type': new Number(t)})} , function(data) {
158 _.dialog('close');
159 $('#reload').click();
160 }, 'json');
161 }
162 newDialogRole = $("#newDialogRole").dialog({
163 autoOpen : false,
164 modal : true,
165 open : function() { $(this).find('input').val('').removeClass('ui-state-error') },
166 closeText: i18n.abort,
167 buttons : _buttons
168 });
169
170 // role info buttons
171 $('#delRole').click( function() {
172 if (selectedRole) $.post(pluginRoot, {'action': 'del', 'role' : selectedRole}, function() {
173 $('#reload').click();
174 });
175 });
176 $('#savRole').click( doSaveRole );
177
178 // top-frame buttons
179 $('#newRole').click( function() {
180 newDialogRole.dialog('open');
181 return false;
182 });
183 $('#reload').click( function() {
184 $.post(pluginRoot, {'action': 'list'} , function(data) {
185 roleDetailsHelp.removeClass('ui-helper-hidden');
186 roleDetailsTable.addClass('ui-helper-hidden');
187
188 var sortedGroups = sortGroups(data);
189 var treeRoot = buildTree(sortedGroups);
190
191 treeSettings.data.opts['static'] = treeRoot;
192 userTree.empty().tree(treeSettings);
193 }, 'json');
194 return false;
195 }).click();
196});
197
Valentin Valchev516c8e52014-11-18 08:37:37 +0000198function digest(val, alg) {
199 var _ret = false;
200 $.ajax({
201 type : "POST",
202 url : pluginRoot,
203 async : false,
204 data : {
205 'action': 'digest',
206 'data' : val,
207 'algorithm' : alg
208 },
209 dataType: 'json',
210 success : function(data) {
211 _ret = data['encoded'];
212 }
213 });
214 return _ret;
215}
Valentin Valcheveddfbc42012-08-21 20:06:24 +0000216function newProp() {
217 var tr = roleDetailsTemplate.clone()
218 .find('li').click( function() {
219 tr.remove();
220 }).end()
221 .find('select').change( function(evt) {
222 tr.find('.v').replaceWith('<input class="v" '+ ($(this).val().indexOf('password') == 0 ? 'type="password"' : '') + '/>');
223 initStaticWidgets(tr);
224 }).end()
225 initStaticWidgets(tr);
226 return tr;
227}
228function hashToArray(s) {
229 var r = [];
230 while(s.length > 0) {
231 r.push(parseInt(s.substring(0, 2), 16));
232 s = s.substring(2);
233 }
234 return r;
235}
236function strToArray(s) {
237 var r = [];
238 var el = s.split(',');
239 for(var i=0;i<el.length;i++) r.push( parseInt(el[i], 10) );
240 return r;
241}
242function doSaveRole() {
243 if (!selectedRole) return;
244 var doProps = true;
245 var data = {
246 name : selectedRole,
247 properties : {},
248 credentials : {}
249 };
250 roleDetailsBody.find('tr').each( function() {
251 var _ = $(this);
252 if (_.hasClass('header-props')) doProps = true;
253 else if (_.hasClass('header-cred')) doProps = false;
254 else {
255 var k = _.find('.k').val();
256 var v = _.find('.v').val();
257 var t = _.find('select').val();
258
259 if (t.indexOf('password-') == 0) {
Valentin Valchev516c8e52014-11-18 08:37:37 +0000260 var hash = digest(v, t.substring(9));
261 //CryptoJS[t.substring(9)](v).toString(CryptoJS.enc.Hex);
262 //v = hashToArray(hash);
263 v = hash;
Valentin Valcheveddfbc42012-08-21 20:06:24 +0000264 } else if (t == 'byte[]') {
265 v = strToArray(v);
266 }
267
268 if (doProps) data.properties[k] = v;
269 else data.credentials[k] = v;
270 }
271 });
272 $.post(pluginRoot, {'action': 'set', 'data' : JSON.stringify(data)});
273}
274
275function isInMemberArray(role, g) {
276 if(g) for(var i in g) if (g[i].name == role.name) return true;
277 return false;
278}
279
280function isMember(role, group) {
281 if (!role) return false;
282 if (!group) return false;
283 if (isInMemberArray(role, group.members)) return true;
284 if (isInMemberArray(role, group.rmembers)) return true;
285}
286
287function buildTree(sortedGroups) {
288 var treeRoot = {
289 data : i18n.root,
290 state: 'open',
291 attributes : { 'rel' : 'root' },
292 children: []
293 };
294 var treeNode = function(name, role, parent, req) {
295 if (!role) return;
296 if (!parent) parent = treeRoot.children;
297 var node = {
298 data : role.name,
299 attributes : {
300 'rel' : 't' + role.type,
301 'role' : JSON.stringify(role)
302 }
303 }
304 if (req) node.attributes['class'] = 'required';
305 parent.push(node);
306 if (role.type == 2) {
307 node['children'] = [];
308 node = node['children'];
309 if (role.members) $.each(role.members, function(idx, role) {
310 treeNode(role.name, role, node, 0);
311 });
312 if (role.rmembers) $.each(role.rmembers, function(idx, role) {
313 treeNode(role.name, role, node, 1);
314 });
315 }
316 }
317
318 $.each(sortedGroups, treeNode);
319 return treeRoot;
320}
321
322function sortGroups(data) {
323 var rootGroups = {}; // only root groups - without parents
324 var unassigned = {}; // non-groups, not assigned to any group
325 var processed = {}; // all processed entries
326 var u = 0;
327 var g = 0;
328 var r = 0;
329
330 var _st = function(map, n, role) {
331 if (typeof map[n] == 'undefined') { // not added - add
332 map[n] = role;
333 } else if (map[n] != false) { // already added
334 map[n] = false; // mark for removal
335 }
336 }
337
338 var groupF = function(i1, role) {
339 var n = role.name;
340 var t = role.type;
341
342 if (t == 2) { // group
343 // don't process twice
344 if (processed[n]) {
345 rootGroups[n] = false;
346 return true;
347 }
348 processed[n]=role;
349
350 _st(rootGroups, n, role);
351
352 if (role.members) $.each(role.members, groupF);
353 if (role.rmembers) $.each(role.rmembers, groupF);
354 g++;
355 } else { // role or user
356 if (t == 1) u++; else r++;
357 _st(unassigned, n, role);
358 }
359 }
360
361 $.each(data, groupF);
362 $('.statline').text( i18n.status.msgFormat(g,u,r) );
363
364 return $.extend(rootGroups, unassigned);
365}
366
367function onSelectNode(role) {
368 $.post(pluginRoot, {'action': 'get', 'role' : role} , function(data) {
369 selectedRole = role;
370 roleDetailsHelp.addClass('ui-helper-hidden');
371 roleDetailsTable.removeClass('ui-helper-hidden');
372 roleDetailsBody.find('tr').not('.header').remove();
373
374 var target = false;
375 var _append = function(k,v) {
376 var t = $.isArray(v) ? 'byte[]' : 'string';
377 target.after(newProp()
378 .data('k', k)
379 .find('input.k').val(k).end()
380 .find('input.v').val(v).end()
381 .find('select').val(t).end()
382 );
383 }
384 var x = data.properties;
385 if (x) {
386 target = roleDetailsTemplateP;
387 $.each(x, _append);
388 }
389 x = data.credentials;
390 if (x) {
391 target = roleDetailsTemplateC;
392 $.each(x, _append);
393 }
394 // show/user credentials view if user/or not (respectively)
395 x = roleDetailsBody.find('.header-cred');
396 if (data.type != 1) x.addClass('ui-helper-hidden');
397 else x.removeClass('ui-helper-hidden');
398 }, 'json')
399 return false;
400}
401
402function dragObj(node, ref_node, type, tree_obj) {
403 // determine the destination folder
404 var _role = false;
405 if ('inside' == type) {
406 _role = $(ref_node).attr('role');
407 } else {
408 _role = tree_obj.parent(ref_node)
409 _role = _role.attr ? _role.attr('role') : false;
410 }
411 var to = _role ? JSON.parse(_role) : false;
412 // determine object to move
413 _role = $(node).attr('role');
414 var source = JSON.parse(_role);
415 // determine the previous location (in case it is move, not copy)
416 _role = tree_obj.parent(node);
417 var from = _role.attr && _role.attr('role') ? JSON.parse(_role.attr('role')) : false;
418
419 return {
420 'to' : to,
421 'from' : from,
422 'node' : source
423 }
424}