Skip to content

Commit

Permalink
feat: Added management command to update UIDs
Browse files Browse the repository at this point in the history
  • Loading branch information
zamanafzal committed Dec 9, 2024
1 parent 7ca0731 commit 73d718a
Show file tree
Hide file tree
Showing 3 changed files with 223 additions and 0 deletions.
49 changes: 49 additions & 0 deletions dafs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"auth_time": 1731330783,
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": [
"samlp|2023testcustomer-e9c62ac6-f8d8-448d-bc3c-df8bd1a82457|sameer_test_user"
],
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": [],
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn": [
"samlp|2023testcustomer-e9c62ac6-f8d8-448d-bc3c-df8bd1a82457|sameer_test_user@auth0"
],
"http://schemas.auth0.com/identities/default/provider": [
"samlp"
],
"http://schemas.auth0.com/identities/default/connection": [
"2023testcustomer-e9c62ac6-f8d8-448d-bc3c-df8bd1a82457"
],
"http://schemas.auth0.com/identities/default/isSocial": [
"false"
],
"http://schemas.auth0.com/clientID": [
"t5tcxN6W8GUn6RtKbkvKWfv1EuUoigYc"
],
"http://schemas.auth0.com/authenticationmethod": [
"urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified"
],
"http://schemas.auth0.com/issuer": [
"https://edx-keycloak.duckdns.org/realms/demo"
],
"http://schemas.auth0.com/nameIdAttributes": [
"[object Object]"
],
"http://schemas.auth0.com/nickname": [],
"http://schemas.auth0.com/picture": [
"https://cdn.auth0.com/avatars/default.png"
],
"http://schemas.auth0.com/sessionIndex": [
"3ff721c9-64e3-47d0-9664-9eb384daed05::44c63888-a638-4e12-b38a-e0ab4f067821"
],
"http://schemas.auth0.com/created_at": [
"2024-11-11T13:05:11.277Z"
],
"http://schemas.auth0.com/updated_at": [
"2024-11-11T13:12:00.322Z"
],
"http://schemas.auth0.com/org_id": [
"org_ZZKMEOFKOfHwaq4i"
],
"name_id": "samlp|2023testcustomer-e9c62ac6-f8d8-448d-bc3c-df8bd1a82457|sameer_test_user",
"session_index": "_2ZWA9nNgoTALt5W41EGocC0Db_4oR2Ue"
}
36 changes: 36 additions & 0 deletions dwadsc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
SELECT * FROM moodle_moodlelearnerdatatransmissionaudit WHERE (moodle_moodlelearnerdatatransmissionaudit.enterprise_course_enrollment_id= 1614006 AND moodle_moodlelearnerdatatransmissionaudit.error_message = '' AND moodle_moodlelearnerdatatransmissionaudit.plugin_configuration_id= 7 AND moodle_moodlelearnerdatatransmissionaudit.status < '400') ORDER BY moodle_moodlelearnerdatatransmissionaudit.id;
SELECT * FROM moodle_moodlelearnerdatatransmissionaudit WHERE (moodle_moodlelearnerdatatransmissionaudit.enterprise_course_enrollment_id= 3378211 AND moodle_moodlelearnerdatatransmissionaudit.error_message = '' AND moodle_moodlelearnerdatatransmissionaudit.plugin_configuration_id= 8 AND moodle_moodlelearnerdatatransmissionaudit.status < '400') ORDER BY moodle_moodlelearnerdatatransmissionaudit.id;




SELECT `moodle_moodlelearnerdatatransmissionaudit`.`id`,
`moodle_moodlelearnerdatatransmissionaudit`.`created`,
`moodle_moodlelearnerdatatransmissionaudit`.`modified`,
`moodle_moodlelearnerdatatransmissionaudit`.`enterprise_customer_uuid`,
`moodle_moodlelearnerdatatransmissionaudit`.`user_email`,
`moodle_moodlelearnerdatatransmissionaudit`.`plugin_configuration_id`,
`moodle_moodlelearnerdatatransmissionaudit`.`enterprise_course_enrollment_id`,
`moodle_moodlelearnerdatatransmissionaudit`.`course_id`,
`moodle_moodlelearnerdatatransmissionaudit`.`content_title`,
`moodle_moodlelearnerdatatransmissionaudit`.`course_completed`,
`moodle_moodlelearnerdatatransmissionaudit`.`progress_status`,
`moodle_moodlelearnerdatatransmissionaudit`.`completed_timestamp`,
`moodle_moodlelearnerdatatransmissionaudit`.`instructor_name`,
`moodle_moodlelearnerdatatransmissionaudit`.`grade`,
`moodle_moodlelearnerdatatransmissionaudit`.`total_hours`,
`moodle_moodlelearnerdatatransmissionaudit`.`subsection_id`,
`moodle_moodlelearnerdatatransmissionaudit`.`subsection_name`,
`moodle_moodlelearnerdatatransmissionaudit`.`status`,
`moodle_moodlelearnerdatatransmissionaudit`.`error_message`,
`moodle_moodlelearnerdatatransmissionaudit`.`friendly_status_message`,
`moodle_moodlelearnerdatatransmissionaudit`.`api_record_id`,
`moodle_moodlelearnerdatatransmissionaudit`.`moodle_user_email`,
`moodle_moodlelearnerdatatransmissionaudit`.`moodle_completed_timestamp`
FROM `moodle_moodlelearnerdatatransmissionaudit`
WHERE `moodle_moodlelearnerdatatransmissionaudit`.`enterprise_course_enrollment_id` = 3378211
AND `moodle_moodlelearnerdatatransmissionaudit`.`is_transmitted` = true
AND `moodle_moodlelearnerdatatransmissionaudit`.`plugin_configuration_id` = 8
ORDER BY `moodle_moodlelearnerdatatransmissionaudit`.`id` DESC
LIMIT 1;

