class FileCloudIntegration
Manages integration with FileCloud for document storage and metadata
/tf/active/vicechatdev/CDocs/utils/filecloud_integration.py
26 - 1313
moderate
Purpose
Manages integration with FileCloud for document storage and metadata
Source Code
class FileCloudIntegration:
"""Manages integration with FileCloud for document storage and metadata"""
def __init__(self, server_url: str, username: str, password: str):
"""
Initialize FileCloud integration
Parameters
----------
server_url : str
URL of the FileCloud server
username : str
FileCloud username
password : str
FileCloud password
"""
self.client = FileCloudAPI(server_url, username, password)
self.metadata_catalog = MetadataCatalog(self.client)
logger.debug("Initialized FileCloud integration")
def connect(self) -> bool:
"""
Establish connection to FileCloud
Returns
-------
bool
True if connection successful, False otherwise
"""
try:
return self.client.login()
except Exception as e:
logger.error(f"Error connecting to FileCloud: {str(e)}")
return False
def upload_document(self, local_file_path: str, remote_folder_path: str,
filename: Optional[str] = None,
metadata: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
"""
Upload a document to FileCloud
Parameters
----------
local_file_path : str
Path to the local file
remote_folder_path : str
Path to the remote folder
filename : str, optional
Name to use for the uploaded file
metadata : Dict[str, Any], optional
Metadata to attach to the file
Returns
-------
Dict[str, Any]
Upload result including file path
"""
try:
# Ensure folder exists
self._ensure_folder_exists(remote_folder_path)
# Upload file
result = self.client.upload_file(
local_file_path=local_file_path,
remote_path=remote_folder_path,
filename=filename,
overwrite=True
)
if not result.get('success', False):
return result
# Get full path to the uploaded file
if filename:
file_path = os.path.join(remote_folder_path, filename)
else:
file_path = os.path.join(remote_folder_path, os.path.basename(local_file_path))
# Add metadata if provided
if metadata and file_path:
self._set_document_metadata(file_path, metadata)
# Add path to result
result['file_path'] = file_path
return result
except Exception as e:
logger.error(f"Error uploading document to FileCloud: {str(e)}")
return {'success': False, 'message': f'Upload error: {str(e)}'}
def download_document(self, file_path: str, local_path: Optional[str] = None) -> Dict[str, Any]:
"""
Download a document from FileCloud
Parameters
----------
file_path : str
Path to the file in FileCloud
local_path : str, optional
Local path where to save the file
Returns
-------
Dict[str, Any]
Download result with file content if local_path not provided
"""
try:
result = self.client.download_file(file_path, local_path)
if local_path and isinstance(result, dict) and result.get('success', False):
return {
'success': True,
'local_path': local_path,
'file_path': file_path
}
if not local_path and isinstance(result, bytes):
return {
'success': True,
'content': result,
'file_path': file_path
}
return result
except Exception as e:
logger.error(f"Error downloading document from FileCloud: {str(e)}")
return {'success': False, 'message': f'Download error: {str(e)}'}
def get_edit_url(self, file_path: str) -> Dict[str, Any]:
"""
Get URL for online editing
Parameters
----------
file_path : str
Path to the file in FileCloud
Returns
-------
Dict[str, Any]
Result with edit URL
"""
try:
# Check if file exists
file_exists = self.client.check_file_exists(file_path)
if not file_exists:
return {'success': False, 'message': f'File not found: {file_path}'}
# Create a temporary share for editing
share_result = self.client.create_document_share(
file_path=file_path,
share_type="collaborate",
expiry_days=1 # 24-hour expiry
)
if not share_result.get('success', False):
return {'success': False, 'message': f'Failed to create edit URL: {share_result.get("message", "Unknown error")}'}
# Return the share URL
return {
'success': True,
'edit_url': share_result.get('share_url'),
'file_path': file_path,
'share_id': share_result.get('share_id'),
'expires': datetime.datetime.now() + datetime.timedelta(days=1)
}
except Exception as e:
logger.error(f"Error creating edit URL: {str(e)}")
return {'success': False, 'message': f'Error creating edit URL: {str(e)}'}
def get_view_url(self, file_path: str) -> Dict[str, Any]:
"""
Get URL for viewing a document
Parameters
----------
file_path : str
Path to the file in FileCloud
Returns
-------
Dict[str, Any]
Result with view URL
"""
try:
# Check if file exists
file_exists = self.client.check_file_exists(file_path)
if not file_exists:
return {'success': False, 'message': f'File not found: {file_path}'}
# Create a temporary share for viewing
share_result = self.client.create_document_share(
file_path=file_path,
share_type="view",
expiry_days=1 # 24-hour expiry
)
if not share_result.get('success', False):
return {'success': False, 'message': f'Failed to create view URL: {share_result.get("message", "Unknown error")}'}
# Return the share URL
return {
'success': True,
'view_url': share_result.get('share_url'),
'file_path': file_path,
'share_id': share_result.get('share_id'),
'expires': datetime.datetime.now() + datetime.timedelta(days=1)
}
except Exception as e:
logger.error(f"Error creating view URL: {str(e)}")
return {'success': False, 'message': f'Error creating view URL: {str(e)}'}
def create_document_version(self, document: ControlledDocument,
local_file_path: str,
version_number: str,
created_by: str,
version_comment: str = None) -> Optional[DocumentVersion]:
"""
Create a new version of a controlled document
Parameters
----------
document : ControlledDocument
The document to create a version for
local_file_path : str
Path to the local file
version_number : str
Version number (e.g., "1.0")
created_by : str
UID of the user creating the version
version_comment : str, optional
Comment for the version
Returns
-------
Optional[DocumentVersion]
The new document version or None if creation failed
"""
try:
# Get file extension and type
_, file_ext = os.path.splitext(local_file_path)
is_word = file_ext.lower() in ['.docx', '.doc', '.rtf']
is_pdf = file_ext.lower() == '.pdf'
# Get folder path from centralized function
from CDocs.controllers.filecloud_controller import get_filecloud_document_path
# This will create the path based on document settings (custom or standard)
target_path = get_filecloud_document_path(document, version_number)
version_folder = os.path.dirname(target_path)
# Ensure folder structure exists
self._ensure_folder_exists(version_folder)
# Get filename from path
filename = os.path.basename(target_path)
# Upload file to FileCloud
upload_result = self.upload_document(
local_file_path=local_file_path,
remote_folder_path=version_folder,
filename=filename
)
if not upload_result.get('success', False):
logger.error(f"Failed to upload file: {upload_result.get('message')}")
return None
# Prepare file paths
file_paths = {}
if is_word:
file_paths['word'] = upload_result['file_path']
elif is_pdf:
file_paths['pdf'] = upload_result['file_path']
# Create document version
properties = {
'changeSummary': version_comment if version_comment else '',
'file_type': file_ext.lstrip('.').lower(),
'file_name': filename
}
# Create version in the database
version = document.create_version(
version_number=version_number,
created_by=created_by,
file_paths=file_paths,
properties=properties
)
return version
except Exception as e:
logger.error(f"Error creating document version: {str(e)}")
logger.error(traceback.format_exc())
return None
def upload_new_controlled_document(self,
local_file_path: str,
title: str,
doc_type: str,
department: str,
owner_uid: str,
initial_version: str = "1.0",
additional_metadata: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
"""
Upload a new controlled document to FileCloud and create it in the database
Parameters
----------
local_file_path : str
Path to the local file
title : str
Document title
doc_type : str
Document type code or name
department : str
Department code or name
owner_uid : str
UID of the document owner
initial_version : str, optional
Initial version number (default: "1.0")
additional_metadata : Dict[str, Any], optional
Additional metadata for the document
Returns
-------
Dict[str, Any]
Result with document and version information
"""
try:
# Create controlled document in database
document = ControlledDocument.create(
title=title,
doc_type=doc_type,
department=department,
owner=owner_uid
)
if not document:
return {
'success': False,
'message': 'Failed to create controlled document in database'
}
# Create initial version
version = self.create_document_version(
document=document,
local_file_path=local_file_path,
version_number=initial_version,
created_by=owner_uid
)
if not version:
return {
'success': False,
'message': 'Failed to create document version in FileCloud'
}
# Add FileCloud metadata
doc_metadata = {
'DocNumber': document.doc_number,
'Title': title,
'Department': document.get_department_name(),
'DocType': document.doc_type_name,
'Version': initial_version,
'Status': document.get_status_name()
}
# Add any additional metadata
if additional_metadata:
doc_metadata.update(additional_metadata)
# Set metadata on the file
self._set_document_metadata(version.word_file_path or version.pdf_file_path, doc_metadata)
return {
'success': True,
'document': document.to_dict(),
'version': version.to_dict(),
'doc_number': document.doc_number,
'file_path': version.word_file_path or version.pdf_file_path
}
except Exception as e:
logger.error(f"Error uploading new controlled document: {str(e)}")
return {'success': False, 'message': f'Upload error: {str(e)}'}
def update_document_metadata(self, document_uid: str, metadata: Dict[str, Any]) -> Dict[str, Any]:
"""
Update metadata for a document both in database and FileCloud
Parameters
----------
document_uid : str
UID of the document to update
metadata : Dict[str, Any]
Metadata to update
Returns
-------
Dict[str, Any]
Result of the update
"""
try:
# Get document from database
document = ControlledDocument(uid=document_uid)
if not document.uid:
return {'success': False, 'message': f'Document not found: {document_uid}'}
# Get current version
current_version = document.current_version
if not current_version:
return {'success': False, 'message': f'Document has no current version'}
# Update document properties in database
properties_to_update = {}
if 'title' in metadata:
properties_to_update['title'] = metadata['title']
if 'docType' in metadata:
properties_to_update['docType'] = metadata['docType']
if 'department' in metadata:
properties_to_update['department'] = metadata['department']
if properties_to_update:
db.update_node(document.uid, properties_to_update)
# Update FileCloud metadata if we have a file path
file_path = current_version.word_file_path or current_version.pdf_file_path
if file_path:
fc_metadata = {
'DocNumber': document.doc_number,
'Title': document.title,
'Department': document.get_department_name(),
'DocType': document.doc_type_name,
'Version': current_version.version_number,
'Status': document.get_status_name()
}
self._set_document_metadata(file_path, fc_metadata)
return {
'success': True,
'document': document.to_dict(),
'message': 'Document metadata updated successfully'
}
except Exception as e:
logger.error(f"Error updating document metadata: {str(e)}")
return {'success': False, 'message': f'Update error: {str(e)}'}
def convert_to_pdf(self, document_version: DocumentVersion) -> Dict[str, Any]:
"""
Convert a document version to PDF using FileCloud's conversion service
Parameters
----------
document_version : DocumentVersion
The document version to convert
Returns
-------
Dict[str, Any]
Result of the conversion
"""
try:
# Use the centralized function to get the Word file path
from CDocs.controllers.filecloud_controller import get_filecloud_document_path
document = document_version.document
if not document:
return {'success': False, 'message': 'Document not available'}
# Get the editable file path
word_path = get_filecloud_document_path(
document=document,
version=document_version.version_number
)
if not word_path:
return {'success': False, 'message': 'No Word document to convert'}
# Check if document already has a PDF version
pdf_path = f"{os.path.splitext(word_path)[0]}.pdf"
# Check if PDF already exists
if self.check_file_exists(pdf_path):
return {
'success': True,
'message': 'PDF already exists',
'pdf_path': pdf_path
}
# Determine file type
_, ext = os.path.splitext(word_path)
ext = ext.lower()
# Only convert supported file types
if ext not in ['.doc', '.docx', '.rtf', '.odt', '.txt']:
return {
'success': False,
'message': f'File type {ext} not supported for conversion'
}
# Create temporary directory for processing
temp_dir = tempfile.mkdtemp()
try:
# Download the document
download_result = self.download_document(word_path)
if not download_result.get('success', False):
return {
'success': False,
'message': f"Download failed: {download_result.get('message', 'Unknown error')}"
}
# Save to temp file
temp_doc_path = os.path.join(temp_dir, f"document{ext}")
with open(temp_doc_path, 'wb') as f:
f.write(download_result['content'])
# Set up output path
temp_pdf_path = os.path.join(temp_dir, "document.pdf")
# Convert to PDF using LibreOffice
conversion_command = [
'libreoffice',
'--headless',
'--convert-to', 'pdf',
'--outdir', temp_dir,
temp_doc_path
]
# Run conversion process
process = subprocess.Popen(
conversion_command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout, stderr = process.communicate()
if process.returncode != 0:
return {
'success': False,
'message': f'PDF conversion failed: {stderr.decode()}'
}
# Check if PDF was created
if not os.path.exists(temp_pdf_path):
# Check for file with a different name (LibreOffice may use the original filename)
base_filename = os.path.splitext(os.path.basename(temp_doc_path))[0]
potential_pdf = os.path.join(temp_dir, f"{base_filename}.pdf")
if os.path.exists(potential_pdf):
temp_pdf_path = potential_pdf
else:
return {
'success': False,
'message': 'PDF file not created by conversion process'
}
# Upload PDF to FileCloud
with open(temp_pdf_path, 'rb') as f:
pdf_content = f.read()
# Extract directory path and filename
pdf_dir = os.path.dirname(pdf_path)
pdf_filename = os.path.basename(pdf_path)
# Ensure directory exists
self._ensure_folder_exists(pdf_dir)
# Upload the PDF
upload_result = self.upload_document(
local_file_path=temp_pdf_path,
remote_folder_path=pdf_dir,
filename=pdf_filename
)
if not upload_result.get('success', False):
return {
'success': False,
'message': f"Upload failed: {upload_result.get('message', 'Unknown error')}"
}
# Update the document version with PDF path
document_version.pdf_file_path = pdf_path
# Add metadata about conversion
metadata = {
'converted_on': datetime.now().isoformat(),
'source_path': word_path,
'pdf_path': pdf_path,
'conversion_method': 'libreoffice'
}
self.add_file_metadata(pdf_path, metadata)
return {
'success': True,
'message': 'Document successfully converted to PDF',
'pdf_path': pdf_path
}
except Exception as e:
return {
'success': False,
'message': f'Error during conversion: {str(e)}'
}
finally:
# Clean up temporary directory
try:
if os.path.exists(temp_dir):
shutil.rmtree(temp_dir)
except Exception as cleanup_err:
logger.warning(f"Failed to clean up temporary directory: {cleanup_err}")
except Exception as e:
logger.error(f"Error in convert_to_pdf: {e}")
logger.error(traceback.format_exc())
return {
'success': False,
'message': f'Conversion error: {str(e)}'
}
def get_document_metadata(self, file_path: str) -> Dict[str, Any]:
"""
Get metadata for a document from FileCloud
Parameters
----------
file_path : str
Path to the file in FileCloud
Returns
-------
Dict[str, Any]
Document metadata
"""
try:
# Get metadata from FileCloud
metadata_result = self.metadata_catalog.get_metadata_values(file_path)
if not metadata_result.get('success', False):
return {'success': False, 'message': f'Failed to get metadata: {metadata_result.get("message")}'}
# Convert to simple dictionary format
attribute_values = self.metadata_catalog.get_attribute_values(metadata_result)
return {
'success': True,
'metadata': attribute_values,
'file_path': file_path
}
except Exception as e:
logger.error(f"Error getting document metadata: {str(e)}")
return {'success': False, 'message': f'Metadata retrieval error: {str(e)}'}
def search_documents(self, search_criteria: Dict[str, Any]) -> List[Dict[str, Any]]:
"""
Search for documents in FileCloud based on metadata
Parameters
----------
search_criteria : Dict[str, Any]
Search criteria with keys matching metadata attribute names
Returns
-------
List[Dict[str, Any]]
List of matching documents
"""
try:
# Format criteria for metadata search
formatted_criteria = []
for key, value in search_criteria.items():
if value is not None:
formatted_criteria.append({
'set_name': 'ControlledDocument',
'attribute_name': key,
'value': value,
'operator': 'equals'
})
# Perform search
search_results = self.metadata_catalog.search_files_by_metadata(
search_criteria=formatted_criteria,
search_string="**", # Match any filename
search_location="/documents" # Limit to documents folder
)
# Get metadata for each result
documents = []
for file_path in search_results:
metadata_result = self.get_document_metadata(file_path)
if metadata_result.get('success', False):
documents.append({
'file_path': file_path,
'metadata': metadata_result.get('metadata', {})
})
return documents
except Exception as e:
logger.error(f"Error searching documents: {str(e)}")
return []
def _ensure_folder_exists(self, folder_path: str) -> bool:
"""
Ensure a folder exists in FileCloud, creating it if necessary
Parameters
----------
folder_path : str
Path to the folder
Returns
-------
bool
True if folder exists or was created, False otherwise
"""
try:
# Check if folder exists
folder_exists = self.client.check_folder_exists(folder_path)
if folder_exists:
return True
# Create folder with parent folders
result = self.client.create_directory_tree("", folder_path)
return result.get('success', False)
except Exception as e:
logger.error(f"Error ensuring folder exists: {str(e)}")
return False
def _set_document_metadata(self, file_path: str, metadata: Dict[str, Any]) -> Dict[str, Any]:
"""
Set metadata for a document
Parameters
----------
file_path : str
Path to the file
metadata : Dict[str, Any]
Metadata to set
Returns
-------
Dict[str, Any]
Result of setting metadata
"""
try:
# Get document metadata set ID
doc_set = self.metadata_catalog.get_metadata_set_by_name("ControlledDocument")
if not doc_set:
return {'success': False, 'message': 'Metadata set for controlled documents not found'}
# Ensure file has the metadata set associated
add_set_result = self.metadata_catalog.add_set_to_file_object(
file_path=file_path,
set_id=doc_set.get('id')
)
if not add_set_result.get('success', False) and "already" not in add_set_result.get('message', ''):
return add_set_result
# Save metadata attributes
result = self.metadata_catalog.save_attribute_values_by_name(
file_path=file_path,
set_name="ControlledDocument",
attributes=metadata
)
return result
except Exception as e:
logger.error(f"Error setting document metadata: {str(e)}")
return {'success': False, 'message': f'Error setting metadata: {str(e)}'}
def _convert_docx_to_pdf(self, docx_path: str, pdf_path: str) -> bool:
"""
Convert a DOCX file to PDF
Parameters
----------
docx_path : str
Path to the Word document
pdf_path : str
Path where to save the PDF
Returns
-------
bool
True if conversion was successful, False otherwise
"""
try:
# This is a placeholder implementation
# In a real implementation, you would use a library like python-docx-to-pdf,
# or an external service like LibreOffice, unoconv, or cloud conversion API
# For demonstration, I'll assume the conversion always succeeds
# but in a real implementation, this would perform the actual conversion
# Example using docx2pdf (you'd need to install it):
# from docx2pdf import convert
# convert(docx_path, pdf_path)
# Example using subprocess to call LibreOffice:
# import subprocess
# subprocess.run(['libreoffice', '--headless', '--convert-to', 'pdf',
# '--outdir', os.path.dirname(pdf_path), docx_path])
# For this placeholder, just create an empty PDF file
with open(pdf_path, 'wb') as f:
f.write(b'%PDF-1.5\n%EOF\n')
return True
except Exception as e:
logger.error(f"Error converting DOCX to PDF: {str(e)}")
return False
def manage_document_share(self, document_version: DocumentVersion,
share_name: Optional[str] = None,
validity_period: int = 90) -> Dict[str, Any]:
"""
Create or get an existing share for a document version
Parameters
----------
document_version : DocumentVersion
The document version to share
share_name : str, optional
Name for the share (defaults to document title + version)
validity_period : int, optional
Validity period in days (default: 90)
Returns
-------
Dict[str, Any]
Share information including share_id and share_url
"""
try:
# Get document from version
document = document_version.document
if not document:
return {'success': False, 'message': 'Document not available'}
# Get file path to share
file_path = document_version.word_file_path or document_version.pdf_file_path
if not file_path:
return {'success': False, 'message': 'No file path available for sharing'}
# Check if file exists
if not self.check_file_exists(file_path):
return {'success': False, 'message': f'File not found: {file_path}'}
# If share already exists on the version, return it
if document_version.share_id:
# Verify the share still exists
share_info = self.client.get_share_for_id(document_version.share_id)
if share_info.get('success', False):
return {
'success': True,
'message': 'Share already exists',
'share_id': document_version.share_id,
'share_url': document_version.share_url,
'is_new': False
}
# Check if share exists for this file path
share_path_result = self.client.get_share_for_path(file_path)
existing_share_id = None
if share_path_result.get('success', False) and 'data' in share_path_result:
# Parse the response to extract share ID if a share exists
if 'shares' in share_path_result['data'] and 'share' in share_path_result['data']['shares']:
share_data = share_path_result['data']['shares']['share']
if isinstance(share_data, list) and len(share_data) > 0:
existing_share_id = share_data[0].get('shareid')
elif isinstance(share_data, dict):
existing_share_id = share_data.get('shareid')
# If share exists, use it
if existing_share_id:
# Get full share info
share_info = self.client.get_share_for_id(existing_share_id)
if share_info.get('success', False) and 'data' in share_info:
# Extract share URL from response
share_url = None
share_data = None
# Handle different response structures
if 'shares' in share_info['data'] and 'share' in share_info['data']['shares']:
share_data = share_info['data']['shares']['share']
elif 'xml' in share_info['data'] and 'share' in share_info['data']['xml']:
share_data = share_info['data']['xml']['share']
elif 'share' in share_info['data']:
share_data = share_info['data']['share']
if share_data:
if isinstance(share_data, list):
share_url = share_data[0].get('shareurl')
else:
share_url = share_data.get('shareurl')
# Update document version with share ID and URL
if share_url:
document_version.share_id = existing_share_id
document_version.share_url = share_url
document_version.save()
return {
'success': True,
'message': 'Using existing share',
'share_id': existing_share_id,
'share_url': share_url,
'is_new': False
}
# Create a new share if no valid existing share was found
if not share_name:
# Use document title and version as share name
share_name = f"{document.title} - v{document_version.version_number}"
# Create the share
share_result = self.client.add_share(
share_location=file_path,
share_name=share_name,
validity_period=validity_period,
max_downloads=1000 # High number for practical purposes
)
if not share_result.get('success', False):
return {
'success': False,
'message': f"Failed to create share: {share_result.get('message', 'Unknown error')}"
}
# Extract share ID from the result
share_id = None
if 'data' in share_result:
# Handle different response formats
if 'xml' in share_result['data'] and 'share' in share_result['data']['xml']:
share_data = share_result['data']['xml']['share']
share_id = share_data.get('shareid')
elif 'share' in share_result['data']:
share_data = share_result['data']['share']
if isinstance(share_data, list):
share_id = share_data[0].get('shareid')
else:
share_id = share_data.get('shareid')
if not share_id:
return {'success': False, 'message': 'Failed to get share ID from response'}
# Get share info to get the URL
share_info = self.client.get_share_for_id(share_id)
share_url = None
if share_info.get('success', False) and 'data' in share_info:
# Extract share URL from response
share_data = None
# Handle different response structures
if 'shares' in share_info['data'] and 'share' in share_info['data']['shares']:
share_data = share_info['data']['shares']['share']
elif 'xml' in share_info['data'] and 'share' in share_info['data']['xml']:
share_data = share_info['data']['xml']['share']
elif 'share' in share_info['data']:
share_data = share_info['data']['share']
if share_data:
if isinstance(share_data, list):
share_url = share_data[0].get('shareurl')
else:
share_url = share_data.get('shareurl')
# Update document version with share ID and URL
if share_url:
document_version.share_id = share_id
document_version.share_url = share_url
document_version.save()
return {
'success': True,
'message': 'Share created successfully',
'share_id': share_id,
'share_url': share_url,
'is_new': True
}
else:
return {'success': False, 'message': 'Failed to get share URL'}
except Exception as e:
logger.error(f"Error managing document share: {str(e)}")
logger.error(traceback.format_exc())
return {'success': False, 'message': f'Share management error: {str(e)}'}
def manage_user_share_access(self, document_version: DocumentVersion,
user_id: str,
grant_write_access: bool = False) -> Dict[str, Any]:
"""
Manage a user's access to a document share
Parameters
----------
document_version : DocumentVersion
The document version to manage access for
user_id : str
FileCloud username of the user to grant/modify access
grant_write_access : bool, optional
Whether to grant write access (default: False, read-only)
Returns
-------
Dict[str, Any]
Result of the operation
"""
try:
# Ensure we have a share for this document
if not document_version.share_id:
share_result = self.manage_document_share(document_version)
if not share_result.get('success', False):
return share_result
# Check if user already has access to this share
users_result = self.client.get_users_for_share(share_id=document_version.share_id)
user_exists = False
if users_result.get('success', False) and 'data' in users_result:
# Parse the user list to check if user already has access
user_data = None
# Handle different response structures
if 'users' in users_result['data']:
user_data = users_result['data']['users'].get('user', [])
elif 'xml' in users_result['data'] and 'users' in users_result['data']['xml']:
user_data = users_result['data']['xml']['users'].get('user', [])
if user_data:
# Convert to list if it's a single user dict
if isinstance(user_data, dict):
user_data = [user_data]
# Check if user is in the list
for user in user_data:
if user.get('userid') == user_id:
user_exists = True
break
# If user doesn't have access yet, add them
if not user_exists:
add_result = self.client.add_user_to_share(user_id=user_id, share_id=document_version.share_id)
if not add_result.get('success', False):
return {
'success': False,
'message': f"Failed to add user to share: {add_result.get('message', 'Unknown error')}"
}
# Set appropriate permissions for the user
perm_result = self.client.set_user_access_for_share(
share_id=document_version.share_id,
user_id=user_id,
download=True, # Allow downloading
write=grant_write_access, # Write access based on parameter
share=False, # Don't allow re-sharing
sync=False # Don't allow sync
)
if not perm_result.get('success', False):
return {
'success': False,
'message': f"Failed to set user permissions: {perm_result.get('message', 'Unknown error')}"
}
return {
'success': True,
'message': f"Access {'with write permission' if grant_write_access else 'read-only'} granted to {user_id}",
'user_id': user_id,
'share_id': document_version.share_id,
'write_access': grant_write_access
}
except Exception as e:
logger.error(f"Error managing user share access: {str(e)}")
logger.error(traceback.format_exc())
return {'success': False, 'message': f'Share access management error: {str(e)}'}
def remove_user_from_share(self, document_version: DocumentVersion,
user_id: str) -> Dict[str, Any]:
"""
Remove a user's access to a document share
Parameters
----------
document_version : DocumentVersion
The document version to remove access for
user_id : str
FileCloud username of the user to remove
Returns
-------
Dict[str, Any]
Result of the operation
"""
try:
# Check if we have a share ID
if not document_version.share_id:
return {
'success': True,
'message': 'No share exists for this document version'
}
# Remove the user from the share
remove_result = self.client.delete_user_from_share(
user_id=user_id,
share_id=document_version.share_id
)
if not remove_result.get('success', False):
# Check if the error is because the user doesn't have access (already removed)
if "not found" in remove_result.get('message', '').lower():
return {
'success': True,
'message': f'User {user_id} already has no access to this share',
'user_id': user_id,
'share_id': document_version.share_id
}
else:
return {
'success': False,
'message': f"Failed to remove user from share: {remove_result.get('message', 'Unknown error')}"
}
return {
'success': True,
'message': f'User {user_id} removed from share',
'user_id': user_id,
'share_id': document_version.share_id
}
except Exception as e:
logger.error(f"Error removing user from share: {str(e)}")
return {'success': False, 'message': f'Share access removal error: {str(e)}'}
def delete_document_share(self, document_version: DocumentVersion) -> Dict[str, Any]:
"""
Delete a document share
Parameters
----------
document_version : DocumentVersion
The document version whose share should be deleted
Returns
-------
Dict[str, Any]
Result of the operation
"""
try:
# Check if we have a share ID
if not document_version.share_id:
return {
'success': True,
'message': 'No share exists for this document version'
}
# Delete the share
delete_result = self.client.delete_share(share_id=document_version.share_id)
if not delete_result.get('success', False):
return {
'success': False,
'message': f"Failed to delete share: {delete_result.get('message', 'Unknown error')}"
}
# Clear share data from document version
document_version.share_id = None
document_version.share_url = None
document_version.save()
return {
'success': True,
'message': 'Share deleted successfully'
}
except Exception as e:
logger.error(f"Error deleting document share: {str(e)}")
return {'success': False, 'message': f'Share deletion error: {str(e)}'}
def manage_group_share_access(self, document_version: DocumentVersion,
group_id: str,
grant_write_access: bool = False) -> Dict[str, Any]:
"""
Manage a group's access to a document share
Parameters
----------
document_version : DocumentVersion
The document version to manage access for
group_id : str
FileCloud group ID to grant/modify access
grant_write_access : bool, optional
Whether to grant write access (default: False, read-only)
Returns
-------
Dict[str, Any]
Result of the operation
"""
try:
# Ensure we have a share for this document
if not document_version.share_id:
share_result = self.manage_document_share(document_version)
if not share_result.get('success', False):
return share_result
# Add the group to the share or update permissions
add_result = self.client.add_group_to_share(group_id=group_id, share_id=document_version.share_id)
# Set appropriate permissions for the group
perm_result = self.client.set_group_access_for_share(
share_id=document_version.share_id,
group_id=group_id,
download=True, # Allow downloading
write=grant_write_access, # Write access based on parameter
share=False, # Don't allow re-sharing
sync=False # Don't allow sync
)
if not perm_result.get('success', False):
return {
'success': False,
'message': f"Failed to set group permissions: {perm_result.get('message', 'Unknown error')}"
}
return {
'success': True,
'message': f"Access {'with write permission' if grant_write_access else 'read-only'} granted to group {group_id}",
'group_id': group_id,
'share_id': document_version.share_id,
'write_access': grant_write_access
}
except Exception as e:
logger.error(f"Error managing group share access: {str(e)}")
return {'success': False, 'message': f'Share access management error: {str(e)}'}
def check_file_exists(self, file_path: str) -> bool:
"""
Check if a file exists in FileCloud
Parameters
----------
file_path : str
Path to the file
Returns
-------
bool
True if file exists, False otherwise
"""
try:
return self.client.check_file_exists(file_path)
except Exception as e:
logger.error(f"Error checking if file exists: {str(e)}")
return False
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
bases |
- | - |
Parameter Details
bases: Parameter of type
Return Value
Returns unspecified type
Class Interface
Methods
__init__(self, server_url, username, password)
Purpose: Initialize FileCloud integration Parameters ---------- server_url : str URL of the FileCloud server username : str FileCloud username password : str FileCloud password
Parameters:
server_url: Type: strusername: Type: strpassword: Type: str
Returns: None
connect(self) -> bool
Purpose: Establish connection to FileCloud Returns ------- bool True if connection successful, False otherwise
Returns: Returns bool
upload_document(self, local_file_path, remote_folder_path, filename, metadata) -> Dict[str, Any]
Purpose: Upload a document to FileCloud Parameters ---------- local_file_path : str Path to the local file remote_folder_path : str Path to the remote folder filename : str, optional Name to use for the uploaded file metadata : Dict[str, Any], optional Metadata to attach to the file Returns ------- Dict[str, Any] Upload result including file path
Parameters:
local_file_path: Type: strremote_folder_path: Type: strfilename: Type: Optional[str]metadata: Type: Optional[Dict[str, Any]]
Returns: Returns Dict[str, Any]
download_document(self, file_path, local_path) -> Dict[str, Any]
Purpose: Download a document from FileCloud Parameters ---------- file_path : str Path to the file in FileCloud local_path : str, optional Local path where to save the file Returns ------- Dict[str, Any] Download result with file content if local_path not provided
Parameters:
file_path: Type: strlocal_path: Type: Optional[str]
Returns: Returns Dict[str, Any]
get_edit_url(self, file_path) -> Dict[str, Any]
Purpose: Get URL for online editing Parameters ---------- file_path : str Path to the file in FileCloud Returns ------- Dict[str, Any] Result with edit URL
Parameters:
file_path: Type: str
Returns: Returns Dict[str, Any]
get_view_url(self, file_path) -> Dict[str, Any]
Purpose: Get URL for viewing a document Parameters ---------- file_path : str Path to the file in FileCloud Returns ------- Dict[str, Any] Result with view URL
Parameters:
file_path: Type: str
Returns: Returns Dict[str, Any]
create_document_version(self, document, local_file_path, version_number, created_by, version_comment) -> Optional[DocumentVersion]
Purpose: Create a new version of a controlled document Parameters ---------- document : ControlledDocument The document to create a version for local_file_path : str Path to the local file version_number : str Version number (e.g., "1.0") created_by : str UID of the user creating the version version_comment : str, optional Comment for the version Returns ------- Optional[DocumentVersion] The new document version or None if creation failed
Parameters:
document: Type: ControlledDocumentlocal_file_path: Type: strversion_number: Type: strcreated_by: Type: strversion_comment: Type: str
Returns: Returns Optional[DocumentVersion]
upload_new_controlled_document(self, local_file_path, title, doc_type, department, owner_uid, initial_version, additional_metadata) -> Dict[str, Any]
Purpose: Upload a new controlled document to FileCloud and create it in the database Parameters ---------- local_file_path : str Path to the local file title : str Document title doc_type : str Document type code or name department : str Department code or name owner_uid : str UID of the document owner initial_version : str, optional Initial version number (default: "1.0") additional_metadata : Dict[str, Any], optional Additional metadata for the document Returns ------- Dict[str, Any] Result with document and version information
Parameters:
local_file_path: Type: strtitle: Type: strdoc_type: Type: strdepartment: Type: strowner_uid: Type: strinitial_version: Type: stradditional_metadata: Type: Optional[Dict[str, Any]]
Returns: Returns Dict[str, Any]
update_document_metadata(self, document_uid, metadata) -> Dict[str, Any]
Purpose: Update metadata for a document both in database and FileCloud Parameters ---------- document_uid : str UID of the document to update metadata : Dict[str, Any] Metadata to update Returns ------- Dict[str, Any] Result of the update
Parameters:
document_uid: Type: strmetadata: Type: Dict[str, Any]
Returns: Returns Dict[str, Any]
convert_to_pdf(self, document_version) -> Dict[str, Any]
Purpose: Convert a document version to PDF using FileCloud's conversion service Parameters ---------- document_version : DocumentVersion The document version to convert Returns ------- Dict[str, Any] Result of the conversion
Parameters:
document_version: Type: DocumentVersion
Returns: Returns Dict[str, Any]
get_document_metadata(self, file_path) -> Dict[str, Any]
Purpose: Get metadata for a document from FileCloud Parameters ---------- file_path : str Path to the file in FileCloud Returns ------- Dict[str, Any] Document metadata
Parameters:
file_path: Type: str
Returns: Returns Dict[str, Any]
search_documents(self, search_criteria) -> List[Dict[str, Any]]
Purpose: Search for documents in FileCloud based on metadata Parameters ---------- search_criteria : Dict[str, Any] Search criteria with keys matching metadata attribute names Returns ------- List[Dict[str, Any]] List of matching documents
Parameters:
search_criteria: Type: Dict[str, Any]
Returns: Returns List[Dict[str, Any]]
_ensure_folder_exists(self, folder_path) -> bool
Purpose: Ensure a folder exists in FileCloud, creating it if necessary Parameters ---------- folder_path : str Path to the folder Returns ------- bool True if folder exists or was created, False otherwise
Parameters:
folder_path: Type: str
Returns: Returns bool
_set_document_metadata(self, file_path, metadata) -> Dict[str, Any]
Purpose: Set metadata for a document Parameters ---------- file_path : str Path to the file metadata : Dict[str, Any] Metadata to set Returns ------- Dict[str, Any] Result of setting metadata
Parameters:
file_path: Type: strmetadata: Type: Dict[str, Any]
Returns: Returns Dict[str, Any]
_convert_docx_to_pdf(self, docx_path, pdf_path) -> bool
Purpose: Convert a DOCX file to PDF Parameters ---------- docx_path : str Path to the Word document pdf_path : str Path where to save the PDF Returns ------- bool True if conversion was successful, False otherwise
Parameters:
docx_path: Type: strpdf_path: Type: str
Returns: Returns bool
manage_document_share(self, document_version, share_name, validity_period) -> Dict[str, Any]
Purpose: Create or get an existing share for a document version Parameters ---------- document_version : DocumentVersion The document version to share share_name : str, optional Name for the share (defaults to document title + version) validity_period : int, optional Validity period in days (default: 90) Returns ------- Dict[str, Any] Share information including share_id and share_url
Parameters:
document_version: Type: DocumentVersionshare_name: Type: Optional[str]validity_period: Type: int
Returns: Returns Dict[str, Any]
manage_user_share_access(self, document_version, user_id, grant_write_access) -> Dict[str, Any]
Purpose: Manage a user's access to a document share Parameters ---------- document_version : DocumentVersion The document version to manage access for user_id : str FileCloud username of the user to grant/modify access grant_write_access : bool, optional Whether to grant write access (default: False, read-only) Returns ------- Dict[str, Any] Result of the operation
Parameters:
document_version: Type: DocumentVersionuser_id: Type: strgrant_write_access: Type: bool
Returns: Returns Dict[str, Any]
remove_user_from_share(self, document_version, user_id) -> Dict[str, Any]
Purpose: Remove a user's access to a document share Parameters ---------- document_version : DocumentVersion The document version to remove access for user_id : str FileCloud username of the user to remove Returns ------- Dict[str, Any] Result of the operation
Parameters:
document_version: Type: DocumentVersionuser_id: Type: str
Returns: Returns Dict[str, Any]
delete_document_share(self, document_version) -> Dict[str, Any]
Purpose: Delete a document share Parameters ---------- document_version : DocumentVersion The document version whose share should be deleted Returns ------- Dict[str, Any] Result of the operation
Parameters:
document_version: Type: DocumentVersion
Returns: Returns Dict[str, Any]
manage_group_share_access(self, document_version, group_id, grant_write_access) -> Dict[str, Any]
Purpose: Manage a group's access to a document share Parameters ---------- document_version : DocumentVersion The document version to manage access for group_id : str FileCloud group ID to grant/modify access grant_write_access : bool, optional Whether to grant write access (default: False, read-only) Returns ------- Dict[str, Any] Result of the operation
Parameters:
document_version: Type: DocumentVersiongroup_id: Type: strgrant_write_access: Type: bool
Returns: Returns Dict[str, Any]
check_file_exists(self, file_path) -> bool
Purpose: Check if a file exists in FileCloud Parameters ---------- file_path : str Path to the file Returns ------- bool True if file exists, False otherwise
Parameters:
file_path: Type: str
Returns: Returns bool
Required Imports
import os
import logging
from typing import Dict
from typing import Any
from typing import Optional
Usage Example
# Example usage:
# result = FileCloudIntegration(bases)
Similar Components
AI-powered semantic similarity - components with related functionality:
-
class FileCloudClient_v1 65.0% similar
-
class MetadataCatalog 64.7% similar
-
class FileCloudClient 64.6% similar
-
class FileCloudError 64.5% similar
-
function _get_filecloud_integration_v1 63.6% similar