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:
@@ -30,6 +30,12 @@ class Order(models.Model):
|
||||
# پیش از ۲۰۲۶-۱۰-۰۱ این دو را ندارند (null / خالی).
|
||||
list_price = models.PositiveIntegerField(null=True, blank=True)
|
||||
plan_title = models.CharField(max_length=50, blank=True)
|
||||
# آنچه این سفارش فروخته، در لحظهی ساخت (create_order). پرداخت و بازپرداخت همینها را میدهند و
|
||||
# پس میگیرند، نه عددهای فعلیِ پلن: پیشتر اگر ادمین پلن را بینِ ساختِ سفارش و پرداخت عوض میکرد،
|
||||
# خریدارِ بستهی ۴۵ هزار تومانی ۱۵۰ سوال میگرفت. null یعنی سفارشِ بیپلن یا ساختهشده پیش از این ستون.
|
||||
question_credits = models.PositiveIntegerField(null=True, blank=True)
|
||||
hearts_days = models.PositiveIntegerField(null=True, blank=True)
|
||||
duration_days = models.PositiveIntegerField(null=True, blank=True)
|
||||
currency = models.CharField(max_length=10, default='IRT')
|
||||
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='pending')
|
||||
provider = models.CharField(max_length=10, choices=PROVIDER_CHOICES, default='gateway')
|
||||
@@ -57,7 +63,8 @@ class Order(models.Model):
|
||||
class Transaction(models.Model):
|
||||
order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='transactions')
|
||||
gateway = models.CharField(max_length=30, default='zarinpal')
|
||||
gateway_ref_id = models.CharField(max_length=100, blank=True)
|
||||
# ۳۰۰ مثلِ Order.bazaar_purchase_token: توکنِ خریدِ بازار همینجا مینشیند.
|
||||
gateway_ref_id = models.CharField(max_length=300, blank=True)
|
||||
status = models.CharField(max_length=30)
|
||||
paid_at = models.DateTimeField(null=True, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
Reference in New Issue
Block a user