Merge branch 'main' into storefront-nuxt

This commit is contained in:
Egor Pavlovich Gorbunov 2025-11-25 14:26:27 +03:00
commit ae1f291a51
4 changed files with 78 additions and 73 deletions

View file

@ -1,11 +1,13 @@
import logging
from typing import Any
from django.conf import settings
from django.contrib.auth.models import Permission
from django.core.management.base import BaseCommand
from django.db.models import Q
from engine.core.models import Vendor
from engine.vibes_auth.models import Group
from engine.vibes_auth.models import Group, User
logger = logging.getLogger(__name__)
@ -155,4 +157,7 @@ class Command(BaseCommand):
perms = Permission.objects.filter(codename__in=e_commerce_admin_permissions)
e_commerce_admin.permissions.add(*perms)
valid_codes = [code for code, _ in settings.LANGUAGES]
(User.objects.filter(Q(language="") | ~Q(language__in=valid_codes)).update(language=settings.LANGUAGE_CODE))
self.stdout.write(self.style.SUCCESS("Successfully initialized must-have instances!"))

View file

@ -16,5 +16,7 @@ BAD_KEYS_TO_LISTEN = [
"is_staff",
"is_superuser",
"is_active",
"active",
"is_verified",
"groups",
"user_permissions",
]

View file

