1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-08-27 13:49:10 +02:00

Merge fixes for 5.0.1 to 5.0 branch (#3646)

This commit is contained in:
Jaanus Sellin 2023-04-28 12:10:23 +03:00 committed by GitHub
parent 9f82c08ba2
commit 77dd5d6c9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 61 additions and 77 deletions

View File

@ -23,12 +23,12 @@ describe('project overview', () => {
after(() => {
cy.request({
method: 'DELETE',
url: `${baseUrl}/api/admin/features/${featureToggleName}-A`,
url: `${baseUrl}/api/admin/projects/default/features/${featureToggleName}-A`,
failOnStatusCode: false,
});
cy.request({
method: 'DELETE',
url: `${baseUrl}/api/admin/features/${featureToggleName}-B`,
url: `${baseUrl}/api/admin/projects/default/features/${featureToggleName}-B`,
failOnStatusCode: false,
});
cy.request({

View File

@ -24,7 +24,7 @@ export const createFeature_API = (
export const deleteFeature_API = (name: string): Chainable<any> => {
cy.request({
method: 'DELETE',
url: `${baseUrl}/api/admin/features/${name}`,
url: `${baseUrl}/api/admin/projects/default/features/${name}`,
});
return cy.request({
method: 'DELETE',

View File

@ -95,24 +95,18 @@ export const ArchiveTable = ({
const columns = useMemo(
() => [
...(uiConfig?.flags?.bulkOperations
? [
{
id: 'Select',
Header: ({ getToggleAllRowsSelectedProps }: any) => (
<Checkbox {...getToggleAllRowsSelectedProps()} />
),
Cell: ({ row }: any) => (
<RowSelectCell
{...row?.getToggleRowSelectedProps?.()}
/>
),
maxWidth: 50,
disableSortBy: true,
hideInMenu: true,
},
]
: []),
{
id: 'Select',
Header: ({ getToggleAllRowsSelectedProps }: any) => (
<Checkbox {...getToggleAllRowsSelectedProps()} />
),
Cell: ({ row }: any) => (
<RowSelectCell {...row?.getToggleRowSelectedProps?.()} />
),
maxWidth: 50,
disableSortBy: true,
hideInMenu: true,
},
{
Header: 'Seen',
width: 85,

View File

@ -43,12 +43,7 @@ export const ArchivedFeatureDeleteConfirm = ({
if (deletedFeatures.length === 0) {
return;
}
if (uiConfig?.flags?.bulkOperations) {
await deleteFeatures(projectId, deletedFeatures);
} else {
await deleteFeature(deletedFeatures[0]);
}
await deleteFeatures(projectId, deletedFeatures);
await refetch();
setToastData({

View File

@ -240,24 +240,18 @@ export const ProjectFeatureToggles = ({
const columns = useMemo(
() => [
...(uiConfig?.flags?.bulkOperations
? [
{
id: 'Select',
Header: ({ getToggleAllRowsSelectedProps }: any) => (
<Checkbox {...getToggleAllRowsSelectedProps()} />
),
Cell: ({ row }: any) => (
<RowSelectCell
{...row?.getToggleRowSelectedProps?.()}
/>
),
maxWidth: 50,
disableSortBy: true,
hideInMenu: true,
},
]
: []),
{
id: 'Select',
Header: ({ getToggleAllRowsSelectedProps }: any) => (
<Checkbox {...getToggleAllRowsSelectedProps()} />
),
Cell: ({ row }: any) => (
<RowSelectCell {...row?.getToggleRowSelectedProps?.()} />
),
maxWidth: 50,
disableSortBy: true,
hideInMenu: true,
},
{
id: 'favorite',
Header: (

View File

@ -45,7 +45,6 @@ export interface IFlags {
crOnVariants?: boolean;
proPlanAutoCharge?: boolean;
notifications?: boolean;
bulkOperations?: boolean;
personalAccessTokensKillSwitch?: boolean;
demo?: boolean;
strategyTitle?: boolean;

View File

@ -67,7 +67,6 @@ exports[`should create default config 1`] = `
},
"flags": {
"anonymiseEventLog": false,
"bulkOperations": false,
"caseInsensitiveInOperators": false,
"cleanClientApi": false,
"crOnVariants": false,
@ -94,7 +93,6 @@ exports[`should create default config 1`] = `
"flagResolver": FlagResolver {
"experiments": {
"anonymiseEventLog": false,
"bulkOperations": false,
"caseInsensitiveInOperators": false,
"cleanClientApi": false,
"crOnVariants": false,

View File

@ -1,3 +1,4 @@
import owasp from 'owasp-password-strength-test';
import { ErrorObject } from 'ajv';
import {
ApiErrorSchema,
@ -9,6 +10,7 @@ import {
UnleashError,
} from './api-error';
import BadDataError from './bad-data-error';
import OwaspValidationError from './owasp-validation-error';
describe('v5 deprecation: backwards compatibility', () => {
it.each(UnleashApiErrorTypes)(
@ -320,3 +322,14 @@ describe('OpenAPI error conversion', () => {
expect(description.includes(illegalValue)).toBeTruthy();
});
});
describe('Error serialization special cases', () => {
it('OwaspValidationErrors: adds `validationErrors` to `details`', () => {
const results = owasp.test('123');
const error = new OwaspValidationError(results);
const json = fromLegacyError(error).toJSON();
expect(json.details!![0].message).toBe(results.errors[0]);
expect(json.details!![0].validationErrors).toBe(results.errors);
});
});

View File

@ -1,6 +1,7 @@
import { v4 as uuidV4 } from 'uuid';
import { FromSchema } from 'json-schema-to-ts';
import { ErrorObject } from 'ajv';
import OwaspValidationError from './owasp-validation-error';
export const UnleashApiErrorTypes = [
'ContentTypeError',
@ -14,7 +15,6 @@ export const UnleashApiErrorTypes = [
'NotFoundError',
'NotImplementedError',
'OperationDeniedError',
'OwaspValidationError',
'PasswordMismatch',
'PasswordMismatchError',
'PasswordUndefinedError',
@ -34,6 +34,7 @@ const UnleashApiErrorTypesWithExtraData = [
'AuthenticationRequired',
'NoAccessError',
'InvalidTokenError',
'OwaspValidationError',
] as const;
const AllUnleashApiErrorTypes = [
@ -136,6 +137,15 @@ type UnleashErrorData =
...ValidationErrorDescription[],
];
}
| {
name: 'OwaspValidationError';
details: [
{
validationErrors: string[];
message: string;
},
];
}
);
export class UnleashError extends Error {
@ -245,6 +255,15 @@ export const fromLegacyError = (e: Error): UnleashError => {
});
}
if (name === 'OwaspValidationError') {
return new UnleashError({
name,
message:
'Password validation failed. Refer to the `details` property.',
details: (e as OwaspValidationError).toJSON().details,
});
}
if (name === 'AuthenticationRequired') {
return new UnleashError({
name,

View File

@ -14,7 +14,6 @@ import { IAuthRequest } from '../../unleash-types';
import { OpenApiService } from '../../../services/openapi-service';
import { emptyResponse } from '../../../openapi/util/standard-responses';
import { BatchFeaturesSchema, createRequestSchema } from '../../../openapi';
import NotFoundError from '../../../error/notfound-error';
import Controller from '../../controller';
const PATH = '/:projectId';
@ -105,9 +104,6 @@ export default class ProjectArchiveController extends Controller {
req: IAuthRequest<IProjectParam, any, BatchFeaturesSchema>,
res: Response<void>,
): Promise<void> {
if (!this.flagResolver.isEnabled('bulkOperations')) {
throw new NotFoundError('Bulk operations are not enabled');
}
const { projectId } = req.params;
const { features } = req.body;
const user = extractUsername(req);
@ -119,9 +115,6 @@ export default class ProjectArchiveController extends Controller {
req: IAuthRequest<IProjectParam, any, BatchFeaturesSchema>,
res: Response<void>,
): Promise<void> {
if (!this.flagResolver.isEnabled('bulkOperations')) {
throw new NotFoundError('Bulk operations are not enabled');
}
const { projectId } = req.params;
const { features } = req.body;
const user = extractUsername(req);
@ -133,10 +126,6 @@ export default class ProjectArchiveController extends Controller {
req: IAuthRequest<IProjectParam, void, BatchFeaturesSchema>,
res: Response,
): Promise<void> {
if (!this.flagResolver.isEnabled('bulkOperations')) {
throw new NotFoundError('Bulk operations are not enabled');
}
const { features } = req.body;
const { projectId } = req.params;
const userName = extractUsername(req);

View File

@ -40,7 +40,6 @@ import {
} from '../../../openapi';
import { OpenApiService, FeatureToggleService } from '../../../services';
import { querySchema } from '../../../schema/feature-schema';
import NotFoundError from '../../../error/notfound-error';
import { BatchStaleSchema } from '../../../openapi/spec/batch-stale-schema';
interface FeatureStrategyParams {
@ -594,10 +593,6 @@ export default class ProjectFeaturesController extends Controller {
req: IAuthRequest<{ projectId: string }, void, BatchStaleSchema>,
res: Response,
): Promise<void> {
if (!this.flagResolver.isEnabled('bulkOperations')) {
throw new NotFoundError('Bulk operations are not enabled');
}
const { features, stale } = req.body;
const { projectId } = req.params;
const userName = extractUsername(req);

View File

@ -24,7 +24,6 @@ import {
import { emptyResponse } from '../../openapi/util/standard-responses';
import FeatureTagService from 'lib/services/feature-tag-service';
import { TagsBulkAddSchema } from '../../openapi/spec/tags-bulk-add-schema';
import NotFoundError from '../../error/notfound-error';
import { IFlagResolver } from '../../types';
const version = 1;
@ -214,9 +213,6 @@ class TagController extends Controller {
req: IAuthRequest<void, void, TagsBulkAddSchema>,
res: Response<TagSchema>,
): Promise<void> {
if (!this.flagResolver.isEnabled('bulkOperations')) {
throw new NotFoundError('Bulk operations are not enabled');
}
const { features, tags } = req.body;
const userName = extractUsername(req);
await this.featureTagService.updateTags(

View File

@ -49,10 +49,6 @@ const flags = {
process.env.UNLEASH_PRO_PLAN_AUTO_CHARGE,
false,
),
bulkOperations: parseEnvVarBoolean(
process.env.UNLEASH_BULK_OPERATIONS,
false,
),
personalAccessTokensKillSwitch: parseEnvVarBoolean(
process.env.UNLEASH_PAT_KILL_SWITCH,
false,

View File

@ -39,7 +39,6 @@ process.nextTick(async () => {
anonymiseEventLog: false,
responseTimeWithAppNameKillSwitch: false,
newProjectOverview: true,
bulkOperations: true,
optimal304: true,
optimal304Differ: false,
},

View File

@ -15,7 +15,6 @@ beforeAll(async () => {
experimental: {
flags: {
strictSchemaValidation: true,
bulkOperations: true,
},
},
});

View File

@ -89,7 +89,6 @@ beforeAll(async () => {
experimental: {
flags: {
strictSchemaValidation: true,
bulkOperations: true,
},
},
},

View File

@ -11,7 +11,6 @@ beforeAll(async () => {
experimental: {
flags: {
strictSchemaValidation: true,
bulkOperations: true,
},
},
});