function update_document_v4
Updates metadata fields of a controlled document in a Neo4j database after validating user permissions and field constraints.
/tf/active/vicechatdev/CDocs copy/controllers/document_controller.py
1584 - 1695
moderate
Purpose
This function provides a secure way to update document metadata in a document management system. It retrieves an existing document by UID, validates that the user has EDIT_DOCUMENT permission, filters the update data to only allowed fields (title, description, department, owner_uid, doc_type, status), executes a Neo4j Cypher query to update the document properties, and creates an audit trail entry. The function handles permission checking with fallback logic for different permission system implementations and returns a structured response indicating success or failure.
Source Code
def update_document(document_uid: str, user: DocUser, data: Dict[str, Any]) -> Dict[str, Any]:
"""
Update document metadata.
Args:
document_uid: UID of the document to update
user: User making the update
data: Dictionary of data to update
Returns:
Dictionary with update result
"""
logger.info(f"Updating document {document_uid}")
logger.debug(f"Update data: {data}")
try:
# Get current document
document = get_document(document_uid)
if not document:
return {
"success": False,
"message": f"Document {document_uid} not found"
}
# Check permissions - fallback to normal permission check if resource method not available
if hasattr(permissions, 'user_has_permission_for_resource'):
has_permission = permissions.user_has_permission_for_resource(
user, "EDIT_DOCUMENT", document
)
else:
has_permission = permissions.user_has_permission(user, "EDIT_DOCUMENT")
if not has_permission:
return {
"success": False,
"message": "You don't have permission to edit this document"
}
# Validate allowed fields
allowed_fields = [
'title', 'description', 'department', 'owner_uid', 'doc_type', 'status'
]
update_data = {k: v for k, v in data.items() if k in allowed_fields}
# If empty update, return success
if not update_data:
return {
"success": True,
"message": "No fields to update",
"document": document
}
# Build update query
set_clauses = []
params = {
"document_uid": document_uid
}
for key, value in update_data.items():
# Use Neo4j property names (camelCase)
neo4j_key = key
if key == 'doc_type':
neo4j_key = 'docType'
set_clauses.append(f"doc.{neo4j_key} = ${key}")
params[key] = value
# Add modified date
from datetime import datetime
modified_date = datetime.now().isoformat()
set_clauses.append("doc.modifiedDate = $modified_date")
params["modified_date"] = modified_date
# Execute update
query = f"""
MATCH (doc:ControlledDocument)
WHERE doc.UID = $document_uid
SET {', '.join(set_clauses)}
RETURN doc
"""
result = db.run_query(query, params)
if result and len(result) > 0:
updated_document = result[0].get('doc')
# Add audit trail entry
create_audit_entry(
user=user,
document_uid=document_uid,
action="UPDATE_METADATA",
details=f"Updated fields: {', '.join(update_data.keys())}"
)
return {
"success": True,
"message": "Document updated successfully",
"document": updated_document
}
else:
return {
"success": False,
"message": "Failed to update document"
}
except Exception as e:
logger.error(f"Error updating document {document_uid}: {e}")
import traceback
logger.error(traceback.format_exc())
return {
"success": False,
"message": str(e)
}
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
document_uid |
str | - | positional_or_keyword |
user |
DocUser | - | positional_or_keyword |
data |
Dict[str, Any] | - | positional_or_keyword |
Parameter Details
document_uid: Unique identifier (UID) string for the document to be updated. Must correspond to an existing document in the database with a matching UID property.
user: DocUser object representing the authenticated user making the update request. Used for permission checking and audit trail creation. Must have appropriate permissions to edit documents.
data: Dictionary containing the metadata fields to update. Keys should match allowed field names (title, description, department, owner_uid, doc_type, status). Only fields present in the allowed_fields list will be processed; other fields are silently ignored.
Return Value
Type: Dict[str, Any]
Returns a dictionary with keys: 'success' (boolean indicating if update succeeded), 'message' (string describing the result or error), and optionally 'document' (the updated document object from Neo4j if successful). On failure, only success and message keys are present. The document key contains the Neo4j node properties when the update succeeds.
Dependencies
loggingdatetimetracebacktypingCDocs.dbCDocs.config.permissionsCDocs.models.user_extensionsCDocs.utils.audit_trail
Required Imports
import logging
from typing import Dict, Any
from datetime import datetime
import traceback
from CDocs import db
from CDocs.config import permissions
from CDocs.models.user_extensions import DocUser
Conditional/Optional Imports
These imports are only needed under specific conditions:
from datetime import datetime
Condition: imported inside the function to set modified_date timestamp
Required (conditional)Usage Example
from CDocs.models.user_extensions import DocUser
from typing import Dict, Any
# Assume user object is already authenticated
user = DocUser(uid='user123', username='john.doe')
# Prepare update data
update_data = {
'title': 'Updated Document Title',
'description': 'New description for the document',
'status': 'DRAFT',
'department': 'Engineering'
}
# Update the document
result = update_document(
document_uid='doc-12345',
user=user,
data=update_data
)
# Check result
if result['success']:
print(f"Document updated: {result['message']}")
updated_doc = result.get('document')
else:
print(f"Update failed: {result['message']}")
Best Practices
- Always check the 'success' field in the returned dictionary before accessing the 'document' field
- Only fields in the allowed_fields list (title, description, department, owner_uid, doc_type, status) will be updated; other fields are ignored
- The function automatically adds a modifiedDate timestamp to track when updates occur
- Permission checking has fallback logic - ensure your permissions module implements at least one of the expected methods
- All updates are logged and create audit trail entries for compliance tracking
- The function handles exceptions gracefully and returns error messages rather than raising exceptions
- Field name 'doc_type' is automatically converted to camelCase 'docType' for Neo4j property naming conventions
- Empty update data (no allowed fields) returns success without making database changes
- Ensure the document_uid exists before calling this function or handle the 'Document not found' error case
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function update_document_v2 82.6% similar
-
function update_document 78.1% similar
-
function update_document_v1 77.8% similar
-
function update_document_v3 77.1% similar
-
function update_document_metadata_in_filecloud 75.3% similar