@@ -419,3 +419,137 @@ Future<Response> _handlePost(
419419 // Return 201 Created with the wrapped and serialized response
420420 return Response .json (statusCode: HttpStatus .created, body: responseJson);
421421}
422+
423+ /*
424+ Simplified Strict Filtering Rules (ALL FILTERS ARE ANDed if present):
425+
426+ 1. Headlines (`model=headline`):
427+ - Filterable by any combination (ANDed) of:
428+ - `categories` (plural, comma-separated IDs, matching `headline.category.id`)
429+ - `sources` (plural, comma-separated IDs, matching `headline.source.id`)
430+ - `q` (free-text query, searching `headline.title` only)
431+ - *No other filters (like `countries`) are allowed for headlines.*
432+
433+ 2. Sources (`model=source`):
434+ - Filterable by any combination (ANDed) of:
435+ - `countries` (plural, comma-separated ISO codes, matching `source.headquarters.iso_code`)
436+ - `sourceTypes` (plural, comma-separated enum strings, matching `source.sourceType`)
437+ - `languages` (plural, comma-separated language codes, matching `source.language`)
438+ - `q` (free-text query, searching `source.name` only)
439+
440+ 3. Categories (`model=category`):
441+ - Filterable __only__ by:
442+ - `q` (free-text query, searching `category.name` only)
443+
444+ 4. Countries (`model=country`):
445+ - Filterable __only__ by:
446+ - `q` (free-text query, searching `country.name` only)
447+
448+ ------
449+
450+ Explicitly Define Allowed Parameters per Model: When processing the request for a given `modelName`, the handler should have a predefined set of *allowed* query parameter keys for that specific model.
451+
452+ - Example for `modelName == 'headline'`:
453+ - Allowed keys: `categories`, `sources`, `q` (plus standard ones like `limit`, `startAfterId`).
454+ - Example for `modelName == 'source'`:
455+ - Allowed keys: `countries`, `sourceTypes`, `languages`, `q` (plus standard ones).
456+ - And so on for `category` and `country`.
457+
458+ ----------------- TESTED FILTERS ---------------
459+
460+ Model: `headline`
461+
462+ 1. Filter by single category:
463+ - URL: `/api/v1/data?model=headline&categories=c1a2b3c4-d5e6-f789-0123-456789abcdef`
464+ - Expected: Headlines with category ID `c1a2b3c4-d5e6-f789-0123-456789abcdef`.
465+
466+ 2. Filter by multiple comma-separated categories (client-side `_in` implies OR for values):
467+ - URL: `/api/v1/data?model=headline&categories=c1a2b3c4-d5e6-f789-0123-456789abcdef,c2b3c4d5-e6f7-a890-1234-567890abcdef`
468+ - Expected: Headlines whose category ID is *either* of the two provided.
469+
470+ 3. Filter by single source:
471+ - URL: `/api/v1/data?model=headline&sources=s1a2b3c4-d5e6-f789-0123-456789abcdef`
472+ - Expected: Headlines with source ID `s1a2b3c4-d5e6-f789-0123-456789abcdef`.
473+
474+ 4. Filter by multiple comma-separated sources (client-side `_in` implies OR for values):
475+ - URL: `/api/v1/data?model=headline&sources=s1a2b3c4-d5e6-f789-0123-456789abcdef,s2b3c4d5-e6f7-a890-1234-567890abcdef`
476+ - Expected: Headlines whose source ID is *either* of the two provided.
477+
478+ 5. Filter by a category AND a source:
479+ - URL: `/api/v1/data?model=headline&categories=c1a2b3c4-d5e6-f789-0123-456789abcdef&sources=s1a2b3c4-d5e6-f789-0123-456789abcdef`
480+ - Expected: Headlines matching *both* the category ID AND the source ID.
481+
482+ 6. Filter by text query `q` (title only):
483+ - URL: `/api/v1/data?model=headline&q=Dart`
484+ - Expected: Headlines where "Dart" (case-insensitive) appears in the title.
485+
486+ 7. Filter by `q` AND `categories` (q should take precedence, categories ignored):
487+ - URL: `/api/v1/data?model=headline&q=Flutter&categories=c1a2b3c4-d5e6-f789-0123-456789abcdef`
488+ - Expected: Headlines matching `q=Flutter` (in title), ignoring the category filter.
489+
490+ 8. Invalid parameter for headlines (e.g., `countries`):
491+ - URL: `/api/v1/data?model=headline&countries=US`
492+ - Expected: `400 Bad Request` with an error message about an invalid query parameter.
493+
494+ Model: `source`
495+
496+ 9. Filter by single country (ISO code):
497+ - URL: `/api/v1/data?model=source&countries=GB`
498+ - Expected: Sources headquartered in 'GB'.
499+
500+ 10. Filter by multiple comma-separated countries (client-side `_in` implies OR for values):
501+ - URL: `/api/v1/data?model=source&countries=US,GB`
502+ - Expected: Sources headquartered in 'US' OR 'GB'.
503+
504+ 11. Filter by single `sourceType`:
505+ - URL: `/api/v1/data?model=source&sourceTypes=blog`
506+ - Expected: Sources of type 'blog'.
507+
508+ 12. Filter by multiple comma-separated `sourceTypes` (client-side `_in` implies OR for values):
509+ - URL: `/api/v1/data?model=source&sourceTypes=blog,specializedPublisher`
510+ - Expected: Sources of type 'blog' OR 'specializedPublisher'.
511+
512+ 13. Filter by single `language`:
513+ - URL: `/api/v1/data?model=source&languages=en`
514+ - Expected: Sources in 'en' language.
515+
516+ 14. Filter by combination (countries AND sourceTypes AND languages):
517+ - URL: `/api/v1/data?model=source&countries=GB&sourceTypes=nationalNewsOutlet&languages=en`
518+ - Expected: Sources matching all three criteria.
519+
520+ 15. Filter by text query `q` for sources (name only):
521+ - URL: `/api/v1/data?model=source&q=Ventures`
522+ - Expected: Sources where "Ventures" appears in the name.
523+
524+ 16. Filter by `q` AND `countries` for sources (`q` takes precedence):
525+ - URL: `/api/v1/data?model=source&q=Official&countries=US`
526+ - Expected: Sources matching `q=Official` (in name), ignoring the country filter.
527+
528+ 17. Invalid parameter for sources (e.g., `categories`):
529+ - URL: `/api/v1/data?model=source&categories=catId1`
530+ - Expected: `400 Bad Request`.
531+
532+ Model: `category`
533+
534+ 18. Filter by text query `q` for categories (name only):
535+ - URL: `/api/v1/data?model=category&q=Mobile`
536+ - Expected: Categories where "Mobile" appears in name.
537+
538+ 19. Invalid parameter for categories (e.g., `sources`):
539+ - URL: `/api/v1/data?model=category&sources=sourceId1`
540+ - Expected: `400 Bad Request`.
541+
542+ Model: `country`
543+
544+ 20. Filter by text query `q` for countries (name only):
545+ - URL: `/api/v1/data?model=country&q=United`
546+ - Expected: Countries where "United" appears in the name.
547+
548+ 21. Filter by text query `q` for countries (name only, to match "US" if a country name contains "US"):
549+ - URL: `/api/v1/data?model=country&q=US`
550+ - Expected: Country with name containing "US". (Note: This test's expectation might need adjustment if no country name contains "US" but its isoCode is "US". The current `q` logic for country only searches name).
551+
552+ 22. Invalid parameter for countries (e.g., `categories`):
553+ - URL: `/api/v1/data?model=country&categories=catId1`
554+ - Expected: `400 Bad Request`.
555+ */
0 commit comments