From 1897f174b015abd9410c39e823fa4aa0f037f6b9 Mon Sep 17 00:00:00 2001 From: George MacRorie Date: Thu, 3 Nov 2022 09:53:34 +0000 Subject: [PATCH] feat(server/auth): define unary server interceptor (#1110) chore: empty commit to kick ci fix(auth/sql): add auth package qualifier when calling ListWithMethod chore(auth/sql): remove duplicate imports chore(auth/sql): adjust import naming to be consistent fix(sq/auth): ensure order defaults to ascending fix(sql): truncate timestamps to microseconds when inserting into database fix(sql): use precision 6 for mysql timestamp columns --- .../2_create_table_authentications.up.sql | 6 +- internal/server/auth/middleware.go | 4 +- internal/storage/auth/sql/store.go | 48 ++-- internal/storage/auth/sql/store_test.go | 246 ++++++++++-------- internal/storage/testing/testing.go | 4 - 5 files changed, 170 insertions(+), 138 deletions(-) diff --git a/config/migrations/mysql/2_create_table_authentications.up.sql b/config/migrations/mysql/2_create_table_authentications.up.sql index 0226fae54d..a1b3d50b34 100644 --- a/config/migrations/mysql/2_create_table_authentications.up.sql +++ b/config/migrations/mysql/2_create_table_authentications.up.sql @@ -3,9 +3,9 @@ CREATE TABLE IF NOT EXISTS authentications ( hashed_client_token VARCHAR(255) UNIQUE NOT NULL, method INTEGER DEFAULT 0 NOT NULL, metadata TEXT, - expires_at TIMESTAMP, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, + expires_at TIMESTAMP(6), + created_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL, + updated_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL, PRIMARY KEY (`id`) ); diff --git a/internal/server/auth/middleware.go b/internal/server/auth/middleware.go index fc62912136..eadbee6c6d 100644 --- a/internal/server/auth/middleware.go +++ b/internal/server/auth/middleware.go @@ -36,8 +36,8 @@ func GetAuthenticationFrom(ctx context.Context) *authrpc.Authentication { return auth.(*authrpc.Authentication) } -// UnaryInterceptor is a grpc.UnaryServerInterceptor, which extracts a clientToken found -// strored within the authorization field on the incoming request metadata. +// UnaryInterceptor is a grpc.UnaryServerInterceptor which extracts a clientToken found +// within the authorization field on the incoming requests metadata. // The fields value is expected to be in the form "Bearer ". func UnaryInterceptor(logger *zap.Logger, authenticator Authenticator) grpc.UnaryServerInterceptor { return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { diff --git a/internal/storage/auth/sql/store.go b/internal/storage/auth/sql/store.go index 5221d4a9b1..9ae6482471 100644 --- a/internal/storage/auth/sql/store.go +++ b/internal/storage/auth/sql/store.go @@ -4,14 +4,14 @@ import ( "context" "fmt" "strconv" + "time" - "github.com/Masterminds/squirrel" sq "github.com/Masterminds/squirrel" "github.com/gofrs/uuid" "go.flipt.io/flipt/internal/storage" - "go.flipt.io/flipt/internal/storage/auth" - fliptsql "go.flipt.io/flipt/internal/storage/sql" + storageauth "go.flipt.io/flipt/internal/storage/auth" + storagesql "go.flipt.io/flipt/internal/storage/sql" rpcauth "go.flipt.io/flipt/rpc/flipt/auth" "go.uber.org/zap" "google.golang.org/protobuf/types/known/timestamppb" @@ -21,7 +21,7 @@ import ( // based relational database systems. type Store struct { logger *zap.Logger - driver fliptsql.Driver + driver storagesql.Driver builder sq.StatementBuilderType now func() *timestamppb.Timestamp @@ -35,16 +35,21 @@ type Option func(*Store) // NewStore constructs and configures a new instance of *Store. // Queries are issued to the database via the provided statement builder. -func NewStore(driver fliptsql.Driver, builder sq.StatementBuilderType, logger *zap.Logger, opts ...Option) *Store { +func NewStore(driver storagesql.Driver, builder sq.StatementBuilderType, logger *zap.Logger, opts ...Option) *Store { store := &Store{ logger: logger, driver: driver, builder: builder, - now: timestamppb.Now, + now: func() *timestamppb.Timestamp { + // we truncate timestampts to the microsecond to support Postgres/MySQL + // the lowest common denominators in terms of timestamp precision + now := time.Now().UTC().Truncate(time.Microsecond) + return timestamppb.New(now) + }, generateID: func() string { return uuid.Must(uuid.NewV4()).String() }, - generateToken: auth.GenerateRandomToken, + generateToken: storageauth.GenerateRandomToken, } for _, opt := range opts { @@ -97,7 +102,7 @@ func (s *Store) CreateAuthentication(ctx context.Context, r *storage.CreateAuthe } ) - hashedToken, err := auth.HashClientToken(clientToken) + hashedToken, err := storageauth.HashClientToken(clientToken) if err != nil { return "", nil, fmt.Errorf("creating authentication: %w", err) } @@ -116,10 +121,10 @@ func (s *Store) CreateAuthentication(ctx context.Context, r *storage.CreateAuthe &authentication.Id, &hashedToken, &authentication.Method, - &fliptsql.JSONField[map[string]string]{T: authentication.Metadata}, - &fliptsql.NullableTimestamp{Timestamp: authentication.ExpiresAt}, - &fliptsql.Timestamp{Timestamp: authentication.CreatedAt}, - &fliptsql.Timestamp{Timestamp: authentication.UpdatedAt}, + &storagesql.JSONField[map[string]string]{T: authentication.Metadata}, + &storagesql.NullableTimestamp{Timestamp: authentication.ExpiresAt}, + &storagesql.Timestamp{Timestamp: authentication.CreatedAt}, + &storagesql.Timestamp{Timestamp: authentication.UpdatedAt}, ). ExecContext(ctx); err != nil { return "", nil, fmt.Errorf( @@ -137,7 +142,7 @@ func (s *Store) CreateAuthentication(ctx context.Context, r *storage.CreateAuthe // Given a row is present for the hash of the clientToken then materialize into an Authentication. // Else, given it cannot be located, a storage.ErrNotFound error is wrapped and returned instead. func (s *Store) GetAuthenticationByClientToken(ctx context.Context, clientToken string) (*rpcauth.Authentication, error) { - hashedToken, err := auth.HashClientToken(clientToken) + hashedToken, err := storageauth.HashClientToken(clientToken) if err != nil { return nil, fmt.Errorf("getting authentication by token: %w", err) } @@ -191,16 +196,13 @@ func (s *Store) ListAuthentications(ctx context.Context, req *storage.ListReques "updated_at", ). From("authentications"). - Limit(req.QueryParams.Limit + 1) + Limit(req.QueryParams.Limit + 1). + OrderBy(fmt.Sprintf("created_at %s", req.QueryParams.Order)) if req.Predicate.Method != nil { query = query.Where(sq.Eq{"method": *req.Predicate.Method}) } - if req.QueryParams.Order != storage.OrderAsc { - query = query.OrderBy(fmt.Sprintf("created_at %s", req.QueryParams.Order)) - } - var offset int if v, err := strconv.ParseInt(req.QueryParams.PageToken, 10, 64); err == nil { offset = int(v) @@ -237,18 +239,18 @@ func (s *Store) ListAuthentications(ctx context.Context, req *storage.ListReques return } -func (s *Store) scanAuthentication(scanner squirrel.RowScanner, authentication *rpcauth.Authentication) error { +func (s *Store) scanAuthentication(scanner sq.RowScanner, authentication *rpcauth.Authentication) error { var ( - expiresAt fliptsql.NullableTimestamp - createdAt fliptsql.Timestamp - updatedAt fliptsql.Timestamp + expiresAt storagesql.NullableTimestamp + createdAt storagesql.Timestamp + updatedAt storagesql.Timestamp ) if err := scanner. Scan( &authentication.Id, &authentication.Method, - &fliptsql.JSONField[*map[string]string]{T: &authentication.Metadata}, + &storagesql.JSONField[*map[string]string]{T: &authentication.Metadata}, &expiresAt, &createdAt, &updatedAt, diff --git a/internal/storage/auth/sql/store_test.go b/internal/storage/auth/sql/store_test.go index 163e61c966..8775a89868 100644 --- a/internal/storage/auth/sql/store_test.go +++ b/internal/storage/auth/sql/store_test.go @@ -10,10 +10,10 @@ import ( "github.com/stretchr/testify/require" "go.flipt.io/flipt/errors" "go.flipt.io/flipt/internal/storage" - fliptsql "go.flipt.io/flipt/internal/storage/sql" - fliptsqltesting "go.flipt.io/flipt/internal/storage/sql/testing" + storageauth "go.flipt.io/flipt/internal/storage/auth" + storagesql "go.flipt.io/flipt/internal/storage/sql" + sqltesting "go.flipt.io/flipt/internal/storage/sql/testing" storagetesting "go.flipt.io/flipt/internal/storage/testing" - "go.flipt.io/flipt/rpc/flipt/auth" rpcauth "go.flipt.io/flipt/rpc/flipt/auth" "go.uber.org/zap" "go.uber.org/zap/zaptest" @@ -43,7 +43,7 @@ func TestAuthenticationStoreHarness(t *testing.T) { func TestAuthentication_CreateAuthentication(t *testing.T) { // established a store factory with a single seeded auth entry - storeFn := newTestStore(t, createAuth("create_auth_id", "create_auth_token", auth.Method_TOKEN)) + storeFn := newTestStore(t, createAuth("create_auth_id", "create_auth_token", rpcauth.Method_TOKEN)) ctx := context.TODO() for _, test := range []struct { @@ -52,13 +52,13 @@ func TestAuthentication_CreateAuthentication(t *testing.T) { req *storage.CreateAuthenticationRequest expectedErrAs error expectedToken string - expectedAuthentication *auth.Authentication + expectedAuthentication *rpcauth.Authentication }{ { name: "successfully creates authentication", opts: commonOpts, req: &storage.CreateAuthenticationRequest{ - Method: auth.Method_TOKEN, + Method: rpcauth.Method_TOKEN, ExpiresAt: timestamppb.New(time.Unix(2, 0)), Metadata: map[string]string{ "io.flipt.auth.token.name": "access_all_areas", @@ -66,9 +66,9 @@ func TestAuthentication_CreateAuthentication(t *testing.T) { }, }, expectedToken: "token:TestAuthentication_CreateAuthentication/successfully_creates_authentication", - expectedAuthentication: &auth.Authentication{ + expectedAuthentication: &rpcauth.Authentication{ Id: "id:TestAuthentication_CreateAuthentication/successfully_creates_authentication", - Method: auth.Method_TOKEN, + Method: rpcauth.Method_TOKEN, Metadata: map[string]string{ "io.flipt.auth.token.name": "access_all_areas", "io.flipt.auth.token.description": "The keys to the castle", @@ -82,16 +82,16 @@ func TestAuthentication_CreateAuthentication(t *testing.T) { name: "successfully creates authentication (no expiration)", opts: commonOpts, req: &storage.CreateAuthenticationRequest{ - Method: auth.Method_TOKEN, + Method: rpcauth.Method_TOKEN, Metadata: map[string]string{ "io.flipt.auth.token.name": "access_all_areas", "io.flipt.auth.token.description": "The keys to the castle", }, }, expectedToken: "token:TestAuthentication_CreateAuthentication/successfully_creates_authentication_(no_expiration)", - expectedAuthentication: &auth.Authentication{ + expectedAuthentication: &rpcauth.Authentication{ Id: "id:TestAuthentication_CreateAuthentication/successfully_creates_authentication_(no_expiration)", - Method: auth.Method_TOKEN, + Method: rpcauth.Method_TOKEN, Metadata: map[string]string{ "io.flipt.auth.token.name": "access_all_areas", "io.flipt.auth.token.description": "The keys to the castle", @@ -111,7 +111,7 @@ func TestAuthentication_CreateAuthentication(t *testing.T) { } }, req: &storage.CreateAuthenticationRequest{ - Method: auth.Method_TOKEN, + Method: rpcauth.Method_TOKEN, ExpiresAt: timestamppb.New(time.Unix(2, 0)), Metadata: map[string]string{ "io.flipt.auth.token.name": "access_all_areas", @@ -131,7 +131,7 @@ func TestAuthentication_CreateAuthentication(t *testing.T) { } }, req: &storage.CreateAuthenticationRequest{ - Method: auth.Method_TOKEN, + Method: rpcauth.Method_TOKEN, ExpiresAt: timestamppb.New(time.Unix(2, 0)), Metadata: map[string]string{ "io.flipt.auth.token.name": "access_all_areas", @@ -163,14 +163,14 @@ func TestAuthentication_GetAuthenticationByClientToken(t *testing.T) { ctx := context.TODO() // established a store factory with a single seeded auth entry - storeFn := newTestStore(t, createAuth("get_auth_id", "get_auth_token", auth.Method_TOKEN)) + storeFn := newTestStore(t, createAuth("get_auth_id", "get_auth_token", rpcauth.Method_TOKEN)) // run table tests for _, test := range []struct { name string clientToken string expectedErrAs error - expectedAuthentication *auth.Authentication + expectedAuthentication *rpcauth.Authentication }{ { name: "error not found for unexpected clientToken", @@ -180,9 +180,9 @@ func TestAuthentication_GetAuthenticationByClientToken(t *testing.T) { { name: "successfully retrieves authentication by clientToken", clientToken: "get_auth_token", - expectedAuthentication: &auth.Authentication{ + expectedAuthentication: &rpcauth.Authentication{ Id: "get_auth_id", - Method: auth.Method_TOKEN, + Method: rpcauth.Method_TOKEN, Metadata: map[string]string{ "io.flipt.auth.token.name": "access_some_areas", "io.flipt.auth.token.description": "The keys to some of the castle", @@ -214,114 +214,141 @@ func TestAuthentication_GetAuthenticationByClientToken(t *testing.T) { func TestAuthentication_ListAuthentications_ByMethod(t *testing.T) { ctx := context.TODO() + + // increment each timestamp by 1 when seeding auths + var i int64 + seedOpts := func(t *testing.T) []Option { + return []Option{WithNowFunc(func() *timestamppb.Timestamp { + i++ + return timestamppb.New(time.Unix(i, 0)) + })} + } + storeFn := newTestStore(t, - createAuth("token_id_one", "token_client_token_one", auth.Method_TOKEN), - createAuth("token_id_two", "token_client_token_two", auth.Method_TOKEN), - createAuth("token_id_three", "token_client_token_three", auth.Method_TOKEN), - createAuth("none_id_one", "none_client_token_one", auth.Method_NONE), - createAuth("none_id_two", "none_client_token_two", auth.Method_NONE), - createAuth("none_id_three", "none_client_token_three", auth.Method_NONE), + createAuth("none_id_one", "none_client_token_one", rpcauth.Method_NONE, withOpts(seedOpts)), + createAuth("none_id_two", "none_client_token_two", rpcauth.Method_NONE, withOpts(seedOpts)), + createAuth("none_id_three", "none_client_token_three", rpcauth.Method_NONE, withOpts(seedOpts)), + createAuth("token_id_one", "token_client_token_one", rpcauth.Method_TOKEN, withOpts(seedOpts)), + createAuth("token_id_two", "token_client_token_two", rpcauth.Method_TOKEN, withOpts(seedOpts)), + createAuth("token_id_three", "token_client_token_three", rpcauth.Method_TOKEN, withOpts(seedOpts)), ) - // list predicated with none auth method - req := storage.NewListRequest(ListWithMethod(auth.Method_NONE)) - noneMethod, err := storeFn().ListAuthentications(ctx, req) - require.NoError(t, err) - assert.Equal(t, storage.ResultSet[*rpcauth.Authentication]{ - Results: []*rpcauth.Authentication{ - { - Id: "none_id_one", - Method: auth.Method_NONE, - Metadata: map[string]string{ - "io.flipt.auth.token.name": "access_some_areas", - "io.flipt.auth.token.description": "The keys to some of the castle", + t.Run("method == none", func(t *testing.T) { + // list predicated with none auth method + req := storage.NewListRequest(storageauth.ListWithMethod(rpcauth.Method_NONE)) + noneMethod, err := storeFn().ListAuthentications(ctx, req) + + require.NoError(t, err) + assert.Equal(t, storage.ResultSet[*rpcauth.Authentication]{ + Results: []*rpcauth.Authentication{ + { + Id: "none_id_one", + Method: rpcauth.Method_NONE, + Metadata: map[string]string{ + "io.flipt.auth.token.name": "access_some_areas", + "io.flipt.auth.token.description": "The keys to some of the castle", + }, + ExpiresAt: timestamppb.New(time.Unix(2, 0)), + CreatedAt: timestamppb.New(time.Unix(1, 0)), + UpdatedAt: timestamppb.New(time.Unix(1, 0)), }, - ExpiresAt: timestamppb.New(time.Unix(2, 0)), - CreatedAt: someTimestamp, - UpdatedAt: someTimestamp, - }, - { - Id: "none_id_two", - Method: auth.Method_NONE, - Metadata: map[string]string{ - "io.flipt.auth.token.name": "access_some_areas", - "io.flipt.auth.token.description": "The keys to some of the castle", + { + Id: "none_id_two", + Method: rpcauth.Method_NONE, + Metadata: map[string]string{ + "io.flipt.auth.token.name": "access_some_areas", + "io.flipt.auth.token.description": "The keys to some of the castle", + }, + ExpiresAt: timestamppb.New(time.Unix(2, 0)), + CreatedAt: timestamppb.New(time.Unix(2, 0)), + UpdatedAt: timestamppb.New(time.Unix(2, 0)), }, - ExpiresAt: timestamppb.New(time.Unix(2, 0)), - CreatedAt: someTimestamp, - UpdatedAt: someTimestamp, - }, - { - Id: "none_id_three", - Method: auth.Method_NONE, - Metadata: map[string]string{ - "io.flipt.auth.token.name": "access_some_areas", - "io.flipt.auth.token.description": "The keys to some of the castle", + { + Id: "none_id_three", + Method: rpcauth.Method_NONE, + Metadata: map[string]string{ + "io.flipt.auth.token.name": "access_some_areas", + "io.flipt.auth.token.description": "The keys to some of the castle", + }, + ExpiresAt: timestamppb.New(time.Unix(2, 0)), + CreatedAt: timestamppb.New(time.Unix(3, 0)), + UpdatedAt: timestamppb.New(time.Unix(3, 0)), }, - ExpiresAt: timestamppb.New(time.Unix(2, 0)), - CreatedAt: someTimestamp, - UpdatedAt: someTimestamp, }, - }, - }, noneMethod) - - // list predicated with token auth method - req = storage.NewListRequest(ListWithMethod(auth.Method_TOKEN)) - tokenMethod, err := storeFn().ListAuthentications(ctx, req) - require.NoError(t, err) - assert.Equal(t, storage.ResultSet[*rpcauth.Authentication]{ - Results: []*rpcauth.Authentication{ - { - Id: "token_id_one", - Method: auth.Method_TOKEN, - Metadata: map[string]string{ - "io.flipt.auth.token.name": "access_some_areas", - "io.flipt.auth.token.description": "The keys to some of the castle", + }, noneMethod) + }) + + t.Run("method == token", func(t *testing.T) { + // list predicated with token auth method + req := storage.NewListRequest(storageauth.ListWithMethod(rpcauth.Method_TOKEN)) + tokenMethod, err := storeFn().ListAuthentications(ctx, req) + require.NoError(t, err) + assert.Equal(t, storage.ResultSet[*rpcauth.Authentication]{ + Results: []*rpcauth.Authentication{ + { + Id: "token_id_one", + Method: rpcauth.Method_TOKEN, + Metadata: map[string]string{ + "io.flipt.auth.token.name": "access_some_areas", + "io.flipt.auth.token.description": "The keys to some of the castle", + }, + ExpiresAt: timestamppb.New(time.Unix(2, 0)), + CreatedAt: timestamppb.New(time.Unix(4, 0)), + UpdatedAt: timestamppb.New(time.Unix(4, 0)), }, - ExpiresAt: timestamppb.New(time.Unix(2, 0)), - CreatedAt: someTimestamp, - UpdatedAt: someTimestamp, - }, - { - Id: "token_id_two", - Method: auth.Method_TOKEN, - Metadata: map[string]string{ - "io.flipt.auth.token.name": "access_some_areas", - "io.flipt.auth.token.description": "The keys to some of the castle", + { + Id: "token_id_two", + Method: rpcauth.Method_TOKEN, + Metadata: map[string]string{ + "io.flipt.auth.token.name": "access_some_areas", + "io.flipt.auth.token.description": "The keys to some of the castle", + }, + ExpiresAt: timestamppb.New(time.Unix(2, 0)), + CreatedAt: timestamppb.New(time.Unix(5, 0)), + UpdatedAt: timestamppb.New(time.Unix(5, 0)), }, - ExpiresAt: timestamppb.New(time.Unix(2, 0)), - CreatedAt: someTimestamp, - UpdatedAt: someTimestamp, - }, - { - Id: "token_id_three", - Method: auth.Method_TOKEN, - Metadata: map[string]string{ - "io.flipt.auth.token.name": "access_some_areas", - "io.flipt.auth.token.description": "The keys to some of the castle", + { + Id: "token_id_three", + Method: rpcauth.Method_TOKEN, + Metadata: map[string]string{ + "io.flipt.auth.token.name": "access_some_areas", + "io.flipt.auth.token.description": "The keys to some of the castle", + }, + ExpiresAt: timestamppb.New(time.Unix(2, 0)), + CreatedAt: timestamppb.New(time.Unix(6, 0)), + UpdatedAt: timestamppb.New(time.Unix(6, 0)), }, - ExpiresAt: timestamppb.New(time.Unix(2, 0)), - CreatedAt: someTimestamp, - UpdatedAt: someTimestamp, }, - }, - }, tokenMethod) + }, tokenMethod) + }) } type authentication struct { id string token string - method auth.Method + method rpcauth.Method + optFn func(t *testing.T) []Option } -func createAuth(id, token string, method auth.Method) authentication { - return authentication{id, token, method} +func withOpts(optFn func(t *testing.T) []Option) func(*authentication) { + return func(a *authentication) { + a.optFn = optFn + } +} + +func createAuth(id, token string, method rpcauth.Method, opts ...func(*authentication)) authentication { + a := authentication{id, token, method, nil} + for _, opt := range opts { + opt(&a) + } + + return a } func newTestStore(t *testing.T, seed ...authentication) func(...Option) *Store { t.Helper() - db, err := fliptsqltesting.Open() + db, err := sqltesting.Open() if err != nil { t.Fatal(err) } @@ -332,7 +359,7 @@ func newTestStore(t *testing.T, seed ...authentication) func(...Option) *Store { storeFn = func(opts ...Option) *Store { return NewStore( db.Driver, - fliptsql.BuilderFor(db.DB, db.Driver), + storagesql.BuilderFor(db.DB, db.Driver), logger, opts..., ) @@ -342,14 +369,19 @@ func newTestStore(t *testing.T, seed ...authentication) func(...Option) *Store { // seed any authentication fixtures for _, a := range seed { a := a - store := storeFn( + opts := []Option{ WithNowFunc(func() *timestamppb.Timestamp { return someTimestamp }), WithTokenGeneratorFunc(func() string { return a.token }), WithIDGeneratorFunc(func() string { return a.id }), - ) - clientToken, _, err := store.CreateAuthentication(ctx, &storage.CreateAuthenticationRequest{ + } + + if a.optFn != nil { + opts = append(opts, a.optFn(t)...) + } + + clientToken, _, err := storeFn(opts...).CreateAuthentication(ctx, &storage.CreateAuthenticationRequest{ Method: a.method, ExpiresAt: timestamppb.New(time.Unix(2, 0)), Metadata: map[string]string{ @@ -361,6 +393,8 @@ func newTestStore(t *testing.T, seed ...authentication) func(...Option) *Store { require.Equal(t, a.token, clientToken) logger.Debug("seeded authentication", zap.String("id", a.id)) + + time.Sleep(10 * time.Millisecond) } return storeFn diff --git a/internal/storage/testing/testing.go b/internal/storage/testing/testing.go index 8acb646b3e..6675338905 100644 --- a/internal/storage/testing/testing.go +++ b/internal/storage/testing/testing.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "testing" - "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -41,9 +40,6 @@ func TestAuthenticationStoreHarness(t *testing.T, fn func(t *testing.T) storage. _, ok := index[token] require.False(t, ok, "Token already exists") index[token] = i - - // sleep for DBs which use ms precision - time.Sleep(10 * time.Millisecond) } })