Files
2025-11-18 03:36:49 +08:00

81 lines
3.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
display_name = models.CharField(max_length=100, blank=True, default='')
contact_phone = models.CharField(max_length=30, blank=True, default='')
default_free_traffic_gb_per_domain_override = models.PositiveIntegerField(null=True, blank=True)
class Meta:
verbose_name = '用户资料'
verbose_name_plural = '用户资料'
def __str__(self):
return self.display_name or self.user.get_username()
# Create your models here.
class LoginRecord(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='login_records')
ip_address = models.GenericIPAddressField(null=True, blank=True)
user_agent = models.CharField(max_length=255, blank=True, default='')
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = '登录历史'
verbose_name_plural = '登录历史'
ordering = ['-created_at']
def __str__(self):
return f"{self.user.get_username()} @ {self.created_at}"
class LoginThrottle(models.Model):
user = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL, related_name='login_throttles')
ip_address = models.GenericIPAddressField(null=True, blank=True)
fail_count = models.PositiveIntegerField(default=0)
total_fail_count = models.PositiveIntegerField(default=0)
last_failed_at = models.DateTimeField(null=True, blank=True)
banned_until = models.DateTimeField(null=True, blank=True)
note = models.CharField(max_length=255, blank=True, default='')
class Meta:
verbose_name = '登录节流'
verbose_name_plural = '登录节流'
ordering = ['-last_failed_at']
indexes = [
models.Index(fields=['ip_address']),
models.Index(fields=['user']),
models.Index(fields=['banned_until']),
]
def is_banned(self):
from django.utils import timezone
return bool(self.banned_until and self.banned_until > timezone.now())
def register_failure(self, ban_threshold=5, ban_minutes=15):
from django.utils import timezone
from datetime import timedelta
now = timezone.now()
self.fail_count += 1
self.total_fail_count += 1
self.last_failed_at = now
if self.fail_count >= ban_threshold:
self.banned_until = now + timedelta(minutes=int(ban_minutes))
self.note = f'自动封禁 {int(ban_minutes)} 分钟(超过失败阈值 {int(ban_threshold)}'
self.fail_count = 0
self.save(update_fields=['fail_count', 'total_fail_count', 'last_failed_at', 'banned_until', 'note'])
def register_success(self):
if self.fail_count or self.banned_until:
self.fail_count = 0
self.banned_until = None
self.note = ''
self.save(update_fields=['fail_count', 'banned_until', 'note'])