Files
bugsink/phonehome/models.py
Klaas van Schelven e363917e9c Per-month quota for email-sending
Fix #34
2025-07-28 14:41:32 +02:00

50 lines
1.8 KiB
Python

import json
import uuid
from django.db import models
from bugsink.transaction import immediate_atomic
from bugsink.app_settings import get_settings
class Installation(models.Model):
# "Installation" would probably be better at home in some different app, especially now that we're adding more and
# more stuff to it. But cross-app migrations are annoying enough and the upside is _very_ limited so it stays here.
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
created_at = models.DateTimeField(auto_now_add=True)
silence_email_system_warning = models.BooleanField(default=False)
email_quota_usage = models.TextField(null=False, default='{"per_month": {}}')
@classmethod
@immediate_atomic(only_if_needed=True) # minimalize write-lock-hogging (while being callable within atomic blocks)
def check_and_inc_email_quota(cls, date):
obj = cls.objects.first()
email_quota_usage = json.loads(obj.email_quota_usage)
key = date.strftime('%Y-%m')
if key not in email_quota_usage["per_month"]:
email_quota_usage['per_month'] = {key: 0} # full overwrite: no need to keep old info around.
if (get_settings().MAX_EMAILS_PER_MONTH is not None
and email_quota_usage['per_month'][key] >= get_settings().MAX_EMAILS_PER_MONTH):
return False
email_quota_usage['per_month'][key] += 1
obj.email_quota_usage = json.dumps(email_quota_usage)
obj.save()
return True
class OutboundMessage(models.Model):
attempted_at = models.DateTimeField(auto_now_add=True)
sent_at = models.DateTimeField(null=True)
message = models.TextField()
def __str__(self):
return f"OutboundMessage(attempted_at={self.attempted_at}, sent_at={self.sent_at})"