Explicitly create users in Zammad before using them

Closes #40. Closes #141. For some reason, Zammad behaves differently when
the corresponding user doesn't exit yet. This also allows us to
explicitly set a name for users (at least for new ones).
This commit is contained in:
Yannik Rödel 2024-04-04 18:02:14 +02:00
parent e2623df390
commit 8a43f29bc4

View file

@ -158,7 +158,10 @@ def get_form_value(
return (value_object.filename or "upload"), value_object.file.read()
else:
try:
return cast(form.getfirst(name))
result = cast(form.getfirst(name))
if isinstance(result, str):
result = result.strip()
return result
except (TypeError, ValueError):
fail("400 Bad Request", f"Invalid value for field: {name}")
@ -187,6 +190,7 @@ if not isinstance(hcaptcha_data, Mapping) or not hcaptcha_data.get("success", Fa
# Extract all the actually provided form data. This is different from form to
# form (see the match block below).
contact_name = get_form_value("contactname")
contact_names = contact_name.split(" ")
contact_email = get_form_value("contactemail")
if not EMAIL_REGEX.fullmatch(contact_email):
@ -289,13 +293,41 @@ ZAMMAD_TOKEN = os.environ.get("ZAMMAD_TOKEN", "")
session.headers.update(Authorization=f"Token token={ZAMMAD_TOKEN}")
try:
# Create a new user for the client. For some reason, using "guess:{email}" as the
# customer_id when creating the ticket doesn't really work, as described in the
# Zammad documentation [1]. Instead, we sometimes need to explictily create the
# user beforehand. See this discussion [2] for more details.
# [1]: https://docs.zammad.org/en/latest/api/ticket/index.html#create
# [2]: https://codeberg.org/angestoepselt/homepage/issues/141
response = session.post(
f"{ZAMMAD_URL}/api/v1/users",
json=dict(
# Yes, yes... This goes against pretty much all best practices for parsing
# names. But: it's only internal and we save the name verbatim again below
# so we're going to go ahead and do it anyway.
firstname=" ".join(contact_names[:-1]) if len(contact_names) >= 2 else "?",
lastname=contact_names[-1],
email=contact_email,
)
)
if response.status_code == 422:
# This email address is already in use by another user.
customer_id = f"guess:{contact_email}"
else:
response.raise_for_status()
customer_id = response.json()["id"]
assert isinstance(customer_id, (str, int))
# Add the actual ticket to the system.
response = session.post(
f"{ZAMMAD_URL}/api/v1/tickets",
headers={
"X-On-Behalf-Of": contact_email,
},
json=dict(
title=f"Kontaktformular {contact_name} {form_name}",
group=form_group,
customer_id=f"guess:{contact_email}",
customer_id=customer_id,
article=dict(
type="web",
internal=True,