feat(app): add shared_only filter and batch unshare endpoints
This commit is contained in:
@@ -53,6 +53,7 @@ def list_apps(
|
|||||||
status: str | None = None,
|
status: str | None = None,
|
||||||
search: str | None = None,
|
search: str | None = None,
|
||||||
include_shared: bool = True,
|
include_shared: bool = True,
|
||||||
|
shared_only: bool = False,
|
||||||
page: int = 1,
|
page: int = 1,
|
||||||
pagesize: int = 10,
|
pagesize: int = 10,
|
||||||
ids: Optional[str] = None,
|
ids: Optional[str] = None,
|
||||||
@@ -84,6 +85,7 @@ def list_apps(
|
|||||||
status=status,
|
status=status,
|
||||||
search=search,
|
search=search,
|
||||||
include_shared=include_shared,
|
include_shared=include_shared,
|
||||||
|
shared_only=shared_only,
|
||||||
page=page,
|
page=page,
|
||||||
pagesize=pagesize,
|
pagesize=pagesize,
|
||||||
)
|
)
|
||||||
@@ -107,6 +109,23 @@ def list_my_shared_out(
|
|||||||
return success(data=data)
|
return success(data=data)
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete("/share/{target_workspace_id}", summary="取消对某工作空间的所有应用分享")
|
||||||
|
@cur_workspace_access_guard()
|
||||||
|
def unshare_all_apps_to_workspace(
|
||||||
|
target_workspace_id: uuid.UUID,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
current_user=Depends(get_current_user),
|
||||||
|
):
|
||||||
|
"""Cancel all app shares from current workspace to a target workspace."""
|
||||||
|
workspace_id = current_user.current_workspace_id
|
||||||
|
service = app_service.AppService(db)
|
||||||
|
count = service.unshare_all_apps_to_workspace(
|
||||||
|
target_workspace_id=target_workspace_id,
|
||||||
|
workspace_id=workspace_id
|
||||||
|
)
|
||||||
|
return success(msg=f"已取消 {count} 个应用的分享")
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{app_id}", summary="获取应用详情")
|
@router.get("/{app_id}", summary="获取应用详情")
|
||||||
@cur_workspace_access_guard()
|
@cur_workspace_access_guard()
|
||||||
def get_app(
|
def get_app(
|
||||||
@@ -397,6 +416,23 @@ def list_app_shares(
|
|||||||
return success(data=data)
|
return success(data=data)
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete("/shared/{source_workspace_id}", summary="批量移除某来源工作空间的所有共享应用")
|
||||||
|
@cur_workspace_access_guard()
|
||||||
|
def remove_all_shared_apps_from_workspace(
|
||||||
|
source_workspace_id: uuid.UUID,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
current_user=Depends(get_current_user),
|
||||||
|
):
|
||||||
|
"""Remove all shared apps from a specific source workspace (recipient operation)."""
|
||||||
|
workspace_id = current_user.current_workspace_id
|
||||||
|
service = app_service.AppService(db)
|
||||||
|
count = service.remove_all_shared_apps_from_workspace(
|
||||||
|
source_workspace_id=source_workspace_id,
|
||||||
|
workspace_id=workspace_id
|
||||||
|
)
|
||||||
|
return success(msg=f"已移除 {count} 个共享应用")
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/{app_id}/shared", summary="移除共享给我的应用")
|
@router.delete("/{app_id}/shared", summary="移除共享给我的应用")
|
||||||
@cur_workspace_access_guard()
|
@cur_workspace_access_guard()
|
||||||
def remove_shared_app(
|
def remove_shared_app(
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import uuid
|
|||||||
from typing import Annotated, Any, Dict, List, Optional, Tuple
|
from typing import Annotated, Any, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
from fastapi import Depends
|
from fastapi import Depends
|
||||||
from sqlalchemy import and_, func, or_, select
|
from sqlalchemy import and_, delete, func, or_, select
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.core.error_codes import BizCode
|
from app.core.error_codes import BizCode
|
||||||
@@ -878,6 +878,7 @@ class AppService:
|
|||||||
status: Optional[str] = None,
|
status: Optional[str] = None,
|
||||||
search: Optional[str] = None,
|
search: Optional[str] = None,
|
||||||
include_shared: bool = True,
|
include_shared: bool = True,
|
||||||
|
shared_only: bool = False,
|
||||||
page: int = 1,
|
page: int = 1,
|
||||||
pagesize: int = 10,
|
pagesize: int = 10,
|
||||||
) -> Tuple[List[App], int]:
|
) -> Tuple[List[App], int]:
|
||||||
@@ -924,7 +925,14 @@ class AppService:
|
|||||||
filters.append(func.lower(App.name).like(f"%{search.lower()}%"))
|
filters.append(func.lower(App.name).like(f"%{search.lower()}%"))
|
||||||
|
|
||||||
# 基础查询:本工作空间的应用
|
# 基础查询:本工作空间的应用
|
||||||
if include_shared:
|
if shared_only:
|
||||||
|
# 只返回共享给本工作空间的应用,不含自有应用
|
||||||
|
shared_app_ids_stmt = (
|
||||||
|
select(AppShare.source_app_id)
|
||||||
|
.where(AppShare.target_workspace_id == workspace_id)
|
||||||
|
)
|
||||||
|
stmt = select(App).where(App.id.in_(shared_app_ids_stmt))
|
||||||
|
elif include_shared:
|
||||||
# 查询本工作空间的应用 + 分享给本工作空间的应用
|
# 查询本工作空间的应用 + 分享给本工作空间的应用
|
||||||
# 使用 OR 条件:workspace_id = current OR app_id IN (shared apps)
|
# 使用 OR 条件:workspace_id = current OR app_id IN (shared apps)
|
||||||
|
|
||||||
@@ -1891,6 +1899,39 @@ class AppService:
|
|||||||
extra={"app_id": str(app_id), "target_workspace_id": str(target_workspace_id)}
|
extra={"app_id": str(app_id), "target_workspace_id": str(target_workspace_id)}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def unshare_all_apps_to_workspace(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
target_workspace_id: uuid.UUID,
|
||||||
|
workspace_id: uuid.UUID
|
||||||
|
) -> int:
|
||||||
|
"""Cancel all app shares from current workspace to a target workspace.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
target_workspace_id: Target workspace ID to cancel all shares to
|
||||||
|
workspace_id: Current workspace ID (source)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Number of share records deleted
|
||||||
|
"""
|
||||||
|
from app.models import AppShare
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"取消对目标工作空间的所有应用分享",
|
||||||
|
extra={"target_workspace_id": str(target_workspace_id), "workspace_id": str(workspace_id)}
|
||||||
|
)
|
||||||
|
|
||||||
|
stmt = delete(AppShare).where(
|
||||||
|
AppShare.source_workspace_id == workspace_id,
|
||||||
|
AppShare.target_workspace_id == target_workspace_id
|
||||||
|
)
|
||||||
|
result = self.db.execute(stmt)
|
||||||
|
self.db.commit()
|
||||||
|
|
||||||
|
count = result.rowcount
|
||||||
|
logger.info("已取消分享记录数", extra={"count": count})
|
||||||
|
return count
|
||||||
|
|
||||||
def list_app_shares(
|
def list_app_shares(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
@@ -1976,6 +2017,39 @@ class AppService:
|
|||||||
extra={"app_id": str(app_id), "workspace_id": str(workspace_id)}
|
extra={"app_id": str(app_id), "workspace_id": str(workspace_id)}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def remove_all_shared_apps_from_workspace(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
source_workspace_id: uuid.UUID,
|
||||||
|
workspace_id: uuid.UUID
|
||||||
|
) -> int:
|
||||||
|
"""Remove all shared apps from a specific source workspace.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
source_workspace_id: The workspace that shared the apps
|
||||||
|
workspace_id: Current workspace ID (recipient)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Number of share records deleted
|
||||||
|
"""
|
||||||
|
from app.models import AppShare
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"批量移除来源工作空间的共享应用",
|
||||||
|
extra={"source_workspace_id": str(source_workspace_id), "workspace_id": str(workspace_id)}
|
||||||
|
)
|
||||||
|
|
||||||
|
stmt = delete(AppShare).where(
|
||||||
|
AppShare.source_workspace_id == source_workspace_id,
|
||||||
|
AppShare.target_workspace_id == workspace_id
|
||||||
|
)
|
||||||
|
result = self.db.execute(stmt)
|
||||||
|
self.db.commit()
|
||||||
|
|
||||||
|
count = result.rowcount
|
||||||
|
logger.info("已移除共享记录数", extra={"count": count})
|
||||||
|
return count
|
||||||
|
|
||||||
def list_my_shared_out(
|
def list_my_shared_out(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
@@ -2139,6 +2213,7 @@ def list_apps(
|
|||||||
status: Optional[str] = None,
|
status: Optional[str] = None,
|
||||||
search: Optional[str] = None,
|
search: Optional[str] = None,
|
||||||
include_shared: bool = True,
|
include_shared: bool = True,
|
||||||
|
shared_only: bool = False,
|
||||||
page: int = 1,
|
page: int = 1,
|
||||||
pagesize: int = 10,
|
pagesize: int = 10,
|
||||||
) -> Tuple[List[App], int]:
|
) -> Tuple[List[App], int]:
|
||||||
@@ -2151,6 +2226,7 @@ def list_apps(
|
|||||||
status=status,
|
status=status,
|
||||||
search=search,
|
search=search,
|
||||||
include_shared=include_shared,
|
include_shared=include_shared,
|
||||||
|
shared_only=shared_only,
|
||||||
page=page,
|
page=page,
|
||||||
pagesize=pagesize,
|
pagesize=pagesize,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user