Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
ruibaby committed Jul 18, 2024
2 parents a9725df + 2a807b7 commit e0642ea
Show file tree
Hide file tree
Showing 23 changed files with 723 additions and 588 deletions.
49 changes: 49 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/docker-in-docker
{
"name": "Halo Dev Container",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/base:bullseye",

"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"version": "20.10",
"enableNonRootDocker": "true",
"moby": "true"
},
"ghcr.io/devcontainers/features/java:1": {
"version": "17",
"jdkDistro": "tem"
},
"ghcr.io/devcontainers/features/node:1": {
"version": "20"
},
"ghcr.io/devcontainers/features/github-cli:1": {}
},
"customizations": {
"vscode": {
"extensions": [
"Vue.volar",
"vscodevim.vim",
"shengchen.vscode-checkstyle",
"streetsidesoftware.code-spell-checker",
"vscjava.vscode-gradle",
"vmware.vscode-boot-dev-pack",
"vscjava.vscode-java-pack",
"bradlc.vscode-tailwindcss"
]
}
}

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "docker --version",

// Configure tool-specific properties.
// "customizations": {},

// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for more information:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
# https://containers.dev/guide/dependabot

version: 2
updates:
- package-ecosystem: "devcontainers"
directory: "/"
schedule:
interval: weekly
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package run.halo.app.security;

import org.pf4j.ExtensionPoint;
import org.springframework.web.server.WebFilter;

