Fix the problem of being able to configure invalid external URL (#6840)

#### What type of PR is this?

/kind bug
/area core
/milestone 2.20.x

#### What this PR does / why we need it:

This PR makes users not be able to configure a invalid external URL like `https:www/halo.run` even if it is an valid URL format.

#### Which issue(s) this PR fixes:

Fixes #6837 

#### Does this PR introduce a user-facing change?

```release-note
修复可配置无效的外部访问地址的问题
```
pull/6844/head
John Niang 2024-10-12 16:21:10 +08:00 committed by GitHub
parent 91a69de849
commit 6d149ae3bb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 71 additions and 1 deletions

View File

@ -2,6 +2,7 @@ package run.halo.app.infra.properties;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.util.HashSet;
@ -69,9 +70,26 @@ public class HaloProperties implements Validator {
@Override
public void validate(Object target, Errors errors) {
var props = (HaloProperties) target;
if (props.isUseAbsolutePermalink() && props.getExternalUrl() == null) {
var externalUrl = props.getExternalUrl();
if (props.isUseAbsolutePermalink() && externalUrl == null) {
errors.rejectValue("externalUrl", "external-url.required.when-using-absolute-permalink",
"External URL is required when property `use-absolute-permalink` is set to true.");
}
// check if the external URL is a http or https URL and is not an opaque URL.
if (externalUrl != null && !isValidExternalUrl(externalUrl)) {
errors.rejectValue("externalUrl", "external-url.invalid-format",
"External URL must be a http or https URL.");
}
}
private boolean isValidExternalUrl(URL externalUrl) {
try {
var uri = externalUrl.toURI();
return !uri.isOpaque()
&& uri.getAuthority() != null
&& Set.of("http", "https").contains(uri.getScheme());
} catch (URISyntaxException e) {
return false;
}
}
}

View File

@ -2,6 +2,7 @@ package run.halo.app;
import static org.assertj.core.api.Assertions.assertThat;
import java.net.URI;
import org.junit.jupiter.api.Test;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@ -34,4 +35,10 @@ public class PathPrefixPredicateTest {
}
@Test
void urlTest() {
URI uri = URI.create("https:///path");
System.out.println(uri);
}
}

View File

@ -0,0 +1,45 @@
package run.halo.app.infra.properties;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.stream.Stream;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.validation.SimpleErrors;
class HaloPropertiesTest {
static Stream<Arguments> validateTest() throws MalformedURLException {
return Stream.of(
Arguments.of(true, new URL("http://localhost:8080"), true),
Arguments.of(false, new URL("http://localhost:8080"), true),
Arguments.of(true, new URL("https://localhost:8080"), true),
Arguments.of(false, new URL("https://localhost:8080"), true),
Arguments.of(true, new URL("ftp://localhost:8080"), false),
Arguments.of(false, new URL("ftp://localhost:8080"), false),
Arguments.of(true, new URL("http:www/halo/run"), false),
Arguments.of(false, new URL("http:www/halo.run"), false),
Arguments.of(true, new URL("https:www/halo/run"), false),
Arguments.of(false, new URL("https:www/halo/run"), false),
Arguments.of(true, new URL("https:///path"), false),
Arguments.of(false, new URL("https:///path"), false),
Arguments.of(true, new URL("http:///path"), false),
Arguments.of(false, new URL("http:///path"), false),
Arguments.of(true, null, false),
Arguments.of(false, null, true)
);
}
@ParameterizedTest
@MethodSource
void validateTest(boolean useAbsolutePermalink, URL externalUrl, boolean valid) {
var properties = new HaloProperties();
properties.setUseAbsolutePermalink(useAbsolutePermalink);
properties.setExternalUrl(externalUrl);
var errors = new SimpleErrors(properties);
properties.validate(properties, errors);
Assertions.assertEquals(valid, !errors.hasErrors());
}
}