From badde34b2e2530e0bb5d4ce9cc5232b77ac2bf3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Sat, 16 Nov 2019 16:09:45 +0100 Subject: [PATCH] misc: adapt password storage (#36515) --- tests/test_form_pages.py | 12 +++++++----- wcs/qommon/form.py | 18 +++++++++--------- wcs/sql.py | 9 ++++++--- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/tests/test_form_pages.py b/tests/test_form_pages.py index f563d97b7..e2d791bd1 100644 --- a/tests/test_form_pages.py +++ b/tests/test_form_pages.py @@ -21,7 +21,9 @@ from django.utils.six import StringIO, BytesIO from django.utils.six.moves.urllib import parse as urlparse from quixote.http_request import Upload as QuixoteUpload -from django.utils.encoding import force_text +from django.utils.encoding import force_bytes, force_text + +from wcs.qommon import force_str from wcs.qommon.emails import docutils from wcs.qommon.form import UploadedFile from wcs.qommon.ident.password_accounts import PasswordAccount @@ -2017,15 +2019,15 @@ def form_password_field_submit(app, password): data_id = formdef.data_class().select()[0].id data = formdef.data_class().get(data_id) assert data.data == {'0': { - 'sha1': hashlib.sha1(password).hexdigest(), - 'md5': hashlib.md5(password).hexdigest(), - 'cleartext': force_text(password, 'utf-8'), + 'sha1': force_str(hashlib.sha1(force_bytes(password)).hexdigest()), + 'md5': force_str(hashlib.md5(force_bytes(password)).hexdigest()), + 'cleartext': force_str(password), }} def test_form_password_field_submit(pub): user = create_user(pub) form_password_field_submit(get_app(pub), 'foobar') - form_password_field_submit(get_app(pub), '\xe2\x80\xa2\t83003706') + form_password_field_submit(get_app(pub), force_str(u'• 83003706')) form_password_field_submit(login(get_app(pub), username='foo', password='foo'), 'foobar\u00eb') def test_form_multi_page_formdef_count_condition(pub): diff --git a/wcs/qommon/form.py b/wcs/qommon/form.py index 2bb35beda..782e7c79f 100644 --- a/wcs/qommon/form.py +++ b/wcs/qommon/form.py @@ -62,7 +62,7 @@ from quixote.form import * from quixote.html import htmltext, htmltag, htmlescape, TemplateIO from quixote.util import randbytes -from django.utils.encoding import force_text +from django.utils.encoding import force_bytes, force_text from django.utils import six from django.utils.six.moves.html_parser import HTMLParser from django.utils.six import StringIO @@ -74,10 +74,10 @@ from .template import render as render_template, Template, TemplateError from ..portfolio import has_portfolio from wcs.conditions import Condition, ValidationError -from . import _, ngettext +from . import _, ngettext, force_str from . import misc from .humantime import humanduration2seconds, seconds2humanduration, timewords -from .misc import strftime, C_, HAS_PDFTOPPM +from .misc import strftime, C_, HAS_PDFTOPPM, json_loads from .publisher import get_cfg from .template_utils import render_block_to_string @@ -2076,7 +2076,7 @@ class PasswordEntryWidget(CompositeWidget): required=kwargs.get('required', False), autocomplete='off') else: - encoded_value = base64.encodestring(json.dumps(value)) + encoded_value = force_text(base64.encodestring(force_bytes(json.dumps(value)))) if value: fake_value = '*' * 8 else: @@ -2120,8 +2120,8 @@ $(function() { def _parse(self, request): CompositeWidget._parse(self, request) if request.form.get('%s$encoded' % self.name): - self.value = json.loads(base64.decodestring( - request.form.get('%s$encoded' % self.name))) + self.value = json_loads(base64.decodestring( + force_bytes(request.form.get('%s$encoded' % self.name)))) return pwd1 = self.get('pwd1') or '' @@ -2177,9 +2177,9 @@ $(function() { pwd1 = None PASSWORD_FORMATS = { - 'cleartext': lambda x: x, - 'md5': lambda x: hashlib.md5(x).hexdigest(), - 'sha1': lambda x: hashlib.sha1(x).hexdigest(), + 'cleartext': lambda x: force_str(x), + 'md5': lambda x: force_str(hashlib.md5(force_bytes(x)).hexdigest()), + 'sha1': lambda x: force_str(hashlib.sha1(force_bytes(x)).hexdigest()), } if pwd1: diff --git a/wcs/sql.py b/wcs/sql.py index a31d81434..b57dc62e5 100644 --- a/wcs/sql.py +++ b/wcs/sql.py @@ -30,7 +30,7 @@ from django.utils.six import BytesIO from quixote import get_publisher from . import qommon -from wcs.qommon import PICKLE_KWARGS +from wcs.qommon import force_str, PICKLE_KWARGS from .qommon.storage import _take, parse_clause as parse_storage_clause from .qommon.substitution import invalidate_substitution_cache from .qommon import get_cfg @@ -1140,7 +1140,10 @@ class SqlMixin(object): if value is not None: if field.key in ('ranked-items', 'password'): # turn {'poire': 2, 'abricot': 1, 'pomme': 3} into an array - value = [[x, site_unicode(y).encode('utf-8')] for x, y in value.items()] + if six.PY2: + value = [[x, site_unicode(y).encode('utf-8')] for x, y in value.items()] + else: + value = [[force_str(x), force_str(y)] for x, y in value.items()] elif sql_type == 'varchar': assert isinstance(value, six.string_types) elif sql_type == 'date': @@ -1182,7 +1185,7 @@ class SqlMixin(object): elif field.key == 'password': d = {} for fmt, val in value: - d[fmt] = force_text(val, 'utf-8') + d[fmt] = force_str(val) value = d if sql_type == 'date': value = value.timetuple()