Skip to content

Commit c74167e

Browse files
committed
Consolidate unknown key configuration
1 parent 12a2cde commit c74167e

51 files changed

Lines changed: 98 additions & 124 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/development/core/server/kibana-plugin-server.routeconfig.validate.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ validate: RouteValidatorFullConfig<P, Q, B> | false;
1414

1515
## Remarks
1616

17-
You \*must\* specify a validation schema to be able to read: - url path segments - request query - request body To opt out of validating the request, specify `validate: false`<!-- -->. In this case request params, query, and body will be \*\*empty\*\* objects and have no access to raw values. In some cases you may want to use another validation library. To do this, you need to instruct the `@kbn/config-schema` library to output \*\*non-validated values\*\* with setting schema as `schema.object({}, { allowUnknowns: true })`<!-- -->;
17+
You \*must\* specify a validation schema to be able to read: - url path segments - request query - request body To opt out of validating the request, specify `validate: false`<!-- -->. In this case request params, query, and body will be \*\*empty\*\* objects and have no access to raw values. In some cases you may want to use another validation library. To do this, you need to instruct the `@kbn/config-schema` library to output \*\*non-validated values\*\* with setting schema as `schema.object({}, { unknowns: 'allow' })`<!-- -->;
1818

1919
## Example
2020

