(e *core.RequestEvent)
| 14 | ) |
| 15 | |
| 16 | func recordRequestVerification(e *core.RequestEvent) error { |
| 17 | collection, err := findAuthCollection(e) |
| 18 | if err != nil { |
| 19 | return err |
| 20 | } |
| 21 | |
| 22 | if collection.Name == core.CollectionNameSuperusers { |
| 23 | return e.BadRequestError("All superusers are verified by default.", nil) |
| 24 | } |
| 25 | |
| 26 | form := new(recordRequestVerificationForm) |
| 27 | if err = e.BindBody(form); err != nil { |
| 28 | return firstApiError(err, e.BadRequestError("An error occurred while loading the submitted data.", err)) |
| 29 | } |
| 30 | if err = form.validate(); err != nil { |
| 31 | return firstApiError(err, e.BadRequestError("An error occurred while validating the submitted data.", err)) |
| 32 | } |
| 33 | |
| 34 | record, err := e.App.FindAuthRecordByEmail(collection, form.Email) |
| 35 | if err != nil { |
| 36 | // eagerly write 204 response as a very basic measure against emails enumeration |
| 37 | e.NoContent(http.StatusNoContent) |
| 38 | return fmt.Errorf("failed to fetch %s record with email %s: %w", collection.Name, form.Email, err) |
| 39 | } |
| 40 | |
| 41 | resendKey := getVerificationResendKey(record) |
| 42 | if !record.Verified() && e.App.Store().Has(resendKey) { |
| 43 | // eagerly write 204 response as a very basic measure against emails enumeration |
| 44 | e.NoContent(http.StatusNoContent) |
| 45 | return errors.New("try again later - you've already requested a verification email") |
| 46 | } |
| 47 | |
| 48 | event := new(core.RecordRequestVerificationRequestEvent) |
| 49 | event.RequestEvent = e |
| 50 | event.Collection = collection |
| 51 | event.Record = record |
| 52 | |
| 53 | return e.App.OnRecordRequestVerificationRequest().Trigger(event, func(e *core.RecordRequestVerificationRequestEvent) error { |
| 54 | if e.Record.Verified() { |
| 55 | return e.NoContent(http.StatusNoContent) |
| 56 | } |
| 57 | |
| 58 | // run in background because we don't need to show the result to the client |
| 59 | app := e.App |
| 60 | routine.FireAndForget(func() { |
| 61 | if err := mails.SendRecordVerification(app, e.Record); err != nil { |
| 62 | app.Logger().Error("Failed to send verification email", "error", err) |
| 63 | } |
| 64 | |
| 65 | app.Store().Set(resendKey, struct{}{}) |
| 66 | time.AfterFunc(2*time.Minute, func() { |
| 67 | app.Store().Remove(resendKey) |
| 68 | }) |
| 69 | }) |
| 70 | |
| 71 | return execAfterSuccessTx(true, e.App, func() error { |
| 72 | return e.NoContent(http.StatusNoContent) |
| 73 | }) |
nothing calls this directly
no test coverage detected
searching dependent graphs…