40 lines
1.5 KiB
Python
40 lines
1.5 KiB
Python
"""
|
|
User ORM model
|
|
"""
|
|
from sqlalchemy import Column, String, Integer, Boolean, TIMESTAMP, ForeignKey, Table
|
|
from sqlalchemy.sql import func
|
|
from sqlalchemy.orm import relationship
|
|
from app.database import Base
|
|
|
|
|
|
# Many-to-many relationship table: users <-> roles
|
|
user_roles = Table(
|
|
'user_roles',
|
|
Base.metadata,
|
|
Column('user_id', Integer, ForeignKey('users.id', ondelete='CASCADE'), primary_key=True),
|
|
Column('role_id', Integer, ForeignKey('roles.id', ondelete='CASCADE'), primary_key=True),
|
|
Column('created_at', TIMESTAMP, server_default=func.now()),
|
|
)
|
|
|
|
|
|
class User(Base):
|
|
"""User account"""
|
|
|
|
__tablename__ = "users"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
username = Column(String(50), unique=True, nullable=False, index=True, comment="Username (unique)")
|
|
password_hash = Column(String(255), nullable=False, comment="Password hash (bcrypt)")
|
|
email = Column(String(255), nullable=True, unique=True, index=True, comment="Email address")
|
|
full_name = Column(String(100), nullable=True, comment="Full name")
|
|
is_active = Column(Boolean, default=True, nullable=False, comment="Account active status")
|
|
created_at = Column(TIMESTAMP, server_default=func.now())
|
|
updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now())
|
|
last_login_at = Column(TIMESTAMP, nullable=True, comment="Last login time")
|
|
|
|
# Relationships
|
|
roles = relationship("Role", secondary=user_roles, back_populates="users")
|
|
|
|
def __repr__(self):
|
|
return f"<User(id={self.id}, username='{self.username}')>"
|