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