API keys: Remove state hideAPIkeys and refactor interface to IsDisabled (#64018)
* remove state and refactor interface to IsDisabled * update docs and span * Update pkg/services/apikey/apikey.go Co-authored-by: Alexander Zobnin <alexanderzobnin@gmail.com> --------- Co-authored-by: Alexander Zobnin <alexanderzobnin@gmail.com>
This commit is contained in:
co-authored by
Alexander Zobnin
parent
e6e8351ee9
commit
ad4b053231
@@ -7,11 +7,12 @@ import (
|
||||
type Service interface {
|
||||
GetAPIKeys(ctx context.Context, query *GetApiKeysQuery) error
|
||||
GetAllAPIKeys(ctx context.Context, orgID int64) ([]*APIKey, error)
|
||||
CountAPIKeys(ctx context.Context, orgID int64) (int64, error)
|
||||
DeleteApiKey(ctx context.Context, cmd *DeleteCommand) error
|
||||
AddAPIKey(ctx context.Context, cmd *AddCommand) error
|
||||
GetApiKeyById(ctx context.Context, query *GetByIDQuery) error
|
||||
GetApiKeyByName(ctx context.Context, query *GetByNameQuery) error
|
||||
GetAPIKeyByHash(ctx context.Context, hash string) (*APIKey, error)
|
||||
UpdateAPIKeyLastUsedDate(ctx context.Context, tokenID int64) error
|
||||
// IsDisabled returns true if the API key is not available for use.
|
||||
IsDisabled(ctx context.Context, orgID int64) (bool, error)
|
||||
}
|
||||
|
||||
@@ -68,8 +68,15 @@ func (s *Service) AddAPIKey(ctx context.Context, cmd *apikey.AddCommand) error {
|
||||
func (s *Service) UpdateAPIKeyLastUsedDate(ctx context.Context, tokenID int64) error {
|
||||
return s.store.UpdateAPIKeyLastUsedDate(ctx, tokenID)
|
||||
}
|
||||
func (s *Service) CountAPIKeys(ctx context.Context, orgID int64) (int64, error) {
|
||||
return s.store.CountAPIKeys(ctx, orgID)
|
||||
|
||||
// IsDisabled returns true if the apikey service is disabled for the given org.
|
||||
// This is the case if the org has no apikeys.
|
||||
func (s *Service) IsDisabled(ctx context.Context, orgID int64) (bool, error) {
|
||||
apikeys, err := s.store.CountAPIKeys(ctx, orgID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return apikeys == 0, nil
|
||||
}
|
||||
|
||||
func readQuotaConfig(cfg *setting.Cfg) (*quota.Map, error) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
type Service struct {
|
||||
ExpectedError error
|
||||
ExpectedCount int64
|
||||
ExpectedBool bool
|
||||
ExpectedAPIKeys []*apikey.APIKey
|
||||
ExpectedAPIKey *apikey.APIKey
|
||||
}
|
||||
@@ -20,9 +20,6 @@ func (s *Service) GetAPIKeys(ctx context.Context, query *apikey.GetApiKeysQuery)
|
||||
func (s *Service) GetAllAPIKeys(ctx context.Context, orgID int64) ([]*apikey.APIKey, error) {
|
||||
return s.ExpectedAPIKeys, s.ExpectedError
|
||||
}
|
||||
func (s *Service) CountAPIKeys(ctx context.Context, orgID int64) (int64, error) {
|
||||
return s.ExpectedCount, s.ExpectedError
|
||||
}
|
||||
func (s *Service) GetApiKeyById(ctx context.Context, query *apikey.GetByIDQuery) error {
|
||||
query.Result = s.ExpectedAPIKey
|
||||
return s.ExpectedError
|
||||
@@ -44,3 +41,6 @@ func (s *Service) AddAPIKey(ctx context.Context, cmd *apikey.AddCommand) error {
|
||||
func (s *Service) UpdateAPIKeyLastUsedDate(ctx context.Context, tokenID int64) error {
|
||||
return s.ExpectedError
|
||||
}
|
||||
func (s *Service) IsDisabled(ctx context.Context, orgID int64) (bool, error) {
|
||||
return s.ExpectedBool, s.ExpectedError
|
||||
}
|
||||
|
||||
@@ -79,15 +79,11 @@ func (s *ServiceImpl) getOrgAdminNode(c *contextmodel.ReqContext) (*navtree.NavL
|
||||
})
|
||||
}
|
||||
|
||||
hideApiKeys, _, _ := s.kvStore.Get(c.Req.Context(), c.OrgID, "serviceaccounts", "hideApiKeys")
|
||||
apiKeys, err := s.apiKeyService.CountAPIKeys(c.Req.Context(), c.OrgID)
|
||||
disabled, err := s.apiKeyService.IsDisabled(c.Req.Context(), c.OrgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Hide API keys if the global setting is set or if the org setting is set and there are no API keys
|
||||
apiKeysHidden := hideApiKeys == "1" && apiKeys == 0
|
||||
if hasAccess(ac.ReqOrgAdmin, ac.ApiKeyAccessEvaluator) && !apiKeysHidden {
|
||||
if hasAccess(ac.ReqOrgAdmin, ac.ApiKeyAccessEvaluator) && !disabled {
|
||||
configNodes = append(configNodes, &navtree.NavLink{
|
||||
Text: "API keys",
|
||||
Id: "apikeys",
|
||||
|
||||
@@ -40,7 +40,6 @@ type service interface {
|
||||
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
|
||||
HideApiKeysTab(ctx context.Context, orgID int64) error
|
||||
MigrateApiKeysToServiceAccounts(ctx context.Context, orgID int64) error
|
||||
MigrateApiKey(ctx context.Context, orgID int64, keyId int64) error
|
||||
// Service account tokens
|
||||
@@ -86,8 +85,6 @@ func (api *ServiceAccountsAPI) RegisterAPIEndpoints() {
|
||||
accesscontrol.EvalPermission(serviceaccounts.ActionWrite, serviceaccounts.ScopeID)), routing.Wrap(api.CreateToken))
|
||||
serviceAccountsRoute.Delete("/:serviceAccountId/tokens/:tokenId", auth(middleware.ReqOrgAdmin,
|
||||
accesscontrol.EvalPermission(serviceaccounts.ActionWrite, serviceaccounts.ScopeID)), routing.Wrap(api.DeleteToken))
|
||||
serviceAccountsRoute.Post("/hideApiKeys", auth(middleware.ReqOrgAdmin,
|
||||
accesscontrol.EvalPermission(serviceaccounts.ActionCreate)), routing.Wrap(api.HideApiKeysTab))
|
||||
serviceAccountsRoute.Post("/migrate", auth(middleware.ReqOrgAdmin,
|
||||
accesscontrol.EvalPermission(serviceaccounts.ActionCreate)), routing.Wrap(api.MigrateApiKeysToServiceAccounts))
|
||||
serviceAccountsRoute.Post("/migrate/:keyId", auth(middleware.ReqOrgAdmin,
|
||||
@@ -357,14 +354,6 @@ func (api *ServiceAccountsAPI) SearchOrgServiceAccountsWithPaging(c *contextmode
|
||||
return response.JSON(http.StatusOK, serviceAccountSearch)
|
||||
}
|
||||
|
||||
// POST /api/serviceaccounts/hideapikeys
|
||||
func (api *ServiceAccountsAPI) HideApiKeysTab(ctx *contextmodel.ReqContext) response.Response {
|
||||
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")
|
||||
}
|
||||
|
||||
// POST /api/serviceaccounts/migrate
|
||||
func (api *ServiceAccountsAPI) MigrateApiKeysToServiceAccounts(ctx *contextmodel.ReqContext) response.Response {
|
||||
if err := api.service.MigrateApiKeysToServiceAccounts(ctx.Req.Context(), ctx.OrgID); err != nil {
|
||||
|
||||
@@ -364,13 +364,6 @@ func (s *ServiceAccountsStoreImpl) SearchOrgServiceAccounts(ctx context.Context,
|
||||
return searchResult, nil
|
||||
}
|
||||
|
||||
func (s *ServiceAccountsStoreImpl) HideApiKeysTab(ctx context.Context, orgId int64) error {
|
||||
if err := s.kvStore.Set(ctx, orgId, "serviceaccounts", "hideApiKeys", "1"); err != nil {
|
||||
s.log.Error("Failed to hide API keys tab", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ServiceAccountsStoreImpl) MigrateApiKeysToServiceAccounts(ctx context.Context, orgId int64) error {
|
||||
basicKeys, err := s.apiKeyService.GetAllAPIKeys(ctx, orgId)
|
||||
if err != nil {
|
||||
|
||||
@@ -226,13 +226,6 @@ func (sa *ServiceAccountsService) DeleteServiceAccountToken(ctx context.Context,
|
||||
return sa.store.DeleteServiceAccountToken(ctx, orgID, serviceAccountID, tokenID)
|
||||
}
|
||||
|
||||
func (sa *ServiceAccountsService) HideApiKeysTab(ctx context.Context, orgID int64) error {
|
||||
if err := validOrgID(orgID); err != nil {
|
||||
return err
|
||||
}
|
||||
return sa.store.HideApiKeysTab(ctx, orgID)
|
||||
}
|
||||
|
||||
func (sa *ServiceAccountsService) MigrateApiKey(ctx context.Context, orgID, keyID int64) error {
|
||||
if err := validOrgID(orgID); err != nil {
|
||||
return err
|
||||
|
||||
@@ -59,11 +59,6 @@ func (f *FakeServiceAccountStore) DeleteServiceAccount(ctx context.Context, orgI
|
||||
return f.ExpectedError
|
||||
}
|
||||
|
||||
// HideApiKeysTab is a fake hiding the api keys tab.
|
||||
func (f *FakeServiceAccountStore) HideApiKeysTab(ctx context.Context, orgID int64) error {
|
||||
return f.ExpectedError
|
||||
}
|
||||
|
||||
// MigrateApiKeysToServiceAccounts is a fake migrating api keys to service accounts.
|
||||
func (f *FakeServiceAccountStore) MigrateApiKeysToServiceAccounts(ctx context.Context, orgID int64) error {
|
||||
return f.ExpectedError
|
||||
|
||||
@@ -7,17 +7,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/serviceaccounts"
|
||||
)
|
||||
|
||||
/*
|
||||
Store is the database store for service accounts.
|
||||
|
||||
migration from apikeys to service accounts:
|
||||
HideApiKeyTab is used to hide the api key tab in the UI.
|
||||
MigrateApiKeysToServiceAccounts migrates all API keys to service accounts.
|
||||
MigrateApiKey migrates a single API key to a service account.
|
||||
|
||||
// only used for interal api calls
|
||||
RevertApiKey reverts a single service account to an API key.
|
||||
*/
|
||||
type store interface {
|
||||
CreateServiceAccount(ctx context.Context, orgID int64, saForm *serviceaccounts.CreateServiceAccountForm) (*serviceaccounts.ServiceAccountDTO, error)
|
||||
SearchOrgServiceAccounts(ctx context.Context, query *serviceaccounts.SearchOrgServiceAccountsQuery) (*serviceaccounts.SearchOrgServiceAccountsResult, error)
|
||||
@@ -26,7 +15,6 @@ type store interface {
|
||||
RetrieveServiceAccount(ctx context.Context, orgID, serviceAccountID int64) (*serviceaccounts.ServiceAccountProfileDTO, error)
|
||||
RetrieveServiceAccountIdByName(ctx context.Context, orgID int64, name string) (int64, error)
|
||||
DeleteServiceAccount(ctx context.Context, orgID, serviceAccountID int64) error
|
||||
HideApiKeysTab(ctx context.Context, orgID int64) error
|
||||
MigrateApiKeysToServiceAccounts(ctx context.Context, orgID int64) error
|
||||
MigrateApiKey(ctx context.Context, orgID int64, keyId int64) error
|
||||
ListTokens(ctx context.Context, query *serviceaccounts.GetSATokensQuery) ([]apikey.APIKey, error)
|
||||
|
||||
Reference in New Issue
Block a user