mirror of https://github.com/harness/drone.git
feat: [CODE-1805]: Add service account rule bypass list support (#3297)
* Make service account store code more consistent * Merge remote-tracking branch 'origin/main' into dd/service-account-bypass * Merge remote-tracking branch 'origin/main' into dd/service-account-bypass * Merge remote-tracking branch 'origin/main' into dd/service-account-bypass * Remove principal controller interface * Address review comments * Merge remote-tracking branch 'origin/main' into dd/service-account-bypass * Merge remote-tracking branch 'origin/main' into dd/service-account-bypass * Add pagination to repo/space list service account * Revert to non embedded Principal to ServiceAccount * Merge remote-tracking branch 'origin/main' into dd/service-account-bypass * Add query param to service account list * Add inherited param to principal filter * Merge remote-tracking branch 'origin/main' into akp/CODE-1805 * Merge remote-tracking branch 'origin/main' into akp/CODE-1805 * Return service account info instead of vanilla service account * Return principal info to return id instead opull/3616/head
parent
9224727874
commit
2f9d9583e6
|
@ -19,13 +19,13 @@ import (
|
|||
"github.com/harness/gitness/app/store"
|
||||
)
|
||||
|
||||
type controller struct {
|
||||
type Controller struct {
|
||||
principalStore store.PrincipalStore
|
||||
authorizer authz.Authorizer
|
||||
}
|
||||
|
||||
func newController(principalStore store.PrincipalStore, authorizer authz.Authorizer) *controller {
|
||||
return &controller{
|
||||
func newController(principalStore store.PrincipalStore, authorizer authz.Authorizer) Controller {
|
||||
return Controller{
|
||||
principalStore: principalStore,
|
||||
authorizer: authorizer,
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ import (
|
|||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
func (c controller) Find(
|
||||
func (c Controller) Find(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
principalID int64,
|
||||
|
|
|
@ -26,7 +26,7 @@ import (
|
|||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
func (c controller) CheckExistenceByEmails(
|
||||
func (c Controller) CheckExistenceByEmails(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
in *CheckUsersInput,
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package principal
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
)
|
||||
|
||||
// Controller interface provides an abstraction that allows to have different implementations of
|
||||
// principal related information.
|
||||
type Controller interface {
|
||||
// List lists the principals based on the provided filter.
|
||||
List(ctx context.Context, session *auth.Session, opts *types.PrincipalFilter) ([]*types.PrincipalInfo, error)
|
||||
Find(ctx context.Context, session *auth.Session, principalID int64) (*types.PrincipalInfo, error)
|
||||
CheckExistenceByEmails(ctx context.Context, session *auth.Session, input *CheckUsersInput) (*CheckUsersOutput, error)
|
||||
}
|
|
@ -27,7 +27,7 @@ import (
|
|||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
func (c controller) List(
|
||||
func (c Controller) List(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
opts *types.PrincipalFilter,
|
|
@ -26,6 +26,9 @@ var WireSet = wire.NewSet(
|
|||
ProvideController,
|
||||
)
|
||||
|
||||
func ProvideController(principalStore store.PrincipalStore, authorizer authz.Authorizer) Controller {
|
||||
func ProvideController(
|
||||
principalStore store.PrincipalStore,
|
||||
authorizer authz.Authorizer,
|
||||
) Controller {
|
||||
return newController(principalStore, authorizer)
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/store/database/dbtx"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
@ -28,7 +29,9 @@ func (c *Controller) ListServiceAccounts(
|
|||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
) ([]*types.ServiceAccount, error) {
|
||||
inherited bool,
|
||||
opts *types.PrincipalFilter,
|
||||
) ([]*types.ServiceAccountInfo, int64, error) {
|
||||
repo, err := GetRepoCheckServiceAccountAccess(
|
||||
ctx,
|
||||
session,
|
||||
|
@ -39,8 +42,61 @@ func (c *Controller) ListServiceAccounts(
|
|||
c.repoStore,
|
||||
c.spaceStore)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("access check failed: %w", err)
|
||||
return nil, 0, fmt.Errorf("access check failed: %w", err)
|
||||
}
|
||||
|
||||
return c.principalStore.ListServiceAccounts(ctx, enum.ParentResourceTypeRepo, repo.ID)
|
||||
repoParentInfo := &types.ServiceAccountParentInfo{
|
||||
ID: repo.ID,
|
||||
Type: enum.ParentResourceTypeRepo,
|
||||
}
|
||||
var parentInfos []*types.ServiceAccountParentInfo
|
||||
if inherited {
|
||||
ancestorIDs, err := c.spaceStore.GetAncestorIDs(ctx, repo.ParentID)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to get parent space ids: %w", err)
|
||||
}
|
||||
|
||||
parentInfos = make([]*types.ServiceAccountParentInfo, len(ancestorIDs)+1)
|
||||
for i := range ancestorIDs {
|
||||
parentInfos[i] = &types.ServiceAccountParentInfo{
|
||||
Type: enum.ParentResourceTypeSpace,
|
||||
ID: ancestorIDs[i],
|
||||
}
|
||||
}
|
||||
parentInfos[len(parentInfos)-1] = repoParentInfo
|
||||
} else {
|
||||
parentInfos = make([]*types.ServiceAccountParentInfo, 1)
|
||||
parentInfos[0] = repoParentInfo
|
||||
}
|
||||
|
||||
var accounts []*types.ServiceAccount
|
||||
var count int64
|
||||
err = c.tx.WithTx(ctx, func(ctx context.Context) error {
|
||||
accounts, err = c.principalStore.ListServiceAccounts(ctx, parentInfos, opts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list service accounts: %w", err)
|
||||
}
|
||||
|
||||
if opts.Page == 1 && len(accounts) < opts.Size {
|
||||
count = int64(len(accounts))
|
||||
return nil
|
||||
}
|
||||
|
||||
count, err = c.principalStore.CountServiceAccounts(ctx, parentInfos, opts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to count pull requests: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}, dbtx.TxDefaultReadOnly)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
infos := make([]*types.ServiceAccountInfo, len(accounts))
|
||||
for i := range accounts {
|
||||
infos[i] = accounts[i].ToServiceAccountInfo()
|
||||
}
|
||||
|
||||
return infos, count, nil
|
||||
}
|
||||
|
|
|
@ -80,8 +80,9 @@ func (c *Controller) CreateNoAuth(ctx context.Context,
|
|||
Salt: uniuri.NewLen(uniuri.UUIDLen),
|
||||
Created: time.Now().UnixMilli(),
|
||||
Updated: time.Now().UnixMilli(),
|
||||
ParentType: in.ParentType,
|
||||
ParentID: in.ParentID,
|
||||
|
||||
ParentType: in.ParentType,
|
||||
ParentID: in.ParentID,
|
||||
}
|
||||
|
||||
err := c.principalStore.CreateServiceAccount(ctx, sa)
|
||||
|
|
|
@ -24,8 +24,11 @@ import (
|
|||
)
|
||||
|
||||
// Find tries to find the provided service account.
|
||||
func (c *Controller) Find(ctx context.Context, session *auth.Session,
|
||||
saUID string) (*types.ServiceAccount, error) {
|
||||
func (c *Controller) Find(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
saUID string,
|
||||
) (*types.ServiceAccount, error) {
|
||||
sa, err := c.FindNoAuth(ctx, saUID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -16,9 +16,11 @@ package space
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
apiauth "github.com/harness/gitness/app/api/auth"
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/store/database/dbtx"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
@ -28,10 +30,12 @@ func (c *Controller) ListServiceAccounts(
|
|||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
spaceRef string,
|
||||
) ([]*types.ServiceAccount, error) {
|
||||
inherited bool,
|
||||
opts *types.PrincipalFilter,
|
||||
) ([]*types.ServiceAccountInfo, int64, error) {
|
||||
space, err := c.spaceCache.Get(ctx, spaceRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if err = apiauth.CheckServiceAccount(
|
||||
|
@ -45,8 +49,56 @@ func (c *Controller) ListServiceAccounts(
|
|||
"",
|
||||
enum.PermissionServiceAccountView,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return c.principalStore.ListServiceAccounts(ctx, enum.ParentResourceTypeSpace, space.ID)
|
||||
var parentInfos []*types.ServiceAccountParentInfo
|
||||
if inherited {
|
||||
ancestorIDs, err := c.spaceStore.GetAncestorIDs(ctx, space.ID)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to get parent space ids: %w", err)
|
||||
}
|
||||
|
||||
parentInfos = make([]*types.ServiceAccountParentInfo, len(ancestorIDs))
|
||||
for i := range ancestorIDs {
|
||||
parentInfos[i] = &types.ServiceAccountParentInfo{
|
||||
Type: enum.ParentResourceTypeSpace,
|
||||
ID: ancestorIDs[i],
|
||||
}
|
||||
}
|
||||
} else {
|
||||
parentInfos = make([]*types.ServiceAccountParentInfo, 1)
|
||||
parentInfos[0] = &types.ServiceAccountParentInfo{
|
||||
Type: enum.ParentResourceTypeSpace,
|
||||
ID: space.ID,
|
||||
}
|
||||
}
|
||||
|
||||
var accounts []*types.ServiceAccount
|
||||
var count int64
|
||||
err = c.tx.WithTx(ctx, func(ctx context.Context) error {
|
||||
accounts, err = c.principalStore.ListServiceAccounts(ctx, parentInfos, opts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list service accounts: %w", err)
|
||||
}
|
||||
|
||||
if opts.Page == 1 && len(accounts) < opts.Size {
|
||||
count = int64(len(accounts))
|
||||
return nil
|
||||
}
|
||||
|
||||
count, err = c.principalStore.CountServiceAccounts(ctx, parentInfos, opts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to count pull requests: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}, dbtx.TxDefaultReadOnly)
|
||||
|
||||
infos := make([]*types.ServiceAccountInfo, len(accounts))
|
||||
for i := range accounts {
|
||||
infos[i] = accounts[i].ToServiceAccountInfo()
|
||||
}
|
||||
|
||||
return infos, count, nil
|
||||
}
|
||||
|
|
|
@ -27,7 +27,9 @@ func HandleList(principalCtrl principal.Controller) http.HandlerFunc {
|
|||
ctx := r.Context()
|
||||
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
principalFilter := request.ParsePrincipalFilter(r)
|
||||
|
||||
principalInfos, err := principalCtrl.List(ctx, session, principalFilter)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
|
@ -35,13 +35,23 @@ func HandleListServiceAccounts(repoCtrl *repo.Controller) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
sas, err := repoCtrl.ListServiceAccounts(ctx, session, repoRef)
|
||||
filter := request.ParsePrincipalFilter(r)
|
||||
|
||||
inherited, err := request.ParseInheritedFromQuery(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: implement pagination - or should we block that many service accounts in the first place.
|
||||
render.JSON(w, http.StatusOK, sas)
|
||||
serviceAccountInfos, count, err := repoCtrl.ListServiceAccounts(
|
||||
ctx, session, repoRef, inherited, filter,
|
||||
)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Pagination(r, w, filter.Page, filter.Size, int(count))
|
||||
render.JSON(w, http.StatusOK, serviceAccountInfos)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,13 +33,23 @@ func HandleListServiceAccounts(spaceCtrl *space.Controller) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
sas, err := spaceCtrl.ListServiceAccounts(ctx, session, spaceRef)
|
||||
filter := request.ParsePrincipalFilter(r)
|
||||
|
||||
inherited, err := request.ParseInheritedFromQuery(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: do we need pagination? we should block that many service accounts in the first place.
|
||||
render.JSON(w, http.StatusOK, sas)
|
||||
serviceAccountInfos, count, err := spaceCtrl.ListServiceAccounts(
|
||||
ctx, session, spaceRef, inherited, filter,
|
||||
)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Pagination(r, w, filter.Page, filter.Size, int(count))
|
||||
render.JSON(w, http.StatusOK, serviceAccountInfos)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,6 +85,8 @@ type (
|
|||
// FindServiceAccountByUID finds the service account by uid.
|
||||
FindServiceAccountByUID(ctx context.Context, uid string) (*types.ServiceAccount, error)
|
||||
|
||||
FindManyServiceAccountByUID(ctx context.Context, uid []string) ([]*types.ServiceAccount, error)
|
||||
|
||||
// CreateServiceAccount saves the service account.
|
||||
CreateServiceAccount(ctx context.Context, sa *types.ServiceAccount) error
|
||||
|
||||
|
@ -97,13 +99,15 @@ type (
|
|||
// ListServiceAccounts returns a list of service accounts for a specific parent.
|
||||
ListServiceAccounts(
|
||||
ctx context.Context,
|
||||
parentType enum.ParentResourceType, parentID int64,
|
||||
parentInfos []*types.ServiceAccountParentInfo,
|
||||
opts *types.PrincipalFilter,
|
||||
) ([]*types.ServiceAccount, error)
|
||||
|
||||
// CountServiceAccounts returns a count of service accounts for a specific parent.
|
||||
CountServiceAccounts(
|
||||
ctx context.Context,
|
||||
parentType enum.ParentResourceType, parentID int64,
|
||||
parentInfos []*types.ServiceAccountParentInfo,
|
||||
opts *types.PrincipalFilter,
|
||||
) (int64, error)
|
||||
|
||||
/*
|
||||
|
@ -185,6 +189,7 @@ type (
|
|||
GetRootSpace(ctx context.Context, spaceID int64) (*types.Space, error)
|
||||
|
||||
// GetAncestorIDs returns a list of all space IDs along the recursive path to the root space.
|
||||
// NB: it returns also the spaceID itself in the []int64 slice.
|
||||
GetAncestorIDs(ctx context.Context, spaceID int64) ([]int64, error)
|
||||
|
||||
// GetTreeLevel returns the level of a space in a space tree.
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
|
@ -79,6 +80,40 @@ func (s *PrincipalStore) FindServiceAccountByUID(ctx context.Context, uid string
|
|||
return s.mapDBServiceAccount(dst), nil
|
||||
}
|
||||
|
||||
func (s *PrincipalStore) FindManyServiceAccountByUID(
|
||||
ctx context.Context,
|
||||
uids []string,
|
||||
) ([]*types.ServiceAccount, error) {
|
||||
uniqueUIDs := make([]string, len(uids))
|
||||
var err error
|
||||
for i, uid := range uids {
|
||||
uniqueUIDs[i], err = s.uidTransformation(uid)
|
||||
if err != nil {
|
||||
log.Ctx(ctx).Debug().Msgf("failed to transform uid '%s': %s", uid, err.Error())
|
||||
return nil, gitness_store.ErrResourceNotFound
|
||||
}
|
||||
}
|
||||
|
||||
stmt := database.Builder.
|
||||
Select(serviceAccountColumns).
|
||||
From("principals").
|
||||
Where("principal_type = ?", enum.PrincipalTypeServiceAccount).
|
||||
Where(squirrel.Eq{"principal_uid_unique": uniqueUIDs})
|
||||
db := dbtx.GetAccessor(ctx, s.db)
|
||||
|
||||
sqlQuery, params, err := stmt.ToSql()
|
||||
if err != nil {
|
||||
return nil, database.ProcessSQLErrorf(ctx, err, "failed to generate find many service accounts query")
|
||||
}
|
||||
|
||||
dst := []*serviceAccount{}
|
||||
if err := db.SelectContext(ctx, &dst, sqlQuery, params...); err != nil {
|
||||
return nil, database.ProcessSQLErrorf(ctx, err, "find many service accounts failed")
|
||||
}
|
||||
|
||||
return s.mapDBServiceAccounts(dst), nil
|
||||
}
|
||||
|
||||
// CreateServiceAccount saves the service account.
|
||||
func (s *PrincipalStore) CreateServiceAccount(ctx context.Context, sa *types.ServiceAccount) error {
|
||||
const sqlQuery = `
|
||||
|
@ -178,17 +213,39 @@ func (s *PrincipalStore) DeleteServiceAccount(ctx context.Context, id int64) err
|
|||
}
|
||||
|
||||
// ListServiceAccounts returns a list of service accounts for a specific parent.
|
||||
func (s *PrincipalStore) ListServiceAccounts(ctx context.Context, parentType enum.ParentResourceType,
|
||||
parentID int64) ([]*types.ServiceAccount, error) {
|
||||
const sqlQuery = serviceAccountSelectBase + `
|
||||
WHERE principal_type = 'serviceaccount' AND principal_sa_parent_type = $1 AND principal_sa_parent_id = $2
|
||||
ORDER BY principal_uid ASC`
|
||||
func (s *PrincipalStore) ListServiceAccounts(
|
||||
ctx context.Context,
|
||||
parentInfos []*types.ServiceAccountParentInfo,
|
||||
opts *types.PrincipalFilter,
|
||||
) ([]*types.ServiceAccount, error) {
|
||||
stmt := database.Builder.
|
||||
Select(serviceAccountColumns).
|
||||
From("principals").
|
||||
Where("principal_type = ?", enum.PrincipalTypeServiceAccount)
|
||||
|
||||
stmt, err := selectServiceAccountParents(parentInfos, stmt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to select service account parents: %w", err)
|
||||
}
|
||||
|
||||
stmt = stmt.Limit(database.Limit(opts.Size))
|
||||
stmt = stmt.Offset(database.Offset(opts.Page, opts.Size))
|
||||
|
||||
if opts.Query != "" {
|
||||
stmt = stmt.Where(PartialMatch("principal_display_name", opts.Query))
|
||||
}
|
||||
|
||||
sqlQuery, params, err := stmt.ToSql()
|
||||
if err != nil {
|
||||
return nil, database.ProcessSQLErrorf(
|
||||
ctx, err, "failed to generate list service accounts query",
|
||||
)
|
||||
}
|
||||
|
||||
db := dbtx.GetAccessor(ctx, s.db)
|
||||
|
||||
dst := []*serviceAccount{}
|
||||
err := db.SelectContext(ctx, &dst, sqlQuery, parentType, parentID)
|
||||
if err != nil {
|
||||
if err := db.SelectContext(ctx, &dst, sqlQuery, params...); err != nil {
|
||||
return nil, database.ProcessSQLErrorf(ctx, err, "Failed executing default list query")
|
||||
}
|
||||
|
||||
|
@ -196,18 +253,36 @@ func (s *PrincipalStore) ListServiceAccounts(ctx context.Context, parentType enu
|
|||
}
|
||||
|
||||
// CountServiceAccounts returns a count of service accounts for a specific parent.
|
||||
func (s *PrincipalStore) CountServiceAccounts(ctx context.Context,
|
||||
parentType enum.ParentResourceType, parentID int64) (int64, error) {
|
||||
const sqlQuery = `
|
||||
SELECT count(*)
|
||||
FROM principals
|
||||
WHERE principal_type = 'serviceaccount' and principal_sa_parentType = $1 and principal_sa_parentId = $2`
|
||||
func (s *PrincipalStore) CountServiceAccounts(
|
||||
ctx context.Context,
|
||||
parentInfos []*types.ServiceAccountParentInfo,
|
||||
opts *types.PrincipalFilter,
|
||||
) (int64, error) {
|
||||
stmt := database.Builder.
|
||||
Select("count(*)").
|
||||
From("principals").
|
||||
Where("principal_type = ?", enum.PrincipalTypeServiceAccount)
|
||||
|
||||
if opts.Query != "" {
|
||||
stmt = stmt.Where(PartialMatch("principal_display_name", opts.Query))
|
||||
}
|
||||
|
||||
stmt, err := selectServiceAccountParents(parentInfos, stmt)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to select service account parents: %w", err)
|
||||
}
|
||||
|
||||
sqlQuery, params, err := stmt.ToSql()
|
||||
if err != nil {
|
||||
return 0, database.ProcessSQLErrorf(
|
||||
ctx, err, "failed to generate count service accounts query",
|
||||
)
|
||||
}
|
||||
|
||||
db := dbtx.GetAccessor(ctx, s.db)
|
||||
|
||||
var count int64
|
||||
err := db.QueryRowContext(ctx, sqlQuery, parentType, parentID).Scan(&count)
|
||||
if err != nil {
|
||||
if err = db.QueryRowContext(ctx, sqlQuery, params...).Scan(&count); err != nil {
|
||||
return 0, database.ProcessSQLErrorf(ctx, err, "Failed executing count query")
|
||||
}
|
||||
|
||||
|
@ -243,3 +318,28 @@ func (s *PrincipalStore) mapToDBserviceAccount(sa *types.ServiceAccount) (*servi
|
|||
|
||||
return dbSA, nil
|
||||
}
|
||||
|
||||
func selectServiceAccountParents(
|
||||
parents []*types.ServiceAccountParentInfo,
|
||||
stmt squirrel.SelectBuilder,
|
||||
) (squirrel.SelectBuilder, error) {
|
||||
var typeSelector squirrel.Or
|
||||
for _, parent := range parents {
|
||||
switch parent.Type {
|
||||
case enum.ParentResourceTypeRepo:
|
||||
typeSelector = append(typeSelector, squirrel.Eq{
|
||||
"principal_sa_parent_type": enum.ParentResourceTypeRepo,
|
||||
"principal_sa_parent_id": parent.ID,
|
||||
})
|
||||
case enum.ParentResourceTypeSpace:
|
||||
typeSelector = append(typeSelector, squirrel.Eq{
|
||||
"principal_sa_parent_type": enum.ParentResourceTypeSpace,
|
||||
"principal_sa_parent_id": parent.ID,
|
||||
})
|
||||
default:
|
||||
return squirrel.SelectBuilder{}, fmt.Errorf("service account parent type '%s' is not supported", parent.Type)
|
||||
}
|
||||
}
|
||||
|
||||
return stmt.Where(typeSelector), nil
|
||||
}
|
||||
|
|
|
@ -43,6 +43,12 @@ type (
|
|||
ParentType *enum.ParentResourceType `json:"parent_type"`
|
||||
ParentID *int64 `json:"parent_id"`
|
||||
}
|
||||
|
||||
ServiceAccountInfo struct {
|
||||
PrincipalInfo
|
||||
ParentType enum.ParentResourceType `json:"parent_type"`
|
||||
ParentID int64 `json:"parent_id"`
|
||||
}
|
||||
)
|
||||
|
||||
func (s *ServiceAccount) ToPrincipal() *Principal {
|
||||
|
@ -63,3 +69,16 @@ func (s *ServiceAccount) ToPrincipal() *Principal {
|
|||
func (s *ServiceAccount) ToPrincipalInfo() *PrincipalInfo {
|
||||
return s.ToPrincipal().ToPrincipalInfo()
|
||||
}
|
||||
|
||||
func (s *ServiceAccount) ToServiceAccountInfo() *ServiceAccountInfo {
|
||||
return &ServiceAccountInfo{
|
||||
PrincipalInfo: *s.ToPrincipalInfo(),
|
||||
ParentType: s.ParentType,
|
||||
ParentID: s.ParentID,
|
||||
}
|
||||
}
|
||||
|
||||
type ServiceAccountParentInfo struct {
|
||||
Type enum.ParentResourceType `json:"type"`
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue