function manage_user_share_access_v2
Manages user access permissions to a FileCloud document share, creating shares if needed and setting read-only or write access for specified users.
/tf/active/vicechatdev/CDocs/controllers/permission_startup_check.py
66 - 297
complex
Purpose
This function provides comprehensive management of user access to document versions in FileCloud. It handles the complete workflow: checking if a share exists for the document version, creating a new share if necessary, verifying if the user already has access, adding the user to the share if needed, and setting appropriate permissions (read-only or write access). It includes extensive error handling and logging throughout the process, making it suitable for production environments where document access control is critical.
Source Code
def manage_user_share_access(
document_version: DocumentVersion,
user_id: str,
grant_write_access: bool = False
) -> Dict[str, Any]:
"""
Manage a user's access to a document share in FileCloud.
This function ensures the user has appropriate access (read-only or edit)
to a document share in FileCloud based on their role and document status.
Args:
document_version: The document version to share
user_id: User's email address (used as FileCloud identifier)
grant_write_access: Whether to grant write access (True) or read-only (False)
Returns:
Dict with result information
"""
try:
# Get FileCloud client - using direct FC API access
fc_client = get_filecloud_client()
if not fc_client:
logger.error("Could not get FileCloud client")
return {
'success': False,
'message': 'FileCloud connection not available'
}
# Check if share_id attribute exists, if not, initialize it
if not hasattr(document_version, 'share_id') or not document_version.share_id:
# Either attribute missing or it's None/empty - create a new share
# Get document
doc = document_version.document
if not doc:
logger.error("Could not get document from version")
return {
'success': False,
'message': 'Document not found for version'
}
# Get file path in FileCloud
file_path = get_filecloud_document_path(
doc,
version=document_version.version_number
)
# Check if file exists - with error handling
try:
file_exists = fc_client.check_file_exists(file_path)
if not file_exists:
logger.error(f"File not found at path: {file_path}")
return {
'success': False,
'message': f'File not found: {file_path}'
}
except Exception as file_check_error:
logger.error(f"Error checking if file exists: {str(file_check_error)}")
# Continue anyway - the file might still exist even if the check fails
# Create a new share directly using the FC API
share_name = f"{doc.title} v{document_version.version_number}"
# Add try/except specifically for add_share
try:
share_result = fc_client.add_share(
share_location=file_path,
share_name=share_name,
max_downloads=1000
)
except Exception as share_error:
logger.error(f"Error creating share: {str(share_error)}")
return {
'success': False,
'message': f"Error creating share: {str(share_error)}"
}
if not share_result.get('success', False):
logger.error(f"Failed to create share: {share_result.get('message', 'Unknown error')}")
return {
'success': False,
'message': f"Failed to create share: {share_result.get('message', 'Unknown error')}"
}
# Extract share ID and URL
share_id = share_result.get('share_id')
share_url = share_result.get('share_url')
if not share_id:
logger.error("No share ID returned from FileCloud API")
return {
'success': False,
'message': 'Share creation failed: No share ID returned'
}
# Update document version with share information
if not hasattr(document_version, 'share_id'):
setattr(document_version, 'share_id', share_id)
else:
document_version.share_id = share_id
if not hasattr(document_version, 'share_url'):
setattr(document_version, 'share_url', share_url)
else:
document_version.share_url = share_url
try:
document_version.save()
logger.info(f"Successfully saved share info for document version {document_version.uid}")
except Exception as save_err:
logger.warning(f"Failed to save document version with share info: {save_err}")
# Continue despite this error
# Get the share ID safely
share_id = getattr(document_version, 'share_id', None)
if not share_id:
logger.error("No share ID available for document version")
return {
'success': False,
'message': 'No share ID available for document'
}
# 1. First check if user is already in the share
user_exists_in_share = False
try:
users_result = fc_client.get_users_for_share(share_id=share_id)
if users_result.get('success', False):
# Extract users from the result
# Structure varies based on if there's a single user or multiple users
try:
if 'data' in users_result:
# Handle different response structures
if 'users' in users_result['data']:
users_data = users_result['data']['users']
user_list = []
# Users data can be a dict with a 'user' key, or directly a user list
if isinstance(users_data, dict) and 'user' in users_data:
user_data = users_data['user']
# User can be a single dict or a list of dicts
if isinstance(user_data, list):
user_list = user_data
else:
user_list = [user_data]
elif isinstance(users_data, list):
user_list = users_data
# Check if user is in the list
for user in user_list:
# Check if user is a dictionary before calling get()
if isinstance(user, dict):
if user.get('userid') == user_id or user.get('email') == user_id:
user_exists_in_share = True
logger.info(f"User {user_id} already exists in share {share_id}")
break
elif isinstance(user, str) and (user == user_id):
# If user is directly a string (username or email)
user_exists_in_share = True
logger.info(f"User {user_id} already exists in share {share_id}")
break
except Exception as parse_err:
logger.warning(f"Error parsing users response: {str(parse_err)}")
# Continue anyway, we'll try to add the user
except Exception as users_err:
logger.warning(f"Error getting users for share: {str(users_err)}")
# Continue anyway, we'll try to add the user
# 2. Add user to share if not already added
if not user_exists_in_share:
# Add user to share first - using the correct parameter names
try:
# Make sure we're using valid parameters for add_user_to_share
logger.info(f"Adding user {user_id} to share {share_id}")
add_result = fc_client.add_user_to_share(
user_id=user_id,
share_id=share_id
)
if not add_result.get('success', False):
# If user already added but not detected above, continue anyway
if "already added" in str(add_result.get('message', '')).lower():
logger.info(f"User {user_id} was already added to share {share_id}")
user_exists_in_share = True
else:
logger.error(f"Failed to add user to share: {add_result.get('message', 'Unknown error')}")
return {
'success': False,
'message': f"Failed to add user to share: {add_result.get('message', 'Unknown error')}"
}
except Exception as add_err:
logger.error(f"Error adding user to share: {str(add_err)}")
return {
'success': False,
'message': f"Error adding user to share: {str(add_err)}"
}
# 3. Set appropriate access rights
# Use set_user_access_for_share method to grant appropriate permissions
try:
perm_result = fc_client.set_user_access_for_share(
share_id=share_id,
user_id=user_id,
write=grant_write_access, # Set write permission based on parameter
download=True, # Always allow download
share=False, # Don't allow resharing by default
sync=False # Don't allow sync
)
if not perm_result.get('success', False):
logger.warning(f"Set user access permissions failed: {perm_result.get('message', 'Unknown error')}")
# Continue despite permission setting issues - at least user has basic access
except Exception as perm_err:
logger.warning(f"Error setting user permissions: {str(perm_err)}")
# Continue anyway, at least the user is added to the share
return {
'success': True,
'message': f"User access {'with edit rights' if grant_write_access else 'read-only'} set successfully",
'share_url': getattr(document_version, 'share_url', None),
'share_id': share_id,
'user_id': user_id,
'permission': "write" if grant_write_access else "read"
}
except Exception as e:
logger.error(f"Error managing user share access: {str(e)}")
return {
'success': False,
'message': f"Error: {str(e)}"
}
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
document_version |
DocumentVersion | - | positional_or_keyword |
user_id |
str | - | positional_or_keyword |
grant_write_access |
bool | False | positional_or_keyword |
Parameter Details
document_version: A DocumentVersion model instance representing the specific version of a document to be shared. Must have attributes like 'document', 'version_number', and optionally 'share_id' and 'share_url'. The function will create and populate share_id/share_url if they don't exist.
user_id: String identifier for the user, typically their email address, used as the FileCloud user identifier. This is used to add the user to the share and set their permissions.
grant_write_access: Boolean flag determining permission level. When True, grants write/edit access to the document. When False (default), grants read-only access with download capability. Defaults to False for security.
Return Value
Type: Dict[str, Any]
Returns a dictionary with keys: 'success' (bool indicating operation success), 'message' (str describing the result or error), 'share_url' (str URL to access the share, if successful), 'share_id' (str FileCloud share identifier), 'user_id' (str echoing the input user_id), and 'permission' (str either 'write' or 'read' indicating granted access level). On failure, only 'success' and 'message' keys are guaranteed to be present.
Dependencies
loggingtyping
Required Imports
import logging
from typing import Dict, Any
from CDocs.models.document import DocumentVersion
from CDocs.controllers.filecloud_controller import get_filecloud_client, get_filecloud_document_path
Usage Example
from CDocs.models.document import DocumentVersion
from your_module import manage_user_share_access
# Get a document version instance (from database query)
doc_version = DocumentVersion.objects.get(uid='some-uuid')
# Grant read-only access to a user
result = manage_user_share_access(
document_version=doc_version,
user_id='user@example.com',
grant_write_access=False
)
if result['success']:
print(f"User granted {result['permission']} access")
print(f"Share URL: {result['share_url']}")
else:
print(f"Error: {result['message']}")
# Grant write access to another user
write_result = manage_user_share_access(
document_version=doc_version,
user_id='editor@example.com',
grant_write_access=True
)
if write_result['success']:
print(f"Editor granted write access at {write_result['share_url']}")
Best Practices
- Always check the 'success' key in the returned dictionary before accessing other keys like 'share_url' or 'share_id'
- The function modifies the document_version object by adding/updating share_id and share_url attributes - ensure the object is from a valid database session
- Use grant_write_access=False by default for security; only grant write access when explicitly needed
- The function includes extensive error handling and will continue operation even if some steps fail (e.g., permission setting), so check logs for warnings
- User IDs should be email addresses that exist in the FileCloud system
- The function is idempotent - calling it multiple times with the same parameters will not create duplicate shares or user access entries
- Ensure proper logging configuration to capture detailed error messages and warnings for troubleshooting
- The FileCloud client connection must be established before calling this function; verify get_filecloud_client() returns a valid client
- Document version objects should have their associated document relationship properly loaded to avoid database query errors
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function manage_user_share_access 97.6% similar
-
function manage_user_share_access_v1 97.2% similar
-
function remove_user_access 78.5% similar
-
function get_user_access_url 76.9% similar
-
function manage_document_permissions 76.3% similar