mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-08 06:25:45 +01:00
Merged in bugfix/disable_repository_config (pull request #218)
Bugfix: Disable repository config without permission
This commit is contained in:
@@ -8,6 +8,7 @@ import sonia.scm.repository.GitRepositoryConfig;
|
|||||||
import sonia.scm.repository.NamespaceAndName;
|
import sonia.scm.repository.NamespaceAndName;
|
||||||
import sonia.scm.repository.Repository;
|
import sonia.scm.repository.Repository;
|
||||||
import sonia.scm.repository.RepositoryManager;
|
import sonia.scm.repository.RepositoryManager;
|
||||||
|
import sonia.scm.repository.RepositoryPermissions;
|
||||||
import sonia.scm.store.ConfigurationStore;
|
import sonia.scm.store.ConfigurationStore;
|
||||||
import sonia.scm.web.GitVndMediaType;
|
import sonia.scm.web.GitVndMediaType;
|
||||||
|
|
||||||
@@ -50,6 +51,7 @@ public class GitRepositoryConfigResource {
|
|||||||
})
|
})
|
||||||
public Response getRepositoryConfig(@PathParam("namespace") String namespace, @PathParam("name") String name) {
|
public Response getRepositoryConfig(@PathParam("namespace") String namespace, @PathParam("name") String name) {
|
||||||
Repository repository = getRepository(namespace, name);
|
Repository repository = getRepository(namespace, name);
|
||||||
|
RepositoryPermissions.read(repository).check();
|
||||||
ConfigurationStore<GitRepositoryConfig> repositoryConfigStore = getStore(repository);
|
ConfigurationStore<GitRepositoryConfig> repositoryConfigStore = getStore(repository);
|
||||||
GitRepositoryConfig config = repositoryConfigStore.get();
|
GitRepositoryConfig config = repositoryConfigStore.get();
|
||||||
GitRepositoryConfigDto dto = repositoryConfigMapper.map(config, repository);
|
GitRepositoryConfigDto dto = repositoryConfigMapper.map(config, repository);
|
||||||
@@ -68,6 +70,7 @@ public class GitRepositoryConfigResource {
|
|||||||
})
|
})
|
||||||
public Response setRepositoryConfig(@PathParam("namespace") String namespace, @PathParam("name") String name, GitRepositoryConfigDto dto) {
|
public Response setRepositoryConfig(@PathParam("namespace") String namespace, @PathParam("name") String name, GitRepositoryConfigDto dto) {
|
||||||
Repository repository = getRepository(namespace, name);
|
Repository repository = getRepository(namespace, name);
|
||||||
|
RepositoryPermissions.modify(repository).check();
|
||||||
ConfigurationStore<GitRepositoryConfig> repositoryConfigStore = getStore(repository);
|
ConfigurationStore<GitRepositoryConfig> repositoryConfigStore = getStore(repository);
|
||||||
GitRepositoryConfig config = repositoryConfigMapper.map(dto);
|
GitRepositoryConfig config = repositoryConfigMapper.map(dto);
|
||||||
repositoryConfigStore.set(config);
|
repositoryConfigStore.set(config);
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ type State = {
|
|||||||
error?: Error,
|
error?: Error,
|
||||||
branches: Branch[],
|
branches: Branch[],
|
||||||
selectedBranchName?: string,
|
selectedBranchName?: string,
|
||||||
defaultBranchChanged: boolean
|
defaultBranchChanged: boolean,
|
||||||
|
disabled: boolean
|
||||||
};
|
};
|
||||||
|
|
||||||
const GIT_CONFIG_CONTENT_TYPE = "application/vnd.scmm-gitConfig+json";
|
const GIT_CONFIG_CONTENT_TYPE = "application/vnd.scmm-gitConfig+json";
|
||||||
@@ -33,7 +34,8 @@ class RepositoryConfig extends React.Component<Props, State> {
|
|||||||
loadingDefaultBranch: true,
|
loadingDefaultBranch: true,
|
||||||
submitPending: false,
|
submitPending: false,
|
||||||
branches: [],
|
branches: [],
|
||||||
defaultBranchChanged: false
|
defaultBranchChanged: false,
|
||||||
|
disabled: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,11 +55,11 @@ class RepositoryConfig extends React.Component<Props, State> {
|
|||||||
apiClient
|
apiClient
|
||||||
.get(repository._links.configuration.href)
|
.get(repository._links.configuration.href)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(payload => payload.defaultBranch)
|
.then(payload =>
|
||||||
.then(selectedBranchName =>
|
|
||||||
this.setState({
|
this.setState({
|
||||||
...this.state,
|
...this.state,
|
||||||
selectedBranchName,
|
selectedBranchName: payload.defaultBranch,
|
||||||
|
disabled: !payload._links.update,
|
||||||
loadingDefaultBranch: false
|
loadingDefaultBranch: false
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@@ -98,7 +100,7 @@ class RepositoryConfig extends React.Component<Props, State> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { t } = this.props;
|
const { t } = this.props;
|
||||||
const { loadingBranches, loadingDefaultBranch, submitPending, error } = this.state;
|
const { loadingBranches, loadingDefaultBranch, submitPending, error, disabled } = this.state;
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return (
|
return (
|
||||||
@@ -110,6 +112,12 @@ class RepositoryConfig extends React.Component<Props, State> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const submitButton = disabled? null: <SubmitButton
|
||||||
|
label={t("scm-git-plugin.repo-config.submit")}
|
||||||
|
loading={submitPending}
|
||||||
|
disabled={!this.state.selectedBranchName}
|
||||||
|
/>;
|
||||||
|
|
||||||
if (!(loadingBranches || loadingDefaultBranch)) {
|
if (!(loadingBranches || loadingDefaultBranch)) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -121,12 +129,9 @@ class RepositoryConfig extends React.Component<Props, State> {
|
|||||||
branches={this.state.branches}
|
branches={this.state.branches}
|
||||||
selected={this.branchSelected}
|
selected={this.branchSelected}
|
||||||
selectedBranch={this.state.selectedBranchName}
|
selectedBranch={this.state.selectedBranchName}
|
||||||
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
<SubmitButton
|
{ submitButton }
|
||||||
label={t("scm-git-plugin.repo-config.submit")}
|
|
||||||
loading={submitPending}
|
|
||||||
disabled={!this.state.selectedBranchName}
|
|
||||||
/>
|
|
||||||
</form>
|
</form>
|
||||||
<hr />
|
<hr />
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ public class GitConfigResourceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SubjectAware(username = "writeOnly")
|
@SubjectAware(username = "readWrite")
|
||||||
public void shouldReadDefaultRepositoryConfig() throws URISyntaxException, UnsupportedEncodingException {
|
public void shouldReadDefaultRepositoryConfig() throws URISyntaxException, UnsupportedEncodingException {
|
||||||
when(repositoryManager.get(new NamespaceAndName("space", "X"))).thenReturn(new Repository("id", "git", "space", "X"));
|
when(repositoryManager.get(new NamespaceAndName("space", "X"))).thenReturn(new Repository("id", "git", "space", "X"));
|
||||||
|
|
||||||
@@ -193,7 +193,7 @@ public class GitConfigResourceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SubjectAware(username = "writeOnly")
|
@SubjectAware(username = "readOnly")
|
||||||
public void shouldReadStoredRepositoryConfig() throws URISyntaxException, UnsupportedEncodingException {
|
public void shouldReadStoredRepositoryConfig() throws URISyntaxException, UnsupportedEncodingException {
|
||||||
when(repositoryManager.get(new NamespaceAndName("space", "X"))).thenReturn(new Repository("id", "git", "space", "X"));
|
when(repositoryManager.get(new NamespaceAndName("space", "X"))).thenReturn(new Repository("id", "git", "space", "X"));
|
||||||
GitRepositoryConfig gitRepositoryConfig = new GitRepositoryConfig();
|
GitRepositoryConfig gitRepositoryConfig = new GitRepositoryConfig();
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ admin = secret, admin
|
|||||||
[roles]
|
[roles]
|
||||||
reader = configuration:read:git
|
reader = configuration:read:git
|
||||||
writer = configuration:write:git
|
writer = configuration:write:git
|
||||||
readerWriter = configuration:*:git
|
readerWriter = configuration:*:git,repository:*:id
|
||||||
admin = *
|
admin = *
|
||||||
repoRead = repository:read:*
|
repoRead = repository:read:*
|
||||||
repoWrite = repository:modify:*
|
repoWrite = repository:modify:*
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ type Props = {
|
|||||||
selected: (branch?: Branch) => void,
|
selected: (branch?: Branch) => void,
|
||||||
selectedBranch?: string,
|
selectedBranch?: string,
|
||||||
label: string,
|
label: string,
|
||||||
|
disabled?: boolean,
|
||||||
|
|
||||||
// context props
|
// context props
|
||||||
classes: Object
|
classes: Object
|
||||||
@@ -47,7 +48,7 @@ class BranchSelector extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { branches, classes, label } = this.props;
|
const { branches, classes, label, disabled } = this.props;
|
||||||
|
|
||||||
if (branches) {
|
if (branches) {
|
||||||
return (
|
return (
|
||||||
@@ -79,6 +80,7 @@ class BranchSelector extends React.Component<Props, State> {
|
|||||||
className="is-fullwidth"
|
className="is-fullwidth"
|
||||||
options={branches.map(b => b.name)}
|
options={branches.map(b => b.name)}
|
||||||
optionSelected={this.branchSelected}
|
optionSelected={this.branchSelected}
|
||||||
|
disabled={!!disabled}
|
||||||
preselectedOption={
|
preselectedOption={
|
||||||
this.state.selectedBranch
|
this.state.selectedBranch
|
||||||
? this.state.selectedBranch.name
|
? this.state.selectedBranch.name
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ type Props = {
|
|||||||
value?: string,
|
value?: string,
|
||||||
autofocus?: boolean,
|
autofocus?: boolean,
|
||||||
onChange: (value: string, name?: string) => void,
|
onChange: (value: string, name?: string) => void,
|
||||||
helpText?: string
|
helpText?: string,
|
||||||
|
disabled?: boolean
|
||||||
};
|
};
|
||||||
|
|
||||||
class Textarea extends React.Component<Props> {
|
class Textarea extends React.Component<Props> {
|
||||||
@@ -31,7 +32,7 @@ class Textarea extends React.Component<Props> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { placeholder, value, label, helpText } = this.props;
|
const { placeholder, value, label, helpText, disabled } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="field">
|
<div className="field">
|
||||||
@@ -45,6 +46,7 @@ class Textarea extends React.Component<Props> {
|
|||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
onChange={this.handleInput}
|
onChange={this.handleInput}
|
||||||
value={value}
|
value={value}
|
||||||
|
disabled={!!disabled}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -71,7 +71,8 @@ class RepositoryForm extends React.Component<Props, State> {
|
|||||||
this.state.nameValidationError ||
|
this.state.nameValidationError ||
|
||||||
this.state.contactValidationError ||
|
this.state.contactValidationError ||
|
||||||
this.isFalsy(repository.name) ||
|
this.isFalsy(repository.name) ||
|
||||||
(namespaceStrategy === CUSTOM_NAMESPACE_STRATEGY && this.isFalsy(repository.namespace))
|
(namespaceStrategy === CUSTOM_NAMESPACE_STRATEGY &&
|
||||||
|
this.isFalsy(repository.namespace))
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -86,10 +87,24 @@ class RepositoryForm extends React.Component<Props, State> {
|
|||||||
return !this.props.repository;
|
return !this.props.repository;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
isModifiable = () => {
|
||||||
|
return !!this.props.repository && !!this.props.repository._links.update;
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { loading, t } = this.props;
|
const { loading, t } = this.props;
|
||||||
const repository = this.state.repository;
|
const repository = this.state.repository;
|
||||||
|
|
||||||
|
const disabled = !this.isModifiable() && !this.isCreateMode();
|
||||||
|
|
||||||
|
const submitButton = disabled ? null : (
|
||||||
|
<SubmitButton
|
||||||
|
disabled={!this.isValid()}
|
||||||
|
loading={loading}
|
||||||
|
label={t("repositoryForm.submit")}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
let subtitle = null;
|
let subtitle = null;
|
||||||
if (this.props.repository) {
|
if (this.props.repository) {
|
||||||
// edit existing repo
|
// edit existing repo
|
||||||
@@ -108,6 +123,7 @@ class RepositoryForm extends React.Component<Props, State> {
|
|||||||
validationError={this.state.contactValidationError}
|
validationError={this.state.contactValidationError}
|
||||||
errorMessage={t("validation.contact-invalid")}
|
errorMessage={t("validation.contact-invalid")}
|
||||||
helpText={t("help.contactHelpText")}
|
helpText={t("help.contactHelpText")}
|
||||||
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Textarea
|
<Textarea
|
||||||
@@ -115,12 +131,9 @@ class RepositoryForm extends React.Component<Props, State> {
|
|||||||
onChange={this.handleDescriptionChange}
|
onChange={this.handleDescriptionChange}
|
||||||
value={repository ? repository.description : ""}
|
value={repository ? repository.description : ""}
|
||||||
helpText={t("help.descriptionHelpText")}
|
helpText={t("help.descriptionHelpText")}
|
||||||
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
<SubmitButton
|
{submitButton}
|
||||||
disabled={!this.isValid()}
|
|
||||||
loading={loading}
|
|
||||||
label={t("repositoryForm.submit")}
|
|
||||||
/>
|
|
||||||
</form>
|
</form>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user