function get_training_assignment
Retrieves a specific training assignment for a user from a Neo4j graph database, validating user authorization and parsing a composite UID format.
/tf/active/vicechatdev/CDocs/controllers/training_controller.py
954 - 1032
moderate
Purpose
This function fetches detailed training assignment information for a user, including document content, training status, progress, dates, and quiz requirements. It enforces security by verifying that users can only access their own training assignments. The function parses a composite training_uid (format: user_uid-document_uid) and queries a Neo4j database to retrieve the training relationship between a user and a controlled document.
Source Code
def get_training_assignment(user: DocUser, training_uid: str) -> Optional[Dict[str, Any]]:
"""
Get specific training assignment for a user.
Args:
user: User requesting training assignment
training_uid: UID of training assignment (format: user_uid-document_uid)
Returns:
Training assignment data or None if not found
"""
try:
# Parse the training_uid to get user and document UIDs
# Format is: user_uid-document_uid where both are UUIDs
# UUIDs are 36 characters long, so we split at position 36
if len(training_uid) > 36 and training_uid[36] == '-':
user_uid = training_uid[:36]
document_uid = training_uid[37:] # Skip the separating hyphen
else:
# If the format is unexpected, log it and return None
logger.error(f"Invalid training UID format: {training_uid}")
return None
# Verify this is the correct user requesting their own training
if user_uid != user.uid:
logger.warning(f"User {user.uid} attempting to access training assignment for user {user_uid}")
return None
query = """
MATCH (u:User {UID: $user_uid})-[r:REQUIRES_TRAINING]->(d:ControlledDocument {UID: $document_uid})
RETURN {
uid: u.UID + '-' + d.UID,
status: r.status,
progress: COALESCE(r.progress, 0),
assigned_date: r.assigned_date,
due_date: r.expires_date,
expires_date: r.expires_date,
completed_date: r.completed_date,
score: r.score,
quiz_required: COALESCE(d.training_quiz_required, false),
instructions: COALESCE(d.training_instructions, ''),
validity_days: COALESCE(d.training_validity_days, 365),
assigned_by: r.assigned_by,
document: {
uid: d.UID,
title: d.title,
content: d.content,
doc_number: d.docNumber,
type: 'document'
}
} as training
"""
result = db.run_query(query, {
'user_uid': user_uid,
'document_uid': document_uid
})
if not result:
logger.info(f"No training assignment found for uid: {training_uid}")
return None
training_data = result[0]['training']
# Convert Neo4j DateTime objects to ISO strings
def convert_datetime(data):
if isinstance(data, dict):
for key, value in data.items():
if hasattr(value, 'iso_format'): # Neo4j DateTime
data[key] = value.iso_format()
elif isinstance(value, dict):
convert_datetime(value)
return data
return convert_datetime(training_data)
except Exception as e:
logger.error(f"Error getting training assignment {training_uid}: {e}")
return None
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
user |
DocUser | - | positional_or_keyword |
training_uid |
str | - | positional_or_keyword |
Parameter Details
user: DocUser object representing the authenticated user making the request. Used to verify authorization - the user can only access their own training assignments. Must have a 'uid' attribute containing the user's unique identifier.
training_uid: String identifier for the training assignment in the format 'user_uid-document_uid' where both UIDs are 36-character UUIDs separated by a hyphen. Example: '550e8400-e29b-41d4-a716-446655440000-650e8400-e29b-41d4-a716-446655440001'. The function validates this format and extracts both component UIDs.
Return Value
Type: Optional[Dict[str, Any]]
Returns Optional[Dict[str, Any]]. On success, returns a dictionary containing training assignment details with keys: 'uid' (composite training UID), 'status' (training status), 'progress' (completion percentage, default 0), 'assigned_date', 'due_date', 'expires_date', 'completed_date', 'score', 'quiz_required' (boolean), 'instructions', 'validity_days' (default 365), 'assigned_by', and 'document' (nested dict with 'uid', 'title', 'content', 'doc_number', 'type'). All Neo4j DateTime objects are converted to ISO format strings. Returns None if: training not found, invalid UID format, user lacks authorization, or an error occurs.
Dependencies
typingdatetimeloggingCDocs.configCDocs.models.documentCDocs.models.user_extensionsCDocs.models.trainingCDocs.utilsCDocs.dbCDocs.controllerstraceback
Required Imports
from typing import Dict, Any, Optional
from CDocs.models.user_extensions import DocUser
from CDocs.db import db_operations as db
from CDocs.controllers import log_controller_action
import logging
Usage Example
from CDocs.models.user_extensions import DocUser
from CDocs.controllers.training_controller import get_training_assignment
# Assume user is authenticated and retrieved from session
user = DocUser(uid='550e8400-e29b-41d4-a716-446655440000', username='john.doe')
# Composite training UID format: user_uid-document_uid
training_uid = '550e8400-e29b-41d4-a716-446655440000-650e8400-e29b-41d4-a716-446655440001'
# Get the training assignment
training = get_training_assignment(user, training_uid)
if training:
print(f"Training Status: {training['status']}")
print(f"Progress: {training['progress']}%")
print(f"Document: {training['document']['title']}")
print(f"Quiz Required: {training['quiz_required']}")
print(f"Due Date: {training['due_date']}")
else:
print("Training assignment not found or access denied")
Best Practices
- Always validate the user object before calling this function to ensure proper authentication
- The training_uid must follow the exact format 'user_uid-document_uid' with 36-character UUIDs
- Handle None return values appropriately - they indicate either missing data, authorization failure, or invalid input
- The function enforces user isolation - users can only access their own training assignments
- DateTime fields in the response are automatically converted to ISO format strings for JSON serialization
- Check logs for detailed error messages if None is returned, as different failure modes are logged differently
- The function is decorated with log_controller_action for audit trail purposes
- Ensure Neo4j database connection is established before calling this function
- The function uses COALESCE in Cypher queries to provide default values for optional fields
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function remove_training_assignment 79.8% similar
-
function get_document_training_assignments 78.0% similar
-
function complete_user_training_by_uid 76.3% similar
-
function get_document_training_info 73.6% similar
-
function get_user_training_dashboard 70.4% similar