feat: folder permissions (ACLs) - share folders with users/groups, inherit to subfolders, permission dialog UI
This commit is contained in:
@@ -27,11 +27,24 @@ def _serialize_folder(f: ContactFolder, contact_count: int = 0) -> dict:
|
||||
async def list_folders(
|
||||
db: AsyncSession, tenant_id: uuid.UUID, user_id: uuid.UUID
|
||||
) -> list[dict]:
|
||||
"""List all folders for a user (flat list, frontend builds tree)."""
|
||||
"""List all folders visible to a user (owned + shared via ACLs).
|
||||
|
||||
Returns a flat list; the frontend builds the tree.
|
||||
Each folder includes ``access_level`` (owner|admin|write|read) and
|
||||
``is_shared`` flag.
|
||||
"""
|
||||
from app.services.contact_folder_permission_service import get_visible_folder_ids
|
||||
|
||||
# Get visible folder IDs and access map
|
||||
visible_ids, access_map = await get_visible_folder_ids(db, tenant_id, user_id)
|
||||
|
||||
if not visible_ids:
|
||||
return []
|
||||
|
||||
result = await db.execute(
|
||||
select(ContactFolder)
|
||||
.where(ContactFolder.tenant_id == tenant_id)
|
||||
.where(ContactFolder.user_id == user_id)
|
||||
.where(ContactFolder.id.in_(visible_ids))
|
||||
.where(ContactFolder.deleted_at.is_(None))
|
||||
.order_by(ContactFolder.parent_id, ContactFolder.sort_order, ContactFolder.name)
|
||||
)
|
||||
@@ -50,8 +63,23 @@ async def list_folders(
|
||||
for fid, cnt in count_result:
|
||||
counts[fid] = cnt
|
||||
|
||||
# Check which folders have permissions (are shared)
|
||||
from app.models.contact_folder_permission import ContactFolderPermission
|
||||
shared_q = await db.execute(
|
||||
select(ContactFolderPermission.folder_id)
|
||||
.where(ContactFolderPermission.folder_id.in_(folder_ids))
|
||||
.where(ContactFolderPermission.tenant_id == tenant_id)
|
||||
.group_by(ContactFolderPermission.folder_id)
|
||||
)
|
||||
shared_ids = {row[0] for row in shared_q}
|
||||
|
||||
return [
|
||||
{**_serialize_folder(f), "contact_count": counts.get(f.id, 0)}
|
||||
{
|
||||
**_serialize_folder(f),
|
||||
"contact_count": counts.get(f.id, 0),
|
||||
"access_level": access_map.get(f.id, "none"),
|
||||
"is_shared": f.id in shared_ids,
|
||||
}
|
||||
for f in folders
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user