From 39fd5525cd921682fc739a2dd51cac05e37ce662 Mon Sep 17 00:00:00 2001 From: imperosol Date: Sun, 26 Oct 2025 14:03:03 +0100 Subject: [PATCH] `hmac_hexdigest` util function --- api/templates/api/third_party/auth.jinja | 32 ++++++++++++++++++ core/utils.py | 43 ++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 api/templates/api/third_party/auth.jinja diff --git a/api/templates/api/third_party/auth.jinja b/api/templates/api/third_party/auth.jinja new file mode 100644 index 00000000..e4e9e4f6 --- /dev/null +++ b/api/templates/api/third_party/auth.jinja @@ -0,0 +1,32 @@ +{% extends "core/base.jinja" %} + +{% block content %} +
+ {% csrf_token %} +

{% trans %}Confidentiality{% endtrans %}

+

+ {% trans trimmed app=third_party_app %} + By ticking this box and clicking on the send button, you + acknowledge and agree to provide {{ app }} with your + first name, last name, nickname and any other information + that was the third party app was explicitly authorized to fetch + and that it must have acknowledged to you, in a complete and accurate manner. + {% endtrans %} +

+

+ {% trans trimmed app=third_party_app, cgu_link=third_party_cgu, sith_cgu_link=sith_cgu %} + The privacy policies of {{ app }} + and of the Students' Association + applies as soon as the form is submitted. + {% endtrans %} +

+
{{ form.cgu_accepted }} {{ form.cgu_accepted.label_tag() }}
+
+

{% trans %}Confirmation of identity{% endtrans %}

+
+ {{ form.is_username_valid }} {{ form.is_username_valid.label_tag() }} +
+ {% for field in form.hidden_fields() %}{{ field }}{% endfor %} + +
+{% endblock %} \ No newline at end of file diff --git a/core/utils.py b/core/utils.py index 0e284768..1e72b096 100644 --- a/core/utils.py +++ b/core/utils.py @@ -12,22 +12,32 @@ # OR WITHIN THE LOCAL FILE "LICENSE" # # +from __future__ import annotations +import hmac from datetime import date, timedelta # Image utils from io import BytesIO -from typing import Final +from typing import TYPE_CHECKING +from urllib.parse import urlencode import PIL from django.conf import settings from django.core.files.base import ContentFile -from django.core.files.uploadedfile import UploadedFile -from django.http import HttpRequest from django.utils.timezone import localdate from PIL import ExifTags from PIL.Image import Image, Resampling +if TYPE_CHECKING: + from _hashlib import HASH + from collections.abc import Buffer, Mapping, Sequence + from typing import Any, Callable, Final + + from django.core.files.uploadedfile import UploadedFile + from django.http import HttpRequest + + RED_PIXEL_PNG: Final[bytes] = ( b"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52" b"\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90\x77\x53" @@ -205,3 +215,30 @@ def get_client_ip(request: HttpRequest) -> str | None: return ip return None + + +def hmac_hexdigest( + key: str | bytes, + data: Mapping[str, Any] | Sequence[tuple[str, Any]], + digest: str | Callable[[Buffer], HASH] = "sha256", +) -> str: + """Return the hexdigest of the signature of the given data. + + Args: + key: the HMAC key used for the signature + data: the data to sign + digest: a PEP247 hashing algorithm + + Examples: + ```python + data = { + "foo": 5, + "bar": "somevalue", + } + hmac_key = secrets.token_hex(64) + signature = hmac_hexdigest(hmac_key, data, "sha512") + ``` + """ + if isinstance(key, str): + key = key.encode() + return hmac.digest(key, urlencode(data).encode(), digest).hex()