diff --git a/plugins/catalog-backend/src/database/CommonDatabase.ts b/plugins/catalog-backend/src/database/CommonDatabase.ts index 6b1beae538..4067adf631 100644 --- a/plugins/catalog-backend/src/database/CommonDatabase.ts +++ b/plugins/catalog-backend/src/database/CommonDatabase.ts @@ -563,17 +563,17 @@ function parsePagination( const json = Buffer.from(input.after, 'base64').toString('utf8'); cursor = JSON.parse(json); } catch { - throw new InputError('Malformed after cursor'); + throw new InputError('Malformed after cursor, could not be parsed'); } if (cursor.limit !== undefined) { if (!Number.isInteger(cursor.limit)) { - throw new InputError('Malformed after cursor'); + throw new InputError('Malformed after cursor, limit was not an number'); } limit = cursor.limit; } if (cursor.offset !== undefined) { if (!Number.isInteger(cursor.offset)) { - throw new InputError('Malformed after cursor'); + throw new InputError('Malformed after cursor, offset was not a number'); } offset = cursor.offset; } diff --git a/plugins/catalog-backend/src/service/request/parseEntityPaginationParams.test.ts b/plugins/catalog-backend/src/service/request/parseEntityPaginationParams.test.ts index c6f6942344..d537c431c0 100644 --- a/plugins/catalog-backend/src/service/request/parseEntityPaginationParams.test.ts +++ b/plugins/catalog-backend/src/service/request/parseEntityPaginationParams.test.ts @@ -19,5 +19,33 @@ import { parseEntityPaginationParams } from './parseEntityPaginationParams'; describe('parseEntityPaginationParams', () => { it('works for the happy path', () => { expect(parseEntityPaginationParams({})).toBeUndefined(); + expect(parseEntityPaginationParams({ limit: '1' })).toEqual({ limit: 1 }); + expect(parseEntityPaginationParams({ offset: '0' })).toEqual({ offset: 0 }); + expect(parseEntityPaginationParams({ offset: '2' })).toEqual({ offset: 2 }); + expect(parseEntityPaginationParams({ after: 'x' })).toEqual({ after: 'x' }); + expect( + parseEntityPaginationParams({ limit: '1', offset: '2', after: 'x' }), + ).toEqual({ limit: 1, offset: 2, after: 'x' }); + }); + + it('rejects bad values', () => { + expect(() => parseEntityPaginationParams({ limit: '' })).toThrow( + 'Invalid limit, not an integer', + ); + expect(() => parseEntityPaginationParams({ limit: '0' })).toThrow( + 'Invalid limit, must be greater than zero', + ); + expect(() => parseEntityPaginationParams({ limit: '-1' })).toThrow( + 'Invalid limit, must be greater than zero', + ); + expect(() => parseEntityPaginationParams({ offset: '' })).toThrow( + 'Invalid offset, not an integer', + ); + expect(() => parseEntityPaginationParams({ offset: '-1' })).toThrow( + 'Invalid offset, must be zero or greater', + ); + expect(() => parseEntityPaginationParams({ after: '' })).toThrow( + 'Invalid after, must not be empty', + ); }); }); diff --git a/plugins/catalog-backend/src/service/request/parseEntityPaginationParams.ts b/plugins/catalog-backend/src/service/request/parseEntityPaginationParams.ts index 57e7ff59e3..6ebd8c6d99 100644 --- a/plugins/catalog-backend/src/service/request/parseEntityPaginationParams.ts +++ b/plugins/catalog-backend/src/service/request/parseEntityPaginationParams.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { InputError } from '@backstage/errors'; import { EntityPagination } from '../../database'; import { parseIntegerParam, parseStringParam } from './common'; @@ -32,9 +33,19 @@ export function parseEntityPaginationParams( return undefined; } + if (offset !== undefined && offset < 0) { + throw new InputError(`Invalid offset, must be zero or greater`); + } + if (limit !== undefined && limit <= 0) { + throw new InputError(`Invalid limit, must be greater than zero`); + } + if (after !== undefined && !after) { + throw new InputError(`Invalid after, must not be empty`); + } + return { - ...(offset ? { offset } : {}), - ...(limit ? { limit } : {}), - ...(after ? { after } : {}), + ...(offset !== undefined ? { offset } : {}), + ...(limit !== undefined ? { limit } : {}), + ...(after !== undefined ? { after } : {}), }; }