Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Vanessa 2025-06-16 23:33:10 +08:00
commit 06f65e178e
7 changed files with 104 additions and 13 deletions

View file

@ -45,6 +45,7 @@
* [Docker 部署](#docker-部署)
* [Unraid 部署](#unraid-部署)
* [宝塔面板 部署](#宝塔面板部署)
* [小皮面板 部署](#小皮面板部署)
* [内部预览版](#内部预览版)
* [🏘️ 社区](#-社区)
* [🛠️ 开发指南](#-开发指南)
@ -338,6 +339,29 @@ Publish parameters: --accessAuthCode=******(访问授权码)
</details>
### 小皮面板部署
<details>
<summary>小皮面板 部署文档</summary>
#### 前提
* 需要安装小皮面板,前往[小皮面板](https://www.xp.cn/download),选择对应的脚本执行安装
#### 部署
1. 登录小皮面板后,点击左侧菜单的 **Docker**
2. 首次打开会提示安装 Docker点击 **点击安装 Docker**
3. 按照提示安装 Docker
4. 点击 **应用商店**,找到 **思源笔记**,点击 **安装** -> **立即安装**
5. 等待安装结束后,可在 **任务队列** 界面的 **已结束** 中点击 **详情** 查看安装信息
#### 访问思源笔记
* 在浏览器输入 `http://<小皮面板机器IP>:6806` 访问
</details>
### 内部预览版
我们会在有重大更新前发布内部预览版,请访问 [https://github.com/siyuan-note/insider](https://github.com/siyuan-note/insider)。

View file

@ -27,6 +27,29 @@ import (
"github.com/siyuan-note/siyuan/kernel/util"
)
func changeAttrViewLayout(c *gin.Context) {
ret := gulu.Ret.NewResult()
arg, ok := util.JsonArg(c, ret)
if !ok {
c.JSON(http.StatusOK, ret)
return
}
blockID := arg["blockID"].(string)
avID := arg["avID"].(string)
layoutType := arg["layoutType"].(av.LayoutType)
err := model.ChangeAttrViewLayout(blockID, avID, layoutType)
if err != nil {
ret.Code = -1
ret.Msg = err.Error()
c.JSON(http.StatusOK, ret)
return
}
ret = renderAttrView(avID, "", "", 1, -1)
c.JSON(http.StatusOK, ret)
}
func duplicateAttributeViewBlock(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
@ -532,10 +555,9 @@ func renderHistoryAttributeView(c *gin.Context) {
func renderAttributeView(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret)
if !ok {
c.JSON(http.StatusOK, ret)
return
}
@ -563,7 +585,13 @@ func renderAttributeView(c *gin.Context) {
query = queryArg.(string)
}
view, attrView, err := model.RenderAttributeView(id, viewID, query, page, pageSize)
ret = renderAttrView(id, viewID, query, page, pageSize)
c.JSON(http.StatusOK, ret)
}
func renderAttrView(avID, viewID, query string, page, pageSize int) (ret *gulu.Result) {
ret = gulu.Ret.NewResult()
view, attrView, err := model.RenderAttributeView(avID, viewID, query, page, pageSize)
if err != nil {
ret.Code = -1
ret.Msg = err.Error()
@ -602,6 +630,7 @@ func renderAttributeView(c *gin.Context) {
"view": view,
"isMirror": av.IsMirror(attrView.ID),
}
return
}
func getCurrentAttrViewImages(c *gin.Context) {

View file

@ -455,6 +455,7 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/av/duplicateAttributeViewBlock", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, duplicateAttributeViewBlock)
ginServer.Handle("POST", "/api/av/appendAttributeViewDetachedBlocksWithValues", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, appendAttributeViewDetachedBlocksWithValues)
ginServer.Handle("POST", "/api/av/getCurrentAttrViewImages", model.CheckAuth, getCurrentAttrViewImages)
ginServer.Handle("POST", "/api/av/changeAttrViewLayout", model.CheckAuth, changeAttrViewLayout)
ginServer.Handle("POST", "/api/ai/chatGPT", model.CheckAuth, model.CheckAdminRole, chatGPT)
ginServer.Handle("POST", "/api/ai/chatGPTWithAction", model.CheckAuth, model.CheckAdminRole, chatGPTWithAction)

View file

@ -28,6 +28,7 @@ import (
"github.com/88250/lute"
"github.com/88250/lute/html"
"github.com/gin-gonic/gin"
"github.com/siyuan-note/filelock"
"github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/conf"
"github.com/siyuan-note/siyuan/kernel/model"
@ -171,8 +172,13 @@ func getEmojiConf(c *gin.Context) {
}
if !util.IsValidUploadFileName(html.UnescapeString(name)) {
emojiFullName := filepath.Join(customConfDir, name)
fullPathFilteredName := filepath.Join(customConfDir, util.FilterUploadFileName(name))
// XSS through emoji name https://github.com/siyuan-note/siyuan/issues/15034
logging.LogWarnf("invalid custom emoji name [%s]", name)
logging.LogWarnf("renaming invalid custom emoji file [%s] to [%s]", name, fullPathFilteredName)
if removeErr := filelock.Rename(emojiFullName, fullPathFilteredName); nil != removeErr {
logging.LogErrorf("renaming invalid custom emoji file to [%s] failed: %s", fullPathFilteredName, removeErr)
}
}
if customEmoji.IsDir() {
@ -194,9 +200,13 @@ func getEmojiConf(c *gin.Context) {
}
if !util.IsValidUploadFileName(html.UnescapeString(name)) {
emojiFullName := filepath.Join(customConfDir, name)
fullPathFilteredName := filepath.Join(customConfDir, util.FilterUploadFileName(name))
// XSS through emoji name https://github.com/siyuan-note/siyuan/issues/15034
logging.LogWarnf("invalid custom emoji name [%s]", name)
continue
logging.LogWarnf("renaming invalid custom emoji file [%s] to [%s]", name, fullPathFilteredName)
if removeErr := filelock.Rename(emojiFullName, fullPathFilteredName); nil != removeErr {
logging.LogErrorf("renaming invalid custom emoji file to [%s] failed: %s", fullPathFilteredName, removeErr)
}
}
addCustomEmoji(customEmoji.Name()+"/"+name, &items)

View file

@ -45,7 +45,7 @@ import (
)
func (tx *Transaction) doSetAttrViewBlockView(operation *Operation) (ret *TxErr) {
err := SetDatabaseBlockView(operation.BlockID, operation.ID, operation.AvID)
err := SetDatabaseBlockView(operation.BlockID, operation.AvID, operation.ID)
if err != nil {
return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
}
@ -53,25 +53,25 @@ func (tx *Transaction) doSetAttrViewBlockView(operation *Operation) (ret *TxErr)
}
func (tx *Transaction) doChangeAttrViewLayout(operation *Operation) (ret *TxErr) {
err := changeAttrViewLayout(operation)
err := ChangeAttrViewLayout(operation.BlockID, operation.AvID, operation.Layout)
if err != nil {
return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
}
return
}
func changeAttrViewLayout(operation *Operation) (err error) {
attrView, err := av.ParseAttributeView(operation.AvID)
func ChangeAttrViewLayout(blockID, avID string, layout av.LayoutType) (err error) {
attrView, err := av.ParseAttributeView(avID)
if err != nil {
return
}
view, err := getAttrViewViewByBlockID(attrView, operation.BlockID)
view, err := getAttrViewViewByBlockID(attrView, blockID)
if err != nil {
return
}
newLayout := operation.Layout
newLayout := layout
if newLayout == view.LayoutType {
return
}

View file

@ -22,7 +22,6 @@ import (
"encoding/json"
"errors"
"fmt"
util2 "github.com/88250/lute/util"
"image"
"image/jpeg"
"image/png"
@ -44,6 +43,7 @@ import (
"github.com/88250/lute/html/atom"
"github.com/88250/lute/parse"
"github.com/88250/lute/render"
util2 "github.com/88250/lute/util"
"github.com/siyuan-note/filelock"
"github.com/siyuan-note/logging"
"github.com/siyuan-note/riff"
@ -557,6 +557,19 @@ func ImportSY(zipPath, boxID, toPath string) (err error) {
}
// 将包含的自定义表情统一移动到 data/emojis/ 下
unzipRootEmojisPath := filepath.Join(unzipRootPath, "emojis")
filelock.Walk(unzipRootEmojisPath, func(path string, d fs.DirEntry, err error) error {
if !util.IsValidUploadFileName(d.Name()) {
emojiFullName := filepath.Join(unzipRootEmojisPath, d.Name())
fullPathFilteredName := filepath.Join(unzipRootEmojisPath, util.FilterUploadFileName(d.Name()))
// XSS through emoji name https://github.com/siyuan-note/siyuan/issues/15034
logging.LogWarnf("renaming invalid custom emoji file [%s] to [%s]", d.Name(), fullPathFilteredName)
if removeErr := filelock.Rename(emojiFullName, fullPathFilteredName); nil != removeErr {
logging.LogErrorf("renaming invalid custom emoji file to [%s] failed: %s", fullPathFilteredName, removeErr)
}
}
return nil
})
var emojiDirs []string
filelock.Walk(unzipRootPath, func(path string, d fs.DirEntry, err error) error {
if strings.Contains(path, "emojis") && d.IsDir() {
@ -675,6 +688,19 @@ func ImportData(zipPath string) (err error) {
}
tmpDataPath := filepath.Join(unzipPath, dirs[0].Name())
tmpDataEmojisPath := filepath.Join(tmpDataPath, "emojis")
filelock.Walk(tmpDataEmojisPath, func(path string, d fs.DirEntry, err error) error {
if !util.IsValidUploadFileName(d.Name()) {
emojiFullName := filepath.Join(tmpDataEmojisPath, d.Name())
fullPathFilteredName := filepath.Join(tmpDataEmojisPath, util.FilterUploadFileName(d.Name()))
// XSS through emoji name https://github.com/siyuan-note/siyuan/issues/15034
logging.LogWarnf("renaming invalid custom emoji file [%s] to [%s]", d.Name(), fullPathFilteredName)
if removeErr := filelock.Rename(emojiFullName, fullPathFilteredName); nil != removeErr {
logging.LogErrorf("renaming invalid custom emoji file to [%s] failed: %s", fullPathFilteredName, removeErr)
}
}
return nil
})
if err = filelock.Copy(tmpDataPath, util.DataDir); err != nil {
logging.LogErrorf("copy data dir from [%s] to [%s] failed: %s", tmpDataPath, util.DataDir, err)
err = errors.New("copy data failed")

View file

@ -207,6 +207,7 @@ func FilterUploadFileName(name string) string {
ret = strings.ReplaceAll(ret, "#", "")
ret = strings.ReplaceAll(ret, "%", "")
ret = strings.ReplaceAll(ret, "$", "")
ret = strings.ReplaceAll(ret, ";", "")
ret = TruncateLenFileName(ret)
return ret
}