diff --git a/aprendizations/initdb.py b/aprendizations/initdb.py index 6cfe51d..57c236f 100644 --- a/aprendizations/initdb.py +++ b/aprendizations/initdb.py @@ -186,7 +186,10 @@ def main(): print(f' {student["uid"]}, {student["name"]}') passwd = args.pw or student['uid'] - hashed_pw = bcrypt.hashpw(passwd.encode('utf-8'), bcrypt.gensalt()) + # passwd = passwd[:72] # HACK: truncate to avoid exception on bcrypt 5.0 + print(type(passwd), passwd) + hashed_pw = bcrypt.hashpw(passwd[:72].encode('utf-8'), bcrypt.gensalt()) + print(type(hashed_pw), hashed_pw) session.add(Student(id=student['uid'], name=student['name'], password=hashed_pw)) @@ -204,16 +207,19 @@ def main(): print('\nUpdating passwords of students:') count = 0 for sid in args.update: + passwd = args.pw or sid + hashed_pw = bcrypt.hashpw(passwd[:72].encode('utf-8'), bcrypt.gensalt()) + print(type(passwd), passwd) + print(type(hashed_pw), hashed_pw) try: - query = select(Student).filter_by(id=sid) + query = select(Student).where(Student.id == sid) student = session.execute(query).scalar_one() + student.password = hashed_pw # FIXME: update not working except NoResultFound: print(f' -> student {sid} does not exist!') continue count += 1 print(f' {sid}, {student.name}') - passwd = (args.pw or sid).encode('utf-8') - student.password = str(bcrypt.hashpw(passwd, bcrypt.gensalt())) session.commit() print(f'Total {count} password(s) updated.') diff --git a/aprendizations/learnapp.py b/aprendizations/learnapp.py index 9d34de0..5d27016 100644 --- a/aprendizations/learnapp.py +++ b/aprendizations/learnapp.py @@ -165,10 +165,14 @@ class Application(): logger.info('User "%s" does not exist', uid) return False - loop = asyncio.get_running_loop() + # NOTE: + # bcrypt 5.0 raises ValueError exception for password larger than 72 chars. + # I'm truncating the password to avoid this exception + print(type(password.encode('utf-8')), password.encode('utf-8')) + print(type(student.password), student.password) pw_ok: bool = await loop.run_in_executor(None, bcrypt.checkpw, - password.encode('utf-8'), + password[:72].encode('utf-8'), student.password) if pw_ok: @@ -209,7 +213,7 @@ class Application(): logger.info('User "%s" logged out', uid) # ------------------------------------------------------------------------ - async def change_password(self, uid: str, password: str) -> bool: + async def change_password(self, uid: str, password: str, loop) -> bool: ''' Change user Password. Returns True if password is successfully changed @@ -217,15 +221,15 @@ class Application(): if not password: return False - loop = asyncio.get_running_loop() + # loop = asyncio.get_running_loop() hashed_pw = await loop.run_in_executor(None, - bcrypt.hashpw, - password.encode('utf-8'), - bcrypt.gensalt()) + bcrypt.hashpw, + password[:72].encode('utf-8'), + bcrypt.gensalt()) with Session(self._engine) as session: query = select(Student).where(Student.id == uid) - session.execute(query).scalar_one().password = str(hashed_pw) + session.execute(query).scalar_one().password = hashed_pw session.commit() logger.info('User "%s" changed password', uid) diff --git a/aprendizations/serve.py b/aprendizations/serve.py index f1e6497..4f78880 100644 --- a/aprendizations/serve.py +++ b/aprendizations/serve.py @@ -84,7 +84,8 @@ class ChangePasswordHandler(BaseHandler): '''Try to change password and show success/fail status''' userid = self.current_user passwd = self.get_body_arguments('new_password')[0] # FIXME porque [0]? - ok = await self.app.change_password(userid, passwd) + loop = tornado.ioloop.IOLoop.current() + ok = await self.app.change_password(userid, passwd, loop) notification = self.render_string('notification.html', ok=ok) self.write({'msg': to_unicode(notification)}) diff --git a/setup.py b/setup.py index a0fd837..2a4f5ac 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,7 @@ setup( 'pyyaml>=6.0', 'pygments>=2.19', 'sqlalchemy>=2.0.37', - 'bcrypt>=4.2.1', + 'bcrypt>=5.0', 'networkx>=3.4.2', 'pandas>=2.3', 'openpyxl' -- libgit2 0.21.2