🛂 fix: Validate types Query Param in People Picker Access Middleware (#12276)

* 🛂 fix: Validate `types` query param in people picker access middleware

checkPeoplePickerAccess only inspected `req.query.type` (singular),
allowing callers to bypass type-specific permission checks by using
the `types` (plural) parameter accepted by the controller. Now both
`type` and `types` are collected and each requested principal type is
validated against the caller's role permissions.

* 🛂 refactor: Hoist valid types constant, improve logging, and add edge-case tests

- Hoist VALID_PRINCIPAL_TYPES to module-level Set to avoid per-request allocation
- Include both `type` and `types` in error log for debuggability
- Restore detailed JSDoc documenting per-type permission requirements
- Add missing .json() assertion on partial-denial test
- Add edge-case tests: all-invalid types, empty string types, PrincipalType.PUBLIC

* 🏷️ fix: Align TPrincipalSearchParams with actual controller API

The stale type used `type` (singular) but the controller and all callers
use `types` (plural array). Aligns with PrincipalSearchParams in
types/queries.ts.
This commit is contained in:
Danny Avila 2026-03-17 02:46:11 -04:00 committed by GitHub
parent 68435cdcd0
commit 2f09d29c71
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 209 additions and 20 deletions

View file

@ -200,9 +200,9 @@ export type TUpdateResourcePermissionsResponse = z.infer<
* Principal search request parameters
*/
export type TPrincipalSearchParams = {
q: string; // search query (required)
limit?: number; // max results (1-50, default 10)
type?: PrincipalType.USER | PrincipalType.GROUP | PrincipalType.ROLE; // filter by type (optional)
q: string;
limit?: number;
types?: Array<PrincipalType.USER | PrincipalType.GROUP | PrincipalType.ROLE>;
};
/**
@ -228,7 +228,7 @@ export type TPrincipalSearchResult = {
export type TPrincipalSearchResponse = {
query: string;
limit: number;
type?: PrincipalType.USER | PrincipalType.GROUP | PrincipalType.ROLE;
types?: Array<PrincipalType.USER | PrincipalType.GROUP | PrincipalType.ROLE> | null;
results: TPrincipalSearchResult[];
count: number;
sources: {