UNLOCK_ALL_PHONES: tester accounts see every island unlocked (map and server rule)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 11:12:13 +03:30
parent 33478179e2
commit 3187f69714
3 changed files with 52 additions and 0 deletions

View File

@@ -190,6 +190,19 @@ class NodeIsUnlockedMatchesHomeTests(_World, TestCase):
self._assert_matches_home('بعد از درس‌های جزیره‌ی دو')
self.assertEqual(self.statuses()['سه'], 'unlocked')
def test_tester_phone_has_every_node_unlocked_on_map_and_server(self):
"""UNLOCK_ALL_PHONES: نقشه و قفلِ سرور هر دو باز؛ کاربرِ دیگر همان قفلِ عادی را دارد.
فقط قفلِ ترتیب را سنجیده؛ اشتراکِ فصل‌ها دست نمی‌خورد (تستش جای دیگر است)."""
from django.test import override_settings
self.assertEqual(self.statuses()['سه'], 'locked')
self.assertFalse(node_is_unlocked(self.user.id, self.n3))
with override_settings(UNLOCK_ALL_PHONES=frozenset({self.user.phone})):
self.assertNotIn('locked', self.statuses().values())
self.assertTrue(node_is_unlocked(self.user.id, self.n3))
with override_settings(UNLOCK_ALL_PHONES=frozenset({'09129999999'})):
self.assertEqual(self.statuses()['سه'], 'locked')
self.assertFalse(node_is_unlocked(self.user.id, self.n3))
def test_a_node_missing_from_the_tree_is_locked_and_logged(self):
ghost = Node(id=999999, unit=self.unit, title='شبح', order=9)
with self.assertLogs('content.views', level='WARNING'):

View File

@@ -263,6 +263,18 @@ def answers_missing_response(answered: int, required: int) -> Response:
)
def user_has_all_nodes_unlocked(user_id) -> bool:
"""
کاربرِ آزمونگر (`settings.UNLOCK_ALL_PHONES`): قفلِ ترتیبِ جزیره‌ها برایش برداشته می‌شود.
وقتی فهرست خالی است (حالتِ عادی) هیچ کوئری‌ای زده نمی‌شود.
"""
from django.conf import settings
if user_id is None or not settings.UNLOCK_ALL_PHONES:
return False
from accounts.models import User
return User.objects.filter(pk=user_id, phone__in=settings.UNLOCK_ALL_PHONES).exists()
def node_is_unlocked(user_id, node) -> bool:
"""
آیا این جزیره برای این کاربر روی نقشه قفل نیست؟ همان قاعده‌ی `HomeView` است
@@ -273,6 +285,8 @@ def node_is_unlocked(user_id, node) -> bool:
اگر جزیره در درختِ کش‌شده نبود (مثلاً تازه ساخته شده و کش کهنه است) «قفل» حساب می‌شود
و در لاگ WARNING می‌ماند؛ همان‌طور که نقشه هم آن را نشان نمی‌دهد.
"""
if user_has_all_nodes_unlocked(user_id):
return True
tree = _grade_tree(node.unit.grade_id) or []
unit = next((u for u in tree if u['id'] == str(node.unit_id)), None)
if unit is not None:
@@ -455,6 +469,7 @@ class HomeView(APIView):
from subscription.services import has_active_subscription
subscribed = user_id is not None and has_active_subscription(user_id)
unlock_all = user_has_all_nodes_unlocked(user_id)
units_payload = []
for index, unit in enumerate(tree):
node_payload = []
@@ -471,6 +486,8 @@ class HomeView(APIView):
)
if node_status != 'completed':
unlock_next = False
if unlock_all and node_status == 'locked':
node_status = 'unlocked'
node_payload.append({
'id': node['id'],
'title': node['title'],