generated from coulomb/repo-seed
Scoped CMIS workspace folders with create, list, parent, path lookup, delete, and delete-tree behavior
This commit is contained in:
@@ -55,9 +55,11 @@ class CMISAction(str, Enum):
|
||||
QUERY = "query"
|
||||
GET_RELATIONSHIPS = "get_relationships"
|
||||
GET_CHANGE_LOG = "get_change_log"
|
||||
CREATE_FOLDER = "create_folder"
|
||||
CREATE_DOCUMENT = "create_document"
|
||||
UPDATE_PROPERTIES = "update_properties"
|
||||
DELETE_OBJECT = "delete_object"
|
||||
DELETE_TREE = "delete_tree"
|
||||
SET_CONTENT_STREAM = "set_content_stream"
|
||||
APPLY_ACL = "apply_acl"
|
||||
APPLY_POLICY = "apply_policy"
|
||||
@@ -84,9 +86,11 @@ ACTION_CAPABILITIES: dict[CMISAction, CMISCapability] = {
|
||||
CMISAction.QUERY: CMISCapability.DISCOVERY_QUERY,
|
||||
CMISAction.GET_RELATIONSHIPS: CMISCapability.RELATIONSHIPS,
|
||||
CMISAction.GET_CHANGE_LOG: CMISCapability.CHANGE_LOG,
|
||||
CMISAction.CREATE_FOLDER: CMISCapability.OBJECT_WRITE,
|
||||
CMISAction.CREATE_DOCUMENT: CMISCapability.OBJECT_WRITE,
|
||||
CMISAction.UPDATE_PROPERTIES: CMISCapability.OBJECT_WRITE,
|
||||
CMISAction.DELETE_OBJECT: CMISCapability.OBJECT_WRITE,
|
||||
CMISAction.DELETE_TREE: CMISCapability.OBJECT_WRITE,
|
||||
CMISAction.SET_CONTENT_STREAM: CMISCapability.CONTENT_STREAM_WRITE,
|
||||
CMISAction.APPLY_ACL: CMISCapability.ACL,
|
||||
CMISAction.APPLY_POLICY: CMISCapability.POLICY,
|
||||
@@ -104,16 +108,20 @@ IMPLEMENTED_CMIS_ACTIONS: frozenset[CMISAction] = frozenset(
|
||||
CMISAction.QUERY,
|
||||
CMISAction.GET_RELATIONSHIPS,
|
||||
CMISAction.GET_CHANGE_LOG,
|
||||
CMISAction.CREATE_FOLDER,
|
||||
CMISAction.CREATE_DOCUMENT,
|
||||
CMISAction.UPDATE_PROPERTIES,
|
||||
CMISAction.DELETE_OBJECT,
|
||||
CMISAction.DELETE_TREE,
|
||||
CMISAction.SET_CONTENT_STREAM,
|
||||
}
|
||||
)
|
||||
MUTATION_ACTIONS = {
|
||||
CMISAction.CREATE_DOCUMENT,
|
||||
CMISAction.CREATE_FOLDER,
|
||||
CMISAction.UPDATE_PROPERTIES,
|
||||
CMISAction.DELETE_OBJECT,
|
||||
CMISAction.DELETE_TREE,
|
||||
CMISAction.SET_CONTENT_STREAM,
|
||||
CMISAction.APPLY_ACL,
|
||||
CMISAction.APPLY_POLICY,
|
||||
@@ -670,7 +678,7 @@ class CMISDomainMapper:
|
||||
can_write = self.access_point.profile.allow_mutations
|
||||
return [
|
||||
_type_definition(CMISBaseType.DOCUMENT, "kontextual:document", "Kontextual Document", can_write),
|
||||
_type_definition(CMISBaseType.FOLDER, "kontextual:folder", "Kontextual Folder", False),
|
||||
_type_definition(CMISBaseType.FOLDER, "kontextual:folder", "Kontextual Folder", can_write),
|
||||
_type_definition(
|
||||
CMISBaseType.RELATIONSHIP,
|
||||
"kontextual:relationship",
|
||||
@@ -874,6 +882,9 @@ class CMISDomainMapper:
|
||||
"cmis:creationDate": asset.created_at,
|
||||
"cmis:lastModificationDate": asset.updated_at,
|
||||
"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,
|
||||
@@ -890,7 +901,14 @@ class CMISDomainMapper:
|
||||
key = getattr(record, "key", None)
|
||||
if key:
|
||||
properties[f"kontextual:metadata:{key}"] = getattr(record, "value", None)
|
||||
return compact_dict(properties)
|
||||
compacted = compact_dict(properties)
|
||||
compacted.setdefault("cmis:createdBy", "system")
|
||||
compacted.setdefault("cmis:lastModifiedBy", "system")
|
||||
compacted.setdefault("cmis:secondaryObjectTypeIds", [])
|
||||
compacted.setdefault("kontextual:owner", "")
|
||||
compacted.setdefault("kontextual:topics", [])
|
||||
compacted.setdefault("kontextual:reviewState", "")
|
||||
return compacted
|
||||
|
||||
def map_content_stream(
|
||||
self,
|
||||
@@ -925,6 +943,12 @@ class CMISDomainMapper:
|
||||
"cmis:isLatestMajorVersion": True,
|
||||
"cmis:versionSeriesId": f"cmis:version-series:{asset.id}",
|
||||
"cmis:versionLabel": "1",
|
||||
"cmis:isVersionSeriesCheckedOut": False,
|
||||
"cmis:isPrivateWorkingCopy": False,
|
||||
"cmis:versionSeriesCheckedOutBy": None,
|
||||
"cmis:versionSeriesCheckedOutId": None,
|
||||
"cmis:checkinComment": "",
|
||||
"cmis:isImmutable": False,
|
||||
}
|
||||
latest_sequence = max((version.sequence for version in versions), default=current_version.sequence)
|
||||
return {
|
||||
@@ -933,6 +957,12 @@ class CMISDomainMapper:
|
||||
"cmis:isLatestMajorVersion": current_version.sequence == latest_sequence,
|
||||
"cmis:versionSeriesId": f"cmis:version-series:{asset.id}",
|
||||
"cmis:versionLabel": str(current_version.sequence),
|
||||
"cmis:isVersionSeriesCheckedOut": False,
|
||||
"cmis:isPrivateWorkingCopy": False,
|
||||
"cmis:versionSeriesCheckedOutBy": None,
|
||||
"cmis:versionSeriesCheckedOutId": None,
|
||||
"cmis:checkinComment": "",
|
||||
"cmis:isImmutable": False,
|
||||
"kontextual:versionId": current_version.version_id,
|
||||
"kontextual:versionChangeType": current_version.change_type.value,
|
||||
}
|
||||
@@ -1187,7 +1217,10 @@ def cmis_browser_object(projection: dict[str, Any]) -> dict[str, Any]:
|
||||
for key, value in properties.items()
|
||||
},
|
||||
"succinctProperties": properties,
|
||||
"allowableActions": cmis_browser_allowable_actions(projection.get("allowable_actions", [])),
|
||||
"allowableActions": cmis_browser_allowable_actions(
|
||||
projection.get("allowable_actions", []),
|
||||
base_type_id=properties.get("cmis:baseTypeId"),
|
||||
),
|
||||
}
|
||||
acl = projection.get("acl")
|
||||
if isinstance(acl, dict) and acl:
|
||||
@@ -1292,8 +1325,13 @@ def cmis_browser_property_value(property_id: str, value: Any) -> dict[str, Any]:
|
||||
}
|
||||
|
||||
|
||||
def cmis_browser_allowable_actions(actions: list[str] | tuple[str, ...]) -> dict[str, bool]:
|
||||
def cmis_browser_allowable_actions(
|
||||
actions: list[str] | tuple[str, ...],
|
||||
*,
|
||||
base_type_id: str | None = None,
|
||||
) -> dict[str, bool]:
|
||||
native = set(actions)
|
||||
is_folder = base_type_id == CMISBaseType.FOLDER.value
|
||||
return {
|
||||
"canGetObjectParents": CMISAction.GET_OBJECT_PARENTS.value in native,
|
||||
"canGetProperties": CMISAction.GET_OBJECT.value in native,
|
||||
@@ -1305,13 +1343,13 @@ def cmis_browser_allowable_actions(actions: list[str] | tuple[str, ...]) -> dict
|
||||
"canSetContentStream": CMISAction.SET_CONTENT_STREAM.value in native,
|
||||
"canGetChildren": CMISAction.GET_CHILDREN.value in native,
|
||||
"canCreateDocument": CMISAction.CREATE_DOCUMENT.value in native,
|
||||
"canCreateFolder": False,
|
||||
"canCreateFolder": CMISAction.CREATE_FOLDER.value in native,
|
||||
"canCreateRelationship": False,
|
||||
"canCreateItem": False,
|
||||
"canDeleteTree": False,
|
||||
"canDeleteTree": CMISAction.DELETE_TREE.value in native,
|
||||
"canGetDescendants": False,
|
||||
"canGetFolderTree": False,
|
||||
"canGetFolderParent": False,
|
||||
"canGetFolderParent": is_folder and CMISAction.GET_OBJECT_PARENTS.value in native,
|
||||
"canGetRenditions": False,
|
||||
"canMoveObject": False,
|
||||
"canAddObjectToFolder": False,
|
||||
@@ -1329,6 +1367,9 @@ def cmis_browser_allowable_actions(actions: list[str] | tuple[str, ...]) -> dict
|
||||
|
||||
|
||||
def cmis_browser_root_folder(access_point: CMISAccessPoint) -> dict[str, Any]:
|
||||
allowable_actions = [CMISAction.GET_OBJECT.value, CMISAction.GET_CHILDREN.value]
|
||||
if access_point.profile.allow_mutations:
|
||||
allowable_actions.extend([CMISAction.CREATE_DOCUMENT.value, CMISAction.CREATE_FOLDER.value])
|
||||
return {
|
||||
"object_id": access_point.root_folder_id,
|
||||
"base_type_id": CMISBaseType.FOLDER.value,
|
||||
@@ -1352,8 +1393,10 @@ def cmis_browser_root_folder(access_point: CMISAccessPoint) -> dict[str, Any]:
|
||||
"cmis:allowedChildObjectTypeIds": [CMISBaseType.DOCUMENT.value, CMISBaseType.FOLDER.value],
|
||||
"kontextual:sensitivity": "internal",
|
||||
"kontextual:lifecycle": LifecycleState.ACTIVE.value,
|
||||
"kontextual:filingSource": "root",
|
||||
"kontextual:workspaceFolder": False,
|
||||
},
|
||||
"allowable_actions": [CMISAction.GET_OBJECT.value, CMISAction.GET_CHILDREN.value],
|
||||
"allowable_actions": allowable_actions,
|
||||
}
|
||||
|
||||
|
||||
@@ -1545,6 +1588,7 @@ def _browser_propdef(
|
||||
|
||||
def _browser_object_properties(projection: dict[str, Any]) -> dict[str, Any]:
|
||||
properties = dict(projection.get("properties", {}))
|
||||
properties.update(projection.get("version", {}))
|
||||
base_type = projection.get("base_type_id") or properties.get("cmis:baseTypeId")
|
||||
properties["cmis:objectId"] = projection.get("object_id", properties.get("cmis:objectId"))
|
||||
properties["cmis:name"] = projection.get("name", properties.get("cmis:name"))
|
||||
@@ -1612,8 +1656,8 @@ def _type_definition(
|
||||
"queryable": is_document,
|
||||
"controllable_acl": is_document,
|
||||
"controllable_policy": False,
|
||||
"creatable": can_write and is_document,
|
||||
"fileable": is_document,
|
||||
"creatable": can_write and base_type_id in {CMISBaseType.DOCUMENT, CMISBaseType.FOLDER},
|
||||
"fileable": base_type_id in {CMISBaseType.DOCUMENT, CMISBaseType.FOLDER},
|
||||
"fulltext_indexed": False,
|
||||
"included_in_supertype_query": is_document,
|
||||
"versionable": False,
|
||||
@@ -1627,6 +1671,14 @@ def _property_definitions(base_type_id: CMISBaseType) -> dict[str, dict[str, Any
|
||||
"cmis:name": {"property_type": "string", "cardinality": "single", "required": True},
|
||||
"cmis:baseTypeId": {"property_type": "id", "cardinality": "single", "required": True},
|
||||
"cmis:objectTypeId": {"property_type": "id", "cardinality": "single", "required": True},
|
||||
"cmis:createdBy": {"property_type": "string", "cardinality": "single", "required": False},
|
||||
"cmis:lastModifiedBy": {"property_type": "string", "cardinality": "single", "required": False},
|
||||
"cmis:creationDate": {"property_type": "datetime", "cardinality": "single", "required": False},
|
||||
"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},
|
||||
}
|
||||
@@ -1653,8 +1705,109 @@ def _property_definitions(base_type_id: CMISBaseType) -> dict[str, dict[str, Any
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
"kontextual:assetId": {
|
||||
"property_type": "id",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
"kontextual:assetType": {
|
||||
"property_type": "string",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
"kontextual:owner": {
|
||||
"property_type": "string",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
"kontextual:topics": {
|
||||
"property_type": "string",
|
||||
"cardinality": "multi",
|
||||
"required": False,
|
||||
},
|
||||
"kontextual:reviewState": {
|
||||
"property_type": "string",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
"cmis:isImmutable": {
|
||||
"property_type": "boolean",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
"cmis:isLatestVersion": {
|
||||
"property_type": "boolean",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
"cmis:isMajorVersion": {
|
||||
"property_type": "boolean",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
"cmis:isLatestMajorVersion": {
|
||||
"property_type": "boolean",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
"cmis:versionLabel": {
|
||||
"property_type": "string",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
"cmis:versionSeriesId": {
|
||||
"property_type": "id",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
"cmis:isVersionSeriesCheckedOut": {
|
||||
"property_type": "boolean",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
"cmis:isPrivateWorkingCopy": {
|
||||
"property_type": "boolean",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
"cmis:versionSeriesCheckedOutBy": {
|
||||
"property_type": "string",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
"cmis:versionSeriesCheckedOutId": {
|
||||
"property_type": "id",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
"cmis:checkinComment": {
|
||||
"property_type": "string",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
"kontextual:versionId": {
|
||||
"property_type": "id",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
"kontextual:versionChangeType": {
|
||||
"property_type": "string",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
},
|
||||
}
|
||||
)
|
||||
if base_type_id == CMISBaseType.FOLDER:
|
||||
definitions["kontextual:filingSource"] = {
|
||||
"property_type": "string",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
}
|
||||
definitions["kontextual:workspaceFolder"] = {
|
||||
"property_type": "boolean",
|
||||
"cardinality": "single",
|
||||
"required": False,
|
||||
}
|
||||
if base_type_id == CMISBaseType.RELATIONSHIP:
|
||||
definitions["cmis:sourceId"] = {"property_type": "id", "cardinality": "single", "required": True}
|
||||
definitions["cmis:targetId"] = {"property_type": "id", "cardinality": "single", "required": True}
|
||||
|
||||
Reference in New Issue
Block a user