mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-09 06:55:47 +01:00
Validate namespaces correctly
This commit is contained in:
@@ -268,7 +268,7 @@ class RepositoryForm extends React.Component<Props, State> {
|
|||||||
|
|
||||||
handleNamespaceChange = (namespace: string) => {
|
handleNamespaceChange = (namespace: string) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
namespaceValidationError: !validator.isNameValid(namespace),
|
namespaceValidationError: !validator.isNamespaceValid(namespace),
|
||||||
repository: {
|
repository: {
|
||||||
...this.state.repository,
|
...this.state.repository,
|
||||||
namespace
|
namespace
|
||||||
|
|||||||
@@ -25,6 +25,11 @@
|
|||||||
import { validation } from "@scm-manager/ui-components";
|
import { validation } from "@scm-manager/ui-components";
|
||||||
|
|
||||||
const nameRegex = /(?!^\.\.$)(?!^\.$)(?!.*[.]git$)(?!.*[\\\[\]])^[A-Za-z0-9\.][A-Za-z0-9\.\-_]*$/;
|
const nameRegex = /(?!^\.\.$)(?!^\.$)(?!.*[.]git$)(?!.*[\\\[\]])^[A-Za-z0-9\.][A-Za-z0-9\.\-_]*$/;
|
||||||
|
const namespaceExceptionsRegex = /^(([0-9]{1,3})|(create))$/;
|
||||||
|
|
||||||
|
export const isNamespaceValid = (name: string) => {
|
||||||
|
return nameRegex.test(name) && !namespaceExceptionsRegex.test(name);
|
||||||
|
};
|
||||||
|
|
||||||
export const isNameValid = (name: string) => {
|
export const isNameValid = (name: string) => {
|
||||||
return nameRegex.test(name);
|
return nameRegex.test(name);
|
||||||
|
|||||||
@@ -27,17 +27,25 @@ package sonia.scm.repository;
|
|||||||
import sonia.scm.plugin.Extension;
|
import sonia.scm.plugin.Extension;
|
||||||
import sonia.scm.util.ValidationUtil;
|
import sonia.scm.util.ValidationUtil;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import static sonia.scm.ScmConstraintViolationException.Builder.doThrow;
|
import static sonia.scm.ScmConstraintViolationException.Builder.doThrow;
|
||||||
|
|
||||||
@Extension
|
@Extension
|
||||||
public class CustomNamespaceStrategy implements NamespaceStrategy {
|
public class CustomNamespaceStrategy implements NamespaceStrategy {
|
||||||
|
|
||||||
|
private static final Pattern ONE_TO_THREE_DIGITS = Pattern.compile("[0-9]{1,3}");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String createNamespace(Repository repository) {
|
public String createNamespace(Repository repository) {
|
||||||
String namespace = repository.getNamespace();
|
String namespace = repository.getNamespace();
|
||||||
|
|
||||||
doThrow()
|
doThrow()
|
||||||
.violation("invalid namespace", "namespace")
|
.violation("invalid namespace", "namespace")
|
||||||
.when(!ValidationUtil.isRepositoryNameValid(namespace) || namespace.matches("[0-9]{1,3}"));
|
.when(
|
||||||
|
!ValidationUtil.isRepositoryNameValid(namespace)
|
||||||
|
|| ONE_TO_THREE_DIGITS.matcher(namespace).matches()
|
||||||
|
|| namespace.equals("create"));
|
||||||
|
|
||||||
return namespace;
|
return namespace;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,11 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package sonia.scm.repository;
|
package sonia.scm.repository;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
import sonia.scm.ScmConstraintViolationException;
|
import sonia.scm.ScmConstraintViolationException;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@@ -34,19 +35,21 @@ class CustomNamespaceStrategyTest {
|
|||||||
|
|
||||||
private final NamespaceStrategy namespaceStrategy = new CustomNamespaceStrategy();
|
private final NamespaceStrategy namespaceStrategy = new CustomNamespaceStrategy();
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
void shouldReturnNamespaceFromRepository() {
|
@ValueSource(strings = {"valid", "123_", "something_valid", "1234", "create_it"})
|
||||||
Repository heartOfGold = RepositoryTestData.createHeartOfGold();
|
void shouldReturnNamespaceFromRepository(String expectedValidNamespace) {
|
||||||
assertThat(namespaceStrategy.createNamespace(heartOfGold)).isEqualTo(RepositoryTestData.NAMESPACE);
|
Repository repository = RepositoryTestData.createHeartOfGold();
|
||||||
|
repository.setNamespace(expectedValidNamespace);
|
||||||
|
|
||||||
|
assertThat(namespaceStrategy.createNamespace(repository)).isEqualTo(expectedValidNamespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
void shouldThrowAnValidationExceptionForAnInvalidNamespace() {
|
@ValueSource(strings = {"..", " ", "0", "123", "create"})
|
||||||
Repository repository = new Repository();
|
void shouldThrowAnValidationExceptionForAnInvalidNamespace(String expectedAsInvalidNamespace) {
|
||||||
repository.setNamespace("..");
|
Repository repository = RepositoryTestData.createHeartOfGold();
|
||||||
repository.setName(".");
|
repository.setNamespace(expectedAsInvalidNamespace);
|
||||||
|
|
||||||
assertThrows(ScmConstraintViolationException.class, () -> namespaceStrategy.createNamespace(repository));
|
assertThrows(ScmConstraintViolationException.class, () -> namespaceStrategy.createNamespace(repository));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user