Skip to content

Commit

Permalink
simplify http endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
oeway committed Nov 20, 2024
1 parent 29f1825 commit b7e615b
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 97 deletions.
18 changes: 12 additions & 6 deletions docs/artifact-manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,14 +290,20 @@ Permissions can be set both at the artifact level and the workspace level. In th

**Permission Levels:**

The following permission levels are supported:

- **n**: No access to the artifact.
- **l**: List-only access (includes `list`).
- **l+**: List and create access (includes `list`, `create`, `commit`).
- **r**: Read-only access (includes `read`, `get_file`, `list_files`, `list`).
- **r+**: Read and create access (includes `read`, `get_file`, `list_files`, `list`, `put_file`, `create`, `commit`).
- **rw**: Read and write access (includes `read`, `get_file`, `list_files`, `list`, `edit`, `commit`, `put_file`, `remove_file`).
- **rw+**: Full access, including creation, editing, committing, and file removal (includes `read`, `get_file`, `list_files`, `list`, `edit`, `commit`, `put_file`, `remove_file`, `create`, `reset_stats`).
- **\***: Full access for all operations (includes all operations listed above).
- **l+**: List and create access (includes `list`, `create`, and `commit`).
- **lv**: List and list vectors access (includes `list` and `list_vectors`).
- **lv+**: List, list vectors, create, and commit access (includes `list`, `list_vectors`, `create`, `commit`, `add_vectors`, and `add_documents`).
- **lf**: List and list files access (includes `list` and `list_files`).
- **lf+**: List, list files, create, and commit access (includes `list`, `list_files`, `create`, `commit`, and `put_file`).
- **r**: Read-only access (includes `read`, `get_file`, `list_files`, `list`, `search_by_vector`, `search_by_text`, and `get_vector`).
- **r+**: Read, write, and create access (includes `read`, `get_file`, `put_file`, `list_files`, `list`, `search_by_vector`, `search_by_text`, `get_vector`, `create`, `commit`, `add_vectors`, and `add_documents`).
- **rw**: Read, write, and create access with file management (includes `read`, `get_file`, `get_vector`, `search_by_vector`, `search_by_text`, `list_files`, `list_vectors`, `list`, `edit`, `commit`, `put_file`, `add_vectors`, `add_documents`, `remove_file`, and `remove_vectors`).
- **rw+**: Read, write, create, and manage access (includes `read`, `get_file`, `get_vector`, `search_by_vector`, `search_by_text`, `list_files`, `list_vectors`, `list`, `edit`, `commit`, `put_file`, `add_vectors`, `add_documents`, `remove_file`, `remove_vectors`, and `create`).
- **\***: Full access to all operations (includes `read`, `get_file`, `get_vector`, `search_by_vector`, `search_by_text`, `list_files`, `list_vectors`, `list`, `edit`, `commit`, `put_file`, `add_vectors`, `add_documents`, `remove_file`, `remove_vectors`, `create`, and `reset_stats`).

**Shortcut Permission Notation:**

Expand Down
2 changes: 1 addition & 1 deletion hypha/VERSION
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": "0.20.39.post9"
"version": "0.20.39.post10"
}
182 changes: 92 additions & 90 deletions hypha/artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,39 +160,12 @@ async def get_artifact(
):
"""Get artifact metadata, manifest, and config (excluding secrets)."""
try:
artifact_id = self._validate_artifact_id(
artifact_alias, {"ws": workspace}
return await self.read(
artifact_id=f"{workspace}/{artifact_alias}",
version=version,
silent=silent,
context={"user": user_info.model_dump(), "ws": workspace},
)
session = await self._get_session(read_only=True)
async with session.begin():
# Fetch artifact along with parent
(
artifact,
parent_artifact,
) = await self._get_artifact_with_permission(
user_info, artifact_id, "read", session
)

version_index = self._get_version_index(artifact, version)

if version_index == self._get_version_index(artifact, None):
# Prepare artifact representation
artifact_data = self._generate_artifact_data(
artifact, parent_artifact
)
else:
s3_config = self._get_s3_config(artifact)
artifact_data = await self._load_version_from_s3(
artifact, version_index, s3_config
)

# Increment view count unless silent
if not silent:
await self._increment_stat(session, artifact.id, "view_count")
await session.commit()

return artifact_data

except KeyError:
raise HTTPException(status_code=404, detail="Artifact not found")
except PermissionError:
Expand All @@ -204,64 +177,40 @@ async def get_artifact(
logger.error(f"S3 client error: {str(e)}")
raise HTTPException(status_code=500, detail="File storage error.")
except Exception as e:
logger.error(f"Unhandled exception: {str(e)}")
logger.error(f"Unhandled error in http get_artifact: {str(e)}")
raise HTTPException(
status_code=500, detail="An unexpected error occurred."
status_code=500, detail=f"An unexpected error occurred: {str(e)}"
)

finally:
await session.close()

# HTTP endpoint for listing child artifacts
@router.get("/{workspace}/artifacts/{artifact_alias}/children")
async def list_children(
workspace: str,
artifact_alias: str,
keywords: str = None,
filters: str = None,
offset: int = 0,
mode: str = "AND",
limit: int = 100,
order_by: str = None,
user_info: self.store.login_optional = Depends(self.store.login_optional),
):
"""List child artifacts of a specified artifact."""
try:
artifact_id = self._validate_artifact_id(
artifact_alias, {"ws": workspace}
if keywords:
keywords = keywords.split(",")
if filters:
filters = json.loads(filters)
return await self.list_children(
parent_id=f"{workspace}/{artifact_alias}",
offset=offset,
limit=limit,
order_by=order_by,
keywords=keywords,
filters=filters,
mode=mode,
context={"user": user_info.model_dump(), "ws": workspace},
)
session = await self._get_session(read_only=True)
async with session.begin():
parent_artifact, _ = await self._get_artifact_with_permission(
user_info, artifact_id, "list", session
)
# Query child artifacts
query = (
select(ArtifactModel)
.where(
ArtifactModel.workspace == workspace,
ArtifactModel.parent_id == parent_artifact.id,
)
.limit(limit)
.offset(offset)
)

if order_by:
if order_by.endswith("<"):
query = query.order_by(
getattr(ArtifactModel, order_by[:-1]).asc()
)
else:
query = query.order_by(
getattr(ArtifactModel, order_by).desc()
)

result = await session.execute(query)
children = result.scalars().all()

# Return children data, excluding secrets
return [
self._generate_artifact_data(child, parent_artifact)
for child in children
]

except KeyError:
raise HTTPException(status_code=404, detail="Parent artifact not found")
except PermissionError:
Expand All @@ -273,14 +222,11 @@ async def list_children(
logger.error(f"S3 client error: {str(e)}")
raise HTTPException(status_code=500, detail="File storage error.")
except Exception as e:
logger.error(f"Unhandled exception: {str(e)}")
logger.error(f"Unhandled exception in http list_children: {str(e)}")
raise HTTPException(
status_code=500, detail="An unexpected error occurred."
status_code=500, detail=f"An unexpected error occurred: {str(e)}"
)

finally:
await session.close()

# HTTP endpoint for retrieving files within an artifact
@router.get("/{workspace}/artifacts/{artifact_alias}/files/{path:path}")
async def get_file(
Expand Down Expand Up @@ -360,8 +306,10 @@ async def get_file(
except HTTPException as e:
raise e # Re-raise HTTPExceptions to be handled by FastAPI
except Exception as e:
logger.error(f"Unhandled exception in get_file: {str(e)}")
raise HTTPException(status_code=500, detail="Internal server error")
logger.error(f"Unhandled exception in http get_file: {str(e)}")
raise HTTPException(
status_code=500, detail=f"Internal server error: {str(e)}"
)
finally:
await session.close()

Expand Down Expand Up @@ -457,48 +405,95 @@ def _expand_permission(self, permission):
if isinstance(permission, str):
permission_map = {
"n": [],
"l": ["list"],
"l": [
"list",
],
"l+": ["list", "create", "commit"],
"r": ["read", "get_file", "list_files", "list"],
"lv": ["list", "list_vectors"],
"lv+": [
"list",
"list_vectors",
"create",
"commit",
"add_vectors",
"add_documents",
],
"lf": ["list", "list_files"],
"lf+": ["list", "list_files", "create", "commit", "put_file"],
"r": [
"read",
"get_file",
"list_files",
"list",
"search_by_vector",
"search_by_text",
"get_vector",
],
"r+": [
"read",
"get_file",
"put_file",
"list_files",
"list",
"search_by_vector",
"search_by_text",
"get_vector",
"create",
"commit",
"add_vectors",
"add_documents",
],
"rw": [
"read",
"get_file",
"get_vector",
"search_by_vector",
"search_by_text",
"list_files",
"list_vectors",
"list",
"edit",
"commit",
"put_file",
"add_vectors",
"add_documents",
"remove_file",
"remove_vectors",
],
"rw+": [
"read",
"get_file",
"get_vector",
"search_by_vector",
"search_by_text",
"list_files",
"list_vectors",
"list",
"edit",
"commit",
"put_file",
"add_vectors",
"add_documents",
"remove_file",
"remove_vectors",
"create",
],
"*": [
"read",
"get_file",
"get_vector",
"search_by_vector",
"search_by_text",
"list_files",
"list_vectors",
"list",
"edit",
"commit",
"put_file",
"add_vectors",
"add_documents",
"remove_file",
"remove_vectors",
"create",
"reset_stats",
"publish",
Expand Down Expand Up @@ -544,12 +539,19 @@ async def _get_artifact_with_permission(
operation_map = {
"list": UserPermission.read,
"read": UserPermission.read,
"get_vector": UserPermission.read,
"get_file": UserPermission.read,
"list_files": UserPermission.read,
"list_vectors": UserPermission.read,
"search_by_text": UserPermission.read,
"search_by_vector": UserPermission.read,
"create": UserPermission.read_write,
"edit": UserPermission.read_write,
"commit": UserPermission.read_write,
"add_vectors": UserPermission.read_write,
"add_documents": UserPermission.read_write,
"put_file": UserPermission.read_write,
"remove_vectors": UserPermission.read_write,
"remove_file": UserPermission.read_write,
"delete": UserPermission.admin,
"reset_stats": UserPermission.admin,
Expand Down Expand Up @@ -1483,7 +1485,7 @@ async def add_vectors(
try:
async with session.begin():
artifact, _ = await self._get_artifact_with_permission(
user_info, artifact_id, "put_file", session
user_info, artifact_id, "add_vectors", session
)
assert (
artifact.type == "vector-collection"
Expand Down Expand Up @@ -1558,7 +1560,7 @@ async def add_documents(
try:
async with session.begin():
artifact, _ = await self._get_artifact_with_permission(
user_info, artifact_id, "put_file", session
user_info, artifact_id, "add_documents", session
)
assert (
artifact.type == "vector-collection"
Expand Down Expand Up @@ -1601,7 +1603,7 @@ async def search_by_vector(
try:
async with session.begin():
artifact, _ = await self._get_artifact_with_permission(
user_info, artifact_id, "list", session
user_info, artifact_id, "search_by_vector", session
)
assert (
artifact.type == "vector-collection"
Expand Down Expand Up @@ -1644,7 +1646,7 @@ async def search_by_text(
try:
async with session.begin():
artifact, _ = await self._get_artifact_with_permission(
user_info, artifact_id, "list", session
user_info, artifact_id, "search_by_text", session
)
assert (
artifact.type == "vector-collection"
Expand Down Expand Up @@ -1680,7 +1682,7 @@ async def remove_vectors(
try:
async with session.begin():
artifact, _ = await self._get_artifact_with_permission(
user_info, artifact_id, "remove_file", session
user_info, artifact_id, "remove_vectors", session
)
assert (
artifact.type == "vector-collection"
Expand Down Expand Up @@ -1709,7 +1711,7 @@ async def get_vector(
try:
async with session.begin():
artifact, _ = await self._get_artifact_with_permission(
user_info, artifact_id, "get_file", session
user_info, artifact_id, "get_vector", session
)
assert (
artifact.type == "vector-collection"
Expand Down Expand Up @@ -1745,7 +1747,7 @@ async def list_vectors(
try:
async with session.begin():
artifact, _ = await self._get_artifact_with_permission(
user_info, artifact_id, "list", session
user_info, artifact_id, "list_vectors", session
)
assert (
artifact.type == "vector-collection"
Expand Down

0 comments on commit b7e615b

Please sign in to comment.