Merge pull request #9473 from backstage/jhaals/catalog-model

catalog-model/catalog-backend: Remove usage of deprecated validation …
This commit is contained in:
Johan Haals
2022-02-11 15:06:44 +01:00
committed by GitHub
9 changed files with 39 additions and 101 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend': patch
---
Update internal `Location` validation.
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/catalog-model': minor
---
**BREAKING**: Remove deprecated validation methods `analyzeLocationSchema`, `locationSchema` and `locationSpecSchema`.
This functionality was primarily used internally by the `catalog-backend`.
-12
View File
@@ -7,18 +7,12 @@ import { JsonObject } from '@backstage/types';
import { JSONSchema7 } from 'json-schema';
import { JsonValue } from '@backstage/types';
import { SerializedError } from '@backstage/errors';
import * as yup from 'yup';
// @alpha
export interface AlphaEntity extends Entity {
status?: EntityStatus;
}
// @public @deprecated
export const analyzeLocationSchema: yup.SchemaOf<{
location: LocationSpec;
}>;
// @public
interface ApiEntityV1alpha1 extends Entity {
// (undocumented)
@@ -354,9 +348,6 @@ export { LocationEntityV1alpha1 };
// @public
export const locationEntityV1alpha1Validator: KindValidator;
// @public @deprecated
export const locationSchema: yup.SchemaOf<Location_2>;
// @public
export type LocationSpec = {
type: string;
@@ -364,9 +355,6 @@ export type LocationSpec = {
presence?: 'optional' | 'required';
};
// @public @deprecated
export const locationSpecSchema: yup.SchemaOf<LocationSpec>;
// @public
export function makeValidator(overrides?: Partial<Validators>): Validators;
+1 -3
View File
@@ -35,12 +35,10 @@
"@backstage/errors": "^0.2.0",
"@backstage/types": "^0.1.1",
"@types/json-schema": "^7.0.5",
"@types/yup": "^0.29.13",
"ajv": "^7.0.3",
"json-schema": "^0.4.0",
"lodash": "^4.17.21",
"uuid": "^8.0.0",
"yup": "^0.32.9"
"uuid": "^8.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.13.2-next.0",
@@ -25,8 +25,3 @@ export {
getEntitySourceLocation,
} from './helpers';
export type { Location, LocationSpec } from './types';
export {
analyzeLocationSchema,
locationSchema,
locationSpecSchema,
} from './validation';
@@ -1,63 +0,0 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as yup from 'yup';
import { LocationSpec, Location } from './types';
/**
* Deprecated.
*
* @public
* @deprecated Use {@link JSONSchema} or validators instead.
*/
export const locationSpecSchema: yup.SchemaOf<LocationSpec> = yup
.object({
type: yup.string().required(),
target: yup.string().required(),
presence: yup.mixed().oneOf(['required', 'optional']),
})
.noUnknown()
.required();
/**
* Deprecated.
*
* @public
* @deprecated Use {@link JSONSchema} or validators instead.
*/
export const locationSchema: yup.SchemaOf<Location> = yup
.object({
id: yup.string().required(),
type: yup.string().required(),
target: yup.string().required(),
presence: yup.mixed().oneOf(['required', 'optional']),
})
.noUnknown()
.required();
/**
* Deprecated.
*
* @public
* @deprecated Use {@link JSONSchema} or validators instead.
*/
export const analyzeLocationSchema: yup.SchemaOf<{ location: LocationSpec }> =
yup
.object({
location: locationSpecSchema,
})
.noUnknown()
.required();
+1 -2
View File
@@ -62,7 +62,7 @@
"winston": "^3.2.1",
"yaml": "^1.9.2",
"yn": "^4.0.0",
"yup": "^0.32.9"
"zod": "^3.11.6"
},
"devDependencies": {
"@backstage/backend-test-utils": "^0.1.17",
@@ -74,7 +74,6 @@
"@types/lodash": "^4.14.151",
"@types/supertest": "^2.0.8",
"@types/uuid": "^8.0.0",
"@types/yup": "^0.29.13",
"@vscode/sqlite3": "^5.0.7",
"aws-sdk-mock": "^5.2.1",
"msw": "^0.35.0",
@@ -15,11 +15,7 @@
*/
import { errorHandler } from '@backstage/backend-common';
import {
analyzeLocationSchema,
locationSpecSchema,
stringifyEntityRef,
} from '@backstage/catalog-model';
import { stringifyEntityRef } from '@backstage/catalog-model';
import { Config } from '@backstage/config';
import { NotFoundError } from '@backstage/errors';
import express from 'express';
@@ -34,8 +30,13 @@ import {
parseEntityPaginationParams,
parseEntityTransformParams,
} from './request';
import { disallowReadonlyMode, validateRequestBody } from './util';
import {
disallowReadonlyMode,
locationSpec,
validateRequestBody,
} from './util';
import { RefreshOptions, LocationService, RefreshService } from './types';
import { z } from 'zod';
/**
* Options used by {@link createRouter}.
@@ -165,7 +166,7 @@ export async function createRouter(
if (locationService) {
router
.post('/locations', async (req, res) => {
const input = await validateRequestBody(req, locationSpecSchema);
const location = await validateRequestBody(req, locationSpec);
const dryRun = yn(req.query.dryRun, { default: false });
// when in dryRun addLocation is effectively a read operation so we don't
@@ -174,7 +175,7 @@ export async function createRouter(
disallowReadonlyMode(readonlyEnabled);
}
const output = await locationService.createLocation(input, dryRun, {
const output = await locationService.createLocation(location, dryRun, {
authorizationToken: getBearerToken(req.header('authorization')),
});
res.status(201).json(output);
@@ -206,8 +207,12 @@ export async function createRouter(
if (locationAnalyzer) {
router.post('/analyze-location', async (req, res) => {
const input = await validateRequestBody(req, analyzeLocationSchema);
const output = await locationAnalyzer.analyzeLocation(input);
const body = await validateRequestBody(
req,
z.object({ location: locationSpec }),
);
const schema = z.object({ location: locationSpec });
const output = await locationAnalyzer.analyzeLocation(schema.parse(body));
res.status(200).json(output);
});
}
+11 -6
View File
@@ -17,7 +17,7 @@
import { InputError, NotAllowedError } from '@backstage/errors';
import { Request } from 'express';
import lodash from 'lodash';
import yup from 'yup';
import { z } from 'zod';
export async function requireRequestBody(req: Request): Promise<unknown> {
const contentType = req.header('content-type');
@@ -40,19 +40,24 @@ export async function requireRequestBody(req: Request): Promise<unknown> {
return body;
}
export const locationSpec = z
.object({
type: z.string(),
target: z.string(),
presence: z.literal('required').or(z.literal('optional')).optional(),
})
.strict(); // no unknown keys;
export async function validateRequestBody<T>(
req: Request,
schema: yup.AnySchema<T>,
schema: z.Schema<T>,
): Promise<T> {
const body = await requireRequestBody(req);
try {
await schema.validate(body, { strict: true });
return await schema.parse(body);
} catch (e) {
throw new InputError(`Malformed request: ${e}`);
}
return body as unknown as T;
}
export function disallowReadonlyMode(readonly: boolean) {