mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-17 02:31:14 +01:00
align validation of repository name and namespace
This commit is contained in:
@@ -248,7 +248,8 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per
|
|||||||
/**
|
/**
|
||||||
* Returns true if the {@link Repository} is valid.
|
* Returns true if the {@link Repository} is valid.
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>The name is not empty and contains only A-z, 0-9, _, -, /</li>
|
* <li>The namespace is valid</li>
|
||||||
|
* <li>The name is valid</li>
|
||||||
* <li>The type is not empty</li>
|
* <li>The type is not empty</li>
|
||||||
* <li>The contact is empty or contains a valid email address</li>
|
* <li>The contact is empty or contains a valid email address</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
@@ -257,9 +258,10 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
return ValidationUtil.isRepositoryNameValid(name) && Util.isNotEmpty(type)
|
return ValidationUtil.isRepositoryNameValid(namespace)
|
||||||
&& ((Util.isEmpty(contact))
|
&& ValidationUtil.isRepositoryNameValid(name)
|
||||||
|| ValidationUtil.isMailAddressValid(contact));
|
&& Util.isNotEmpty(type)
|
||||||
|
&& ((Util.isEmpty(contact)) || ValidationUtil.isMailAddressValid(contact));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -35,14 +35,12 @@ package sonia.scm.util;
|
|||||||
|
|
||||||
//~--- non-JDK imports --------------------------------------------------------
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
import com.google.common.base.Splitter;
|
|
||||||
|
|
||||||
import sonia.scm.Validateable;
|
import sonia.scm.Validateable;
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Sebastian Sdorra
|
* @author Sebastian Sdorra
|
||||||
@@ -58,10 +56,10 @@ public final class ValidationUtil
|
|||||||
private static final String REGEX_NAME =
|
private static final String REGEX_NAME =
|
||||||
"^[A-z0-9\\.\\-_@]|[^ ]([A-z0-9\\.\\-_@ ]*[A-z0-9\\.\\-_@]|[^ ])?$";
|
"^[A-z0-9\\.\\-_@]|[^ ]([A-z0-9\\.\\-_@ ]*[A-z0-9\\.\\-_@]|[^ ])?$";
|
||||||
|
|
||||||
|
public static final String REGEX_REPOSITORYNAME = "(?!^\\.\\.$)(?!^\\.$)(?!.*[\\\\\\[\\]])^[A-z0-9\\.][A-z0-9\\.\\-_]*$";
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
private static final Pattern REGEX_REPOSITORYNAME = Pattern.compile(
|
private static final Pattern PATTERN_REPOSITORYNAME = Pattern.compile(REGEX_REPOSITORYNAME);
|
||||||
"(?!^\\.\\.$)(?!^\\.$)(?!.*[\\\\\\[\\]])^[A-z0-9\\.][A-z0-9\\.\\-_]*$"
|
|
||||||
);
|
|
||||||
|
|
||||||
//~--- constructors ---------------------------------------------------------
|
//~--- constructors ---------------------------------------------------------
|
||||||
|
|
||||||
@@ -151,7 +149,7 @@ public final class ValidationUtil
|
|||||||
* @return {@code true} if repository name is valid
|
* @return {@code true} if repository name is valid
|
||||||
*/
|
*/
|
||||||
public static boolean isRepositoryNameValid(String name) {
|
public static boolean isRepositoryNameValid(String name) {
|
||||||
return REGEX_REPOSITORYNAME.matcher(name).matches();
|
return PATTERN_REPOSITORYNAME.matcher(name).matches();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { validation } from "@scm-manager/ui-components";
|
import { validation } from "@scm-manager/ui-components";
|
||||||
|
|
||||||
|
const nameRegex = /(?!^\.\.$)(?!^\.$)(?!.*[\\\[\]])^[A-z0-9\.][A-z0-9\.\-_]*$/;
|
||||||
|
|
||||||
export const isNameValid = (name: string) => {
|
export const isNameValid = (name: string) => {
|
||||||
return validation.isNameValid(name);
|
return nameRegex.test(name);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function isContactValid(mail: string) {
|
export function isContactValid(mail: string) {
|
||||||
|
|||||||
@@ -11,6 +11,81 @@ describe("repository name validation", () => {
|
|||||||
expect(validator.isNameValid("scm/manager")).toBe(false);
|
expect(validator.isNameValid("scm/manager")).toBe(false);
|
||||||
expect(validator.isNameValid("scm/ma/nager")).toBe(false);
|
expect(validator.isNameValid("scm/ma/nager")).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should allow same names as the backend", () => {
|
||||||
|
const validPaths = [
|
||||||
|
"scm",
|
||||||
|
"s",
|
||||||
|
"sc",
|
||||||
|
".hiddenrepo",
|
||||||
|
"b.",
|
||||||
|
"...",
|
||||||
|
"..c",
|
||||||
|
"d..",
|
||||||
|
"a..c"
|
||||||
|
];
|
||||||
|
|
||||||
|
validPaths.forEach((path) =>
|
||||||
|
expect(validator.isNameValid(path)).toBe(true)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should deny same names as the backend", () => {
|
||||||
|
const invalidPaths = [
|
||||||
|
".",
|
||||||
|
"/",
|
||||||
|
"//",
|
||||||
|
"..",
|
||||||
|
"/.",
|
||||||
|
"/..",
|
||||||
|
"./",
|
||||||
|
"../",
|
||||||
|
"/../",
|
||||||
|
"/./",
|
||||||
|
"/...",
|
||||||
|
"/abc",
|
||||||
|
".../",
|
||||||
|
"/sdf/",
|
||||||
|
"asdf/",
|
||||||
|
"./b",
|
||||||
|
"scm/plugins/.",
|
||||||
|
"scm/../plugins",
|
||||||
|
"scm/main/",
|
||||||
|
"/scm/main/",
|
||||||
|
"scm/./main",
|
||||||
|
"scm//main",
|
||||||
|
"scm\\main",
|
||||||
|
"scm/main-$HOME",
|
||||||
|
"scm/main-${HOME}-home",
|
||||||
|
"scm/main-%HOME-home",
|
||||||
|
"scm/main-%HOME%-home",
|
||||||
|
"abc$abc",
|
||||||
|
"abc%abc",
|
||||||
|
"abc<abc",
|
||||||
|
"abc>abc",
|
||||||
|
"abc#abc",
|
||||||
|
"abc+abc",
|
||||||
|
"abc{abc",
|
||||||
|
"abc}abc",
|
||||||
|
"abc(abc",
|
||||||
|
"abc)abc",
|
||||||
|
"abc[abc",
|
||||||
|
"abc]abc",
|
||||||
|
"abc|abc",
|
||||||
|
"scm/main",
|
||||||
|
"scm/plugins/git-plugin",
|
||||||
|
".scm/plugins",
|
||||||
|
"a/b..",
|
||||||
|
"a/..b",
|
||||||
|
"scm/main",
|
||||||
|
"scm/plugins/git-plugin",
|
||||||
|
"scm/plugins/git-plugin"
|
||||||
|
];
|
||||||
|
|
||||||
|
invalidPaths.forEach((path) =>
|
||||||
|
expect(validator.isNameValid(path)).toBe(false)
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("repository contact validation", () => {
|
describe("repository contact validation", () => {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import lombok.NoArgsConstructor;
|
|||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.hibernate.validator.constraints.Email;
|
import org.hibernate.validator.constraints.Email;
|
||||||
import org.hibernate.validator.constraints.NotEmpty;
|
import org.hibernate.validator.constraints.NotEmpty;
|
||||||
|
import sonia.scm.util.ValidationUtil;
|
||||||
|
|
||||||
import javax.validation.constraints.Pattern;
|
import javax.validation.constraints.Pattern;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
@@ -25,8 +26,9 @@ public class RepositoryDto extends HalRepresentation {
|
|||||||
private List<HealthCheckFailureDto> healthCheckFailures;
|
private List<HealthCheckFailureDto> healthCheckFailures;
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
private Instant lastModified;
|
private Instant lastModified;
|
||||||
|
// we could not validate the namespace, this must be done by the namespace strategy
|
||||||
private String namespace;
|
private String namespace;
|
||||||
@Pattern(regexp = "^[A-z0-9\\-_]+$")
|
@Pattern(regexp = ValidationUtil.REGEX_REPOSITORYNAME)
|
||||||
private String name;
|
private String name;
|
||||||
private boolean archived = false;
|
private boolean archived = false;
|
||||||
@NotEmpty
|
@NotEmpty
|
||||||
|
|||||||
Reference in New Issue
Block a user