Bug 56342 - School user import is not case-insensitive for school name and creates errors on rerun
School user import is not case-insensitive for school name and creates errors...
Status: NEW
Product: UCS@school
Classification: Unclassified
Component: Import scripts
UCS@school 5.0
Other Linux
: P5 normal (vote)
: ---
Assigned To: UCS@school maintainers
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2023-07-20 12:58 CEST by J Leadbetter
Modified: 2023-07-20 15:48 CEST (History)
0 users

See Also:
What kind of report is it?: Bug Report
What type of bug is this?: 5: Major Usability: Impairs usability in key scenarios
Who will be affected by this bug?: 2: Will only affect a few installed domains
How will those affected feel about the bug?: 3: A User would likely not purchase the product
User Pain: 0.171
Enterprise Customer affected?:
School Customer affected?:
ISV affected?:
Waiting Support:
Flags outvoted (downgraded) after PO Review:
Ticket number:
Bug group (optional):
Max CVSS v3 score:


Attachments
Patch for Bug 56340 (713 bytes, patch)
2023-07-20 15:13 CEST, J Leadbetter
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description J Leadbetter univentionstaff 2023-07-20 12:58:45 CEST
## Background

If you have a school -- e.g., "Schule1" -- and you run the import with "schule1", it successfully imports users under "schule1" the first time, but subsequent runs of the identical import will fail with the following error:

```
2023-07-20 12:48:00 ERROR cmdline.main:255  ValueError: Missing school prefix in name: SchoolClass(name='schuleA-1a', school='SchuleA', dn='cn=schuleA-1a,cn=klassen,cn=schueler,cn=groups,ou=SchuleA,dc=autotest203,dc=test').
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/ucsschool/importer/frontend/cmdline.py", line 241, in main
    self.do_import()
  File "/usr/lib/python3/dist-packages/ucsschool/importer/frontend/cmdline.py", line 164, in do_import
    six.reraise(etype, exc, etraceback)
  File "/usr/lib/python3/dist-packages/six.py", line 693, in reraise
    raise value
  File "/usr/lib/python3/dist-packages/ucsschool/importer/frontend/cmdline.py", line 150, in do_import
    importer.mass_import()
  File "/usr/lib/python3/dist-packages/ucsschool/importer/mass_import/mass_import.py", line 84, in mass_import
    self.import_users()
  File "/usr/lib/python3/dist-packages/ucsschool/importer/mass_import/mass_import.py", line 143, in import_users
    raise exception
  File "/usr/lib/python3/dist-packages/ucsschool/importer/mass_import/mass_import.py", line 117, in import_users
    user_import.delete_users(users_to_delete)  # 0% - 10%
  File "/usr/lib/python3/dist-packages/ucsschool/importer/mass_import/user_import.py", line 498, in delete_users
    success = self.do_delete(user)
  File "/usr/lib/python3/dist-packages/ucsschool/importer/mass_import/sisopi_user_import.py", line 230, in do_delete
    success = user.modify(lo=self.connection)
  File "/usr/lib/python3/dist-packages/ucsschool/importer/models/import_user.py", line 1062, in modify
    lo, validate, move_if_necessary, check_password_policies=True
  File "/usr/lib/python3/dist-packages/ucsschool/lib/models/user.py", line 326, in modify
    return super(User, self).modify(lo=lo, validate=validate, move_if_necessary=move_if_necessary)
  File "/usr/lib/python3/dist-packages/ucsschool/lib/models/base.py", line 619, in modify
    success = self.modify_without_hooks(lo, validate, move_if_necessary)
  File "/usr/lib/python3/dist-packages/ucsschool/importer/models/import_user.py", line 1103, in modify_without_hooks
    return super(ImportUser, self).modify_without_hooks(lo, validate, move_if_necessary)
  File "/usr/lib/python3/dist-packages/ucsschool/lib/models/base.py", line 646, in modify_without_hooks
    self.do_modify(udm_obj, lo)
  File "/usr/lib/python3/dist-packages/ucsschool/lib/models/user.py", line 338, in do_modify
    if not self.remove_from_school(removed_school, lo):
  File "/usr/lib/python3/dist-packages/ucsschool/lib/models/user.py", line 588, in remove_from_school
    self.remove_from_groups_of_school(school, lo)
  File "/usr/lib/python3/dist-packages/ucsschool/lib/models/user.py", line 608, in remove_from_groups_of_school
    group.modify(lo)
  File "/usr/lib/python3/dist-packages/ucsschool/lib/models/base.py", line 619, in modify
    success = self.modify_without_hooks(lo, validate, move_if_necessary)
  File "/usr/lib/python3/dist-packages/ucsschool/lib/models/group.py", line 275, in modify_without_hooks
    success = super(SchoolClass, self).modify_without_hooks(lo, validate, move_if_necessary)
  File "/usr/lib/python3/dist-packages/ucsschool/lib/models/base.py", line 634, in modify_without_hooks
    self.validate(lo, validate_unlikely_changes=True)
  File "/usr/lib/python3/dist-packages/ucsschool/lib/models/group.py", line 331, in validate
    raise ValueError("Missing school prefix in name: {!r}.".format(self))
ValueError: Missing school prefix in name: SchoolClass(name='schuleA-1a', school='SchuleA', dn='cn=schuleA-1a,cn=klassen,cn=schueler,cn=groups,ou=SchuleA,dc=autotest203,dc=test').
```

Attempts to modify the user may result in other errors, and the solution seems to be to manually delete the user (not via the import) and re-import with the correctly cased school name. However, when dealing with an import of thousands of users, this isn't really feasible.

## Expected Behavior

The expected behavior should be one of two things:

1. Either the import should fail with a reasonable error message explaining that the school name is case-sensitive, OR
2. The import should be case-insensitive and correctly import the user into the right school.

Ideally, we'd go with #2, as we store our data in LDAP and we usually expect this to be case-insensitive.

## How to Reproduce

Create a new school with a name that has upper-case letters:

```bash
/usr/share/ucs-school-import/scripts/create_ou Schule1
```

Use the example `user_import.json` configuration defined in the [SiSoPi documentation](https://docs.software-univention.de/ucsschool-umc-user-import/5.0/de/single-source.html#beispielaufbau).

Create the following `schule1.csv` import file:

```csv
"Schule","Vorname","Nachname","Klassen","Beschreibung","Telefon","EMail"
"schule1","Vincent","Störtländer","1a","A teacher.","+67-303-103581",""
```

Then run the import:

```bash
/usr/share/ucs-school-import/scripts/ucs-school-user-import \
  --verbose \
  --user_role teacher \
  --infile schule1.csv \
  --school schule1
```

The import is successful, and you can verify the user exists.

Run the exact same import again, and note the traceback.