mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-31 01:16:01 +02:00
feat: Anonimize demo users list flag view (#7432)
This commit is contained in:
parent
ea1221c45e
commit
70c7e3f978
@ -1,4 +1,4 @@
|
||||
import type { IFeatureOverview } from '../../types';
|
||||
import type { IFeatureSearchOverview } from '../../types';
|
||||
import type {
|
||||
IFeatureSearchParams,
|
||||
IQueryParam,
|
||||
@ -9,7 +9,7 @@ export default class FakeFeatureSearchStore implements IFeatureSearchStore {
|
||||
searchFeatures(
|
||||
params: IFeatureSearchParams,
|
||||
queryParams: IQueryParam[],
|
||||
): Promise<{ features: IFeatureOverview[]; total: number }> {
|
||||
): Promise<{ features: IFeatureSearchOverview[]; total: number }> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import type { Response } from 'express';
|
||||
import Controller from '../../routes/controller';
|
||||
import type { FeatureSearchService, OpenApiService } from '../../services';
|
||||
import {
|
||||
type IFeatureSearchOverview,
|
||||
type IFlagResolver,
|
||||
type IUnleashConfig,
|
||||
type IUnleashServices,
|
||||
@ -12,6 +13,7 @@ import type { Logger } from '../../logger';
|
||||
import {
|
||||
createResponseSchema,
|
||||
getStandardResponses,
|
||||
type SearchFeaturesSchema,
|
||||
searchFeaturesSchema,
|
||||
} from '../../openapi';
|
||||
import type { IAuthRequest } from '../../routes/unleash-types';
|
||||
@ -20,6 +22,7 @@ import {
|
||||
featureSearchQueryParameters,
|
||||
} from '../../openapi/spec/feature-search-query-parameters';
|
||||
import { normalizeQueryParams } from './search-utils';
|
||||
import { anonymise } from '../../util';
|
||||
|
||||
const PATH = '/features';
|
||||
|
||||
@ -71,9 +74,24 @@ export default class FeatureSearchController extends Controller {
|
||||
});
|
||||
}
|
||||
|
||||
maybeAnonymise(
|
||||
features: IFeatureSearchOverview[],
|
||||
): IFeatureSearchOverview[] {
|
||||
if (this.flagResolver.isEnabled('anonymiseEventLog')) {
|
||||
return features.map((feature) => ({
|
||||
...feature,
|
||||
createdBy: {
|
||||
...feature.createdBy,
|
||||
name: anonymise(feature.createdBy.name),
|
||||
},
|
||||
}));
|
||||
}
|
||||
return features;
|
||||
}
|
||||
|
||||
async searchFeatures(
|
||||
req: IAuthRequest<any, any, any, FeatureSearchQueryParameters>,
|
||||
res: Response,
|
||||
res: Response<SearchFeaturesSchema>,
|
||||
): Promise<void> {
|
||||
const {
|
||||
query,
|
||||
@ -131,7 +149,7 @@ export default class FeatureSearchController extends Controller {
|
||||
res,
|
||||
searchFeaturesSchema.$id,
|
||||
serializeDates({
|
||||
features,
|
||||
features: this.maybeAnonymise(features),
|
||||
total,
|
||||
}),
|
||||
);
|
||||
|
@ -2,14 +2,14 @@ import type {
|
||||
IFeatureSearchParams,
|
||||
IQueryParam,
|
||||
} from '../feature-toggle/types/feature-toggle-strategies-store-type';
|
||||
import type { IFeatureOverview } from '../../types';
|
||||
import type { IFeatureSearchOverview } from '../../types';
|
||||
|
||||
export interface IFeatureSearchStore {
|
||||
searchFeatures(
|
||||
params: IFeatureSearchParams,
|
||||
queryParams: IQueryParam[],
|
||||
): Promise<{
|
||||
features: IFeatureOverview[];
|
||||
features: IFeatureSearchOverview[];
|
||||
total: number;
|
||||
}>;
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import metricsHelper from '../../util/metrics-helper';
|
||||
import { DB_TIME } from '../../metric-events';
|
||||
import type { Logger, LogProvider } from '../../logger';
|
||||
import type {
|
||||
IFeatureOverview,
|
||||
IFeatureSearchOverview,
|
||||
IFeatureSearchStore,
|
||||
IFlagResolver,
|
||||
@ -21,8 +20,8 @@ import { applyGenericQueryParams, applySearchFilters } from './search-utils';
|
||||
import type { FeatureSearchEnvironmentSchema } from '../../openapi/spec/feature-search-environment-schema';
|
||||
import { generateImageUrl } from '../../util';
|
||||
|
||||
const sortEnvironments = (overview: IFeatureOverview[]) => {
|
||||
return overview.map((data: IFeatureOverview) => ({
|
||||
const sortEnvironments = (overview: IFeatureSearchOverview[]) => {
|
||||
return overview.map((data: IFeatureSearchOverview) => ({
|
||||
...data,
|
||||
environments: data.environments
|
||||
.filter((f) => f.name)
|
||||
@ -106,7 +105,7 @@ class FeatureSearchStore implements IFeatureSearchStore {
|
||||
}: IFeatureSearchParams,
|
||||
queryParams: IQueryParam[],
|
||||
): Promise<{
|
||||
features: IFeatureOverview[];
|
||||
features: IFeatureSearchOverview[];
|
||||
total: number;
|
||||
}> {
|
||||
const stopTimer = this.timer('searchFeatures');
|
||||
@ -325,7 +324,9 @@ class FeatureSearchStore implements IFeatureSearchStore {
|
||||
rows,
|
||||
featureLifecycleEnabled,
|
||||
);
|
||||
const features = sortEnvironments(overview);
|
||||
const features = sortEnvironments(
|
||||
overview,
|
||||
) as IFeatureSearchOverview[];
|
||||
return {
|
||||
features,
|
||||
total: Number(rows[0].total) || 0,
|
||||
|
@ -22,6 +22,7 @@ beforeAll(async () => {
|
||||
flags: {
|
||||
strictSchemaValidation: true,
|
||||
featureLifecycle: true,
|
||||
anonymiseEventLog: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -186,7 +187,7 @@ test('should search matching features by name', async () => {
|
||||
name: 'my_feature_a',
|
||||
createdBy: {
|
||||
id: 1,
|
||||
name: 'user@getunleash.io',
|
||||
name: '3957b71c0@unleash.run',
|
||||
imageUrl:
|
||||
'https://gravatar.com/avatar/3957b71c0a6d2528f03b423f432ed2efe855d263400f960248a1080493d9d68a?s=42&d=retro&r=g',
|
||||
},
|
||||
@ -195,7 +196,7 @@ test('should search matching features by name', async () => {
|
||||
name: 'my_feature_b',
|
||||
createdBy: {
|
||||
id: 1,
|
||||
name: 'user@getunleash.io',
|
||||
name: '3957b71c0@unleash.run',
|
||||
imageUrl:
|
||||
'https://gravatar.com/avatar/3957b71c0a6d2528f03b423f432ed2efe855d263400f960248a1080493d9d68a?s=42&d=retro&r=g',
|
||||
},
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
CREATE_FEATURE_STRATEGY,
|
||||
DELETE_FEATURE,
|
||||
DELETE_FEATURE_STRATEGY,
|
||||
type FeatureToggleView,
|
||||
type IFlagResolver,
|
||||
type IUnleashConfig,
|
||||
type IUnleashServices,
|
||||
@ -52,6 +53,7 @@ import type {
|
||||
UnleashTransaction,
|
||||
} from '../../db/transaction';
|
||||
import { BadDataError } from '../../error';
|
||||
import { anonymise } from '../../util';
|
||||
|
||||
interface FeatureStrategyParams {
|
||||
projectId: string;
|
||||
@ -694,9 +696,25 @@ export default class ProjectFeaturesController extends Controller {
|
||||
);
|
||||
}
|
||||
|
||||
maybeAnonymise(feature: FeatureToggleView): FeatureToggleView {
|
||||
if (
|
||||
this.flagResolver.isEnabled('anonymiseEventLog') &&
|
||||
feature.createdBy
|
||||
) {
|
||||
return {
|
||||
...feature,
|
||||
createdBy: {
|
||||
...feature.createdBy,
|
||||
name: anonymise(feature.createdBy?.name),
|
||||
},
|
||||
};
|
||||
}
|
||||
return feature;
|
||||
}
|
||||
|
||||
async getFeature(
|
||||
req: IAuthRequest<FeatureParams, any, any, any>,
|
||||
res: Response,
|
||||
res: Response<FeatureSchema>,
|
||||
): Promise<void> {
|
||||
const { featureName, projectId } = req.params;
|
||||
const { variantEnvironments } = req.query;
|
||||
@ -708,7 +726,8 @@ export default class ProjectFeaturesController extends Controller {
|
||||
environmentVariants: variantEnvironments === 'true',
|
||||
userId: user.id,
|
||||
});
|
||||
res.status(200).json(feature);
|
||||
|
||||
res.status(200).json(serializeDates(this.maybeAnonymise(feature)));
|
||||
}
|
||||
|
||||
async updateFeature(
|
||||
|
@ -18,7 +18,14 @@ let db: ITestDb;
|
||||
|
||||
beforeAll(async () => {
|
||||
db = await dbInit('feature_strategy_auth_api_serial', getLogger);
|
||||
app = await setupAppWithAuth(db.stores);
|
||||
app = await setupAppWithAuth(db.stores, {
|
||||
experimental: {
|
||||
flags: {
|
||||
strictSchemaValidation: true,
|
||||
anonymiseEventLog: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
@ -161,7 +168,7 @@ test('Should read flag creator', async () => {
|
||||
|
||||
expect(feature.createdBy).toEqual({
|
||||
id: user.id,
|
||||
name: 'user@getunleash.io',
|
||||
name: '3957b71c0@unleash.run',
|
||||
imageUrl:
|
||||
'https://gravatar.com/avatar/3957b71c0a6d2528f03b423f432ed2efe855d263400f960248a1080493d9d68a?s=42&d=retro&r=g',
|
||||
});
|
||||
|
@ -255,7 +255,7 @@ export type IFeatureSearchOverview = Exclude<
|
||||
createdBy: {
|
||||
id: number;
|
||||
name: string;
|
||||
imageUrl: string | null;
|
||||
imageUrl: string;
|
||||
};
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user