mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-02 03:25:56 +01:00
Disable repository types (#1908)
Disable repository types via global config for Git, Mercurial and Subversion. It is only possible to disable a type, if no repositories of this type exist. Also prevent repository creation if no type is allowed at all to catch nasty errors. Co-authored-by: Konstantin Schaper <konstantin.schaper@cloudogu.com>
This commit is contained in:
@@ -37,6 +37,7 @@ import sonia.scm.repository.Compatibility;
|
||||
public class SvnConfigDto extends HalRepresentation implements UpdateSvnConfigDto {
|
||||
|
||||
private boolean disabled;
|
||||
private boolean allowDisable;
|
||||
|
||||
private boolean enabledGZip;
|
||||
private Compatibility compatibility;
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.mapstruct.AfterMapping;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MappingTarget;
|
||||
import sonia.scm.config.ConfigurationPermissions;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.SvnConfig;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -43,6 +44,8 @@ public abstract class SvnConfigToSvnConfigDtoMapper extends BaseMapper<SvnConfig
|
||||
|
||||
@Inject
|
||||
private ScmPathInfoStore scmPathInfoStore;
|
||||
@Inject
|
||||
private RepositoryManager repositoryManager;
|
||||
|
||||
@AfterMapping
|
||||
void appendLinks(SvnConfig config, @MappingTarget SvnConfigDto target) {
|
||||
@@ -51,6 +54,7 @@ public abstract class SvnConfigToSvnConfigDtoMapper extends BaseMapper<SvnConfig
|
||||
linksBuilder.single(link("update", update()));
|
||||
}
|
||||
target.add(linksBuilder.build());
|
||||
target.setAllowDisable(repositoryManager.getAll().stream().noneMatch(r -> r.getType().equals("svn")));
|
||||
}
|
||||
|
||||
private String self() {
|
||||
|
||||
@@ -21,87 +21,65 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
import React from "react";
|
||||
import { withTranslation, WithTranslation } from "react-i18next";
|
||||
import React, { FC, useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Links } from "@scm-manager/ui-types";
|
||||
import { Checkbox, Select } from "@scm-manager/ui-components";
|
||||
|
||||
type Configuration = {
|
||||
disabled: boolean;
|
||||
allowDisable: boolean;
|
||||
compatibility: string;
|
||||
enabledGZip: boolean;
|
||||
_links: Links;
|
||||
};
|
||||
|
||||
type Props = WithTranslation & {
|
||||
type Props = {
|
||||
initialConfiguration: Configuration;
|
||||
readOnly: boolean;
|
||||
|
||||
onConfigurationChange: (p1: Configuration, p2: boolean) => void;
|
||||
};
|
||||
|
||||
type State = Configuration;
|
||||
const SvnConfigurationForm: FC<Props> = ({ initialConfiguration, readOnly, onConfigurationChange }) => {
|
||||
const [t] = useTranslation("plugins");
|
||||
const [configuration, setConfiguration] = useState(initialConfiguration);
|
||||
|
||||
class SvnConfigurationForm extends React.Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
...props.initialConfiguration,
|
||||
};
|
||||
}
|
||||
useEffect(() => setConfiguration(initialConfiguration), [initialConfiguration]);
|
||||
useEffect(() => onConfigurationChange(configuration, true), [configuration]);
|
||||
|
||||
handleChange = (value: any, name?: string) => {
|
||||
if (!name) {
|
||||
throw new Error("required name not set");
|
||||
}
|
||||
this.setState(
|
||||
// @ts-ignore
|
||||
{
|
||||
[name]: value,
|
||||
},
|
||||
() => this.props.onConfigurationChange(this.state, true)
|
||||
);
|
||||
};
|
||||
const options = ["NONE", "PRE14", "PRE15", "PRE16", "PRE17", "WITH17"].map((option: string) => ({
|
||||
value: option,
|
||||
label: t("scm-svn-plugin.config.compatibility-values." + option.toLowerCase())
|
||||
}));
|
||||
|
||||
compatibilityOptions = (values: string[]) => {
|
||||
const options = [];
|
||||
for (const value of values) {
|
||||
options.push(this.compatibilityOption(value));
|
||||
}
|
||||
return options;
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<Select
|
||||
name="compatibility"
|
||||
label={t("scm-svn-plugin.config.compatibility")}
|
||||
helpText={t("scm-svn-plugin.config.compatibilityHelpText")}
|
||||
value={configuration.compatibility}
|
||||
options={options}
|
||||
onChange={option => setConfiguration({ ...configuration, compatibility: option })}
|
||||
/>
|
||||
<Checkbox
|
||||
name="enabledGZip"
|
||||
label={t("scm-svn-plugin.config.enabledGZip")}
|
||||
helpText={t("scm-svn-plugin.config.enabledGZipHelpText")}
|
||||
checked={configuration.enabledGZip}
|
||||
onChange={value => setConfiguration({ ...configuration, enabledGZip: value })}
|
||||
disabled={readOnly}
|
||||
/>
|
||||
<Checkbox
|
||||
name="disabled"
|
||||
label={t("scm-svn-plugin.config.disabled")}
|
||||
helpText={t("scm-svn-plugin.config.disabledHelpText")}
|
||||
checked={configuration.disabled}
|
||||
onChange={value => setConfiguration({ ...configuration, disabled: value })}
|
||||
disabled={readOnly || !configuration.allowDisable}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
compatibilityOption = (value: string) => {
|
||||
return {
|
||||
value,
|
||||
label: this.props.t("scm-svn-plugin.config.compatibility-values." + value.toLowerCase()),
|
||||
};
|
||||
};
|
||||
|
||||
render() {
|
||||
const { readOnly, t } = this.props;
|
||||
const compatibilityOptions = this.compatibilityOptions(["NONE", "PRE14", "PRE15", "PRE16", "PRE17", "WITH17"]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Select
|
||||
name="compatibility"
|
||||
label={t("scm-svn-plugin.config.compatibility")}
|
||||
helpText={t("scm-svn-plugin.config.compatibilityHelpText")}
|
||||
value={this.state.compatibility}
|
||||
options={compatibilityOptions}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
<Checkbox
|
||||
name="enabledGZip"
|
||||
label={t("scm-svn-plugin.config.enabledGZip")}
|
||||
helpText={t("scm-svn-plugin.config.enabledGZipHelpText")}
|
||||
checked={this.state.enabledGZip}
|
||||
onChange={this.handleChange}
|
||||
disabled={readOnly}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withTranslation("plugins")(SvnConfigurationForm);
|
||||
export default SvnConfigurationForm;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"enabledGZip": "GZip Compression aktivieren",
|
||||
"enabledGZipHelpText": "Aktiviert GZip Kompression für SVN Responses",
|
||||
"disabled": "Deaktiviert",
|
||||
"disabledHelpText": "Aktiviert oder deaktiviert das SVN Plugin",
|
||||
"disabledHelpText": "Aktiviert oder deaktiviert das SVN Plugin. Nur erlaubt, wenn keine Subversion Repositories existieren.",
|
||||
"required": "Dieser Konfigurationswert wird benötigt"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"enabledGZip": "Enable GZip Compression",
|
||||
"enabledGZipHelpText": "Enable GZip compression for SVN responses.",
|
||||
"disabled": "Disabled",
|
||||
"disabledHelpText": "Enable or disable the SVN plugin",
|
||||
"disabledHelpText": "Enable or disable the SVN plugin. Only allowed if no Subversion repositories exist.",
|
||||
"required": "This configuration value is required"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.mockito.Answers;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.SvnConfig;
|
||||
import sonia.scm.repository.SvnRepositoryHandler;
|
||||
import sonia.scm.web.RestDispatcher;
|
||||
@@ -68,6 +69,9 @@ public class SvnConfigResourceTest {
|
||||
|
||||
private final URI baseUri = URI.create("/");
|
||||
|
||||
@Mock
|
||||
private RepositoryManager repositoryManager;
|
||||
|
||||
@InjectMocks
|
||||
private SvnConfigDtoToSvnConfigMapperImpl dtoToConfigMapper;
|
||||
|
||||
|
||||
@@ -37,9 +37,12 @@ import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.repository.Compatibility;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.RepositoryTestData;
|
||||
import sonia.scm.repository.SvnConfig;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@@ -50,11 +53,14 @@ import static org.mockito.Mockito.when;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SvnConfigToSvnConfigDtoMapperTest {
|
||||
|
||||
private URI baseUri = URI.create("http://example.com/base/");
|
||||
private final URI baseUri = URI.create("http://example.com/base/");
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private ScmPathInfoStore scmPathInfoStore;
|
||||
|
||||
@Mock
|
||||
private RepositoryManager manager;
|
||||
|
||||
@InjectMocks
|
||||
private SvnConfigToSvnConfigDtoMapperImpl mapper;
|
||||
|
||||
@@ -80,10 +86,12 @@ public class SvnConfigToSvnConfigDtoMapperTest {
|
||||
public void shouldMapFields() {
|
||||
SvnConfig config = createConfiguration();
|
||||
|
||||
when(manager.getAll()).thenReturn(Collections.singleton(RepositoryTestData.create42Puzzle("svn")));
|
||||
when(subject.isPermitted("configuration:write:svn")).thenReturn(true);
|
||||
SvnConfigDto dto = mapper.map(config);
|
||||
|
||||
assertTrue(dto.isDisabled());
|
||||
assertFalse(dto.isAllowDisable());
|
||||
|
||||
assertEquals(Compatibility.PRE15, dto.getCompatibility());
|
||||
assertTrue(dto.isEnabledGZip());
|
||||
@@ -92,6 +100,17 @@ public class SvnConfigToSvnConfigDtoMapperTest {
|
||||
assertEquals(expectedBaseUri.toString(), dto.getLinks().getLinkBy("update").get().getHref());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAllowDisableIfNoSubversionRepositoriesExist() {
|
||||
SvnConfig config = createConfiguration();
|
||||
|
||||
when(manager.getAll()).thenReturn(Collections.singleton(RepositoryTestData.create42Puzzle("git")));
|
||||
when(subject.isPermitted("configuration:write:svn")).thenReturn(true);
|
||||
SvnConfigDto dto = mapper.map(config);
|
||||
|
||||
assertTrue(dto.isAllowDisable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldMapFieldsWithoutUpdate() {
|
||||
SvnConfig config = createConfiguration();
|
||||
|
||||
Reference in New Issue
Block a user