1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-04-06 01:15:28 +02:00

feat: private projects handle in playground (#4791)

This commit is contained in:
Jaanus Sellin 2023-09-21 11:22:29 +03:00 committed by GitHub
parent 7233143ace
commit 5e6ed0baac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 46 additions and 7 deletions

View File

@ -19,6 +19,7 @@ beforeAll(async () => {
advancedPlayground: true, advancedPlayground: true,
strictSchemaValidation: true, strictSchemaValidation: true,
strategyVariant: true, strategyVariant: true,
privateProjects: true,
}, },
}, },
}, },

View File

@ -4,7 +4,7 @@ import { IUnleashServices } from 'lib/types/services';
import { ALL } from '../../types/models/api-token'; import { ALL } from '../../types/models/api-token';
import { PlaygroundFeatureSchema } from 'lib/openapi/spec/playground-feature-schema'; import { PlaygroundFeatureSchema } from 'lib/openapi/spec/playground-feature-schema';
import { Logger } from '../../logger'; import { Logger } from '../../logger';
import { ISegment, IUnleashConfig } from 'lib/types'; import { IFlagResolver, ISegment, IUnleashConfig } from 'lib/types';
import { offlineUnleashClient } from './offline-unleash-client'; import { offlineUnleashClient } from './offline-unleash-client';
import { FeatureInterface } from 'lib/features/playground/feature-evaluator/feature'; import { FeatureInterface } from 'lib/features/playground/feature-evaluator/feature';
import { import {
@ -16,10 +16,11 @@ import { FeatureConfigurationClient } from '../../types/stores/feature-strategie
import { generateObjectCombinations } from './generateObjectCombinations'; import { generateObjectCombinations } from './generateObjectCombinations';
import groupBy from 'lodash.groupby'; import groupBy from 'lodash.groupby';
import { omitKeys } from '../../util'; import { omitKeys } from '../../util';
import { AdvancedPlaygroundFeatureSchema } from '../../openapi/spec/advanced-playground-feature-schema'; import { AdvancedPlaygroundFeatureSchema } from '../../openapi';
import { AdvancedPlaygroundEnvironmentFeatureSchema } from '../../openapi/spec/advanced-playground-environment-feature-schema'; import { AdvancedPlaygroundEnvironmentFeatureSchema } from '../../openapi/spec/advanced-playground-environment-feature-schema';
import { validateQueryComplexity } from './validateQueryComplexity'; import { validateQueryComplexity } from './validateQueryComplexity';
import { playgroundStrategyEvaluation } from 'lib/openapi'; import { playgroundStrategyEvaluation } from 'lib/openapi';
import { IPrivateProjectChecker } from '../private-project/privateProjectCheckerType';
type EvaluationInput = { type EvaluationInput = {
features: FeatureConfigurationClient[]; features: FeatureConfigurationClient[];
@ -66,16 +67,28 @@ export class PlaygroundService {
private readonly segmentService: ISegmentService; private readonly segmentService: ISegmentService;
private flagResolver: IFlagResolver;
private privateProjectChecker: IPrivateProjectChecker;
constructor( constructor(
config: IUnleashConfig, config: IUnleashConfig,
{ {
featureToggleServiceV2, featureToggleServiceV2,
segmentService, segmentService,
}: Pick<IUnleashServices, 'featureToggleServiceV2' | 'segmentService'>, privateProjectChecker,
}: Pick<
IUnleashServices,
| 'featureToggleServiceV2'
| 'segmentService'
| 'privateProjectChecker'
>,
) { ) {
this.logger = config.getLogger('services/playground-service.ts'); this.logger = config.getLogger('services/playground-service.ts');
this.flagResolver = config.flagResolver;
this.featureToggleService = featureToggleServiceV2; this.featureToggleService = featureToggleServiceV2;
this.segmentService = segmentService; this.segmentService = segmentService;
this.privateProjectChecker = privateProjectChecker;
} }
async evaluateAdvancedQuery( async evaluateAdvancedQuery(
@ -83,10 +96,29 @@ export class PlaygroundService {
environments: string[], environments: string[],
context: SdkContextSchema, context: SdkContextSchema,
limit: number, limit: number,
userId: number,
): Promise<AdvancedPlaygroundFeatureEvaluationResult[]> { ): Promise<AdvancedPlaygroundFeatureEvaluationResult[]> {
const segments = await this.segmentService.getActive(); const segments = await this.segmentService.getActive();
let filteredProjects: typeof projects;
if (this.flagResolver.isEnabled('privateProjects')) {
const accessibleProjects =
await this.privateProjectChecker.getUserAccessibleProjects(
userId,
);
filteredProjects =
projects === ALL
? accessibleProjects
: projects.filter((project) =>
accessibleProjects.includes(project),
);
console.log(accessibleProjects);
}
const environmentFeatures = await Promise.all( const environmentFeatures = await Promise.all(
environments.map((env) => this.resolveFeatures(projects, env)), environments.map((env) =>
this.resolveFeatures(filteredProjects, env),
),
); );
const contexts = generateObjectCombinations(context); const contexts = generateObjectCombinations(context);

View File

@ -20,6 +20,7 @@ import {
advancedPlaygroundViewModel, advancedPlaygroundViewModel,
playgroundViewModel, playgroundViewModel,
} from './playground-view-model'; } from './playground-view-model';
import { IAuthRequest } from '../../routes/unleash-types';
export default class PlaygroundController extends Controller { export default class PlaygroundController extends Controller {
private openApiService: OpenApiService; private openApiService: OpenApiService;
@ -112,9 +113,10 @@ export default class PlaygroundController extends Controller {
} }
async evaluateAdvancedContext( async evaluateAdvancedContext(
req: Request<any, any, AdvancedPlaygroundRequestSchema>, req: IAuthRequest<any, any, AdvancedPlaygroundRequestSchema>,
res: Response<AdvancedPlaygroundResponseSchema>, res: Response<AdvancedPlaygroundResponseSchema>,
): Promise<void> { ): Promise<void> {
const { user } = req;
// used for runtime control, do not remove // used for runtime control, do not remove
const { payload } = this.flagResolver.getVariant('advancedPlayground'); const { payload } = this.flagResolver.getVariant('advancedPlayground');
const limit = const limit =
@ -127,6 +129,7 @@ export default class PlaygroundController extends Controller {
req.body.environments, req.body.environments,
req.body.context, req.body.context,
limit, limit,
user.id,
); );
const response: AdvancedPlaygroundResponseSchema = const response: AdvancedPlaygroundResponseSchema =

View File

@ -20,6 +20,7 @@ import { clientMetricsSchema } from './schema';
import { PartialSome } from '../../types/partial'; import { PartialSome } from '../../types/partial';
import { IPrivateProjectChecker } from '../../features/private-project/privateProjectCheckerType'; import { IPrivateProjectChecker } from '../../features/private-project/privateProjectCheckerType';
import { IFlagResolver } from '../../types'; import { IFlagResolver } from '../../types';
import { ALL_PROJECTS } from '../../util';
export default class ClientInstanceService { export default class ClientInstanceService {
apps = {}; apps = {};
@ -178,7 +179,7 @@ export default class ClientInstanceService {
): Promise<IClientApplication[]> { ): Promise<IClientApplication[]> {
const applications = const applications =
await this.clientApplicationsStore.getAppsForStrategy(query); await this.clientApplicationsStore.getAppsForStrategy(query);
if (this.flagResolver.isEnabled('privateProjects') && userId) { if (this.flagResolver.isEnabled('privateProjects')) {
const accessibleProjects = const accessibleProjects =
await this.privateProjectChecker.getUserAccessibleProjects( await this.privateProjectChecker.getUserAccessibleProjects(
userId, userId,
@ -188,7 +189,7 @@ export default class ClientInstanceService {
...application, ...application,
usage: application.usage?.filter( usage: application.usage?.filter(
(usageItem) => (usageItem) =>
usageItem.project === '*' || usageItem.project === ALL_PROJECTS ||
accessibleProjects.includes(usageItem.project), accessibleProjects.includes(usageItem.project),
), ),
}; };

View File

@ -251,6 +251,7 @@ export const createServices = (
const playgroundService = new PlaygroundService(config, { const playgroundService = new PlaygroundService(config, {
featureToggleServiceV2, featureToggleServiceV2,
segmentService, segmentService,
privateProjectChecker,
}); });
const configurationRevisionService = new ConfigurationRevisionService( const configurationRevisionService = new ConfigurationRevisionService(

View File

@ -63,6 +63,7 @@ beforeAll(async () => {
service = new PlaygroundService(config, { service = new PlaygroundService(config, {
featureToggleServiceV2: featureToggleService, featureToggleServiceV2: featureToggleService,
segmentService, segmentService,
privateProjectChecker,
}); });
}); });