import re from sqlalchemy import Boolean, Column, String from sqlalchemy.orm import validates from app.db.base_class import Base class User(Base): """ User model with flexible authentication (username or email). """ username = Column(String, unique=True, index=True, nullable=True) email = Column(String, unique=True, index=True, nullable=True) hashed_password = Column(String, nullable=False) is_active = Column(Boolean, default=True) is_superuser = Column(Boolean, default=False) @validates('email') def validate_email(self, key, email): if email is None: return email # Simple email validation regex if not re.match(r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$', email): raise ValueError('Invalid email format') return email @validates('username') def validate_username(self, key, username): if username is None: return username # Username validation: alphanumeric + underscore, 3-20 chars if not re.match(r'^[a-zA-Z0-9_]{3,20}$', username): raise ValueError( 'Username must be 3-20 characters and contain only letters, numbers, ' 'and underscores' ) return username