Translation of UI (german and english)
Bugfix for feeds
- removed categories related and up
- load new books now working
- category random now working
login page is free of non accessible elements
boolean custom column is vivible in UI
books with only with certain languages can be shown
book shelfs can be deleted from UI
Anonymous user view is more resticted
Added browse of series in sidebar
Dependencys in vendor folder are updated to newer versions (licencs files are now present)
Bugfix editing Authors names
Made upload on windows working
This commit is contained in:
Vendored
+116
-7
@@ -6,7 +6,7 @@
|
||||
A module that implements various functions to deal with untrusted
|
||||
sources. Mainly useful for web applications.
|
||||
|
||||
:copyright: (c) 2011 by Armin Ronacher and the Django Software Foundation.
|
||||
:copyright: (c) 2014 by Armin Ronacher and the Django Software Foundation.
|
||||
:license: BSD, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
@@ -25,11 +25,13 @@ if PY2:
|
||||
from itertools import izip
|
||||
text_type = unicode
|
||||
int_to_byte = chr
|
||||
number_types = (int, long, float)
|
||||
else:
|
||||
from functools import reduce
|
||||
izip = zip
|
||||
text_type = str
|
||||
int_to_byte = operator.methodcaller('to_bytes', 1, 'big')
|
||||
number_types = (int, float)
|
||||
|
||||
|
||||
try:
|
||||
@@ -122,6 +124,10 @@ class BadPayload(BadData):
|
||||
that. The original exception that caused that will be stored on the
|
||||
exception as :attr:`original_error`.
|
||||
|
||||
This can also happen with a :class:`JSONWebSignatureSerializer` that
|
||||
is subclassed and uses a different serializer for the payload than
|
||||
the expected one.
|
||||
|
||||
.. versionadded:: 0.15
|
||||
"""
|
||||
|
||||
@@ -164,6 +170,27 @@ class BadTimeSignature(BadSignature):
|
||||
self.date_signed = date_signed
|
||||
|
||||
|
||||
class BadHeader(BadSignature):
|
||||
"""Raised if a signed header is invalid in some form. This only
|
||||
happens for serializers that have a header that goes with the
|
||||
signature.
|
||||
|
||||
.. versionadded:: 0.24
|
||||
"""
|
||||
|
||||
def __init__(self, message, payload=None, header=None,
|
||||
original_error=None):
|
||||
BadSignature.__init__(self, message, payload)
|
||||
|
||||
#: If the header is actually available but just malformed it
|
||||
#: might be stored here.
|
||||
self.header = header
|
||||
|
||||
#: If available, the error that indicates why the payload
|
||||
#: was not valid. This might be `None`.
|
||||
self.original_error = original_error
|
||||
|
||||
|
||||
class SignatureExpired(BadTimeSignature):
|
||||
"""Signature timestamp is older than required max_age. This is a
|
||||
subclass of :exc:`BadTimeSignature` so you can use the baseclass for
|
||||
@@ -211,6 +238,10 @@ class SigningAlgorithm(object):
|
||||
"""Returns the signature for the given key and value"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def verify_signature(self, key, value, sig):
|
||||
"""Verifies the given signature matches the expected signature"""
|
||||
return constant_time_compare(sig, self.get_signature(key, value))
|
||||
|
||||
|
||||
class NoneAlgorithm(SigningAlgorithm):
|
||||
"""This class provides a algorithm that does not perform any signing and
|
||||
@@ -321,6 +352,15 @@ class Signer(object):
|
||||
"""Signs the given string."""
|
||||
return value + want_bytes(self.sep) + self.get_signature(value)
|
||||
|
||||
def verify_signature(self, value, sig):
|
||||
"""Verifies the signature for the given value."""
|
||||
key = self.derive_key()
|
||||
try:
|
||||
sig = base64_decode(sig)
|
||||
except Exception:
|
||||
return False
|
||||
return self.algorithm.verify_signature(key, value, sig)
|
||||
|
||||
def unsign(self, signed_value):
|
||||
"""Unsigns the given string."""
|
||||
signed_value = want_bytes(signed_value)
|
||||
@@ -328,7 +368,7 @@ class Signer(object):
|
||||
if sep not in signed_value:
|
||||
raise BadSignature('No %r found in value' % self.sep)
|
||||
value, sig = signed_value.rsplit(sep, 1)
|
||||
if constant_time_compare(sig, self.get_signature(value)):
|
||||
if self.verify_signature(value, sig):
|
||||
return value
|
||||
raise BadSignature('Signature %r does not match' % sig,
|
||||
payload=value)
|
||||
@@ -499,7 +539,7 @@ class Serializer(object):
|
||||
return serializer.loads(payload)
|
||||
except Exception as e:
|
||||
raise BadPayload('Could not load the payload because an '
|
||||
'exception ocurred on unserializing the data',
|
||||
'exception occurred on unserializing the data',
|
||||
original_error=e)
|
||||
|
||||
def dump_payload(self, obj):
|
||||
@@ -645,14 +685,23 @@ class JSONWebSignatureSerializer(Serializer):
|
||||
base64d_header, base64d_payload = payload.split(b'.', 1)
|
||||
try:
|
||||
json_header = base64_decode(base64d_header)
|
||||
except Exception as e:
|
||||
raise BadHeader('Could not base64 decode the header because of '
|
||||
'an exception', original_error=e)
|
||||
try:
|
||||
json_payload = base64_decode(base64d_payload)
|
||||
except Exception as e:
|
||||
raise BadPayload('Could not base64 decode the payload because of '
|
||||
'an exception', original_error=e)
|
||||
header = Serializer.load_payload(self, json_header,
|
||||
serializer=json)
|
||||
try:
|
||||
header = Serializer.load_payload(self, json_header,
|
||||
serializer=json)
|
||||
except BadData as e:
|
||||
raise BadHeader('Could not unserialize header because it was '
|
||||
'malformed', original_error=e)
|
||||
if not isinstance(header, dict):
|
||||
raise BadPayload('Header payload is not a JSON object')
|
||||
raise BadHeader('Header payload is not a JSON object',
|
||||
header=header)
|
||||
payload = Serializer.load_payload(self, json_payload)
|
||||
if return_header:
|
||||
return payload, header
|
||||
@@ -700,7 +749,8 @@ class JSONWebSignatureSerializer(Serializer):
|
||||
self.make_signer(salt, self.algorithm).unsign(want_bytes(s)),
|
||||
return_header=True)
|
||||
if header.get('alg') != self.algorithm_name:
|
||||
raise BadSignature('Algorithm mismatch')
|
||||
raise BadHeader('Algorithm mismatch', header=header,
|
||||
payload=payload)
|
||||
if return_header:
|
||||
return payload, header
|
||||
return payload
|
||||
@@ -710,6 +760,65 @@ class JSONWebSignatureSerializer(Serializer):
|
||||
return self._loads_unsafe_impl(s, salt, kwargs, kwargs)
|
||||
|
||||
|
||||
class TimedJSONWebSignatureSerializer(JSONWebSignatureSerializer):
|
||||
"""Works like the regular :class:`JSONWebSignatureSerializer` but also
|
||||
records the time of the signing and can be used to expire signatures.
|
||||
|
||||
JWS currently does not specify this behavior but it mentions a possibility
|
||||
extension like this in the spec. Expiry date is encoded into the header
|
||||
similarily as specified in `draft-ietf-oauth-json-web-token
|
||||
<http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#expDef`_.
|
||||
|
||||
The unsign method can raise a :exc:`SignatureExpired` method if the
|
||||
unsigning failed because the signature is expired. This exception is a
|
||||
subclass of :exc:`BadSignature`.
|
||||
"""
|
||||
|
||||
DEFAULT_EXPIRES_IN = 3600
|
||||
|
||||
def __init__(self, secret_key, expires_in=None, **kwargs):
|
||||
JSONWebSignatureSerializer.__init__(self, secret_key, **kwargs)
|
||||
if expires_in is None:
|
||||
expires_in = self.DEFAULT_EXPIRES_IN
|
||||
self.expires_in = expires_in
|
||||
|
||||
def make_header(self, header_fields):
|
||||
header = JSONWebSignatureSerializer.make_header(self, header_fields)
|
||||
iat = self.now()
|
||||
exp = iat + self.expires_in
|
||||
header['iat'] = iat
|
||||
header['exp'] = exp
|
||||
return header
|
||||
|
||||
def loads(self, s, salt=None, return_header=False):
|
||||
payload, header = JSONWebSignatureSerializer.loads(
|
||||
self, s, salt, return_header=True)
|
||||
|
||||
if 'exp' not in header:
|
||||
raise BadSignature('Missing expiry date', payload=payload)
|
||||
|
||||
if not (isinstance(header['exp'], number_types)
|
||||
and header['exp'] > 0):
|
||||
raise BadSignature('expiry date is not an IntDate',
|
||||
payload=payload)
|
||||
|
||||
if header['exp'] < self.now():
|
||||
raise SignatureExpired('Signature expired', payload=payload,
|
||||
date_signed=self.get_issue_date(header))
|
||||
|
||||
if return_header:
|
||||
return payload, header
|
||||
return payload
|
||||
|
||||
def get_issue_date(self, header):
|
||||
rv = header.get('iat')
|
||||
if isinstance(rv, number_types):
|
||||
return datetime.utcfromtimestamp(int(rv))
|
||||
|
||||
def now(self):
|
||||
return int(time.time())
|
||||
|
||||
|
||||
class URLSafeSerializerMixin(object):
|
||||
"""Mixed in with a regular serializer it will attempt to zlib compress
|
||||
the string to make it shorter if necessary. It will also base64 encode
|
||||
|
||||
Reference in New Issue
Block a user