function remove_training_assignment
Removes a training assignment relationship between a user and a controlled document in a Neo4j graph database, with audit logging and permission checks.
/tf/active/vicechatdev/CDocs/controllers/training_controller.py
450 - 564
moderate
Purpose
This function is used in a document management system to revoke a training requirement for a specific user on a controlled document. It parses a composite assignment UID (user_uid-document_uid), validates the assignment exists, deletes the REQUIRES_TRAINING relationship in Neo4j, and logs the removal event for audit purposes. This is typically used by administrators managing training compliance requirements.
Source Code
def remove_training_assignment(
user: DocUser,
assignment_uid: str
) -> Dict[str, Any]:
"""
Remove a training assignment.
Args:
user: Admin user removing the assignment
assignment_uid: Assignment UID (format: user_uid-document_uid)
Returns:
Dictionary with operation status
"""
try:
# Parse the assignment_uid to get user and document UIDs
parts = assignment_uid.split('-')
if len(parts) < 8: # UUID has 5 parts, so we need at least 8 for user-document
return {
"success": False,
"message": "Invalid assignment ID format"
}
# Find the split point - UUID format is 8-4-4-4-12 characters
# So we look for a pattern that matches this
user_uid = None
document_uid = None
for i in range(1, len(parts)):
potential_user_uid = '-'.join(parts[:i])
potential_document_uid = '-'.join(parts[i:])
# Check if both parts look like UUIDs (36 characters)
if len(potential_user_uid) == 36 and len(potential_document_uid) == 36:
user_uid = potential_user_uid
document_uid = potential_document_uid
break
if not user_uid or not document_uid:
return {
"success": False,
"message": "Could not parse assignment ID"
}
# Check if assignment exists
check_query = """
MATCH (u:User {UID: $user_uid})-[r:REQUIRES_TRAINING]->(d:ControlledDocument {UID: $document_uid})
RETURN r, u.Name as user_name, d.title as doc_title
"""
result = db.run_query(check_query, {
'user_uid': user_uid,
'document_uid': document_uid
})
if not result:
return {
"success": False,
"message": "Training assignment not found"
}
assignment_data = result[0]
user_name = assignment_data.get('user_name', 'Unknown')
doc_title = assignment_data.get('doc_title', 'Unknown Document')
# Remove the training assignment relationship
remove_query = """
MATCH (u:User {UID: $user_uid})-[r:REQUIRES_TRAINING]->(d:ControlledDocument {UID: $document_uid})
DELETE r
RETURN count(r) as deleted_count
"""
remove_result = db.run_query(remove_query, {
'user_uid': user_uid,
'document_uid': document_uid
})
if not remove_result or remove_result[0].get('deleted_count', 0) == 0:
return {
"success": False,
"message": "Failed to remove training assignment"
}
# Log removal event
audit_trail.log_event(
event_type="TRAINING_REMOVED",
user=user.uid,
resource_uid=document_uid,
resource_type="ControlledDocument",
details={
"assignment_uid": assignment_uid,
"assigned_user_uid": user_uid,
"assigned_user_name": user_name,
"document_title": doc_title,
"removed_by": user.name,
"removal_date": datetime.now().isoformat()
}
)
return {
"success": True,
"message": f"Training assignment removed for {user_name} - {doc_title}",
"removed_assignment": {
"user_name": user_name,
"document_title": doc_title,
"assignment_uid": assignment_uid
}
}
except Exception as e:
logger.error(f"Error removing training assignment {assignment_uid}: {e}")
return {
"success": False,
"message": f"Failed to remove training assignment: {e}"
}
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
user |
DocUser | - | positional_or_keyword |
assignment_uid |
str | - | positional_or_keyword |
Parameter Details
user: DocUser object representing the administrator performing the removal operation. Must have MANAGE_TRAINING permission (enforced by decorator). Used for audit logging to track who removed the assignment.
assignment_uid: String in format 'user_uid-document_uid' where both UIDs are 36-character UUIDs (format: 8-4-4-4-12). This composite identifier uniquely identifies the training assignment relationship to be removed. Example: '550e8400-e29b-41d4-a716-446655440000-660e8400-e29b-41d4-a716-446655440001'
Return Value
Type: Dict[str, Any]
Returns a dictionary with operation status. On success: {'success': True, 'message': str, 'removed_assignment': {'user_name': str, 'document_title': str, 'assignment_uid': str}}. On failure: {'success': False, 'message': str} with error description. The 'message' field provides human-readable feedback, and 'removed_assignment' contains details about what was removed.
Dependencies
typingdatetimeloggingtracebackCDocs.configCDocs.models.documentCDocs.models.user_extensionsCDocs.models.trainingCDocs.utilsCDocs.dbCDocs.controllers
Required Imports
from typing import Dict, Any
from datetime import datetime
import logging
from CDocs.models.user_extensions import DocUser
from CDocs.utils import audit_trail
from CDocs.db import db_operations as db
from CDocs.controllers import require_permission, log_controller_action
Usage Example
from CDocs.models.user_extensions import DocUser
from your_module import remove_training_assignment
# Assuming admin_user is already authenticated and has MANAGE_TRAINING permission
admin_user = DocUser(uid='admin-uid-123', name='Admin User')
# Composite assignment UID format: user_uid-document_uid
assignment_uid = '550e8400-e29b-41d4-a716-446655440000-660e8400-e29b-41d4-a716-446655440001'
result = remove_training_assignment(
user=admin_user,
assignment_uid=assignment_uid
)
if result['success']:
print(f"Successfully removed: {result['message']}")
print(f"User: {result['removed_assignment']['user_name']}")
print(f"Document: {result['removed_assignment']['document_title']}")
else:
print(f"Error: {result['message']}")
Best Practices
- Always check the 'success' field in the returned dictionary before processing results
- The assignment_uid must be exactly in the format 'user_uid-document_uid' with both being valid 36-character UUIDs
- Ensure the calling user has MANAGE_TRAINING permission before invoking (enforced by decorator)
- The function performs audit logging automatically - no additional logging needed for compliance
- Handle exceptions gracefully as the function catches all exceptions and returns error messages in the response dictionary
- The function validates assignment existence before deletion to prevent silent failures
- Use the returned 'removed_assignment' data for UI feedback or further processing
- The function is idempotent-safe: attempting to remove a non-existent assignment returns a clear error message rather than throwing an exception
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function get_training_assignment 79.8% similar
-
function complete_user_training_by_uid 74.6% similar
-
function get_document_training_assignments 72.2% similar
-
function disable_document_training 69.3% similar
-
function assign_user_training 68.6% similar