Commit Graph

329 Commits (9676ccee0e415ad34ff2eb0ec23129a3861625f9)

Author SHA1 Message Date
guqing cc891d6655
feat: add annotations expression object for thymeleaf (#3076)
#### What type of PR is this?
/kind feature
/area core
/milestone 2.1.x
#### What this PR does / why we need it:
新增操作 annotations 的表达式对象
在 thymeleaf 模板中使用示例:
```html
<p th:text="${#annotations.get(user, 'background')}"></p>
<p th:text="${#annotations.getOrDefault(user, 'background', 'default-value')}"></p>
<p th:text="${#annotations.contains(user, 'background')}"></p>
```
#### Which issue(s) this PR fixes:

Fixes #3073

#### Special notes for your reviewer:
/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?
```release-note
新增 Annotations 表达式对象用于在 thymeleaf 中操作自定义模型的 annotations
```
2022-12-29 13:30:34 +00:00
guqing 9d0ad5de26
refactor: remove finalizer when resources deleted completely (#3065)
#### What type of PR is this?
/kind improvement
/area core

#### What this PR does / why we need it:
主题卸载时等待删除关联资源后再清除 Finalizer
see #2967 for more detail.
https://github.com/halo-dev/halo/issues/2967#issuecomment-1354384978

#### Which issue(s) this PR fixes:
how to test it?
- 在主题中多添加一个 AnnotationSetting 资源 yaml,测试主题删除是否正常。
- 对包 `org.springframework.retry` 开启 debug 日志后能在删除主题时看到类似如下日志:
```
16:33:02.822 [Test worker] DEBUG org.springframework.retry.support.RetryTemplate - Retry: count=0
16:33:03.128 [Test worker] DEBUG org.springframework.retry.support.RetryTemplate - Checking for rethrow: count=1
```
Fixes #2967
#### Special notes for your reviewer:
/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
主题卸载时等待删除关联资源后再清除 Finalizer
```
2022-12-29 10:12:36 +00:00
John Niang 313605d52c
Provide an endpoint to update user profile (#3067)
#### What type of PR is this?

/kind feature
/area core
/milestone 2.1.x

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

Provide an endpoint to update current user profile instead of whole user data.

##### Request example

```bash
curl -X 'PUT' \
  'http://localhost:8090/apis/api.console.halo.run/v1alpha1/users/-' \
  -H 'accept: */*' \
  -H 'Content-Type: */*' \
  -d '{
  "spec": {
    "displayName": "JohnNiang",
    "email": "johnniang@halo.run",
    "password": "xxx",
    "registeredAt": "2022-12-19T03:46:54.809770900Z",
    "twoFactorAuthEnabled": false,
    "disabled": false
  },
  "status": {
    "permalink": "http://localhost:8090/authors/admin"
  },
  "apiVersion": "v1alpha1",
  "kind": "User",
  "metadata": {
    "finalizers": [
      "user-protection"
    ],
    "name": "admin",
    "annotations": {
      "rbac.authorization.halo.run/role-names": "[\"super-role\"]"
    },
    "version": 3,
    "creationTimestamp": "2022-12-19T03:46:54.911951800Z"
  }
}'
```

##### Response example

```json
{
  "spec": {
    "displayName": "JohnNiang",
    "email": "johnniang@halo.run",
    "password": "{bcrypt}$2a$10$IBV8/q7Q6Fj78Ls5AG1eBO0bCQ.rM6vli5pAVexf/gqu.hNfjJxaq",
    "registeredAt": "2022-12-19T03:46:54.809770900Z",
    "twoFactorAuthEnabled": false,
    "disabled": false
  },
  "status": {
    "permalink": "http://localhost:8090/authors/admin"
  },
  "apiVersion": "v1alpha1",
  "kind": "User",
  "metadata": {
    "finalizers": [
      "user-protection"
    ],
    "name": "admin",
    "annotations": {
      "rbac.authorization.halo.run/role-names": "[\"super-role\"]"
    },
    "version": 5,
    "creationTimestamp": "2022-12-19T03:46:54.911951800Z"
  }
}
```

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

Fixes https://github.com/halo-dev/halo/issues/3035

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

```release-note
提供更新当前登录用户信息功能
```
2022-12-29 03:16:33 +00:00
John Niang da55532777
Refine exception detail with i18n (#3042)
#### What type of PR is this?

/kind feature
/kind api-change
/area core
/milestone 2.1.x

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

- Configuring message source location and name enables i18n message resolution.
- Simple global error handler.
- Refactor some exceptions with `ResponseStatusException` to control what HTTP status and problem detail need to be returned.

**TODO**

- [x] Add more UTs.
#### Which issue(s) this PR fixes:

Fixes https://github.com/halo-dev/halo/issues/3020

#### Special notes for your reviewer:

Steps to test:

1. Try to refine `src/main/resources/config/i18n/messages_zh.properties` and switch Browser language with Chinese.
2. Delibrately make a mistake as you wish and see the error tips in console.
3. Try to access one page which doesn't exist and see the rendered result.

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

```release-note
完成系统异常的国际化
```
2022-12-26 14:10:31 +00:00
guqing ddf47f6600
feat: add annotation setting extension (#3028)
#### What type of PR is this?
/kind feature
/milestone 2.1.x
/area core

#### What this PR does / why we need it:
新增 AnnotationSetting 自定义模型以扩展自定义元数据设置表单

主题安装/更新/重载时都会重新加载与 theme.yaml 同层级的其他 yaml,但只会保存 kind 为 Setting 和 AnnotationSetting的,主题卸载时会删除这些 yaml 资源

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

Fixes #3005

#### Special notes for your reviewer:
how to test it?
- 修改影响到了主题安装、更新、重载和删除,需要检查这些功能是否正确加载了 Setting 和 AnnotationSetting
- 插件启动时初始化的 AnnotationSetting 在插件停止时会被删除
- 主题添加了 annotation setting 资源,使用非超级管理员也可以获取

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
新增 AnnotationSetting 以扩展自定义元数据设置表单
```
2022-12-26 13:54:36 +00:00
chengfeiyue a7da2c0d76
Support querying sub-categories of any level (#2995)
What type of PR is this?

/kind feature
/kind api-change

What this PR does / why we need it:

添加一个方法可以根据分类树的任意一层级的名称查询子树

Which issue(s) this PR fixes:

Fixes https://github.com/halo-dev/halo/issues/2960

Special notes for your reviewer:

None

Does this PR introduce a user-facing change?

```release-note
CategoryFinder 添加根据分类查询子分类树结构的方法
```
2022-12-22 03:56:29 +00:00
guqing 9d6bcdf072
fix: page stats does not subscribe in finder (#3003)
#### What type of PR is this?
/kind bug
/area core
#### What this PR does / why we need it:
修复自定义页面 Finder 中 getByName 方法没有返回访问量的问题
此问题为重构 #2918 时引入。

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

Fixes #2992

#### Special notes for your reviewer:
/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?
```release-note
None
```
2022-12-20 14:56:29 +00:00
guqing 27775c9ac9
feat: add reset config API for theme and plugin (#2964)
#### What type of PR is this?
/kind feature
/kind api-change
/area core

#### What this PR does / why we need it:
为主题和插件提供重置设置项 API

此 PR 会重新读取配置对应的 Setting 资源,从其中读取默认值后更新到现有的 ConfigMap 中替换其 data
see #2789 for more details
#### Which issue(s) this PR fixes:

Fixes #2789

#### Special notes for your reviewer:
how to test it?
1. 在主题设置或插件设置配置一些设置项后保存
2. 执行重置配置
3. 配置恢复为了 Setting 中指定的默认值

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
为主题和插件提供重置设置项 API
```
2022-12-19 02:28:10 +00:00
will efc940df99
fix: not clearing the template engine cache after upgrading the theme (#2970)
#### What type of PR is this?

/kind improvement

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

通过在模板引擎管理器里添加clearCache方法,在升级主题后进行缓存刷新,让新模板内容生效。

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

Fixes #2953 

#### Special notes for your reviewer:

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

```release-note
NONE
```
2022-12-19 02:24:10 +00:00
guqing 7a2f5d0a99
feat: add author pages for theme-side (#2923)
#### What type of PR is this?
/kind feature
/area core

#### What this PR does / why we need it:
为主题端新增作者页面
see #2837 for more detail
#### Which issue(s) this PR fixes:

Fixes #2837

#### Special notes for your reviewer:
/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
主题端支持作者页面
```
2022-12-14 09:32:18 +00:00
guqing 925dec476f
fix: plugin logo cannot be loaded when it is not enabled (#2940)
#### What type of PR is this?
/kind bug
/area core

#### What this PR does / why we need it:
修复插件 logo 为相对路径时先启用再停后就无法加载 logo  的问题

原因是 reverse proxy reconciler 资源被删除要取消注册路由时没有确切指定名称,logo 这样的 ReverseProxy 是插件安装时初始化的这条初始化的规则要跟随插件的生命周期,只有插件卸载时才会被删除,而在此之前插件被停止时就被误取消注册了

see #2937 for more detail
#### Which issue(s) this PR fixes:

Fixes #2937

#### Special notes for your reviewer:
/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
修复插件 logo 为相对路径时先启用再停后就无法加载 logo  的问题
```
2022-12-14 08:51:24 +00:00
guqing a9a65dd408
refactor: metrics to fix post visits cannot be migrated (#2870)
#### What type of PR is this?
/kind improvement
/area core

#### What this PR does / why we need it:
重构访问量统计逻辑
1. 去掉了访问量总数存储在 Meter Counter 中的逻辑,因为迁移时是直接像 Counter 自定义模型创建数据,而文章被访问时是存储在 Meter Counter 后定时同步到数据库,这就存在双向同步问题且都有新数据无法知道该如何合并数据。
2. 目前访问时会发送一个事件,当得到事件后会缓存在队列中,每隔一分钟将增量更新到数据库中
3. 评论统计也去掉了 Meter Counter 改为事件队列处理
4. 如果后续要暴露 Metrics 应该使用 Gauge 监控 Counter 自定义模型
5. Counter 自定义模型的查询优化后续可以使用 Indexer 或者加缓存来实现而非将 Meter Counter 当作缓存
#### Which issue(s) this PR fixes:

Fixes #2820

#### Special notes for your reviewer:
1. 测试迁移导入看文章访问量是否正确
2. 创建评论及回复观察未读回复数量、评论回复数、最新回复时间是否正确
3. 多创建一些回复然后删除评论,看是否正确删除

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
重构访问量统计逻辑,修复文章visits无法迁移的问题
```
2022-12-13 03:42:44 +00:00
guqing 52906f21c1
fix: single page does not count visits (#2918)
#### What type of PR is this?
/kind bug
/area core

#### What this PR does / why we need it:
修复自定义页面没有统计访问量的问题
#### Which issue(s) this PR fixes:

Fixes #2912

#### Special notes for your reviewer:
how to test it?
创建自定义页面并到主题端访问,可以看到访问量增加

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?
```release-note
修复自定义页面没有统计访问量的问题
```
2022-12-12 03:48:22 +00:00
guqing 68ccbb098b
refactor: plugin author to an object (#2806)
#### What type of PR is this?
/kind improvement
/area core
/kind api-change

#### What this PR does / why we need it:
将 Plugin 的 author 改为 Author 对象与主题保持一致。
移除了测试类中使用的 jar 文件,改为使用时压缩

⚠️ 此为破坏性更新,需要修改 Console 插件列表的展示,以及所有官方插件的 plugin.yaml

#### Special notes for your reviewer:
/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
Require-user-change:将 Plugin 的 author 类型从 String 为 Author
```
2022-11-30 15:45:50 +00:00
John Niang 9f3c7ae378
Simplify MenuItem with targetRef instead of multi refs (#2799)
#### What type of PR is this?

/kind improvement
/kind api-change
/area core
/milestone 2.0.x

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

Two things this PR does:

1. **Simplify MenuItem with targetRef instead of multi refs**
2. Organize extensions with group `content.halo.run` into content folder

> **Warning** The first thing has some break changes about structure of MenuItem, please @halo-dev/sig-halo-console be aware of that.

Before:

```java
        @Schema(description = "Category reference.")
        private Ref categoryRef;

        @Schema(description = "Tag reference.")
        private Ref tagRef;

        @Schema(description = "Post reference.")
        private Ref postRef;

        @Schema(description = "SinglePage reference.")
        private Ref singlePageRef;
```

After:

```java
        @Schema(description = "Target reference. Like Category, Tag, Post or SinglePage")
        private Ref targetRef;
```

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

Fixes https://github.com/halo-dev/halo/issues/2739

#### Special notes for your reviewer:

Because this PR contains break changes, we cannot test it in console directly.

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

```release-note
None
```
2022-11-30 13:43:49 +00:00
guqing bd02d9bb3b
chore: temporarily disable JWT authentication function (#2804)
#### What type of PR is this?
/kind improvement
/area core
/kind api-change

#### What this PR does / why we need it:
- 暂时关闭 JWT 认证功能,`POST /api/auth/token` API 将失效。
- 移除  `halo.security.oauth2.jwt` 配置,公私钥放在 classpath 只是之前还没有 halo work dir 时的临时方案
- Disable  JWT 相关的单元测试

后续会 Revert 此 PR。

#### Special notes for your reviewer:
how to test it?
1. 期望 `/api/auth/token` 失效
2. 期望 Console 登录功能没问题

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
None
```
2022-11-30 10:21:47 +00:00
guqing 9d60b8ae06
feat: theme templates support global seo settings (#2801)
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.0.0-rc.2

#### What this PR does / why we need it:
适配 SEO 系统设置,此功能之前遗漏

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

Fixes #2797

#### Special notes for your reviewer:
how to test it?
1. seo 设置禁用搜索引擎,会在所有页面的 head 添加 `<meta name="robots" content="noindex" />`
2. seo 设置填写`关键词`和`描述`会在所有页面的 head 标签填充 `<meta name="xxx> content="xxx" />` 

/cc @halo-dev/sig-halo
#### Does this PR introduce a user-facing change?

```release-note
支持 SEO 全局系统设置
```
2022-11-30 02:31:46 +00:00
John Niang eefdd27c44
Simplify references in Attachment (#2800)
#### What type of PR is this?

/kind improvement
/kind api-change
/area core
/milestone 2.0.x

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

This PR replace refs in Attachment extension with simple name.

> **Warning** Please @halo-dev/sig-halo-console be aware of that this PR contains break changes, so that we can not use Attachment feature in the console directly. The console has to adapt the break changes.

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

```release-note
None
```
2022-11-30 02:23:46 +00:00
guqing de983a2e46
refactor: cannot reload when settingName is not configured before (#2745)
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.0.0-rc.1
/kind api-change

#### What this PR does / why we need it:
- 修复 theme.yaml 之前没有配置过 settingName 会无法 reload 的问题
- 将 `/themes/{name}/reload-setting` 的 API 修改为 `/themes/{name}/reload`

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

Fixes #2735

#### Special notes for your reviewer:
/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
修复 theme.yaml 之前没有配置过 settingName 会无法 reload 的问题
```
2022-11-28 03:00:17 +00:00
John Niang 145cfb88b7
Delegate ReactiveExtensionClient for default implementation of ExtensionClient (#2774)
#### What type of PR is this?

/kind bug
/kind cleanup
/area core

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

This PR fully delegates ReactiveExtensionClient for default implementation of ExtensionClient and remove old implementation, including its tests. The main reason I delegate is for keeping consistent about implementation of ExtensionClient.

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

Fixes https://github.com/halo-dev/halo/issues/2755

#### Special notes for your reviewer:

You can test full functions after starting Halo with current changes.

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

```release-note
None
```
2022-11-25 13:41:25 +00:00
John Niang 0df7857ef8
Refactor reconcilers registration (#2737)
#### What type of PR is this?

/kind cleanup
/kind improvement
/area core
/milestone 2.0.0

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

This PR mainly refactors registration of reconcilers to register reconciler more convinient. After that, it is possible to reigster and start reconciler in plugin.

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

Fixes https://github.com/halo-dev/halo/issues/2305

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

```release-note
None
```
2022-11-25 11:13:09 +00:00
guqing a76ade8aa8
feat: add global error web exception handler (#2741)
#### What type of PR is this?
/kind feature
/milestone 2.0.0-rc.1
/area core

#### What this PR does / why we need it:
新增全局异常处理
参考文档:
- [web.reactive.webflux.error-handling](https://docs.spring.io/spring-boot/docs/3.0.0-RC2/reference/htmlsingle/#web.reactive.webflux.error-handling)
- [webflux-ann-rest-exceptions](https://docs.spring.io/spring-framework/docs/6.0.0-RC4/reference/html/web-reactive.html#webflux-ann-rest-exceptions)

发生异常时返回形如以下结构
```json
{
    "type": "about:blank",
    "title": "Not Found",
    "status": 404,
    "detail": "Hello not found test.",
    "instance": "/hello"
}
```
此结构遵循 [RFC 7807 Problem Details](https://www.rfc-editor.org/rfc/rfc7807.html)

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

Fixes #2732

#### Special notes for your reviewer:
how to test it?
更新文章前把 title 字段删除,会出现校验异常 BadRequest

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
新增全局异常处理
```
2022-11-24 12:45:07 +00:00
John Niang edfc9ac1e1
Ignore websocket protocol while proxying console (#2760)
#### What type of PR is this?

/kind feature
/area core

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

Ignore websocket protocol while proxying console. If we don't do this, console dev environment will crash with following error:

```bash
  VITE v3.2.4  ready in 1672 ms

  ➜  Local:   http://localhost:3000/console/                                                                           16:12:21
  ➜  Network: http://172.23.176.1:3000/console/                                                                        16:12:21
  ➜  Network: http://172.18.96.1:3000/console/                                                                         16:12:21
  ➜  Network: http://192.168.31.106:3000/console/                                                                      16:12:21
[vite-plugin-static-copy] Collected 8 items.                                                                           16:12:21
node:events:491
      throw er; // Unhandled 'error' event
      ^

RangeError: Invalid WebSocket frame: RSV1 must be clear
    at Receiver$1.getInfo (file:///C:/Users/johnn/workspaces/halo-dev/console/node_modules/.pnpm/vite@3.2.4_ajklay5k626t46b6fyghkbup3i/node_modules/vite/dist/node/chunks/dep-67e7f8ab.js:54186:14)
    at Receiver$1.startLoop (file:///C:/Users/johnn/workspaces/halo-dev/console/node_modules/.pnpm/vite@3.2.4_ajklay5k626t46b6fyghkbup3i/node_modules/vite/dist/node/chunks/dep-67e7f8ab.js:54133:22)
    at Receiver$1._write (file:///C:/Users/johnn/workspaces/halo-dev/console/node_modules/.pnpm/vite@3.2.4_ajklay5k626t46b6fyghkbup3i/node_modules/vite/dist/node/chunks/dep-67e7f8ab.js:54080:10)
    at writeOrBuffer (node:internal/streams/writable:392:12)
    at _write (node:internal/streams/writable:333:10)
    at Writable.write (node:internal/streams/writable:337:10)
    at Socket.socketOnData (file:///C:/Users/johnn/workspaces/halo-dev/console/node_modules/.pnpm/vite@3.2.4_ajklay5k626t46b6fyghkbup3i/node_modules/vite/dist/node/chunks/dep-67e7f8ab.js:56826:37)
    at Socket.emit (node:events:513:28)
    at addChunk (node:internal/streams/readable:324:12)
    at readableAddChunk (node:internal/streams/readable:297:9)
    at Readable.push (node:internal/streams/readable:234:10)
    at TCP.onStreamRead (node:internal/stream_base_commons:190:23)
Emitted 'error' event on WebSocket$1 instance at:
    at Receiver$1.receiverOnError (file:///C:/Users/johnn/workspaces/halo-dev/console/node_modules/.pnpm/vite@3.2.4_ajklay5k626t46b6fyghkbup3i/node_modules/vite/dist/node/chunks/dep-67e7f8ab.js:56712:13)
    at Receiver$1.emit (node:events:513:28)
    at emitErrorNT (node:internal/streams/destroy:151:8)
    at emitErrorCloseNT (node:internal/streams/destroy:116:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  code: 'WS_ERR_UNEXPECTED_RSV_1',
  [Symbol(status-code)]: 1002
}

Node.js v18.12.1
 ELIFECYCLE  Command failed with exit code 1.
```

#### Special notes for your reviewer:

Steps to test:

1. Edit your application.yaml with console proxy configuration
2. Start Halo
3. Use non-Chromelike browser to request <http://localhost:8090>.
4. See the result

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

```release-note
None
```
2022-11-24 11:31:06 +00:00
John Niang f96ef7f1b3
Provide ungrouped query param to filter ungrouped attachments (#2752)
#### What type of PR is this?

/kind feature
/area core
/milestone 2.0.0-rc.1

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

Provide `ungrouped` query param to filter ungrouped attachments. Please note that we will ignore `group` query param when `ungropued` is `true`.

```bash
curl -X 'GET' \
  'http://localhost:8090/apis/api.console.halo.run/v1alpha1/attachments?ungrouped=true' \
  -H 'accept: */*'
```

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

Fixes https://github.com/halo-dev/halo/issues/2451

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

```release-note
None
```
2022-11-24 07:43:02 +00:00
guqing cca95cbfab
refactor: snapshot attributes and post publish (#2709)
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.0
 
#### What this PR does / why we need it:
1. 简化 Snapshot 的指责,去除 Snapshot 中关于 version,publishTime 等与发布相关的东西,Snapshot本身没有发布概念
2. 对应修改文章和自定义页面,将版本的概念转移到拥有 Snapshot 的模型上,如 Post 和 SinglePage

⚠️此 PR 为破坏性更新,对旧数据不兼容,可能导致旧数据文章内容无法显示问题

Console 端需要做出一些修改:
- 将文章发布前调用保存内容的 API 修改为 `/posts/{name}/content`
- 将自定义页面发布前调用保存内容的 API 修改为 `/singlepages/{name}/content`

发布接口提供了一个 `async` 参数,默认值为 `false`此时发布API需要等待发布成功后才返回结果,如果等待超时则提示`Publishing wait timeout.`, 如果传递 `async=true` 表示异步发布,更新完数据就成功,reconciler 在后台慢慢执行。

#### Special notes for your reviewer:
how to test it?
1. 新创建一篇文章,测试点击保存是否成功
2. 新创建一篇文章,测试编辑内容后直接发布是否成功
3. 测试发布过的文章的取消发布状态是否显示未发布状态
4. 对于 Snapshot,新建文章点保存会创建一个snapshot,点击发布则是更新之前点保存创建的一条,所以记录数不会多,发布之后进入编辑随便写点内容直接点发布后查询snapshot则会多一条记录。
5. 文章的 status 里的 conditions 最新添加的都在第一个即头插入,如果连续两次发布则不会在增加 condition,长度超过20条会把旧的 condition 删除掉
6. 自定义页面上同

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
Action Required: 简化 Snapshot 模型的职责,去除版本相关属性
```
2022-11-18 13:32:23 +00:00
John Niang e87067eb60
Enable adding more workers for controller (#2718)
#### What type of PR is this?

/kind feature
/kind improvement
/area core
/milestone 2.0

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

This PR enables adding more workers for controller to speed up reconciliations. Default woker count is 1 for one controller.

**What's next?**

- [ ] Enable configuring worker count for every controller in configuration properties.

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

Fixes https://github.com/halo-dev/halo/issues/2708

#### Special notes for reviewers

You can see there are more threads for post controller in the following screenshot:

![image](https://user-images.githubusercontent.com/16865714/202608470-8763826a-a69c-47b5-8f41-f0612919d681.png)

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

```release-note
None
```
2022-11-18 08:08:22 +00:00
guqing c8bc96ffc3
refactor: support chaining calls for flux and mono in javascript inline tag (#2715)
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.0

#### What this PR does / why we need it:
支持在 JavaScript 中对 Flux 或 Mono 的泛型类型属性链式调用
测试参考:
7e9bdec492/src/test/java/run/halo/app/theme/ReactiveFinderExpressionParserTests.java (L131-L147)
期望
7e9bdec492/src/test/java/run/halo/app/theme/ReactiveFinderExpressionParserTests.java (L64-L79)

#### Special notes for your reviewer:
/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
支持在 JavaScript 中对 Flux 或 Mono 的泛型类型属性链式调用
```
2022-11-18 06:32:22 +00:00
guqing eeb9c4dc7a
feat: support obtaining the configuration of halo.external-url for themes and plugins (#2714)
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.0

#### What this PR does / why we need it:
主题和插件支持获取 `halo.external-url` 配置信息

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

Fixes #2711
#### Special notes for your reviewer:
how to test it?
1. 在主题中使用`<p th:text="${site.url}"></p>` 可以正确显示
2. 在插件中可以依赖注入 ExternalUrlSupplier

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
主题和插件支持获取外部访问地址配置
```
2022-11-18 06:30:27 +00:00
guqing 9f53cd1123
feat: theme finders supports the reactive API (#2695)
#### What type of PR is this?
/kind feature
/area core
/milestone 2.0

#### What this PR does / why we need it:
将所有 Finder 的返回值都修改为 Mono 或 Flux

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

Fixes #2671

#### Special notes for your reviewer:
how to test it?
切换几个主题都点一下,没有报错即为正常

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
主题端 Finder 支持 Reactive API
```
2022-11-17 02:48:22 +00:00
John Niang f1ac4e3740
Provide sort query param for sorting attachment (#2705)
#### What type of PR is this?

/kind feature
/area core
/milestone 2.0

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

Provide sort query param for sorting attachment. By default, we use creationTimestamp(desc) to sort the attachments.

Below is an example to sort with creationTimestamp(desc) and size(asc):

```bash
curl -X 'GET' \
  'http://localhost:8090/apis/api.console.halo.run/v1alpha1/attachments?sort=creationTimestamp%2Cdesc&sort=size%2Casc' \
  -H 'accept: */*'
```

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

Fixes https://github.com/halo-dev/halo/issues/2627

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

```release-note
附件列表支持排序
```
2022-11-16 10:10:19 +00:00
John Niang 0c8ccecdf3
Initialize default theme when Halo starts up for the first time (#2704)
#### What type of PR is this?

/kind feature
/area core
/milestone 2.0

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

1. Initialize default theme when we detect the theme root has no themes here. This process won't stop Halo starting up if error occurs.
2. Refactor ThemeEndpoint with ThemeService to make it reusable.

Default theme configuration is as following:

```yaml
halo:
  theme:
    initializer:
      disabled: false
      location: classpath:themes/theme-earth.zip
```

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

Fixes https://github.com/halo-dev/halo/issues/2700

#### Special notes for your reviewer:

Steps to test:

1. Delete all themes at console if installed
2. Restart Halo and check the log
4. Check the theme root folder `~/halo-next/themes`
5. Try to access index page and you will see the default theme

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

```release-note
在首次启动 Halo 时初始化默认主题
```
2022-11-15 10:50:18 +00:00
John Niang dac4eecea6
Implement full-text search of posts with Lucene default (#2675)
#### What type of PR is this?

/kind feature
/area core
/milestone 2.0

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

This PR mainly implement full-text search of posts and provide extension point for other search engine.

Meanwhile, I implement ExtensionGetter to get implemention(s) of extension point from system ConfigMap.

But there still are something to do here:

- [x] Udpate documents when posts are published or posts are becoming unpublic.
- [x] Delete documents when posts are unpublished or deleted.

Because I'm waiting for https://github.com/halo-dev/halo/pull/2659 got merged.

I create two endpoints:

1. For full-text search of post

    ```bash
    curl -X 'GET' \
      'http://localhost:8090/apis/api.halo.run/v1alpha1/indices/post?keyword=halo&limit=10000&highlightPreTag=%3CB%3E&highlightPostTag=%3C%2FB%3E' \
      -H 'accept: */*'
    ```

1. For refreshing indices

    ```bash
    curl -X 'POST' \
      'http://localhost:8090/apis/api.console.halo.run/v1alpha1/indices/post' \
      -H 'accept: */*' \
      -d ''
    ```

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

Fixes #https://github.com/halo-dev/halo/issues/2637

#### Special notes for your reviewer:

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

```release-note
提供文章全文搜索功能并支持搜索引擎扩展
```
2022-11-11 16:12:13 +00:00
John Niang 8b9ea1d301
Fix test issues on Windows (#2693)
#### What type of PR is this?

/kind cleanup

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

Fix failing tests on Windows.

```bash
╰─$ ./gradlew check

> Task :checkstyleTest
Checkstyle rule violations were found. See the report at: file:///C:/Users/johnn/workspaces/halo-dev/halo/build/reports/checkstyle/test.html
Checkstyle files with violations: 8
Checkstyle violations by severity: [warning:20]


> Task :test
2022-11-11T14:19:41.265+08:00 DEBUG 5948 --- [ionShutdownHook] r.halo.app.metrics.CounterMeterHandler   : Persist counter meters to database before destroy...
2022-11-11T14:19:41.277+08:00 DEBUG 5948 --- [ionShutdownHook] r.halo.app.metrics.CounterMeterHandler   : Persist counter meters to database before destroy...
2022-11-11T14:19:41.281+08:00 DEBUG 5948 --- [ionShutdownHook] r.halo.app.metrics.CounterMeterHandler   : Persist counter meters to database before destroy...
2022-11-11T14:19:41.285+08:00 DEBUG 5948 --- [ionShutdownHook] r.halo.app.metrics.CounterMeterHandler   : Persist counter meters to database before destroy...
2022-11-11T14:19:41.289+08:00 DEBUG 5948 --- [ionShutdownHook] r.halo.app.metrics.CounterMeterHandler   : Persist counter meters to database before destroy...
2022-11-11T14:19:41.298+08:00 DEBUG 5948 --- [ionShutdownHook] r.halo.app.metrics.CounterMeterHandler   : Persist counter meters to database before destroy...
2022-11-11T14:19:41.301+08:00 DEBUG 5948 --- [ionShutdownHook] r.halo.app.metrics.CounterMeterHandler   : Persist counter meters to database before destroy...
2022-11-11T14:19:41.304+08:00 DEBUG 5948 --- [ionShutdownHook] r.halo.app.metrics.CounterMeterHandler   : Persist counter meters to database before destroy...
2022-11-11T14:19:41.306+08:00 DEBUG 5948 --- [ionShutdownHook] r.halo.app.metrics.CounterMeterHandler   : Persist counter meters to database before destroy...
2022-11-11T14:19:41.309+08:00 DEBUG 5948 --- [ionShutdownHook] r.halo.app.metrics.CounterMeterHandler   : Persist counter meters to database before destroy...
2022-11-11T14:19:41.311+08:00 DEBUG 5948 --- [ionShutdownHook] r.halo.app.metrics.CounterMeterHandler   : Persist counter meters to database before destroy...

BUILD SUCCESSFUL in 47s
7 actionable tasks: 2 executed, 5 up-to-date

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

```release-note
None
```
2022-11-11 10:52:11 +00:00
guqing 7e592a3835
feat: add plugin finder for theme-side (#2683)
#### What type of PR is this?
/kind feature
/milestone 2.0
/area core
#### What this PR does / why we need it:
主题端提供判断插件是否已经启用的方法

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

#### Special notes for your reviewer:
how to test it?
在主题端使用 `${pluginFinder.available(your-plugin-name)}`  来查看某个插件是否已经启用,如果是则得到 true ,否则 false,如果插件没有安装也得到 false

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
主题端支持获取插件启用状态
```
2022-11-11 02:26:11 +00:00
guqing 3adf5b8a95
refactor: change from manual publishing to automatic publishing (#2659)
#### What type of PR is this?
/kind improvement
/milestone 2.0
/area core
/kind api-change

#### What this PR does / why we need it:
- 通过修改 `spec.publish=true` 且 `spec.releasedSnapshot = spec.headSnapshot` 来实现通过 reconciler 异步发布
- Snapshot 中的 subjectRef 类型改为了 Ref 类型,因为之前的 Snapshot.SubjectRef 只包含了 kind 和 name 可能会冲突

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

Fixes #2650

#### Special notes for your reviewer:
how to test it?
1. 通过 `POST /apis/console.halo.run/v1alpha1/posts` 创建文章并将 `spec.publish=true`,创建后查询可以看到 `spec.baseSnapshot`、`spec.headSnapshot`、`spec.releasedSnapshot` 三个值都相等,且 `status.phase=PUBLISHED`(此过程相当于创建即发布没有保存过程)
2. 先通过 `POST /apis/console.halo.run/v1alpha1/posts` 创建一篇草稿(`spec.publish=false`),在获取它并设置 `spec.publish=true` ,更新后期望文章为发布状态 `spec.headSnapshot`, `spec.releasedSnapshot` 都不等于空且等于 `spec.baseSnapshot`),且 `spec.version=1`(此过程相当于先保存后发布且之前从未发布过)
3. 在步骤2的基础上修改`spec.releasedSnapshot=spec.headSnapshot`并更新,期望 `spec.version=2`且`spec.releasedSnapshot` 对应的 Snapshot 数据具有 publishTime(此过程相当于发布后编辑内容在发布的场景)
4. 自定义页面亦如是

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?
```release-note
重构文章发布以解决创建与发布 API 几乎同时调用时无法成功发布文章的问题
```
2022-11-10 14:44:10 +00:00
guqing 5c05554bd8
feat: total pages returned from paging results (#2669) 2022-11-10 14:31:33 +08:00
guqing a2bb3d4a00
feat: add setting item for primary menu selector (#2667) 2022-11-09 16:01:44 +08:00
guqing 8d6838a956
refactor: add page size configuration for post (#2660) 2022-11-08 10:01:50 +08:00
guqing 36613c0442
refactor: ThemeLinkBuilder needs to rely on external url (#2661) 2022-11-08 09:33:38 +08:00
guqing 9b4ed96e2a
fix: cannot stop thread when system is interrupted (#2639)
#### What type of PR is this?
/kind bug
/kind improvement
/area core
/milestone 2.0

#### What this PR does / why we need it:
修复 Halo 异常停止时日志服务线程无法中断的问题

#### Special notes for your reviewer:
how to test it?
使用 mysql 启动 halo 但不启动 mysql,此时 halo 会无法链接 mysql
期望现象:Halo 服务终止,异常现象:Halo 抛异常但 Netty 服务器不会停止

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
修复 Halo 异常停止时日志服务线程无法中断的问题
```
2022-11-03 06:32:19 +00:00
guqing 73df5e4576
feat: create reverse proxy for logo when plugin created (#2652)
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.0
#### What this PR does / why we need it:
插件 logo 支持配置外部 URL 或相对于 resources 的路径

Console 端展示插件 logo 时使用的字段需要使用 status.logo 而非 spec.logo
#### Which issue(s) this PR fixes:
Fixes #2651

#### Special notes for your reviewer:
how to test it?
1. 插件配置 logo 为外部 url 例如 https://guqing.xyz/avatar
2. 安装此插件后不会注册 ReverseProxy 规则
3. logo 配置为相对于 resources 的路径例如:/logo.png
4. 安装此插件后可以访问到 /plugins/{your-plugin-name}/assets/logo.png
5. 开发模式启动插件后,修改了 plugin.yaml 中的 spec.logo 则也会更新 ReverseProxy 的 rule

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?
```release-note
插件 Logo 支持配置外部 URL 或相对于 resources 的路径
```
2022-11-03 02:48:21 +00:00
guqing 1078145b18
feat: support custom rendering templates configure through themes (#2638)
#### What type of PR is this?
/kind feature
/milestone 2.0
/area core
#### What this PR does / why we need it:
文章/自定义页面/分类支持通过主题配置多套渲染模板
首先需要在 theme.yaml 中声明模板,以文章为例:
```yaml
apiVersion: theme.halo.run/v1alpha1
kind: Theme
metadata:
  name: fake-theme-name
spec:
  # ...
  customTemplates:
    # 支持通过以下形式配置 post, category, page 
    post:
      - name: 新闻
        description: 新闻类型的文章模板
        screenshot: foo.png
        # file 路径相对于主题目录的 templates 目录,.html 后缀可以带也可以省略
        # 默认 thymeleaf 查找 html 文件,除非修改了 thymeleaf suffix 配置
        file: post_news.html
```
当文章页选择模板时便可得到下拉列表以配置使用哪个模板 see https://github.com/halo-dev/halo/issues/2322#issuecomment-1215135195
选择了模板之后将模板名存储到 post 的 spec.template 中,渲染时便会首先使用 spec.template,如果该模板不存在则渲染默认模板
#### Which issue(s) this PR fixes:

Fixes #2569

#### Special notes for your reviewer:
how to test it?
1. 创建一篇文章并发布
2. 安装一个主题并查看文章详情,默认渲染主题提供的 post.html 页面
3. 修改此文章的 spec.template 字段为一个新的 html 例如 spec.template=post_docs
4. 查看该文章的详情页会渲染为 post_docs.html
5. 分类、自定义页面亦如是

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
文章/自定义页面/分类支持通过主题配置多套渲染模板
```
2022-11-02 06:22:17 +00:00
guqing c0986a4b4c
refactor: permalink automatically appends external url if it is configured (#2641)
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.0
#### What this PR does / why we need it:
如果配置了 halo.externalUrl 则 permalink 生成时会自动加上 external url

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

Fixes #

#### Special notes for your reviewer:
how to test it?
1. 配置 `halo.externalUrl` 并启动
2. 创建几篇文章、标签、分类、自定义页面
3. console 端能看到访问路径自动带上了 external url 并且通过访问路径能正确访问到相应资源

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
文章/分类/标签的访问路径自动追加外部访问地址
```
2022-11-01 15:22:16 +00:00
guqing 1be6a07d96
refactor: avoid NPE caused by children field data problem (#2645)
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.0

#### What this PR does / why we need it:
菜单和分类数列表加强健壮性,防止因为 children 字段存在垃圾数据时导致 NPE 问题
#### Which issue(s) this PR fixes:
a part of #2643

#### Special notes for your reviewer:
how to test it?
1. 创建一个层级结构菜单,比如
```
A
|-B
|-C
```
2. 删除菜单 C 然后访问主题端首页不会发生以下异常信息
```
Caused by: java.lang.NullPointerException: Cannot invoke "run.halo.app.theme.finders.vo.MenuItemVo.setParentName(String)" because "childNode" is null
```

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
修复获取菜单和分类列表时会出现 NPE 的问题
```
2022-11-01 13:30:16 +00:00
guqing c3a3281fcc
fix: labels update for post and singlepage (#2648)
#### What type of PR is this?
/kind bug
/area core
/milestone 2.0
#### What this PR does / why we need it:
修复文章和自定义页面的 labels 在文章标记为删除状态时没有更新的问题
#### Which issue(s) this PR fixes:
A part of  #2647

#### Special notes for your reviewer:
how to test it?
1. 创建文章
2. 由于没有发布,此时访问文章的 permalink 访问不到
3. 发布文章,可以正常访问
4. 更新文章的 `spec.deleted=true`,在访问文章期望404,并且 `metadata.labels` 中的数据正确
5. 自定义页面亦如是

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
None
```
2022-11-01 13:12:16 +00:00
guqing b63131c36e
feat: support obtaining the previous post and next post according to post name (#2636)
#### What type of PR is this?
/kind feature
/area core
/milestone 2.0

#### What this PR does / why we need it:
支持通过文章名称获取上一篇和下一篇文章数据

本 PR 通过实现一个固定大小的滑动窗口数据结构来通过传入的文章名称获取上一篇和下一篇文章
例如当具有一系列文章名为 [a, b, c, d, e, f, g]
查询文章名为 d 的文章的上一篇和下一篇则使用一个固定大小为 3 的滑动窗口, 示意图如下
<img width="526" alt="image" src="https://user-images.githubusercontent.com/38999863/198243133-20f77431-1107-4526-9f4f-6a11c68204e7.png">
通过窗口右移来调整当窗口圈住所需元素 D 时且 元素 D 的位置不是窗口的最后一个元素时得到一个想要的窗口
此时:
1. 如果 D 位于 window 中的第一个元素则 D 没有上一篇
2. 如果 D 位于 window 中间则 window 的第一个元素为 D 的上一篇,最后一个元素为下一篇
3. 如果 D 位于 window 的最后一个位置,则 D 没有下一篇
#### Which issue(s) this PR fixes:

Fixes #2635

#### Special notes for your reviewer:
how to test it?
1. 创建几篇文章然后发布
4. 能通过 `${postFinder.cursor(your-post-name)}` 来获取到带有上一页下一页的文章数据
5. 当文章处于第一条时没有上一页,当文章处于最后一页时没有下一页(可以通过`${postCursor.hasPrevious()}` 和 `${postCursor.hasNext()}` 判断按钮是否展示)

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
支持通过文章名称获取上一篇和下一篇文章数据
```
2022-10-31 07:44:16 +00:00
guqing 84617c3e96
refactor: ignore trailing separator for permalink router (#2632)
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.0
#### What this PR does / why we need it:
permalink 路由匹配时自动忽略末尾分隔符
例如
/archives  匹配到 /archives
/archives/ 匹配到 /archives

#### Special notes for your reviewer:
/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
None
```
2022-10-26 07:24:10 +00:00
guqing fa3e0c44f4
refactor: use LinkedHashMultimap to replace MultiValueMap (#2629)
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.0
#### What this PR does / why we need it:
ReverseProxyRouterFunctionRegistry 的注册方法之前使用了一个 LinkedMultiValueMap<String, String>,相当于是一个 Map<String, List<String>>,当插件启动后扫描到 ReverseProxy 资源保存到数据库会触发 ReverseProxyReconciler 调用`ReverseProxyRouterFunctionRegistry#register`,如果此时插件的 PluginApplicationContext 还没有被创建好,register 时会在中途因为获取不到 PluginApplicationContext 而失败然后 requeue,而 LinkedMultiValueMap 此时已经保存了一条记录 requeue后再执行 LinkedMultiValueMap(即`Map<String, List<String>>`) 这个 value 是一个 List 需要更多的判断来防止重复,需要用一个 Map<String, Set<String>>这样的结构来保证 requeue 时 ReverseProxyRouterFunctionRegistry 中集合结构之前的数据一致性这样更方便,所以将从 spring 的 LinkedMultiValueMap 切换到  guava 提供的 LinkedHashMultimap(它的结构是Map<K, Set<V>)

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

```release-note
None
```
2022-10-26 05:00:11 +00:00
John Niang d9cb6bf732
Provide an endpoint to upgrade plugin (#2624)
#### What type of PR is this?

/kind feature
/area core
/milestone 2.0

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

Provide an endpoint to upgrade plugin by uploading a new jar file.

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

Fixes https://github.com/halo-dev/halo/issues/2551

#### Special notes for your reviewer:

1. Install an old plugin
2. Update the plugin and package again
3. Upgrade the plugin and see the result

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

```release-note
提供插件更新功能
```
2022-10-26 04:02:10 +00:00
guqing 3ec7e31cac
refactor: fill in the name of the rendered template as the template id to the view model (#2626)
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.0

#### What this PR does / why we need it:
渲染模板页面时将被渲染的模板名称填充到试图模型中作为 templateId
为什么需要它:
1. thymeleaf 渲染模板可以使用 fragment,此时在 thymeleaf 的 IElementTagProcessor 等处理器中获取到的 template name不一定是例如 post.html这样的名称
2. 比如渲染文章模板 post.html 而 #2569 计划将要在 theme.yaml 中通过配置允许用户选择文章所渲染的模板,因为无法确定渲染模板的标志,例如有些处理器想在文章页插入 head 这样的需求就需要知道哪个模板是文章页。see also [issuecomment-1215135195](https://github.com/halo-dev/halo/issues/2322#issuecomment-1215135195)
所以目前想到的是通过在 render 时填充一个 templateId 到 view model 中标识模板身份
#### Which issue(s) this PR fixes:

Fixes #2621

#### Special notes for your reviewer:
how to test it?
见 issue #2621

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
修复设置了文章的 htmlMetas 字段但没有在页面的 head 注入标签的问题
```
2022-10-26 03:12:10 +00:00