mirror of
https://github.com/siyuan-note/siyuan.git
synced 2026-03-07 13:20:16 +01:00
♻️ Bazaar adds parameter validation (#17132)
This commit is contained in:
parent
d03ebdec82
commit
17d49b481f
2 changed files with 162 additions and 73 deletions
|
|
@ -25,6 +25,14 @@ import (
|
|||
"github.com/siyuan-note/siyuan/kernel/util"
|
||||
)
|
||||
|
||||
var validPackageTypes = map[string]bool{
|
||||
"plugins": true,
|
||||
"themes": true,
|
||||
"icons": true,
|
||||
"templates": true,
|
||||
"widgets": true,
|
||||
}
|
||||
|
||||
func batchUpdatePackage(c *gin.Context) {
|
||||
ret := gulu.Ret.NewResult()
|
||||
defer c.JSON(http.StatusOK, ret)
|
||||
|
|
@ -34,7 +42,10 @@ func batchUpdatePackage(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
frontend := arg["frontend"].(string)
|
||||
var frontend string
|
||||
if !util.ParseJsonArgs(arg, ret, util.BindJsonArg("frontend", true, &frontend)) {
|
||||
return
|
||||
}
|
||||
model.BatchUpdateBazaarPackages(frontend)
|
||||
}
|
||||
|
||||
|
|
@ -47,7 +58,10 @@ func getUpdatedPackage(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
frontend := arg["frontend"].(string)
|
||||
var frontend string
|
||||
if !util.ParseJsonArgs(arg, ret, util.BindJsonArg("frontend", true, &frontend)) {
|
||||
return
|
||||
}
|
||||
plugins, widgets, icons, themes, templates := model.UpdatedPackages(frontend)
|
||||
ret.Data = map[string]interface{}{
|
||||
"plugins": plugins,
|
||||
|
|
@ -67,11 +81,21 @@ func getBazaarPackageREADME(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
repoURL := arg["repoURL"].(string)
|
||||
repoHash := arg["repoHash"].(string)
|
||||
packageType := arg["packageType"].(string)
|
||||
var repoURL, repoHash, pkgType string
|
||||
if !util.ParseJsonArgs(arg, ret,
|
||||
util.BindJsonArg("repoURL", true, &repoURL),
|
||||
util.BindJsonArg("repoHash", true, &repoHash),
|
||||
util.BindJsonArg("packageType", true, &pkgType),
|
||||
) {
|
||||
return
|
||||
}
|
||||
if !validPackageTypes[pkgType] {
|
||||
ret.Code = -1
|
||||
ret.Msg = "Invalid package type"
|
||||
return
|
||||
}
|
||||
ret.Data = map[string]interface{}{
|
||||
"html": model.GetPackageREADME(repoURL, repoHash, packageType),
|
||||
"html": model.GetPackageREADME(repoURL, repoHash, pkgType),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -84,10 +108,12 @@ func getBazaarPlugin(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
frontend := arg["frontend"].(string)
|
||||
var keyword string
|
||||
if keywordArg := arg["keyword"]; nil != keywordArg {
|
||||
keyword = keywordArg.(string)
|
||||
var frontend, keyword string
|
||||
if !util.ParseJsonArgs(arg, ret,
|
||||
util.BindJsonArg("frontend", true, &frontend),
|
||||
util.BindJsonArg("keyword", false, &keyword),
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
ret.Data = map[string]interface{}{
|
||||
|
|
@ -104,10 +130,12 @@ func getInstalledPlugin(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
frontend := arg["frontend"].(string)
|
||||
var keyword string
|
||||
if keywordArg := arg["keyword"]; nil != keywordArg {
|
||||
keyword = keywordArg.(string)
|
||||
var frontend, keyword string
|
||||
if !util.ParseJsonArgs(arg, ret,
|
||||
util.BindJsonArg("frontend", true, &frontend),
|
||||
util.BindJsonArg("keyword", false, &keyword),
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
ret.Data = map[string]interface{}{
|
||||
|
|
@ -124,14 +152,16 @@ func installBazaarPlugin(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
var keyword string
|
||||
if keywordArg := arg["keyword"]; nil != keywordArg {
|
||||
keyword = keywordArg.(string)
|
||||
var frontend, keyword, repoURL, repoHash, packageName string
|
||||
if !util.ParseJsonArgs(arg, ret,
|
||||
util.BindJsonArg("frontend", true, &frontend),
|
||||
util.BindJsonArg("keyword", false, &keyword),
|
||||
util.BindJsonArg("repoURL", true, &repoURL),
|
||||
util.BindJsonArg("repoHash", true, &repoHash),
|
||||
util.BindJsonArg("packageName", true, &packageName),
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
repoURL := arg["repoURL"].(string)
|
||||
repoHash := arg["repoHash"].(string)
|
||||
packageName := arg["packageName"].(string)
|
||||
err := model.InstallBazaarPlugin(repoURL, repoHash, packageName)
|
||||
if err != nil {
|
||||
ret.Code = 1
|
||||
|
|
@ -139,8 +169,6 @@ func installBazaarPlugin(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
frontend := arg["frontend"].(string)
|
||||
|
||||
util.PushMsg(model.Conf.Language(69), 3000)
|
||||
ret.Data = map[string]interface{}{
|
||||
"packages": model.BazaarPlugins(frontend, keyword),
|
||||
|
|
@ -156,13 +184,14 @@ func uninstallBazaarPlugin(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
var keyword string
|
||||
if keywordArg := arg["keyword"]; nil != keywordArg {
|
||||
keyword = keywordArg.(string)
|
||||
var frontend, keyword, packageName string
|
||||
if !util.ParseJsonArgs(arg, ret,
|
||||
util.BindJsonArg("frontend", true, &frontend),
|
||||
util.BindJsonArg("keyword", false, &keyword),
|
||||
util.BindJsonArg("packageName", true, &packageName),
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
frontend := arg["frontend"].(string)
|
||||
packageName := arg["packageName"].(string)
|
||||
err := model.UninstallBazaarPlugin(packageName, frontend)
|
||||
if err != nil {
|
||||
ret.Code = -1
|
||||
|
|
@ -185,8 +214,8 @@ func getBazaarWidget(c *gin.Context) {
|
|||
}
|
||||
|
||||
var keyword string
|
||||
if keywordArg := arg["keyword"]; nil != keywordArg {
|
||||
keyword = keywordArg.(string)
|
||||
if !util.ParseJsonArgs(arg, ret, util.BindJsonArg("keyword", false, &keyword)) {
|
||||
return
|
||||
}
|
||||
|
||||
ret.Data = map[string]interface{}{
|
||||
|
|
@ -204,8 +233,8 @@ func getInstalledWidget(c *gin.Context) {
|
|||
}
|
||||
|
||||
var keyword string
|
||||
if keywordArg := arg["keyword"]; nil != keywordArg {
|
||||
keyword = keywordArg.(string)
|
||||
if !util.ParseJsonArgs(arg, ret, util.BindJsonArg("keyword", false, &keyword)) {
|
||||
return
|
||||
}
|
||||
|
||||
ret.Data = map[string]interface{}{
|
||||
|
|
@ -222,14 +251,15 @@ func installBazaarWidget(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
var keyword string
|
||||
if keywordArg := arg["keyword"]; nil != keywordArg {
|
||||
keyword = keywordArg.(string)
|
||||
var keyword, repoURL, repoHash, packageName string
|
||||
if !util.ParseJsonArgs(arg, ret,
|
||||
util.BindJsonArg("keyword", false, &keyword),
|
||||
util.BindJsonArg("repoURL", true, &repoURL),
|
||||
util.BindJsonArg("repoHash", true, &repoHash),
|
||||
util.BindJsonArg("packageName", true, &packageName),
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
repoURL := arg["repoURL"].(string)
|
||||
repoHash := arg["repoHash"].(string)
|
||||
packageName := arg["packageName"].(string)
|
||||
err := model.InstallBazaarWidget(repoURL, repoHash, packageName)
|
||||
if err != nil {
|
||||
ret.Code = 1
|
||||
|
|
@ -252,12 +282,13 @@ func uninstallBazaarWidget(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
var keyword string
|
||||
if keywordArg := arg["keyword"]; nil != keywordArg {
|
||||
keyword = keywordArg.(string)
|
||||
var keyword, packageName string
|
||||
if !util.ParseJsonArgs(arg, ret,
|
||||
util.BindJsonArg("keyword", false, &keyword),
|
||||
util.BindJsonArg("packageName", true, &packageName),
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
packageName := arg["packageName"].(string)
|
||||
err := model.UninstallBazaarWidget(packageName)
|
||||
if err != nil {
|
||||
ret.Code = -1
|
||||
|
|
@ -280,8 +311,8 @@ func getBazaarIcon(c *gin.Context) {
|
|||
}
|
||||
|
||||
var keyword string
|
||||
if keywordArg := arg["keyword"]; nil != keywordArg {
|
||||
keyword = keywordArg.(string)
|
||||
if !util.ParseJsonArgs(arg, ret, util.BindJsonArg("keyword", false, &keyword)) {
|
||||
return
|
||||
}
|
||||
|
||||
ret.Data = map[string]interface{}{
|
||||
|
|
@ -299,8 +330,8 @@ func getInstalledIcon(c *gin.Context) {
|
|||
}
|
||||
|
||||
var keyword string
|
||||
if keywordArg := arg["keyword"]; nil != keywordArg {
|
||||
keyword = keywordArg.(string)
|
||||
if !util.ParseJsonArgs(arg, ret, util.BindJsonArg("keyword", false, &keyword)) {
|
||||
return
|
||||
}
|
||||
|
||||
ret.Data = map[string]interface{}{
|
||||
|
|
@ -317,14 +348,15 @@ func installBazaarIcon(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
var keyword string
|
||||
if keywordArg := arg["keyword"]; nil != keywordArg {
|
||||
keyword = keywordArg.(string)
|
||||
var keyword, repoURL, repoHash, packageName string
|
||||
if !util.ParseJsonArgs(arg, ret,
|
||||
util.BindJsonArg("keyword", false, &keyword),
|
||||
util.BindJsonArg("repoURL", true, &repoURL),
|
||||
util.BindJsonArg("repoHash", true, &repoHash),
|
||||
util.BindJsonArg("packageName", true, &packageName),
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
repoURL := arg["repoURL"].(string)
|
||||
repoHash := arg["repoHash"].(string)
|
||||
packageName := arg["packageName"].(string)
|
||||
err := model.InstallBazaarIcon(repoURL, repoHash, packageName)
|
||||
if err != nil {
|
||||
ret.Code = 1
|
||||
|
|
@ -348,12 +380,13 @@ func uninstallBazaarIcon(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
var keyword string
|
||||
if keywordArg := arg["keyword"]; nil != keywordArg {
|
||||
keyword = keywordArg.(string)
|
||||
var keyword, packageName string
|
||||
if !util.ParseJsonArgs(arg, ret,
|
||||
util.BindJsonArg("keyword", false, &keyword),
|
||||
util.BindJsonArg("packageName", true, &packageName),
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
packageName := arg["packageName"].(string)
|
||||
err := model.UninstallBazaarIcon(packageName)
|
||||
if err != nil {
|
||||
ret.Code = -1
|
||||
|
|
@ -377,8 +410,8 @@ func getBazaarTemplate(c *gin.Context) {
|
|||
}
|
||||
|
||||
var keyword string
|
||||
if keywordArg := arg["keyword"]; nil != keywordArg {
|
||||
keyword = keywordArg.(string)
|
||||
if !util.ParseJsonArgs(arg, ret, util.BindJsonArg("keyword", false, &keyword)) {
|
||||
return
|
||||
}
|
||||
|
||||
ret.Data = map[string]interface{}{
|
||||
|
|
@ -396,8 +429,8 @@ func getInstalledTemplate(c *gin.Context) {
|
|||
}
|
||||
|
||||
var keyword string
|
||||
if keywordArg := arg["keyword"]; nil != keywordArg {
|
||||
keyword = keywordArg.(string)
|
||||
if !util.ParseJsonArgs(arg, ret, util.BindJsonArg("keyword", false, &keyword)) {
|
||||
return
|
||||
}
|
||||
|
||||
ret.Data = map[string]interface{}{
|
||||
|
|
@ -510,15 +543,17 @@ func installBazaarTheme(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
var keyword string
|
||||
if keywordArg := arg["keyword"]; nil != keywordArg {
|
||||
keyword = keywordArg.(string)
|
||||
var keyword, repoURL, repoHash, packageName string
|
||||
var mode float64
|
||||
if !util.ParseJsonArgs(arg, ret,
|
||||
util.BindJsonArg("keyword", false, &keyword),
|
||||
util.BindJsonArg("repoURL", true, &repoURL),
|
||||
util.BindJsonArg("repoHash", true, &repoHash),
|
||||
util.BindJsonArg("packageName", true, &packageName),
|
||||
util.BindJsonArg("mode", true, &mode),
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
repoURL := arg["repoURL"].(string)
|
||||
repoHash := arg["repoHash"].(string)
|
||||
packageName := arg["packageName"].(string)
|
||||
mode := arg["mode"].(float64)
|
||||
update := false
|
||||
if nil != arg["update"] {
|
||||
update = arg["update"].(bool)
|
||||
|
|
@ -530,6 +565,7 @@ func installBazaarTheme(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
// TODO 安装新主题之后,不应该始终取消外观模式“跟随系统” https://github.com/siyuan-note/siyuan/issues/16990
|
||||
// 安装集市主题后不跟随系统切换外观模式
|
||||
model.Conf.Appearance.ModeOS = false
|
||||
model.Conf.Save()
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
|
@ -213,6 +214,58 @@ func JsonArg(c *gin.Context, result *gulu.Result) (arg map[string]interface{}, o
|
|||
return
|
||||
}
|
||||
|
||||
// ParseJsonArg 使用泛型从 JSON 参数中提取指定键的值。
|
||||
// - 如果 required 为 true 但参数缺失,则会在 ret.Msg 中写入 “[key] is required”
|
||||
// - 如果参数存在但类型不匹配,则会在 ret.Msg 中写入 “[key] should be [T]”
|
||||
// - 返回值 ok 为 false 时,表示提取失败或类型不匹配
|
||||
func ParseJsonArg[T any](key string, required bool, arg map[string]interface{}, ret *gulu.Result) (value T, ok bool) {
|
||||
raw, exists := arg[key]
|
||||
if !exists || raw == nil {
|
||||
if required {
|
||||
ret.Code = -1
|
||||
ret.Msg = key + " is required"
|
||||
} else {
|
||||
ok = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
value, ok = raw.(T)
|
||||
if !ok {
|
||||
var zero T
|
||||
ret.Code = -1
|
||||
ret.Msg = fmt.Sprintf("%s should be %T", key, zero)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// JsonArgParseFunc 为单次提取函数,用于 ParseJsonArgs 批量提取。
|
||||
type JsonArgParseFunc func(arg map[string]interface{}, ret *gulu.Result) bool
|
||||
|
||||
// BindJsonArg 创建一个提取函数:从 arg 取 key 并写入 dest,供 ParseJsonArgs 使用。
|
||||
func BindJsonArg[T any](key string, required bool, dest *T) JsonArgParseFunc {
|
||||
return func(arg map[string]interface{}, ret *gulu.Result) bool {
|
||||
v, ok := ParseJsonArg[T](key, required, arg, ret)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
*dest = v
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// ParseJsonArgs 按顺序执行多个提取函数。
|
||||
// - 任一失败返回 false 并在 ret 中写入错误信息
|
||||
// - 全部成功返回 true
|
||||
func ParseJsonArgs(arg map[string]interface{}, ret *gulu.Result, extractors ...JsonArgParseFunc) bool {
|
||||
for _, ext := range extractors {
|
||||
if !ext(arg, ret) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func InvalidIDPattern(idArg string, result *gulu.Result) bool {
|
||||
if ast.IsNodeIDPattern(idArg) {
|
||||
return false
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue