From a9450498fd85f31362455c39bfa34eb949a2d01b Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 13 Jul 2012 14:55:01 +0530 Subject: [PATCH] profile cleanup start and new auth table for better security --- js/legacy/model/doclist.js | 4 +- js/legacy/widgets/form/fields.js | 10 +- js/legacy/widgets/form/form.js | 43 ++--- js/legacy/widgets/form/form_grid.js | 5 +- py/core/doctype/profile/profile.py | 146 ++++++++++++++-- py/core/doctype/profile/profile.txt | 242 +++++++++++--------------- py/core/doctype/userrole/userrole.txt | 9 +- py/webnotes/__init__.py | 10 +- py/webnotes/auth.py | 93 +++------- py/webnotes/install_lib/install.py | 14 +- 10 files changed, 305 insertions(+), 271 deletions(-) diff --git a/js/legacy/model/doclist.js b/js/legacy/model/doclist.js index e38d9b9b55..33638a4fbe 100644 --- a/js/legacy/model/doclist.js +++ b/js/legacy/model/doclist.js @@ -26,7 +26,9 @@ function compress_doclist(list) { var o = list[i]; var fl = []; if(!kl[o.doctype]) { // make key only once # doctype must be first - var tfl = ['doctype', 'name', 'docstatus', 'owner', 'parent', 'parentfield', 'parenttype', 'idx', 'creation', 'modified', 'modified_by', '__islocal', '__newname', '__modified', '_user_tags']; // for text + var tfl = ['doctype', 'name', 'docstatus', 'owner', 'parent', 'parentfield', 'parenttype', + 'idx', 'creation', 'modified', 'modified_by', '__islocal', '__newname', '__modified', + '_user_tags', '__temp']; var fl = [].concat(tfl); for(key in wn.meta.docfield_map[o.doctype]) { // all other values diff --git a/js/legacy/widgets/form/fields.js b/js/legacy/widgets/form/fields.js index 3a6db8586b..7c9c7928c7 100644 --- a/js/legacy/widgets/form/fields.js +++ b/js/legacy/widgets/form/fields.js @@ -298,9 +298,9 @@ Field.prototype.set = function(val) { this.docname = this.grid.add_newrow(); // new row } - var set_val = val; - if(this.validate)set_val = this.validate(val); - _f.set_value(this.doctype, this.docname, this.df.fieldname, set_val); + if(this.validate) + val = this.validate(val); + cur_frm.set_value_in_locals(this.doctype, this.docname, this.df.fieldname, val); this.value = val; // for return } @@ -513,9 +513,9 @@ ReadOnlyField.prototype = new Field(); function HTMLField() { } HTMLField.prototype = new Field(); HTMLField.prototype.with_label = 0; -HTMLField.prototype.set_disp = function(val) { this.disp_area.innerHTML = val; } +HTMLField.prototype.set_disp = function(val) { if(this.disp_area) this.disp_area.innerHTML = val; } HTMLField.prototype.set_input = function(val) { if(val) this.set_disp(val); } -HTMLField.prototype.onrefresh = function() { this.set_disp(this.df.options?this.df.options:''); } +HTMLField.prototype.onrefresh = function() { if(this.df.options) this.set_disp(this.df.options); } // ====================================================================================== diff --git a/js/legacy/widgets/form/form.js b/js/legacy/widgets/form/form.js index b0ca86b7f1..efb436e1a7 100644 --- a/js/legacy/widgets/form/form.js +++ b/js/legacy/widgets/form/form.js @@ -838,7 +838,7 @@ _f.Frm.prototype.save = function(save_action, call_back) { } else { // no validation for cancellation validated = true; if(this.cscript.validate) - this.runclientscript('validate', this.doctype, this.docname); + this.runclientscript('validate'); if(!validated) { this.savingflag = false; @@ -1090,43 +1090,26 @@ _f.get_value = function(dt, dn, fn) { return locals[dt][dn][fn]; } -_f.set_value = function(dt, dn, fn, v) { +_f.Frm.prototype.set_value_in_locals = function(dt, dn, fn, v) { var d = locals[dt][dn]; - - if(!d) { - console.log('_f.set_value - '+ fn+': "'+dt+','+dn+'" not found'); - return; - } - var changed = d[fn] != v; - if(changed && (d[fn]==null || v==null) && (cstr(d[fn])==cstr(v))) changed = 0; + if(changed && (d[fn]==null || v==null) && (cstr(d[fn])==cstr(v))) + changed = false; if(changed) { - //console.log('value changed for ' + dt + ', ' + dn + ', ' + fn) - - var prev_unsaved = d.__unsaved d[fn] = v; - d.__unsaved = 1; - - if(d.parent && d.parenttype) { - var doc = locals[d.parenttype][d.parent]; - doc.__unsaved = 1; - var frm = wn.views.formview[d.parenttype].frm; - } else { - var doc = locals[d.doctype][d.name] - doc.__unsaved = 1; - var frm = wn.views.formview[d.doctype] && wn.views.formview[d.doctype].frm; - } - - // No need to refresh labels and toolbar again and again. - // Just check if __unsaved was not set previously - if(frm && frm==cur_frm && frm.frm_head && !prev_unsaved) { - frm.frm_head.refresh_labels(); - //frm.frm_head.refresh_toolbar(); - } + if(d.parenttype) + d.__unsaved = 1; + this.set_unsaved(); } } +_f.Frm.prototype.set_unsaved = function() { + if(cur_frm.doc.__unsaved) return; + cur_frm.doc.__unsaved = 1; + cur_frm.frm_head.refresh_labels() +} + _f.Frm.prototype.show_comments = function() { if(!cur_frm.comments) { cur_frm.comments = new Dialog(540, 400, 'Comments'); diff --git a/js/legacy/widgets/form/form_grid.js b/js/legacy/widgets/form/form_grid.js index bac0439fca..148da1d46b 100644 --- a/js/legacy/widgets/form/form_grid.js +++ b/js/legacy/widgets/form/form_grid.js @@ -138,8 +138,7 @@ _f.FormGrid.prototype.refresh = function() { _f.FormGrid.prototype.set_unsaved = function() { // set unsaved - locals[cur_frm.doctype][cur_frm.docname].__unsaved=1; - cur_frm.frm_head && cur_frm.frm_head.refresh_labels(); + cur_frm.set_unsaved(); } _f.FormGrid.prototype.insert_row = function() { @@ -155,7 +154,6 @@ _f.FormGrid.prototype.insert_row = function() { // refresh this.refresh(); this.cell_select('', row_idx, ci); - this.set_unsaved(); } _f.FormGrid.prototype.new_row_doc = function() { @@ -165,6 +163,7 @@ _f.FormGrid.prototype.new_row_doc = function() { d.parent = this.field.frm.docname; d.parentfield = this.field.df.fieldname; d.parenttype = this.field.frm.doctype; + this.set_unsaved(); return d; } _f.FormGrid.prototype.add_newrow = function() { diff --git a/py/core/doctype/profile/profile.py b/py/core/doctype/profile/profile.py index 123027fa8a..22ab5adc02 100644 --- a/py/core/doctype/profile/profile.py +++ b/py/core/doctype/profile/profile.py @@ -20,25 +20,16 @@ # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -# Please edit this list and import only required elements -import webnotes +import webnotes, json +from webnotes.utils import cint -from webnotes import msgprint - -sql = webnotes.conn.sql - -# ----------------------------------------------------------------------------------------- - - class DocType: def __init__(self, doc, doclist): self.doc = doc self.doclist = doclist - - # Autoname is Email id - # -------------------- def autoname(self): + """set name as email id""" import re from webnotes.utils import validate_email_add @@ -49,12 +40,81 @@ class DocType: raise Exception self.doc.name = self.doc.email + + def validate(self): + self.validate_max_users() + self.update_roles() + self.logout_if_disabled() + + def logout_if_disabled(self): + """logout if disabled""" + if cint(self.doc.disabled): + import webnotes.login_manager + webnotes.login_manager.logout(self.doc.name) + def validate_max_users(self): + """don't allow more than max users if set in conf""" + import conf + if hasattr(conf, 'max_users'): + active_users = webnotes.conn.sql("""select count(*) from tabProfile + where ifnull(enabled, 0)=1 and docstatus<2 + and name not in ('Administrator', 'Guest')""")[0][0] + if active_users >= conf.max_users and conf.max_users: + webnotes.msgprint(""" + You already have %(active_users)s active users, \ + which is the maximum number that you are currently allowed to add.

\ + So, to add more users, you can:
\ + 1. Upgrade to the unlimited users plan, or
\ + 2. Disable one or more of your existing users and try again""" \ + % {'active_users': active_users}, raise_exception=1) + + def update_roles(self): + """update roles if set""" + if self.doc.fields.get('__temp'): + roles = json.loads(self.doc.fields['__temp']) + del self.doc.fields['__temp'] + + # remove roles + webnotes.conn.sql("""delete from tabUserRole where parent='%s' + and role in ('%s')""" % (self.doc.name, "','".join(roles['unset_roles']))) + + self.check_one_system_manager() + + # add roles + user_roles = webnotes.get_roles(self.doc.name) + for role in roles['set_roles']: + if not role in user_roles: + self.add_role(role) + + def add_role(self, role): + """add role to Profile""" + from webnotes.model.doc import Document + d = Document('UserRole') + d.role = role + d.parenttype = 'Profile' + d.parentfield = 'user_roles' + d.parent = self.doc.name + d.save() + + def check_one_system_manager(self): + if not webnotes.conn.sql("""select parent from tabUserRole where role='System Manager' + and docstatus<2"""): + webnotes.msgprint("""Cannot un-select as System Manager as there must + be atleast one 'System Manager'""", raise_exception=1) + def on_update(self): # owner is always name - if not self.doc.password: - webnotes.conn.set(self.doc, 'password' ,'password') webnotes.conn.set(self.doc, 'owner' ,self.doc.name) + self.update_new_password() + + def update_new_password(self): + """update new password if set""" + if self.doc.new_password: + webnotes.conn.sql("""insert into __Auth (user, `password`) values (%s, password(%s)) + on duplicate key update `password`=password(%s)""", (self.doc.name, + self.doc.new_password, self.doc.new_password)) + webnotes.conn.set(self.doc, 'new_password', '') + webnotes.msgprint("Password updated.") def get_fullname(self): return (self.doc.first_name or '') + \ @@ -75,4 +135,60 @@ class DocType: (tab[0], field, '%s', field, '%s'), (newdn, olddn)) webnotes.conn.sql("""\ update `tabProfile` set email=%s - where name=%s""", (newdn, newdn)) \ No newline at end of file + where name=%s""", (newdn, newdn)) + +@webnotes.whitelist() +def get_all_roles(arg=None): + """return all roles""" + return [r[0] for r in webnotes.conn.sql("""select name from tabRole + where name not in ('Administrator', 'Guest', 'All') order by name""")] + +@webnotes.whitelist() +def get_user_roles(arg=None): + """get roles for a user""" + return webnotes.get_roles(webnotes.form_dict['uid']) + +@webnotes.whitelist() +def get_perm_info(arg=None): + """get permission info""" + return webnotes.conn.sql("""select parent, permlevel, `read`, `write`, submit, + cancel, amend from tabDocPerm where role=%s + and docstatus<2 order by parent, permlevel""", + webnotes.form_dict['role'], as_dict=1) + +def send_welcome_mail(email, args): + """send welcome mail to user with password and login url""" + pr = Document('Profile', email) + from webnotes.utils.email_lib import sendmail_md + args.update({ + 'company': webnotes.conn.get_default('company'), + 'password': args.get('password'), + 'account_url': webnotes.conn.get_value('Website Settings', + 'Website Settings', 'subdomain') or "" + }) + if not args.get('last_name'): args['last_name'] = '' + sendmail_md(pr.email, subject="Welcome to ERPNext", msg=welcome_txt % args) + +@webnotes.whitelist() +def delete(arg=None): + """delete user""" + webnotes.conn.sql("update tabProfile set enabled=0, docstatus=2 where name=%s", + webnotes.form_dict['uid']) + webnotes.login_manager.logout(user=webnotes.form_dict['uid']) + +welcome_txt = """ +## %(company)s + +Dear %(first_name)s %(last_name)s + +Welcome! + +A new account has been created for you, here are your details: + +login-id: %(user)s +password: %(password)s + +To login to your new ERPNext account, please go to: + +%(account_url)s +""" \ No newline at end of file diff --git a/py/core/doctype/profile/profile.txt b/py/core/doctype/profile/profile.txt index 35d8e8338b..5af90dbfbb 100644 --- a/py/core/doctype/profile/profile.txt +++ b/py/core/doctype/profile/profile.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-05-03 18:43:24', + 'creation': '2012-07-03 13:30:35', 'docstatus': 0, - 'modified': '2012-05-24 12:30:06', + 'modified': '2012-07-13 14:20:39', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -19,12 +19,14 @@ 'allow_print': 0, 'colour': u'White:FFF', 'default_print_format': u'Standard', + 'description': u'Profile Represents a User in the system.', 'doctype': 'DocType', + 'document_type': u'System', 'hide_heading': 0, 'hide_toolbar': 0, 'issingle': 0, 'istable': 0, - 'max_attachments': 1, + 'max_attachments': 5, 'module': u'Core', 'name': '__common__', 'print_outline': u'Yes', @@ -62,7 +64,7 @@ # DocPerm { - 'cancel': 0, + 'cancel': 1, 'create': 1, 'doctype': u'DocPerm', 'execute': 0, @@ -74,6 +76,7 @@ # DocPerm { + 'cancel': 1, 'create': 1, 'doctype': u'DocPerm', 'permlevel': 0, @@ -83,6 +86,7 @@ # DocPerm { + 'cancel': 0, 'doctype': u'DocPerm', 'permlevel': 1, 'role': u'Administrator', @@ -91,10 +95,20 @@ # DocPerm { + 'cancel': 0, 'doctype': u'DocPerm', + 'match': u'owner', 'permlevel': 0, - 'role': u'All', - 'write': 0 + 'role': u'All' + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'sb0', + 'fieldtype': u'Section Break', + 'label': u'Profile Details', + 'permlevel': 0 }, # DocField @@ -112,20 +126,8 @@ # DocField { 'doctype': u'DocField', - 'fieldname': u'password', - 'fieldtype': u'Password', - 'hidden': 1, - 'label': u'Password', - 'permlevel': 1 - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'registered', - 'fieldtype': u'Check', - 'hidden': 1, - 'label': u'Registered', + 'fieldname': u'sb0_5', + 'fieldtype': u'Section Break', 'permlevel': 0 }, @@ -153,6 +155,22 @@ 'search_index': 0 }, + # DocField + { + 'colour': u'White:FFF', + 'description': u'Id of the profile will be the email.', + 'doctype': u'DocField', + 'fieldname': u'email', + 'fieldtype': u'Data', + 'hidden': 0, + 'label': u'Email', + 'oldfieldname': u'email', + 'oldfieldtype': u'Data', + 'permlevel': 0, + 'reqd': 1, + 'search_index': 0 + }, + # DocField { 'doctype': u'DocField', @@ -187,19 +205,6 @@ 'permlevel': 0 }, - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'gender', - 'fieldtype': u'Select', - 'label': u'Gender', - 'oldfieldname': u'gender', - 'oldfieldtype': u'Select', - 'options': u'\nMale\nFemale', - 'permlevel': 0, - 'search_index': 0 - }, - # DocField { 'doctype': u'DocField', @@ -212,41 +217,26 @@ # DocField { + 'colour': u'White:FFF', + 'description': u'Set a new password.', 'doctype': u'DocField', - 'fieldname': u'email', - 'fieldtype': u'Data', + 'fieldname': u'new_password', + 'fieldtype': u'Password', 'hidden': 0, - 'label': u'Email', - 'oldfieldname': u'email', - 'oldfieldtype': u'Data', + 'label': u'New Password', 'permlevel': 0, - 'reqd': 1, - 'search_index': 0 + 'print_hide': 1 }, # DocField { 'doctype': u'DocField', - 'fieldname': u'bio', - 'fieldtype': u'Text', + 'fieldname': u'password', + 'fieldtype': u'Password', 'hidden': 1, - 'label': u'Bio', - 'oldfieldname': u'bio', - 'oldfieldtype': u'Text', - 'permlevel': 0, - 'search_index': 0 - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'interests', - 'fieldtype': u'Text', - 'hidden': 1, - 'label': u'Interests', - 'oldfieldname': u'interests', - 'oldfieldtype': u'Text', - 'permlevel': 0 + 'label': u'Password', + 'permlevel': 1, + 'print_hide': 1 }, # DocField @@ -260,30 +250,6 @@ 'permlevel': 0 }, - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'activities', - 'fieldtype': u'Text', - 'hidden': 1, - 'label': u'Activities', - 'oldfieldname': u'activities', - 'oldfieldtype': u'Text', - 'permlevel': 0 - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'messanger_status', - 'fieldtype': u'Data', - 'label': u'Messanger Status', - 'oldfieldname': u'messanger_status', - 'oldfieldtype': u'Data', - 'permlevel': 0, - 'search_index': 0 - }, - # DocField { 'doctype': u'DocField', @@ -299,21 +265,42 @@ # DocField { 'doctype': u'DocField', - 'fieldname': u'section_break0', + 'fieldname': u'gender', + 'fieldtype': u'Select', + 'label': u'Gender', + 'oldfieldname': u'gender', + 'oldfieldtype': u'Select', + 'options': u'\nMale\nFemale\nOther', + 'permlevel': 0, + 'search_index': 0 + }, + + # DocField + { + 'colour': u'White:FFF', + 'description': u'Check / Uncheck roles assigned to the Profile. To find out what permissions the Role has, click on the "?" icon.', + 'doctype': u'DocField', + 'fieldname': u'sb1', 'fieldtype': u'Section Break', - 'hidden': 0, - 'oldfieldtype': u'Section Break', - 'permlevel': 1, - 'reqd': 0, - 'search_index': 0 - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'roles', - 'fieldtype': u'Column Break', 'label': u'Roles', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'roles_html', + 'fieldtype': u'HTML', + 'label': u'Roles HTML', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'sb2', + 'fieldtype': u'Section Break', + 'label': u'User Defaults', 'oldfieldtype': u'Column Break', 'permlevel': 1, 'width': u'50%' @@ -324,41 +311,12 @@ 'colour': u'White:FFF', 'default': u'Simple', 'doctype': u'DocField', - 'fieldname': u'userroles', - 'fieldtype': u'Table', + 'fieldname': u'defaults_html', + 'fieldtype': u'HTML', 'hidden': 0, - 'label': u'User Roles', - 'oldfieldname': u'userroles', - 'oldfieldtype': u'Table', - 'options': u'UserRole', - 'permlevel': 1, - 'reqd': 0, - 'search_index': 0 - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'system_defaults', - 'fieldtype': u'Column Break', - 'label': u'System Defaults', - 'oldfieldtype': u'Column Break', - 'permlevel': 1, - 'width': u'50%' - }, - - # DocField - { - 'colour': u'White:FFF', - 'default': u'Simple', - 'doctype': u'DocField', - 'fieldname': u'defaults', - 'fieldtype': u'Table', - 'hidden': 0, - 'label': u'Defaults', + 'label': u'Defaults HTML', 'oldfieldname': u'defaults', 'oldfieldtype': u'Table', - 'options': u'DefaultValue', 'permlevel': 1, 'reqd': 0, 'search_index': 0 @@ -367,24 +325,17 @@ # DocField { 'doctype': u'DocField', - 'fieldname': u'login_details', + 'fieldname': u'sb3', 'fieldtype': u'Section Break', - 'label': u'Login Details', + 'label': u'Security Settings', 'oldfieldtype': u'Section Break', 'permlevel': 1 }, # DocField { - 'doctype': u'DocField', - 'fieldname': u'login_before', - 'fieldtype': u'Int', - 'label': u'Login Before', - 'permlevel': 1 - }, - - # DocField - { + 'colour': u'White:FFF', + 'description': u'Allow user to login only after this hour (0-24)', 'doctype': u'DocField', 'fieldname': u'login_after', 'fieldtype': u'Int', @@ -394,6 +345,19 @@ # DocField { + 'colour': u'White:FFF', + 'description': u'Allow user to login only before this hour (0-24)', + 'doctype': u'DocField', + 'fieldname': u'login_before', + 'fieldtype': u'Int', + 'label': u'Login Before', + 'permlevel': 1 + }, + + # DocField + { + 'colour': u'White:FFF', + 'description': u'Restrict user from this IP address only. Multiple IP addresses can be added by separating with commas. Also accepts partial IP addresses like (111.111.111)', 'doctype': u'DocField', 'fieldname': u'restrict_ip', 'fieldtype': u'Data', diff --git a/py/core/doctype/userrole/userrole.txt b/py/core/doctype/userrole/userrole.txt index 31d8c96f68..f8dc30b261 100644 --- a/py/core/doctype/userrole/userrole.txt +++ b/py/core/doctype/userrole/userrole.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-03-27 14:35:39', + 'creation': '2012-07-03 13:30:34', 'docstatus': 0, - 'modified': '2012-03-27 14:35:39', + 'modified': '2012-07-13 12:25:07', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -21,13 +21,14 @@ 'hide_heading': 0, 'hide_toolbar': 0, 'issingle': 0, - 'istable': 1, + 'istable': 0, 'module': u'Core', 'name': '__common__', 'read_only': 0, 'section_style': u'Simple', 'server_code_error': u' ', - 'show_in_menu': 0 + 'show_in_menu': 0, + 'version': 1 }, # These values are common for all DocField diff --git a/py/webnotes/__init__.py b/py/webnotes/__init__.py index 1ae6d36956..acfbd4f0d2 100644 --- a/py/webnotes/__init__.py +++ b/py/webnotes/__init__.py @@ -218,7 +218,7 @@ def clear_cache(user=None): from webnotes.session_cache import clear clear(user) -def get_roles(user=None): +def get_roles(user=None, with_standard=True): """get roles of current user""" if not user: user = session['user'] @@ -226,5 +226,11 @@ def get_roles(user=None): if user=='Guest': return ['Guest'] - return [r[0] for r in conn.sql("""select distinct role from tabUserRole + roles = [r[0] for r in conn.sql("""select role from tabUserRole where parent=%s and role!='All'""", user)] + ['All'] + + # filter standard if required + if not with_standard: + roles = filter(lambda x: x not in ['All', 'Guest', 'Administrator'], roles) + + return roles diff --git a/py/webnotes/auth.py b/py/webnotes/auth.py index d37cba3f60..3d871c1dcd 100644 --- a/py/webnotes/auth.py +++ b/py/webnotes/auth.py @@ -107,7 +107,6 @@ class HTTPRequest: class LoginManager: def __init__(self): - self.cp = None if webnotes.form_dict.get('cmd')=='login': # clear cache from webnotes.session_cache import clear_cache @@ -132,45 +131,31 @@ class LoginManager: if not (user and pwd): user, pwd = webnotes.form_dict.get('usr'), webnotes.form_dict.get('pwd') if not (user and pwd): - webnotes.response['message'] = 'Incomplete Login Details' - raise webnotes.AuthenticationError - # custom authentication (for single-sign on) - self.load_control_panel() - if hasattr(self.cp, 'authenticate'): - self.user = self.cp.authenticate() + self.fail('Incomplete login details') - # check the password - if user=='Administrator': - p = webnotes.conn.sql("""select name, first_name, last_name - from tabProfile where name=%s - and (`password`=%s OR `password`=PASSWORD(%s))""", (user, pwd, pwd), as_dict=1) + self.check_if_enabled(user) + self.user = self.check_password(user, pwd) + + def check_if_enabled(self, user): + """raise exception if user not enabled""" + if user=='Administrator': return + if not int(webnotes.conn.get_value('Profile', user, 'enabled')): + self.fail('User disabled or missing') + + def check_password(self, user, pwd): + """check password""" + user = webnotes.conn.sql("""select `user` from __Auth where `user`=%s + and `password`=password(%s)""", (user, pwd)) + if not user: + self.fail('Incorrect password') else: - p = webnotes.conn.sql("""select name, first_name, last_name - from tabProfile where name=%s - and (`password`=%s OR `password`=PASSWORD(%s)) - and IFNULL(enabled,0)=1""", (user, pwd, pwd), as_dict=1) - if not p: - webnotes.response['message'] = 'Authentication Failed' - raise webnotes.AuthenticationError - #webnotes.msgprint('Authentication Failed',raise_exception=1) - - p = p[0] - self.user = p['name'] - self.user_fullname = (p.get('first_name') and (p.get('first_name') + ' ') or '') \ - + (p.get('last_name') or '') + return user[0][0] # in correct case - # triggers - # -------- + def fail(self, message): + webnotes.response['message'] = message + raise webnotes.AuthenticationError + - def load_control_panel(self): - import webnotes.model.code - try: - if not self.cp: - self.cp = webnotes.model.code.get_obj('Control Panel') - except Exception, e: - webnotes.response['Control Panel Exception'] = webnotes.utils.getTraceback() - - # -------- def run_trigger(self, method='on_login'): try: from startup import event_handlers @@ -180,15 +165,8 @@ class LoginManager: except ImportError, e: pass - # deprecated - self.load_control_panel() - if self.cp and hasattr(self.cp, method): - getattr(self.cp, method)(self) - - # ip validation - # ------------- - def validate_ip_address(self): + """check if IP Address is valid""" ip_list = webnotes.conn.get_value('Profile', self.user, 'restrict_ip', ignore=True) if not ip_list: @@ -205,9 +183,7 @@ class LoginManager: raise webnotes.AuthenticationError def validate_hour(self): - """ - check if user is logging in during restricted hours - """ + """check if user is logging in during restricted hours""" login_before = int(webnotes.conn.get_value('Profile', self.user, 'login_before', ignore=True) or 0) login_after = int(webnotes.conn.get_value('Profile', self.user, 'login_after', ignore=True) or 0) @@ -222,28 +198,17 @@ class LoginManager: if login_after and current_hour < login_after: webnotes.msgprint('Not allowed to login before restricted hour', raise_exception=1) - - # login as guest - # -------------- def login_as_guest(self): + """login as guest""" self.user = 'Guest' self.post_login() - # Logout - # ------ - - def call_on_logout_event(self): - import webnotes.model.code - cp = webnotes.model.code.get_obj('Control Panel', 'Control Panel') - if hasattr(cp, 'on_logout'): - cp.on_logout(self) - def logout(self, arg='', user=None): if not user: user = webnotes.session.get('user') self.user = user self.run_trigger('on_logout') - if user=='demo@webnotestech.com': + if user in ['demo@erpnext.com', 'Administrator']: webnotes.conn.sql('delete from tabSessions where sid=%s', webnotes.session.get('sid')) else: webnotes.conn.sql('delete from tabSessions where user=%s', user) @@ -258,8 +223,6 @@ class CookieManager: webnotes.cookies = Cookie.SimpleCookie() self.get_incoming_cookies() - # get incoming cookies - # -------------------- def get_incoming_cookies(self): import os cookies = {} @@ -271,9 +234,6 @@ class CookieManager: webnotes.incoming_cookies = cookies - # Set cookies - # ----------- - def set_cookies(self): if webnotes.session.get('sid'): webnotes.cookies['sid'] = webnotes.session['sid'] @@ -284,9 +244,6 @@ class CookieManager: webnotes.cookies['sid']['expires'] = expires.strftime('%a, %d %b %Y %H:%M:%S') webnotes.cookies['sid']['path'] = '/' - # Set Remember Me - # --------------- - def set_remember_me(self): if webnotes.utils.cint(webnotes.form_dict.get('remember_me')): remember_days = webnotes.conn.get_value('Control Panel',None,'remember_for_days') or 7 diff --git a/py/webnotes/install_lib/install.py b/py/webnotes/install_lib/install.py index fa513958f8..f6adadfb15 100755 --- a/py/webnotes/install_lib/install.py +++ b/py/webnotes/install_lib/install.py @@ -98,6 +98,7 @@ class Installer: self.create_scheduler_log() self.create_session_cache() self.create_cache_item() + self.create_auth_table() # set the basic passwords webnotes.conn.begin() @@ -134,7 +135,7 @@ class Installer: webnotes.conn.sql("""create table `__SessionCache` ( user VARCHAR(120), country VARCHAR(120), - cache LONGTEXT)""") + cache LONGTEXT) ENGINE=InnoDB""") def create_cache_item(self): import webnotes @@ -143,7 +144,12 @@ class Installer: `key` VARCHAR(180) NOT NULL PRIMARY KEY, `value` LONGTEXT, `expires_on` DATETIME - ) ENGINE=MyISAM DEFAULT CHARSET=utf8""") + ) ENGINE=InnoDB DEFAULT CHARSET=utf8""") - - + def create_auth_table(self): + import webnotes + self.dbman.drop_table('__Auth') + webnotes.conn.sql("""create table __Auth( + `user` VARCHAR(180) NOT NULL PRIMARY KEY, + `password` VARCHAR(180) NOT NULL + ) ENGINE=InnoDB DEFAULT CHARSET=utf8""")