from datetime import datetime, timezone from app.extensions import db, bcrypt class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False, index=True) email = db.Column(db.String(255), unique=True, nullable=True) first_name = db.Column(db.String(100), nullable=True) last_name = db.Column(db.String(100), nullable=True) password_hash = db.Column(db.String(255), nullable=False) role = db.Column(db.String(20), default='user', nullable=False) # 'admin' or 'user' master_key_salt = db.Column(db.LargeBinary, nullable=True) # For password manager is_active = db.Column(db.Boolean, default=True, nullable=False) storage_quota_mb = db.Column(db.Integer, default=5120) # 5 GB default created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc)) updated_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) # Relationships files = db.relationship('File', backref='owner', lazy='dynamic', foreign_keys='File.owner_id') calendars = db.relationship('Calendar', backref='owner', lazy='dynamic') address_books = db.relationship('AddressBook', backref='owner', lazy='dynamic') task_lists = db.relationship('TaskList', backref='owner', lazy='dynamic') email_accounts = db.relationship('EmailAccount', backref='user', lazy='dynamic', order_by='EmailAccount.sort_order') password_folders = db.relationship('PasswordFolder', backref='owner', lazy='dynamic') def set_password(self, password): self.password_hash = bcrypt.generate_password_hash(password).decode('utf-8') def check_password(self, password): return bcrypt.check_password_hash(self.password_hash, password) @property def full_name(self) -> str: """Vor- + Nachname zusammengesetzt, sonst Leerstring.""" parts = [self.first_name or '', self.last_name or ''] return ' '.join(p.strip() for p in parts if p and p.strip()) @property def display_name(self) -> str: """Voller Name falls vorhanden, sonst Username.""" return self.full_name or self.username def to_dict(self, include_email=False): data = { 'id': self.id, 'username': self.username, 'first_name': self.first_name or '', 'last_name': self.last_name or '', 'full_name': self.full_name, 'display_name': self.display_name, 'role': self.role, 'is_active': self.is_active, 'storage_quota_mb': self.storage_quota_mb, 'created_at': self.created_at.isoformat() if self.created_at else None, } if include_email: data['email'] = self.email return data