From cbe2ef0524ed9f4af98bc4afc95bb9480fba944a Mon Sep 17 00:00:00 2001
From: Jiri Kalvoda <jirikalvoda@kam.mff.cuni.cz>
Date: Tue, 28 Sep 2021 22:52:00 +0200
Subject: [PATCH] =?UTF-8?q?Users:=20find=5For=5Fcreate=5Fuser=20um=C3=AD?=
 =?UTF-8?q?=20na=20po=C5=BE=C3=A1d=C3=A1n=C3=AD=20zm=C4=9Bnit=20=C3=BA?=
 =?UTF-8?q?=C4=8Dastn=C3=ADka=20na=20orga?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 mo/imports.py         |  2 +-
 mo/users.py           | 18 ++++++++++++++----
 mo/web/org_contest.py |  2 +-
 3 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/mo/imports.py b/mo/imports.py
index 73ec1a6f..927539ff 100644
--- a/mo/imports.py
+++ b/mo/imports.py
@@ -195,7 +195,7 @@ class Import:
 
     def find_or_create_user(self, email: str, krestni: Optional[str], prijmeni: Optional[str], is_org: bool) -> Optional[db.User]:
         try:
-            user, is_new = mo.users.find_or_create_user(email, krestni, prijmeni, is_org, reason='import')
+            user, is_new, is_change_user_to_org = mo.users.find_or_create_user(email, krestni, prijmeni, is_org, reason='import')
         except mo.CheckError as e:
             return self.error(str(e))
         if is_new:
diff --git a/mo/users.py b/mo/users.py
index 17fc472e..aae885ac 100644
--- a/mo/users.py
+++ b/mo/users.py
@@ -52,6 +52,11 @@ def validate_and_find_school(kod: str) -> db.Place:
     return place
 
 
+class CheckErrorOrgIsUser(mo.CheckError):
+    """Při požadavku na orga nalezen uživatel nebo opačně."""
+    pass
+
+
 def change_user_to_org(user, reason: str):
     if (db.get_session().query(db.Participation, db.Contest, db.Round)
             .select_from(db.Participation)
@@ -70,10 +75,11 @@ def change_user_to_org(user, reason: str):
     )
 
 
-def find_or_create_user(email: str, krestni: Optional[str], prijmeni: Optional[str], is_org: bool, reason: str) -> Tuple[db.User, bool]:
+def find_or_create_user(email: str, krestni: Optional[str], prijmeni: Optional[str], is_org: bool, reason: str, allow_change_user_to_org=False) -> Tuple[db.User, bool, bool]:
     sess = db.get_session()
     user = sess.query(db.User).filter_by(email=email).one_or_none()
     is_new = user is None
+    is_change_user_to_org = False
     if user is None:  # HACK: Podmínku je nutné zapsat znovu místo užití is_new, jinak si s tím mypy neporadí
         if not krestni or not prijmeni:
             raise mo.CheckError('Osoba s daným emailem zatím neexistuje, je nutné uvést její jméno.')
@@ -91,10 +97,14 @@ def find_or_create_user(email: str, krestni: Optional[str], prijmeni: Optional[s
             raise mo.CheckError(f'Osoba již registrována s odlišným jménem {user.full_name()}')
         if (user.is_admin or user.is_org) != is_org:
             if is_org:
-                raise mo.CheckError('Nelze předefinovat účastníka na organizátora')
+                if allow_change_user_to_org:
+                    change_user_to_org(user, reason)
+                    is_change_user_to_org = True
+                else:
+                    raise CheckErrorOrgIsUser('Nelze předefinovat účastníka na organizátora.')
             else:
-                raise mo.CheckError('Nelze předefinovat organizátora na účastníka')
-    return user, is_new
+                raise CheckError('Nelze předefinovat organizátora na účastníka.')
+    return user, is_new, is_change_user_to_org
 
 
 def find_or_create_participant(user: db.User, year: int, school_id: Optional[int], birth_year: Optional[int], grade: Optional[str], reason: str) -> Tuple[db.Participant, bool]:
diff --git a/mo/web/org_contest.py b/mo/web/org_contest.py
index f2524acc..65fb7a65 100644
--- a/mo/web/org_contest.py
+++ b/mo/web/org_contest.py
@@ -1634,7 +1634,7 @@ def org_contest_add_user(ct_id: int, site_id: Optional[int] = None):
 
     if form.validate_on_submit():
         try:
-            user, is_new_user = mo.users.find_or_create_user(form.email.data, form.first_name.data, form.last_name.data, False, reason='web')
+            user, is_new_user, is_change_user_to_org = mo.users.find_or_create_user(form.email.data, form.first_name.data, form.last_name.data, False, reason='web')
             participant, is_new_participant = mo.users.find_or_create_participant(user, contest.round.year, form.school.get_place_id(), form.birth_year.data, form.grade.data, reason='web')
             participation, is_new_participation = mo.users.find_or_create_participation(user, contest, form.participation_place.get_place(), reason='web')
         except mo.CheckError as e:
-- 
GitLab