124 lines
4.8 KiB
Python
124 lines
4.8 KiB
Python
"""
|
|
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}>'
|
|
|