Searchable service accounts (#45844)

* WIP

* draft of WIP

* feat: search and filtering works 🌈

* Update pkg/models/org_user.go

* Apply suggestions from code review

* refactor: remove unsed function

* refactor: formatting

* Apply suggestions from code review

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

* WIP

* comment

* Update public/app/features/serviceaccounts/ServiceAccountsListPage.tsx

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

* review comments

* wip

* working search and initial load of service accounts

* number of tokens working

* removed api call

* Apply suggestions from code review

* added accescontrol param

* accesscontrol prefix corrected

Co-authored-by: J Guerreiro <joao.guerreiro@grafana.com>
Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com>
This commit is contained in:
Eric Leijonmarck
2022-03-04 12:04:07 +01:00
committed by GitHub
co-authored by J Guerreiro Alex Khomenko
parent 45e4611807
commit 3d168eb34b
10 changed files with 354 additions and 90 deletions
@@ -10,6 +10,8 @@ import (
"github.com/google/uuid"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/sqlstore"
"xorm.io/xorm"
@@ -291,6 +293,85 @@ func (s *ServiceAccountsStoreImpl) UpdateServiceAccount(ctx context.Context,
return updatedUser, err
}
func (s *ServiceAccountsStoreImpl) SearchOrgServiceAccounts(ctx context.Context, query *models.SearchOrgUsersQuery) ([]*serviceaccounts.ServiceAccountDTO, error) {
query.IsServiceAccount = true
serviceAccounts := make([]*serviceaccounts.ServiceAccountDTO, 0)
err := s.sqlStore.WithDbSession(ctx, func(dbSession *sqlstore.DBSession) error {
sess := dbSession.Table("org_user")
sess.Join("INNER", s.sqlStore.Dialect.Quote("user"), fmt.Sprintf("org_user.user_id=%s.id", s.sqlStore.Dialect.Quote("user")))
whereConditions := make([]string, 0)
whereParams := make([]interface{}, 0)
whereConditions = append(whereConditions, "org_user.org_id = ?")
whereParams = append(whereParams, query.OrgID)
// TODO: add to chore, for cleaning up after we have created
// service accounts table in the modelling
whereConditions = append(whereConditions, fmt.Sprintf("%s.is_service_account = %t", s.sqlStore.Dialect.Quote("user"), query.IsServiceAccount))
if s.sqlStore.Cfg.IsFeatureToggleEnabled(featuremgmt.FlagAccesscontrol) {
acFilter, err := accesscontrol.Filter(ctx, "org_user.user_id", "serviceaccounts", "serviceaccounts:read", query.User)
if err != nil {
return err
}
whereConditions = append(whereConditions, acFilter.Where)
whereParams = append(whereParams, acFilter.Args...)
}
if query.Query != "" {
queryWithWildcards := "%" + query.Query + "%"
whereConditions = append(whereConditions, "(email "+s.sqlStore.Dialect.LikeStr()+" ? OR name "+s.sqlStore.Dialect.LikeStr()+" ? OR login "+s.sqlStore.Dialect.LikeStr()+" ?)")
whereParams = append(whereParams, queryWithWildcards, queryWithWildcards, queryWithWildcards)
}
if len(whereConditions) > 0 {
sess.Where(strings.Join(whereConditions, " AND "), whereParams...)
}
if query.Limit > 0 {
offset := query.Limit * (query.Page - 1)
sess.Limit(query.Limit, offset)
}
sess.Cols(
"org_user.user_id",
"org_user.org_id",
"org_user.role",
"user.email",
"user.name",
"user.login",
"user.last_seen_at",
)
sess.Asc("user.email", "user.login")
if err := sess.Find(&serviceAccounts); err != nil {
return err
}
// get total
serviceaccount := serviceaccounts.ServiceAccountDTO{}
countSess := dbSession.Table("org_user")
sess.Join("INNER", s.sqlStore.Dialect.Quote("user"), fmt.Sprintf("org_user.user_id=%s.id", s.sqlStore.Dialect.Quote("user")))
if len(whereConditions) > 0 {
countSess.Where(strings.Join(whereConditions, " AND "), whereParams...)
}
count, err := countSess.Count(&serviceaccount)
if err != nil {
return err
}
query.Result.TotalCount = count
return nil
})
if err != nil {
return nil, err
}
return serviceAccounts, nil
}
func contains(s []int64, e int64) bool {
for _, a := range s {
if a == e {