diff --git a/modules/cabana/relation.go b/modules/cabana/relation.go index 5615e26..7ebc1c6 100644 --- a/modules/cabana/relation.go +++ b/modules/cabana/relation.go @@ -544,10 +544,17 @@ func normalizeRelationQuery(schema *RelationSchema, candidates bool, in Relation panel = schema.Manage } sortKey := in.Sort - if sortKey == "" && len(panel.List.Columns) > 0 { - sortKey = panel.List.Columns[0].Key - } - if sortKey != "" { + if sortKey == "" { + // No explicit sort: use the first sortable column, or none (the + // primary key then orders the page). Only a sort the client names is + // validated, so a panel whose first column is not sortable still loads. + for _, col := range panel.List.Columns { + if col.Sortable { + sortKey = col.Key + break + } + } + } else { valid := false for _, col := range panel.List.Columns { if col.Key == sortKey && col.Sortable { diff --git a/modules/cabana/relation_test.go b/modules/cabana/relation_test.go index 8a292ec..36c07a5 100644 --- a/modules/cabana/relation_test.go +++ b/modules/cabana/relation_test.go @@ -94,6 +94,27 @@ func TestRelationStablePages(t *testing.T) { } } +// TestRelationDefaultSort pins WR-06: with no sort in the request the panel +// orders by its first sortable column, or by the primary key when none is +// sortable, instead of rejecting the request. +func TestRelationDefaultSort(t *testing.T) { + schema := &RelationSchema{ + View: RelationPanel{List: RelationList{Columns: []RelationColumn{{Key: "label"}, {Key: "email", Sortable: true}}}}, + Manage: RelationPanel{List: RelationList{Columns: []RelationColumn{{Key: "label"}}}}, + } + _, _, key, _, err := normalizeRelationQuery(schema, false, RelationQuery{}) + if err != nil || key != "email" { + t.Fatalf("view default sort = %q err=%v, want the first sortable column", key, err) + } + _, _, key, _, err = normalizeRelationQuery(schema, true, RelationQuery{}) + if err != nil || key != "" { + t.Fatalf("manage default sort = %q err=%v, want none (primary key order)", key, err) + } + if _, _, _, _, err := normalizeRelationQuery(schema, false, RelationQuery{Sort: "label"}); err == nil { + t.Fatal("an explicit sort on a non-sortable column was accepted") + } +} + func TestRelationCandidateExclusions(t *testing.T) { contract := relationTestController{}.AdminRelationContracts()[0] ids, err := contract.ExcludedRelatedIDs(&relationTestOwner{OwnerID: 41})