mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-07-09 07:32:34 +02:00
Merge branch 'develop' into feature/admin_info
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
@@ -6,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## Unreleased
|
||||
### Added
|
||||
- Add support for pr merge with prior rebase ([#1332](https://github.com/scm-manager/scm-manager/pull/1332))
|
||||
- Tags overview for repository [#1331](https://github.com/scm-manager/scm-manager/pull/1331)
|
||||
- Permissions can be specified for namespaces ([#1335](https://github.com/scm-manager/scm-manager/pull/1335))
|
||||
- Show update info on admin information page ([#1342](https://github.com/scm-manager/scm-manager/pull/1342))
|
||||
@@ -17,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Overflow for too long branch names ([#1339](https://github.com/scm-manager/scm-manager/pull/1339))
|
||||
- Set default branch in branch selector if nothing is selected ([#1338](https://github.com/scm-manager/scm-manager/pull/1338))
|
||||
- Handling of branch with slashes in source view ([#1340](https://github.com/scm-manager/scm-manager/pull/1340))
|
||||
- Detect not existing paths correctly in Mercurial ([#1343](https://github.com/scm-manager/scm-manager/pull/1343))
|
||||
|
||||
## [2.5.0] - 2020-09-10
|
||||
### Added
|
||||
|
||||
4
pom.xml
4
pom.xml
@@ -464,7 +464,7 @@
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>3.17.0</version>
|
||||
<version>3.17.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -903,7 +903,7 @@
|
||||
|
||||
<properties>
|
||||
<!-- test libraries -->
|
||||
<mockito.version>3.5.7</mockito.version>
|
||||
<mockito.version>3.5.9</mockito.version>
|
||||
<hamcrest.version>2.1</hamcrest.version>
|
||||
<junit.version>5.6.2</junit.version>
|
||||
|
||||
|
||||
@@ -21,11 +21,22 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.repository.api;
|
||||
|
||||
public enum MergeStrategy {
|
||||
MERGE_COMMIT,
|
||||
FAST_FORWARD_IF_POSSIBLE,
|
||||
SQUASH
|
||||
MERGE_COMMIT(true),
|
||||
FAST_FORWARD_IF_POSSIBLE(true),
|
||||
SQUASH(true),
|
||||
REBASE(false);
|
||||
|
||||
private final boolean commitMessageAllowed;
|
||||
|
||||
MergeStrategy(boolean commitMessageAllowed) {
|
||||
this.commitMessageAllowed = commitMessageAllowed;
|
||||
}
|
||||
|
||||
public boolean isCommitMessageAllowed() {
|
||||
return commitMessageAllowed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,8 @@ public class GitMergeCommand extends AbstractGitCommand implements MergeCommand
|
||||
private static final Set<MergeStrategy> STRATEGIES = ImmutableSet.of(
|
||||
MergeStrategy.MERGE_COMMIT,
|
||||
MergeStrategy.FAST_FORWARD_IF_POSSIBLE,
|
||||
MergeStrategy.SQUASH
|
||||
MergeStrategy.SQUASH,
|
||||
MergeStrategy.REBASE
|
||||
);
|
||||
|
||||
@Inject
|
||||
@@ -94,6 +95,9 @@ public class GitMergeCommand extends AbstractGitCommand implements MergeCommand
|
||||
case MERGE_COMMIT:
|
||||
return inClone(clone -> new GitMergeCommit(clone, request, context, repository), workingCopyFactory, request.getTargetBranch());
|
||||
|
||||
case REBASE:
|
||||
return inClone(clone -> new GitMergeRebase(clone, request, context, repository), workingCopyFactory, request.getTargetBranch());
|
||||
|
||||
default:
|
||||
throw new MergeStrategyNotSupportedException(repository, request.getMergeStrategy());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.repository.spi;
|
||||
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.MergeCommand;
|
||||
import org.eclipse.jgit.api.RebaseResult;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.repository.InternalRepositoryException;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.api.MergeCommandResult;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
public class GitMergeRebase extends GitMergeStrategy {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GitMergeRebase.class);
|
||||
|
||||
private final MergeCommandRequest request;
|
||||
|
||||
GitMergeRebase(Git clone, MergeCommandRequest request, GitContext context, Repository repository) {
|
||||
super(clone, request, context, repository);
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
MergeCommandResult run() throws IOException {
|
||||
RebaseResult result;
|
||||
String branchToMerge = request.getBranchToMerge();
|
||||
String targetBranch = request.getTargetBranch();
|
||||
try {
|
||||
checkOutBranch(branchToMerge);
|
||||
result =
|
||||
getClone()
|
||||
.rebase()
|
||||
.setUpstream(targetBranch)
|
||||
.call();
|
||||
} catch (GitAPIException e) {
|
||||
throw new InternalRepositoryException(getContext().getRepository(), "could not rebase branch " + branchToMerge + " onto " + targetBranch, e);
|
||||
}
|
||||
|
||||
if (result.getStatus().isSuccessful()) {
|
||||
return fastForwardTargetBranch(branchToMerge, targetBranch, result);
|
||||
} else {
|
||||
logger.info("could not rebase branch {} into {} with rebase status '{}' due to ...", branchToMerge, targetBranch, result.getStatus());
|
||||
logger.info("... conflicts: {}", result.getConflicts());
|
||||
logger.info("... failing paths: {}", result.getFailingPaths());
|
||||
logger.info("... message: {}", result);
|
||||
return MergeCommandResult.failure(branchToMerge, targetBranch, Optional.ofNullable(result.getConflicts()).orElse(Collections.singletonList("UNKNOWN")));
|
||||
}
|
||||
}
|
||||
|
||||
private MergeCommandResult fastForwardTargetBranch(String branchToMerge, String targetBranch, RebaseResult result) throws IOException {
|
||||
try {
|
||||
getClone().checkout().setName(targetBranch).call();
|
||||
ObjectId sourceRevision = resolveRevision(branchToMerge);
|
||||
getClone()
|
||||
.merge()
|
||||
.setFastForward(MergeCommand.FastForwardMode.FF_ONLY)
|
||||
.include(branchToMerge, sourceRevision)
|
||||
.call();
|
||||
push();
|
||||
return MergeCommandResult.success(getTargetRevision().name(), branchToMerge, sourceRevision.name());
|
||||
} catch (GitAPIException e) {
|
||||
return MergeCommandResult.failure(branchToMerge, targetBranch, result.getConflicts());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -473,6 +473,47 @@ public class GitMergeCommandTest extends AbstractGitCommandTestBase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAllowMergeWithRebase() throws IOException, GitAPIException {
|
||||
GitMergeCommand command = createCommand();
|
||||
MergeCommandRequest request = new MergeCommandRequest();
|
||||
request.setTargetBranch("master");
|
||||
request.setBranchToMerge("mergeable");
|
||||
request.setMergeStrategy(MergeStrategy.REBASE);
|
||||
request.setAuthor(new Person("Dirk Gently", "dirk@holistic.det"));
|
||||
|
||||
MergeCommandResult mergeCommandResult = command.merge(request);
|
||||
|
||||
assertThat(mergeCommandResult.isSuccess()).isTrue();
|
||||
|
||||
Repository repository = createContext().open();
|
||||
Iterable<RevCommit> commits = new Git(repository).log().add(repository.resolve("master")).setMaxCount(1).call();
|
||||
RevCommit mergeCommit = commits.iterator().next();
|
||||
assertThat(mergeCommit.getParentCount()).isEqualTo(1);
|
||||
assertThat(mergeCommit.getParent(0).name()).isEqualTo("fcd0ef1831e4002ac43ea539f4094334c79ea9ec");
|
||||
assertThat(mergeCommit.getName()).isEqualTo(mergeCommandResult.getNewHeadRevision());
|
||||
assertThat(mergeCommit.getName()).doesNotStartWith("91b99de908fcd04772798a31c308a64aea1a5523");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRejectRebaseMergeIfBranchCannotBeRebased() throws IOException, GitAPIException {
|
||||
GitMergeCommand command = createCommand();
|
||||
MergeCommandRequest request = new MergeCommandRequest();
|
||||
request.setTargetBranch("master");
|
||||
request.setBranchToMerge("not-rebasable");
|
||||
request.setMergeStrategy(MergeStrategy.REBASE);
|
||||
request.setAuthor(new Person("Dirk Gently", "dirk@holistic.det"));
|
||||
|
||||
MergeCommandResult mergeCommandResult = command.merge(request);
|
||||
|
||||
assertThat(mergeCommandResult.isSuccess()).isFalse();
|
||||
Repository repository = createContext().open();
|
||||
Iterable<RevCommit> commits = new Git(repository).log().add(repository.resolve("master")).setMaxCount(1).call();
|
||||
RevCommit headCommit = commits.iterator().next();
|
||||
assertThat(headCommit.getName()).isEqualTo("fcd0ef1831e4002ac43ea539f4094334c79ea9ec");
|
||||
|
||||
}
|
||||
|
||||
private GitMergeCommand createCommand() {
|
||||
return createCommand(git -> {
|
||||
});
|
||||
|
||||
Binary file not shown.
@@ -36,6 +36,9 @@ import sonia.scm.repository.spi.javahg.HgFileviewCommand;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static sonia.scm.ContextEntry.ContextBuilder.entity;
|
||||
import static sonia.scm.NotFoundException.notFound;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -93,7 +96,8 @@ public class HgBrowseCommand extends AbstractCommand implements BrowseCommand
|
||||
cmd.setLimit(request.getLimit());
|
||||
cmd.setOffset(request.getOffset());
|
||||
|
||||
FileObject file = cmd.execute();
|
||||
FileObject file = cmd.execute()
|
||||
.orElseThrow(() -> notFound(entity("File", request.getPath()).in("Revision", revision).in(getRepository())));
|
||||
return new BrowserResult(c == null? "tip": c.getNode(), revision, file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.repository.spi.javahg;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
@@ -29,12 +29,12 @@ package sonia.scm.repository.spi.javahg;
|
||||
import com.aragost.javahg.Repository;
|
||||
import com.aragost.javahg.internals.AbstractCommand;
|
||||
import com.aragost.javahg.internals.HgInputStream;
|
||||
|
||||
import sonia.scm.repository.FileObject;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Mercurial command to list files of a repository.
|
||||
@@ -161,7 +161,7 @@ public class HgFileviewCommand extends AbstractCommand
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public FileObject execute() throws IOException
|
||||
public Optional<FileObject> execute() throws IOException
|
||||
{
|
||||
cmdAppend("-t");
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.repository.spi.javahg;
|
||||
|
||||
import com.aragost.javahg.DateTime;
|
||||
@@ -35,6 +35,10 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Optional;
|
||||
|
||||
import static java.util.Optional.empty;
|
||||
import static java.util.Optional.of;
|
||||
|
||||
class HgFileviewCommandResultReader {
|
||||
|
||||
@@ -48,7 +52,7 @@ class HgFileviewCommandResultReader {
|
||||
this.disableLastCommit = disableLastCommit;
|
||||
}
|
||||
|
||||
FileObject parseResult() throws IOException {
|
||||
Optional<FileObject> parseResult() throws IOException {
|
||||
Deque<FileObject> stack = new LinkedList<>();
|
||||
|
||||
FileObject last = null;
|
||||
@@ -82,13 +86,17 @@ class HgFileviewCommandResultReader {
|
||||
|
||||
if (stack.isEmpty()) {
|
||||
// if the stack is empty, the requested path is probably a file
|
||||
return last;
|
||||
return of(last);
|
||||
} else if (stack.size() == 1 && stack.getFirst().isDirectory() && stack.getFirst().getChildren().isEmpty()) {
|
||||
// There are no empty directories in hg. When we get this,
|
||||
// we just get the requested path as a directory, but it does not exist.
|
||||
return empty();
|
||||
} else {
|
||||
// if the stack is not empty, the requested path is a directory
|
||||
if (stream.read() == TRUNCATED_MARK) {
|
||||
stack.getLast().setTruncated(true);
|
||||
}
|
||||
return stack.getLast();
|
||||
return of(stack.getLast());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,11 +21,10 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.repository.spi.javahg;
|
||||
|
||||
import com.aragost.javahg.internals.HgInputStream;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import sonia.scm.repository.FileObject;
|
||||
|
||||
@@ -34,6 +33,7 @@ import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Iterator;
|
||||
import java.util.Optional;
|
||||
import java.util.OptionalLong;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
@@ -55,7 +55,7 @@ class HgFileviewCommandResultReaderTest {
|
||||
.file("b.txt", 100, time2.toEpochMilli(), "file b\nwith some\nmore text")
|
||||
.build();
|
||||
|
||||
FileObject fileObject = reader.parseResult();
|
||||
FileObject fileObject = reader.parseResult().get();
|
||||
|
||||
assertThat(fileObject.isDirectory()).isTrue();
|
||||
assertThat(fileObject.getChildren())
|
||||
@@ -84,7 +84,7 @@ class HgFileviewCommandResultReaderTest {
|
||||
.file("a.txt")
|
||||
.truncated();
|
||||
|
||||
FileObject fileObject = reader.parseResult();
|
||||
FileObject fileObject = reader.parseResult().get();
|
||||
|
||||
assertThat(fileObject.isTruncated()).isTrue();
|
||||
}
|
||||
@@ -96,7 +96,7 @@ class HgFileviewCommandResultReaderTest {
|
||||
.file("dir/a.txt")
|
||||
.build();
|
||||
|
||||
FileObject fileObject = reader.parseResult();
|
||||
FileObject fileObject = reader.parseResult().get();
|
||||
|
||||
assertThat(fileObject.isDirectory()).isTrue();
|
||||
assertThat(fileObject.getName()).isEqualTo("dir");
|
||||
@@ -117,7 +117,7 @@ class HgFileviewCommandResultReaderTest {
|
||||
.file("d.txt")
|
||||
.build();
|
||||
|
||||
FileObject fileObject = reader.parseResult();
|
||||
FileObject fileObject = reader.parseResult().get();
|
||||
|
||||
assertThat(fileObject.getChildren())
|
||||
.extracting("name")
|
||||
@@ -152,7 +152,7 @@ class HgFileviewCommandResultReaderTest {
|
||||
.file("d.txt")
|
||||
.build();
|
||||
|
||||
FileObject fileObject = reader.parseResult();
|
||||
FileObject fileObject = reader.parseResult().get();
|
||||
|
||||
assertThat(fileObject.getChildren())
|
||||
.extracting("name")
|
||||
@@ -179,7 +179,7 @@ class HgFileviewCommandResultReaderTest {
|
||||
.file("d.txt")
|
||||
.build();
|
||||
|
||||
FileObject fileObject = reader.parseResult();
|
||||
FileObject fileObject = reader.parseResult().get();
|
||||
|
||||
assertThat(fileObject.getChildren())
|
||||
.extracting("name")
|
||||
@@ -213,7 +213,7 @@ class HgFileviewCommandResultReaderTest {
|
||||
.file("directory/b.txt")
|
||||
.build();
|
||||
|
||||
FileObject fileObject = reader.parseResult();
|
||||
FileObject fileObject = reader.parseResult().get();
|
||||
|
||||
assertThat(fileObject.getChildren())
|
||||
.extracting("name")
|
||||
@@ -248,7 +248,7 @@ class HgFileviewCommandResultReaderTest {
|
||||
.file("a.txt")
|
||||
.build();
|
||||
|
||||
FileObject fileObject = reader.parseResult();
|
||||
FileObject fileObject = reader.parseResult().get();
|
||||
|
||||
assertThat(fileObject.getChildren())
|
||||
.extracting("description")
|
||||
@@ -258,6 +258,17 @@ class HgFileviewCommandResultReaderTest {
|
||||
.containsOnly(OptionalLong.empty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldIgnoreSingleEmptyDir() throws IOException {
|
||||
HgFileviewCommandResultReader reader = new MockInput()
|
||||
.dir("empty")
|
||||
.build();
|
||||
|
||||
Optional<FileObject> fileObject = reader.parseResult();
|
||||
|
||||
assertThat(fileObject).isEmpty();
|
||||
}
|
||||
|
||||
private HgInputStream createInputStream(String input) {
|
||||
return new HgInputStream(new ByteArrayInputStream(input.getBytes(UTF_8)), UTF_8.newDecoder());
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<commons.daemon.version>1.2.2</commons.daemon.version>
|
||||
<commons.daemon.version>1.2.3</commons.daemon.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"realmDescriptionHelpText": "Beschreibung des Authentication Realm.",
|
||||
"dateFormatHelpText": "Moments Datumsformat. Zulässige Formate sind in der MomentJS Dokumentation beschrieben.",
|
||||
"pluginUrlHelpText": "Die URL der Plugin Center API. Beschreibung der Platzhalter: version = SCM-Manager Version; os = Betriebssystem; arch = Architektur",
|
||||
"releaseFeedUrlHelpText": "Die URL des RSS Release Feed des SCM-Manager. Darüber wird über die neue SCM-Manager Versionen informiert. Um diese Funktion zu deaktivieren lassen Sie dieses Feld leer.",
|
||||
"releaseFeedUrlHelpText": "Die URL des RSS Release Feed des SCM-Manager. Darüber wird über die neue SCM-Manager Version informiert. Um diese Funktion zu deaktivieren lassen Sie dieses Feld leer.",
|
||||
"enableForwardingHelpText": "mod_proxy Port Weiterleitung aktivieren.",
|
||||
"disableGroupingGridHelpText": "Repository Gruppen deaktivieren. Nach einer Änderung an dieser Einstellung muss die Seite komplett neu geladen werden.",
|
||||
"allowAnonymousAccessHelpText": "Anonyme Benutzer haben Zugriff auf freigegebene Repositories.",
|
||||
|
||||
@@ -47,7 +47,7 @@ class NamespaceToNamespaceDtoMapper {
|
||||
.self(links.namespace().self(namespace))
|
||||
.single(link("repositories", links.repositoryCollection().forNamespace(namespace)));
|
||||
|
||||
if (NamespacePermissions.permissionRead().isPermitted() || NamespacePermissions.permissionWrite().isPermitted()) {
|
||||
if (NamespacePermissions.permissionRead().isPermitted()) {
|
||||
linkingTo
|
||||
.single(link("permissions", links.namespacePermission().all(namespace)));
|
||||
}
|
||||
|
||||
@@ -78,9 +78,7 @@ public class RepositoryPermissionCollectionToDtoMapper {
|
||||
}
|
||||
|
||||
private Links createLinks(Namespace namespace) {
|
||||
if (!NamespacePermissions.permissionWrite().isPermitted()) {
|
||||
NamespacePermissions.permissionRead().check();
|
||||
}
|
||||
NamespacePermissions.permissionRead().check();
|
||||
Links.Builder linksBuilder = linkingTo()
|
||||
.with(Links.linkingTo().self(resourceLinks.namespacePermission().all(namespace.getNamespace())).build());
|
||||
if (NamespacePermissions.permissionWrite().isPermitted()) {
|
||||
|
||||
@@ -104,7 +104,7 @@ public class DefaultNamespaceManager implements NamespaceManager {
|
||||
}
|
||||
|
||||
private Namespace createNamespaceForName(String namespace) {
|
||||
if (NamespacePermissions.permissionRead().isPermitted() || NamespacePermissions.permissionWrite().isPermitted()) {
|
||||
if (NamespacePermissions.permissionRead().isPermitted()) {
|
||||
return dao.get(namespace)
|
||||
.map(Namespace::clone)
|
||||
.orElse(new Namespace(namespace));
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<value>namespace:permissionRead</value>
|
||||
</permission>
|
||||
<permission>
|
||||
<value>namespace:permissionWrite</value>
|
||||
<value>namespace:permissionRead,permissionWrite</value>
|
||||
</permission>
|
||||
<permission>
|
||||
<value>user:*</value>
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
"displayName": "Berechtigungen auf Namespaces lesen",
|
||||
"description": "Darf die Berechtigungen auf Namespace-Ebene sehen"
|
||||
},
|
||||
"permissionWrite": {
|
||||
"permissionRead,permissionWrite": {
|
||||
"displayName": "Berechtigungen auf Namespaces modifizieren",
|
||||
"description": "Darf die Berechtigungen auf Namespace-Ebene lesen und bearbeiten"
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
"displayName": "Read permissions on namespaces",
|
||||
"description": "May see the permissions set for namespaces"
|
||||
},
|
||||
"permissionWrite": {
|
||||
"permissionRead,permissionWrite": {
|
||||
"displayName": "Modify permissions on namespaces",
|
||||
"description": "May read and modify the permissions set for namespaces"
|
||||
}
|
||||
|
||||
@@ -132,6 +132,7 @@ class IndexDtoGeneratorTest {
|
||||
when(resourceLinks.repositoryTypeCollection()).thenReturn(new ResourceLinks.RepositoryTypeCollectionLinks(scmPathInfo));
|
||||
when(resourceLinks.repositoryRoleCollection()).thenReturn(new ResourceLinks.RepositoryRoleCollectionLinks(scmPathInfo));
|
||||
when(resourceLinks.namespaceStrategies()).thenReturn(new ResourceLinks.NamespaceStrategiesLinks(scmPathInfo));
|
||||
when(resourceLinks.namespaceCollection()).thenReturn(new ResourceLinks.NamespaceCollectionLinks(scmPathInfo));
|
||||
when(resourceLinks.me()).thenReturn(new ResourceLinks.MeLinks(scmPathInfo, new ResourceLinks.UserLinks(scmPathInfo)));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user