diff --git a/CHANGELOG.md b/CHANGELOG.md index 4925cfe5..ebde04cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ FEATURE: New metrics infrastructure based on OpenZiti usage events (https://github.com/openziti/zrok/issues/128). See the [v0.4 Metrics Guide](docs/guides/v0.4_metrics.md) for more information. +CHANGE: The underlying database store now utilizes a `deleted` flag on all tables to implement "soft deletes". This was necessary for the new metrics infrastructure, where we need to account for metrics data that arrived after the lifetime of a share or environment; and also we're going to need this for limits, where we need to see historical information about activity in the past (https://github.com/openziti/zrok/issues/262) + # v0.3.4 CHANGE: `zrok test endpoint` incorporates `--ziti` mode (and related flags) to allow direct endpoint listening on a Ziti service diff --git a/controller/disable.go b/controller/disable.go index dbff3fa9..672c7f33 100644 --- a/controller/disable.go +++ b/controller/disable.go @@ -36,6 +36,10 @@ func (h *disableHandler) Handle(params environment.DisableParams, principal *res logrus.Errorf("error getting environment for user '%v': %v", principal.Email, err) return environment.NewDisableInternalServerError() } + if env.Deleted { + logrus.Errorf("environment '%v' for user '%v' deleted", env.ZId, principal.Email) + return environment.NewDisableUnauthorized() + } edge, err := zrokEdgeSdk.Client(cfg.Ziti) if err != nil { logrus.Errorf("error getting edge client for user '%v': %v", principal.Email, err) @@ -85,29 +89,31 @@ func (h *disableHandler) removeSharesForEnvironment(envId int, tx *sqlx.Tx, edge if err != nil { return err } - shrs, err := str.FindSharesForEnvironment(envId, tx) - if err != nil { - return err - } - for _, shr := range shrs { - shrToken := shr.Token - logrus.Infof("garbage collecting share '%v' for environment '%v'", shrToken, env.ZId) - if err := zrokEdgeSdk.DeleteServiceEdgeRouterPolicy(env.ZId, shrToken, edge); err != nil { - logrus.Error(err) + if !env.Deleted { + shrs, err := str.FindSharesForEnvironment(envId, tx) + if err != nil { + return err } - if err := zrokEdgeSdk.DeleteServicePolicyDial(env.ZId, shrToken, edge); err != nil { - logrus.Error(err) + for _, shr := range shrs { + shrToken := shr.Token + logrus.Infof("garbage collecting share '%v' for environment '%v'", shrToken, env.ZId) + if err := zrokEdgeSdk.DeleteServiceEdgeRouterPolicy(env.ZId, shrToken, edge); err != nil { + logrus.Error(err) + } + if err := zrokEdgeSdk.DeleteServicePolicyDial(env.ZId, shrToken, edge); err != nil { + logrus.Error(err) + } + if err := zrokEdgeSdk.DeleteServicePolicyBind(env.ZId, shrToken, edge); err != nil { + logrus.Error(err) + } + if err := zrokEdgeSdk.DeleteConfig(env.ZId, shrToken, edge); err != nil { + logrus.Error(err) + } + if err := zrokEdgeSdk.DeleteService(env.ZId, shr.ZId, edge); err != nil { + logrus.Error(err) + } + logrus.Infof("removed share '%v' for environment '%v'", shr.Token, env.ZId) } - if err := zrokEdgeSdk.DeleteServicePolicyBind(env.ZId, shrToken, edge); err != nil { - logrus.Error(err) - } - if err := zrokEdgeSdk.DeleteConfig(env.ZId, shrToken, edge); err != nil { - logrus.Error(err) - } - if err := zrokEdgeSdk.DeleteService(env.ZId, shr.ZId, edge); err != nil { - logrus.Error(err) - } - logrus.Infof("removed share '%v' for environment '%v'", shr.Token, env.ZId) } return nil } @@ -117,13 +123,15 @@ func (h *disableHandler) removeFrontendsForEnvironment(envId int, tx *sqlx.Tx, e if err != nil { return err } - fes, err := str.FindFrontendsForEnvironment(envId, tx) - if err != nil { - return err - } - for _, fe := range fes { - if err := zrokEdgeSdk.DeleteServicePolicy(env.ZId, fmt.Sprintf("tags.zrokFrontendToken=\"%v\" and type=1", fe.Token), edge); err != nil { - logrus.Errorf("error removing frontend access for '%v': %v", fe.Token, err) + if !env.Deleted { + fes, err := str.FindFrontendsForEnvironment(envId, tx) + if err != nil { + return err + } + for _, fe := range fes { + if err := zrokEdgeSdk.DeleteServicePolicy(env.ZId, fmt.Sprintf("tags.zrokFrontendToken=\"%v\" and type=1", fe.Token), edge); err != nil { + logrus.Errorf("error removing frontend access for '%v': %v", fe.Token, err) + } } } return nil diff --git a/controller/gc.go b/controller/gc.go index 30df247f..ad58d89c 100644 --- a/controller/gc.go +++ b/controller/gc.go @@ -37,7 +37,7 @@ func GC(inCfg *Config) error { return err } defer func() { _ = tx.Rollback() }() - sshrs, err := str.GetAllShares(tx) + sshrs, err := str.FindAllShares(tx) if err != nil { return err } diff --git a/controller/invite.go b/controller/invite.go index 1458418d..2bcc207c 100644 --- a/controller/invite.go +++ b/controller/invite.go @@ -3,7 +3,6 @@ package controller import ( "github.com/go-openapi/runtime/middleware" "github.com/openziti/zrok/controller/store" - "github.com/openziti/zrok/rest_model_zrok" "github.com/openziti/zrok/rest_server_zrok/operations/account" "github.com/openziti/zrok/util" "github.com/sirupsen/logrus" @@ -19,7 +18,7 @@ func newInviteHandler(cfg *Config) *inviteHandler { } } -func (self *inviteHandler) Handle(params account.InviteParams) middleware.Responder { +func (h *inviteHandler) Handle(params account.InviteParams) middleware.Responder { if params.Body == nil || params.Body.Email == "" { logrus.Errorf("missing email") return account.NewInviteBadRequest() @@ -38,11 +37,11 @@ func (self *inviteHandler) Handle(params account.InviteParams) middleware.Respon } defer func() { _ = tx.Rollback() }() - if self.cfg.Registration != nil && self.cfg.Registration.TokenStrategy == "store" { - inviteToken, err := str.GetInviteTokenByToken(params.Body.Token, tx) + if h.cfg.Registration != nil && h.cfg.Registration.TokenStrategy == "store" { + inviteToken, err := str.FindInviteTokenByToken(params.Body.Token, tx) if err != nil { logrus.Errorf("cannot get invite token '%v' for '%v': %v", params.Body.Token, params.Body.Email, err) - return account.NewInviteBadRequest().WithPayload(rest_model_zrok.ErrorMessage("Missing invite token")) + return account.NewInviteBadRequest().WithPayload("missing invite token") } if err := str.DeleteInviteToken(inviteToken.Id, tx); err != nil { logrus.Error(err) @@ -62,9 +61,10 @@ func (self *inviteHandler) Handle(params account.InviteParams) middleware.Respon SourceAddress: params.HTTPRequest.RemoteAddr, } - if _, err := str.FindAccountWithEmail(params.Body.Email, tx); err == nil { + // deleted accounts still exist as far as invites are concerned (ignore deleted flag) + if _, err := str.FindAccountWithEmailAndDeleted(params.Body.Email, tx); err == nil { logrus.Errorf("found account for '%v', cannot process account request", params.Body.Email) - return account.NewInviteBadRequest().WithPayload(rest_model_zrok.ErrorMessage("Duplicate email found")) + return account.NewInviteBadRequest().WithPayload("duplicate email found") } else { logrus.Infof("no account found for '%v': %v", params.Body.Email, err) } diff --git a/controller/metrics/shareCache.go b/controller/metrics/shareCache.go index 69ce4c88..2789953d 100644 --- a/controller/metrics/shareCache.go +++ b/controller/metrics/shareCache.go @@ -23,7 +23,7 @@ func (sc *shareCache) getToken(svcZId string) (string, error) { return "", err } defer func() { _ = tx.Rollback() }() - shr, err := sc.str.FindShareWithZId(svcZId, tx) + shr, err := sc.str.FindShareWithZIdAndDeleted(svcZId, tx) if err != nil { return "", err } diff --git a/controller/resetPassword.go b/controller/resetPassword.go index 4a5aa2ad..f34a942e 100644 --- a/controller/resetPassword.go +++ b/controller/resetPassword.go @@ -37,6 +37,10 @@ func (handler *resetPasswordHandler) Handle(params account.ResetPasswordParams) logrus.Errorf("error finding account for '%v': %v", params.Body.Token, err) return account.NewResetPasswordNotFound() } + if a.Deleted { + logrus.Errorf("account '%v' for '%v' deleted", a.Email, a.Token) + return account.NewResetPasswordNotFound() + } hpwd, err := hashPassword(params.Body.Password) if err != nil { logrus.Errorf("error hashing password for '%v' (%v): %v", params.Body.Token, a.Email, err) diff --git a/controller/resetPasswordRequest.go b/controller/resetPasswordRequest.go index b20356e2..7913d359 100644 --- a/controller/resetPasswordRequest.go +++ b/controller/resetPasswordRequest.go @@ -42,7 +42,7 @@ func (handler *resetPasswordRequestHandler) Handle(params account.ResetPasswordR a, err := str.FindAccountWithEmail(params.Body.EmailAddress, tx) if err != nil { - logrus.Infof("no account found for '%v': %v", params.Body.EmailAddress, err) + logrus.Errorf("no account found for '%v': %v", params.Body.EmailAddress, err) return account.NewResetPasswordRequestInternalServerError() } diff --git a/controller/store/account.go b/controller/store/account.go index cf33ce03..9872f943 100644 --- a/controller/store/account.go +++ b/controller/store/account.go @@ -37,15 +37,23 @@ func (self *Store) GetAccount(id int, tx *sqlx.Tx) (*Account, error) { func (self *Store) FindAccountWithEmail(email string, tx *sqlx.Tx) (*Account, error) { a := &Account{} - if err := tx.QueryRowx("select * from accounts where email = $1", email).StructScan(a); err != nil { + if err := tx.QueryRowx("select * from accounts where email = $1 and not deleted", email).StructScan(a); err != nil { return nil, errors.Wrap(err, "error selecting account by email") } return a, nil } +func (self *Store) FindAccountWithEmailAndDeleted(email string, tx *sqlx.Tx) (*Account, error) { + a := &Account{} + if err := tx.QueryRowx("select * from accounts where email = $1", email).StructScan(a); err != nil { + return nil, errors.Wrap(err, "error selecting acount by email") + } + return a, nil +} + func (self *Store) FindAccountWithToken(token string, tx *sqlx.Tx) (*Account, error) { a := &Account{} - if err := tx.QueryRowx("select * from accounts where token = $1", token).StructScan(a); err != nil { + if err := tx.QueryRowx("select * from accounts where token = $1 and not deleted", token).StructScan(a); err != nil { return nil, errors.Wrap(err, "error selecting account by token") } return a, nil diff --git a/controller/store/account_request.go b/controller/store/account_request.go index 23b0690e..9b3f1961 100644 --- a/controller/store/account_request.go +++ b/controller/store/account_request.go @@ -39,7 +39,7 @@ func (self *Store) GetAccountRequest(id int, tx *sqlx.Tx) (*AccountRequest, erro func (self *Store) FindAccountRequestWithToken(token string, tx *sqlx.Tx) (*AccountRequest, error) { ar := &AccountRequest{} - if err := tx.QueryRowx("select * from account_requests where token = $1", token).StructScan(ar); err != nil { + if err := tx.QueryRowx("select * from account_requests where token = $1 and not deleted", token).StructScan(ar); err != nil { return nil, errors.Wrap(err, "error selecting account_request by token") } return ar, nil @@ -49,10 +49,10 @@ func (self *Store) FindExpiredAccountRequests(before time.Time, limit int, tx *s var sql string switch self.cfg.Type { case "postgres": - sql = "select * from account_requests where created_at < $1 limit %d for update" + sql = "select * from account_requests where created_at < $1 and not deleted limit %d for update" case "sqlite3": - sql = "select * from account_requests where created_at < $1 limit %d" + sql = "select * from account_requests where created_at < $1 and not deleted limit %d" default: return nil, errors.Errorf("unknown database type '%v'", self.cfg.Type) @@ -75,14 +75,14 @@ func (self *Store) FindExpiredAccountRequests(before time.Time, limit int, tx *s func (self *Store) FindAccountRequestWithEmail(email string, tx *sqlx.Tx) (*AccountRequest, error) { ar := &AccountRequest{} - if err := tx.QueryRowx("select * from account_requests where email = $1", email).StructScan(ar); err != nil { + if err := tx.QueryRowx("select * from account_requests where email = $1 and not deleted", 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 = $1") + stmt, err := tx.Prepare("update account_requests set deleted = true, updated_at = current_timestamp where id = $1") if err != nil { return errors.Wrap(err, "error preparing account_requests delete statement") } @@ -106,7 +106,7 @@ func (self *Store) DeleteMultipleAccountRequests(ids []int, tx *sqlx.Tx) error { indexes[i] = fmt.Sprintf("$%d", i+1) } - stmt, err := tx.Prepare(fmt.Sprintf("delete from account_requests where id in (%s)", strings.Join(indexes, ","))) + stmt, err := tx.Prepare(fmt.Sprintf("update account_requests set deleted = true, updated_at = current_timestamp where id in (%s)", strings.Join(indexes, ","))) if err != nil { return errors.Wrap(err, "error preparing account_requests delete multiple statement") } diff --git a/controller/store/environment.go b/controller/store/environment.go index 834a2292..4c3e47c0 100644 --- a/controller/store/environment.go +++ b/controller/store/environment.go @@ -48,7 +48,7 @@ func (self *Store) GetEnvironment(id int, tx *sqlx.Tx) (*Environment, error) { } func (self *Store) FindEnvironmentsForAccount(accountId int, tx *sqlx.Tx) ([]*Environment, error) { - rows, err := tx.Queryx("select environments.* from environments where account_id = $1", accountId) + rows, err := tx.Queryx("select environments.* from environments where account_id = $1 and not deleted", accountId) if err != nil { return nil, errors.Wrap(err, "error selecting environments by account id") } @@ -65,14 +65,14 @@ func (self *Store) FindEnvironmentsForAccount(accountId int, tx *sqlx.Tx) ([]*En func (self *Store) FindEnvironmentForAccount(envZId string, accountId int, tx *sqlx.Tx) (*Environment, error) { env := &Environment{} - if err := tx.QueryRowx("select environments.* from environments where z_id = $1 and account_id = $2", envZId, accountId).StructScan(env); err != nil { + if err := tx.QueryRowx("select environments.* from environments where z_id = $1 and account_id = $2 and not deleted", envZId, accountId).StructScan(env); err != nil { return nil, errors.Wrap(err, "error finding environment by z_id and account_id") } return env, nil } func (self *Store) DeleteEnvironment(id int, tx *sqlx.Tx) error { - stmt, err := tx.Prepare("delete from environments where id = $1") + stmt, err := tx.Prepare("update environments set updated_at = current_timestamp, deleted = true where id = $1") if err != nil { return errors.Wrap(err, "error preparing environments delete statement") } diff --git a/controller/store/environment_test.go b/controller/store/environment_test.go index 66400806..d5142022 100644 --- a/controller/store/environment_test.go +++ b/controller/store/environment_test.go @@ -26,6 +26,7 @@ func TestEphemeralEnvironment(t *testing.T) { assert.Nil(t, err) assert.NotNil(t, env) assert.Nil(t, env.AccountId) + assert.False(t, env.Deleted) } func TestEnvironment(t *testing.T) { @@ -57,4 +58,5 @@ func TestEnvironment(t *testing.T) { assert.NotNil(t, env) assert.NotNil(t, env.AccountId) assert.Equal(t, acctId, *env.AccountId) + assert.False(t, env.Deleted) } diff --git a/controller/store/frontend.go b/controller/store/frontend.go index d53f8e8b..8ffea5e6 100644 --- a/controller/store/frontend.go +++ b/controller/store/frontend.go @@ -50,7 +50,7 @@ func (str *Store) GetFrontend(id int, tx *sqlx.Tx) (*Frontend, error) { func (str *Store) FindFrontendWithToken(token string, tx *sqlx.Tx) (*Frontend, error) { i := &Frontend{} - if err := tx.QueryRowx("select frontends.* from frontends where token = $1", token).StructScan(i); err != nil { + if err := tx.QueryRowx("select frontends.* from frontends where token = $1 and not deleted", token).StructScan(i); err != nil { return nil, errors.Wrap(err, "error selecting frontend by name") } return i, nil @@ -58,7 +58,7 @@ func (str *Store) FindFrontendWithToken(token string, tx *sqlx.Tx) (*Frontend, e func (str *Store) FindFrontendWithZId(zId string, tx *sqlx.Tx) (*Frontend, error) { i := &Frontend{} - if err := tx.QueryRowx("select frontends.* from frontends where z_id = $1", zId).StructScan(i); err != nil { + if err := tx.QueryRowx("select frontends.* from frontends where z_id = $1 and not deleted", zId).StructScan(i); err != nil { return nil, errors.Wrap(err, "error selecting frontend by ziti id") } return i, nil @@ -66,14 +66,14 @@ func (str *Store) FindFrontendWithZId(zId string, tx *sqlx.Tx) (*Frontend, error func (str *Store) FindFrontendPubliclyNamed(publicName string, tx *sqlx.Tx) (*Frontend, error) { i := &Frontend{} - if err := tx.QueryRowx("select frontends.* from frontends where public_name = $1", publicName).StructScan(i); err != nil { + if err := tx.QueryRowx("select frontends.* from frontends where public_name = $1 and not deleted", publicName).StructScan(i); err != nil { return nil, errors.Wrap(err, "error selecting frontend by public_name") } return i, nil } func (str *Store) FindFrontendsForEnvironment(envId int, tx *sqlx.Tx) ([]*Frontend, error) { - rows, err := tx.Queryx("select frontends.* from frontends where environment_id = $1", envId) + rows, err := tx.Queryx("select frontends.* from frontends where environment_id = $1 and not deleted", envId) if err != nil { return nil, errors.Wrap(err, "error selecting frontends by environment_id") } @@ -89,7 +89,7 @@ func (str *Store) FindFrontendsForEnvironment(envId int, tx *sqlx.Tx) ([]*Fronte } func (str *Store) FindPublicFrontends(tx *sqlx.Tx) ([]*Frontend, error) { - rows, err := tx.Queryx("select frontends.* from frontends where environment_id is null and reserved = true") + rows, err := tx.Queryx("select frontends.* from frontends where environment_id is null and reserved = true and not deleted") if err != nil { return nil, errors.Wrap(err, "error selecting public frontends") } @@ -119,7 +119,7 @@ func (str *Store) UpdateFrontend(fe *Frontend, tx *sqlx.Tx) error { func (str *Store) DeleteFrontend(id int, tx *sqlx.Tx) error { - stmt, err := tx.Prepare("delete from frontends where id = $1") + stmt, err := tx.Prepare("update frontends set updated_at = current_timestamp, deleted = true where id = $1") if err != nil { return errors.Wrap(err, "error preparing frontends delete statement") } diff --git a/controller/store/frontend_test.go b/controller/store/frontend_test.go index 24b6cd4c..88f8969c 100644 --- a/controller/store/frontend_test.go +++ b/controller/store/frontend_test.go @@ -42,6 +42,7 @@ func TestPublicFrontend(t *testing.T) { assert.NotNil(t, fe) assert.Equal(t, envId, *fe.EnvironmentId) assert.Equal(t, feName, *fe.PublicName) + assert.False(t, fe.Deleted) fe0, err := str.FindFrontendPubliclyNamed(feName, tx) assert.Nil(t, err) @@ -56,6 +57,7 @@ func TestPublicFrontend(t *testing.T) { assert.Nil(t, fe0) fe0, err = str.GetFrontend(fe.Id, tx) - assert.NotNil(t, err) - assert.Nil(t, fe0) + assert.Nil(t, err) + assert.NotNil(t, fe0) + assert.True(t, fe0.Deleted) } diff --git a/controller/store/invite_tokens.go b/controller/store/invite_tokens.go index 71d3d757..83a5db33 100644 --- a/controller/store/invite_tokens.go +++ b/controller/store/invite_tokens.go @@ -32,16 +32,16 @@ func (str *Store) CreateInviteTokens(inviteTokens []*InviteToken, tx *sqlx.Tx) e return nil } -func (str *Store) GetInviteTokenByToken(token string, tx *sqlx.Tx) (*InviteToken, error) { +func (str *Store) FindInviteTokenByToken(token string, tx *sqlx.Tx) (*InviteToken, error) { inviteToken := &InviteToken{} - if err := tx.QueryRowx("select * from invite_tokens where token = $1", token).StructScan(inviteToken); err != nil { + if err := tx.QueryRowx("select * from invite_tokens where token = $1 and not deleted", token).StructScan(inviteToken); err != nil { return nil, errors.Wrap(err, "error getting unused invite_token") } return inviteToken, nil } func (str *Store) DeleteInviteToken(id int, tx *sqlx.Tx) error { - stmt, err := tx.Prepare("delete from invite_tokens where id = $1") + stmt, err := tx.Prepare("update invite_tokens set updated_at = current_timestamp, deleted = true where id = $1") if err != nil { return errors.Wrap(err, "error preparing invite_tokens delete statement") } diff --git a/controller/store/password_reset_request.go b/controller/store/password_reset_request.go index 9e2ed4ee..a5c617c5 100644 --- a/controller/store/password_reset_request.go +++ b/controller/store/password_reset_request.go @@ -30,7 +30,7 @@ func (self *Store) CreatePasswordResetRequest(prr *PasswordResetRequest, tx *sql func (self *Store) FindPasswordResetRequestWithToken(token string, tx *sqlx.Tx) (*PasswordResetRequest, error) { prr := &PasswordResetRequest{} - if err := tx.QueryRowx("select * from password_reset_requests where token = $1", token).StructScan(prr); err != nil { + if err := tx.QueryRowx("select * from password_reset_requests where token = $1 and not deleted", token).StructScan(prr); err != nil { return nil, errors.Wrap(err, "error selecting password_reset_requests by token") } return prr, nil @@ -40,10 +40,10 @@ func (self *Store) FindExpiredPasswordResetRequests(before time.Time, limit int, var sql string switch self.cfg.Type { case "postgres": - sql = "select * from password_reset_requests where created_at < $1 limit %d for update" + sql = "select * from password_reset_requests where created_at < $1 and not deleted limit %d for update" case "sqlite3": - sql = "select * from password_reset_requests where created_at < $1 limit %d" + sql = "select * from password_reset_requests where created_at < $1 and not deleted limit %d" default: return nil, errors.Errorf("unknown database type '%v'", self.cfg.Type) } @@ -64,7 +64,7 @@ func (self *Store) FindExpiredPasswordResetRequests(before time.Time, limit int, } func (self *Store) DeletePasswordResetRequest(id int, tx *sqlx.Tx) error { - stmt, err := tx.Prepare("delete from password_reset_requests where id = $1") + stmt, err := tx.Prepare("update password_reset_requests set updated_at = current_timestamp, deleted = true where id = $1") if err != nil { return errors.Wrap(err, "error preparing password_reset_requests delete statement") } @@ -88,7 +88,7 @@ func (self *Store) DeleteMultiplePasswordResetRequests(ids []int, tx *sqlx.Tx) e indexes[i] = fmt.Sprintf("$%d", i+1) } - stmt, err := tx.Prepare(fmt.Sprintf("delete from password_reset_requests where id in (%s)", strings.Join(indexes, ","))) + stmt, err := tx.Prepare(fmt.Sprintf("update password_reset_requests set updated_at = current_timestamp, deleted = true where id in (%s)", strings.Join(indexes, ","))) if err != nil { return errors.Wrap(err, "error preparing password_reset_requests delete multiple statement") } diff --git a/controller/store/share.go b/controller/store/share.go index b0b68517..86e55c61 100644 --- a/controller/store/share.go +++ b/controller/store/share.go @@ -39,8 +39,8 @@ func (self *Store) GetShare(id int, tx *sqlx.Tx) (*Share, error) { return shr, nil } -func (self *Store) GetAllShares(tx *sqlx.Tx) ([]*Share, error) { - rows, err := tx.Queryx("select * from shares order by id") +func (self *Store) FindAllShares(tx *sqlx.Tx) ([]*Share, error) { + rows, err := tx.Queryx("select * from shares where not deleted order by id") if err != nil { return nil, errors.Wrap(err, "error selecting all shares") } @@ -57,13 +57,13 @@ func (self *Store) GetAllShares(tx *sqlx.Tx) ([]*Share, error) { func (self *Store) FindShareWithToken(shrToken string, tx *sqlx.Tx) (*Share, error) { shr := &Share{} - if err := tx.QueryRowx("select * from shares where token = $1", shrToken).StructScan(shr); err != nil { + if err := tx.QueryRowx("select * from shares where token = $1 and not deleted", shrToken).StructScan(shr); err != nil { return nil, errors.Wrap(err, "error selecting share by token") } return shr, nil } -func (self *Store) FindShareWithZId(zId string, tx *sqlx.Tx) (*Share, error) { +func (self *Store) FindShareWithZIdAndDeleted(zId string, tx *sqlx.Tx) (*Share, error) { shr := &Share{} if err := tx.QueryRowx("select * from shares where z_id = $1", zId).StructScan(shr); err != nil { return nil, errors.Wrap(err, "error selecting share by z_id") @@ -72,7 +72,7 @@ func (self *Store) FindShareWithZId(zId string, tx *sqlx.Tx) (*Share, error) { } func (self *Store) FindSharesForEnvironment(envId int, tx *sqlx.Tx) ([]*Share, error) { - rows, err := tx.Queryx("select shares.* from shares where environment_id = $1", envId) + rows, err := tx.Queryx("select shares.* from shares where environment_id = $1 and not deleted", envId) if err != nil { return nil, errors.Wrap(err, "error selecting shares by environment id") } @@ -101,7 +101,7 @@ func (self *Store) UpdateShare(shr *Share, tx *sqlx.Tx) error { } func (self *Store) DeleteShare(id int, tx *sqlx.Tx) error { - stmt, err := tx.Prepare("delete from shares where id = $1") + stmt, err := tx.Prepare("update shares set updated_at = current_timestamp, deleted = true where id = $1") if err != nil { return errors.Wrap(err, "error preparing shares delete statement") } diff --git a/controller/verify.go b/controller/verify.go index ae194fc5..a7c1e6af 100644 --- a/controller/verify.go +++ b/controller/verify.go @@ -26,7 +26,7 @@ func (self *verifyHandler) Handle(params account.VerifyParams) middleware.Respon ar, err := str.FindAccountRequestWithToken(params.Body.Token, tx) if err != nil { - logrus.Errorf("error finding account with token '%v': %v", params.Body.Token, err) + logrus.Errorf("error finding account request with token '%v': %v", params.Body.Token, err) return account.NewVerifyNotFound() }