Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for API keys #4515

Merged
merged 8 commits into from
Aug 25, 2020
Prev Previous commit
Next Next commit
Cover the rest of psql_apikeys.go with tests
  • Loading branch information
ikapelyukhin committed Aug 21, 2020
commit 94840939d4390975c03ca91997f9a8928c5e7e2a
199 changes: 192 additions & 7 deletions src/jetstream/repository/apikeys/psql_apikeys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func TestAddAPIKey(t *testing.T) {
var (
userID = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
insertIntoAPIKeys = `INSERT INTO api_keys`
comment = "test"
)

Convey("Given a request to add an API key", t, func() {
Expand All @@ -46,19 +47,31 @@ func TestAddAPIKey(t *testing.T) {

repository, _ := NewPgsqlAPIKeysRepository(db)

_ = mock

Convey("when the comment exceeds maximal length", func() {
_, err := repository.AddAPIKey(userID, strings.Repeat("a", 256))

Convey("there should be no error returned", func() {
Convey("an error should be returned", func() {
So(err, ShouldResemble, errors.New("comment maximum length is 255 characters"))
})
})

Convey("when the comment is not empty", func() {
comment := "test"
Convey("when a key can't be inserted", func() {
mock.ExpectExec(insertIntoAPIKeys).
WithArgs(sqlmock.AnyArg(), sqlmock.AnyArg(), userID, comment).
WillReturnResult(sqlmock.NewResult(0, 0))

apiKey, err := repository.AddAPIKey(userID, comment)

Convey("an error should be returned", func() {
So(err, ShouldResemble, errors.New("unable to INSERT api key: no rows were updated"))
})

Convey("should return nil", func() {
So(apiKey, ShouldBeNil)
})
})

Convey("when the comment is not empty", func() {
mock.ExpectExec(insertIntoAPIKeys).
WithArgs(sqlmock.AnyArg(), sqlmock.AnyArg(), userID, comment).
WillReturnResult(sqlmock.NewResult(1, 1))
Expand Down Expand Up @@ -121,8 +134,22 @@ func TestListAPIKeys(t *testing.T) {

Convey("if records exist in the DB", func() {
t := time.Now()
r1 := &interfaces.APIKey{GUID: "00000000-0000-0000-0000-000000000000", Secret: "", UserGUID: userID, Comment: "First key", LastUsed: &t}
r2 := &interfaces.APIKey{GUID: "11111111-1111-1111-1111-111111111111", Secret: "", UserGUID: userID, Comment: "Second key", LastUsed: nil}

r1 := &interfaces.APIKey{
GUID: "00000000-0000-0000-0000-000000000000",
Secret: "",
UserGUID: userID,
Comment: "First key",
LastUsed: &t,
}

r2 := &interfaces.APIKey{
GUID: "11111111-1111-1111-1111-111111111111",
Secret: "",
UserGUID: userID,
Comment: "Second key",
LastUsed: nil,
}

expectedList := []interfaces.APIKey{*r1, *r2}

Expand Down Expand Up @@ -152,3 +179,161 @@ func TestListAPIKeys(t *testing.T) {
})
})
}

func TestGetAPIKeyBySecret(t *testing.T) {
var (
rowFields = []string{"guid", "user_guid", "comment", "last_used"}
selectAPIKeyBySecret = `SELECT (.+) FROM api_keys WHERE secret = (.+)`
)

Convey("Given a request to get an API key by its secret", t, func() {
db, mock, err := sqlmock.New()
if err != nil {
t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
}
defer db.Close()

repository, err := NewPgsqlAPIKeysRepository(db)

Convey("if no matching record exists in the DB", func() {
rs := sqlmock.NewRows(rowFields)
mock.ExpectQuery(selectAPIKeyBySecret).WillReturnRows(rs)
results, err := repository.GetAPIKeyBySecret("test")

Convey("DB query expectations should be met", func() {
So(mock.ExpectationsWereMet(), ShouldBeNil)
})

Convey("an error should be returned", func() {
So(err, ShouldResemble, errors.New("sql: no rows in result set"))
})

Convey("result should be nil", func() {
So(results, ShouldBeNil)
})
})

Convey("if records exist in the DB", func() {
t := time.Now()

r := &interfaces.APIKey{
GUID: "00000000-0000-0000-0000-000000000000",
Secret: "",
UserGUID: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
Comment: "First key",
LastUsed: &t,
}

mockRows := sqlmock.NewRows(rowFields).
AddRow(r.GUID, r.UserGUID, r.Comment, r.LastUsed)

mock.ExpectQuery(selectAPIKeyBySecret).WillReturnRows(mockRows)

results, err := repository.GetAPIKeyBySecret("test")

Convey("DB query expectations should be met", func() {
So(mock.ExpectationsWereMet(), ShouldBeNil)
})

Convey("there should be no error returned", func() {
So(err, ShouldBeNil)
})

Convey("result should be of correct type", func() {
So(results, ShouldResemble, r)
})
})
})
}

func TestDeleteAPIKey(t *testing.T) {
var (
userID = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
keyID = "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
deleteFromAPIKeys = `DELETE FROM api_keys WHERE user_guid = (.+) AND guid = (.+)`
)

Convey("Given a request to add an API key", t, func() {
db, mock, err := sqlmock.New()
if err != nil {
t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
}
defer db.Close()

repository, _ := NewPgsqlAPIKeysRepository(db)

Convey("when a matching key doesn't exist", func() {
mock.ExpectExec(deleteFromAPIKeys).
WithArgs(userID, keyID).
WillReturnResult(sqlmock.NewResult(0, 0))

err := repository.DeleteAPIKey(userID, keyID)

Convey("an error should be returned", func() {
So(err, ShouldResemble, errors.New("unable to DELETE api key: no rows were updated"))
})
})

Convey("when a matching key exists", func() {
mock.ExpectExec(deleteFromAPIKeys).
WithArgs(userID, keyID).
WillReturnResult(sqlmock.NewResult(1, 1))

err := repository.DeleteAPIKey(userID, keyID)

Convey("DB query expectations should be met", func() {
So(mock.ExpectationsWereMet(), ShouldBeNil)
})

Convey("there should be no error returned", func() {
So(err, ShouldBeNil)
})
})
})
}

//
func TestUpdateAPIKeyLastUsed(t *testing.T) {
var (
keyID = "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
updateLastUsed = `UPDATE api_keys SET last_used = (.+) WHERE guid = (.+)`
)

Convey("Given a request to update API key last used", t, func() {
db, mock, err := sqlmock.New()
if err != nil {
t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
}
defer db.Close()

repository, _ := NewPgsqlAPIKeysRepository(db)

Convey("when a matching key doesn't exist", func() {
mock.ExpectExec(updateLastUsed).
WithArgs(sqlmock.AnyArg(), keyID).
WillReturnResult(sqlmock.NewResult(0, 0))

err := repository.UpdateAPIKeyLastUsed(keyID)

Convey("an error should be returned", func() {
So(err, ShouldResemble, errors.New("unable to UPDATE api key: no rows were updated"))
})
})

Convey("when a matching key exists", func() {
mock.ExpectExec(updateLastUsed).
WithArgs(sqlmock.AnyArg(), keyID).
WillReturnResult(sqlmock.NewResult(1, 1))

err := repository.UpdateAPIKeyLastUsed(keyID)

Convey("DB query expectations should be met", func() {
So(mock.ExpectationsWereMet(), ShouldBeNil)
})

Convey("there should be no error returned", func() {
So(err, ShouldBeNil)
})
})
})
}