Exemplo n.º 1
0
def parse_etags(value):
    """Parse an etag header.

    :param value: the tag header to parse
    :return: an :class:`~werkzeug.datastructures.ETags` object.
    """
    if not value:
        return ETags()
    strong = []
    weak = []
    end = len(value)
    pos = 0
    while pos < end:
        match = _etag_re.match(value, pos)
        if match is None:
            break
        is_weak, quoted, raw = match.groups()
        if raw == '*':
            return ETags(star_tag=True)
        elif quoted:
            raw = quoted
        if is_weak:
            weak.append(raw)
        else:
            strong.append(raw)
        pos = match.end()
    return ETags(strong, weak)
Exemplo n.º 2
0
def require_etag(
    etag: ETags,
    error_details: Optional[Dict[str, str]] = None,
) -> None:
    """Ensure the current request matches the given ETag.

    Args:
        etag: An Werkzeug ETag instance to compare the global request instance to.

        error_details:
            An optional dict, which will be communicated to the client whenever there is an
            etag mismatch.

    Raises:
        ProblemException: When If-Match missing or ETag doesn't match.
    """
    etags_required = active_config.rest_api_etag_locking
    if not request.if_match:
        if not etags_required:
            return
        raise ProblemException(
            HTTPStatus.PRECONDITION_REQUIRED,
            "Precondition required",
            "If-Match header required for this operation. See documentation.",
            ext=error_details,
        )

    if request.if_match.as_set() != etag.as_set():
        raise ProblemException(
            HTTPStatus.PRECONDITION_FAILED,
            "Precondition failed",
            f"ETag didn't match. Expected {etag}. Probable cause: Object changed by another user.",
            ext=error_details,
        )
Exemplo n.º 3
0
def etag_of_dict(dict_: Dict[str, Any]) -> ETags:
    """Build a sha256 hash over a dictionary's content.

    Keys are sorted first to ensure a stable hash.

    Examples:
        >>> etag_of_dict({'a': 'b', 'c': 'd'})
        <ETags '"88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589"'>

        >>> etag_of_dict({'a': 'b', 'c': {'d': {'e': 'f'}}})
        <ETags '"bef57ec7f53a6d40beb640a780a639c83bc29ac8a9816f1fc6c5c6dcd93c4721"'>

    Args:
        dict_ (dict): A dictionary.

    Returns:
        str: The hex-digest of the built hash.

    """
    def _update(_hash_obj, _d):
        if isinstance(_d, list):
            for value in sorted(_d):
                _update(_hash_obj, value)
        else:
            for key, value in sorted(_d.items()):
                _hash_obj.update(key.encode('utf-8'))
                if isinstance(value, (dict, list)):
                    _update(_hash_obj, value)
                else:
                    _hash_obj.update(value.encode('utf-8'))

    _hash = hashlib.sha256()
    _update(_hash, dict_)
    return ETags(strong_etags=[_hash.hexdigest()])
Exemplo n.º 4
0
def require_etag(etag: ETags) -> None:
    """Ensure the current request matches the given ETag.

    Args:
        etag: An Werkzeug ETag instance to compare the global request instance to.

    Raises:
        ProblemException: When If-Match missing or ETag doesn't match.
    """
    etags_required = config.rest_api_etag_locking
    if not request.if_match:
        if not etags_required:
            return
        raise ProblemException(
            HTTPStatus.PRECONDITION_REQUIRED,
            "Precondition required",
            "If-Match header required for this operation. See documentation.",
        )

    if request.if_match.as_set() != etag.as_set():
        raise ProblemException(
            HTTPStatus.PRECONDITION_FAILED,
            "Precondition failed",
            "ETag didn't match. Probable cause: Object changed by another user.",
        )
Exemplo n.º 5
0
def _get_etag(folder):
    attributes = folder.attributes()
    if 'meta_data' in attributes:
        etags = [str(attributes['meta_data']['updated_at'])]
        return ETags(strong_etags=etags)
    else:
        raise ProblemException(
            500, "Folder %r has no meta_data." % (folder.name(), ),
            "Can't create ETag.")
