- Fix SUBTREE→BASE scope in _fetch_user_attributes (security)
- Remove is_ldap_user threading from all 8 media client interfaces;
set flag after join via workflow-level User.query.update instead
- Use find_user_dn (search-based) instead of build_user_dn (concatenation)
in delete_user and reset_user_password for robustness
- Wrap all user-facing strings in _() for i18n in ldap_auth.py
- Fix username fallback from hardcoded "wizarr" to unique per-user
- Return failure from _update_existing_user when password update fails
- Replace dynamic Tailwind classes with explicit conditionals in alert
- Add stale group cleanup and upsert in sync_ldap_groups
- Remove fake @ldap.local email fallback in user_sync
Security:
- Fix XSS in HTMX responses by replacing f-string HTML with Jinja partials
- Fix TLS verify_cert not being applied (add Tls config to ldap3 Server)
- Fix password_hash NOT NULL conflict for LDAP-only admin accounts
- Fix should_create_ldap_user defaulting to True for existing invitations
Correctness:
- Fix DN reconstruction fragility using escape_rdn for special characters
- Fix connection leaks with try/finally in all LDAPClient methods
- Fix sync interval logic (check FLASK_ENV not WIZARR_ENABLE_SCHEDULER)
- Only register LDAP sync job when LDAP is actually configured
- Make find_user_dn and service_connection public API methods
Cleanup:
- Squash 5 incremental LDAP migrations into single 20251226_add_ldap_support
- Remove duplicate imports/queries in auth routes
- Replace f-string logging with %s formatting
- Extract inline HTML to Jinja template partials