diff --git a/api/app/models/appshare_model.py b/api/app/models/appshare_model.py index 643b0e11..6902051a 100644 --- a/api/app/models/appshare_model.py +++ b/api/app/models/appshare_model.py @@ -1,6 +1,6 @@ import datetime import uuid -from sqlalchemy import Column, DateTime, ForeignKey, String +from sqlalchemy import Boolean, Column, DateTime, ForeignKey, String from sqlalchemy.dialects.postgresql import UUID from app.db import Base from sqlalchemy.orm import relationship @@ -19,6 +19,7 @@ class AppShare(Base): target_workspace_id = Column(UUID(as_uuid=True), ForeignKey('workspaces.id'), nullable=False, comment="目标工作空间ID") shared_by = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=False, comment="分享者用户ID") permission = Column(String, default="readonly", nullable=False, comment="权限模式: readonly | editable") + is_active = Column(Boolean, default=True, nullable=False, comment="是否有效,False 表示逻辑删除") created_at = Column(DateTime, default=datetime.datetime.now) updated_at = Column(DateTime, default=datetime.datetime.now) diff --git a/api/app/services/app_service.py b/api/app/services/app_service.py index ca9a3c4a..c06d79a9 100644 --- a/api/app/services/app_service.py +++ b/api/app/services/app_service.py @@ -102,7 +102,8 @@ class AppService: # 2. 检查是否是共享给本工作空间的应用 stmt = select(AppShare).where( AppShare.source_app_id == app.id, - AppShare.target_workspace_id == workspace_id + AppShare.target_workspace_id == workspace_id, + AppShare.is_active.is_(True) ) share = self.db.scalars(stmt).first() @@ -140,7 +141,8 @@ class AppService: stmt = select(AppShare).where( AppShare.source_app_id == app.id, - AppShare.target_workspace_id == workspace_id + AppShare.target_workspace_id == workspace_id, + AppShare.is_active.is_(True) ) share = self.db.scalars(stmt).first() return share.permission if share else None @@ -509,7 +511,8 @@ class AppService: from app.models import AppShare stmt = select(AppShare).where( AppShare.source_app_id == app.id, - AppShare.target_workspace_id == current_workspace_id + AppShare.target_workspace_id == current_workspace_id, + AppShare.is_active.is_(True) ) share = self.db.scalars(stmt).first() if share: @@ -933,20 +936,15 @@ class AppService: # 只返回共享给本工作空间的应用,不含自有应用 shared_app_ids_stmt = ( select(AppShare.source_app_id) - .where(AppShare.target_workspace_id == workspace_id) + .where(AppShare.target_workspace_id == workspace_id, AppShare.is_active.is_(True)) ) stmt = select(App).where(App.id.in_(shared_app_ids_stmt)) elif include_shared: # 查询本工作空间的应用 + 分享给本工作空间的应用 - # 使用 OR 条件:workspace_id = current OR app_id IN (shared apps) - - # 获取分享给本工作空间的应用ID列表 shared_app_ids_stmt = ( select(AppShare.source_app_id) - .where(AppShare.target_workspace_id == workspace_id) + .where(AppShare.target_workspace_id == workspace_id, AppShare.is_active.is_(True)) ) - - # 构建主查询:本工作空间的应用 OR 分享的应用 stmt = select(App).where( or_( App.workspace_id == workspace_id, @@ -1801,7 +1799,8 @@ class AppService: # 检查是否已经分享过 stmt = select(AppShare).where( AppShare.source_app_id == app_id, - AppShare.target_workspace_id == target_ws_id + AppShare.target_workspace_id == target_ws_id, + AppShare.is_active.is_(True) ) existing_share = self.db.scalars(stmt).first() @@ -1880,7 +1879,8 @@ class AppService: # 2. 查找分享记录 stmt = select(AppShare).where( AppShare.source_app_id == app_id, - AppShare.target_workspace_id == target_workspace_id + AppShare.target_workspace_id == target_workspace_id, + AppShare.is_active.is_(True) ) share = self.db.scalars(stmt).first() @@ -1894,8 +1894,8 @@ class AppService: f"app_id={app_id}, target_workspace_id={target_workspace_id}" ) - # 3. 删除分享记录 - self.db.delete(share) + # 3. 逻辑删除分享记录 + share.is_active = False self.db.commit() logger.info( @@ -1925,16 +1925,21 @@ class AppService: extra={"target_workspace_id": str(target_workspace_id), "workspace_id": str(workspace_id)} ) - # Query IDs first to get a reliable count, avoiding rowcount driver inconsistencies + # Query active records first for reliable count id_stmt = select(AppShare.id).where( AppShare.source_workspace_id == workspace_id, - AppShare.target_workspace_id == target_workspace_id + AppShare.target_workspace_id == target_workspace_id, + AppShare.is_active.is_(True) ) ids = list(self.db.scalars(id_stmt).all()) count = len(ids) if ids: - self.db.execute(delete(AppShare).where(AppShare.id.in_(ids))) + # Soft delete: mark as inactive + from sqlalchemy import update as sa_update + self.db.execute( + sa_update(AppShare).where(AppShare.id.in_(ids)).values(is_active=False) + ) self.db.commit() logger.info("已取消分享记录数", extra={"count": count}) @@ -1969,7 +1974,8 @@ class AppService: # 查询分享记录 stmt = select(AppShare).where( - AppShare.source_app_id == app_id + AppShare.source_app_id == app_id, + AppShare.is_active.is_(True) ).order_by(AppShare.created_at.desc()) shares = list(self.db.scalars(stmt).all()) @@ -2007,7 +2013,8 @@ class AppService: stmt = select(AppShare).where( AppShare.source_app_id == app_id, - AppShare.target_workspace_id == workspace_id + AppShare.target_workspace_id == workspace_id, + AppShare.is_active.is_(True) ) share = self.db.scalars(stmt).first() @@ -2017,7 +2024,8 @@ class AppService: f"app_id={app_id}, workspace_id={workspace_id}" ) - self.db.delete(share) + # Soft delete + share.is_active = False self.db.commit() logger.info( @@ -2047,16 +2055,20 @@ class AppService: extra={"source_workspace_id": str(source_workspace_id), "workspace_id": str(workspace_id)} ) - # Query IDs first to get a reliable count, avoiding rowcount driver inconsistencies + # Query active records for reliable count, then soft delete id_stmt = select(AppShare.id).where( AppShare.source_workspace_id == source_workspace_id, - AppShare.target_workspace_id == workspace_id + AppShare.target_workspace_id == workspace_id, + AppShare.is_active.is_(True) ) ids = list(self.db.scalars(id_stmt).all()) count = len(ids) if ids: - self.db.execute(delete(AppShare).where(AppShare.id.in_(ids))) + from sqlalchemy import update as sa_update + self.db.execute( + sa_update(AppShare).where(AppShare.id.in_(ids)).values(is_active=False) + ) self.db.commit() logger.info("已移除共享记录数", extra={"count": count}) @@ -2076,7 +2088,10 @@ class AppService: stmt = ( select(AppShare) - .where(AppShare.source_workspace_id == workspace_id) + .where( + AppShare.source_workspace_id == workspace_id, + AppShare.is_active.is_(True) + ) .order_by(AppShare.created_at.desc()) ) return list(self.db.scalars(stmt).all()) @@ -2109,7 +2124,8 @@ class AppService: stmt = select(AppShare).where( AppShare.source_app_id == app_id, - AppShare.target_workspace_id == target_workspace_id + AppShare.target_workspace_id == target_workspace_id, + AppShare.is_active.is_(True) ) share = self.db.scalars(stmt).first()