saas-market-analysis-dubai/apps/users/models.py
2025-09-17 03:04:22 +05:30

140 lines
4.7 KiB
Python

"""
User models for the Dubai Analytics Platform.
"""
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils import timezone
import uuid
import secrets
class User(AbstractUser):
"""Custom user model with additional fields for the platform."""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
email = models.EmailField(unique=True)
subscription_type = models.CharField(
max_length=20,
choices=[
('free', 'Free'),
('paid', 'Paid'),
('premium', 'Premium'),
],
default='free'
)
api_key = models.CharField(max_length=64, unique=True, blank=True, null=True)
is_api_enabled = models.BooleanField(default=False)
last_api_usage = models.DateTimeField(null=True, blank=True)
company_name = models.CharField(max_length=255, blank=True)
phone_number = models.CharField(max_length=20, blank=True)
is_verified = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
class Meta:
db_table = 'users'
def __str__(self):
return f"{self.email} ({self.subscription_type})"
def save(self, *args, **kwargs):
# Generate API key if not exists and API is enabled
if self.is_api_enabled and not self.api_key:
self.api_key = self.generate_api_key()
super().save(*args, **kwargs)
def generate_api_key(self):
"""Generate a secure API key."""
return secrets.token_urlsafe(32)
def get_usage_limits(self):
"""Get usage limits based on subscription type."""
from django.conf import settings
return settings.BILLING_SETTINGS.get(f'{self.subscription_type.upper()}_TIER_LIMITS', {})
def can_make_api_call(self):
"""Check if user can make an API call based on their limits."""
if not self.is_api_enabled:
return False
limits = self.get_usage_limits()
if not limits:
return False
# This would need to be implemented with actual usage tracking
# For now, return True if user has API enabled
return True
class UserProfile(models.Model):
"""Extended user profile information."""
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
avatar = models.ImageField(upload_to='avatars/', blank=True, null=True)
bio = models.TextField(blank=True)
website = models.URLField(blank=True)
location = models.CharField(max_length=255, blank=True)
timezone = models.CharField(max_length=50, default='Asia/Dubai')
language = models.CharField(max_length=10, default='en')
notification_preferences = models.JSONField(default=dict)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'user_profiles'
def __str__(self):
return f"{self.user.email} Profile"
class UserSession(models.Model):
"""Track user sessions for security."""
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sessions')
session_key = models.CharField(max_length=40, unique=True)
ip_address = models.GenericIPAddressField()
user_agent = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
last_activity = models.DateTimeField(auto_now=True)
is_active = models.BooleanField(default=True)
class Meta:
db_table = 'user_sessions'
indexes = [
models.Index(fields=['user', 'is_active']),
models.Index(fields=['session_key']),
]
def __str__(self):
return f"{self.user.email} - {self.session_key[:8]}..."
class APIKey(models.Model):
"""API keys for programmatic access."""
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='api_keys')
name = models.CharField(max_length=100)
key = models.CharField(max_length=64, unique=True)
is_active = models.BooleanField(default=True)
last_used = models.DateTimeField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
expires_at = models.DateTimeField(null=True, blank=True)
class Meta:
db_table = 'api_keys'
indexes = [
models.Index(fields=['user', 'is_active']),
models.Index(fields=['key']),
]
def __str__(self):
return f"{self.user.email} - {self.name}"
def is_expired(self):
"""Check if API key is expired."""
if not self.expires_at:
return False
return timezone.now() > self.expires_at
def is_valid(self):
"""Check if API key is valid."""
return self.is_active and not self.is_expired()