packages/kbn-config-schema/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ __Output type:__ `{ [K in keyof TProps]: TypeOf<TProps[K]> } as TObject`
239239
__Options:__
240240
* `defaultValue: TObject | Reference<TObject> | (() => TObject)` - defines a default value, see [Default values](#default-values) section for more details.
241241
* `validate: (value: TObject) => string | void` - defines a custom validator function, see [Custom validation](#custom-validation) section for more details.
242-
* `allowUnknowns: boolean` - indicates whether unknown object properties should be allowed. It's `false` by default.
242+
* `unknowns: 'allow' | 'ignore' | 'forbid'` - indicates whether unknown object properties should be allowed, ignored, or forbidden. It's `forbid` by default.
243243

244244
__Usage:__
245245
```typescript
@@ -250,7 +250,7 @@ const valueSchema = schema.object({
250250
```
251251

252252
__Notes:__
253-
* Using `allowUnknowns` is discouraged and should only be used in exceptional circumstances. Consider using `schema.recordOf()` instead.
253+
* Using `unknowns: 'allow'` is discouraged and should only be used in exceptional circumstances. Consider using `schema.recordOf()` instead.
254254
* Currently `schema.object()` always has a default value of `{}`, but this may change in the near future. Try to not rely on this behaviour and specify default value explicitly or use `schema.maybe()` if the value is optional.
255255
* `schema.object()` also supports a json string as input if it can be safely parsed using `JSON.parse` and if the resulting value is a plain object.
256256

packages/kbn-config-schema/src/types/object_type.test.ts

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -276,10 +276,10 @@ test('individual keys can validated', () => {
276276
);
277277
});
278278

279-
test('allow unknown keys when allowUnknowns = true', () => {
279+
test('allow unknown keys when unknowns = `allow`', () => {
280280
const type = schema.object(
281281
{ foo: schema.string({ defaultValue: 'test' }) },
282-
{ allowUnknowns: true }
282+
{ unknowns: 'allow' }
283283
);
284284

285285
expect(
@@ -292,10 +292,10 @@ test('allow unknown keys when allowUnknowns = true', () => {
292292
});
293293
});
294294

295-
test('allowUnknowns = true affects only own keys', () => {
295+
test('unknowns = `allow` affects only own keys', () => {
296296
const type = schema.object(
297297
{ foo: schema.object({ bar: schema.string() }) },
298-
{ allowUnknowns: true }
298+
{ unknowns: 'allow' }
299299
);
300300

301301
expect(() =>
@@ -308,10 +308,10 @@ test('allowUnknowns = true affects only own keys', () => {
308308
).toThrowErrorMatchingInlineSnapshot(`"[foo.baz]: definition for this key is missing"`);
309309
});
310310

311-
test('does not allow unknown keys when allowUnknowns = false', () => {
311+
test('does not allow unknown keys when unknowns = `forbid`', () => {
312312
const type = schema.object(
313313
{ foo: schema.string({ defaultValue: 'test' }) },
314-
{ allowUnknowns: false }
314+
{ unknowns: 'forbid' }
315315
);
316316
expect(() =>
317317
type.validate({
@@ -320,10 +320,10 @@ test('does not allow unknown keys when allowUnknowns = false', () => {
320320
).toThrowErrorMatchingInlineSnapshot(`"[bar]: definition for this key is missing"`);
321321
});
322322

323-
test('allow and remove unknown keys when ignoreUnknowns = true', () => {
323+
test('allow and remove unknown keys when unknowns = `ignore`', () => {
324324
const type = schema.object(
325325
{ foo: schema.string({ defaultValue: 'test' }) },
326-
{ ignoreUnknowns: true }
326+
{ unknowns: 'ignore' }
327327
);
328328

329329
expect(
@@ -335,10 +335,10 @@ test('allow and remove unknown keys when ignoreUnknowns = true', () => {
335335
});
336336
});
337337

338-
test('ignoreUnknowns = true affects only own keys', () => {
338+
test('unknowns = `ignore` affects only own keys', () => {
339339
const type = schema.object(
340340
{ foo: schema.object({ bar: schema.string() }) },
341-
{ ignoreUnknowns: true }
341+
{ unknowns: 'ignore' }
342342
);
343343

344344
expect(() =>
@@ -350,15 +350,3 @@ test('ignoreUnknowns = true affects only own keys', () => {
350350
})
351351
).toThrowErrorMatchingInlineSnapshot(`"[foo.baz]: definition for this key is missing"`);
352352
});
353-
354-
test('does not allow unknown keys when ignoreUnknowns = false', () => {
355-
const type = schema.object(
356-
{ foo: schema.string({ defaultValue: 'test' }) },
357-
{ ignoreUnknowns: false }
358-
);
359-
expect(() =>
360-
type.validate({
361-
bar: 'baz',
362-
})
363-
).toThrowErrorMatchingInlineSnapshot(`"[bar]: definition for this key is missing"`);
364-
});

packages/kbn-config-schema/src/types/object_type.ts

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,16 @@ export type TypeOf<RT extends Type<any>> = RT['type'];
3030
// this might not have perfect _rendering_ output, but it will be typed.
3131
export type ObjectResultType<P extends Props> = Readonly<{ [K in keyof P]: TypeOf<P[K]> }>;
3232

33-
interface AllowUnknowns {
34-
allowUnknowns: true;
35-
ignoreUnknowns?: false;
33+
interface UnknownOptions {
34+
/**
35+
* Options for dealing with unknown keys:
36+
* - allow: unknown keys will be permitted
37+
* - ignore: unknown keys will not fail validation, but will be stripped out
38+
* - forbid (default): unknown keys will fail validation
39+
*/
40+
unknowns?: 'allow' | 'ignore' | 'forbid';
3641
}
3742

38-
interface IgnoreUnknowns {
39-
allowUnknowns?: false;
40-
ignoreUnknowns: true;
41-
}
42-
43-
interface ForbidUnknowns {
44-
allowUnknowns?: false;
45-
ignoreUnknowns?: false;
46-
}
47-
// type check to not permit both to be set to `true` at the same time
48-
type UnknownOptions = AllowUnknowns | IgnoreUnknowns | ForbidUnknowns;
49-
5043
export type ObjectTypeOptions<P extends Props = any> = TypeOptions<
5144
{ [K in keyof P]: TypeOf<P[K]> }
5245
> &
@@ -55,10 +48,7 @@ export type ObjectTypeOptions<P extends Props = any> = TypeOptions<
5548
export class ObjectType<P extends Props = any> extends Type<ObjectResultType<P>> {
5649
private props: Record<string, AnySchema>;
5750

58-
constructor(
59-
props: P,
60-
{ allowUnknowns = false, ignoreUnknowns = false, ...typeOptions }: ObjectTypeOptions<P> = {}
61-
) {
51+
constructor(props: P, { unknowns = 'forbid', ...typeOptions }: ObjectTypeOptions<P> = {}) {
6252
const schemaKeys = {} as Record<string, AnySchema>;
6353
for (const [key, value] of Object.entries(props)) {
6454
schemaKeys[key] = value.getSchema();
@@ -68,8 +58,8 @@ export class ObjectType<P extends Props = any> extends Type<ObjectResultType<P>>
6858
.keys(schemaKeys)
6959
.default()
7060
.optional()
71-
.unknown(Boolean(allowUnknowns))
72-
.options({ stripUnknown: { objects: ignoreUnknowns } });
61+
.unknown(unknowns === 'allow')
62+
.options({ stripUnknown: { objects: unknowns === 'ignore' } });
7363

7464
super(schema, typeOptions);
7565
this.props = schemaKeys;

src/core/server/http/router/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ export interface RouteConfig<P, Q, B, Method extends RouteMethod> {
177177
* access to raw values.
178178
* In some cases you may want to use another validation library. To do this, you need to
179179
* instruct the `@kbn/config-schema` library to output **non-validated values** with
180-
* setting schema as `schema.object({}, { allowUnknowns: true })`;
180+
* setting schema as `schema.object({}, { unknowns: 'allow' })`;
181181
*
182182
* @example
183183
* ```ts
@@ -210,7 +210,7 @@ export interface RouteConfig<P, Q, B, Method extends RouteMethod> {
210210
* path: 'path/{id}',
211211
* validate: {
212212
* // handler has access to raw non-validated params in runtime
213-
* params: schema.object({}, { allowUnknowns: true })
213+
* params: schema.object({}, { unknowns: 'allow' })
214214
* },
215215
* },
216216
* (context, req, res,) {

src/core/server/http/router/router.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ describe('Router', () => {
5959
{
6060
path: '/',
6161
options: { body: { output: 'file' } } as any, // We explicitly don't support 'file'
62-
validate: { body: schema.object({}, { allowUnknowns: true }) },
62+
validate: { body: schema.object({}, { unknowns: 'allow' }) },
6363
},
6464
(context, req, res) => res.ok({})
6565
)

src/core/server/ui_settings/routes/set_many.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { CannotOverrideError } from '../ui_settings_errors';
2424

2525
const validate = {
2626
body: schema.object({
27-
changes: schema.object({}, { allowUnknowns: true }),
27+
changes: schema.object({}, { unknowns: 'allow' }),
2828
}),
2929
};
3030

src/core/server/ui_settings/ui_settings_config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const configSchema = schema.object({
3939
})
4040
),
4141
},
42-
{ allowUnknowns: true }
42+
{ unknowns: 'allow' }
4343
),
4444
});
4545

src/plugins/data/server/autocomplete/value_suggestions_route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@ export function registerValueSuggestionsRoute(
3939
{
4040
index: schema.string(),
4141
},
42-
{ allowUnknowns: false }
42+
{ unknowns: 'allow' }
4343
),
4444
body: schema.object(
4545
{
4646
field: schema.string(),
4747
query: schema.string(),
4848
boolFilter: schema.maybe(schema.any()),
4949
},
50-
{ allowUnknowns: false }
50+
{ unknowns: 'allow' }
5151
),
5252
},
5353
},

src/plugins/data/server/search/routes.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ export function registerSearchRoute(router: IRouter): void {
2828
validate: {
2929
params: schema.object({ strategy: schema.string() }),
3030

31-
query: schema.object({}, { allowUnknowns: true }),
31+
query: schema.object({}, { unknowns: 'allow' }),
3232

33-
body: schema.object({}, { allowUnknowns: true }),
33+
body: schema.object({}, { unknowns: 'allow' }),
3434
},
3535
},
3636
async (context, request, res) => {
@@ -64,7 +64,7 @@ export function registerSearchRoute(router: IRouter): void {
6464
id: schema.string(),
6565
}),
6666

67-
query: schema.object({}, { allowUnknowns: true }),
67+
query: schema.object({}, { unknowns: 'allow' }),
6868
},
6969
},
7070
async (context, request, res) => {

0 commit comments

Comments
 (0)