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

feat: stop change project on change request enabled (#3391)

This commit is contained in:
Mateusz Kwasniewski 2023-03-28 11:28:22 +02:00 committed by GitHub
parent 585df244e5
commit 3b311f74c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 65 additions and 12 deletions

View File

@ -8,6 +8,7 @@ import { Alert, List, ListItem, styled } from '@mui/material';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { IChangeRequest } from 'component/changeRequest/changeRequest.types'; import { IChangeRequest } from 'component/changeRequest/changeRequest.types';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
const StyledContainer = styled('div')(({ theme }) => ({ const StyledContainer = styled('div')(({ theme }) => ({
display: 'grid', display: 'grid',
@ -42,6 +43,10 @@ const FeatureSettingsProjectConfirm = ({
const currentProjectId = useRequiredPathParam('projectId'); const currentProjectId = useRequiredPathParam('projectId');
const { project } = useProject(projectId); const { project } = useProject(projectId);
const { isChangeRequestConfiguredInAnyEnv } =
useChangeRequestsEnabled(projectId);
const targetProjectHasChangeRequestsEnabled =
isChangeRequestConfiguredInAnyEnv();
const hasSameEnvironments: boolean = useMemo(() => { const hasSameEnvironments: boolean = useMemo(() => {
return arraysHaveSameItems( return arraysHaveSameItems(
feature.environments.map(env => env.name), feature.environments.map(env => env.name),
@ -55,7 +60,11 @@ const FeatureSettingsProjectConfirm = ({
return ( return (
<ConditionallyRender <ConditionallyRender
condition={hasSameEnvironments && !hasPendingChangeRequests} condition={
hasSameEnvironments &&
!hasPendingChangeRequests &&
!targetProjectHasChangeRequestsEnabled
}
show={ show={
<Dialogue <Dialogue
open={open} open={open}
@ -82,26 +91,32 @@ const FeatureSettingsProjectConfirm = ({
open={open} open={open}
onClick={onClose} onClick={onClose}
title="Confirm change project" title="Confirm change project"
primaryButtonText="OK" primaryButtonText="Close"
> >
<StyledContainer> <StyledContainer>
<StyledAlert severity="warning"> <StyledAlert severity="warning">
Incompatible project environments Cannot proceed with the move
</StyledAlert> </StyledAlert>
<p>
In order to move a feature toggle between two <ConditionallyRender
projects, both projects must have the exact same condition={!hasSameEnvironments}
environments enabled. show={
</p> <p>
In order to move a feature toggle between
two projects, both projects must have the
exact same environments enabled.
</p>
}
/>
<ConditionallyRender <ConditionallyRender
condition={hasPendingChangeRequests} condition={hasPendingChangeRequests}
show={ show={
<> <>
<p> <p>
In addition the feature toggle must not The feature toggle must not have any
have any pending change requests. This pending change requests. This feature
feature toggle is currently referenced toggle is currently referenced in the
in the following change requests: following change requests:
</p> </p>
<StyledList> <StyledList>
{changeRequests?.map(changeRequest => { {changeRequests?.map(changeRequest => {
@ -122,6 +137,21 @@ const FeatureSettingsProjectConfirm = ({
</> </>
} }
/> />
<ConditionallyRender
condition={targetProjectHasChangeRequestsEnabled}
show={
<p>
You're not allowed to move the feature to
project{' '}
<Link
to={`/projects/${projectId}/settings/change-requests`}
>
{projectId}
</Link>
. This project has change requests enabled.
</p>
}
/>
</StyledContainer> </StyledContainer>
</Dialogue> </Dialogue>
} }

View File

@ -1350,6 +1350,15 @@ class FeatureToggleService {
newProject: string, newProject: string,
createdBy: string, createdBy: string,
): Promise<void> { ): Promise<void> {
const changeRequestEnabled =
await this.changeRequestAccessReadModel.isChangeRequestsEnabledForProject(
newProject,
);
if (changeRequestEnabled) {
throw new NoAccessError(
`Changing project not allowed. Project ${newProject} has change requests enabled.`,
);
}
const feature = await this.featureToggleStore.get(featureName); const feature = await this.featureToggleStore.get(featureName);
const oldProject = feature.project; const oldProject = feature.project;
feature.project = newProject; feature.project = newProject;

View File

@ -354,6 +354,20 @@ test('cloning a feature toggle not allowed for change requests enabled', async (
); );
}); });
test('changing to a project with change requests enabled should not be allowed', async () => {
await db.rawDatabase('change_request_settings').insert({
project: 'default',
environment: 'default',
});
await expect(
service.changeProject('newToggleName', 'default', 'user'),
).rejects.toEqual(
new NoAccessError(
`Changing project not allowed. Project default has change requests enabled.`,
),
);
});
test('Cloning a feature toggle also clones segments correctly', async () => { test('Cloning a feature toggle also clones segments correctly', async () => {
const featureName = 'ToggleWithSegments'; const featureName = 'ToggleWithSegments';
const clonedFeatureName = 'AWholeNewFeatureToggle'; const clonedFeatureName = 'AWholeNewFeatureToggle';