Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions internal/store/postgres/user_orgs_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,16 @@ func (r UserOrgsRepository) Search(ctx context.Context, principalID string, rql
}, nil
}

// buildBaseQuery returns the organizations the principal holds a DIRECT
// org-level policy on. This is intentionally narrower than the membership
// listing path (membership.ListOrgsByPrincipal, used by
// ListOrganizationsByUser/ListOrganizationsByCurrentUser) — see the analogous
// note on UserProjectsRepository.buildBaseQuery.
//
// The divergence is deliberate: this admin search aggregate answers "what is
// this principal explicitly granted", while the membership path answers "what
// can this principal access". Do not "fix" one to match the other without a
// product decision.
func (r UserOrgsRepository) buildBaseQuery(principalID string) (string, []interface{}, error) {
projectCountSubquery := dialect.From(TABLE_PROJECTS).
Select(
Expand Down
11 changes: 11 additions & 0 deletions internal/store/postgres/user_projects_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,17 @@ func (r UserProjectsRepository) prepareDataQuery(userID string, orgID string, rq
return query.Offset(uint(rql.Offset)).Limit(uint(rql.Limit)), nil
}

// buildBaseQuery returns the projects the user holds a DIRECT project-level
// policy on. This is intentionally narrower than the membership listing path
// (membership.ListProjectsByPrincipal, used by ListProjectsByUser/
// ListProjectsByCurrentUser), which also expands group-held policies and
// org-level inheritance — e.g. an org admin with no direct project policy
// sees every org project there, but none here.
//
// The divergence is deliberate: this admin search aggregate answers "what is
// this user explicitly granted", while the membership path answers "what can
// this user access". Do not "fix" one to match the other without a product
// decision.
func (r UserProjectsRepository) buildBaseQuery(userID string, orgID string) *goqu.SelectDataset {
subquery := dialect.From(goqu.T(TABLE_PROJECTS).As(TABLE_ALIAS_SUB_PROJECT)).
Select(goqu.I(TABLE_ALIAS_SUB_PROJECT+"."+COLUMN_ID)).
Expand Down
Loading