ServiceAccounts: refactor UI (#49508)

* ServiceAccounts: refactor ServiceAccountRoleRow

* Refactor ServiceAccountRoleRow

* Refactor ServiceAccountProfile

* Refactor components

* Change service accounts icon

* Refine service accounts page header

* Improve service accounts filtering

* Change delete button style

* Tweak account id

* Auto focus name field when create service account

* Add disable/enable button

* Enable/disable service accounts

* Optimize updating service account (do not fetch all)

* Remove status column (replace by enable/disable button)

* Add banner with service accounts description

* Add tokens from main page

* Update tokens count when add token from main page

* Fix action buttons column

* Fix tokens count when change role

* Refine table row classes

* Fix buttons

* Simplify working with state

* Show message when service account updated

* Able to filter disabled accounts

* Mark disabled accounts in a table

* Refine disabled account view

* Move non-critical components to separate folder

* Remove confusing focusing

* Fix date picker position when creating new token

* DatePicker: able to set minimum date that can be selected

* Don't allow to select expiration dates prior today

* Set tomorrow as a default token expiration date

* Fix displaying expiration period

* Rename Add token button

* Refine page styles

* Show modal when disabling SA from main page

* Arrange role picker

* Refine SA page styles

* Generate default token name

* More smooth navigation between SA pages

* Stop loading indicator in case of error

* Remove legacy styles usage

* Tweaks after code review

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>

* Get rid of useDisapatch in favor of mapDispatchToProps

* Tests for ServiceAccountsListPage

* Tests for service account page

* Show new role picker only with license

* Get rid of deprecated css classes

* Apply suggestion from code review

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>

* Fix service accounts icon

* Tests for service account create page

* Return service account info when update

* Add behaviour tests for ServiceAccountsListPage

* Fix disabled cursor on confirm button

* More behavior tests for service account page

* Temporary disable service account migration banner

* Use safe where condition

Co-authored-by: Jguer <joao.guerreiro@grafana.com>

* Apply review suggestions

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>

* Remove autofocus from search

Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
Co-authored-by: Jguer <joao.guerreiro@grafana.com>
This commit is contained in:
Alexander Zobnin
2022-06-01 10:35:16 +03:00
committed by GitHub
parent 0d7a3209e7
commit 50538d5309
26 changed files with 1468 additions and 770 deletions

View File

@@ -16,6 +16,7 @@ import (
"github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/serviceaccounts/database"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/web"
)
@@ -169,6 +170,13 @@ func (api *ServiceAccountsAPI) RetrieveServiceAccount(ctx *models.ReqContext) re
metadata := api.getAccessControlMetadata(ctx, map[string]bool{saIDString: true})
serviceAccount.AvatarUrl = dtos.GetGravatarUrlWithDefault("", serviceAccount.Name)
serviceAccount.AccessControl = metadata[saIDString]
tokens, err := api.store.ListTokens(ctx.Req.Context(), serviceAccount.OrgId, serviceAccount.Id)
if err != nil {
api.log.Warn("Failed to list tokens for service account", "serviceAccount", serviceAccount.Id)
}
serviceAccount.Tokens = int64(len(tokens))
return response.JSON(http.StatusOK, serviceAccount)
}
@@ -205,7 +213,12 @@ func (api *ServiceAccountsAPI) updateServiceAccount(c *models.ReqContext) respon
resp.AvatarUrl = dtos.GetGravatarUrlWithDefault("", resp.Name)
resp.AccessControl = metadata[saIDString]
return response.JSON(http.StatusOK, resp)
return response.JSON(http.StatusOK, util.DynMap{
"message": "Service account updated",
"id": resp.Id,
"name": resp.Name,
"serviceaccount": resp,
})
}
// SearchOrgServiceAccountsWithPaging is an HTTP handler to search for org users with paging.
@@ -222,10 +235,14 @@ func (api *ServiceAccountsAPI) SearchOrgServiceAccountsWithPaging(c *models.ReqC
}
// its okay that it fails, it is only filtering that might be weird, but to safe quard against any weird incoming query param
onlyWithExpiredTokens := c.QueryBool("expiredTokens")
onlyDisabled := c.QueryBool("disabled")
filter := serviceaccounts.FilterIncludeAll
if onlyWithExpiredTokens {
filter = serviceaccounts.FilterOnlyExpiredTokens
}
if onlyDisabled {
filter = serviceaccounts.FilterOnlyDisabled
}
serviceAccountSearch, err := api.store.SearchOrgServiceAccounts(ctx, c.OrgId, c.Query("query"), filter, page, perPage, c.SignedInUser)
if err != nil {
return response.Error(http.StatusInternalServerError, "Failed to get service accounts for current organization", err)

View File

@@ -452,9 +452,10 @@ func TestServiceAccountsAPI_UpdateServiceAccount(t *testing.T) {
err := json.Unmarshal(actual.Body.Bytes(), &actualBody)
require.NoError(t, err)
assert.Equal(t, scopeID, int(actualBody["id"].(float64)))
assert.Equal(t, string(*tc.body.Role), actualBody["role"].(string))
assert.Equal(t, *tc.body.Name, actualBody["name"].(string))
assert.Equal(t, tc.user.Login, actualBody["login"].(string))
serviceAccountData := actualBody["serviceaccount"].(map[string]interface{})
assert.Equal(t, string(*tc.body.Role), serviceAccountData["role"].(string))
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))

View File

@@ -378,6 +378,11 @@ func (s *ServiceAccountsStoreImpl) SearchOrgServiceAccounts(
whereConditions,
"(SELECT count(*) FROM api_key WHERE api_key.service_account_id = org_user.user_id AND api_key.expires < ?) > 0")
whereParams = append(whereParams, now)
case serviceaccounts.FilterOnlyDisabled:
whereConditions = append(
whereConditions,
"is_disabled = ?")
whereParams = append(whereParams, s.sqlStore.Dialect.BooleanStr(true))
default:
s.log.Warn("invalid filter user for service account filtering", "service account search filtering", filter)
}

View File

@@ -67,6 +67,7 @@ type ServiceAccountProfileDTO struct {
AvatarUrl string `json:"avatarUrl" xorm:"-"`
Role string `json:"role" xorm:"role"`
Teams []string `json:"teams" xorm:"-"`
Tokens int64 `json:"tokens,omitempty"`
AccessControl map[string]bool `json:"accessControl,omitempty" xorm:"-"`
}
@@ -74,5 +75,6 @@ type ServiceAccountFilter string // used for filtering
const (
FilterOnlyExpiredTokens ServiceAccountFilter = "expiredTokens"
FilterOnlyDisabled ServiceAccountFilter = "disabled"
FilterIncludeAll ServiceAccountFilter = "all"
)