[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:
@@ -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,
|
||||
}
|
||||
@@ -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
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user