diff --git a/akarpov/templates/base.html b/akarpov/templates/base.html index c062138..0eb87f3 100644 --- a/akarpov/templates/base.html +++ b/akarpov/templates/base.html @@ -76,6 +76,7 @@ diff --git a/akarpov/templates/tools/uuid/main.html b/akarpov/templates/tools/uuid/main.html new file mode 100644 index 0000000..30fb7ae --- /dev/null +++ b/akarpov/templates/tools/uuid/main.html @@ -0,0 +1,58 @@ +{% extends 'base.html' %} +{% load static %} + +{% block content %} +
+
+
+
+
+ +
+
+ +
+
+
+
+ {% if data %} +
+ + + + + + + + + {% for key, val in data.items %} + + + + + {% endfor %} + +
namevalue
{{ key }}{{ val }}
+ {% endif %} +
+ {% for token, version in tokens %} +
+
+
+

{{ token }}

+
+
+ Generated: {{ now }}, Version: {{ version }} +
+
+
+ {% endfor %} +
+ + + +{% endblock %} diff --git a/akarpov/tools/urls.py b/akarpov/tools/urls.py index 056adc1..7c5d9d4 100644 --- a/akarpov/tools/urls.py +++ b/akarpov/tools/urls.py @@ -3,6 +3,7 @@ app_name = "tools" urlpatterns = [ path("qr/", include("akarpov.tools.qr.urls", namespace="qr")), + path("uuid/", include("akarpov.tools.uuidtools.urls", namespace="uuid")), path( "promocodes/", include("akarpov.tools.promocodes.urls", namespace="promocodes") ), diff --git a/akarpov/tools/uuidtools/__init__.py b/akarpov/tools/uuidtools/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/akarpov/tools/uuidtools/apps.py b/akarpov/tools/uuidtools/apps.py new file mode 100644 index 0000000..1791ab6 --- /dev/null +++ b/akarpov/tools/uuidtools/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class UuidtoolsConfig(AppConfig): + name = "akarpov.tools.uuidtools" diff --git a/akarpov/tools/uuidtools/forms.py b/akarpov/tools/uuidtools/forms.py new file mode 100644 index 0000000..3ac0fe4 --- /dev/null +++ b/akarpov/tools/uuidtools/forms.py @@ -0,0 +1,5 @@ +from django import forms + + +class UUIDForm(forms.Form): + token = forms.UUIDField() diff --git a/akarpov/tools/uuidtools/migrations/__init__.py b/akarpov/tools/uuidtools/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/akarpov/tools/uuidtools/services.py b/akarpov/tools/uuidtools/services.py new file mode 100644 index 0000000..da7d654 --- /dev/null +++ b/akarpov/tools/uuidtools/services.py @@ -0,0 +1,56 @@ +import datetime +from uuid import UUID + + +def uuid1_time_to_datetime(time: int): + return datetime.datetime(1582, 10, 15) + datetime.timedelta(microseconds=time // 10) + + +version_info = { + 1: """UUID Version 1 (Time-Based): The current time and the specific MAC address of the computer generating the + UUID are used to construct IDs in UUID version 1. This means that even if they generate UUIDs simultaneously, + separate machines are probably going to produce different ones. If your clock also knew your computer’s unique + number, it would display a different number each time you glanced at it depending on the time and who you were. + When generating a UUID that is specific to a certain computer and linked to the moment it was generated, + this version is frequently utilised.""", + 2: """V2 UUIDs include the MAC address of the generator, lossy timestamp, and an account ID such as user ID or + group ID on the local computer. Because of the information included in the UUID, there is limited space for + randomness. The clock section of the UUID only advances every 429.47 seconds (~7 minutes). During any 7 minute + period, there are only 64 available different UUIDs! """, + 3: """UUID Version 3 (Name-Based, Using MD5):The UUID version 3 uses MD5 hashing to create IDs. + It uses the MD5 technique to combine the “namespace UUID” (a unique UUID) and the name you supply to get a unique + identification. Imagine it as a secret recipe book where you add a secret ingredient (namespace UUID) to a standard + ingredient (name), and when you combine them using a specific method (MD5), you get a unique dish (UUID). + When you need to consistently produce UUIDs based on particular names, this variant is frequently utilised.""", + 4: """UUID Version 4 (Random): UUID version 4 uses random integers to create identifiers. It doesn’t depend on + any particular details like names or times. Instead, it simply generates a slew of random numbers and characters. + Imagine shaking a dice-filled box and then examining the face-up numbers that came out. It resembles receiving an + unpredictable combination each time. When you just require a single unique identification without any kind of + pattern or order, this version is fantastic.""", + 5: """UUID Version 5 (Name-Based, Using SHA-1): Similar to version 3, UUID version 5 generates identifiers using + the SHA-1 algorithm rather than the MD5 technique. Similar to version 3, you provide it a “namespace UUID” and a + name, and it uses the SHA-1 technique to combine them to get a unique identification. Consider it similar to + baking a cake: you need a special pan (namespace UUID), your recipe (name), and a particular baking technique ( + SHA-1). No matter how many times you cook this recipe, you will always end up with a unique cake (UUID). Similar + to version 3, UUID version 5 is frequently used in situations where a consistent and distinctive identity based + on particular names is required. The better encryption capabilities of SHA-1 make its use preferred over MD5 in + terms of security.""", +} + + +def decode_uuid(token: str) -> dict: + data = {"token": token} + try: + uuid = UUID(token) + except ValueError: + return {"message": "not a valid UUID token"} + data["version"] = f"{uuid.version}, {uuid.variant}" + data["hex"] = uuid.hex + data["bytes"] = bin(uuid.int)[2:] + data["num"] = uuid.int + if uuid.version == 1: + data["time"] = uuid1_time_to_datetime(uuid.time) + + if uuid.version in version_info: + data["info"] = version_info[uuid.version] + return data diff --git a/akarpov/tools/uuidtools/urls.py b/akarpov/tools/uuidtools/urls.py new file mode 100644 index 0000000..f164ac1 --- /dev/null +++ b/akarpov/tools/uuidtools/urls.py @@ -0,0 +1,9 @@ +from django.urls import path + +from . import views + +app_name = "uuidtools" + +urlpatterns = [ + path("", views.MainView.as_view(), name="main"), +] diff --git a/akarpov/tools/uuidtools/views.py b/akarpov/tools/uuidtools/views.py new file mode 100644 index 0000000..73141b6 --- /dev/null +++ b/akarpov/tools/uuidtools/views.py @@ -0,0 +1,28 @@ +import uuid + +import uuid6 +from django.utils.timezone import now +from django.views import generic + +from akarpov.tools.uuidtools.services import decode_uuid + + +class MainView(generic.TemplateView): + template_name = "tools/uuid/main.html" + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + if "uuid" in self.request.GET: + data = decode_uuid(str(self.request.GET["uuid"])) + context["data"] = data + context["uuid"] = self.request.GET["uuid"] + + context["tokens"] = [ + (uuid.uuid4(), 4), + (uuid6.uuid6(), 6), + (uuid6.uuid8(), 8), + (uuid.uuid1(), 1), + ] + context["now"] = now() + return context diff --git a/compose/local/django/celery/worker/start b/compose/local/django/celery/worker/start index 4ddcfa1..1f51415 100644 --- a/compose/local/django/celery/worker/start +++ b/compose/local/django/celery/worker/start @@ -4,4 +4,4 @@ set -o errexit set -o nounset -watchfiles celery.__main__.main --args '-A config.celery_app worker -l INFO' +celery -A config.celery_app worker --loglevel=info -c 5 diff --git a/poetry.lock b/poetry.lock index 6fb985c..3f16b28 100644 --- a/poetry.lock +++ b/poetry.lock @@ -7792,6 +7792,18 @@ files = [ {file = "uuid-1.30.tar.gz", hash = "sha256:1f87cc004ac5120466f36c5beae48b4c48cc411968eed0eaecd3da82aa96193f"}, ] +[[package]] +name = "uuid6" +version = "2023.5.2" +description = "New time-based UUID formats which are suited for use as a database key" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "uuid6-2023.5.2-py3-none-any.whl", hash = "sha256:9a8125a621426f24d3e4811f9885e7c0c6567ed3cc47f68fe8d41112e603bf85"}, + {file = "uuid6-2023.5.2.tar.gz", hash = "sha256:03cb97f25ca7b0ac4bea2b3a205f66bfe7f58d3b179bb0f76e1d7946446b6133"}, +] + [[package]] name = "uvicorn" version = "0.23.2" @@ -8498,4 +8510,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "eb4d0226aea0edef38f5f573bbcc3382e419d786a3ac5a687b7f20580a9971b3" +content-hash = "12fea72940b7adc01d93ab09ab68372aadae74473ab6c1aac83a7ae935f7441f" diff --git a/pyproject.toml b/pyproject.toml index 5eb850c..64e9514 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -109,6 +109,7 @@ pytest-lambda = "^2.2.0" pgvector = "^0.2.2" pycld2 = "^0.41" textract = "^1.6.5" +uuid6 = "^2023.5.2" [build-system]