Service Accounts: Display name to ID (#46258)

* ServiceAccounts: modernize SA creation interface

* ServiceAccounts: improve service account ID generation

* ServiceAccounts: remove unused method

* ServiceAccounts: Make SA ID display name dependent

* ServiceAccounts: Add tests for Service Account creation

* trim trailing whitespace

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

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>

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

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>
This commit is contained in:
J Guerreiro
2022-03-08 12:07:58 +01:00
committed by GitHub
co-authored by Ieva
parent 130ec748b9
commit 2aeae69a16
13 changed files with 187 additions and 66 deletions
@@ -3,11 +3,11 @@ package database
//nolint:goimports
import (
"context"
"errors"
"fmt"
"strings"
"time"
"github.com/google/uuid"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol"
@@ -28,19 +28,24 @@ func NewServiceAccountsStore(store *sqlstore.SQLStore) *ServiceAccountsStoreImpl
}
}
func (s *ServiceAccountsStoreImpl) CreateServiceAccount(ctx context.Context, sa *serviceaccounts.CreateServiceAccountForm) (saDTO *serviceaccounts.ServiceAccountDTO, err error) {
// create a new service account - "user" with empty permissions
generatedLogin := "Service-Account-" + uuid.New().String()
func (s *ServiceAccountsStoreImpl) CreateServiceAccount(ctx context.Context, orgID int64, name string) (saDTO *serviceaccounts.ServiceAccountDTO, err error) {
generatedLogin := "sa-" + strings.ToLower(name)
generatedLogin = strings.ReplaceAll(generatedLogin, " ", "-")
cmd := models.CreateUserCommand{
Login: generatedLogin,
Name: sa.Name,
OrgId: sa.OrgID,
OrgId: orgID,
Name: name,
IsServiceAccount: true,
}
newuser, err := s.sqlStore.CreateUser(ctx, cmd)
if err != nil {
return nil, fmt.Errorf("failed to create user: %v", err)
if errors.Is(err, models.ErrUserAlreadyExists) {
return nil, &ErrSAInvalidName{}
}
return nil, fmt.Errorf("failed to create service account: %w", err)
}
return &serviceaccounts.ServiceAccountDTO{
Id: newuser.Id,
Name: newuser.Name,
@@ -8,9 +8,33 @@ import (
"github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/serviceaccounts/tests"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestStore_CreateServiceAccount(t *testing.T) {
sqlStore, store := setupTestDatabase(t)
t.Run("create service account", func(t *testing.T) {
saDTO, err := store.CreateServiceAccount(context.Background(), 1, "new Service Account")
require.NoError(t, err)
assert.Equal(t, "sa-new-service-account", saDTO.Login)
assert.Equal(t, "new Service Account", saDTO.Name)
assert.Equal(t, 0, int(saDTO.Tokens))
query := models.GetUserByIdQuery{Id: saDTO.Id}
err = sqlStore.GetUserById(context.Background(), &query)
retrieved := query.Result
require.NoError(t, err)
assert.Equal(t, "sa-new-service-account", retrieved.Login)
assert.Equal(t, "new Service Account", retrieved.Name)
assert.Equal(t, "sa-new-service-account", retrieved.Email)
assert.Equal(t, "", retrieved.Password)
assert.Equal(t, 1, int(retrieved.OrgId))
assert.Len(t, retrieved.Salt, 10)
assert.Equal(t, true, retrieved.IsServiceAccount)
})
}
func TestStore_DeleteServiceAccount(t *testing.T) {
cases := []struct {
desc string
@@ -6,6 +6,17 @@ import (
"github.com/grafana/grafana/pkg/models"
)
type ErrSAInvalidName struct {
}
func (e *ErrSAInvalidName) Error() string {
return "service account name already in use"
}
func (e *ErrSAInvalidName) Unwrap() error {
return models.ErrUserAlreadyExists
}
type ErrMisingSAToken struct {
}