blob: 517c3cf0cec68facb7c13e08d9bbdd848ec558e1 [file] [log] [blame]
Rushabh Mehtaaaf86ba2012-02-28 17:40:13 +05301// ERPNext - web based ERP (http://erpnext.com)
2// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17$.extend(wn.pages.users, {
18 onload: function(wrapper) {
19 wn.pages.users.profiles = {};
20 wn.pages.users.refresh();
21 wn.pages.users.setup();
22 wn.pages.users.role_editor = new erpnext.RoleEditor();
23 },
24 setup: function() {
25 // set roles
26 $('.users-area').on('click', '.btn.user-roles', function() {
27 var uid = $(this).parent().parent().attr('data-name');
28 wn.pages.users.role_editor.show(uid);
29 });
30
31 // settings
32 $('.users-area').on('click', '.btn.user-settings', function() {
33 var uid = $(this).parent().parent().attr('data-name');
34 wn.pages.users.show_settings(uid);
35 });
36
37 // delete
38 $('.users-area').on('click', 'a.close', function() {
39 $card = $(this).parent();
40 var uid = $card.attr('data-name');
41 $card.css('opacity', 0.6);
42 wn.call({
43 method: 'utilities.page.users.users.delete',
44 args: {'uid': uid},
45 callback: function(r,rt) {
46 if(!r.exc)
47 $card.fadeOut()
48 }
49 });
50 })
51
52 },
53 refresh: function() {
54 // make the list
55 wn.call({
56 method:'utilities.page.users.users.get',
57 callback: function(r, rt) {
58 $('.users-area').empty();
59 for(var i in r.message) {
60 var p = r.message[i];
61 wn.pages.users.profiles[p.name] = p;
62 wn.pages.users.render(p);
63 }
64 }
65 });
Anand Doshi1ed4ef12012-04-27 15:30:23 +053066 if(!$('.subscription-info').length && (wn.boot.max_users || wn.boot.expires_on)) {
Anand Doshi3f6eed22012-05-01 12:23:28 +053067 var $sub_info = $('<div class="subscription-info-box"><div>')
68 .insertAfter($(wn.pages.users).find('.help'));
Anand Doshi1ed4ef12012-04-27 15:30:23 +053069 if(wn.boot.max_users) {
70 $sub_info.append(repl('\
71 <span class="subscription-info"> \
72 Max Users: <b>%(max_users)s</b> \
73 </span>', { max_users: wn.boot.max_users }));
74 }
75 if(wn.boot.expires_on) {
76 $sub_info.append(repl('\
77 <span class="subscription-info"> \
78 Expires On: <b>%(expires_on)s</b> \
79 </span>', { expires_on: dateutil.str_to_user(wn.boot.expires_on) }));
80 }
81 }
Rushabh Mehtaaaf86ba2012-02-28 17:40:13 +053082 },
83 render: function(data) {
84 if(data.file_list) {
Rushabh Mehta1572adf2012-02-29 15:19:20 +053085 data.imgsrc = 'files/' + data.file_list.split('\n')[0].split(',')[1];
Rushabh Mehtaaaf86ba2012-02-28 17:40:13 +053086 } else {
Rushabh Mehtaa9209432012-05-07 18:00:57 +053087 data.imgsrc = 'images/lib/ui/no_img_' + (data.gender=='Female' ? 'f' : 'm') + '.gif';
Rushabh Mehtaaaf86ba2012-02-28 17:40:13 +053088 }
Rushabh Mehta204e77d2012-02-29 19:09:20 +053089 data.fullname = wn.user_info(data.name).fullname;
Rushabh Mehtaaaf86ba2012-02-28 17:40:13 +053090 data.delete_html = '';
91 if(!data.enabled)
92 data.delete_html = '<a class="close" title="delete">&times;</a>';
93
94 $('.users-area').append(repl('<div class="user-card" data-name="%(name)s">\
95 %(delete_html)s\
96 <img src="%(imgsrc)s">\
97 <div class="user-info">\
98 <b class="user-fullname">%(fullname)s</b><br>\
99 %(name)s<br>\
100 <button class="btn btn-small user-roles"><i class="icon-user"></i> Roles</button>\
101 <button class="btn btn-small user-settings"><i class="icon-cog"></i> Settings</button>\
102 </div>\
103 </div>', data));
104
105 if(!data.enabled) {
106 $('.users-area .user-card:last')
107 .addClass('disabled')
108 .find('.user-fullname').html('Disabled');
109 }
110 },
111 show_settings: function(uid) {
112 var me = wn.pages.users;
113 if(!me.settings_dialog)
114 me.make_settings_dialog();
115
116 var p = me.profiles[uid];
117 me.uid = uid;
118
119 me.settings_dialog.set_values({
120 restrict_ip: p.restrict_ip || '',
121 login_before: p.login_before || '',
122 login_after: p.login_after || '',
123 enabled: p.enabled || 0,
124 new_password: ''
125 });
126
127 me.settings_dialog.show();
128
129 },
130 make_settings_dialog: function() {
131 var me = wn.pages.users;
132 me.settings_dialog = new wn.widgets.Dialog({
133 title: 'Set User Security',
134 width: 500,
135 fields: [
136 {
137 label:'Enabled',
138 description: 'Uncheck to disable',
139 fieldtype: 'Check', fieldname: 'enabled'
140 },
141 {
142 label:'IP Address',
143 description: 'Restrict user login by IP address, partial ips (111.111.111), \
144 multiple addresses (separated by commas) allowed',
145 fieldname:'restrict_ip', fieldtype:'Data'
146 },
147 {
148 label:'Login After',
149 description: 'User can only login after this hour (0-24)',
150 fieldtype: 'Int', fieldname: 'login_after'
151 },
152 {
153 label:'Login Before',
154 description: 'User can only login before this hour (0-24)',
155 fieldtype: 'Int', fieldname: 'login_before'
156 },
157 {
158 label:'New Password',
159 description: 'Update the current user password',
160 fieldtype: 'Data', fieldname: 'new_password'
161 },
162 {
163 label:'Update', fieldtype:'Button', fieldname:'update'
164 }
165 ]
166 });
167
168 this.settings_dialog.fields_dict.update.input.onclick = function() {
169 var btn = this;
Rushabh Mehtaaaf86ba2012-02-28 17:40:13 +0530170 var args = me.settings_dialog.get_values();
171 args.user = me.uid;
172
173 if (args.new_password) {
174 me.get_password(btn, args);
175 } else {
Rushabh Mehtaffb25fc2012-03-01 11:29:22 +0530176 me.update_security(btn, args);
Rushabh Mehtaaaf86ba2012-02-28 17:40:13 +0530177 }
178 };
179
180 },
Rushabh Mehtaffb25fc2012-03-01 11:29:22 +0530181 update_security: function(btn, args) {
Rushabh Mehtaaaf86ba2012-02-28 17:40:13 +0530182 var me = wn.pages.users;
Rushabh Mehtaffb25fc2012-03-01 11:29:22 +0530183 $(btn).set_working();
Rushabh Mehtaaaf86ba2012-02-28 17:40:13 +0530184 $c_page('utilities', 'users', 'update_security', JSON.stringify(args), function(r,rt) {
Rushabh Mehtaffb25fc2012-03-01 11:29:22 +0530185 $(btn).done_working();
Rushabh Mehtaaaf86ba2012-02-28 17:40:13 +0530186 if(r.exc) {
187 msgprint(r.exc);
188 return;
189 }
190 me.settings_dialog.hide();
191 $.extend(me.profiles[me.uid], me.settings_dialog.get_values());
192 me.refresh();
193 });
194 },
195 get_password: function(btn, args) {
196 var me = wn.pages.users;
197 var pass_d = new wn.widgets.Dialog({
198 title: 'Your Password',
199 width: 300,
200 fields: [
201 {
202 label: 'Please Enter <b style="color: black">Your Password</b>',
203 description: "Your password is required to update the user's password",
204 fieldtype: 'Password', fieldname: 'sys_admin_pwd', reqd: 1
205 },
206 {
207 label: 'Continue', fieldtype: 'Button', fieldname: 'continue'
208 }
209 ]
210 });
211
212 pass_d.fields_dict.continue.input.onclick = function() {
213 btn.pwd_dialog.hide();
214 args.sys_admin_pwd = btn.pwd_dialog.get_values().sys_admin_pwd;
215 btn.set_working();
Anand Doshiecd8df82012-03-02 12:18:47 +0530216 me.update_security(btn, args);
Rushabh Mehtaaaf86ba2012-02-28 17:40:13 +0530217 btn.done_working();
218 }
219
220 pass_d.show();
221 btn.pwd_dialog = pass_d;
222 btn.done_working();
223 },
224 add_user: function() {
225 var me = wn.pages.users;
Anand Doshi1ed4ef12012-04-27 15:30:23 +0530226 var active_users = $('.user-card:not(.disabled)');
Anand Doshi5c2a7922012-04-30 20:03:23 +0530227 if(wn.boot.max_users && (active_users.length >= wn.boot.max_users)) {
Anand Doshi1ed4ef12012-04-27 15:30:23 +0530228 msgprint(repl("Alas! <br />\
229 You already have <b>%(active_users)s</b> active users, \
230 which is the maximum number that you are currently allowed to add. <br /><br /> \
231 So, to add more users, you can:<br /> \
232 1. <b>Upgrade to the unlimited users plan</b>, or<br /> \
233 2. <b>Disable one or more of your existing users and try again</b>",
234 {active_users: active_users.length}));
235 return;
236 }
Rushabh Mehtaaaf86ba2012-02-28 17:40:13 +0530237 var d = new wn.widgets.Dialog({
238 title: 'Add User',
239 width: 400,
240 fields: [{
241 fieldtype: 'Data', fieldname: 'user', reqd: 1,
242 label: 'Email Id of the user to add'
243 }, {
244 fieldtype: 'Data', fieldname: 'first_name', reqd: 1, label: 'First Name'
245 }, {
246 fieldtype: 'Data', fieldname: 'last_name', label: 'Last Name'
247 }, {
248 fieldtype: 'Data', fieldname: 'password', reqd: 1, label: 'Password'
249 }, {
250 fieldtype: 'Button', label: 'Add', fieldname: 'add'
251 }]
252 });
253
254 d.make();
255 d.fields_dict.add.input.onclick = function() {
256 v = d.get_values();
257 if(v) {
258 d.fields_dict.add.input.set_working();
259 $c_page('utilities', 'users', 'add_user', v, function(r,rt) {
260 if(r.exc) { msgprint(r.exc); return; }
261 else {
Anand Doshia6952c92012-03-07 19:37:23 +0530262 wn.boot.user_info[v.user] = {fullname:v.first_name + ' ' + (v.last_name || '')};
Rushabh Mehtaaaf86ba2012-02-28 17:40:13 +0530263 d.hide();
264 me.refresh();
265 }
266 })
267 }
268 }
269 d.show();
270 }
271});
272
273erpnext.RoleEditor = Class.extend({
274 init: function() {
275 this.dialog = new wn.widgets.Dialog({
276 title: 'Set Roles'
277 });
278 var me = this;
279 $(this.dialog.body).html('<div class="help">Loading...</div>')
280 wn.call({
281 method:'utilities.page.users.users.get_roles',
282 callback: function(r) {
283 me.roles = r.message;
284 me.show_roles();
285 }
286 });
287 },
288 show_roles: function() {
289 var me = this;
290 $(this.dialog.body).empty();
291 for(var i in this.roles) {
292 $(this.dialog.body).append(repl('<div class="user-role" \
293 data-user-role="%(role)s">\
294 <input type="checkbox"> \
295 <a href="#"><i class="icon-question-sign"></i></a> %(role)s\
296 </div>', {role: this.roles[i]}));
297 }
298 $(this.dialog.body).append('<div style="clear: both">\
Rushabh Mehtab9004bd2012-03-05 18:28:33 +0530299 <button class="btn btn-small btn-info">Save</button></div>');
300 $(this.dialog.body).find('button.btn-info').click(function() {
Rushabh Mehtaaaf86ba2012-02-28 17:40:13 +0530301 me.save();
302 });
303 $(this.dialog.body).find('.user-role a').click(function() {
304 me.show_permissions($(this).parent().attr('data-user-role'))
305 return false;
306 })
307 },
308 show: function(uid) {
309 var me = this;
310 this.uid = uid;
311 this.dialog.show();
312 // set user roles
313 wn.call({
314 method:'utilities.page.users.users.get_user_roles',
315 args: {uid:uid},
316 callback: function(r, rt) {
317 $(me.dialog.body).find('input[type="checkbox"]').attr('checked', false);
318 for(var i in r.message) {
319 $(me.dialog.body)
320 .find('[data-user-role="'+r.message[i]
321 +'"] input[type="checkbox"]').attr('checked',true);
322 }
323 }
324 })
325 },
326 save: function() {
327 var set_roles = [];
328 var unset_roles = [];
329 $(this.dialog.body).find('[data-user-role]').each(function() {
330 var $check = $(this).find('input[type="checkbox"]');
331 if($check.attr('checked')) {
332 set_roles.push($(this).attr('data-user-role'));
333 } else {
334 unset_roles.push($(this).attr('data-user-role'));
335 }
336 })
337 wn.call({
338 method:'utilities.page.users.users.update_roles',
339 args: {
340 set_roles: JSON.stringify(set_roles),
341 unset_roles: JSON.stringify(unset_roles),
342 uid: this.uid
343 },
Rushabh Mehtab9004bd2012-03-05 18:28:33 +0530344 btn: $(this.dialog.body).find('.btn-info').get(0),
Rushabh Mehtaaaf86ba2012-02-28 17:40:13 +0530345 callback: function() {
346
347 }
348 })
349 },
350 show_permissions: function(role) {
351 // show permissions for a role
352 var me = this;
353 if(!this.perm_dialog)
354 this.make_perm_dialog()
355 $(this.perm_dialog.body).empty();
356 wn.call({
357 method:'utilities.page.users.users.get_perm_info',
358 args: {role: role},
359 callback: function(r) {
360 var $body = $(me.perm_dialog.body);
361 $body.append('<table class="user-perm"><tbody><tr>\
362 <th style="text-align: left">Document Type</th>\
363 <th>Level</th>\
364 <th>Read</th>\
365 <th>Write</th>\
366 <th>Submit</th>\
367 <th>Cancel</th>\
368 <th>Amend</th></tr></tbody></table>');
369 for(var i in r.message) {
370 var perm = r.message[i];
371
372 // if permission -> icon
373 for(key in perm) {
374 if(key!='parent' && key!='permlevel') {
375 if(perm[key]) {
376 perm[key] = '<i class="icon-ok"></i>';
377 } else {
378 perm[key] = '';
379 }
380 }
381 }
382
383 $body.find('tbody').append(repl('<tr>\
384 <td style="text-align: left">%(parent)s</td>\
385 <td>%(permlevel)s</td>\
386 <td>%(read)s</td>\
387 <td>%(write)s</td>\
388 <td>%(submit)s</td>\
389 <td>%(cancel)s</td>\
390 <td>%(amend)s</td>\
391 </tr>', perm))
392 }
393
394 me.perm_dialog.show();
395 }
396 });
397
398 },
399 make_perm_dialog: function() {
400 this.perm_dialog = new wn.widgets.Dialog({
401 title:'Role Permissions',
402 width: 500
403 });
404 }
405})