feat(sharing): user picker in share dialog
Replace the free-text username input with a Select populated from a new /sharing/users endpoint. Users already on the target's share list are filtered out, and the trigger surfaces loading / empty states. Matches the existing permission model since sharing only ever required knowing a username. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -59,6 +59,34 @@ class SharedFolderResponse(BaseModel):
|
||||
photo_count: int
|
||||
|
||||
|
||||
class ShareableUser(BaseModel):
|
||||
id: str
|
||||
username: str
|
||||
|
||||
|
||||
# ── Shareable users ──────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/users", response_model=list[ShareableUser])
|
||||
async def list_shareable_users(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
"""List every active user other than the caller, for the share-picker
|
||||
dropdown. Sharing only requires knowing a username today, so surfacing
|
||||
the list is no wider an attack surface than the free-text input it
|
||||
replaces. Inactive accounts are filtered out."""
|
||||
result = await db.execute(
|
||||
select(User)
|
||||
.where(User.id != current_user.id)
|
||||
.where(User.is_active.is_(True))
|
||||
.order_by(User.username)
|
||||
)
|
||||
return [
|
||||
ShareableUser(id=str(u.id), username=u.username)
|
||||
for u in result.scalars().all()
|
||||
]
|
||||
|
||||
|
||||
# ── Heap sharing ─────────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/heaps/shared-with-me")
|
||||
|
||||
Reference in New Issue
Block a user