0001-templatetags-add-tags-for-token-generation-validatio.patch
tests/test_templates.py | ||
---|---|---|
1 | 1 |
# -*- coding: utf-8 -*- |
2 | 2 | |
3 |
import random |
|
3 | 4 |
import datetime |
4 | 5 |
import pytest |
6 |
import string |
|
5 | 7 | |
6 | 8 |
from quixote import cleanup |
7 | 9 |
from qommon.template import Template, TemplateError |
... | ... | |
432 | 434 |
assert tmpl.render({'value': 'not a number'}) == '0' |
433 | 435 |
assert tmpl.render({'value': ''}) == '0' |
434 | 436 |
assert tmpl.render({'value': None}) == '0' |
437 | ||
438 | ||
439 |
def test_token_decimal(): |
|
440 |
tokens = [Template('{% token_decimal 4 %}').render() for i in range(100)] |
|
441 |
assert all(len(token) == 4 for token in tokens) |
|
442 |
assert all(token.isdigit() for token in tokens) |
|
443 |
# check randomness, i.e. duplicates are rare |
|
444 |
assert len(set(tokens)) > 70 |
|
445 |
t = Template('{% if token1|token_check:token2 %}ok{% endif %}') |
|
446 |
assert t.render({'token1': tokens[0] + ' ', 'token2': tokens[0].lower()}) == 'ok' |
|
447 | ||
448 | ||
449 |
def test_token_alphanum(): |
|
450 |
tokens = [Template('{% token_alphanum 4 %}').render() for i in range(100)] |
|
451 |
assert all(len(token) == 4 for token in tokens) |
|
452 |
assert all(token.upper() == token for token in tokens) |
|
453 |
assert all(token.isalnum() for token in tokens) |
|
454 |
# check randomness, i.e. duplicates are rare |
|
455 |
assert len(set(tokens)) > 90 |
|
456 |
# check there are letters and digits |
|
457 |
assert any(set(token) & set(string.ascii_uppercase) for token in tokens) |
|
458 |
assert any(set(token) & set(string.digits) for token in tokens) |
|
459 |
# no look-alike characters |
|
460 |
assert not any(set(token) & set('01IiOo') for token in tokens) |
|
461 |
t = Template('{% if token1|token_check:token2 %}ok{% endif %}') |
|
462 |
assert t.render({'token1': tokens[0] + ' ', 'token2': tokens[0].lower()}) == 'ok' |
wcs/qommon/templatetags/qommon.py | ||
---|---|---|
19 | 19 |
from decimal import InvalidOperation as DecimalInvalidOperation |
20 | 20 |
from decimal import DivisionByZero as DecimalDivisionByZero |
21 | 21 |
import math |
22 |
import string |
|
23 |
import hashlib |
|
24 |
import random |
|
22 | 25 | |
23 | 26 |
from django import template |
24 | 27 |
from django.template import defaultfilters |
... | ... | |
265 | 268 |
@register.filter(name='abs') |
266 | 269 |
def abs_(value): |
267 | 270 |
return decimal(abs(parse_decimal(value))) |
271 | ||
272 | ||
273 |
def generate_token(alphabet, length): |
|
274 |
r = random.SystemRandom() |
|
275 |
choices = [r.randrange(len(alphabet)) for i in range(length)] |
|
276 |
return ''.join([alphabet[choice] for choice in choices]) |
|
277 | ||
278 | ||
279 |
@register.simple_tag |
|
280 |
def token_decimal(length=6): |
|
281 |
# entropy by default is log(10^6)/log(2) = 19.93 bits |
|
282 |
# decimal always need more length than alphanum for the same security level |
|
283 |
# for 128bits security level, length must be more than log(2^128)/log(10) = 38.53 digits |
|
284 |
return generate_token(string.digits, length) |
|
285 | ||
286 | ||
287 |
@register.simple_tag |
|
288 |
def token_alphanum(length=4): |
|
289 |
# use of a 28 characters alphabet using uppercase letters and digits but |
|
290 |
# removing confusing characters and digits 0, O, 1 and I. |
|
291 |
# entropy by default is log(28^4)/log(2) = 19.22 bits |
|
292 |
# for 128 bits security level length must be more than log(2^128)/log(28) = 26.62 characters |
|
293 |
return generate_token('23456789ABCDEFGHJKLMNPQRSTUVWXYZ', length) |
|
294 | ||
295 | ||
296 |
@register.filter |
|
297 |
def token_check(token1, token2): |
|
298 |
return token1.strip().upper() == token2.strip().upper() |
|
268 |
- |