hosting-platform/backend/app/models/user.py

124 lines
4.8 KiB
Python
Raw Normal View History

2026-01-11 14:38:39 +00:00
"""
User and Customer models for authentication and customer management
"""
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from app.models.domain import db
class User(db.Model):
"""Base user model for authentication"""
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255), unique=True, nullable=False, index=True)
password_hash = db.Column(db.String(255), nullable=False)
full_name = db.Column(db.String(255), nullable=False)
# Account status
is_active = db.Column(db.Boolean, default=True)
is_verified = db.Column(db.Boolean, default=False)
role = db.Column(db.String(20), default='customer') # 'customer' or 'admin'
# Timestamps
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
last_login = db.Column(db.DateTime, nullable=True)
# Verification
verification_token = db.Column(db.String(255), nullable=True)
reset_token = db.Column(db.String(255), nullable=True)
reset_token_expires = db.Column(db.DateTime, nullable=True)
# Relationships
customer = db.relationship('Customer', backref='user', uselist=False, cascade='all, delete-orphan')
def set_password(self, password):
"""Hash and set password"""
self.password_hash = generate_password_hash(password)
def check_password(self, password):
"""Verify password"""
return check_password_hash(self.password_hash, password)
def to_dict(self, include_sensitive=False):
"""Convert to dictionary"""
data = {
'id': self.id,
'email': self.email,
'full_name': self.full_name,
'role': self.role,
'is_active': self.is_active,
'is_verified': self.is_verified,
'created_at': self.created_at.isoformat() if self.created_at else None,
'last_login': self.last_login.isoformat() if self.last_login else None
}
if include_sensitive:
data['verification_token'] = self.verification_token
data['reset_token'] = self.reset_token
return data
def __repr__(self):
return f'<User {self.email}>'
class Customer(db.Model):
"""Customer profile extending User"""
__tablename__ = "customers"
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, unique=True)
# Company info
company_name = db.Column(db.String(255), nullable=True)
phone = db.Column(db.String(50), nullable=True)
# Billing
billing_address = db.Column(db.Text, nullable=True)
billing_city = db.Column(db.String(100), nullable=True)
billing_country = db.Column(db.String(100), nullable=True)
billing_postal_code = db.Column(db.String(20), nullable=True)
# Subscription
subscription_plan = db.Column(db.String(50), default='free') # free, basic, pro, enterprise
subscription_status = db.Column(db.String(20), default='active') # active, suspended, cancelled
subscription_started = db.Column(db.DateTime, default=datetime.utcnow)
subscription_expires = db.Column(db.DateTime, nullable=True)
# Limits
max_domains = db.Column(db.Integer, default=5)
max_containers = db.Column(db.Integer, default=3)
# Timestamps
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
domains = db.relationship('Domain', backref='customer', lazy='dynamic', foreign_keys='Domain.customer_id')
def to_dict(self):
"""Convert to dictionary"""
return {
'id': self.id,
'user_id': self.user_id,
'company_name': self.company_name,
'phone': self.phone,
'billing_address': self.billing_address,
'billing_city': self.billing_city,
'billing_country': self.billing_country,
'billing_postal_code': self.billing_postal_code,
'subscription_plan': self.subscription_plan,
'subscription_status': self.subscription_status,
'subscription_started': self.subscription_started.isoformat() if self.subscription_started else None,
'subscription_expires': self.subscription_expires.isoformat() if self.subscription_expires else None,
'max_domains': self.max_domains,
'max_containers': self.max_containers,
'created_at': self.created_at.isoformat() if self.created_at else None
}
def __repr__(self):
return f'<Customer {self.company_name or self.user.email}>'