CSV User Sync
Versions
Current version
0.1.1 (2026022600)
0.1.1
Plugin type: Local plugins
Frankenstyle component name: local_csv_user_sync
Version build number: 2026022600
Version release name: 0.1.1
Maturity: Beta
Supported Moodle versions: 4.4, 4.5, 5.0, 5.1
Repository URL (Git): https://github.com/mdlbox/moodle-csv_user_sync/
Repository branch:
Repository tag:
Issue/bug tracker URL: https://github.com/mdlbox/moodle-csv_user_sync/issues
CSV User Sync (local_csv_user_sync)
local_csv_user_sync is a Moodle local plugin that synchronizes users and manual course enrolments from a CSV source.
It supports user creation and updates, enrolment creation/update/removal, dry-run mode, detailed logging, and a secure onboarding email flow for new users.
Features
- Imports users from CSV into Moodle.
- Updates existing users (optionally only when values changed).
- Synchronizes manual enrolments by course shortname and role shortname.
- Supports enrolment suspension and deletion flags.
- Can auto-create missing manual enrolment instances for courses.
- Supports CSV source from:
- absolute file path, or
- uploaded file in plugin settings.
- Supports configurable delimiter and encoding (
UTF-8,ISO-8859-1,Windows-1252,auto). - Validates CSV structure and required headers before processing.
- Supports Moodle custom profile fields from CSV.
- Provides downloadable CSV template (including custom profile fields).
- Includes dry-run mode (simulate actions without writing data).
- Uses task-level locking to prevent concurrent sync runs.
- Logs to both
mtraceand plugin DB table (local_csv_user_sync_log). - Includes GDPR privacy provider for exported/deleted user-related log data.
Requirements
- Moodle
4.5branch or newer ($plugin->requires = 2024100700). - Plugin component:
local_csv_user_sync.
Installation
- Copy the plugin into:
local/csv_user_sync
- Visit:
Site administration -> Notifications
- Complete database upgrade if prompted.
Configuration
Path:
Site administration -> Plugins -> Local plugins -> CSV User Sync
1) CSV Source (exactly one)
Configure only one source:
CSV file path(absolute path), orCSV file upload(stored file areacsvsource)
If both or neither are set, the task stops with a configuration error.
2) Parser Options
File encoding:UTF-8,ISO-8859-1,Windows-1252,autoDelimiter: single character (default;)
3) Authentication and New User Email
Default authentication method: used when CSVauthis empty or invalid.Send credentials email: for newly created users.Email template: supports placeholders:
{{firstname}}{{lastname}}{{username}}{{setpasswordurl}}{{sitename}}{{loginurl}}
- Legacy compatibility:
{{password}}is still accepted as an alias for{{setpasswordurl}}.
4) Sync Behavior
Update only changed dataDetailed loggingDry-run mode
CSV Format
Header normalization
Headers are normalized before matching:
- lowercase
- spaces/hyphens converted to
_ - non
[a-z0-9_]characters removed - UTF-8 BOM removed from first header
Example:
Course Shortname->course_shortname
Required headers
These headers must exist:
usernamefirstnamelastnameemail
Enrolment headers must be paired:
course_shortnameandrole_shortnamemust both be present if either is present.
Supported user headers
usernamefirstnamelastnameemailauthcitycountrylangidnumberinstitutiondepartmentphone1phone2address
Supported enrolment headers
course_shortnamerole_shortnameenrol_start_date(alias:start_date)enrol_end_date(alias:end_date)suspended(0or1, empty treated as0)deleted(0or1, empty treated as0)
Custom profile fields
Two ways are accepted:
profile_field_<shortname><shortname>(if it is not a reserved/system header and matches an existing profile field)
Accepted date formats
Y-m-d(example2026-02-18)d.m.Y(example18.02.2026)d/m/Y(example18/02/2026)YYYYMMDD(example20260218)- Unix timestamp (seconds, 10 digits)
- Unix timestamp (milliseconds, 13 digits)
- Empty value means
0(no date)
Runtime Behavior
For each row:
- Validate mandatory user values.
- Create or update user.
- If course shortname is present, process enrolment.
Enrolment logic highlights:
- If
deleted = 1: remove existing manual enrolment. - If
suspended = 1: set enrolment to suspended. - If enrolment exists and start/end dates are empty: preserve existing dates.
- If role changes, plugin enforces exactly one manual role assignment for that instance.
If a manual enrolment instance is missing on a target course, the plugin creates one (unless dry-run).
Security Notes
- Template download endpoint requires:
- authenticated session
- valid
sesskey moodle/site:configcapability
- Plugin file serving is restricted to system context and
moodle/site:config. - User data from CSV is sanitized before writes.
- New user:
- It sends a one-time password setup/reset URL (
{{setpasswordurl}}) when supported by user auth. - Falls back to login URL when reset links are not available.
- It sends a one-time password setup/reset URL (
- Exception messages are sanitized before persistent logging to reduce sensitive path leakage.
Logging and Privacy
Logs are written to:
mtraceoutputlocal_csv_user_sync_logtable (runid, level, rownum, userid, username, message, timecreated)
Privacy support:
- Plugin declares metadata and supports export/deletion for user-related records in
local_csv_user_sync_log.
Scheduled Task
Task class:
\local_csv_user_sync\task\sync_task
Default schedule:
- random minute / random hour, daily (
R R * * *)
Manual execution example:
php admin/cli/scheduled_task.php --execute="\\local_csv_user_sync\\task\\sync_task"
Dry-run Mode
When enabled:
- no DB writes for users/enrolments
- actions are simulated and logged
- enrolment for newly "created" dry-run users is skipped because no real user ID exists
Troubleshooting
Common checks:
- Ensure exactly one CSV source is configured.
- Ensure delimiter is exactly one character.
- Ensure required headers exist.
- Ensure
course_shortnameandrole_shortnameare both present for enrolment imports. - Ensure role shortnames and course shortnames exist in Moodle.
- Ensure uploaded file still exists in plugin file storage.
0.1.0 (2026021604)
0.1.0
Plugin type: Local plugins
Frankenstyle component name: local_csv_user_sync
Version build number: 2026021604
Version release name: 0.1.0
Maturity: Stable
Supported Moodle versions: 4.4, 4.5, 5.0, 5.1
Repository URL (Git): https://github.com/mdlbox/moodle-csv_user_sync/
Repository branch: https://github.com/mdlbox/moodle-csv_user_sync/tree/main
Repository tag:
Issue/bug tracker URL: https://github.com/mdlbox/moodle-csv_user_sync/issues
CSV User Sync (local_csv_user_sync)
local_csv_user_sync is a Moodle local plugin that synchronizes users and manual course enrolments from a CSV source.
It supports user creation and updates, enrolment creation/update/removal, dry-run mode, detailed logging, and a secure onboarding email flow for new users.
Features
- Imports users from CSV into Moodle.
- Updates existing users (optionally only when values changed).
- Synchronizes manual enrolments by course shortname and role shortname.
- Supports enrolment suspension and deletion flags.
- Can auto-create missing manual enrolment instances for courses.
- Supports CSV source from:
- absolute file path, or
- uploaded file in plugin settings.
- Supports configurable delimiter and encoding (
UTF-8,ISO-8859-1,Windows-1252,auto). - Validates CSV structure and required headers before processing.
- Supports Moodle custom profile fields from CSV.
- Provides downloadable CSV template (including custom profile fields).
- Includes dry-run mode (simulate actions without writing data).
- Uses task-level locking to prevent concurrent sync runs.
- Logs to both
mtraceand plugin DB table (local_cus_log). - Includes GDPR privacy provider for exported/deleted user-related log data.
Requirements
- Moodle
4.5branch or newer ($plugin->requires = 2024100700). - Plugin component:
local_csv_user_sync.
Installation
- Copy the plugin into:
local/csv_user_sync
- Visit:
Site administration -> Notifications
- Complete database upgrade if prompted.
Configuration
Path:
Site administration -> Plugins -> Local plugins -> CSV User Sync
1) CSV Source (exactly one)
Configure only one source:
CSV file path(absolute path), orCSV file upload(stored file areacsvsource)
If both or neither are set, the task stops with a configuration error.
2) Parser Options
File encoding:UTF-8,ISO-8859-1,Windows-1252,autoDelimiter: single character (default;)
3) Authentication and New User Email
Default authentication method: used when CSVauthis empty or invalid.Send credentials email: for newly created users.Email template: supports placeholders:
{{firstname}}{{lastname}}{{username}}{{setpasswordurl}}{{sitename}}{{loginurl}}
- Legacy compatibility:
{{password}}is still accepted as an alias for{{setpasswordurl}}.
4) Sync Behavior
Update only changed dataDetailed loggingDry-run mode
CSV Format
Header normalization
Headers are normalized before matching:
- lowercase
- spaces/hyphens converted to
_ - non
[a-z0-9_]characters removed - UTF-8 BOM removed from first header
Example:
Course Shortname->course_shortname
Required headers
These headers must exist:
usernamefirstnamelastnameemail
Enrolment headers must be paired:
course_shortnameandrole_shortnamemust both be present if either is present.
Supported user headers
usernamefirstnamelastnameemailauthcitycountrylangidnumberinstitutiondepartmentphone1phone2address
Supported enrolment headers
course_shortnamerole_shortnameenrol_start_date(alias:start_date)enrol_end_date(alias:end_date)suspended(0or1, empty treated as0)deleted(0or1, empty treated as0)
Custom profile fields
Two ways are accepted:
profile_field_<shortname><shortname>(if it is not a reserved/system header and matches an existing profile field)
Accepted date formats
Y-m-d(example2026-02-18)d.m.Y(example18.02.2026)d/m/Y(example18/02/2026)YYYYMMDD(example20260218)- Unix timestamp (seconds, 10 digits)
- Unix timestamp (milliseconds, 13 digits)
- Empty value means
0(no date)
Runtime Behavior
For each row:
- Validate mandatory user values.
- Create or update user.
- If course shortname is present, process enrolment.
Enrolment logic highlights:
- If
deleted = 1: remove existing manual enrolment. - If
suspended = 1: set enrolment to suspended. - If enrolment exists and start/end dates are empty: preserve existing dates.
- If role changes, plugin enforces exactly one manual role assignment for that instance.
If a manual enrolment instance is missing on a target course, the plugin creates one (unless dry-run).
Security Notes
- Template download endpoint requires:
- authenticated session
- valid
sesskey moodle/site:configcapability
- Plugin file serving is restricted to system context and
moodle/site:config. - User data from CSV is sanitized before writes.
- New user:
- It sends a one-time password setup/reset URL (
{{setpasswordurl}}) when supported by user auth. - Falls back to login URL when reset links are not available.
- It sends a one-time password setup/reset URL (
- Exception messages are sanitized before persistent logging to reduce sensitive path leakage.
Logging and Privacy
Logs are written to:
mtraceoutputlocal_cus_logtable (runid, level, rownum, userid, username, message, timecreated)
Privacy support:
- Plugin declares metadata and supports export/deletion for user-related records in
local_cus_log.
Scheduled Task
Task class:
\local_csv_user_sync\task\sync_task
Default schedule:
- random minute / random hour, daily (
R R * * *)
Manual execution example:
php admin/cli/scheduled_task.php --execute="\\local_csv_user_sync\\task\\sync_task"
Dry-run Mode
When enabled:
- no DB writes for users/enrolments
- actions are simulated and logged
- enrolment for newly "created" dry-run users is skipped because no real user ID exists
Troubleshooting
Common checks:
- Ensure exactly one CSV source is configured.
- Ensure delimiter is exactly one character.
- Ensure required headers exist.
- Ensure
course_shortnameandrole_shortnameare both present for enrolment imports. - Ensure role shortnames and course shortnames exist in Moodle.
- Ensure uploaded file still exists in plugin file storage.