Exemplo n.º 6
0
def etag_of_dict(dict_: Dict[str, Any]) -> ETags:
    """Build a sha256 hash over a dictionary's content.

    Keys are sorted first to ensure a stable hash.

    Examples:
        >>> etag_of_dict({'a': 'b', 'c': 'd'})
        <ETags '"88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589"'>

        >>> etag_of_dict({'a': 'b', 'c': {'d': {'e': 'f'}}})
        <ETags '"bef57ec7f53a6d40beb640a780a639c83bc29ac8a9816f1fc6c5c6dcd93c4721"'>

        >>> etag_of_dict({'a': [{'b': 1, 'd': 2}, {'d': 2, 'b': 3}]})
        <ETags '"6ea899bec9b061d54f1f8fcdb7405363126c0e96d198d09792eff0996590ee3e"'>

    Args:
        dict_ (dict): A dictionary.

    Returns:
        str: The hex-digest of the built hash.

    """
    def _first(sequence):
        try:
            return sequence[0]
        except IndexError:
            pass

    def _update(_hash_obj, _d):
        if isinstance(_d, (list, tuple)):
            first = _first(_d)
            if isinstance(first, dict):
                for entry in _d:
                    _update(_hash_obj, entry)
            else:
                for value in sorted(_d):
                    _update(_hash_obj, value)
        else:
            if isinstance(_d, dict):
                for key, value in sorted(_d.items()):
                    _hash_obj.update(key.encode('utf-8'))
                    if isinstance(value, (dict, list, tuple)):
                        _update(_hash_obj, value)
                    elif isinstance(value, bool):
                        _hash_obj.update(str(value).lower().encode('utf-8'))
                    else:
                        _hash_obj.update(str(value).encode('utf-8'))
            else:
                _hash_obj.update(str(_d).encode('utf-8'))

    _hash = hashlib.sha256()
    _update(_hash, dict_)
    return ETags(strong_etags=[_hash.hexdigest()])
Exemplo n.º 7
0
def parse_etags(value):
    if not value:
        return ETags()
    strong = []
    weak = []
    end = len(value)
    pos = 0
    while pos < end:
        match = _etag_re.match(value, pos)
        if match is None:
            break
        is_weak, quoted, raw = match.groups()
        if raw == '*':
            return ETags(star_tag=True)
        if quoted:
            raw = quoted
        if is_weak:
            weak.append(raw)
        else:
            strong.append(raw)
        pos = match.end()

    return ETags(strong, weak)
Exemplo n.º 8
0
def require_etag(etag: ETags) -> None:
    """Ensure the current request matches the given ETag.

    Args:
        etag: An Werkzeug ETag instance to compare the global request instance to.

    Raises:
        ProblemException: When ETag doesn't match.
    """
    if request.if_match.as_set() != etag.as_set():
        raise ProblemException(
            412,
            "Precondition failed",
            "ETag didn't match. Probable cause: Object changed by another user.",
        )
Exemplo n.º 9
0
def etag_of_dict(dict_):
    """Build a sha256 hash over a dictionary's content.

    Keys are sorted first to ensure a stable hash.

    Args:
        dict_ (dict): A dictionary.

    Returns:
        str: The hex-digest of the built hash.

    """
    _hash = hashlib.sha256()
    for key in sorted(dict_.keys()):
        _hash.update(dict_[key])
    return ETags(strong_etags=_hash.hexdigest())
Exemplo n.º 10
0
def etag_of_obj(obj):
    """Build an ETag from an objects last updated time.

    Args:
        obj: An object with a `updated_at` method.

    Returns:
        The value which the method returns, else raises a `ProblemException`.

    """
    updated_at = obj.updated_at()
    assert updated_at is not None
    if updated_at is None:
        raise ProblemException(500, "Object %r has no meta_data." % (obj.name(),),
                               "Can't create ETag.")

    return ETags(strong_etags=[str(updated_at)])