feat: register local agent project workspaces
This commit is contained in:
@@ -64,8 +64,26 @@ def _roots_for_user(user_id: str | None) -> tuple[Path, ...]:
|
||||
roots = configured_roots()
|
||||
from app import auth, database
|
||||
|
||||
registered_roots: list[Path] = []
|
||||
if user_id is not None:
|
||||
for value in database.list_workspace_roots(user_id):
|
||||
try:
|
||||
root = Path(value).expanduser().resolve(strict=True)
|
||||
except (OSError, RuntimeError):
|
||||
continue
|
||||
if root.is_dir() and root not in registered_roots:
|
||||
registered_roots.append(root)
|
||||
|
||||
def combine(*groups: tuple[Path, ...] | list[Path]) -> tuple[Path, ...]:
|
||||
combined: list[Path] = []
|
||||
for group in groups:
|
||||
for root in group:
|
||||
if root not in combined:
|
||||
combined.append(root)
|
||||
return tuple(combined)
|
||||
|
||||
if user_id is None or user_id == database.LOCAL_USER_ID:
|
||||
return roots
|
||||
return combine(roots, registered_roots)
|
||||
|
||||
email = auth.account_email(user_id)
|
||||
if email is None:
|
||||
@@ -110,9 +128,29 @@ def _roots_for_user(user_id: str | None) -> tuple[Path, ...]:
|
||||
if first_root == second_root or first_root in second_root.parents or second_root in first_root.parents:
|
||||
raise ValueError("جذور مساحة العمل لحسابين مختلفين متداخلة في إعداد الخادم.")
|
||||
assigned = resolved_by_email.get(email.casefold())
|
||||
if not assigned:
|
||||
if not assigned and not registered_roots:
|
||||
raise WorkspaceAccessDenied("لم يخصص مسؤول الخادم مساحة عمل لهذا الحساب.")
|
||||
return assigned
|
||||
# For authenticated accounts, the global roots are validation boundaries,
|
||||
# not grants. Keep account access limited to its explicit assignment plus
|
||||
# folders that account registered from its local desktop.
|
||||
return combine(assigned or (), registered_roots)
|
||||
|
||||
|
||||
def validate_workspace_registration(value: str, *, must_exist: bool = True) -> Path:
|
||||
"""Resolve a directory explicitly selected in the local desktop app."""
|
||||
if not value.strip():
|
||||
raise ValueError("اختر مجلد مشروع صالحًا.")
|
||||
try:
|
||||
root = Path(value).expanduser().resolve(strict=must_exist)
|
||||
except (OSError, RuntimeError) as exc:
|
||||
raise ValueError("مجلد المشروع غير موجود أو غير متاح.") from exc
|
||||
if must_exist and not root.is_dir():
|
||||
raise ValueError("يجب اختيار مجلد صالح للمشروع.")
|
||||
if root == Path(root.anchor):
|
||||
raise ValueError("اختر مجلد مشروع محددًا، وليس جذر القرص.")
|
||||
if root.name.startswith(".") or root.name in IGNORED_PARTS:
|
||||
raise ValueError("لا يمكن تسجيل مجلد مخفي أو مستثنى كمشروع.")
|
||||
return root
|
||||
|
||||
|
||||
def selected_root(value: str | None, *, user_id: str | None = None) -> Path | None:
|
||||
|
||||
Reference in New Issue
Block a user