misc: adapt password storage (#36515)

This commit is contained in:
Frédéric Péters 2019-11-16 16:09:45 +01:00
parent 191f01bd7e
commit badde34b2e
3 changed files with 22 additions and 17 deletions

View File

@ -21,7 +21,9 @@ from django.utils.six import StringIO, BytesIO
from django.utils.six.moves.urllib import parse as urlparse from django.utils.six.moves.urllib import parse as urlparse
from quixote.http_request import Upload as QuixoteUpload 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.emails import docutils
from wcs.qommon.form import UploadedFile from wcs.qommon.form import UploadedFile
from wcs.qommon.ident.password_accounts import PasswordAccount 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_id = formdef.data_class().select()[0].id
data = formdef.data_class().get(data_id) data = formdef.data_class().get(data_id)
assert data.data == {'0': { assert data.data == {'0': {
'sha1': hashlib.sha1(password).hexdigest(), 'sha1': force_str(hashlib.sha1(force_bytes(password)).hexdigest()),
'md5': hashlib.md5(password).hexdigest(), 'md5': force_str(hashlib.md5(force_bytes(password)).hexdigest()),
'cleartext': force_text(password, 'utf-8'), 'cleartext': force_str(password),
}} }}
def test_form_password_field_submit(pub): def test_form_password_field_submit(pub):
user = create_user(pub) user = create_user(pub)
form_password_field_submit(get_app(pub), 'foobar') 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') form_password_field_submit(login(get_app(pub), username='foo', password='foo'), 'foobar\u00eb')
def test_form_multi_page_formdef_count_condition(pub): def test_form_multi_page_formdef_count_condition(pub):

View File

@ -62,7 +62,7 @@ from quixote.form import *
from quixote.html import htmltext, htmltag, htmlescape, TemplateIO from quixote.html import htmltext, htmltag, htmlescape, TemplateIO
from quixote.util import randbytes 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 import six
from django.utils.six.moves.html_parser import HTMLParser from django.utils.six.moves.html_parser import HTMLParser
from django.utils.six import StringIO 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 ..portfolio import has_portfolio
from wcs.conditions import Condition, ValidationError from wcs.conditions import Condition, ValidationError
from . import _, ngettext from . import _, ngettext, force_str
from . import misc from . import misc
from .humantime import humanduration2seconds, seconds2humanduration, timewords 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 .publisher import get_cfg
from .template_utils import render_block_to_string from .template_utils import render_block_to_string
@ -2076,7 +2076,7 @@ class PasswordEntryWidget(CompositeWidget):
required=kwargs.get('required', False), required=kwargs.get('required', False),
autocomplete='off') autocomplete='off')
else: else:
encoded_value = base64.encodestring(json.dumps(value)) encoded_value = force_text(base64.encodestring(force_bytes(json.dumps(value))))
if value: if value:
fake_value = '*' * 8 fake_value = '*' * 8
else: else:
@ -2120,8 +2120,8 @@ $(function() {
def _parse(self, request): def _parse(self, request):
CompositeWidget._parse(self, request) CompositeWidget._parse(self, request)
if request.form.get('%s$encoded' % self.name): if request.form.get('%s$encoded' % self.name):
self.value = json.loads(base64.decodestring( self.value = json_loads(base64.decodestring(
request.form.get('%s$encoded' % self.name))) force_bytes(request.form.get('%s$encoded' % self.name))))
return return
pwd1 = self.get('pwd1') or '' pwd1 = self.get('pwd1') or ''
@ -2177,9 +2177,9 @@ $(function() {
pwd1 = None pwd1 = None
PASSWORD_FORMATS = { PASSWORD_FORMATS = {
'cleartext': lambda x: x, 'cleartext': lambda x: force_str(x),
'md5': lambda x: hashlib.md5(x).hexdigest(), 'md5': lambda x: force_str(hashlib.md5(force_bytes(x)).hexdigest()),
'sha1': lambda x: hashlib.sha1(x).hexdigest(), 'sha1': lambda x: force_str(hashlib.sha1(force_bytes(x)).hexdigest()),
} }
if pwd1: if pwd1:

View File

@ -30,7 +30,7 @@ from django.utils.six import BytesIO
from quixote import get_publisher from quixote import get_publisher
from . import qommon 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.storage import _take, parse_clause as parse_storage_clause
from .qommon.substitution import invalidate_substitution_cache from .qommon.substitution import invalidate_substitution_cache
from .qommon import get_cfg from .qommon import get_cfg
@ -1140,7 +1140,10 @@ class SqlMixin(object):
if value is not None: if value is not None:
if field.key in ('ranked-items', 'password'): if field.key in ('ranked-items', 'password'):
# turn {'poire': 2, 'abricot': 1, 'pomme': 3} into an array # 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': elif sql_type == 'varchar':
assert isinstance(value, six.string_types) assert isinstance(value, six.string_types)
elif sql_type == 'date': elif sql_type == 'date':
@ -1182,7 +1185,7 @@ class SqlMixin(object):
elif field.key == 'password': elif field.key == 'password':
d = {} d = {}
for fmt, val in value: for fmt, val in value:
d[fmt] = force_text(val, 'utf-8') d[fmt] = force_str(val)
value = d value = d
if sql_type == 'date': if sql_type == 'date':
value = value.timetuple() value = value.timetuple()