#### What type of PR is this?
/kind bug
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR fixes the problem of not working for relative permalink caused by <https://github.com/halo-dev/halo/pull/7459>.
#### Special notes for your reviewer:
1. Try to start Halo instance with `halo.use-absolute-permalink=false` and check the permalinks of posts and attachments.
1. Try to start Halo instance with `halo.use-absolute-permalink=true` and check the permalinks of posts and attachments.
#### Does this PR introduce a user-facing change?
```release-note
None
```
#### What type of PR is this?
/kind cleanup
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR corrects location of LogoutHandler instead of in LogoutSuccessHandler. LogoutHanadler should be invoked before LogoutSuccessHandler.
#### Does this PR introduce a user-facing change?
```release-note
None
```
#### What type of PR is this?
/kind improvement
#### What this PR does / why we need it:
This PR adds UserLoginEvent and UserLogoutEvent which are shared to plugins.
#### Which issue(s) this PR fixes:
Fixes https://github.com/halo-dev/halo/issues/7436
#### Does this PR introduce a user-facing change?
```release-note
添加用户登录/登出事件
```
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR bumps Spring Boot to [3.5.0](https://github.com/spring-projects/spring-boot/releases/tag/v3.5.0).
#### Does this PR introduce a user-facing change?
```release-note
升级依赖 Spring Boot 至 3.5.0
```
* Add support for configuring external URL online
* Fix the problem of timeout on external URL initialization
* Add external URL editing capability to overview page
Signed-off-by: Ryan Wang <i@ryanc.cc>
---------
Signed-off-by: Ryan Wang <i@ryanc.cc>
Co-authored-by: Ryan Wang <i@ryanc.cc>
#### What type of PR is this?
/kind bug
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR check if the locale is undetermined during resolving locale. Or it will cause the error below if locale is `und`:
```java
2025-05-21T17:28:45.953+08:00 ERROR 58760 --- [undedElastic-14] o.s.w.s.adapter.HttpWebHandlerAdapter : [c1824fa5-1] 500 Server Error for HTTP GET "/"
org.thymeleaf.exceptions.TemplateOutputException: An error happened during template rendering
at org.thymeleaf.engine.OutputTemplateHandler.handleText(OutputTemplateHandler.java:75) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.AbstractTemplateHandler.handleText(AbstractTemplateHandler.java:221) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.handleText(ProcessorTemplateHandler.java:587) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.Text.beHandled(Text.java:97) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.Model.process(Model.java:300) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.GatheringModelProcessable.process(GatheringModelProcessable.java:78) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.queueProcessable(ProcessorTemplateHandler.java:2106) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.handleCloseElement(ProcessorTemplateHandler.java:1642) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.CloseElementTag.beHandled(CloseElementTag.java:139) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.Model.process(Model.java:300) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.OpenElementTagModelProcessable.process(OpenElementTagModelProcessable.java:110) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.queueProcessable(ProcessorTemplateHandler.java:2106) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.handleOpenElement(ProcessorTemplateHandler.java:1559) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.OpenElementTag.beHandled(OpenElementTag.java:205) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.TemplateModel.process(TemplateModel.java:155) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ThrottledTemplateProcessor.process(ThrottledTemplateProcessor.java:235) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ThrottledTemplateProcessor.process(ThrottledTemplateProcessor.java:200) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.spring6.SpringWebFluxTemplateEngine$StreamThrottledTemplateProcessor.process(SpringWebFluxTemplateEngine.java:720) ~[thymeleaf-spring6-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.spring6.SpringWebFluxTemplateEngine.lambda$createChunkedStream$2(SpringWebFluxTemplateEngine.java:269) ~[thymeleaf-spring6-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at reactor.core.publisher.FluxGenerate$GenerateSubscription.slowPath(FluxGenerate.java:271) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxGenerate$GenerateSubscription.request(FluxGenerate.java:213) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.request(FluxPeekFuseable.java:144) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.requestUpstream(FluxSubscribeOn.java:131) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.onSubscribe(FluxSubscribeOn.java:124) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onSubscribe(FluxPeekFuseable.java:178) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxGenerate.subscribe(FluxGenerate.java:85) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.InternalFluxOperator.subscribe(InternalFluxOperator.java:68) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.run(FluxSubscribeOn.java:194) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.scheduler.BoundedElasticThreadPerTaskScheduler$SchedulerTask.run(BoundedElasticThreadPerTaskScheduler.java:1013) ~[reactor-core-3.7.5.jar:3.7.5]
at java.base/java.lang.VirtualThread.run(VirtualThread.java:329) ~[na:na]
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Locale "" cannot be used as it does not specify a language. (template: "modules/layout" - line 12, col 49)
at org.thymeleaf.messageresolver.StandardMessageResolutionUtils.computeMessageResourceNamesFromBase(StandardMessageResolutionUtils.java:202) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.messageresolver.StandardMessageResolutionUtils.resolveMessagesForTemplate(StandardMessageResolutionUtils.java:69) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.messageresolver.StandardMessageResolver.resolveMessagesForTemplate(StandardMessageResolver.java:380) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.messageresolver.StandardMessageResolver.resolveMessage(StandardMessageResolver.java:282) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.messageresolver.StandardMessageResolver.resolveMessage(StandardMessageResolver.java:227) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.context.AbstractEngineContext.getMessage(AbstractEngineContext.java:134) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.standard.expression.MessageExpression.executeMessageExpression(MessageExpression.java:265) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:69) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:109) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:138) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.standard.processor.StandardUtextTagProcessor.doProcess(StandardUtextTagProcessor.java:87) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.handleOpenElement(ProcessorTemplateHandler.java:1314) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.OpenElementTag.beHandled(OpenElementTag.java:205) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.TemplateModel.process(TemplateModel.java:136) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.TemplateManager.process(TemplateManager.java:519) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.util.LazyProcessingCharSequence.writeUnresolved(LazyProcessingCharSequence.java:85) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.util.AbstractLazyCharSequence.write(AbstractLazyCharSequence.java:103) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.AbstractTextualTemplateEvent.writeContent(AbstractTextualTemplateEvent.java:224) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.Text.write(Text.java:78) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.OutputTemplateHandler.handleText(OutputTemplateHandler.java:71) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
... 29 common frames omitted
```
#### Does this PR introduce a user-facing change?
```release-note
修复因 Locale 解析错误导致无法访问页面的问题
```
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR removes `/uploads/**` from static resources to make it protected by Halo security.
#### Does this PR introduce a user-facing change?
```release-note
None
```
* refactor: improve entity component layout for better device responsiveness
Signed-off-by: Ryan Wang <i@ryanc.cc>
* Resolve CSS style conflicts
Signed-off-by: Ryan Wang <i@ryanc.cc>
* Update missing translaions
Signed-off-by: Ryan Wang <i@ryanc.cc>
---------
Signed-off-by: Ryan Wang <i@ryanc.cc>
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR sets Java 21 as minimal version. After doing that, Halo can only run on Java 21 or newer version.
Fortunately, all plugins and themes won't be affected by the restriction.
> https://docs.gradle.org/current/userguide/toolchains.html#sec:release-flag-toolchain
#### Which issue(s) this PR fixes:
Fixes https://github.com/halo-dev/halo/issues/6867
#### Does this PR introduce a user-facing change?
```release-note
[Action Required] 更新最低运行环境为 Java 21
```
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
Defining `into` property in `processResources` task is not working, so I create a new copy task to process UI dist.
#### Does this PR introduce a user-facing change?
```release-note
None
```
#### What type of PR is this?
/kind cleanup
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR bumps versions to 2.21.0-SNAPSHOT, including ui packages and API client.
#### Does this PR introduce a user-facing change?
```release-note
None
```
#### What type of PR is this?
/kind improvement
#### What this PR does / why we need it:
过期的Spring @Component API
#### Which issue(s) this PR fixes:
Fixes#7431
#### Does this PR introduce a user-facing change?
```release-note
None
```
#### What type of PR is this?
/area plugin
/area editor
/milestone 2.20.x
#### What this PR does / why we need it:
Previously, editor extension related types were not exported because the type names conflicted with some UI component names, making it impossible to import extension types in plugins. This PR modifies the type names and exports them in index.ts.
#### Does this PR introduce a user-facing change?
```release-note
导出与编辑器扩展相关的类型定义
```
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.20.x
#### What this PR does / why we need it:
This PR adds support for redirection on logout. We can request <http://localhost:8090/logout?redirect_uri=/archives> with GET method, then click the logout to see the redirection.
#### Which issue(s) this PR fixes:
Fixes https://github.com/halo-dev/halo/issues/7401
#### Does this PR introduce a user-facing change?
```release-note
登出页面支持自定义重定向
```
#### What type of PR is this?
/kind bug
/area core
/milestone 2.20.x
#### What this PR does / why we need it:
1. This PR removes duplicate invocations while resolving handler functions of theme.
2. Throw NotFoundException while post was not found.
#### Which issue(s) this PR fixes:
Fixes https://github.com/halo-dev/halo/issues/7409
#### Does this PR introduce a user-facing change?
```release-note
修复访问不存在的分类或者文章页面时始终抛出异常的问题
```
#### What type of PR is this?
/kind feature
#### What this PR does / why we need it:
标签支持根据文章量排序
#### Does this PR introduce a user-facing change?
```release-note
标签支持根据文章量排序
```
#### What type of PR is this?
/kind bug
/area core
/milestone 2.20.x
#### What this PR does / why we need it:
This PR adds SwitchUserGrantedAuthorityMixin into HaloSecurityJackson2Module to fix the deserialization error.
See https://github.com/halo-dev/halo/issues/7406 for more.
#### Which issue(s) this PR fixes:
Fixes https://github.com/halo-dev/halo/issues/7406
#### Does this PR introduce a user-facing change?
```release-note
修复个人中心处可能出现登录设备查询异常的问题
```
#### 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 Argon2 password encoder as default to remove password limit of 72.
Please note that there is no compatibility issue for old passwords.
#### Which issue(s) this PR fixes:
Fixes#7405
#### Special notes for your reviewer:
1. Try to login as admin
2. Create a password having the length of 73 or more for a new user
3. See the result
#### Does this PR introduce a user-facing change?
```release-note
修复无法设置长度超过72个字符的密码的问题
```