diff --git a/surfsense_backend/alembic/versions/42_drop_user_search_space_preferences.py b/surfsense_backend/alembic/versions/42_drop_user_search_space_preferences.py new file mode 100644 index 000000000..3ce491cfc --- /dev/null +++ b/surfsense_backend/alembic/versions/42_drop_user_search_space_preferences.py @@ -0,0 +1,41 @@ +"""Drop user_search_space_preferences table + +Revision ID: 42 +Revises: 41 +Create Date: 2025-11-28 + +This table is no longer needed after RBAC implementation: +- LLM preferences are now stored on SearchSpace directly +- User-SearchSpace relationships are handled by SearchSpaceMembership +""" + +import sqlalchemy as sa + +from alembic import op + +# revision identifiers, used by Alembic. +revision = "42" +down_revision = "41" +branch_labels = None +depends_on = None + + +def upgrade(): + # Drop the user_search_space_preferences table + op.drop_table("user_search_space_preferences") + + +def downgrade(): + # Recreate the table if rolling back + op.create_table( + "user_search_space_preferences", + sa.Column("id", sa.Integer(), primary_key=True), + sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now()), + sa.Column("user_id", sa.UUID(), sa.ForeignKey("user.id", ondelete="CASCADE"), nullable=False), + sa.Column("search_space_id", sa.Integer(), sa.ForeignKey("searchspaces.id", ondelete="CASCADE"), nullable=False), + sa.Column("long_context_llm_id", sa.Integer(), nullable=True), + sa.Column("fast_llm_id", sa.Integer(), nullable=True), + sa.Column("strategic_llm_id", sa.Integer(), nullable=True), + sa.UniqueConstraint("user_id", "search_space_id", name="uq_user_searchspace"), + ) + diff --git a/surfsense_backend/app/db.py b/surfsense_backend/app/db.py index 6195bec87..f5a8fd20f 100644 --- a/surfsense_backend/app/db.py +++ b/surfsense_backend/app/db.py @@ -441,11 +441,6 @@ class SearchSpace(BaseModel, TimestampMixin): order_by="LLMConfig.id", cascade="all, delete-orphan", ) - user_preferences = relationship( - "UserSearchSpacePreference", - back_populates="search_space", - cascade="all, delete-orphan", - ) # RBAC relationships roles = relationship( @@ -527,36 +522,6 @@ class LLMConfig(BaseModel, TimestampMixin): search_space = relationship("SearchSpace", back_populates="llm_configs") -class UserSearchSpacePreference(BaseModel, TimestampMixin): - __tablename__ = "user_search_space_preferences" - __table_args__ = ( - UniqueConstraint( - "user_id", - "search_space_id", - name="uq_user_searchspace", - ), - ) - - user_id = Column( - UUID(as_uuid=True), ForeignKey("user.id", ondelete="CASCADE"), nullable=False - ) - search_space_id = Column( - Integer, ForeignKey("searchspaces.id", ondelete="CASCADE"), nullable=False - ) - - # User-specific LLM preferences for this search space - # Note: These can be negative IDs for global configs (from YAML) or positive IDs for custom configs (from DB) - # Foreign keys removed to support global configs with negative IDs - long_context_llm_id = Column(Integer, nullable=True) - fast_llm_id = Column(Integer, nullable=True) - strategic_llm_id = Column(Integer, nullable=True) - - # Future RBAC fields can be added here - # role = Column(String(50), nullable=True) # e.g., 'owner', 'editor', 'viewer' - # permissions = Column(JSON, nullable=True) - - user = relationship("User", back_populates="search_space_preferences") - search_space = relationship("SearchSpace", back_populates="user_preferences") class Log(BaseModel, TimestampMixin): @@ -720,11 +685,6 @@ if config.AUTH_TYPE == "GOOGLE": "OAuthAccount", lazy="joined" ) search_spaces = relationship("SearchSpace", back_populates="user") - search_space_preferences = relationship( - "UserSearchSpacePreference", - back_populates="user", - cascade="all, delete-orphan", - ) # RBAC relationships search_space_memberships = relationship( @@ -746,11 +706,6 @@ else: class User(SQLAlchemyBaseUserTableUUID, Base): search_spaces = relationship("SearchSpace", back_populates="user") - search_space_preferences = relationship( - "UserSearchSpacePreference", - back_populates="user", - cascade="all, delete-orphan", - ) # RBAC relationships search_space_memberships = relationship(