mirror of
https://github.com/siyuan-note/siyuan.git
synced 2026-01-06 16:58:49 +01:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
06f65e178e
7 changed files with 104 additions and 13 deletions
|
|
@ -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)。
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue