Security review fixes: admin permissions, guest sessions, payment edge cases, assistant leaks
- Admin: refund/cancel/mark-resolved/Bazaar-link actions need change permission; question and curriculum import need add/delete; content browser needs view_question; guest device ids are shown to superusers only. - Accounts: registering a guest's phone revokes the guest's earlier sessions; self-deletion keeps Redemption, UserOffer and the phone's OTP rows; the public demo guest cannot be deleted (DEMO_GUEST_DEVICE_IDS); display-name contact filter covers any separator and social handles. - Payment: callback without Authority is 400; a second Bazaar purchase on a paid order is 409; orders snapshot credits/hearts/days at creation (payment.0011). - Assistant: a broken diagram no longer makes a streamed answer free; a late off-topic marker refuses the answer (not stored, not cached); a disconnect saves the partial answer; only KNOWN_COLLECTIONS are searched. - Infra: secret-key file is created atomically (workers no longer split keys); no default INTERNAL_SERVICE_KEY; Kavenegar key and Bazaar token kept out of error logs; Swagger/ReDoc pinned; schema throttled; docker compose bound to 127.0.0.1; non-ASCII digit ids are 400; ticket text capped at 5000. - docs/security-before-production.md: remaining open items 24-31 and the guard tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1053,8 +1053,20 @@ def _normalize(obj):
|
||||
return obj
|
||||
|
||||
|
||||
# بزرگترین شکلِ معتبرِ سنجشها چند کیلوبایت بود؛ بیش از این نشانهی خروجیِ خراب یا دستکاریشده است.
|
||||
MAX_DIAGRAM_CHARS = 8000
|
||||
|
||||
|
||||
def parse(body: str) -> dict | None:
|
||||
"""
|
||||
شکلِ معتبر یا None. هیچ خطایی بیرون نمیرود: شکل اختیاری است، و خطایی که از اینجا بالا میرفت
|
||||
(OverflowError از عددِ ۴۰۰ رقمی، RecursionError از JSONِ خیلی تودرتو) در استریم کلِ جواب را
|
||||
«شکست» حساب میکرد و سوال را رایگان و بیثبت میگذاشت، در حالی که متن به کاربر رسیده بود.
|
||||
"""
|
||||
body = (body or '').strip()
|
||||
if len(body) > MAX_DIAGRAM_CHARS:
|
||||
logger.warning('diagram: بلوکِ شکل %s نویسه بود (سقف %s)، دور ریخته شد', len(body), MAX_DIAGRAM_CHARS)
|
||||
return None
|
||||
if body.startswith('```'):
|
||||
body = body.strip('`').removeprefix('json').strip()
|
||||
try:
|
||||
@@ -1062,6 +1074,9 @@ def parse(body: str) -> dict | None:
|
||||
except (json.JSONDecodeError, TypeError, ValueError):
|
||||
logger.info('diagram: JSONِ نامعتبر از مدل، دور ریخته شد')
|
||||
return None
|
||||
except Exception:
|
||||
logger.exception('diagram: خطای پیشبینینشده در خواندنِ شکل، دور ریخته شد')
|
||||
return None
|
||||
|
||||
|
||||
class StreamSplitter:
|
||||
|
||||
Reference in New Issue
Block a user