fix(backend): return API permissions sorted by key

This commit is contained in:
Elias Schneider
2026-10-27 23:32:53 +01:00
parent 75e4ee624a
commit 75fe4ae519
2 changed files with 31 additions and 4 deletions
+8 -4
View File
@@ -46,6 +46,10 @@ func newService(db *gorm.DB, issuer string) *Service {
return &Service{db: db, issuer: issuer}
}
func permissionsByKey(db *gorm.DB) *gorm.DB {
return db.Order("api_permissions.key")
}
// isIssuerAudience reports whether the audience refers to Pocket ID itself (the issuer)
// A custom API must not claim the issuer as its audience, otherwise its tokens would be indistinguishable from Pocket ID's own identity tokens
func isIssuerAudience(audience, issuer string) bool {
@@ -55,7 +59,7 @@ func isIssuerAudience(audience, issuer string) bool {
func (s *Service) List(ctx context.Context, search string, listRequestOptions utils.ListRequestOptions) (apis []API, response utils.PaginationResponse, err error) {
query := s.db.
WithContext(ctx).
Preload("Permissions").
Preload("Permissions", permissionsByKey).
Model(&API{})
if listRequestOptions.Sort.Column == "resource" {
@@ -79,7 +83,7 @@ func (s *Service) Get(ctx context.Context, tx *gorm.DB, id string) (api API, err
}
err = query.
Preload("Permissions").
Preload("Permissions", permissionsByKey).
Where("id = ?", id).
First(&api).
Error
@@ -432,7 +436,7 @@ func (s *Service) ListClientAPIs(ctx context.Context, clientID string) ([]Client
// Load the API rows for the grants we collected, so the caller can see the API's name and audience
var apis []API
err = tx.WithContext(ctx).
Preload("Permissions").
Preload("Permissions", permissionsByKey).
Where("id IN ?", slices.Collect(maps.Keys(grants))).
Order("name").
Find(&apis).
@@ -670,7 +674,7 @@ func (s *Service) ListAssignableAPIs(ctx context.Context, clientID, search strin
query := s.db.
WithContext(ctx).
Preload("Permissions").
Preload("Permissions", permissionsByKey).
Model(&API{}).
Where("id NOT IN (?)", granted)
+23
View File
@@ -327,6 +327,29 @@ func TestUpdatePermissionsRejectsInvalidKeyCharacters(t *testing.T) {
require.NoError(t, err)
}
func TestPermissionsAreReturnedByKey(t *testing.T) {
db := testutils.NewDatabaseForTest(t)
svc := New(Dependencies{DB: db}).service
orders, err := svc.Create(t.Context(), apiCreateDto{Name: "Orders", Resource: "https://api.orders.example.com"})
require.NoError(t, err)
var input []apiPermissionInputDto
for _, key := range []string{"epsilon", "alpha", "delta", "beta", "gamma"} {
input = append(input, apiPermissionInputDto{Key: key, Name: key})
}
_, err = svc.UpdatePermissions(t.Context(), orders.ID, apiPermissionsUpdateDto{Permissions: input})
require.NoError(t, err)
got, err := svc.Get(t.Context(), nil, orders.ID)
require.NoError(t, err)
keys := make([]string, len(got.Permissions))
for i, p := range got.Permissions {
keys[i] = p.Key
}
assert.Equal(t, []string{"alpha", "beta", "delta", "epsilon", "gamma"}, keys)
}
func TestCreateRejectsIssuerResource(t *testing.T) {
db := testutils.NewDatabaseForTest(t)
const issuer = "https://id.example.com"