Improve auth process

This commit is contained in:
Urtzi Alfaro
2025-07-20 08:22:17 +02:00
parent 5f56c2fd00
commit 8486d1db7c
5 changed files with 331 additions and 287 deletions

View File

@@ -1,12 +1,13 @@
# services/tenant/app/models/tenants.py
# services/tenant/app/models/tenants.py - FIXED VERSION
"""
Tenant models for bakery management
Tenant models for bakery management - FIXED
Removed cross-service User relationship to eliminate circular dependencies
"""
from sqlalchemy import Column, String, Boolean, DateTime, Float, ForeignKey, Text
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import relationship
from datetime import datetime
from datetime import datetime, timezone
import uuid
from shared.database.base import Base
@@ -37,30 +38,30 @@ class Tenant(Base):
# ML status
model_trained = Column(Boolean, default=False)
last_training_date = Column(DateTime)
last_training_date = Column(DateTime(timezone=True))
# Ownership (The user who created the tenant, still a direct link)
# Ownership (user_id without FK - cross-service reference)
owner_id = Column(UUID(as_uuid=True), nullable=False, index=True)
# Timestamps
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
# Relationships
# Define the many-to-many relationship through TenantMember
# Relationships - only within tenant service
members = relationship("TenantMember", back_populates="tenant", cascade="all, delete-orphan")
users = relationship("User", secondary="tenant_members", back_populates="tenants")
# REMOVED: users relationship - no cross-service SQLAlchemy relationships
def __repr__(self):
return f"<Tenant(id={self.id}, name={self.name})>"
class TenantMember(Base):
"""Tenant membership model for team access - Association Table"""
"""Tenant membership model for team access"""
__tablename__ = "tenant_members"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
tenant_id = Column(UUID(as_uuid=True), ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False)
user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True) # Added ForeignKey to users.id
user_id = Column(UUID(as_uuid=True), nullable=False, index=True) # No FK - cross-service reference
# Role and permissions specific to this tenant
role = Column(String(50), default="member") # owner, admin, member, viewer
@@ -68,15 +69,48 @@ class TenantMember(Base):
# Status
is_active = Column(Boolean, default=True)
invited_by = Column(UUID(as_uuid=True))
invited_at = Column(DateTime, default=datetime.utcnow)
joined_at = Column(DateTime)
invited_by = Column(UUID(as_uuid=True)) # No FK - cross-service reference
invited_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
joined_at = Column(DateTime(timezone=True))
created_at = Column(DateTime, default=datetime.utcnow)
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
# Relationships to access the associated Tenant and User objects
# Relationships - only within tenant service
tenant = relationship("Tenant", back_populates="members")
user = relationship("User", back_populates="tenant_memberships") # Changed back_populates to avoid conflict
# REMOVED: user relationship - no cross-service SQLAlchemy relationships
def __repr__(self):
return f"<TenantMember(tenant_id={self.tenant_id}, user_id={self.user_id}, role={self.role})>"
return f"<TenantMember(tenant_id={self.tenant_id}, user_id={self.user_id}, role={self.role})>"
# Additional models for subscriptions, plans, etc.
class Subscription(Base):
"""Subscription model for tenant billing"""
__tablename__ = "subscriptions"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
tenant_id = Column(UUID(as_uuid=True), ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False)
plan = Column(String(50), default="basic") # basic, professional, enterprise
status = Column(String(50), default="active") # active, suspended, cancelled
# Billing
monthly_price = Column(Float, default=0.0)
billing_cycle = Column(String(20), default="monthly") # monthly, yearly
next_billing_date = Column(DateTime(timezone=True))
trial_ends_at = Column(DateTime(timezone=True))
# Limits
max_users = Column(Integer, default=1)
max_locations = Column(Integer, default=1)
max_products = Column(Integer, default=50)
# Timestamps
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
# Relationships
tenant = relationship("Tenant")
def __repr__(self):
return f"<Subscription(tenant_id={self.tenant_id}, plan={self.plan}, status={self.status})>"