Skip to content

Commit

Permalink
Merge branch 'dev' into dependabot/npm_and_yarn/frontend/multi-9423f4…
Browse files Browse the repository at this point in the history
…c335
  • Loading branch information
danoswaltCL authored Sep 20, 2024
2 parents 8431540 + 9fb219d commit 125d4ba
Show file tree
Hide file tree
Showing 18 changed files with 655 additions and 581 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,16 @@ interface ExperimentPaginationInfo extends PaginationResponse {
* - name
* - context
* - state
* - tags
* - logging
* - filterMode
* - consistencyRule
* - assignmentUnit
* - postExperimentRule
* - enrollmentCompleteCondition
* - group
* - conditions
* - partitions
* - factors
* - experimentSegmentInclusion
* - experimentSegmentExclusion
* - conditionPayload
* - type
* properties:
Expand Down
62 changes: 43 additions & 19 deletions backend/packages/Upgrade/src/api/services/FeatureFlagService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -808,40 +808,58 @@ export class FeatureFlagService {
logger.info({ message: 'Imported feature flags', details: createdFlags });
return fileStatusArray;
}

public async validateImportFeatureFlags(
featureFlagFiles: IFeatureFlagFile[],
logger: UpgradeLogger
): Promise<ValidatedFeatureFlagsError[]> {
logger.info({ message: 'Validate feature flags' });

const featureFlagsIds = featureFlagFiles
.map((featureFlagFile) => {
try {
return JSON.parse(featureFlagFile.fileContent as string).key;
} catch (parseError) {
return null;
}
})
.filter((key) => key !== null);
const parsedFeatureFlags = featureFlagFiles.map((featureFlagFile) => {
try {
return {
fileName: featureFlagFile.fileName,
content: JSON.parse(featureFlagFile.fileContent as string),
};
} catch (parseError) {
logger.error({ message: 'Error in parsing feature flag file', details: parseError });
return {
fileName: featureFlagFile.fileName,
content: null,
};
}
});

const featureFlagsIds = parsedFeatureFlags
.filter((parsedFile) => parsedFile.content !== null)
.map((parsedFile) => parsedFile.content.key);

const existingFeatureFlags = await this.featureFlagRepository.findBy({ key: In(featureFlagsIds) });
const seenKeys = [];

const validationErrors = await Promise.allSettled(
featureFlagFiles.map(async (featureFlagFile) => {
let featureFlag: FeatureFlagImportDataValidation;
try {
featureFlag = JSON.parse(featureFlagFile.fileContent as string);
} catch (parseError) {
logger.error({ message: 'Error in parsing feature flag file', details: parseError });
parsedFeatureFlags.map(async (parsedFile) => {
if (!parsedFile.content) {
return {
fileName: featureFlagFile.fileName,
fileName: parsedFile.fileName,
compatibilityType: FF_COMPATIBILITY_TYPE.INCOMPATIBLE,
};
}

const error = await this.validateImportFeatureFlag(featureFlagFile.fileName, featureFlag, existingFeatureFlags);
const featureFlag = parsedFile.content;
if (seenKeys.includes(featureFlag.key)) {
return {
fileName: parsedFile.fileName,
compatibilityType: FF_COMPATIBILITY_TYPE.INCOMPATIBLE,
};
}
seenKeys.push(featureFlag.key);

const error = await this.validateImportFeatureFlag(parsedFile.fileName, featureFlag, existingFeatureFlags);
return error;
})
);

// Filter out the files that have no promise rejection errors
return validationErrors
.map((result) => {
Expand Down Expand Up @@ -878,16 +896,22 @@ export class FeatureFlagService {
if (keyExists) {
compatibilityType = FF_COMPATIBILITY_TYPE.INCOMPATIBLE;
} else {
const segmentIds = [
const segmentIdsSet = new Set([
...flag.featureFlagSegmentInclusion.flatMap((segmentInclusion) => {
return segmentInclusion.segment.subSegments.map((subSegment) => subSegment.id);
}),
...flag.featureFlagSegmentExclusion.flatMap((segmentExclusion) => {
return segmentExclusion.segment.subSegments.map((subSegment) => subSegment.id);
}),
];
]);

const segmentIds = Array.from(segmentIdsSet);
const segments = await this.segmentService.getSegmentByIds(segmentIds);

if (segmentIds.length !== segments.length) {
compatibilityType = FF_COMPATIBILITY_TYPE.WARNING;
}

segments.forEach((segment) => {
if (segment == undefined) {
compatibilityType = FF_COMPATIBILITY_TYPE.WARNING;
Expand Down
8 changes: 4 additions & 4 deletions backend/packages/Upgrade/src/auth/AuthService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ export class AuthService {
}

public async validateUser(token: string, request: express.Request): Promise<User> {
// env.google.clientId can be a single client ID or multiple comma-separated client IDs
const clientIds = env.google.clientId.split(',');
// env.google.clientId is an array of client IDs
const clientIds = env.google.clientId;
const client = new OAuth2Client(clientIds[0]);
request.logger.info({ message: 'Validating token' });

Expand All @@ -37,8 +37,8 @@ export class AuthService {
} catch (error) {
// If ID token verification fails, try to verify it as an access token
try {
// env.google.serviceAccountId can be a single service account ID or multiple comma-separated service account IDs
const serviceAccountIds = env.google.serviceAccountId.split(',');
// env.google.serviceAccountId is an array of service account IDs
const serviceAccountIds = env.google.serviceAccountId;
const tokenInfo = await client.getTokenInfo(token);

if (!tokenInfo || !serviceAccountIds.includes(tokenInfo.aud)) {
Expand Down
6 changes: 3 additions & 3 deletions backend/packages/Upgrade/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'path';
import pkg from '../package.json';

import { getOsEnv, getOsPath, getOsPaths, normalizePort, toBool } from './lib/env';
import { getOsEnvOptional, toNumber, parseAdminUsers } from './lib/env/utils';
import { getOsEnvOptional, toNumber, parseAdminUsers, getOsEnvArray } from './lib/env/utils';

/**
* Load .env file or for tests the .env.test file.
Expand Down Expand Up @@ -78,8 +78,8 @@ export const env = {
emailBucket: getOsEnv('EMAIL_BUCKET'),
},
google: {
clientId: getOsEnv('GOOGLE_CLIENT_ID'),
serviceAccountId: getOsEnv('GOOGLE_SERVICE_ACCOUNT_ID'),
clientId: getOsEnvArray('GOOGLE_CLIENT_ID'),
serviceAccountId: getOsEnvArray('GOOGLE_SERVICE_ACCOUNT_ID'),
domainName: getOsEnvOptional('DOMAIN_NAME'),
},
scheduler: {
Expand Down
Loading

0 comments on commit 125d4ba

Please sign in to comment.