test
This commit is contained in:
@@ -12,7 +12,7 @@ from django.db.models import Count, Q
|
|||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
import qrcode
|
import qrcode
|
||||||
from otpauth import OtpAuth
|
from otpauth import TOTP
|
||||||
|
|
||||||
from problem.models import Problem
|
from problem.models import Problem
|
||||||
from submission.models import Submission, JudgeStatus
|
from submission.models import Submission, JudgeStatus
|
||||||
@@ -143,7 +143,7 @@ class TwoFactorAuthAPI(APIView):
|
|||||||
|
|
||||||
label = f"{SysOptions.website_name_shortcut}:{user.username}"
|
label = f"{SysOptions.website_name_shortcut}:{user.username}"
|
||||||
image = qrcode.make(
|
image = qrcode.make(
|
||||||
OtpAuth(token).to_uri(
|
TOTP(token).to_uri(
|
||||||
"totp", label, SysOptions.website_name.replace(" ", "")
|
"totp", label, SysOptions.website_name.replace(" ", "")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -157,7 +157,7 @@ class TwoFactorAuthAPI(APIView):
|
|||||||
"""
|
"""
|
||||||
code = request.data["code"]
|
code = request.data["code"]
|
||||||
user = request.user
|
user = request.user
|
||||||
if OtpAuth(user.tfa_token).valid_totp(code):
|
if TOTP(user.tfa_token).verify(code):
|
||||||
user.two_factor_auth = True
|
user.two_factor_auth = True
|
||||||
user.save()
|
user.save()
|
||||||
return self.success("Succeeded")
|
return self.success("Succeeded")
|
||||||
@@ -171,7 +171,7 @@ class TwoFactorAuthAPI(APIView):
|
|||||||
user = request.user
|
user = request.user
|
||||||
if not user.two_factor_auth:
|
if not user.two_factor_auth:
|
||||||
return self.error("2FA is already turned off")
|
return self.error("2FA is already turned off")
|
||||||
if OtpAuth(user.tfa_token).valid_totp(code):
|
if TOTP(user.tfa_token).verify(code):
|
||||||
user.two_factor_auth = False
|
user.two_factor_auth = False
|
||||||
user.save()
|
user.save()
|
||||||
return self.success("Succeeded")
|
return self.success("Succeeded")
|
||||||
@@ -216,7 +216,7 @@ class UserLoginAPI(APIView):
|
|||||||
if user.two_factor_auth and "tfa_code" not in data:
|
if user.two_factor_auth and "tfa_code" not in data:
|
||||||
return self.error("tfa_required")
|
return self.error("tfa_required")
|
||||||
|
|
||||||
if OtpAuth(user.tfa_token).valid_totp(data["tfa_code"]):
|
if TOTP(user.tfa_token).verify(data["tfa_code"]):
|
||||||
auth.login(request, user)
|
auth.login(request, user)
|
||||||
return self.success("Succeeded")
|
return self.success("Succeeded")
|
||||||
else:
|
else:
|
||||||
@@ -287,7 +287,7 @@ class UserChangeEmailAPI(APIView):
|
|||||||
if user.two_factor_auth:
|
if user.two_factor_auth:
|
||||||
if "tfa_code" not in data:
|
if "tfa_code" not in data:
|
||||||
return self.error("tfa_required")
|
return self.error("tfa_required")
|
||||||
if not OtpAuth(user.tfa_token).valid_totp(data["tfa_code"]):
|
if not TOTP(user.tfa_token).verify(data["tfa_code"]):
|
||||||
return self.error("Invalid two factor verification code")
|
return self.error("Invalid two factor verification code")
|
||||||
data["new_email"] = data["new_email"].lower()
|
data["new_email"] = data["new_email"].lower()
|
||||||
if User.objects.filter(email=data["new_email"]).exists():
|
if User.objects.filter(email=data["new_email"]).exists():
|
||||||
@@ -313,7 +313,7 @@ class UserChangePasswordAPI(APIView):
|
|||||||
if user.two_factor_auth:
|
if user.two_factor_auth:
|
||||||
if "tfa_code" not in data:
|
if "tfa_code" not in data:
|
||||||
return self.error("tfa_required")
|
return self.error("tfa_required")
|
||||||
if not OtpAuth(user.tfa_token).valid_totp(data["tfa_code"]):
|
if not TOTP(user.tfa_token).verify(data["tfa_code"]):
|
||||||
return self.error("Invalid two factor verification code")
|
return self.error("Invalid two factor verification code")
|
||||||
user.set_password(data["new_password"])
|
user.set_password(data["new_password"])
|
||||||
user.save()
|
user.save()
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ django-dramatiq==0.13.0
|
|||||||
django-redis==5.4.0
|
django-redis==5.4.0
|
||||||
djangorestframework==3.16.0
|
djangorestframework==3.16.0
|
||||||
dramatiq==1.18.0
|
dramatiq==1.18.0
|
||||||
|
envelopes==0.4
|
||||||
gunicorn==23.0.0
|
gunicorn==23.0.0
|
||||||
idna==3.10
|
idna==3.10
|
||||||
otpauth==2.2.1
|
otpauth==2.2.1
|
||||||
@@ -15,10 +16,12 @@ pillow==11.2.1
|
|||||||
prometheus-client==0.22.1
|
prometheus-client==0.22.1
|
||||||
psycopg==3.2.9
|
psycopg==3.2.9
|
||||||
psycopg-binary==3.2.9
|
psycopg-binary==3.2.9
|
||||||
|
python-dateutil==2.9.0.post0
|
||||||
qrcode==8.2
|
qrcode==8.2
|
||||||
raven==6.10.0
|
raven==6.10.0
|
||||||
redis==6.2.0
|
redis==6.2.0
|
||||||
requests==2.32.4
|
requests==2.32.4
|
||||||
|
six==1.17.0
|
||||||
sqlparse==0.5.3
|
sqlparse==0.5.3
|
||||||
typing-extensions==4.14.0
|
typing-extensions==4.14.0
|
||||||
urllib3==2.4.0
|
urllib3==2.4.0
|
||||||
|
|||||||
@@ -10,11 +10,13 @@ dependencies = [
|
|||||||
"django-dramatiq>=0.13.0",
|
"django-dramatiq>=0.13.0",
|
||||||
"django-redis>=5.4.0",
|
"django-redis>=5.4.0",
|
||||||
"djangorestframework>=3.16.0",
|
"djangorestframework>=3.16.0",
|
||||||
|
"envelopes>=0.4",
|
||||||
"gunicorn>=23.0.0",
|
"gunicorn>=23.0.0",
|
||||||
"otpauth>=2.2.1",
|
"otpauth>=2.2.1",
|
||||||
"pillow>=11.2.1",
|
"pillow>=11.2.1",
|
||||||
"psycopg>=3.2.9",
|
"psycopg>=3.2.9",
|
||||||
"psycopg-binary>=3.2.9",
|
"psycopg-binary>=3.2.9",
|
||||||
|
"python-dateutil>=2.9.0.post0",
|
||||||
"qrcode>=8.2",
|
"qrcode>=8.2",
|
||||||
"raven>=6.10.0",
|
"raven>=6.10.0",
|
||||||
"requests>=2.32.4",
|
"requests>=2.32.4",
|
||||||
|
|||||||
31
uv.lock
generated
31
uv.lock
generated
@@ -136,6 +136,12 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/ac/00/d9ea755cdeda3d498504775b62122b72ba282b91446fd58980171fb1084c/dramatiq-1.18.0-py3-none-any.whl", hash = "sha256:d360f608aa3cd06f5db714bfcd23825dc7098bacfee52aca536b0bb0faae3c69", size = 121231, upload-time = "2025-05-30T12:00:30.199Z" },
|
{ url = "https://files.pythonhosted.org/packages/ac/00/d9ea755cdeda3d498504775b62122b72ba282b91446fd58980171fb1084c/dramatiq-1.18.0-py3-none-any.whl", hash = "sha256:d360f608aa3cd06f5db714bfcd23825dc7098bacfee52aca536b0bb0faae3c69", size = 121231, upload-time = "2025-05-30T12:00:30.199Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "envelopes"
|
||||||
|
version = "0.4"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/2e/ac/0aaba34d717868729428bf4dca601c93cd6b0f9123894f2509911027b0dd/Envelopes-0.4.tar.gz", hash = "sha256:a4a02b4dc21467794d3a646f946d99a8c5b3311b2df8e211f96ca9e0b838e7e0", size = 33450, upload-time = "2013-11-13T20:02:09.033Z" }
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gunicorn"
|
name = "gunicorn"
|
||||||
version = "23.0.0"
|
version = "23.0.0"
|
||||||
@@ -167,11 +173,13 @@ dependencies = [
|
|||||||
{ name = "django-dramatiq" },
|
{ name = "django-dramatiq" },
|
||||||
{ name = "django-redis" },
|
{ name = "django-redis" },
|
||||||
{ name = "djangorestframework" },
|
{ name = "djangorestframework" },
|
||||||
|
{ name = "envelopes" },
|
||||||
{ name = "gunicorn" },
|
{ name = "gunicorn" },
|
||||||
{ name = "otpauth" },
|
{ name = "otpauth" },
|
||||||
{ name = "pillow" },
|
{ name = "pillow" },
|
||||||
{ name = "psycopg" },
|
{ name = "psycopg" },
|
||||||
{ name = "psycopg-binary" },
|
{ name = "psycopg-binary" },
|
||||||
|
{ name = "python-dateutil" },
|
||||||
{ name = "qrcode" },
|
{ name = "qrcode" },
|
||||||
{ name = "raven" },
|
{ name = "raven" },
|
||||||
{ name = "requests" },
|
{ name = "requests" },
|
||||||
@@ -185,11 +193,13 @@ requires-dist = [
|
|||||||
{ name = "django-dramatiq", specifier = ">=0.13.0" },
|
{ name = "django-dramatiq", specifier = ">=0.13.0" },
|
||||||
{ name = "django-redis", specifier = ">=5.4.0" },
|
{ name = "django-redis", specifier = ">=5.4.0" },
|
||||||
{ name = "djangorestframework", specifier = ">=3.16.0" },
|
{ name = "djangorestframework", specifier = ">=3.16.0" },
|
||||||
|
{ name = "envelopes", specifier = ">=0.4" },
|
||||||
{ name = "gunicorn", specifier = ">=23.0.0" },
|
{ name = "gunicorn", specifier = ">=23.0.0" },
|
||||||
{ name = "otpauth", specifier = ">=2.2.1" },
|
{ name = "otpauth", specifier = ">=2.2.1" },
|
||||||
{ name = "pillow", specifier = ">=11.2.1" },
|
{ name = "pillow", specifier = ">=11.2.1" },
|
||||||
{ name = "psycopg", specifier = ">=3.2.9" },
|
{ name = "psycopg", specifier = ">=3.2.9" },
|
||||||
{ name = "psycopg-binary", specifier = ">=3.2.9" },
|
{ name = "psycopg-binary", specifier = ">=3.2.9" },
|
||||||
|
{ name = "python-dateutil", specifier = ">=2.9.0.post0" },
|
||||||
{ name = "qrcode", specifier = ">=8.2" },
|
{ name = "qrcode", specifier = ">=8.2" },
|
||||||
{ name = "raven", specifier = ">=6.10.0" },
|
{ name = "raven", specifier = ">=6.10.0" },
|
||||||
{ name = "requests", specifier = ">=2.32.4" },
|
{ name = "requests", specifier = ">=2.32.4" },
|
||||||
@@ -306,6 +316,18 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/7b/1d/bf54cfec79377929da600c16114f0da77a5f1670f45e0c3af9fcd36879bc/psycopg_binary-3.2.9-cp313-cp313-win_amd64.whl", hash = "sha256:2290bc146a1b6a9730350f695e8b670e1d1feb8446597bed0bbe7c3c30e0abcb", size = 2928009, upload-time = "2025-05-13T16:08:53.67Z" },
|
{ url = "https://files.pythonhosted.org/packages/7b/1d/bf54cfec79377929da600c16114f0da77a5f1670f45e0c3af9fcd36879bc/psycopg_binary-3.2.9-cp313-cp313-win_amd64.whl", hash = "sha256:2290bc146a1b6a9730350f695e8b670e1d1feb8446597bed0bbe7c3c30e0abcb", size = 2928009, upload-time = "2025-05-13T16:08:53.67Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "python-dateutil"
|
||||||
|
version = "2.9.0.post0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "six" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "qrcode"
|
name = "qrcode"
|
||||||
version = "8.2"
|
version = "8.2"
|
||||||
@@ -351,6 +373,15 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" },
|
{ url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "six"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlparse"
|
name = "sqlparse"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
|
|||||||
Reference in New Issue
Block a user