Auth: Service account store refactor (#58961)

* refactor: renaming of files from database to store

* refactor: make service account store private

- moves store interface to manager package
- adds an interface to the ProvideAPI constructor
- refactors tests to use the store when necessary
- adds mocks for the new interface implementations in the tests package

* wip

* refactor: make fakestore in service

* wip

* wip

* wip

* working tests

* trailing whitespaces

* Update pkg/services/serviceaccounts/api/api.go

* Update pkg/services/serviceaccounts/tests/common.go

* Update pkg/services/serviceaccounts/tests/common.go

* refactor: doc string for retriever

* fix import unused

* remove: serviceaccount from featuretoggle

* added: back legacy serviceaccounts feature toggle

* added: docs

* refactor: make query for the SearchQuery

* add: validation of service input fields

* add validation
This commit is contained in:
Eric Leijonmarck
2022-12-13 14:56:10 +01:00
committed by GitHub
parent 13adaddfaa
commit 371d7850a5
19 changed files with 692 additions and 267 deletions

View File

@@ -1,6 +1,7 @@
package api
import (
"context"
"errors"
"net/http"
"strconv"
@@ -12,6 +13,7 @@ import (
"github.com/grafana/grafana/pkg/middleware"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/apikey"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/serviceaccounts/database"
@@ -22,22 +24,39 @@ import (
type ServiceAccountsAPI struct {
cfg *setting.Cfg
service serviceaccounts.Service
service service
accesscontrol accesscontrol.AccessControl
accesscontrolService accesscontrol.Service
RouterRegister routing.RouteRegister
store serviceaccounts.Store
log log.Logger
permissionService accesscontrol.ServiceAccountPermissionsService
}
// Service implements the API exposed methods for service accounts.
type service interface {
CreateServiceAccount(ctx context.Context, orgID int64, saForm *serviceaccounts.CreateServiceAccountForm) (*serviceaccounts.ServiceAccountDTO, error)
RetrieveServiceAccount(ctx context.Context, orgID, serviceAccountID int64) (*serviceaccounts.ServiceAccountProfileDTO, error)
UpdateServiceAccount(ctx context.Context, orgID, serviceAccountID int64,
saForm *serviceaccounts.UpdateServiceAccountForm) (*serviceaccounts.ServiceAccountProfileDTO, error)
SearchOrgServiceAccounts(ctx context.Context, query *serviceaccounts.SearchOrgServiceAccountsQuery) (*serviceaccounts.SearchOrgServiceAccountsResult, error)
ListTokens(ctx context.Context, query *serviceaccounts.GetSATokensQuery) ([]apikey.APIKey, error)
DeleteServiceAccount(ctx context.Context, orgID, serviceAccountID int64) error
GetAPIKeysMigrationStatus(ctx context.Context, orgID int64) (*serviceaccounts.APIKeysMigrationStatus, error)
HideApiKeysTab(ctx context.Context, orgID int64) error
MigrateApiKeysToServiceAccounts(ctx context.Context, orgID int64) error
MigrateApiKey(ctx context.Context, orgID int64, keyId int64) error
RevertApiKey(ctx context.Context, saId int64, keyId int64) error
// Service account tokens
AddServiceAccountToken(ctx context.Context, serviceAccountID int64, cmd *serviceaccounts.AddServiceAccountTokenCommand) error
DeleteServiceAccountToken(ctx context.Context, orgID, serviceAccountID, tokenID int64) error
}
func NewServiceAccountsAPI(
cfg *setting.Cfg,
service serviceaccounts.Service,
service service,
accesscontrol accesscontrol.AccessControl,
accesscontrolService accesscontrol.Service,
routerRegister routing.RouteRegister,
store serviceaccounts.Store,
permissionService accesscontrol.ServiceAccountPermissionsService,
) *ServiceAccountsAPI {
return &ServiceAccountsAPI{
@@ -46,7 +65,6 @@ func NewServiceAccountsAPI(
accesscontrol: accesscontrol,
accesscontrolService: accesscontrolService,
RouterRegister: routerRegister,
store: store,
log: log.New("serviceaccounts.api"),
permissionService: permissionService,
}
@@ -116,7 +134,7 @@ func (api *ServiceAccountsAPI) CreateServiceAccount(c *models.ReqContext) respon
}
}
serviceAccount, err := api.store.CreateServiceAccount(c.Req.Context(), c.OrgID, &cmd)
serviceAccount, err := api.service.CreateServiceAccount(c.Req.Context(), c.OrgID, &cmd)
switch {
case errors.Is(err, database.ErrServiceAccountAlreadyExists):
return response.Error(http.StatusBadRequest, "Failed to create service account", err)
@@ -159,7 +177,7 @@ func (api *ServiceAccountsAPI) RetrieveServiceAccount(ctx *models.ReqContext) re
return response.Error(http.StatusBadRequest, "Service Account ID is invalid", err)
}
serviceAccount, err := api.store.RetrieveServiceAccount(ctx.Req.Context(), ctx.OrgID, scopeID)
serviceAccount, err := api.service.RetrieveServiceAccount(ctx.Req.Context(), ctx.OrgID, scopeID)
if err != nil {
switch {
case errors.Is(err, serviceaccounts.ErrServiceAccountNotFound):
@@ -174,7 +192,7 @@ func (api *ServiceAccountsAPI) RetrieveServiceAccount(ctx *models.ReqContext) re
serviceAccount.AvatarUrl = dtos.GetGravatarUrlWithDefault("", serviceAccount.Name)
serviceAccount.AccessControl = metadata[saIDString]
tokens, err := api.store.ListTokens(ctx.Req.Context(), &serviceaccounts.GetSATokensQuery{
tokens, err := api.service.ListTokens(ctx.Req.Context(), &serviceaccounts.GetSATokensQuery{
OrgID: &serviceAccount.OrgId,
ServiceAccountID: &serviceAccount.Id,
})
@@ -222,7 +240,7 @@ func (api *ServiceAccountsAPI) UpdateServiceAccount(c *models.ReqContext) respon
}
}
resp, err := api.store.UpdateServiceAccount(c.Req.Context(), c.OrgID, scopeID, &cmd)
resp, err := api.service.UpdateServiceAccount(c.Req.Context(), c.OrgID, scopeID, &cmd)
if err != nil {
switch {
case errors.Is(err, serviceaccounts.ErrServiceAccountNotFound):
@@ -312,7 +330,15 @@ func (api *ServiceAccountsAPI) SearchOrgServiceAccountsWithPaging(c *models.ReqC
if onlyDisabled {
filter = serviceaccounts.FilterOnlyDisabled
}
serviceAccountSearch, err := api.store.SearchOrgServiceAccounts(ctx, c.OrgID, c.Query("query"), filter, page, perPage, c.SignedInUser)
q := serviceaccounts.SearchOrgServiceAccountsQuery{
OrgID: c.OrgID,
Query: c.Query("query"),
Page: page,
Limit: perPage,
Filter: filter,
SignedInUser: c.SignedInUser,
}
serviceAccountSearch, err := api.service.SearchOrgServiceAccounts(ctx, &q)
if err != nil {
return response.Error(http.StatusInternalServerError, "Failed to get service accounts for current organization", err)
}
@@ -326,7 +352,7 @@ func (api *ServiceAccountsAPI) SearchOrgServiceAccountsWithPaging(c *models.ReqC
saIDs[saIDString] = true
metadata := api.getAccessControlMetadata(c, map[string]bool{saIDString: true})
sa.AccessControl = metadata[strconv.FormatInt(sa.Id, 10)]
tokens, err := api.store.ListTokens(ctx, &serviceaccounts.GetSATokensQuery{
tokens, err := api.service.ListTokens(ctx, &serviceaccounts.GetSATokensQuery{
OrgID: &sa.OrgId, ServiceAccountID: &sa.Id,
})
if err != nil {
@@ -340,7 +366,7 @@ func (api *ServiceAccountsAPI) SearchOrgServiceAccountsWithPaging(c *models.ReqC
// GET /api/serviceaccounts/migrationstatus
func (api *ServiceAccountsAPI) GetAPIKeysMigrationStatus(ctx *models.ReqContext) response.Response {
upgradeStatus, err := api.store.GetAPIKeysMigrationStatus(ctx.Req.Context(), ctx.OrgID)
upgradeStatus, err := api.service.GetAPIKeysMigrationStatus(ctx.Req.Context(), ctx.OrgID)
if err != nil {
return response.Error(http.StatusInternalServerError, "Internal server error", err)
}
@@ -349,7 +375,7 @@ func (api *ServiceAccountsAPI) GetAPIKeysMigrationStatus(ctx *models.ReqContext)
// POST /api/serviceaccounts/hideapikeys
func (api *ServiceAccountsAPI) HideApiKeysTab(ctx *models.ReqContext) response.Response {
if err := api.store.HideApiKeysTab(ctx.Req.Context(), ctx.OrgID); err != nil {
if err := api.service.HideApiKeysTab(ctx.Req.Context(), ctx.OrgID); err != nil {
return response.Error(http.StatusInternalServerError, "Internal server error", err)
}
return response.Success("API keys hidden")
@@ -357,7 +383,7 @@ func (api *ServiceAccountsAPI) HideApiKeysTab(ctx *models.ReqContext) response.R
// POST /api/serviceaccounts/migrate
func (api *ServiceAccountsAPI) MigrateApiKeysToServiceAccounts(ctx *models.ReqContext) response.Response {
if err := api.store.MigrateApiKeysToServiceAccounts(ctx.Req.Context(), ctx.OrgID); err != nil {
if err := api.service.MigrateApiKeysToServiceAccounts(ctx.Req.Context(), ctx.OrgID); err != nil {
return response.Error(http.StatusInternalServerError, "Internal server error", err)
}
@@ -371,7 +397,7 @@ func (api *ServiceAccountsAPI) ConvertToServiceAccount(ctx *models.ReqContext) r
return response.Error(http.StatusBadRequest, "Key ID is invalid", err)
}
if err := api.store.MigrateApiKey(ctx.Req.Context(), ctx.OrgID, keyId); err != nil {
if err := api.service.MigrateApiKey(ctx.Req.Context(), ctx.OrgID, keyId); err != nil {
return response.Error(http.StatusInternalServerError, "Error converting API key", err)
}
@@ -389,7 +415,7 @@ func (api *ServiceAccountsAPI) RevertApiKey(ctx *models.ReqContext) response.Res
return response.Error(http.StatusBadRequest, "service account ID is invalid", err)
}
if err := api.store.RevertApiKey(ctx.Req.Context(), serviceAccountId, keyId); err != nil {
if err := api.service.RevertApiKey(ctx.Req.Context(), serviceAccountId, keyId); err != nil {
return response.Error(http.StatusInternalServerError, "error reverting to API key", err)
}
return response.Success("reverted service account to API key")
@@ -464,7 +490,7 @@ type DeleteServiceAccountParams struct {
// swagger:response searchOrgServiceAccountsWithPagingResponse
type SearchOrgServiceAccountsWithPagingResponse struct {
// in:body
Body *serviceaccounts.SearchServiceAccountsResult
Body *serviceaccounts.SearchOrgServiceAccountsResult
}
// swagger:response createServiceAccountResponse

View File

@@ -32,6 +32,7 @@ import (
"github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/serviceaccounts/database"
"github.com/grafana/grafana/pkg/services/serviceaccounts/retriever"
"github.com/grafana/grafana/pkg/services/serviceaccounts/tests"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/team/teamimpl"
@@ -46,6 +47,13 @@ var (
serviceAccountIDPath = serviceAccountPath + "%v"
)
// TODO:
// refactor this set of tests to make use of fakes for the ServiceAccountService
// all of the API tests are calling with all of the db store injections
// which is not ideal
// this is a bit of a hack to get the tests to pass until we refactor the tests
// to use fakes as in the user service tests
func TestServiceAccountsAPI_CreateServiceAccount(t *testing.T) {
store := db.InitTestDB(t)
services := setupTestServices(t, store)
@@ -162,7 +170,7 @@ func TestServiceAccountsAPI_CreateServiceAccount(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
serviceAccountRequestScenario(t, http.MethodPost, serviceAccountPath, testUser, func(httpmethod string, endpoint string, usr *tests.TestUser) {
server, api := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), tc.acmock, store, services.SAStore)
server, api := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), tc.acmock, store)
marshalled, err := json.Marshal(tc.body)
require.NoError(t, err)
@@ -239,7 +247,7 @@ func TestServiceAccountsAPI_DeleteServiceAccount(t *testing.T) {
}
serviceAccountRequestScenario(t, http.MethodDelete, serviceAccountIDPath, &testcase.user, func(httpmethod string, endpoint string, user *tests.TestUser) {
createduser := tests.SetupUserServiceAccount(t, store, testcase.user)
server, _ := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), testcase.acmock, store, services.SAStore)
server, _ := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), testcase.acmock, store)
actual := requestResponse(server, httpmethod, fmt.Sprintf(endpoint, fmt.Sprint(createduser.ID))).Code
require.Equal(t, testcase.expectedCode, actual)
})
@@ -263,7 +271,7 @@ func TestServiceAccountsAPI_DeleteServiceAccount(t *testing.T) {
}
serviceAccountRequestScenario(t, http.MethodDelete, serviceAccountIDPath, &testcase.user, func(httpmethod string, endpoint string, user *tests.TestUser) {
createduser := tests.SetupUserServiceAccount(t, store, testcase.user)
server, _ := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), testcase.acmock, store, services.SAStore)
server, _ := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), testcase.acmock, store)
actual := requestResponse(server, httpmethod, fmt.Sprintf(endpoint, createduser.ID)).Code
require.Equal(t, testcase.expectedCode, actual)
})
@@ -275,21 +283,29 @@ func serviceAccountRequestScenario(t *testing.T, httpMethod string, endpoint str
fn(httpMethod, endpoint, user)
}
func setupTestServer(t *testing.T, svc *tests.ServiceAccountMock,
func setupTestServer(
t *testing.T,
svc *tests.ServiceAccountMock,
routerRegister routing.RouteRegister,
acmock *accesscontrolmock.Mock,
sqlStore db.DB, saStore serviceaccounts.Store) (*web.Mux, *ServiceAccountsAPI) {
sqlStore db.DB,
) (*web.Mux, *ServiceAccountsAPI) {
cfg := setting.NewCfg()
teamSvc := teamimpl.ProvideService(sqlStore, cfg)
userSvc, err := userimpl.ProvideService(sqlStore, nil, cfg, teamimpl.ProvideService(sqlStore, cfg), nil, quotatest.New(false, nil))
orgSvc, err := orgimpl.ProvideService(sqlStore, cfg, quotatest.New(false, nil))
require.NoError(t, err)
userSvc, err := userimpl.ProvideService(sqlStore, orgSvc, cfg, teamimpl.ProvideService(sqlStore, cfg), nil, quotatest.New(false, nil))
require.NoError(t, err)
// TODO: create fake for retriever to pass into the permissionservice
retrieverSvc := retriever.ProvideService(sqlStore, nil, nil, nil, nil)
saPermissionService, err := ossaccesscontrol.ProvideServiceAccountPermissions(
cfg, routing.NewRouteRegister(), sqlStore, acmock, &licensing.OSSLicensingService{}, saStore, acmock, teamSvc, userSvc)
cfg, routing.NewRouteRegister(), sqlStore, acmock, &licensing.OSSLicensingService{}, retrieverSvc, acmock, teamSvc, userSvc)
require.NoError(t, err)
acService := actest.FakeService{}
a := NewServiceAccountsAPI(cfg, svc, acmock, acService, routerRegister, saStore, saPermissionService)
a := NewServiceAccountsAPI(cfg, svc, acmock, acService, routerRegister, saPermissionService)
a.RegisterAPIEndpoints()
a.cfg.ApiKeyMaxSecondsToLive = -1 // disable api key expiration
@@ -317,6 +333,7 @@ func setupTestServer(t *testing.T, svc *tests.ServiceAccountMock,
func TestServiceAccountsAPI_RetrieveServiceAccount(t *testing.T) {
store := db.InitTestDB(t)
services := setupTestServices(t, store)
type testRetrieveSATestCase struct {
desc string
user *tests.TestUser
@@ -380,7 +397,7 @@ func TestServiceAccountsAPI_RetrieveServiceAccount(t *testing.T) {
createdUser := tests.SetupUserServiceAccount(t, store, *tc.user)
scopeID = int(createdUser.ID)
}
server, _ := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), tc.acmock, store, services.SAStore)
server, _ := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), tc.acmock, store)
actual := requestResponse(server, httpmethod, fmt.Sprintf(endpoint, scopeID))
@@ -406,6 +423,7 @@ func newString(s string) *string {
func TestServiceAccountsAPI_UpdateServiceAccount(t *testing.T) {
store := db.InitTestDB(t)
services := setupTestServices(t, store)
type testUpdateSATestCase struct {
desc string
user *tests.TestUser
@@ -498,7 +516,7 @@ func TestServiceAccountsAPI_UpdateServiceAccount(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
server, saAPI := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), tc.acmock, store, services.SAStore)
server, saAPI := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), tc.acmock, store)
scopeID := tc.Id
if tc.user != nil {
createdUser := tests.SetupUserServiceAccount(t, store, *tc.user)
@@ -528,7 +546,7 @@ func TestServiceAccountsAPI_UpdateServiceAccount(t *testing.T) {
assert.Equal(t, tc.user.Login, serviceAccountData["login"].(string))
// Ensure the user was updated in DB
sa, err := saAPI.store.RetrieveServiceAccount(context.Background(), 1, int64(scopeID))
sa, err := saAPI.service.RetrieveServiceAccount(context.Background(), 1, int64(scopeID))
require.NoError(t, err)
require.Equal(t, *tc.body.Name, sa.Name)
require.Equal(t, string(*tc.body.Role), sa.Role)
@@ -540,7 +558,6 @@ func TestServiceAccountsAPI_UpdateServiceAccount(t *testing.T) {
type services struct {
OrgService org.Service
UserService user.Service
SAStore serviceaccounts.Store
SAService tests.ServiceAccountMock
APIKeyService apikey.Service
}
@@ -555,13 +572,13 @@ func setupTestServices(t *testing.T, db *sqlstore.SQLStore) services {
require.NoError(t, err)
userSvc, err := userimpl.ProvideService(db, orgService, db.Cfg, nil, nil, quotaService)
require.NoError(t, err)
saStore := database.ProvideServiceAccountsStore(db, apiKeyService, kvStore, userSvc, orgService)
svcmock := tests.ServiceAccountMock{}
saStore := database.ProvideServiceAccountsStore(nil, db, apiKeyService, kvStore, userSvc, orgService)
svcmock := tests.ServiceAccountMock{Store: saStore, Calls: tests.Calls{}, Stats: nil, SecretScanEnabled: false}
return services{
OrgService: orgService,
UserService: userSvc,
SAStore: saStore,
SAService: svcmock,
APIKeyService: apiKeyService,
}

View File

@@ -72,7 +72,7 @@ func (api *ServiceAccountsAPI) ListTokens(ctx *models.ReqContext) response.Respo
return response.Error(http.StatusBadRequest, "Service Account ID is invalid", err)
}
saTokens, err := api.store.ListTokens(ctx.Req.Context(), &serviceaccounts.GetSATokensQuery{
saTokens, err := api.service.ListTokens(ctx.Req.Context(), &serviceaccounts.GetSATokensQuery{
OrgID: &ctx.OrgID,
ServiceAccountID: &saID,
})
@@ -134,7 +134,7 @@ func (api *ServiceAccountsAPI) CreateToken(c *models.ReqContext) response.Respon
}
// confirm service account exists
if _, err := api.store.RetrieveServiceAccount(c.Req.Context(), c.OrgID, saID); err != nil {
if _, err := api.service.RetrieveServiceAccount(c.Req.Context(), c.OrgID, saID); err != nil {
switch {
case errors.Is(err, serviceaccounts.ErrServiceAccountNotFound):
return response.Error(http.StatusNotFound, "Failed to retrieve service account", err)
@@ -175,7 +175,7 @@ func (api *ServiceAccountsAPI) CreateToken(c *models.ReqContext) response.Respon
cmd.Key = newKeyInfo.HashedKey
if err := api.store.AddServiceAccountToken(c.Req.Context(), saID, &cmd); err != nil {
if err := api.service.AddServiceAccountToken(c.Req.Context(), saID, &cmd); err != nil {
if errors.Is(err, database.ErrInvalidTokenExpiration) {
return response.Error(http.StatusBadRequest, err.Error(), nil)
}
@@ -217,7 +217,7 @@ func (api *ServiceAccountsAPI) DeleteToken(c *models.ReqContext) response.Respon
}
// confirm service account exists
if _, err := api.store.RetrieveServiceAccount(c.Req.Context(), c.OrgID, saID); err != nil {
if _, err := api.service.RetrieveServiceAccount(c.Req.Context(), c.OrgID, saID); err != nil {
switch {
case errors.Is(err, serviceaccounts.ErrServiceAccountNotFound):
return response.Error(http.StatusNotFound, "Failed to retrieve service account", err)
@@ -231,7 +231,7 @@ func (api *ServiceAccountsAPI) DeleteToken(c *models.ReqContext) response.Respon
return response.Error(http.StatusBadRequest, "Token ID is invalid", err)
}
if err = api.store.DeleteServiceAccountToken(c.Req.Context(), c.OrgID, saID, tokenID); err != nil {
if err = api.service.DeleteServiceAccountToken(c.Req.Context(), c.OrgID, saID, tokenID); err != nil {
status := http.StatusNotFound
if err != nil && !errors.Is(err, apikey.ErrNotFound) {
status = http.StatusInternalServerError

View File

@@ -32,7 +32,7 @@ const (
serviceaccountIDTokensDetailPath = "/api/serviceaccounts/%v/tokens/%v" // #nosec G101
)
func createTokenforSA(t *testing.T, store serviceaccounts.Store, keyName string, orgID int64, saID int64, secondsToLive int64) *apikey.APIKey {
func createTokenforSA(t *testing.T, service serviceaccounts.Service, keyName string, orgID int64, saID int64, secondsToLive int64) *apikey.APIKey {
key, err := apikeygen.New(orgID, keyName)
require.NoError(t, err)
@@ -44,7 +44,7 @@ func createTokenforSA(t *testing.T, store serviceaccounts.Store, keyName string,
Result: &apikey.APIKey{},
}
err = store.AddServiceAccountToken(context.Background(), saID, &cmd)
err = service.AddServiceAccountToken(context.Background(), saID, &cmd)
require.NoError(t, err)
return cmd.Result
}
@@ -131,7 +131,7 @@ func TestServiceAccountsAPI_CreateToken(t *testing.T) {
bodyString = string(b)
}
server, _ := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), tc.acmock, store, services.SAStore)
server, _ := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), tc.acmock, store)
actual := requestResponse(server, http.MethodPost, endpoint, strings.NewReader(bodyString))
actualCode := actual.Code
@@ -166,6 +166,7 @@ func TestServiceAccountsAPI_CreateToken(t *testing.T) {
func TestServiceAccountsAPI_DeleteToken(t *testing.T) {
store := db.InitTestDB(t)
services := setupTestServices(t, store)
sa := tests.SetupUserServiceAccount(t, store, tests.TestUser{Login: "sa", IsServiceAccount: true})
type testCreateSAToken struct {
@@ -225,11 +226,11 @@ func TestServiceAccountsAPI_DeleteToken(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
token := createTokenforSA(t, services.SAStore, tc.keyName, sa.OrgID, sa.ID, 1)
token := createTokenforSA(t, &services.SAService, tc.keyName, sa.OrgID, sa.ID, 1)
endpoint := fmt.Sprintf(serviceaccountIDTokensDetailPath, sa.ID, token.Id)
bodyString := ""
server, _ := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), tc.acmock, store, services.SAStore)
server, _ := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), tc.acmock, store)
actual := requestResponse(server, http.MethodDelete, endpoint, strings.NewReader(bodyString))
actualCode := actual.Code
@@ -249,20 +250,11 @@ func TestServiceAccountsAPI_DeleteToken(t *testing.T) {
}
}
type saStoreMockTokens struct {
serviceaccounts.Store
saAPIKeys []apikey.APIKey
}
func (s *saStoreMockTokens) ListTokens(ctx context.Context, query *serviceaccounts.GetSATokensQuery) ([]apikey.APIKey, error) {
return s.saAPIKeys, nil
}
func TestServiceAccountsAPI_ListTokens(t *testing.T) {
store := db.InitTestDB(t)
svcmock := tests.ServiceAccountMock{}
sa := tests.SetupUserServiceAccount(t, store, tests.TestUser{Login: "sa", IsServiceAccount: true})
services := setupTestServices(t, store)
sa := tests.SetupUserServiceAccount(t, store, tests.TestUser{Login: "sa", IsServiceAccount: true})
type testCreateSAToken struct {
desc string
tokens []apikey.APIKey
@@ -351,7 +343,8 @@ func TestServiceAccountsAPI_ListTokens(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
endpoint := fmt.Sprintf(serviceAccountIDPath+"/tokens", sa.ID)
server, _ := setupTestServer(t, &svcmock, routing.NewRouteRegister(), tc.acmock, store, &saStoreMockTokens{saAPIKeys: tc.tokens})
services.SAService.ExpectedTokens = tc.tokens
server, _ := setupTestServer(t, &services.SAService, routing.NewRouteRegister(), tc.acmock, store)
actual := requestResponse(server, http.MethodGet, endpoint, http.NoBody)
actualCode := actual.Code