138 changes: 138 additions & 0 deletions enterprise/management/commands/update_ccb_enterprise_uids.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import logging
import csv
from django.db import transaction
from django.core.management.base import BaseCommand
from django.core.exceptions import ValidationError
from social_django.models import UserSocialAuth

logger = logging.getLogger(__name__)


class CSVUpdateError(Exception):
"""Custom exception for CSV update process."""
pass


class Command(BaseCommand):
"""
Update the CCB enterprise related social auth records UID to the new one.
Example usage:
./manage.py lms update_ccb_enterprise_uids csv_file_path
"""

help = 'Robust record update from CSV with console logging'

def add_arguments(self, parser):
parser.add_argument('csv_file', type=str, help='Path to the CSV file')
parser.add_argument(
'--no-dry-run',
action='store_false',
dest='dry_run',
default=True,
help='Actually save changes instead of simulating'
)

def handle(self, *args, **options):
logger.info("Command has started...")
csv_path = options['csv_file']
dry_run = options['dry_run']

total_processed = 0
total_updated = 0
total_errors = 0

try:
with open(csv_path, 'r') as csvfile:
reader = csv.DictReader(csvfile)

for row_num, row in enumerate(reader, start=1):
total_processed += 1

try:
# Use a separate transaction for each record
with transaction.atomic():
if self.update_record(row, dry_run):
total_updated += 1

except Exception as row_error:
total_errors += 1
error_msg = f"Row {row_num} update failed: {row} - Error: {str(row_error)}"
logger.error(error_msg, exc_info=True)

# Summary logging
summary_msg = (
f"CSV Update Summary:\n"
f"Total Records Processed: {total_processed}\n"
f"Records Successfully Updated: {total_updated}\n"
f"Errors Encountered: {total_errors}\n"
f"Dry Run Mode: {'Enabled' if dry_run else 'Disabled'}"
)
logger.info(summary_msg)
except IOError as io_error:
logger.critical(f"File I/O error: {str(io_error)}")

except Exception as e:
logger.critical(f"Critical error in CSV processing: {str(e)}")

def update_record(self, row, dry_run=True):
"""
Update a single record with detailed error handling.
Args:
row (dict): CSV row data
dry_run (bool): Whether to simulate or actually save changes
Returns:
bool: Whether the update was successful
"""
try:
# Validate required fields are present
old_uid = row.get('old-uid')
new_uid = row.get('new-uid')

if not old_uid or not new_uid:
raise CSVUpdateError("Missing required UID fields")

# Construct full UIDs with proper prefixes
old_uid_with_prefix = f'sf-ccb:{old_uid}'
new_uid_with_prefix = f'ccb:samlp|ccb-c52b6697-57da-492b-8d17-7d5f0c0290f2|{new_uid}@ccb.org.co'

# Retrieve instances
instance_with_old_uid = UserSocialAuth.objects.filter(uid=old_uid_with_prefix).first()

if not instance_with_old_uid:
raise CSVUpdateError(f"No record found with old UID {old_uid_with_prefix}")

# Optional: Check for conflicting new UID
instance_with_new_uid = UserSocialAuth.objects.filter(uid=new_uid_with_prefix).first()
if instance_with_new_uid:
log_entry = f"Warning: Existing record with new UID {new_uid_with_prefix} is deleting."
logger.info(log_entry)
if not dry_run:
instance_with_new_uid.delete()

if not dry_run:
instance_with_old_uid.uid = new_uid_with_prefix
instance_with_old_uid.save()

# Logging
log_entry = f"Successfully updated record: Old UID {old_uid_with_prefix} → New UID {new_uid_with_prefix}"
logger.info(log_entry)

return True

except ValidationError as ve:
error_msg = f"Validation error: {ve}"
logger.error(error_msg)
raise

except CSVUpdateError as update_error:
error_msg = f"Update processing error: {update_error}"
logger.error(error_msg)
raise

except Exception as e:
error_msg = f"Unexpected error during record update: {e}"
logger.error(error_msg, exc_info=True)
raise

0 comments on commit 73d718a

Please sign in to comment.