[IMP] base_crypt: uses the existing password column (making it a stored function field).

bzr revid: vmt@openerp.com-20101223155013-20wd0vxgug1we02b
This commit is contained in:
Vo Minh Thu
2010-12-23 16:50:13 +01:00
parent 0594c0c96f
commit a0640060f5
3 changed files with 88 additions and 55 deletions
@@ -26,11 +26,7 @@
"category" : "Generic Modules/Base",
"description": "Module for password encryption.",
"depends" : ["base"],
"init_xml" : [],
"demo_xml" : [],
"update_xml" : [
"base_update.xml",
],
"data" : [],
"active": False,
"installable": True,
}
+4 -2
View File
@@ -2,6 +2,8 @@
<openerp>
<data>
<!-- TODO not needed anymore, delete this file -->
<record model="ir.ui.view" id="view_users_form_simple_modif_inherit">
<field name="name">res.users.form.modif.inherit</field>
<field name="model">res.users</field>
@@ -10,7 +12,7 @@
<field name="priority" eval="10"/>
<field name="arch" type="xml">
<field name="password" position="replace">
<field name="input_pw" password="True"/>
<field name="password" password="True"/>
</field>
</field>
</record>
@@ -21,7 +23,7 @@
<field name="inherit_id" ref="base.view_users_form"/>
<field name="arch" type="xml">
<field name="password" position="replace">
<field name="input_pw" password="True"/>
<field name="password" password="True"/>
</field>
</field>
</record>
+83 -48
View File
@@ -123,43 +123,65 @@ def encrypt_md5( raw_pw, salt, magic=magic_md5 ):
return magic + salt + '$' + rearranged
#def check_super(passwd):
# salt = _salt_cache[passwd]
# if encrypt_md5( passwd, salt ) == tools.config['admin_passwd']:
# return True
# else:
# raise Exception('AccessDenied')
class users(osv.osv):
_name="res.users"
_inherit="res.users"
# agi - 022108
# Add handlers for 'input_pw' field.
# Maps a res_users id to the salt used to encrypt its associated password.
_salt_cache = {}
def set_pw( self, cr, uid, id, name, value, args, context ):
def set_pw(self, cr, uid, id, name, value, args, context):
print ">>>>>> set_pw %s" % str((self, cr, uid, id, name, value, args, context))
if not value:
raise osv.except_osv(_('Error'), _("Please specify the password !"))
self.write( cr, uid, id, { 'password' : encrypt_md5( value, gen_salt() ) } )
salt = self._salt_cache[id] = gen_salt()
encrypted = encrypt_md5(value, salt)
cr.execute('update res_users set password=%s where id=%s',
(encrypted.encode('utf-8'), id))
cr.commit()
del value
def get_pw( self, cr, uid, ids, name, args, context ):
print ">>>>>> get_pw"
if len(ids) != 1:
# TODO multiple ids (and no id)
return {}
id = ids[0]
cr.execute('select password from res_users where id=%s', (id,))
stored_pw = cr.fetchone()
if stored_pw:
stored_pw = stored_pw[0]
else:
# Return early if no such id.
return False
stored_pw = self.maybe_encrypt_and_store(cr, stored_pw, id)
res = {}
for id in ids:
res[id] = ''
res[id] = stored_pw
return res
# Continuing to original code.
_columns = {
'input_pw': fields.function( get_pw, fnct_inv=set_pw, type='char', method=True, size=20, string='Password', invisible=True),
}
# The column size could be smaller as it is meant to store a hash, but
# an existing column cannot be downsized; thus we use the original
# column size.
'password': fields.function(get_pw, fnct_inv=set_pw, type='char',
method=True, size=64, string='Password', invisible=True,
store=True),
}
# TODO This doesn't seem right: _salt_cache doesn't necessarily contain uid.
def access(self, db, uid, passwd, sec_level, ids):
print ">>>>>> access"
cr = pooler.get_db(db).cursor()
salt = self._salt_cache[passwd]
cr.execute('select id from res_users where id=%s and password=%s', (uid, encrypt_md5( passwd, salt )) )
salt = self._salt_cache[uid]
cr.execute('select id from res_users where id=%s and password=%s',
(uid, encrypt_md5(passwd, salt)))
res = cr.fetchone()
cr.close()
if not res:
@@ -167,39 +189,28 @@ class users(osv.osv):
return res[0]
def login(self, db, login, password):
print ">>>>>> login"
cr = pooler.get_db(db).cursor()
cr.execute( 'select password from res_users where login=%s', (login.encode( 'utf-8' ),) )
stored_pw = cr.fetchone()
cr.execute('select password, id from res_users where login=%s',
(login.encode( 'utf-8' ),))
stored_pw = id = cr.fetchone()
if stored_pw:
stored_pw = stored_pw[0]
id = id[1]
else:
# Return early if no one has a login name like that.
# Return early if there is no such login.
return False
# Calculate a new password ('updated_pw') from 'stored_pw' if the
# latter isn't encrypted yet. Use that to update the database entry.
# Also update the 'stored_pw' to reflect the change.
# TODO use length(magic_md5) instead of 3.
if stored_pw[0:3] != magic_md5:
updated_pw = encrypt_md5( stored_pw, gen_salt() )
cr.execute( 'update res_users set password=%s where login=%s', (updated_pw.encode( 'utf-8' ), login.encode( 'utf-8' ),) )
cr.commit()
cr.execute( 'select password from res_users where login=%s', (login.encode( 'utf-8' ),) )
stored_pw = cr.fetchone()[0]
stored_pw = self.maybe_encrypt_and_store(cr, stored_pw, id)
# Calculate an encrypted password from the user-provided
# password ('encrypted_pw').
salt = self._salt_cache[password] = stored_pw[3:11]
encrypted_pw = encrypt_md5( password, salt )
# Retrieve a user id from the database, factoring in an encrypted
# password.
salt = self._salt_cache[id] = stored_pw[len(magic_md5):11]
encrypted_pw = encrypt_md5(password, salt)
cr.execute('select id from res_users where login=%s and password=%s and active', (login.encode('utf-8'), encrypted_pw.encode('utf-8')))
# Check if the encrypted password matches against the one in the db.
cr.execute('select id from res_users where id=%s and password=%s and active', (id, encrypted_pw.encode('utf-8')))
res = cr.fetchone()
cr.close()
@@ -209,28 +220,52 @@ class users(osv.osv):
return False
def check(self, db, uid, passwd):
# TODO see in self._uid_cache[db][uid] instead of
#if security._uid_cache.has_key( uid ) and (security._uid_cache[uid]==passwd):
print ">>>>>> check"
# TODO cannot use the cache as it would prevent the update by
# maybe_encrypt_and_store.
#cached_pass = self._uid_cache.get(db, {}).get(uid)
#if (cached_pass is not None) and cached_pass == passwd:
# return True
cr = pooler.get_db(db).cursor()
if passwd not in self._salt_cache:
cr.execute( 'select login from res_users where id=%s', (int(uid),) )
if uid not in self._salt_cache:
# TODO is int() useful ?
cr.execute('select login from res_users where id=%s', (int(uid),))
stored_login = cr.fetchone()
if stored_login:
stored_login = stored_login[0]
if not login(db,stored_login,passwd):
if not self.login(db,stored_login,passwd):
return False
salt = self._salt_cache[passwd]
cr.execute(' select count(id) from res_users where id=%s and password=%s', (int(uid), encrypt_md5( passwd, salt )) )
salt = self._salt_cache[uid]
cr.execute('select count(id) from res_users where id=%s and password=%s',
(int(uid), encrypt_md5(passwd, salt)))
res = cr.fetchone()[0]
cr.close()
if not bool(res):
raise Exception('AccessDenied')
# TODO see above
#if res:
# security._uid_cache[uid] = passwd
# if self._uid_cache.has_key(db):
# ulist = self._uid_cache[db]
# ulist[uid] = passwd
# else:
# self._uid_cache[db] = {uid: passwd}
return bool(res)
def maybe_encrypt_and_store(self, cr, pw, id):
# Calculate a new password 'encrypted' from 'pw' if the
# latter isn't encrypted yet. Use it to update the database entry
# and return it, or simply return 'pw'.
if pw[0:len(magic_md5)] != magic_md5:
encrypted = encrypt_md5(pw, gen_salt())
cr.execute('update res_users set password=%s where id=%s',
(encrypted.encode('utf-8'), id))
cr.commit()
return encrypted
return pw
users()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: