Skip to content

Commit c49d3d6

Browse files
committed
fix: restore v2 catalog privacy boundaries
1 parent 0ecd70c commit c49d3d6

5 files changed

Lines changed: 48 additions & 9 deletions

File tree

frontend/src/lib/features/testing/TestRuns.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
api.tests.testPlans.getAll(workspaceId),
5656
api.tests.testRuns.getAll(workspaceId, params),
5757
api.milestones.getAll(),
58-
api.getUsers()
58+
api.getAssignableUsers(workspaceId)
5959
]);
6060
const safeSets = sets || [];
6161
const safeRuns = runs || [];

internal/repository/custom_field_repository.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ func isCustomFieldConfigIdentifier(identifier string, fieldID int) bool {
382382
// type (and which management set) references which custom_field_id.
383383
type AssetTypeUsageRow struct {
384384
CustomFieldID int
385+
SetID int
385386
AssetTypeName string
386387
SetName string
387388
}
@@ -390,7 +391,7 @@ type AssetTypeUsageRow struct {
390391
// ordered by custom_field_id, set name, asset type name.
391392
func (r *CustomFieldRepository) ListAssetTypeUsages() ([]AssetTypeUsageRow, error) {
392393
rows, err := r.db.Query(`
393-
SELECT atf.custom_field_id, at.name, s.name
394+
SELECT atf.custom_field_id, s.id, at.name, s.name
394395
FROM asset_type_fields atf
395396
JOIN asset_types at ON atf.asset_type_id = at.id
396397
JOIN asset_management_sets s ON at.set_id = s.id
@@ -403,7 +404,7 @@ func (r *CustomFieldRepository) ListAssetTypeUsages() ([]AssetTypeUsageRow, erro
403404
var results []AssetTypeUsageRow
404405
for rows.Next() {
405406
var row AssetTypeUsageRow
406-
if err := rows.Scan(&row.CustomFieldID, &row.AssetTypeName, &row.SetName); err != nil {
407+
if err := rows.Scan(&row.CustomFieldID, &row.SetID, &row.AssetTypeName, &row.SetName); err != nil {
407408
return nil, fmt.Errorf("scan asset type usage: %w", err)
408409
}
409410
results = append(results, row)

internal/restapi/v2/catalog.go

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"strconv"
1010
"strings"
1111

12+
"windshift/internal/contextkeys"
1213
"windshift/internal/models"
1314
"windshift/internal/objecttranslation"
1415
"windshift/internal/repository"
@@ -74,7 +75,7 @@ func registerCatalogRoutes(builder *routeBuilder, deps Deps) {
7475
builder.Read("/priorities/{priority_id}", AuthAuthenticated, []string{"priorities:read"}, getPriority(deps.Configuration, deps.ObjectTranslations))
7576
builder.JSON(http.MethodPatch, "/priorities/{priority_id}", http.StatusOK, true, AuthAuthenticated, []string{"priorities:write"}, patchPriority(deps.CatalogMutations))
7677
builder.Command(http.MethodDelete, "/priorities/{priority_id}", AuthAuthenticated, []string{"priorities:write"}, deletePriority(deps.CatalogMutations))
77-
builder.Metadata("/custom-fields", AuthAuthenticated, []string{"custom-fields:read"}, listCustomFields(deps.Configuration))
78+
builder.Metadata("/custom-fields", AuthAuthenticated, []string{"custom-fields:read"}, listCustomFields(deps))
7879
builder.Read("/custom-fields/{custom_field_id}", AuthAuthenticated, []string{"custom-fields:read"}, getCustomField(deps.Configuration))
7980
}
8081

@@ -424,18 +425,47 @@ type customFieldDTO struct {
424425
Indexed models.CustomFieldIndexInfo `json:"indexed"`
425426
}
426427

427-
func listCustomFields(reader configurationReader) metadataOperation[[]customFieldDTO, services.CustomFieldCatalogMeta] {
428-
return func(*http.Request) ([]customFieldDTO, services.CustomFieldCatalogMeta, error) {
429-
results, meta, err := reader.ListCustomFieldsWithMeta()
428+
func listCustomFields(deps Deps) metadataOperation[[]customFieldDTO, services.CustomFieldCatalogMeta] {
429+
return func(r *http.Request) ([]customFieldDTO, services.CustomFieldCatalogMeta, error) {
430+
results, meta, err := deps.Configuration.ListCustomFieldsWithMeta()
430431
if err != nil {
431432
return nil, services.CustomFieldCatalogMeta{}, internalError(err)
432433
}
433434
items := make([]customFieldDTO, len(results))
435+
visibleSets := make(map[int]bool)
436+
hasAssetUsages := false
437+
for _, result := range results {
438+
for _, usage := range result.AssetTypeUsages {
439+
if usage.SetID > 0 {
440+
hasAssetUsages = true
441+
}
442+
}
443+
}
444+
token, _ := r.Context().Value(contextkeys.APIToken).(*models.APIToken)
445+
if hasAssetUsages && (token == nil || deps.Tokens.CheckTokenPermissions(token, []string{"assets:read"})) {
446+
user, authErr := principal(r)
447+
if authErr != nil {
448+
return nil, meta, authErr
449+
}
450+
sets, setErr := deps.Assets.ListSets(user.ID)
451+
if setErr != nil {
452+
return nil, meta, internalError(setErr)
453+
}
454+
for _, set := range sets {
455+
visibleSets[set.ID] = true
456+
}
457+
}
434458
for i := range results {
435459
items[i], err = customFieldFromResult(results[i])
436460
if err != nil {
437461
return nil, services.CustomFieldCatalogMeta{}, internalError(err)
438462
}
463+
items[i].AssetTypeUsages = []services.CustomFieldAssetUsage{}
464+
for _, usage := range results[i].AssetTypeUsages {
465+
if visibleSets[usage.SetID] {
466+
items[i].AssetTypeUsages = append(items[i].AssetTypeUsages, usage)
467+
}
468+
}
439469
}
440470
return items, meta, nil
441471
}

internal/services/catalog_read_service.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,14 @@ func (s *CatalogReadService) ListAssignableUsers(ctx context.Context, userID, wo
206206
return s.workspaceUsers.List(ctx, workspaceID)
207207
}
208208

209-
func (s *CatalogReadService) ListUsers(_ int, page CatalogPageParams) ([]models.User, int, error) {
209+
func (s *CatalogReadService) ListUsers(userID int, page CatalogPageParams) ([]models.User, int, error) {
210+
allowed, err := s.access.HasGlobalPermission(userID, models.PermissionUserList)
211+
if err != nil {
212+
return nil, 0, err
213+
}
214+
if !allowed {
215+
return nil, 0, ErrCatalogForbidden
216+
}
210217
users, err := s.users.ListAll()
211218
if err != nil {
212219
return nil, 0, err

internal/services/config_read_service.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ type CustomFieldResult struct {
128128
}
129129

130130
type CustomFieldAssetUsage struct {
131+
SetID int `json:"-"`
131132
AssetTypeName string `json:"asset_type_name"`
132133
SetName string `json:"set_name"`
133134
}
@@ -176,7 +177,7 @@ func (s *ConfigReadService) ListCustomFieldsWithMeta() ([]CustomFieldResult, Cus
176177
for _, usage := range usages {
177178
if index, ok := byID[usage.CustomFieldID]; ok {
178179
items[index].AssetTypeUsages = append(items[index].AssetTypeUsages, CustomFieldAssetUsage{
179-
AssetTypeName: usage.AssetTypeName, SetName: usage.SetName,
180+
SetID: usage.SetID, AssetTypeName: usage.AssetTypeName, SetName: usage.SetName,
180181
})
181182
}
182183
}

0 commit comments

Comments
 (0)