From ec6afaaa3dd057682f47fe73259f5dc775e58d96 Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Tue, 20 Sep 2022 14:23:01 -0400 Subject: [PATCH] better, more resilient account request processing (#50) --- controller/account.go | 30 +++++++++++++++++++++++++---- controller/store/account_request.go | 20 +++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/controller/account.go b/controller/account.go index 9d0c03dc..e59da0e7 100644 --- a/controller/account.go +++ b/controller/account.go @@ -22,22 +22,38 @@ func (self *createAccountHandler) Handle(params identity.CreateAccountParams) mi logrus.Errorf("missing email") return identity.NewCreateAccountBadRequest().WithPayload("missing email") } + token := createToken() - if err := sendVerificationEmail(params.Body.Email, token, self.cfg); err != nil { - logrus.Error(err) - return identity.NewCreateAccountInternalServerError().WithPayload(rest_model_zrok.ErrorMessage(err.Error())) - } ar := &store.AccountRequest{ Token: token, Email: params.Body.Email, SourceAddress: params.HTTPRequest.RemoteAddr, } + tx, err := str.Begin() if err != nil { logrus.Error(err) return identity.NewCreateAccountInternalServerError().WithPayload(rest_model_zrok.ErrorMessage(err.Error())) } defer func() { _ = tx.Rollback() }() + + if _, err := str.FindAccountWithEmail(params.Body.Email, tx); err == nil { + logrus.Errorf("found account for '%v', cannot process account request", params.Body.Email) + return identity.NewCreateAccountBadRequest() + } else { + logrus.Infof("no account found for '%v': %v", params.Body.Email, err) + } + + if oldAr, err := str.FindAccountRequestWithEmail(params.Body.Email, tx); err == nil { + logrus.Warnf("found previous account request for '%v', removing", params.Body.Email) + if err := str.DeleteAccountRequest(oldAr.Id, tx); err != nil { + logrus.Errorf("error deleteing previous account request for '%v': %v", params.Body.Email, err) + return identity.NewCreateAccountInternalServerError().WithPayload(rest_model_zrok.ErrorMessage(err.Error())) + } + } else { + logrus.Warnf("error finding previous account request for '%v': %v", params.Body.Email, err) + } + if _, err := str.CreateAccountRequest(ar, tx); err != nil { logrus.Error(err) return identity.NewCreateAccountInternalServerError().WithPayload(rest_model_zrok.ErrorMessage(err.Error())) @@ -46,5 +62,11 @@ func (self *createAccountHandler) Handle(params identity.CreateAccountParams) mi logrus.Error(err) return identity.NewCreateAccountInternalServerError().WithPayload(rest_model_zrok.ErrorMessage(err.Error())) } + + if err := sendVerificationEmail(params.Body.Email, token, self.cfg); err != nil { + logrus.Error(err) + return identity.NewCreateAccountInternalServerError().WithPayload(rest_model_zrok.ErrorMessage(err.Error())) + } + return identity.NewCreateAccountCreated() } diff --git a/controller/store/account_request.go b/controller/store/account_request.go index 8644b6f5..45e8ce9b 100644 --- a/controller/store/account_request.go +++ b/controller/store/account_request.go @@ -43,3 +43,23 @@ func (self *Store) FindAccountRequestWithToken(token string, tx *sqlx.Tx) (*Acco } return ar, nil } + +func (self *Store) FindAccountRequestWithEmail(email string, tx *sqlx.Tx) (*AccountRequest, error) { + ar := &AccountRequest{} + if err := tx.QueryRowx("select * from account_requests where email = ?", email).StructScan(ar); err != nil { + return nil, errors.Wrap(err, "error selecting account_request by email") + } + return ar, nil +} + +func (self *Store) DeleteAccountRequest(id int, tx *sqlx.Tx) error { + stmt, err := tx.Prepare("delete from account_requests where id = ?") + if err != nil { + return errors.Wrap(err, "error preparing account_requests delete statement") + } + _, err = stmt.Exec(id) + if err != nil { + return errors.Wrap(err, "error executing account_requests delete statement") + } + return nil +}