Skip to content
Snippets Groups Projects
Commit 273bb4bf authored by Tore.Brede's avatar Tore.Brede
Browse files

Merge branch 'GREG-158_error_handling_partial_success' into 'master'

GREG-158: Better error reponse when e-mail sending failed for invite

See merge request !218
parents f2df515e 320ec643
No related branches found
No related tags found
1 merge request!218GREG-158: Better error reponse when e-mail sending failed for invite
Pipeline #105735 passed
...@@ -168,11 +168,13 @@ ...@@ -168,11 +168,13 @@
"unknown": "An unknown error has occurred. If the problem persists, contact support.", "unknown": "An unknown error has occurred. If the problem persists, contact support.",
"invitationDataFetchFailed": "Failed to fetch invitation data", "invitationDataFetchFailed": "Failed to fetch invitation data",
"guestRegistrationFailed": "Failed to register your data", "guestRegistrationFailed": "Failed to register your data",
"partialSubmitSuccess": "Invite creation partial successful",
"codes": { "codes": {
"invalid_invite": "Invalid invite", "invalid_invite": "Invalid invite",
"invite_expired": "Invite has expired", "invite_expired": "Invite has expired",
"cannot_update_fields": "Failed to update data", "cannot_update_fields": "Failed to update data",
"update_national_id_not_allowed": "Not allowed to update verified national ID" "update_national_id_not_allowed": "Not allowed to update verified national ID",
"invite_email_failed": "There was a problem sending the invite e-mail. Contact support."
} }
} }
} }
...@@ -168,11 +168,13 @@ ...@@ -168,11 +168,13 @@
"errorLoadOusRoleType": "Kunne ikke laste organisasjons og/eller rolletype data fra server", "errorLoadOusRoleType": "Kunne ikke laste organisasjons og/eller rolletype data fra server",
"invitationDataFetchFailed": "Klarte ikke å hente invitasjonsdata", "invitationDataFetchFailed": "Klarte ikke å hente invitasjonsdata",
"guestRegistrationFailed": "Klarte ikke å registrere dataene dine", "guestRegistrationFailed": "Klarte ikke å registrere dataene dine",
"partialSubmitSuccess": "",
"codes": { "codes": {
"invalid_invite": "Ugyldig invitasjon", "invalid_invite": "Ugyldig invitasjon",
"invite_expired": "Invitasjonen har utløpt", "invite_expired": "Invitasjonen har utløpt",
"cannot_update_fields": "Klarte ikke å oppdatere dataene", "cannot_update_fields": "Klarte ikke å oppdatere dataene",
"update_national_id_not_allowed": "Ikke tillatt å endre verifisert fødselsnummer/D-nummer" "update_national_id_not_allowed": "Ikke tillatt å endre verifisert fødselsnummer/D-nummer",
"invite_email_failed": "Klarte ikke å sende e-post med invitasjon. Kontakt support."
} }
} }
} }
...@@ -173,7 +173,8 @@ ...@@ -173,7 +173,8 @@
"invalid_invite": "Ugyldig invitasjon", "invalid_invite": "Ugyldig invitasjon",
"invite_expired": "Invitasjonen har gått ut", "invite_expired": "Invitasjonen har gått ut",
"cannot_update_fields": "Klarte ikkje å oppdatere informasjonen din", "cannot_update_fields": "Klarte ikkje å oppdatere informasjonen din",
"update_national_id_not_allowed": "Ikkje tillate å endre verifisert fødselsnummer/D-nummer" "update_national_id_not_allowed": "Ikkje tillate å endre verifisert fødselsnummer/D-nummer",
"invite_email_failed": "Klarte ikkje å sende e-post med invitasjon. Kontakt support."
} }
} }
} }
...@@ -54,6 +54,8 @@ export default function StepRegistration() { ...@@ -54,6 +54,8 @@ export default function StepRegistration() {
useState<ServerErrorReportData>() useState<ServerErrorReportData>()
const [formDataErrorReport, setFormDataErrorReport] = const [formDataErrorReport, setFormDataErrorReport] =
useState<ServerErrorReportData>() useState<ServerErrorReportData>()
const [submitPartialSuccess, setSubmitPartialSuccess] =
useState<ServerErrorReportData>()
// The organizational unit and role types are not used by this component, but // The organizational unit and role types are not used by this component, but
// loading them here anyways to make sure that they can be loaded using the // loading them here anyways to make sure that they can be loaded using the
...@@ -71,6 +73,62 @@ export default function StepRegistration() { ...@@ -71,6 +73,62 @@ export default function StepRegistration() {
} }
} }
function handleSubmitErrorResponse(res: Response) {
// Try to extract data from body of error message
res
.text()
.then((text) => {
setSubmitState(SubmitState.SubmitFailure)
setSubmitErrorReport({
errorHeading: t('error.invitationCreationFailedHeader'),
statusCode: res.status,
statusText: res.statusText,
errorBodyText: text,
})
})
.catch((error) => {
// Extracting data from body failed, just show an error message with no body text
console.error('error', error)
setSubmitErrorReport({
errorHeading: t('error.invitationCreationFailedHeader'),
statusCode: res.status,
statusText: res.statusText,
errorBodyText: undefined,
})
setSubmitState(SubmitState.SubmitFailure)
})
}
function handleSubmitOkResponse(res: Response) {
// The invite was created, but there may still be some warning
res
.json()
.then((jsonResponse) => {
// If there is a body then it should have some json-content
console.log('result', jsonResponse)
if ('code' in jsonResponse) {
// There is something in the body indicating a warning
setSubmitPartialSuccess({
errorHeading: t('error.partialSubmitSuccess'),
statusCode: undefined,
statusText: undefined,
errorBodyText: t(`error.codes.${jsonResponse.code}`),
})
} else {
console.log(JSON.stringify(jsonResponse))
}
})
.catch((exception) => {
// There was a problem when extracting the body
console.error(exception)
})
.finally(() => {
setSubmitState(SubmitState.SubmitSuccess)
setActiveStep(Steps.SuccessStep)
})
}
const registerGuest = () => { const registerGuest = () => {
const payload = { const payload = {
first_name: formData.first_name, first_name: formData.first_name,
...@@ -96,41 +154,12 @@ export default function StepRegistration() { ...@@ -96,41 +154,12 @@ export default function StepRegistration() {
fetch('/api/ui/v1/invite/', submitJsonOpts('POST', payload)) fetch('/api/ui/v1/invite/', submitJsonOpts('POST', payload))
.then((res) => { .then((res) => {
if (!res.ok) { if (!res.ok) {
// Try to extract data from body of error message handleSubmitErrorResponse(res)
res
.text()
.then((text) => {
setSubmitState(SubmitState.SubmitFailure)
setSubmitErrorReport({
errorHeading: t('error.invitationCreationFailedHeader'),
statusCode: res.status,
statusText: res.statusText,
errorBodyText: text,
})
})
.catch((error) => {
// Extracting data from body failed, just show an error message with no body text
console.error('error', error)
setSubmitErrorReport({
errorHeading: t('error.invitationCreationFailedHeader'),
statusCode: res.status,
statusText: res.statusText,
errorBodyText: undefined,
})
setSubmitState(SubmitState.SubmitFailure)
})
} else { } else {
return res.text() handleSubmitOkResponse(res)
} }
return null return null
}) })
.then((result) => {
if (result !== null) {
console.log('result', result)
setSubmitState(SubmitState.SubmitSuccess)
setActiveStep(Steps.SuccessStep)
}
})
.catch((error) => { .catch((error) => {
console.error('error', error) console.error('error', error)
setSubmitState(SubmitState.SubmitFailure) setSubmitState(SubmitState.SubmitFailure)
...@@ -265,6 +294,15 @@ export default function StepRegistration() { ...@@ -265,6 +294,15 @@ export default function StepRegistration() {
errorBodyText={formDataErrorReport.errorBodyText} errorBodyText={formDataErrorReport.errorBodyText}
/> />
)} )}
{submitPartialSuccess !== undefined && (
<ServerErrorReport
errorHeading={submitPartialSuccess.errorHeading}
statusCode={undefined}
statusText={undefined}
errorBodyText={submitPartialSuccess.errorBodyText}
/>
)}
</Page> </Page>
) )
} }
...@@ -75,9 +75,22 @@ class InvitationView(CreateAPIView, DestroyAPIView): ...@@ -75,9 +75,22 @@ class InvitationView(CreateAPIView, DestroyAPIView):
invitation__role__person_id=person.id, invitation__role__person_id=person.id,
invitation__role__sponsor_id=sponsor_user.sponsor_id, invitation__role__sponsor_id=sponsor_user.sponsor_id,
): ):
send_invite_mail(invitationlink) try:
send_invite_mail(invitationlink)
except Exception:
logger.exception("send_invite_mail_failed", exc_info=True)
# The invite has been created, so send 201, but include some data saying the
# e-mail was not sent properly
return Response(
status=status.HTTP_201_CREATED,
data={
"code": "invite_email_failed",
"message": "Failed to send invite e-mail",
},
)
return Response(status=status.HTTP_201_CREATED) # Empty json-body to avoid client complaining about non-json data in response
return Response(status=status.HTTP_201_CREATED, data={})
def delete(self, request, *args, **kwargs) -> Response: def delete(self, request, *args, **kwargs) -> Response:
try: try:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment