1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-12-22 19:07:54 +01: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 { IChangeRequest } from 'component/changeRequest/changeRequest.types';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
const StyledContainer = styled('div')(({ theme }) => ({
display: 'grid',
@ -42,6 +43,10 @@ const FeatureSettingsProjectConfirm = ({
const currentProjectId = useRequiredPathParam('projectId');
const { project } = useProject(projectId);
const { isChangeRequestConfiguredInAnyEnv } =
useChangeRequestsEnabled(projectId);
const targetProjectHasChangeRequestsEnabled =
isChangeRequestConfiguredInAnyEnv();
const hasSameEnvironments: boolean = useMemo(() => {
return arraysHaveSameItems(
feature.environments.map(env => env.name),
@ -55,7 +60,11 @@ const FeatureSettingsProjectConfirm = ({
return (
<ConditionallyRender
condition={hasSameEnvironments && !hasPendingChangeRequests}
condition={
hasSameEnvironments &&
!hasPendingChangeRequests &&
!targetProjectHasChangeRequestsEnabled
}
show={
<Dialogue
open={open}
@ -82,26 +91,32 @@ const FeatureSettingsProjectConfirm = ({
open={open}
onClick={onClose}
title="Confirm change project"
primaryButtonText="OK"
primaryButtonText="Close"
>
<StyledContainer>
<StyledAlert severity="warning">
Incompatible project environments
Cannot proceed with the move
</StyledAlert>
<p>
In order to move a feature toggle between two
projects, both projects must have the exact same
environments enabled.
</p>
<ConditionallyRender
condition={!hasSameEnvironments}
show={
<p>
In order to move a feature toggle between
two projects, both projects must have the
exact same environments enabled.
</p>
}
/>
<ConditionallyRender
condition={hasPendingChangeRequests}
show={
<>
<p>
In addition the feature toggle must not
have any pending change requests. This
feature toggle is currently referenced
in the following change requests:
The feature toggle must not have any
pending change requests. This feature
toggle is currently referenced in the
following change requests:
</p>
<StyledList>
{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>
</Dialogue>
}

View File

@ -1350,6 +1350,15 @@ class FeatureToggleService {
newProject: string,
createdBy: string,
): 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 oldProject = feature.project;
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 () => {
const featureName = 'ToggleWithSegments';
const clonedFeatureName = 'AWholeNewFeatureToggle';