mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: check if child and parent are in the same project (#5093)
This commit is contained in:
		
							parent
							
								
									7195a63e56
								
							
						
					
					
						commit
						56892c54d9
					
				@ -96,9 +96,10 @@ export class DependentFeaturesService {
 | 
				
			|||||||
            );
 | 
					            );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const [children, parentExists] = await Promise.all([
 | 
					        const [children, parentExists, sameProject] = await Promise.all([
 | 
				
			||||||
            this.dependentFeaturesReadModel.getChildren([child]),
 | 
					            this.dependentFeaturesReadModel.getChildren([child]),
 | 
				
			||||||
            this.featuresReadModel.featureExists(parent),
 | 
					            this.featuresReadModel.featureExists(parent),
 | 
				
			||||||
 | 
					            this.featuresReadModel.featuresInTheSameProject(child, parent),
 | 
				
			||||||
        ]);
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (children.length > 0) {
 | 
					        if (children.length > 0) {
 | 
				
			||||||
@ -113,6 +114,12 @@ export class DependentFeaturesService {
 | 
				
			|||||||
            );
 | 
					            );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!sameProject) {
 | 
				
			||||||
 | 
					            throw new InvalidOperationError(
 | 
				
			||||||
 | 
					                'Parent and child features should be in the same project',
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const featureDependency: FeatureDependency =
 | 
					        const featureDependency: FeatureDependency =
 | 
				
			||||||
            enabled === false
 | 
					            enabled === false
 | 
				
			||||||
                ? {
 | 
					                ? {
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,9 @@ import {
 | 
				
			|||||||
    FEATURE_DEPENDENCY_ADDED,
 | 
					    FEATURE_DEPENDENCY_ADDED,
 | 
				
			||||||
    FEATURE_DEPENDENCY_REMOVED,
 | 
					    FEATURE_DEPENDENCY_REMOVED,
 | 
				
			||||||
    IEventStore,
 | 
					    IEventStore,
 | 
				
			||||||
 | 
					    IUser,
 | 
				
			||||||
} from '../../types';
 | 
					} from '../../types';
 | 
				
			||||||
 | 
					import { ProjectService } from '../../services';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let app: IUnleashTest;
 | 
					let app: IUnleashTest;
 | 
				
			||||||
let db: ITestDb;
 | 
					let db: ITestDb;
 | 
				
			||||||
@ -34,6 +36,15 @@ beforeAll(async () => {
 | 
				
			|||||||
    eventStore = db.stores.eventStore;
 | 
					    eventStore = db.stores.eventStore;
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const createProject = async (name: string) => {
 | 
				
			||||||
 | 
					    await db.stores.projectStore.create({
 | 
				
			||||||
 | 
					        name: name,
 | 
				
			||||||
 | 
					        description: '',
 | 
				
			||||||
 | 
					        id: name,
 | 
				
			||||||
 | 
					        mode: 'open' as const,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getRecordedEventTypesForDependencies = async () =>
 | 
					const getRecordedEventTypesForDependencies = async () =>
 | 
				
			||||||
    (await eventStore.getEvents())
 | 
					    (await eventStore.getEvents())
 | 
				
			||||||
        .map((event) => event.type)
 | 
					        .map((event) => event.type)
 | 
				
			||||||
@ -207,3 +218,19 @@ test('should not allow to add dependency to self', async () => {
 | 
				
			|||||||
        403,
 | 
					        403,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test('should not allow to add dependency to feature from another project', async () => {
 | 
				
			||||||
 | 
					    const child = uuidv4();
 | 
				
			||||||
 | 
					    const parent = uuidv4();
 | 
				
			||||||
 | 
					    await app.createFeature(parent);
 | 
				
			||||||
 | 
					    await createProject('another-project');
 | 
				
			||||||
 | 
					    await app.createFeature(child, 'another-project');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await addFeatureDependency(
 | 
				
			||||||
 | 
					        child,
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            feature: parent,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        403,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
@ -4,4 +4,11 @@ export class FakeFeaturesReadModel implements IFeaturesReadModel {
 | 
				
			|||||||
    featureExists(): Promise<boolean> {
 | 
					    featureExists(): Promise<boolean> {
 | 
				
			||||||
        return Promise.resolve(false);
 | 
					        return Promise.resolve(false);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    featuresInTheSameProject(
 | 
				
			||||||
 | 
					        featureA: string,
 | 
				
			||||||
 | 
					        featureB: string,
 | 
				
			||||||
 | 
					    ): Promise<boolean> {
 | 
				
			||||||
 | 
					        return Promise.resolve(true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -16,4 +16,14 @@ export class FeaturesReadModel implements IFeaturesReadModel {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return rows.length > 0;
 | 
					        return rows.length > 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async featuresInTheSameProject(
 | 
				
			||||||
 | 
					        featureA: string,
 | 
				
			||||||
 | 
					        featureB: string,
 | 
				
			||||||
 | 
					    ): Promise<boolean> {
 | 
				
			||||||
 | 
					        const rows = await this.db('features')
 | 
				
			||||||
 | 
					            .countDistinct('project as count')
 | 
				
			||||||
 | 
					            .whereIn('name', [featureA, featureB]);
 | 
				
			||||||
 | 
					        return Number(rows[0].count) === 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,7 @@
 | 
				
			|||||||
export interface IFeaturesReadModel {
 | 
					export interface IFeaturesReadModel {
 | 
				
			||||||
    featureExists(parent: string): Promise<boolean>;
 | 
					    featureExists(parent: string): Promise<boolean>;
 | 
				
			||||||
 | 
					    featuresInTheSameProject(
 | 
				
			||||||
 | 
					        featureA: string,
 | 
				
			||||||
 | 
					        featureB: string,
 | 
				
			||||||
 | 
					    ): Promise<boolean>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user