/**
* Security web filter for after security.
*
* @author johnniang
* @since 2.18
*/
public interface AfterSecurityWebFilter extends WebFilter, ExtensionPoint {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package run.halo.app.security;

import org.pf4j.ExtensionPoint;
import org.springframework.web.server.WebFilter;

/**
* Security web filter for before security.
*
* @author johnniang
* @since 2.18
*/
public interface BeforeSecurityWebFilter extends WebFilter, ExtensionPoint {

}
8 changes: 4 additions & 4 deletions application/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,10 @@ tasks.named('jacocoTestReport', JacocoReport) {
}

ext.presetPluginUrls = [
'https://github.com/halo-dev/plugin-comment-widget/releases/download/v2.3.1/plugin-comment-widget-2.3.1.jar' : 'plugin-comment-widget.jar',
'https://github.com/halo-dev/plugin-search-widget/releases/download/v1.4.0/plugin-search-widget-1.4.0.jar' : 'plugin-search-widget.jar',
'https://github.com/halo-dev/plugin-sitemap/releases/download/v1.1.1/plugin-sitemap-1.1.1.jar' : 'plugin-sitemap.jar',
'https://github.com/halo-dev/plugin-feed/releases/download/v1.2.2/plugin-feed-1.2.2.jar' : 'plugin-feed.jar',
'https://github.com/halo-dev/plugin-comment-widget/releases/download/v2.4.0/plugin-comment-widget-2.4.0.jar' : 'plugin-comment-widget.jar',
'https://github.com/halo-dev/plugin-search-widget/releases/download/v1.5.0/plugin-search-widget-1.5.0.jar' : 'plugin-search-widget.jar',
'https://github.com/halo-dev/plugin-sitemap/releases/download/v1.1.2/plugin-sitemap-1.1.2.jar' : 'plugin-sitemap.jar',
'https://github.com/halo-dev/plugin-feed/releases/download/v1.3.0/plugin-feed-1.3.0.jar' : 'plugin-feed.jar',

// Currently, plugin-app-store is not open source, so we need to download it from the official website.
// Please see https://github.com/halo-dev/plugin-app-store/issues/55
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,11 @@ public SearchResult search(SearchOption option) {
}

var description = doc.get("description");
var hlDescription =
highlighter.getBestFragment(this.analyzer, "description", description);
String hlDescription = null;
if (description != null) {
hlDescription =
highlighter.getBestFragment(this.analyzer, "description", description);
}

var content = doc.get("content");
var hlContent = highlighter.getBestFragment(this.analyzer, "content", content);
Expand Down Expand Up @@ -310,7 +313,9 @@ public Document convert(HaloDocument haloDoc) {
}

doc.add(new TextField("title", haloDoc.getTitle(), YES));
doc.add(new TextField("description", haloDoc.getDescription(), YES));
if (haloDoc.getDescription() != null) {
doc.add(new TextField("description", haloDoc.getDescription(), YES));
}
doc.add(new TextField("content", haloDoc.getContent(), YES));
doc.add(new StringField("recycled", Boolean.toString(haloDoc.isRecycled()), YES));
doc.add(new StringField("exposed", Boolean.toString(haloDoc.isExposed()), YES));
Expand All @@ -335,7 +340,9 @@ public Document convert(HaloDocument haloDoc) {
var creationTimestamp = haloDoc.getCreationTimestamp();
doc.add(new LongField("creationTimestamp", creationTimestamp.toEpochMilli(), YES));
var updateTimestamp = haloDoc.getUpdateTimestamp();
doc.add(new LongField("updateTimestamp", updateTimestamp.toEpochMilli(), YES));
if (updateTimestamp != null) {
doc.add(new LongField("updateTimestamp", updateTimestamp.toEpochMilli(), YES));
}
doc.add(new StringField("permalink", haloDoc.getPermalink(), YES));
return doc;
}
Expand Down Expand Up @@ -375,8 +382,11 @@ public HaloDocument convert(Document doc) {

var creationTimestamp = doc.getField("creationTimestamp").numericValue().longValue();
haloDoc.setCreationTimestamp(Instant.ofEpochMilli(creationTimestamp));
var updateTimestamp = doc.getField("updateTimestamp").numericValue().longValue();
haloDoc.setUpdateTimestamp(Instant.ofEpochMilli(updateTimestamp));
var updateTimestampField = doc.getField("updateTimestamp");
if (updateTimestampField != null) {
var updateTimestamp = updateTimestampField.numericValue().longValue();
haloDoc.setUpdateTimestamp(Instant.ofEpochMilli(updateTimestamp));
}
// handle content later
return haloDoc;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import run.halo.app.content.ContentWrapper;
import run.halo.app.content.PostService;
import run.halo.app.core.extension.content.Post;
Expand Down Expand Up @@ -36,6 +37,11 @@ public Flux<HaloDocument> fetchAll() {
// get content
return paginatedOperator.list(Post.class, options)
.flatMap(post -> postService.getReleaseContent(post)
.switchIfEmpty(Mono.fromSupplier(() -> ContentWrapper.builder()
.content("")
.raw("")
.rawType("")
.build()))
.map(contentWrapper -> convert(post, contentWrapper))
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import static org.springframework.security.config.web.server.SecurityWebFiltersOrder.ANONYMOUS_AUTHENTICATION;
import static org.springframework.security.config.web.server.SecurityWebFiltersOrder.AUTHENTICATION;
import static org.springframework.security.config.web.server.SecurityWebFiltersOrder.FIRST;
import static org.springframework.security.config.web.server.SecurityWebFiltersOrder.FORM_LOGIN;
import static org.springframework.security.config.web.server.SecurityWebFiltersOrder.LAST;

import lombok.Setter;
import org.pf4j.ExtensionPoint;
Expand Down Expand Up @@ -30,7 +32,12 @@ public SecurityWebFiltersConfigurer(ExtensionGetter extensionGetter) {
public void configure(ServerHttpSecurity http) {
http
.addFilterAt(
new SecurityWebFilterChainProxy(FormLoginSecurityWebFilter.class), FORM_LOGIN
new SecurityWebFilterChainProxy(BeforeSecurityWebFilter.class),
FIRST
)
.addFilterAt(
new SecurityWebFilterChainProxy(FormLoginSecurityWebFilter.class),
FORM_LOGIN
)
.addFilterAt(
new SecurityWebFilterChainProxy(AuthenticationSecurityWebFilter.class),
Expand All @@ -39,7 +46,12 @@ public void configure(ServerHttpSecurity http) {
.addFilterAt(
new SecurityWebFilterChainProxy(AnonymousAuthenticationSecurityWebFilter.class),
ANONYMOUS_AUTHENTICATION
);
)
.addFilterAt(
new SecurityWebFilterChainProxy(AfterSecurityWebFilter.class),
LAST
)
;
}

public class SecurityWebFilterChainProxy implements WebFilter {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ protected Mono<UserDetails> processAutoLoginCookie(String[] cookieTokens,
log.debug("Refreshing persistent login token for user '{}', series '{}'",
token.getUsername(), token.getSeries());
var newToken = new PersistentRememberMeToken(token.getUsername(), token.getSeries(),
generateTokenData(), new Date());
token.getTokenValue(), new Date());
return Mono.just(newToken);
})
.flatMap(newToken -> updateToken(newToken)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,28 +1,41 @@
package run.halo.app.security.authentication.rememberme;

import static org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher.MatchResult;

import lombok.RequiredArgsConstructor;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.web.server.authentication.AuthenticationWebFilter;
import org.springframework.security.web.server.context.ServerSecurityContextRepository;
import org.springframework.stereotype.Component;
import run.halo.app.security.authentication.SecurityConfigurer;

@Component
@RequiredArgsConstructor
public class RememberMeConfigurer implements SecurityConfigurer {

private final RememberMeServices rememberMeServices;

private final ServerSecurityContextRepository securityContextRepository;

private final CookieSignatureKeyResolver cookieSignatureKeyResolver;

@Override
public void configure(ServerHttpSecurity http) {
http.addFilterAt(
new RememberMeAuthenticationFilter(securityContextRepository,
rememberMeServices, authenticationManager()),
SecurityWebFiltersOrder.AUTHENTICATION);
var authManager = new RememberMeAuthenticationManager(cookieSignatureKeyResolver);
var filter = new AuthenticationWebFilter(authManager);
filter.setSecurityContextRepository(securityContextRepository);
filter.setAuthenticationFailureHandler(
(exchange, exception) -> rememberMeServices.loginFail(exchange.getExchange())
);
filter.setServerAuthenticationConverter(rememberMeServices::autoLogin);
filter.setRequiresAuthenticationMatcher(
exchange -> ReactiveSecurityContextHolder.getContext()
.flatMap(securityContext -> MatchResult.notMatch())
.switchIfEmpty(MatchResult.match())
);
http.addFilterAt(filter, SecurityWebFiltersOrder.AUTHENTICATION);
}

RememberMeAuthenticationManager authenticationManager() {
return new RememberMeAuthenticationManager(cookieSignatureKeyResolver);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package run.halo.app.security.device;

import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationListener;
import org.springframework.lang.NonNull;
Expand All @@ -25,6 +27,8 @@
@RequiredArgsConstructor
public class NewDeviceLoginListener implements ApplicationListener<NewDeviceLoginEvent> {
static final String REASON_TYPE = "new-device-login";
private static final DateTimeFormatter DATE_TIME_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss O").withZone(ZoneOffset.systemDefault());
private final NotificationCenter notificationCenter;
private final NotificationReasonEmitter notificationReasonEmitter;

Expand All @@ -43,7 +47,8 @@ Mono<Void> sendNewDeviceNotification(Device device) {
attributes.put("os", device.getStatus().getOs());
attributes.put("browser", device.getStatus().getBrowser());
attributes.put("ipAddress", device.getSpec().getIpAddress());
attributes.put("loginTime", device.getSpec().getLastAuthenticatedTime());
attributes.put("loginTime",
DATE_TIME_FORMATTER.format(device.getSpec().getLastAuthenticatedTime()));
builder.attributes(attributes)
.author(UserIdentity.of(device.getSpec().getPrincipalName()))
.subject(Reason.Subject.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ spec:
[(${subscriber.displayName})] 你好:
你的 [(${site.title})] 账号被用于在 [(${os})] 的 [(${browser})] 上登录。
时间:[(${loginTime})]
时间:[(${loginTime})]
IP 地址:[(${ipAddress})]
如果你知悉上述信息,请忽略此电子邮件。
如果你最近没有使用你的 Halo 账号登录并相信有人可能访问了你的账户,请尽快重设你的密码。
Expand All @@ -180,8 +180,8 @@ spec:
<div class="body">
<p th:text="|你的 ${site.title} 账号被用于在 ${os} 的 ${browser} 上登录:|"></p>
<div class="device-info">
<p th:text="|时间: ${loginTime}|"></p>
<p th:text="|IP 地址: ${ipAddress}|"></p>
<p th:text="|时间: ${loginTime}|"></p>
<p th:text="|IP 地址: ${ipAddress}|"></p>
</div>
<p>如果你知悉上述信息,请忽略此电子邮件。</p>
<p th:text="|如果你最近没有使用你的 ${site.title} 账号登录并相信有人可能访问了你的账户,请尽快重设你的密码。|"></p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.assertArg;
Expand Down Expand Up @@ -160,7 +161,7 @@ void shouldSearch() throws IOException {
var gotHaloDoc = result.getHits().get(0);
assertEquals("fake-id", gotHaloDoc.getId());
assertEquals("<fake-tag>fake</fake-tag>-title", gotHaloDoc.getTitle());
assertEquals("<fake-tag>fake</fake-tag>-desc", gotHaloDoc.getDescription());
assertNull(gotHaloDoc.getDescription());
assertEquals("<fake-tag>fake</fake-tag>-content", gotHaloDoc.getContent());
}

Expand All @@ -169,13 +170,13 @@ HaloDocument createFakeHaloDoc() {
haloDoc.setId("fake-id");
haloDoc.setMetadataName("fake-name");
haloDoc.setTitle("fake-title");
haloDoc.setDescription("fake-desc");
haloDoc.setDescription(null);
haloDoc.setContent("fake-content");
haloDoc.setType("fake-type");
haloDoc.setOwnerName("fake-owner");
var now = Instant.now();
haloDoc.setCreationTimestamp(now);
haloDoc.setUpdateTimestamp(now);
haloDoc.setUpdateTimestamp(null);
haloDoc.setPermalink("/fake-permalink");
haloDoc.setAnnotations(Map.of("fake-anno-key", "fake-anno-value"));
return haloDoc;
Expand Down
Loading

0 comments on commit e0642ea

Please sign in to comment.