mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-19 18:45:15 +02:00
feat: use frontend URL for public share links
This commit is contained in:
parent
0bcd7505fb
commit
3821630404
3 changed files with 76 additions and 14 deletions
|
|
@ -739,7 +739,6 @@ async def update_thread_visibility(
|
||||||
@router.post("/threads/{thread_id}/snapshots", response_model=SnapshotCreateResponse)
|
@router.post("/threads/{thread_id}/snapshots", response_model=SnapshotCreateResponse)
|
||||||
async def create_thread_snapshot(
|
async def create_thread_snapshot(
|
||||||
thread_id: int,
|
thread_id: int,
|
||||||
request: Request,
|
|
||||||
session: AsyncSession = Depends(get_async_session),
|
session: AsyncSession = Depends(get_async_session),
|
||||||
user: User = Depends(current_active_user),
|
user: User = Depends(current_active_user),
|
||||||
):
|
):
|
||||||
|
|
@ -747,23 +746,19 @@ async def create_thread_snapshot(
|
||||||
Create a public snapshot of the thread.
|
Create a public snapshot of the thread.
|
||||||
|
|
||||||
Returns existing snapshot URL if content unchanged (deduplication).
|
Returns existing snapshot URL if content unchanged (deduplication).
|
||||||
Only the thread owner can create snapshots.
|
|
||||||
"""
|
"""
|
||||||
from app.services.public_chat_service import create_snapshot
|
from app.services.public_chat_service import create_snapshot
|
||||||
|
|
||||||
base_url = str(request.base_url).rstrip("/")
|
|
||||||
return await create_snapshot(
|
return await create_snapshot(
|
||||||
session=session,
|
session=session,
|
||||||
thread_id=thread_id,
|
thread_id=thread_id,
|
||||||
user=user,
|
user=user,
|
||||||
base_url=base_url,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/threads/{thread_id}/snapshots", response_model=SnapshotListResponse)
|
@router.get("/threads/{thread_id}/snapshots", response_model=SnapshotListResponse)
|
||||||
async def list_thread_snapshots(
|
async def list_thread_snapshots(
|
||||||
thread_id: int,
|
thread_id: int,
|
||||||
request: Request,
|
|
||||||
session: AsyncSession = Depends(get_async_session),
|
session: AsyncSession = Depends(get_async_session),
|
||||||
user: User = Depends(current_active_user),
|
user: User = Depends(current_active_user),
|
||||||
):
|
):
|
||||||
|
|
@ -774,13 +769,11 @@ async def list_thread_snapshots(
|
||||||
"""
|
"""
|
||||||
from app.services.public_chat_service import list_snapshots_for_thread
|
from app.services.public_chat_service import list_snapshots_for_thread
|
||||||
|
|
||||||
base_url = str(request.base_url).rstrip("/")
|
|
||||||
return SnapshotListResponse(
|
return SnapshotListResponse(
|
||||||
snapshots=await list_snapshots_for_thread(
|
snapshots=await list_snapshots_for_thread(
|
||||||
session=session,
|
session=session,
|
||||||
thread_id=thread_id,
|
thread_id=thread_id,
|
||||||
user=user,
|
user=user,
|
||||||
base_url=base_url,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -236,6 +236,24 @@ class SnapshotListResponse(BaseModel):
|
||||||
snapshots: list[SnapshotInfo]
|
snapshots: list[SnapshotInfo]
|
||||||
|
|
||||||
|
|
||||||
|
class SearchSpaceSnapshotInfo(BaseModel):
|
||||||
|
"""Snapshot info with thread context for search space listing."""
|
||||||
|
|
||||||
|
id: int
|
||||||
|
share_token: str
|
||||||
|
public_url: str
|
||||||
|
created_at: datetime
|
||||||
|
message_count: int
|
||||||
|
thread_id: int
|
||||||
|
thread_title: str
|
||||||
|
|
||||||
|
|
||||||
|
class SearchSpaceSnapshotListResponse(BaseModel):
|
||||||
|
"""List of all snapshots in a search space."""
|
||||||
|
|
||||||
|
snapshots: list[SearchSpaceSnapshotInfo]
|
||||||
|
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Public Chat View Schemas (for unauthenticated access)
|
# Public Chat View Schemas (for unauthenticated access)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,6 @@ async def create_snapshot(
|
||||||
session: AsyncSession,
|
session: AsyncSession,
|
||||||
thread_id: int,
|
thread_id: int,
|
||||||
user: User,
|
user: User,
|
||||||
base_url: str,
|
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""
|
"""
|
||||||
Create a public snapshot of a chat thread.
|
Create a public snapshot of a chat thread.
|
||||||
|
|
@ -169,6 +168,9 @@ async def create_snapshot(
|
||||||
Returns existing snapshot if content unchanged (same hash).
|
Returns existing snapshot if content unchanged (same hash).
|
||||||
Returns new snapshot with unique URL if content changed.
|
Returns new snapshot with unique URL if content changed.
|
||||||
"""
|
"""
|
||||||
|
from app.config import config
|
||||||
|
|
||||||
|
frontend_url = (config.NEXT_FRONTEND_URL or "").rstrip("/")
|
||||||
result = await session.execute(
|
result = await session.execute(
|
||||||
select(NewChatThread)
|
select(NewChatThread)
|
||||||
.options(selectinload(NewChatThread.messages))
|
.options(selectinload(NewChatThread.messages))
|
||||||
|
|
@ -250,7 +252,7 @@ async def create_snapshot(
|
||||||
return {
|
return {
|
||||||
"snapshot_id": existing.id,
|
"snapshot_id": existing.id,
|
||||||
"share_token": existing.share_token,
|
"share_token": existing.share_token,
|
||||||
"public_url": f"{base_url}/public/{existing.share_token}",
|
"public_url": f"{frontend_url}/public/{existing.share_token}",
|
||||||
"is_new": False,
|
"is_new": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -283,7 +285,7 @@ async def create_snapshot(
|
||||||
return {
|
return {
|
||||||
"snapshot_id": snapshot.id,
|
"snapshot_id": snapshot.id,
|
||||||
"share_token": snapshot.share_token,
|
"share_token": snapshot.share_token,
|
||||||
"public_url": f"{base_url}/public/{snapshot.share_token}",
|
"public_url": f"{frontend_url}/public/{snapshot.share_token}",
|
||||||
"is_new": True,
|
"is_new": True,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -352,10 +354,10 @@ async def list_snapshots_for_thread(
|
||||||
session: AsyncSession,
|
session: AsyncSession,
|
||||||
thread_id: int,
|
thread_id: int,
|
||||||
user: User,
|
user: User,
|
||||||
base_url: str,
|
|
||||||
) -> list[dict]:
|
) -> list[dict]:
|
||||||
"""List all public snapshots for a thread."""
|
"""List all public snapshots for a thread."""
|
||||||
# Verify ownership
|
from app.config import config
|
||||||
|
|
||||||
result = await session.execute(
|
result = await session.execute(
|
||||||
select(NewChatThread).filter(NewChatThread.id == thread_id)
|
select(NewChatThread).filter(NewChatThread.id == thread_id)
|
||||||
)
|
)
|
||||||
|
|
@ -370,7 +372,6 @@ async def list_snapshots_for_thread(
|
||||||
detail="Only the creator can view snapshots",
|
detail="Only the creator can view snapshots",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Get snapshots
|
|
||||||
result = await session.execute(
|
result = await session.execute(
|
||||||
select(PublicChatSnapshot)
|
select(PublicChatSnapshot)
|
||||||
.filter(PublicChatSnapshot.thread_id == thread_id)
|
.filter(PublicChatSnapshot.thread_id == thread_id)
|
||||||
|
|
@ -378,11 +379,13 @@ async def list_snapshots_for_thread(
|
||||||
)
|
)
|
||||||
snapshots = result.scalars().all()
|
snapshots = result.scalars().all()
|
||||||
|
|
||||||
|
frontend_url = (config.NEXT_FRONTEND_URL or "").rstrip("/")
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
"id": s.id,
|
"id": s.id,
|
||||||
"share_token": s.share_token,
|
"share_token": s.share_token,
|
||||||
"public_url": f"{base_url}/public/{s.share_token}",
|
"public_url": f"{frontend_url}/public/{s.share_token}",
|
||||||
"created_at": s.created_at.isoformat() if s.created_at else None,
|
"created_at": s.created_at.isoformat() if s.created_at else None,
|
||||||
"message_count": len(s.message_ids) if s.message_ids else 0,
|
"message_count": len(s.message_ids) if s.message_ids else 0,
|
||||||
}
|
}
|
||||||
|
|
@ -390,6 +393,54 @@ async def list_snapshots_for_thread(
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
async def list_snapshots_for_search_space(
|
||||||
|
session: AsyncSession,
|
||||||
|
search_space_id: int,
|
||||||
|
user: User,
|
||||||
|
) -> list[dict]:
|
||||||
|
"""List all public snapshots for a search space."""
|
||||||
|
from app.config import config
|
||||||
|
|
||||||
|
await check_permission(
|
||||||
|
session,
|
||||||
|
user,
|
||||||
|
search_space_id,
|
||||||
|
Permission.PUBLIC_SHARING_VIEW.value,
|
||||||
|
"You don't have permission to view public share links",
|
||||||
|
)
|
||||||
|
|
||||||
|
result = await session.execute(
|
||||||
|
select(PublicChatSnapshot)
|
||||||
|
.join(NewChatThread, PublicChatSnapshot.thread_id == NewChatThread.id)
|
||||||
|
.filter(NewChatThread.search_space_id == search_space_id)
|
||||||
|
.order_by(PublicChatSnapshot.created_at.desc())
|
||||||
|
)
|
||||||
|
snapshots = result.scalars().all()
|
||||||
|
|
||||||
|
snapshot_thread_ids = [s.thread_id for s in snapshots]
|
||||||
|
thread_result = await session.execute(
|
||||||
|
select(NewChatThread.id, NewChatThread.title).filter(
|
||||||
|
NewChatThread.id.in_(snapshot_thread_ids)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
thread_titles = {row[0]: row[1] for row in thread_result.fetchall()}
|
||||||
|
|
||||||
|
frontend_url = (config.NEXT_FRONTEND_URL or "").rstrip("/")
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"id": s.id,
|
||||||
|
"share_token": s.share_token,
|
||||||
|
"public_url": f"{frontend_url}/public/{s.share_token}",
|
||||||
|
"created_at": s.created_at.isoformat() if s.created_at else None,
|
||||||
|
"message_count": len(s.message_ids) if s.message_ids else 0,
|
||||||
|
"thread_id": s.thread_id,
|
||||||
|
"thread_title": thread_titles.get(s.thread_id, "Untitled"),
|
||||||
|
}
|
||||||
|
for s in snapshots
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Snapshot Deletion
|
# Snapshot Deletion
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue