cleanup: trim bloated multi-line comments across the project
This commit is contained in:
@@ -12,13 +12,8 @@ from .models import Choice, Grade, Lesson, Node, NodeProgress, Question, Unit, U
|
||||
|
||||
|
||||
class LessonCompleteImpossibleCountTests(TestCase):
|
||||
"""
|
||||
🔒 تستِ رگرسیونِ فیکسِ امنیتی: LessonCompleteView قبلاً correctCount رو
|
||||
بدونِ مقایسه با تعدادِ واقعیِ سوالهای درس میپذیرفت، پس یک کلاینتِ
|
||||
مخرب میتونست با correctCount بزرگتر از تعدادِ واقعیِ سوالها،
|
||||
xp/coins متورم بگیره. این تست هم ردِ درخواستهای غیرممکن رو، هم
|
||||
رفتارِ صحیحِ تکمیل با مقادیرِ معتبر رو تضمین میکنه.
|
||||
"""
|
||||
"""رگرسیون: correctCount باید با تعدادِ واقعیِ سوالهای درس مقایسه بشه، وگرنه
|
||||
کلاینتِ مخرب میتونه xp/coins رو متورم کنه."""
|
||||
|
||||
def setUp(self):
|
||||
self.client = APIClient()
|
||||
@@ -67,14 +62,9 @@ class LessonCompleteImpossibleCountTests(TestCase):
|
||||
|
||||
|
||||
class LessonCompleteRatioIgnoresClientTotalQuestionsTests(TestCase):
|
||||
"""
|
||||
🔒 تستِ رگرسیونِ فیکسِ دوم: قبلاً ratio از totalQuestions ارسالیی
|
||||
خودِ کلاینت محاسبه میشد، نه از تعدادِ واقعیِ سوالهای درس. یعنی حتی
|
||||
بعد از سقفزدنِ correctCount، کلاینت میتونست با totalQuestions=1
|
||||
(بهجای ۳ سوالِ واقعی)، ratio رو مصنوعاً ۱۰۰٪ کنه و ۳ ستاره/coins
|
||||
کامل بگیره درحالیکه فقط ۱ از ۳ سوال رو درست جواب داده. حالا ratio
|
||||
همیشه بر اساسِ actual_question_count محاسبه میشه.
|
||||
"""
|
||||
"""رگرسیون: ratio باید از actual_question_count محاسبه بشه نه از totalQuestیِ
|
||||
ارسالیِ کلاینت، وگرنه حتی بعدِ سقفزدنِ correctCount کلاینت میتونه با
|
||||
totalQuestions دروغین ratio رو مصنوعاً ۱۰۰٪ کنه."""
|
||||
|
||||
def setUp(self):
|
||||
self.client = APIClient()
|
||||
@@ -114,13 +104,8 @@ class LessonCompleteRatioIgnoresClientTotalQuestionsTests(TestCase):
|
||||
|
||||
|
||||
class QuestionAnswerThrottleTests(TestCase):
|
||||
"""
|
||||
🔒 اثبات محدودیتِ جدیدِ per-user روی QuestionAnswerView
|
||||
(throttle_scope='question_answer'): Idempotency-Key فقط جلوی retry با
|
||||
همون کلید رو میگیره، نه حجمِ بالای درخواستهای *متفاوت* که هرکدوم
|
||||
یک UserAnswer جدید میسازن و منطقِ هارت/NodeProgress رو اجرا میکنن.
|
||||
ScopedRateThrottle با pk کاربرِ احرازهویتشده کلید میخوره، نه IP.
|
||||
"""
|
||||
"""محدودیتِ per-user روی QuestionAnswerView (throttle_scope='question_answer')؛
|
||||
Idempotency-Key فقط retry با همون کلید رو میگیره، نه حجمِ درخواستهای متفاوت."""
|
||||
|
||||
def setUp(self):
|
||||
from django.core.cache import cache
|
||||
@@ -242,14 +227,8 @@ class QuestionAnswerThrottleTests(TestCase):
|
||||
|
||||
|
||||
class LessonCompleteThrottleTests(TestCase):
|
||||
"""
|
||||
🔒 اثبات محدودیتِ جدیدِ per-user روی LessonCompleteView
|
||||
(throttle_scope='lesson_complete'): Idempotency-Key فقط جلوی retry با
|
||||
همون کلید رو میگیره، نه حجمِ بالای درخواستهای *متفاوت* که هرکدوم
|
||||
یک UserLessonCompletion جدید میسازن و سیگنالِ post_save
|
||||
(NodeProgress) + بهروزرسانیِ UserStats رو اجرا میکنن.
|
||||
ScopedRateThrottle با pk کاربرِ احرازهویتشده کلید میخوره، نه IP.
|
||||
"""
|
||||
"""محدودیتِ per-user روی LessonCompleteView (throttle_scope='lesson_complete')؛
|
||||
Idempotency-Key فقط retry با همون کلید رو میگیره، نه حجمِ درخواستهای متفاوت."""
|
||||
|
||||
def setUp(self):
|
||||
from django.core.cache import cache
|
||||
@@ -361,17 +340,9 @@ class LessonCompleteThrottleTests(TestCase):
|
||||
|
||||
|
||||
class QuestionAnswerGuestThrottleBypassTests(TestCase):
|
||||
"""
|
||||
🔒 اثبات فیکسِ امنیتی: قبلاً کلیدِ throttle_scope='question_answer' برای
|
||||
هر کاربرِ احرازهویتشده (مهمان یا نه) user.pk بود. چون GuestSessionView
|
||||
با هر deviceId جدید یک کاربرِ مهمانِ تازه (pk جدید) میسازه، یک مهاجم
|
||||
میتونست با ساختنِ پیدرپیِ حسابهای مهمان، هر بار یک bucket throttle
|
||||
تازه بگیره و منطقِ هارت/NodeProgress رو بیمحدودیت اجرا کنه. حالا
|
||||
GuestAwareContentThrottle برای کاربرهای مهمان کلید رو بر اساسِ IP
|
||||
(همون get_ident که guest_session هم استفاده میکنه) میسازه، پس چرخشِ
|
||||
حساب مهمان دیگه bucket تازه نمیده. رفتارِ throttle برای کاربرِ
|
||||
غیرمهمان (per-user، مثلِ قبل) دستنخورده مونده.
|
||||
"""
|
||||
"""اثباتِ فیکسِ throttle: چرخشِ حساب مهمان (هر deviceId یه pk تازه) نباید
|
||||
bucket تازهی question_answer بده — GuestAwareContentThrottle برای
|
||||
مهمانها کلید رو بر اساسِ IP میسازه، نه user.pk."""
|
||||
|
||||
def setUp(self):
|
||||
from django.core.cache import cache
|
||||
@@ -446,17 +417,9 @@ class QuestionAnswerGuestThrottleBypassTests(TestCase):
|
||||
|
||||
|
||||
class LessonCompleteGuestThrottleBypassTests(TestCase):
|
||||
"""
|
||||
🔒 اثبات فیکسِ امنیتی: قبلاً کلیدِ throttle_scope='lesson_complete' برای
|
||||
هر کاربرِ احرازهویتشده (مهمان یا نه) user.pk بود. چون GuestSessionView
|
||||
با هر deviceId جدید یک کاربرِ مهمانِ تازه (pk جدید) میسازه، یک مهاجم
|
||||
میتونست با ساختنِ پیدرپیِ حسابهای مهمان، هر بار یک bucket throttle
|
||||
تازه بگیره و UserLessonCompletion/xp/coins/progress رو بیمحدودیت
|
||||
تولید کنه. حالا GuestAwareContentThrottle برای کاربرهای مهمان کلید رو
|
||||
بر اساسِ IP میسازه، پس چرخشِ حساب مهمان دیگه bucket تازه نمیده.
|
||||
رفتارِ throttle برای کاربرِ غیرمهمان (per-user، مثلِ قبل) دستنخورده
|
||||
مونده.
|
||||
"""
|
||||
"""اثباتِ فیکسِ throttle: چرخشِ حساب مهمان نباید bucket تازهی
|
||||
lesson_complete بده — GuestAwareContentThrottle برای مهمانها کلید رو
|
||||
بر اساسِ IP میسازه، نه user.pk."""
|
||||
|
||||
def setUp(self):
|
||||
from django.core.cache import cache
|
||||
|
||||
Reference in New Issue
Block a user