Thomas Bruederli
2013-02-10 4279dd18eec644a3ee223c029d86692f2f2f3ce8
commit | author | age
48e9c1 1 /**
T 2  * ACL plugin script
3  *
4  * @version @package_version@
5  * @author Aleksander Machniak <alec@alec.pl>
6  */
7
8 if (window.rcmail) {
9     rcmail.addEventListener('init', function() {
10         if (rcmail.gui_objects.acltable) {
11             rcmail.acl_list_init();
12             // enable autocomplete on user input
13             if (rcmail.env.acl_users_source) {
14                 rcmail.init_address_input_events($('#acluser'), {action:'settings/plugin.acl-autocomplete'});
15                 // fix inserted value
16                 rcmail.addEventListener('autocomplete_insert', function(e) {
17                     if (e.field.id != 'acluser')
18                         return;
19
20                     var value = e.insert;
21                     // get UID from the entry value
22                     if (value.match(/\s*\(([^)]+)\)[, ]*$/))
23                         value = RegExp.$1;
24                     e.field.value = value;
25                 });
26             }
27         }
28
29         rcmail.enable_command('acl-create', 'acl-save', 'acl-cancel', 'acl-mode-switch', true);
30         rcmail.enable_command('acl-delete', 'acl-edit', false);
d90120 31
AM 32         if (rcmail.env.acl_advanced)
33             $('#acl-switch').addClass('selected');
48e9c1 34     });
T 35 }
36
37 // Display new-entry form
38 rcube_webmail.prototype.acl_create = function()
39 {
40     this.acl_init_form();
41 }
42
43 // Display ACL edit form
44 rcube_webmail.prototype.acl_edit = function()
45 {
46     // @TODO: multi-row edition
47     var id = this.acl_list.get_single_selection();
48     if (id)
49         this.acl_init_form(id);
50 }
51
52 // ACL entry delete
53 rcube_webmail.prototype.acl_delete = function()
54 {
55     var users = this.acl_get_usernames();
56
57     if (users && users.length && confirm(this.get_label('acl.deleteconfirm'))) {
58         this.http_request('settings/plugin.acl', '_act=delete&_user='+urlencode(users.join(','))
59             + '&_mbox='+urlencode(this.env.mailbox),
60             this.set_busy(true, 'acl.deleting'));
61     }
62 }
63
64 // Save ACL data
65 rcube_webmail.prototype.acl_save = function()
66 {
67     var user = $('#acluser').val(), rights = '', type;
68
69     $(':checkbox', this.env.acl_advanced ? $('#advancedrights') : sim_ul = $('#simplerights')).map(function() {
70         if (this.checked)
71             rights += this.value;
72     });
73
74     if (type = $('input:checked[name=usertype]').val()) {
75         if (type != 'user')
76             user = type;
77     }
78
79     if (!user) {
80         alert(this.get_label('acl.nouser'));
81         return;
82     }
83     if (!rights) {
84         alert(this.get_label('acl.norights'));
85         return;
86     }
87
88     this.http_request('settings/plugin.acl', '_act=save'
89         + '&_user='+urlencode(user)
90         + '&_acl=' +rights
91         + '&_mbox='+urlencode(this.env.mailbox)
92         + (this.acl_id ? '&_old='+this.acl_id : ''),
93         this.set_busy(true, 'acl.saving'));
94 }
95
96 // Cancel/Hide form
97 rcube_webmail.prototype.acl_cancel = function()
98 {
99     this.ksearch_blur();
100     this.acl_form.hide();
101 }
102
103 // Update data after save (and hide form)
104 rcube_webmail.prototype.acl_update = function(o)
105 {
106     // delete old row
107     if (o.old)
108         this.acl_remove_row(o.old);
109     // make sure the same ID doesn't exist
110     else if (this.env.acl[o.id])
111         this.acl_remove_row(o.id);
112
113     // add new row
114     this.acl_add_row(o, true);
115     // hide autocomplete popup
116     this.ksearch_blur();
117     // hide form
118     this.acl_form.hide();
119 }
120
121 // Switch table display mode
122 rcube_webmail.prototype.acl_mode_switch = function(elem)
123 {
124     this.env.acl_advanced = !this.env.acl_advanced;
125     this.enable_command('acl-delete', 'acl-edit', false);
126     this.http_request('settings/plugin.acl', '_act=list'
127         + '&_mode='+(this.env.acl_advanced ? 'advanced' : 'simple')
128         + '&_mbox='+urlencode(this.env.mailbox),
129         this.set_busy(true, 'loading'));
130 }
131
132 // ACL table initialization
133 rcube_webmail.prototype.acl_list_init = function()
134 {
d90120 135     $('#acl-switch')[this.env.acl_advanced ? 'addClass' : 'removeClass']('selected');
AM 136
48e9c1 137     this.acl_list = new rcube_list_widget(this.gui_objects.acltable,
T 138         {multiselect:true, draggable:false, keyboard:true, toggleselect:true});
139     this.acl_list.addEventListener('select', function(o) { rcmail.acl_list_select(o); });
140     this.acl_list.addEventListener('dblclick', function(o) { rcmail.acl_list_dblclick(o); });
141     this.acl_list.addEventListener('keypress', function(o) { rcmail.acl_list_keypress(o); });
142     this.acl_list.init();
143 }
144
145 // ACL table row selection handler
146 rcube_webmail.prototype.acl_list_select = function(list)
147 {
148     rcmail.enable_command('acl-delete', list.selection.length > 0);
149     rcmail.enable_command('acl-edit', list.selection.length == 1);
150     list.focus();
151 }
152
153 // ACL table double-click handler
154 rcube_webmail.prototype.acl_list_dblclick = function(list)
155 {
156     this.acl_edit();
157 }
158
159 // ACL table keypress handler
160 rcube_webmail.prototype.acl_list_keypress = function(list)
161 {
162     if (list.key_pressed == list.ENTER_KEY)
163         this.command('acl-edit');
164     else if (list.key_pressed == list.DELETE_KEY || list.key_pressed == list.BACKSPACE_KEY)
165         if (!this.acl_form || !this.acl_form.is(':visible'))
166             this.command('acl-delete');
167 }
168
169 // Reloads ACL table
170 rcube_webmail.prototype.acl_list_update = function(html)
171 {
172     $(this.gui_objects.acltable).html(html);
173     this.acl_list_init();
174 }
175
176 // Returns names of users in selected rows
177 rcube_webmail.prototype.acl_get_usernames = function()
178 {
179     var users = [], n, len, cell, row,
180         list = this.acl_list,
181         selection = list.get_selection();
182
183     for (n=0, len=selection.length; n<len; n++) {
184         if (this.env.acl_specials.length && $.inArray(selection[n], this.env.acl_specials) >= 0) {
185             users.push(selection[n]);
186         }
187         else if (row = list.rows[selection[n]]) {
188             cell = $('td.user', row.obj);
189             if (cell.length == 1)
190                 users.push(cell.text());
191         }
192     }
193
194     return users;
195 }
196
197 // Removes ACL table row
198 rcube_webmail.prototype.acl_remove_row = function(id)
199 {
200     var list = this.acl_list;
201
202     list.remove_row(id);
203     list.clear_selection();
204
205     // we don't need it anymore (remove id conflict)
206     $('#rcmrow'+id).remove();
207     this.env.acl[id] = null;
208
209     this.enable_command('acl-delete', list.selection.length > 0);
210     this.enable_command('acl-edit', list.selection.length == 1);
211 }
212
213 // Adds ACL table row
214 rcube_webmail.prototype.acl_add_row = function(o, sel)
215 {
216     var n, len, ids = [], spec = [], id = o.id, list = this.acl_list,
217         items = this.env.acl_advanced ? [] : this.env.acl_items,
218         table = this.gui_objects.acltable,
219         row = $('thead > tr', table).clone();
220
221     // Update new row
222     $('td', row).map(function() {
223         var r, cl = this.className.replace(/^acl/, '');
224
225         if (items && items[cl])
226             cl = items[cl];
227
228         if (cl == 'user')
229             $(this).text(o.username);
230         else
231             $(this).addClass(rcmail.acl_class(o.acl, cl)).text('');
232     });
233
234     row.attr('id', 'rcmrow'+id);
235     row = row.get(0);
236
237     this.env.acl[id] = o.acl;
238
239     // sorting... (create an array of user identifiers, then sort it)
240     for (n in this.env.acl) {
241         if (this.env.acl[n]) {
242             if (this.env.acl_specials.length && $.inArray(n, this.env.acl_specials) >= 0)
243                 spec.push(n);
244             else
245                 ids.push(n);
246         }
247     }
248     ids.sort();
249     // specials on the top
250     ids = spec.concat(ids);
251
252     // find current id
253     for (n=0, len=ids.length; n<len; n++)
254         if (ids[n] == id)
255             break;
256
257     // add row
258     if (n && n < len) {
259         $('#rcmrow'+ids[n-1]).after(row);
260         list.init_row(row);
261         list.rowcount++;
262     }
263     else
264         list.insert_row(row);
265
266     if (sel)
267         list.select_row(o.id);
268 }
269
270 // Initializes and shows ACL create/edit form
271 rcube_webmail.prototype.acl_init_form = function(id)
272 {
273     var ul, row, td, val = '', type = 'user', li_elements, body = $('body'),
274         adv_ul = $('#advancedrights'), sim_ul = $('#simplerights'),
275         name_input = $('#acluser');
276
277     if (!this.acl_form) {
278         var fn = function () { $('input[value=user]').prop('checked', true); };
279         name_input.click(fn).keypress(fn);
280     }
281
282     this.acl_form = $('#aclform');
283
284     // Hide unused items
285     if (this.env.acl_advanced) {
286         adv_ul.show();
287         sim_ul.hide();
288         ul = adv_ul;
289     }
290     else {
291         sim_ul.show();
292         adv_ul.hide();
293         ul = sim_ul;
294     }
295
296     // initialize form fields
297     li_elements = $(':checkbox', ul);
298     li_elements.attr('checked', false);
299
300     if (id && (row = this.acl_list.rows[id])) {
301         row = row.obj;
302         li_elements.map(function() {
303             val = this.value;
304             td = $('td.'+this.id, row);
305             if (td && td.hasClass('enabled'))
306                 this.checked = true;
307         });
308
309         if (!this.env.acl_specials.length || $.inArray(id, this.env.acl_specials) < 0)
310             val = $('td.user', row).text();
311         else
312             type = id;
313     }
314     // mark read (lrs) rights by default
315     else
316         li_elements.filter(function() { return this.id.match(/^acl([lrs]|read)$/); }).prop('checked', true);
317
318     name_input.val(val);
319     $('input[value='+type+']').prop('checked', true);
320
321     this.acl_id = id;
322
323     // position the form horizontally
324     var bw = body.width(), mw = this.acl_form.width();
325
326     if (bw >= mw)
327         this.acl_form.css({left: parseInt((bw - mw)/2)+'px'});
328
329     // display it
330     this.acl_form.show();
331     if (type == 'user')
332         name_input.focus();
333
334     // unfocus the list, make backspace key in name input field working
335     this.acl_list.blur();
336 }
337
338 // Returns class name according to ACL comparision result
339 rcube_webmail.prototype.acl_class = function(acl1, acl2)
340 {
341     var i, len, found = 0;
342
343     acl1 = String(acl1);
344     acl2 = String(acl2);
345
346     for (i=0, len=acl2.length; i<len; i++)
347         if (acl1.indexOf(acl2[i]) > -1)
348             found++;
349
350     if (found == len)
351         return 'enabled';
352     else if (found)
353         return 'partial';
354
355     return 'disabled';
356 }