Merge pull request #9473 from backstage/jhaals/catalog-model
catalog-model/catalog-backend: Remove usage of deprecated validation …
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Update internal `Location` validation.
|
||||
@@ -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`.
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user