Kavenegar is being switched on, so every OTP request now costs credit: - phone numbers are normalised to 09XXXXXXXXX everywhere (login, OTP, family invite, TEST_LOGIN_PHONES keys) and existing rows are migrated; non-Iranian and landline numbers are rejected before any SMS - cooldown and a daily per-phone cap are counted in the database, so the three gunicorn workers no longer triple them - a global daily OTP SMS cap (default 300) stops SMS pumping - per-IP rates widened for CGNAT / school Wi-Fi (env-overridable) - provider message id is logged; SMS text warns not to share the code Second audit round: an offer no longer shortens a longer paid plan, Zarinpal error bodies no longer 500, island XP reaches the parent report, a non-numeric questionId no longer 500s after the answer is generated. 596 tests green. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
41 lines
1.8 KiB
Python
41 lines
1.8 KiB
Python
"""
|
||
شمارههای موجود را به همان شکلِ 09XXXXXXXXX میبرد که serializerها حالا میسازند
|
||
(accounts/phone.py)؛ وگرنه کسی که با +98… ثبتنام کرده بود دیگر به حسابِ خودش
|
||
نمیرسید و حسابِ تازه میگرفت.
|
||
|
||
ردیفی که شکلِ نرمالش از قبل مالِ کاربرِ دیگری است دست نمیخورد (unique است و
|
||
ادغامِ دو حساب تصمیمِ انسانی است)؛ ردیفی هم که موبایلِ ایران نیست همانطور میماند.
|
||
هر دو فقط شمرده و چاپ میشوند. برگشتناپذیر است چون شکلِ قبلی ذخیره نمیشود.
|
||
"""
|
||
from django.db import migrations
|
||
|
||
|
||
def normalize(apps, schema_editor):
|
||
from accounts.phone import normalize_phone
|
||
|
||
User = apps.get_model('accounts', 'User')
|
||
changed = skipped_taken = skipped_invalid = 0
|
||
for user in User.objects.exclude(phone__isnull=True).exclude(phone=''):
|
||
target = normalize_phone(user.phone)
|
||
if target is None:
|
||
skipped_invalid += 1
|
||
elif target != user.phone:
|
||
if User.objects.filter(phone=target).exists():
|
||
skipped_taken += 1
|
||
else:
|
||
User.objects.filter(pk=user.pk).update(phone=target)
|
||
changed += 1
|
||
if changed or skipped_taken or skipped_invalid:
|
||
print(f'\n normalize phones: changed={changed} taken={skipped_taken} invalid={skipped_invalid}')
|
||
|
||
|
||
class Migration(migrations.Migration):
|
||
|
||
dependencies = [
|
||
('accounts', '0004_otpcode_failed_attempts_user_tokens_valid_after'),
|
||
]
|
||
|
||
operations = [
|
||
migrations.RunPython(normalize, migrations.RunPython.noop),
|
||
]
|