@ -17,6 +17,7 @@ from graphene_file_upload.scalars import Upload
from engine.core.graphene import BaseMutation
from engine.core.utils.messages import permission_denied_message
from engine.core.utils.security import is_safe_key
from engine.vibes_auth.graphene.object_types import UserType
from engine.vibes_auth.models import User
from engine.vibes_auth.serializers import (
@ -107,65 +108,62 @@ class UpdateUser(BaseMutation):
try:
user = User.objects.get(uuid=uuid)
if not (info.context.user.has_perm("vibes_auth.change_user") or info.context.user == user):
raise PermissionDenied(permission_denied_message)
email = kwargs.get("email")
if (email is not None and not is_valid_email(email)) or User.objects.filter(email=email).exclude(
uuid=uuid
).exists():
raise BadRequest(_("malformed email"))
phone_number = kwargs.get("phone_number")
if (phone_number is not None and not is_valid_phone_number(phone_number)) or (
User.objects.filter(phone_number=phone_number).exclude(uuid=uuid).exists() and phone_number is not None
):
raise BadRequest(_(f"malformed phone number: {phone_number}"))
password = kwargs.get("password", "")
confirm_password = kwargs.get("confirm_password", "")
if password:
validate_password(password=password, user=user)
if not compare_digest(password, "") and compare_digest(password, confirm_password):
user.set_password(password)
user.save()
attribute_pairs = kwargs.pop("attributes", "")
if attribute_pairs:
for attribute_pair in attribute_pairs.split(";"):
if "-" in attribute_pair:
attr, value = attribute_pair.split("-", 1)
if not user.attributes:
user.attributes = {}
user.attributes.update({attr: value})
else:
raise BadRequest(_(f"Invalid attribute format: {attribute_pair}"))
for attr, value in kwargs.items():
if attr == "password" or attr == "confirm_password":
continue
if is_safe_key(attr) or info.context.user.has_perm("vibes_auth.change_user"):
setattr(user, attr, value)
user.save()
return UpdateUser(user=user)
except User.DoesNotExist as dne:
name = "User"
raise Http404(_(f"{name} does not exist: {uuid}")) from dne
if not (info.context.user.has_perm("vibes_auth.change_user") or info.context.user == user):
raise PermissionDenied(permission_denied_message)
email = kwargs.get("email")
if (email is not None and not is_valid_email(email)) or User.objects.filter(email=email).exclude(
uuid=uuid
).exists():
raise BadRequest(_("malformed email"))
phone_number = kwargs.get("phone_number")
if (phone_number is not None and not is_valid_phone_number(phone_number)) or (
User.objects.filter(phone_number=phone_number).exclude(uuid=uuid).exists() and phone_number is not None
):
raise BadRequest(_(f"malformed phone number: {phone_number}"))
password = kwargs.get("password", "")
confirm_password = kwargs.get("confirm_password", "")
if password:
validate_password(password=password, user=user)
if not compare_digest(password, "") and compare_digest(password, confirm_password):
user.set_password(password)
user.save()
attribute_pairs = kwargs.pop("attributes", "")
if attribute_pairs:
for attribute_pair in attribute_pairs.split(";"):
if "-" in attribute_pair:
attr, value = attribute_pair.split("-", 1)
if not user.attributes:
user.attributes = {}
user.attributes.update({attr: value})
else:
raise BadRequest(_(f"Invalid attribute format: {attribute_pair}"))
for attr, value in kwargs.items():
if attr == "password" or attr == "confirm_password":
continue
if attr not in [
"groups",
"user_permissions",
"is_verified",
"is_staff",
"is_active",
"is_superuser",
] or info.context.user.has_perm("vibes_auth.change_user"):
setattr(user, attr, value)
user.save()
return UpdateUser(user=user)
except Exception as e:
logger.warning("Could not update user: %s", str(e))
logger.debug(traceback.format_exc())
raise BadRequest(str(e)) from e
class DeleteUser(BaseMutation):

30
uv.lock
View file

@ -215,11 +215,11 @@ wheels = [
[[package]]
name = "asgiref"
version = "3.10.0"
version = "3.11.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/46/08/4dfec9b90758a59acc6be32ac82e98d1fbfc321cb5cfa410436dbacf821c/asgiref-3.10.0.tar.gz", hash = "sha256:d89f2d8cd8b56dada7d52fa7dc8075baa08fb836560710d38c292a7a3f78c04e", size = 37483, upload-time = "2025-10-05T09:15:06.557Z" }
sdist = { url = "https://files.pythonhosted.org/packages/76/b9/4db2509eabd14b4a8c71d1b24c8d5734c52b8560a7b1e1a8b56c8d25568b/asgiref-3.11.0.tar.gz", hash = "sha256:13acff32519542a1736223fb79a715acdebe24286d98e8b164a73085f40da2c4", size = 37969, upload-time = "2025-11-19T15:32:20.106Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/17/9c/fc2331f538fbf7eedba64b2052e99ccf9ba9d6888e2f41441ee28847004b/asgiref-3.10.0-py3-none-any.whl", hash = "sha256:aef8a81283a34d0ab31630c9b7dfe70c812c95eba78171367ca8745e88124734", size = 24050, upload-time = "2025-10-05T09:15:05.11Z" },
{ url = "https://files.pythonhosted.org/packages/91/be/317c2c55b8bbec407257d45f5c8d1b6867abc76d12043f2d3d58c538a4ea/asgiref-3.11.0-py3-none-any.whl", hash = "sha256:1db9021efadb0d9512ce8ffaf72fcef601c7b73a8807a1bb2ef143dc6b14846d", size = 24096, upload-time = "2025-11-19T15:32:19.004Z" },
]
[[package]]
@ -1076,14 +1076,14 @@ wheels = [
[[package]]
name = "django-unfold"
version = "0.71.0"
version = "0.72.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "django" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ec/5b/406eae1a429b15ba04f4dfaaf53aa64fb03bcfdc6bdd0753a41027aa3daa/django_unfold-0.71.0.tar.gz", hash = "sha256:995a296f1c15f172b0d8458ff12beb420ea7e9a666fa865a60ec03f70aaf4066", size = 1101347, upload-time = "2025-11-11T16:24:03.289Z" }
sdist = { url = "https://files.pythonhosted.org/packages/55/e6/045b68207d8b4b395623d39d803e6566ea2c110e56665e3ff6bda07de6aa/django_unfold-0.72.0.tar.gz", hash = "sha256:43a0e8a4383037a24b73666c9f721faef12bd500c4628b4fc39d0dafd2e9c0a2", size = 1102339, upload-time = "2025-11-24T09:03:47.347Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/16/94/ad8ba84410655e0207ffcc7c6cba0875e9f79f914e3f2e2de883f706f7c9/django_unfold-0.71.0-py3-none-any.whl", hash = "sha256:76d4019aa9052ebe2e040d868be895d8581018fdf7debca943084aa0e79c2e31", size = 1213722, upload-time = "2025-11-11T16:24:01.985Z" },
{ url = "https://files.pythonhosted.org/packages/2d/dd/6cdb80d5d377f2bdf3b39b639025bb8655b96fac08aa3673ae1e4b3e3384/django_unfold-0.72.0-py3-none-any.whl", hash = "sha256:61448ad42ff7a33c7ad66d14071b24224bb476038a14a1bbe719a774db496e34", size = 1215396, upload-time = "2025-11-24T09:03:45.568Z" },
]
[[package]]
@ -2161,7 +2161,7 @@ wheels = [
[[package]]
name = "jupyterlab"
version = "4.4.10"
version = "4.5.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "async-lru" },
@ -2178,9 +2178,9 @@ dependencies = [
{ name = "tornado" },
{ name = "traitlets" },
]
sdist = { url = "https://files.pythonhosted.org/packages/6a/5d/75c42a48ff5fc826a7dff3fe4004cda47c54f9d981c351efacfbc9139d3c/jupyterlab-4.4.10.tar.gz", hash = "sha256:521c017508af4e1d6d9d8a9d90f47a11c61197ad63b2178342489de42540a615", size = 22969303, upload-time = "2025-10-22T14:50:58.768Z" }
sdist = { url = "https://files.pythonhosted.org/packages/df/e5/4fa382a796a6d8e2cd867816b64f1ff27f906e43a7a83ad9eb389e448cd8/jupyterlab-4.5.0.tar.gz", hash = "sha256:aec33d6d8f1225b495ee2cf20f0514f45e6df8e360bdd7ac9bace0b7ac5177ea", size = 23989880, upload-time = "2025-11-18T13:19:00.365Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f7/46/1eaa5db8d54a594bdade67afbcae42e9a2da676628be3eb39f36dcff6390/jupyterlab-4.4.10-py3-none-any.whl", hash = "sha256:65939ab4c8dcd0c42185c2d0d1a9d60b254dc8c46fc4fdb286b63c51e9358e07", size = 12293385, upload-time = "2025-10-22T14:50:54.075Z" },
{ url = "https://files.pythonhosted.org/packages/6c/1e/5a4d5498eba382fee667ed797cf64ae5d1b13b04356df62f067f48bb0f61/jupyterlab-4.5.0-py3-none-any.whl", hash = "sha256:88e157c75c1afff64c7dc4b801ec471450b922a4eae4305211ddd40da8201c8a", size = 12380641, upload-time = "2025-11-18T13:18:56.252Z" },
]
[[package]]
@ -2573,7 +2573,7 @@ wheels = [
[[package]]
name = "notebook"
version = "7.4.7"
version = "7.5.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "jupyter-server" },
@ -2582,9 +2582,9 @@ dependencies = [
{ name = "notebook-shim" },
{ name = "tornado" },
]
sdist = { url = "https://files.pythonhosted.org/packages/04/09/f6f64ba156842ef68d3ea763fa171a2f7e7224f200a15dd4af5b83c34756/notebook-7.4.7.tar.gz", hash = "sha256:3f0a04027dfcee8a876de48fba13ab77ec8c12f72f848a222ed7f5081b9e342a", size = 13937702, upload-time = "2025-09-27T08:00:22.536Z" }
sdist = { url = "https://files.pythonhosted.org/packages/89/ac/a97041621250a4fc5af379fb377942841eea2ca146aab166b8fcdfba96c2/notebook-7.5.0.tar.gz", hash = "sha256:3b27eaf9913033c28dde92d02139414c608992e1df4b969c843219acf2ff95e4", size = 14052074, upload-time = "2025-11-19T08:36:20.093Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6c/d7/06d13087e20388926e7423d2489e728d2e59f2453039cdb0574a7c070e76/notebook-7.4.7-py3-none-any.whl", hash = "sha256:362b7c95527f7dd3c4c84d410b782872fd9c734fb2524c11dd92758527b6eda6", size = 14342894, upload-time = "2025-09-27T08:00:18.496Z" },
{ url = "https://files.pythonhosted.org/packages/73/96/00df2a4760f10f5af0f45c4955573cae6189931f9a30265a35865f8c1031/notebook-7.5.0-py3-none-any.whl", hash = "sha256:3300262d52905ca271bd50b22617681d95f08a8360d099e097726e6d2efb5811", size = 14460968, upload-time = "2025-11-19T08:36:15.869Z" },
]
[[package]]
@ -3800,14 +3800,14 @@ wheels = [
[[package]]
name = "tinycss2"
version = "1.4.0"
version = "1.5.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "webencodings" },
]
sdist = { url = "https://files.pythonhosted.org/packages/7a/fd/7a5ee21fd08ff70d3d33a5781c255cbe779659bd03278feb98b19ee550f4/tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7", size = 87085, upload-time = "2024-10-24T14:58:29.895Z" }
sdist = { url = "https://files.pythonhosted.org/packages/a3/ae/2ca4913e5c0f09781d75482874c3a95db9105462a92ddd303c7d285d3df2/tinycss2-1.5.1.tar.gz", hash = "sha256:d339d2b616ba90ccce58da8495a78f46e55d4d25f9fd71dfd526f07e7d53f957", size = 88195, upload-time = "2025-11-23T10:29:10.082Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289", size = 26610, upload-time = "2024-10-24T14:58:28.029Z" },
{ url = "https://files.pythonhosted.org/packages/60/45/c7b5c3168458db837e8ceab06dc77824e18202679d0463f0e8f002143a97/tinycss2-1.5.1-py3-none-any.whl", hash = "sha256:3415ba0f5839c062696996998176c4a3751d18b7edaaeeb658c9ce21ec150661", size = 28404, upload-time = "2025-11-23T10:29:08.676Z" },
]
[[package]]