diff --git a/pkg/domain/app/auth/handlers_local.go b/pkg/domain/app/auth/handlers_local.go index 6c6a2964..706a61d5 100644 --- a/pkg/domain/app/auth/handlers_local.go +++ b/pkg/domain/app/auth/handlers_local.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "net/http" + "time" "golang.org/x/crypto/bcrypt" ) @@ -40,7 +41,7 @@ func (service *Service) LocalPostLogin(w http.ResponseWriter, r *http.Request) * } // fetch the password hash from storage - user, err := service.local.storage.GetOneUserByName(payload.Username) + user, err := service.local.storage.GetOneUserByUsername(payload.Username) if err != nil { service.logger.Infof("client %s: login failed (bad username: %s)", r.RemoteAddr, err) return output.JsonErrUnauthorized @@ -138,7 +139,7 @@ func (service *Service) LocalChangePassword(w http.ResponseWriter, r *http.Reque } // fetch the password hash from storage - user, err := service.local.storage.GetOneUserByName(auth.Username) + user, err := service.local.storage.GetOneUserByUsername(auth.Username) if err != nil { // shouldn't be possible since header was valid err = fmt.Errorf("client %s: password change for user '%s' failed (bad username: %s)", r.RemoteAddr, auth.UserTypeAndName(), err) @@ -179,7 +180,7 @@ func (service *Service) LocalChangePassword(w http.ResponseWriter, r *http.Reque } // update password in storage - userId, err := service.local.storage.UpdateUserPassword(auth.Username, string(newPasswordHash)) + userId, err := service.local.storage.PutUserPasswordHash(auth.Username, string(newPasswordHash), time.Now()) if err != nil { err = fmt.Errorf("client %s: password change for user '%s' failed (storage error: %s)", r.RemoteAddr, auth.UserTypeAndName(), err) service.logger.Error(err) diff --git a/pkg/domain/app/auth/local.go b/pkg/domain/app/auth/local.go index 2b69d73b..05c0f885 100644 --- a/pkg/domain/app/auth/local.go +++ b/pkg/domain/app/auth/local.go @@ -9,7 +9,7 @@ type localExtraFuncs struct { // RefreshCheck for local users just queries the DB to confirm no-error func (lef *localExtraFuncs) RefreshCheck() error { // get user must work - _, err := lef.storageService.GetOneUserByName(lef.dbUsername) + _, err := lef.storageService.GetOneUserByUsername(lef.dbUsername) if err != nil { return err } diff --git a/pkg/domain/app/auth/service.go b/pkg/domain/app/auth/service.go index 8430dcdd..47861509 100644 --- a/pkg/domain/app/auth/service.go +++ b/pkg/domain/app/auth/service.go @@ -10,6 +10,7 @@ import ( "net/http" "net/url" "sync" + "time" "github.com/coreos/go-oidc/v3/oidc" "go.uber.org/zap" @@ -39,13 +40,13 @@ type User struct { ID int Username string PasswordHash string - CreatedAt int - UpdatedAt int + CreatedAt time.Time + UpdatedAt time.Time } type Storage interface { - GetOneUserByName(username string) (User, error) - UpdateUserPassword(username string, newPasswordHash string) (userId int, err error) + GetOneUserByUsername(username string) (User, error) + PutUserPasswordHash(username string, passwordHash string, updatedAt time.Time) (userId int, err error) } type Config struct { diff --git a/pkg/storage/accounts_delete_test.go b/pkg/storage/accounts_delete_test.go index 916c3233..8713c9b6 100644 --- a/pkg/storage/accounts_delete_test.go +++ b/pkg/storage/accounts_delete_test.go @@ -82,7 +82,7 @@ func TestDeleteAcmeAccount(t *testing.T) { t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareAcmeAccount(t, acct, tc.expectedGetResult) + compareAcmeAccount(t, acct, tc.expectedGetResult) }) } } diff --git a/pkg/storage/accounts_get_test.go b/pkg/storage/accounts_get_test.go index 15122c85..9483480b 100644 --- a/pkg/storage/accounts_get_test.go +++ b/pkg/storage/accounts_get_test.go @@ -118,7 +118,7 @@ func TestGetAllAcmeAccounts(t *testing.T) { t.Errorf("incorrect result length, expected '%d' but got '%d'", tc.expectedResultLen, len(accts)) } if tc.testIndx <= len(accts)-1 { - CompareAcmeAccount(t, accts[tc.testIndx], tc.expectedAcctAtIndx) + compareAcmeAccount(t, accts[tc.testIndx], tc.expectedAcctAtIndx) } else { t.Errorf("couldnt test result at index '%d' because length of result array was only '%d'", tc.testIndx, len(accts)) } @@ -152,7 +152,7 @@ func TestGetOneAccountById(t *testing.T) { t.Errorf("expected error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedErr), helpers_test.ErrorToVal(err)) } - CompareAcmeAccount(t, acct, tc.expectedAcct) + compareAcmeAccount(t, acct, tc.expectedAcct) }) } } @@ -183,7 +183,7 @@ func TestGetOneAccountByName(t *testing.T) { t.Errorf("expected error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedErr), helpers_test.ErrorToVal(err)) } - CompareAcmeAccount(t, acct, tc.expectedAcct) + compareAcmeAccount(t, acct, tc.expectedAcct) }) } } diff --git a/pkg/storage/accounts_post_test.go b/pkg/storage/accounts_post_test.go index d673d52c..4928b758 100644 --- a/pkg/storage/accounts_post_test.go +++ b/pkg/storage/accounts_post_test.go @@ -111,14 +111,14 @@ func TestPostNewAcmeAccount(t *testing.T) { t.Errorf("expected post error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedPostErr), helpers_test.ErrorToVal(err)) } - CompareAcmeAccount(t, acct, tc.expectedNew) + compareAcmeAccount(t, acct, tc.expectedNew) acct, err = storage.GetOneAcmeAccountByName(acct.Name) if !helpers_test.ErrorsIs(err, tc.expectedGetErr) { t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareAcmeAccount(t, acct, tc.expectedNew) + compareAcmeAccount(t, acct, tc.expectedNew) }) } } diff --git a/pkg/storage/accounts_put_test.go b/pkg/storage/accounts_put_test.go index 1c251da3..057d7c3f 100644 --- a/pkg/storage/accounts_put_test.go +++ b/pkg/storage/accounts_put_test.go @@ -250,14 +250,14 @@ func TestPutAcmeAccountUpdate(t *testing.T) { t.Errorf("expected put error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedPutErr), helpers_test.ErrorToVal(err)) } - CompareAcmeAccount(t, acct, tc.expectedPutResult) + compareAcmeAccount(t, acct, tc.expectedPutResult) acct, err = storage.GetOneAcmeAccountById(tc.getId) if !helpers_test.ErrorsIs(err, tc.expectedGetErr) { t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareAcmeAccount(t, acct, tc.expectedGetResult) + compareAcmeAccount(t, acct, tc.expectedGetResult) }) } } @@ -380,14 +380,14 @@ func TestPutAcmeAccountNewKey(t *testing.T) { t.Errorf("expected put error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedPutErr), helpers_test.ErrorToVal(err)) } - CompareAcmeAccount(t, acct, tc.expectedPutResult) + compareAcmeAccount(t, acct, tc.expectedPutResult) acct, err = storage.GetOneAcmeAccountById(tc.getId) if !helpers_test.ErrorsIs(err, tc.expectedGetErr) { t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareAcmeAccount(t, acct, tc.expectedGetResult) + compareAcmeAccount(t, acct, tc.expectedGetResult) }) } } diff --git a/pkg/storage/accounts_test.go b/pkg/storage/accounts_test.go index 8a8a67d4..ba7e38da 100644 --- a/pkg/storage/accounts_test.go +++ b/pkg/storage/accounts_test.go @@ -5,8 +5,8 @@ import ( "testing" ) -// CompareAcmeAccount compares acct to expectedAcct and throws appropriate errors for any differences -func CompareAcmeAccount(t *testing.T, acct, expectedAcct acme_accounts.Account) { +// compareAcmeAccount compares acct to expectedAcct and throws appropriate errors for any differences +func compareAcmeAccount(t *testing.T, acct, expectedAcct acme_accounts.Account) { if acct.ID != expectedAcct.ID { t.Errorf("acme account: id expected '%d' but got '%d'", expectedAcct.ID, acct.ID) } @@ -19,9 +19,9 @@ func CompareAcmeAccount(t *testing.T, acct, expectedAcct acme_accounts.Account) t.Errorf("acme account: description expected '%s' but got '%s'", expectedAcct.Description, acct.Description) } - CompareAcmeServer(t, acct.AcmeServer, expectedAcct.AcmeServer) + compareAcmeServer(t, acct.AcmeServer, expectedAcct.AcmeServer) - CompareKey(t, acct.AccountKey, expectedAcct.AccountKey) + compareKey(t, acct.AccountKey, expectedAcct.AccountKey) if acct.Status != expectedAcct.Status { t.Errorf("acme account: status expected '%s' but got '%s'", expectedAcct.Status, acct.Status) diff --git a/pkg/storage/acme_servers_delete_test.go b/pkg/storage/acme_servers_delete_test.go index 8fdba97c..82588eee 100644 --- a/pkg/storage/acme_servers_delete_test.go +++ b/pkg/storage/acme_servers_delete_test.go @@ -78,7 +78,7 @@ func TestDeleteServer(t *testing.T) { t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareAcmeServer(t, server, tc.expectedGetResult) + compareAcmeServer(t, server, tc.expectedGetResult) }) } } diff --git a/pkg/storage/acme_servers_get_test.go b/pkg/storage/acme_servers_get_test.go index 19f0881a..68460f11 100644 --- a/pkg/storage/acme_servers_get_test.go +++ b/pkg/storage/acme_servers_get_test.go @@ -86,7 +86,7 @@ func TestGetAllAcmeServers(t *testing.T) { t.Errorf("incorrect result length, expected '%d' but got '%d'", tc.expectedResultLen, len(servers)) } if tc.testIndx <= len(servers)-1 { - CompareAcmeServer(t, servers[tc.testIndx], tc.expectedServerAtIndx) + compareAcmeServer(t, servers[tc.testIndx], tc.expectedServerAtIndx) } else { t.Errorf("couldnt test result at index '%d' because length of result array was only '%d'", tc.testIndx, len(servers)) } @@ -120,7 +120,7 @@ func TestGetOneServerById(t *testing.T) { t.Errorf("expected error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedErr), helpers_test.ErrorToVal(err)) } - CompareAcmeServer(t, serv, tc.expectedServer) + compareAcmeServer(t, serv, tc.expectedServer) }) } } @@ -151,7 +151,7 @@ func TestGetOneServerByName(t *testing.T) { t.Errorf("expected error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedErr), helpers_test.ErrorToVal(err)) } - CompareAcmeServer(t, serv, tc.expectedServer) + compareAcmeServer(t, serv, tc.expectedServer) }) } } diff --git a/pkg/storage/acme_servers_post_test.go b/pkg/storage/acme_servers_post_test.go index ca9bc597..349edb65 100644 --- a/pkg/storage/acme_servers_post_test.go +++ b/pkg/storage/acme_servers_post_test.go @@ -78,14 +78,14 @@ func TestPostNewServer(t *testing.T) { t.Errorf("expected post error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedPostErr), helpers_test.ErrorToVal(err)) } - CompareAcmeServer(t, server, tc.expectedNew) + compareAcmeServer(t, server, tc.expectedNew) server, err = storage.GetOneServerByName(server.Name) if !helpers_test.ErrorsIs(err, tc.expectedGetErr) { t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareAcmeServer(t, server, tc.expectedNew) + compareAcmeServer(t, server, tc.expectedNew) }) } } diff --git a/pkg/storage/acme_servers_put_test.go b/pkg/storage/acme_servers_put_test.go index bf7b2447..8f58e680 100644 --- a/pkg/storage/acme_servers_put_test.go +++ b/pkg/storage/acme_servers_put_test.go @@ -140,14 +140,14 @@ func TestPutServerUpdate(t *testing.T) { t.Errorf("expected put error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedPutErr), helpers_test.ErrorToVal(err)) } - CompareAcmeServer(t, server, tc.expectedPutResult) + compareAcmeServer(t, server, tc.expectedPutResult) server, err = storage.GetOneServerById(tc.getId) if !helpers_test.ErrorsIs(err, tc.expectedGetErr) { t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareAcmeServer(t, server, tc.expectedGetResult) + compareAcmeServer(t, server, tc.expectedGetResult) }) } } diff --git a/pkg/storage/acme_servers_test.go b/pkg/storage/acme_servers_test.go index bf980b77..3e78585f 100644 --- a/pkg/storage/acme_servers_test.go +++ b/pkg/storage/acme_servers_test.go @@ -5,8 +5,8 @@ import ( "testing" ) -// CompareAcmeServers compares server to expectedServer and throws appropriate errors for any differences -func CompareAcmeServer(t *testing.T, server, expectedServer acme_servers.Server) { +// compareAcmeServer compares server to expectedServer and throws appropriate errors for any differences +func compareAcmeServer(t *testing.T, server, expectedServer acme_servers.Server) { if server.ID != expectedServer.ID { t.Errorf("acme server: id expected '%d' but got '%d'", expectedServer.ID, server.ID) } diff --git a/pkg/storage/certificates_delete_test.go b/pkg/storage/certificates_delete_test.go index daea0d1a..77a95264 100644 --- a/pkg/storage/certificates_delete_test.go +++ b/pkg/storage/certificates_delete_test.go @@ -41,7 +41,7 @@ func TestDeleteCert(t *testing.T) { t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareCertificate(t, cert, tc.expectedGetResult) + compareCertificate(t, cert, tc.expectedGetResult) }) } } diff --git a/pkg/storage/certificates_get_test.go b/pkg/storage/certificates_get_test.go index a40225e2..8b876d3d 100644 --- a/pkg/storage/certificates_get_test.go +++ b/pkg/storage/certificates_get_test.go @@ -142,7 +142,7 @@ func TestGetAllCerts(t *testing.T) { t.Errorf("incorrect result length, expected '%d' but got '%d'", tc.expectedResultLen, len(certs)) } if tc.testIndx <= len(certs)-1 { - CompareCertificate(t, certs[tc.testIndx], tc.expectedAtIndx) + compareCertificate(t, certs[tc.testIndx], tc.expectedAtIndx) } else { t.Errorf("couldnt test result at index '%d' because length of result array was only '%d'", tc.testIndx, len(certs)) } @@ -176,7 +176,7 @@ func TestGetOneCertById(t *testing.T) { t.Errorf("expected error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedErr), helpers_test.ErrorToVal(err)) } - CompareCertificate(t, serv, tc.expectedCert) + compareCertificate(t, serv, tc.expectedCert) }) } } @@ -207,7 +207,7 @@ func TestGetOneCertByName(t *testing.T) { t.Errorf("expected error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedErr), helpers_test.ErrorToVal(err)) } - CompareCertificate(t, serv, tc.expectedCert) + compareCertificate(t, serv, tc.expectedCert) }) } } diff --git a/pkg/storage/certificates_post_test.go b/pkg/storage/certificates_post_test.go index aa545430..0af4e533 100644 --- a/pkg/storage/certificates_post_test.go +++ b/pkg/storage/certificates_post_test.go @@ -215,14 +215,14 @@ func TestPostNewCert(t *testing.T) { t.Errorf("expected post error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedPostErr), helpers_test.ErrorToVal(err)) } - CompareCertificate(t, record, tc.expectedNew) + compareCertificate(t, record, tc.expectedNew) record, err = storage.GetOneCertByName(record.Name) if !helpers_test.ErrorsIs(err, tc.expectedGetErr) { t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareCertificate(t, record, tc.expectedNew) + compareCertificate(t, record, tc.expectedNew) }) } } diff --git a/pkg/storage/certificates_put_test.go b/pkg/storage/certificates_put_test.go index 1bcdb8f4..010b98f0 100644 --- a/pkg/storage/certificates_put_test.go +++ b/pkg/storage/certificates_put_test.go @@ -297,14 +297,14 @@ func TestPutDetailsCert(t *testing.T) { t.Errorf("expected put error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedPutErr), helpers_test.ErrorToVal(err)) } - CompareCertificate(t, c, tc.expectedPutResult) + compareCertificate(t, c, tc.expectedPutResult) c, err = storage.GetOneCertById(tc.getId) if !helpers_test.ErrorsIs(err, tc.expectedGetErr) { t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareCertificate(t, c, tc.expectedGetResult) + compareCertificate(t, c, tc.expectedGetResult) }) } } @@ -433,7 +433,7 @@ func TestPutCertApiKey(t *testing.T) { t.Errorf("expected get cert error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareCertificate(t, cert, tc.expectedCert) + compareCertificate(t, cert, tc.expectedCert) }) } } @@ -562,7 +562,7 @@ func TestCertApiKeyNew(t *testing.T) { t.Errorf("expected cert get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareCertificate(t, cert, tc.expectedCert) + compareCertificate(t, cert, tc.expectedCert) }) } @@ -696,7 +696,7 @@ func TestPutCertUpdatedAt(t *testing.T) { t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareCertificate(t, record, tc.expectedCert) + compareCertificate(t, record, tc.expectedCert) }) } @@ -791,7 +791,7 @@ func TestPutCertClientKey(t *testing.T) { t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareCertificate(t, record, tc.expectedCert) + compareCertificate(t, record, tc.expectedCert) }) } } @@ -924,7 +924,7 @@ func TestPutCertLastAccess(t *testing.T) { t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareCertificate(t, record, tc.expectedCert) + compareCertificate(t, record, tc.expectedCert) }) } } diff --git a/pkg/storage/certificates_test.go b/pkg/storage/certificates_test.go index 16845d3c..9e960765 100644 --- a/pkg/storage/certificates_test.go +++ b/pkg/storage/certificates_test.go @@ -7,8 +7,8 @@ import ( "testing" ) -// CompareCertificateCSRExtensions is for comparing the special csr extra extensions -func CompareCertificateCSRExtensions(t *testing.T, extns, expectedExtns []certificates.CertExtension) { +// compareCertificateCSRExtensions is for comparing the special csr extra extensions +func compareCertificateCSRExtensions(t *testing.T, extns, expectedExtns []certificates.CertExtension) { if len(extns) != len(expectedExtns) { t.Errorf("certificate: csr extra extensions expected length '%d' but got '%d'", len(expectedExtns), len(extns)) } @@ -46,8 +46,8 @@ func CompareCertificateCSRExtensions(t *testing.T, extns, expectedExtns []certif } } -// CompareCertificate compares cert to expectedCert and throws appropriate errors for any differences -func CompareCertificate(t *testing.T, cert, expectedCert certificates.Certificate) { +// compareCertificate compares cert to expectedCert and throws appropriate errors for any differences +func compareCertificate(t *testing.T, cert, expectedCert certificates.Certificate) { if cert.ID != expectedCert.ID { t.Errorf("certificate: id expected '%d' but got '%d'", expectedCert.ID, cert.ID) } @@ -60,9 +60,9 @@ func CompareCertificate(t *testing.T, cert, expectedCert certificates.Certificat t.Errorf("certificate: description expected '%s' but got '%s'", expectedCert.Description, cert.Description) } - CompareKey(t, cert.Key, expectedCert.Key) + compareKey(t, cert.Key, expectedCert.Key) - CompareAcmeAccount(t, cert.Account, expectedCert.Account) + compareAcmeAccount(t, cert.Account, expectedCert.Account) if cert.Subject != expectedCert.Subject { t.Errorf("certificate: subject expected '%s' but got '%s'", expectedCert.Subject, cert.Subject) @@ -92,7 +92,7 @@ func CompareCertificate(t *testing.T, cert, expectedCert certificates.Certificat t.Errorf("certificate: city expected '%s' but got '%s'", expectedCert.City, cert.City) } - CompareCertificateCSRExtensions(t, cert.CSRExtraExtensions, expectedCert.CSRExtraExtensions) + compareCertificateCSRExtensions(t, cert.CSRExtraExtensions, expectedCert.CSRExtraExtensions) if cert.PreferredRootCN != expectedCert.PreferredRootCN { t.Errorf("certificate: preferred root cn expected '%s' but got '%s'", expectedCert.PreferredRootCN, cert.PreferredRootCN) diff --git a/pkg/storage/keys_delete_test.go b/pkg/storage/keys_delete_test.go index cbf89f96..79762305 100644 --- a/pkg/storage/keys_delete_test.go +++ b/pkg/storage/keys_delete_test.go @@ -79,7 +79,7 @@ func TestDeleteKey(t *testing.T) { t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareKey(t, key, tc.expectedGetResult) + compareKey(t, key, tc.expectedGetResult) }) } } diff --git a/pkg/storage/keys_get_test.go b/pkg/storage/keys_get_test.go index 5196d733..36e7a8f0 100644 --- a/pkg/storage/keys_get_test.go +++ b/pkg/storage/keys_get_test.go @@ -301,7 +301,7 @@ func TestGetAllKeys(t *testing.T) { t.Errorf("incorrect result length, expected '%d' but got '%d'", tc.expectedResultLen, len(keys)) } if tc.testIndx <= len(keys)-1 { - CompareKey(t, keys[tc.testIndx], tc.expectedKeyAtIndx) + compareKey(t, keys[tc.testIndx], tc.expectedKeyAtIndx) } else { t.Errorf("couldnt test result at index '%d' because length of result array was only '%d'", tc.testIndx, len(keys)) } @@ -334,7 +334,7 @@ func TestGetOneKeyById(t *testing.T) { t.Errorf("expected error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedErr), helpers_test.ErrorToVal(err)) } - CompareKey(t, key, tc.expectedKey) + compareKey(t, key, tc.expectedKey) }) } } @@ -364,7 +364,7 @@ func TestGetOneKeyByName(t *testing.T) { t.Errorf("expected error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedErr), helpers_test.ErrorToVal(err)) } - CompareKey(t, key, tc.expectedKey) + compareKey(t, key, tc.expectedKey) }) } } @@ -394,6 +394,6 @@ func TestGetAvailableKeys(t *testing.T) { continue } - CompareKey(t, keys[i], expectedKey) + compareKey(t, keys[i], expectedKey) } } diff --git a/pkg/storage/keys_post_test.go b/pkg/storage/keys_post_test.go index c000d9e5..5e9cc864 100644 --- a/pkg/storage/keys_post_test.go +++ b/pkg/storage/keys_post_test.go @@ -92,14 +92,14 @@ func TestPostNewKey(t *testing.T) { t.Errorf("expected post error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedPostErr), helpers_test.ErrorToVal(err)) } - CompareKey(t, key, tc.expectedNewKey) + compareKey(t, key, tc.expectedNewKey) key, err = storage.GetOneKeyByName(key.Name) if !helpers_test.ErrorsIs(err, tc.expectedGetErr) { t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareKey(t, key, tc.expectedNewKey) + compareKey(t, key, tc.expectedNewKey) }) } } diff --git a/pkg/storage/keys_put_test.go b/pkg/storage/keys_put_test.go index 51773dfc..96669b57 100644 --- a/pkg/storage/keys_put_test.go +++ b/pkg/storage/keys_put_test.go @@ -191,14 +191,14 @@ red-58 t.Errorf("expected put error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedPutErr), helpers_test.ErrorToVal(err)) } - CompareKey(t, key, tc.expectedPutResult) + compareKey(t, key, tc.expectedPutResult) key, err = storage.GetOneKeyById(tc.getId) if !helpers_test.ErrorsIs(err, tc.expectedGetErr) { t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareKey(t, key, tc.expectedGetResult) + compareKey(t, key, tc.expectedGetResult) }) } } @@ -298,7 +298,7 @@ red-62 t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareKey(t, key, tc.expectedKey) + compareKey(t, key, tc.expectedKey) }) } } @@ -398,7 +398,7 @@ red-67 t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareKey(t, key, tc.expectedKey) + compareKey(t, key, tc.expectedKey) }) } } @@ -516,7 +516,7 @@ red-62 t.Errorf("expected get error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) } - CompareKey(t, key, tc.expectedKey) + compareKey(t, key, tc.expectedKey) }) } } diff --git a/pkg/storage/keys_test.go b/pkg/storage/keys_test.go index 4ad33049..8411abe3 100644 --- a/pkg/storage/keys_test.go +++ b/pkg/storage/keys_test.go @@ -5,8 +5,8 @@ import ( "testing" ) -// CompareKey compares key to expectedKey and throws appropriate errors for any differences -func CompareKey(t *testing.T, key, expectedKey private_keys.Key) { +// compareKey compares key to expectedKey and throws appropriate errors for any differences +func compareKey(t *testing.T, key, expectedKey private_keys.Key) { if key.ID != expectedKey.ID { t.Errorf("key: id expected '%d' but got '%d'", expectedKey.ID, key.ID) } diff --git a/pkg/storage/users.go b/pkg/storage/users.go index ebf91905..7fcedf27 100644 --- a/pkg/storage/users.go +++ b/pkg/storage/users.go @@ -1,10 +1,26 @@ package storage +import ( + "certwarden-backend/pkg/domain/app/auth" + "time" +) + // userDb represents how users are stored in the db type userDb struct { id int username string passwordHash string - createdAt int - updatedAt int + createdAt int64 + updatedAt int64 +} + +// dbToUser converts the user db object to app object +func (userDb *userDb) dbToUser() (user auth.User) { + return auth.User{ + ID: userDb.id, + Username: userDb.username, + PasswordHash: userDb.passwordHash, + CreatedAt: time.Unix(userDb.createdAt, 0), + UpdatedAt: time.Unix(userDb.updatedAt, 0), + } } diff --git a/pkg/storage/users_get.go b/pkg/storage/users_get.go index 5cf19dcf..a4959374 100644 --- a/pkg/storage/users_get.go +++ b/pkg/storage/users_get.go @@ -5,20 +5,8 @@ import ( "context" ) -// dbToUser converts the user db object to app object -func (userDb *userDb) dbToUser() (user auth.User) { - return auth.User{ - ID: userDb.id, - Username: userDb.username, - PasswordHash: userDb.passwordHash, - CreatedAt: userDb.createdAt, - UpdatedAt: userDb.updatedAt, - } -} - -// GetOneUserByName returns a user from the db based on -// username -func (store Storage) GetOneUserByName(username string) (auth.User, error) { +// GetOneUserByUsername returns a user from the db with the specified username +func (store Storage) GetOneUserByUsername(username string) (auth.User, error) { ctx, cancel := context.WithTimeout(store.shutdownContext, store.timeout) defer cancel() diff --git a/pkg/storage/users_get_test.go b/pkg/storage/users_get_test.go new file mode 100644 index 00000000..a1d59dc5 --- /dev/null +++ b/pkg/storage/users_get_test.go @@ -0,0 +1,66 @@ +package storage_test + +import ( + "certwarden-backend/pkg/domain/app/auth" + "certwarden-backend/pkg/helpers_test" + "database/sql" + "fmt" + "testing" + "time" +) + +var ( + user1 = auth.User{ + ID: 1, + Username: "admin", + PasswordHash: "xYz", + CreatedAt: time.Unix(1697139775, 0), + UpdatedAt: time.Unix(1738009344, 0), + } + user2 = auth.User{ + ID: 2, + Username: "user2", + PasswordHash: "abc", + CreatedAt: time.Unix(255111225, 0), + UpdatedAt: time.Unix(122544466, 0), + } + user4 = auth.User{ + ID: 4, + Username: "user4", + PasswordHash: "1234b", + CreatedAt: time.Unix(88222222, 0), + UpdatedAt: time.Unix(22222222, 0), + } +) + +func TestGetOneUserByName(t *testing.T) { + testCases := []struct { + username string + expectedUser auth.User + expectedErr error + }{ + {"", auth.User{}, sql.ErrNoRows}, + {"fake-bad-username", auth.User{}, sql.ErrNoRows}, + {"admin", user1, nil}, + // {"AdMiN", user1, nil}, // case is wrong TODO: make case insensitive + {"user2", user2, nil}, + {"user4", user4, nil}, + } + + // create testing service + storage, err := openStorageWithTestData(t, "getoneuserbyusername") + if err != nil { + t.Fatal(err) + } + + for i, tc := range testCases { + t.Run(fmt.Sprintf("#%d (name: %s)", i, tc.username), func(t *testing.T) { + user, err := storage.GetOneUserByUsername(tc.username) + if !helpers_test.ErrorsIs(err, tc.expectedErr) { + t.Errorf("expected get username error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedErr), helpers_test.ErrorToVal(err)) + } + + compareUser(t, user, tc.expectedUser) + }) + } +} diff --git a/pkg/storage/users_put.go b/pkg/storage/users_put.go index 815db845..b193378b 100644 --- a/pkg/storage/users_put.go +++ b/pkg/storage/users_put.go @@ -1,10 +1,14 @@ package storage -import "context" +import ( + "context" + "errors" + "fmt" + "time" +) -// UpdateUserPassword updates the specified user's password hash to the specified -// hash. -func (store *Storage) UpdateUserPassword(username string, newPasswordHash string) (userId int, err error) { +// PutUserPasswordHash updates the specified user's password hash to the specified hash. +func (store *Storage) PutUserPasswordHash(username string, passwordHash string, updatedAt time.Time) (userId int, err error) { // database action ctx, cancel := context.WithTimeout(store.shutdownContext, store.timeout) defer cancel() @@ -17,20 +21,31 @@ func (store *Storage) UpdateUserPassword(username string, newPasswordHash string updated_at = $2 WHERE username = $3 - RETURNING - id ` - // update password and return id - err = store.db.QueryRowContext(ctx, query, - newPasswordHash, - timeNow(), + res, err := store.db.ExecContext(ctx, query, + passwordHash, + updatedAt.Unix(), username, - ).Scan(&userId) + ) + if err != nil { + return -2, err + } + + // verify update actually happened + rowsAffected, err := res.RowsAffected() + if err != nil { + return -2, err + } + if rowsAffected != 1 { + return -2, errors.Join(fmt.Errorf("expected 1 row update, but got '%d'", rowsAffected), ErrWrongUpdateRowCount) + } + // get updated key to return + updatedUser, err := store.GetOneUserByUsername(username) if err != nil { return -2, err } - return userId, nil + return updatedUser.ID, nil } diff --git a/pkg/storage/users_put_test.go b/pkg/storage/users_put_test.go new file mode 100644 index 00000000..b4cf9513 --- /dev/null +++ b/pkg/storage/users_put_test.go @@ -0,0 +1,93 @@ +package storage_test + +import ( + "certwarden-backend/pkg/domain/app/auth" + "certwarden-backend/pkg/helpers_test" + "certwarden-backend/pkg/storage" + "database/sql" + "fmt" + "testing" + "time" +) + +func TestPutUserPasswordHash(t *testing.T) { + testCases := []struct { + username string + newPasswordHash string + updatedAt time.Time + + expectedPutId int + expectedPutErr error + expectedGetUser auth.User + expectedGetErr error + }{ + { + "", + "somehash", + time.Unix(12222222, 0), + -2, + storage.ErrWrongUpdateRowCount, + auth.User{}, + sql.ErrNoRows, + }, + { + "fake-bad-username", + "somehash", + time.Unix(12222223, 0), + -2, + storage.ErrWrongUpdateRowCount, + auth.User{}, + sql.ErrNoRows, + }, + { + "uSEr2", // case is wrong TODO: make case insensitive + "newHAsh456", + time.Unix(12244224, 0), + -2, + storage.ErrWrongUpdateRowCount, + auth.User{}, + sql.ErrNoRows, + }, + { + "user4", + "anewhash", + time.Unix(22422224, 0), + 4, + nil, + auth.User{ + ID: 4, + Username: "user4", + PasswordHash: "anewhash", + CreatedAt: time.Unix(88222222, 0), + UpdatedAt: time.Unix(22422224, 0), + }, + nil, + }, + } + + // create testing service + storage, err := openStorageWithTestData(t, "putuserpasswordhash") + if err != nil { + t.Fatal(err) + } + + for i, tc := range testCases { + t.Run(fmt.Sprintf("#%d (name: %s)", i, tc.username), func(t *testing.T) { + userId, err := storage.PutUserPasswordHash(tc.username, tc.newPasswordHash, tc.updatedAt) + if !helpers_test.ErrorsIs(err, tc.expectedPutErr) { + t.Errorf("expected put username passwordhash error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedPutErr), helpers_test.ErrorToVal(err)) + } + + if userId != tc.expectedPutId { + t.Errorf("expected put username passwordhash return val '%d' but got '%d'", tc.expectedPutId, userId) + } + + user, err := storage.GetOneUserByUsername(tc.username) + if !helpers_test.ErrorsIs(err, tc.expectedGetErr) { + t.Errorf("expected get username error '%s' but got '%s'", helpers_test.ErrorToVal(tc.expectedGetErr), helpers_test.ErrorToVal(err)) + } + + compareUser(t, user, tc.expectedGetUser) + }) + } +} diff --git a/pkg/storage/users_test.go b/pkg/storage/users_test.go new file mode 100644 index 00000000..71bc0b07 --- /dev/null +++ b/pkg/storage/users_test.go @@ -0,0 +1,29 @@ +package storage_test + +import ( + "certwarden-backend/pkg/domain/app/auth" + "testing" +) + +// compareUser compares user to expectedUser and throws appropriate errors for any differences +func compareUser(t *testing.T, user, expectedUser auth.User) { + if user.ID != expectedUser.ID { + t.Errorf("user: id expected '%d' but got '%d'", expectedUser.ID, user.ID) + } + + if user.Username != expectedUser.Username { + t.Errorf("user: username expected '%s' but got '%s'", expectedUser.Username, user.Username) + } + + if user.PasswordHash != expectedUser.PasswordHash { + t.Errorf("user: passwordhash expected '%s' but got '%s'", expectedUser.PasswordHash, user.PasswordHash) + } + + if !user.CreatedAt.Equal(expectedUser.CreatedAt) { + t.Errorf("key: created at expected '%s' but got '%s'", expectedUser.CreatedAt.UTC(), user.CreatedAt.UTC()) + } + + if !user.UpdatedAt.Equal(expectedUser.UpdatedAt) { + t.Errorf("key: updated at expected '%s' but got '%s'", expectedUser.UpdatedAt.UTC(), user.UpdatedAt.UTC()) + } +} diff --git a/test_data/testdata_v11.db b/test_data/testdata_v11.db index 75a604ef..a966332b 100644 Binary files a/test_data/testdata_v11.db and b/test_data/testdata_v11.db differ