@ -12,6 +12,7 @@ import (
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/oplog"
"github.com/hashicorp/boundary/internal/perms"
"github.com/hashicorp/boundary/internal/types/action"
"github.com/hashicorp/boundary/internal/types/resource"
"github.com/hashicorp/boundary/internal/types/scope"
"github.com/hashicorp/go-dbw"
@ -212,59 +213,36 @@ func (r *Repository) FetchAuthzProtectedEntitiesByScope(ctx context.Context, pro
return targetsMap , nil
}
// ListTargets in targets in a project. Supports the WithProjectId, WithLimit, WithType options.
// ListTargets lists targets in a project based on the data in the WithPermissions option
// provided to the Repository constructor. If no permissions are available, this function
// is a no-op.
// Supports WithLimit which overrides the limit set in the Repository object.
func ( r * Repository ) ListTargets ( ctx context . Context , opt ... Option ) ( [ ] Target , error ) {
const op = "target.(Repository).ListTargets"
opts := GetOpts ( opt ... )
if len ( opts . WithProjectIds ) == 0 && opts . WithUserId == "" && len ( opts . WithTargetIds ) == 0 {
return nil , errors . New ( ctx , errors . InvalidParameter , op , "must specify either project ids, target ids, or user id" )
}
// TODO (jimlambrt 8/2020) - implement WithUserId() optional filtering.
var where [ ] string
var args [ ] interface { }
inClauseCnt := 0
switch len ( opts . WithProjectIds ) {
case 0 :
case 1 :
inClauseCnt += 1
where , args = append ( where , fmt . Sprintf ( "project_id = @%d" , inClauseCnt ) ) , append ( args , sql . Named ( fmt . Sprintf ( "%d" , inClauseCnt ) , opts . WithProjectIds [ 0 ] ) )
default :
idsInClause := make ( [ ] string , 0 , len ( opts . WithProjectIds ) )
for _ , id := range opts . WithProjectIds {
inClauseCnt += 1
idsInClause , args = append ( idsInClause , fmt . Sprintf ( "@%d" , inClauseCnt ) ) , append ( args , sql . Named ( fmt . Sprintf ( "%d" , inClauseCnt ) , id ) )
}
where = append ( where , fmt . Sprintf ( "project_id in (%s)" , strings . Join ( idsInClause , "," ) ) )
if len ( r . permissions ) == 0 {
return [ ] Target { } , nil
}
switch len ( opts . WithTargetIds ) {
case 0 :
case 1 :
inClauseCnt += 1
where , args = append ( where , fmt . Sprintf ( "public_id = @%d" , inClauseCnt ) ) , append ( args , sql . Named ( fmt . Sprintf ( "%d" , inClauseCnt ) , opts . WithTargetIds [ 0 ] ) )
default :
idsInClause := make ( [ ] string , 0 , len ( opts . WithTargetIds ) )
for _ , id := range opts . WithTargetIds {
inClauseCnt += 1
idsInClause , args = append ( idsInClause , fmt . Sprintf ( "@%d" , inClauseCnt ) ) , append ( args , sql . Named ( fmt . Sprintf ( "%d" , inClauseCnt ) , id ) )
}
where = append ( where , fmt . Sprintf ( "public_id in (%s)" , strings . Join ( idsInClause , "," ) ) )
where , args := r . listPermissionWhereClauses ( )
if len ( where ) == 0 {
return [ ] Target { } , nil
}
if opts . WithType != "" {
inClauseCnt += 1
where , args = append ( where , fmt . Sprintf ( "type = @%d" , inClauseCnt ) ) , append ( args , sql . Named ( fmt . Sprintf ( "%d" , inClauseCnt ) , opts . WithType . String ( ) ) )
opts := GetOpts ( opt ... )
limit := r . defaultLimit
if opts . WithLimit != 0 {
limit = opts . WithLimit
}
var foundTargets [ ] * targetView
err := r . list ( ctx , & foundTargets , strings . Join ( where , " and " ) , args , opt ... )
err := r . reader . SearchWhere ( ctx , & foundTargets , strings . Join ( where , " or " ) , args ,
db . WithLimit ( limit ) )
if err != nil {
return nil , errors . Wrap ( ctx , err , op )
}
targets := make ( [ ] Target , 0 , len ( foundTargets ) )
for _ , t := range foundTargets {
subtype , err := t . targetSubtype ( ctx )
if err != nil {
@ -272,25 +250,34 @@ func (r *Repository) ListTargets(ctx context.Context, opt ...Option) ([]Target,
}
targets = append ( targets , subtype )
}
return targets , nil
}
// list will return a listing of resources and honor the WithLimit option or the
// repo defaultLimit
func ( r * Repository ) list ( ctx context . Context , resources interface { } , where string , args [ ] interface { } , opt ... Option ) error {
const op = "target.(Repository).list"
opts := GetOpts ( opt ... )
limit := r . defaultLimit
var dbOpts [ ] db . Option
if opts . WithLimit != 0 {
// non-zero signals an override of the default limit for the repo.
limit = opts . WithLimit
}
dbOpts = append ( dbOpts , db . WithLimit ( limit ) )
if err := r . reader . SearchWhere ( ctx , resources , where , args , dbOpts ... ) ; err != nil {
return errors . Wrap ( ctx , err , op )
func ( r * Repository ) listPermissionWhereClauses ( ) ( [ ] string , [ ] interface { } ) {
var where [ ] string
var args [ ] interface { }
inClauseCnt := 0
for _ , p := range r . permissions {
if p . Action != action . List {
continue
}
inClauseCnt ++
var clauses [ ] string
clauses = append ( clauses , fmt . Sprintf ( "project_id = @project_id_%d" , inClauseCnt ) )
args = append ( args , sql . Named ( fmt . Sprintf ( "project_id_%d" , inClauseCnt ) , p . ScopeId ) )
if len ( p . ResourceIds ) > 0 {
clauses = append ( clauses , fmt . Sprintf ( "public_id = any(@public_id_%d)" , inClauseCnt ) )
args = append ( args , sql . Named ( fmt . Sprintf ( "public_id_%d" , inClauseCnt ) , "{" + strings . Join ( p . ResourceIds , "," ) + "}" ) )
}
where = append ( where , fmt . Sprintf ( "(%s)" , strings . Join ( clauses , " and " ) ) )
}
return nil
return where , args
}
// DeleteTarget will delete a target from the repository.