generated from coulomb/repo-seed
CMIS Browser Binding fixes
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -58,6 +58,7 @@ class CMISAction(str, Enum):
|
||||
CREATE_FOLDER = "create_folder"
|
||||
CREATE_DOCUMENT = "create_document"
|
||||
UPDATE_PROPERTIES = "update_properties"
|
||||
MOVE_OBJECT = "move_object"
|
||||
DELETE_OBJECT = "delete_object"
|
||||
DELETE_TREE = "delete_tree"
|
||||
SET_CONTENT_STREAM = "set_content_stream"
|
||||
@@ -89,6 +90,7 @@ ACTION_CAPABILITIES: dict[CMISAction, CMISCapability] = {
|
||||
CMISAction.CREATE_FOLDER: CMISCapability.OBJECT_WRITE,
|
||||
CMISAction.CREATE_DOCUMENT: CMISCapability.OBJECT_WRITE,
|
||||
CMISAction.UPDATE_PROPERTIES: CMISCapability.OBJECT_WRITE,
|
||||
CMISAction.MOVE_OBJECT: CMISCapability.OBJECT_WRITE,
|
||||
CMISAction.DELETE_OBJECT: CMISCapability.OBJECT_WRITE,
|
||||
CMISAction.DELETE_TREE: CMISCapability.OBJECT_WRITE,
|
||||
CMISAction.SET_CONTENT_STREAM: CMISCapability.CONTENT_STREAM_WRITE,
|
||||
@@ -111,6 +113,7 @@ IMPLEMENTED_CMIS_ACTIONS: frozenset[CMISAction] = frozenset(
|
||||
CMISAction.CREATE_FOLDER,
|
||||
CMISAction.CREATE_DOCUMENT,
|
||||
CMISAction.UPDATE_PROPERTIES,
|
||||
CMISAction.MOVE_OBJECT,
|
||||
CMISAction.DELETE_OBJECT,
|
||||
CMISAction.DELETE_TREE,
|
||||
CMISAction.SET_CONTENT_STREAM,
|
||||
@@ -120,6 +123,7 @@ MUTATION_ACTIONS = {
|
||||
CMISAction.CREATE_DOCUMENT,
|
||||
CMISAction.CREATE_FOLDER,
|
||||
CMISAction.UPDATE_PROPERTIES,
|
||||
CMISAction.MOVE_OBJECT,
|
||||
CMISAction.DELETE_OBJECT,
|
||||
CMISAction.DELETE_TREE,
|
||||
CMISAction.SET_CONTENT_STREAM,
|
||||
@@ -884,7 +888,6 @@ class CMISDomainMapper:
|
||||
"cmis:changeToken": asset.current_version_id,
|
||||
"cmis:description": asset.metadata.get("description", asset.title),
|
||||
"cmis:secondaryObjectTypeIds": list(asset.metadata.get("cmis_secondary_object_type_ids", ())),
|
||||
"cmis:path": self.asset_path(asset),
|
||||
"cmis:contentStreamLength": content_stream.get("length") if content_stream else None,
|
||||
"cmis:contentStreamMimeType": content_stream.get("mime_type") if content_stream else None,
|
||||
"cmis:contentStreamFileName": content_stream.get("file_name") if content_stream else None,
|
||||
@@ -905,6 +908,10 @@ class CMISDomainMapper:
|
||||
compacted.setdefault("cmis:createdBy", "system")
|
||||
compacted.setdefault("cmis:lastModifiedBy", "system")
|
||||
compacted.setdefault("cmis:secondaryObjectTypeIds", [])
|
||||
compacted.setdefault("cmis:contentStreamLength", None)
|
||||
compacted.setdefault("cmis:contentStreamMimeType", None)
|
||||
compacted.setdefault("cmis:contentStreamFileName", None)
|
||||
compacted.setdefault("cmis:contentStreamId", None)
|
||||
compacted.setdefault("kontextual:owner", "")
|
||||
compacted.setdefault("kontextual:topics", [])
|
||||
compacted.setdefault("kontextual:reviewState", "")
|
||||
@@ -980,6 +987,7 @@ class CMISDomainMapper:
|
||||
CMISAction.GET_RELATIONSHIPS,
|
||||
CMISAction.GET_OBJECT_PARENTS,
|
||||
CMISAction.UPDATE_PROPERTIES,
|
||||
CMISAction.MOVE_OBJECT,
|
||||
CMISAction.DELETE_OBJECT,
|
||||
CMISAction.SET_CONTENT_STREAM,
|
||||
]
|
||||
@@ -1209,39 +1217,61 @@ def cmis_browser_type_definition_by_id(
|
||||
raise KeyError(type_id)
|
||||
|
||||
|
||||
def cmis_browser_object(projection: dict[str, Any]) -> dict[str, Any]:
|
||||
properties = _browser_object_properties(projection)
|
||||
def cmis_browser_object(
|
||||
projection: dict[str, Any],
|
||||
*,
|
||||
property_filter: str | None = None,
|
||||
include_allowable_actions: bool = True,
|
||||
include_acl: bool = True,
|
||||
) -> dict[str, Any]:
|
||||
unfiltered_properties = _browser_object_properties(projection)
|
||||
properties = _filter_browser_properties(unfiltered_properties, property_filter)
|
||||
result = {
|
||||
"properties": {
|
||||
key: cmis_browser_property_value(key, value)
|
||||
for key, value in properties.items()
|
||||
},
|
||||
"succinctProperties": properties,
|
||||
"allowableActions": cmis_browser_allowable_actions(
|
||||
projection.get("allowable_actions", []),
|
||||
base_type_id=properties.get("cmis:baseTypeId"),
|
||||
),
|
||||
}
|
||||
acl = projection.get("acl")
|
||||
if include_allowable_actions:
|
||||
result["allowableActions"] = cmis_browser_allowable_actions(
|
||||
projection.get("allowable_actions", []),
|
||||
base_type_id=unfiltered_properties.get("cmis:baseTypeId"),
|
||||
)
|
||||
acl = projection.get("acl") if include_acl else None
|
||||
if isinstance(acl, dict) and acl:
|
||||
result["acl"] = cmis_browser_acl(acl)
|
||||
result["exactACL"] = bool(acl.get("is_exact", True))
|
||||
return compact_dict(result)
|
||||
|
||||
|
||||
def cmis_browser_object_in_folder_list(children: dict[str, Any]) -> dict[str, Any]:
|
||||
def cmis_browser_object_in_folder_list(
|
||||
children: dict[str, Any],
|
||||
*,
|
||||
property_filter: str | None = None,
|
||||
include_allowable_actions: bool = True,
|
||||
include_acl: bool = True,
|
||||
include_path_segment: bool = True,
|
||||
) -> dict[str, Any]:
|
||||
objects = []
|
||||
for item in children.get("objects", []):
|
||||
entry = {
|
||||
"object": cmis_browser_object(
|
||||
item,
|
||||
property_filter=property_filter,
|
||||
include_allowable_actions=include_allowable_actions,
|
||||
include_acl=include_acl,
|
||||
),
|
||||
}
|
||||
if include_path_segment:
|
||||
entry["pathSegment"] = item.get("name") or item.get("object_id")
|
||||
objects.append(
|
||||
{
|
||||
"object": cmis_browser_object(item),
|
||||
"pathSegment": item.get("name") or item.get("object_id"),
|
||||
}
|
||||
entry
|
||||
)
|
||||
return {
|
||||
"objects": objects,
|
||||
"hasMoreItems": bool(children.get("has_more_items", False)),
|
||||
"numItems": int(children.get("num_items", len(objects))),
|
||||
"numItems": int(children.get("total_num_items", children.get("num_items", len(objects)))),
|
||||
}
|
||||
|
||||
|
||||
@@ -1253,15 +1283,17 @@ def cmis_browser_object_list(objects: list[dict[str, Any]], *, has_more_items: b
|
||||
}
|
||||
|
||||
|
||||
def cmis_browser_parent_list(parents: dict[str, Any]) -> list[dict[str, Any]]:
|
||||
def cmis_browser_parent_list(
|
||||
parents: dict[str, Any],
|
||||
*,
|
||||
include_relative_path_segment: bool = True,
|
||||
) -> list[dict[str, Any]]:
|
||||
items = []
|
||||
for parent in parents.get("parents", []):
|
||||
items.append(
|
||||
{
|
||||
"object": cmis_browser_object(parent),
|
||||
"relativePathSegment": parent.get("name"),
|
||||
}
|
||||
)
|
||||
item = {"object": cmis_browser_object(parent)}
|
||||
if include_relative_path_segment:
|
||||
item["relativePathSegment"] = parent.get("relative_path_segment") or parent.get("name")
|
||||
items.append(item)
|
||||
return items
|
||||
|
||||
|
||||
@@ -1270,7 +1302,7 @@ def cmis_browser_query_result(query_result: dict[str, Any]) -> dict[str, Any]:
|
||||
return {
|
||||
"results": results,
|
||||
"hasMoreItems": bool(query_result.get("has_more_items", False)),
|
||||
"numItems": int(query_result.get("num_items", len(results))),
|
||||
"numItems": int(query_result.get("total_num_items", query_result.get("num_items", len(results)))),
|
||||
}
|
||||
|
||||
|
||||
@@ -1351,7 +1383,7 @@ def cmis_browser_allowable_actions(
|
||||
"canGetFolderTree": False,
|
||||
"canGetFolderParent": is_folder and CMISAction.GET_OBJECT_PARENTS.value in native,
|
||||
"canGetRenditions": False,
|
||||
"canMoveObject": False,
|
||||
"canMoveObject": CMISAction.MOVE_OBJECT.value in native,
|
||||
"canAddObjectToFolder": False,
|
||||
"canRemoveObjectFromFolder": False,
|
||||
"canCheckOut": False,
|
||||
@@ -1362,7 +1394,7 @@ def cmis_browser_allowable_actions(
|
||||
"canRemovePolicy": False,
|
||||
"canGetAppliedPolicies": False,
|
||||
"canApplyACL": False,
|
||||
"canDeleteContentStream": False,
|
||||
"canDeleteContentStream": CMISAction.SET_CONTENT_STREAM.value in native,
|
||||
}
|
||||
|
||||
|
||||
@@ -1600,6 +1632,23 @@ def _browser_object_properties(projection: dict[str, Any]) -> dict[str, Any]:
|
||||
return properties
|
||||
|
||||
|
||||
def _filter_browser_properties(properties: dict[str, Any], property_filter: str | None) -> dict[str, Any]:
|
||||
if property_filter is None:
|
||||
return properties
|
||||
requested = {
|
||||
part.strip()
|
||||
for part in property_filter.split(",")
|
||||
if part.strip()
|
||||
}
|
||||
if not requested or "*" in requested:
|
||||
return properties
|
||||
return {
|
||||
key: value
|
||||
for key, value in properties.items()
|
||||
if key in requested or any(pattern.endswith(":*") and key.startswith(pattern[:-1]) for pattern in requested)
|
||||
}
|
||||
|
||||
|
||||
def _browser_property_type(property_id: str, value: Any) -> str:
|
||||
if property_id in {
|
||||
"cmis:objectId",
|
||||
@@ -1677,11 +1726,12 @@ def _property_definitions(base_type_id: CMISBaseType) -> dict[str, dict[str, Any
|
||||
"cmis:lastModificationDate": {"property_type": "datetime", "cardinality": "single", "required": False},
|
||||
"cmis:changeToken": {"property_type": "string", "cardinality": "single", "required": False},
|
||||
"cmis:secondaryObjectTypeIds": {"property_type": "id", "cardinality": "multi", "required": False},
|
||||
"cmis:path": {"property_type": "string", "cardinality": "single", "required": False},
|
||||
"cmis:description": {"property_type": "string", "cardinality": "single", "required": False},
|
||||
"kontextual:sensitivity": {"property_type": "string", "cardinality": "single", "required": False},
|
||||
"kontextual:lifecycle": {"property_type": "string", "cardinality": "single", "required": False},
|
||||
}
|
||||
if base_type_id == CMISBaseType.FOLDER:
|
||||
definitions["cmis:path"] = {"property_type": "string", "cardinality": "single", "required": False}
|
||||
if base_type_id == CMISBaseType.DOCUMENT:
|
||||
definitions.update(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user