feat: implement authentication checks for plugin management and cluster operations

This commit is contained in:
tt
2025-03-19 15:27:57 +08:00
parent 4b2bddd44f
commit d35c05c7f6
7 changed files with 62 additions and 3 deletions

View File

@@ -68,6 +68,7 @@ conversation: # 最近会话配置
# # 认证配置
# auth:
# on: true # 是否开启认证
# kind: 'jwt' # 认证方式 jwt: jwt认证 none: 无需认证
# # 用户配置
# #用户名:密码:资源:权限 *表示通配符 资源格式也可以是[资源ID:权限]

View File

@@ -1134,6 +1134,9 @@ func (o *Options) configureAuth() {
})
o.Auth.Users = usersCfgs
if len(usersCfgs) > 0 {
o.Auth.On = true
}
node, err := snowflake.NewNode(int64(o.Cluster.NodeId))
if err != nil {

View File

@@ -2,6 +2,7 @@ package plugin
import (
"context"
"errors"
"fmt"
"io"
"net/http"
@@ -14,6 +15,8 @@ import (
"github.com/WuKongIM/WuKongIM/internal/service"
"github.com/WuKongIM/WuKongIM/internal/types"
"github.com/WuKongIM/WuKongIM/internal/types/pluginproto"
"github.com/WuKongIM/WuKongIM/pkg/auth"
"github.com/WuKongIM/WuKongIM/pkg/auth/resource"
"github.com/WuKongIM/WuKongIM/pkg/network"
"github.com/WuKongIM/WuKongIM/pkg/wkdb"
"github.com/WuKongIM/WuKongIM/pkg/wkhttp"
@@ -188,6 +191,12 @@ func (s *Server) handlePluginRoute(c *wkhttp.Context) {
}
func (s *Server) handleUpdatePluginConfig(c *wkhttp.Context) {
if !options.G.Auth.HasPermissionWithContext(c, resource.Plugin.ConfigUpdate, auth.ActionWrite) {
c.ResponseErrorWithStatus(http.StatusForbidden, errors.New("没有权限"))
return
}
pluginNo := c.Param("plugin")
var req struct {
@@ -263,6 +272,12 @@ func (s *Server) handleUpdatePluginConfig(c *wkhttp.Context) {
}
func (s *Server) handlePluginBind(c *wkhttp.Context) {
if !options.G.Auth.HasPermissionWithContext(c, resource.PluginUser.Add, auth.ActionWrite) {
c.ResponseErrorWithStatus(http.StatusForbidden, errors.New("没有权限"))
return
}
var req struct {
PluginNo string `json:"plugin_no"`
Uid string `json:"uid"`
@@ -310,6 +325,12 @@ func (s *Server) handlePluginBind(c *wkhttp.Context) {
}
func (s *Server) handlePluginUnbind(c *wkhttp.Context) {
if !options.G.Auth.HasPermissionWithContext(c, resource.PluginUser.Delete, auth.ActionWrite) {
c.ResponseErrorWithStatus(http.StatusForbidden, errors.New("没有权限"))
return
}
var req struct {
PluginNo string `json:"plugin_no"`
Uid string `json:"uid"`
@@ -461,6 +482,11 @@ func (s *Server) searchPluginUsers(req wkdb.SearchPluginUserReq) ([]*pluginUserR
}
func (s *Server) handleUninstall(c *wkhttp.Context) {
if !options.G.Auth.HasPermissionWithContext(c, resource.Plugin.Uninstall, auth.ActionWrite) {
c.ResponseErrorWithStatus(http.StatusForbidden, errors.New("没有权限"))
return
}
var req struct {
PluginNo string `json:"plugin_no"` // 插件编号
NodeId uint64 `json:"node_id"` // 插件所在节点

View File

@@ -14,6 +14,18 @@ var ClusterChannel = channel{
Stop: "clusterchannelStop", // 停止频道
}
// 插件资源
var Plugin = plugin{
Uninstall: "pluginUninstall", // 卸载插件
ConfigUpdate: "pluginConfigUpdate", // 更新插件配置
}
// 插件用户资源
var PluginUser = pluginUser{
Add: "pluginUserAdd", // 添加插件用户
Delete: "pluginUserDelete", // 删除插件用户
}
type slot struct {
Migrate Id
}
@@ -24,4 +36,14 @@ type channel struct {
Stop Id
}
type plugin struct {
Uninstall Id
ConfigUpdate Id
}
type pluginUser struct {
Add Id
Delete Id
}
var All Id = "*"

View File

@@ -165,7 +165,7 @@ func (s *Server) channelClusterConfig(c *wkhttp.Context) {
func (s *Server) channelStart(c *wkhttp.Context) {
if !s.opts.Auth.HasPermissionWithContext(c, resource.ClusterChannel.Start, auth.ActionWrite) {
c.ResponseStatus(http.StatusUnauthorized)
c.ResponseErrorWithStatus(http.StatusForbidden, errors.New("没有权限"))
return
}
@@ -202,7 +202,7 @@ func (s *Server) channelStart(c *wkhttp.Context) {
func (s *Server) channelStop(c *wkhttp.Context) {
if !s.opts.Auth.HasPermissionWithContext(c, resource.ClusterChannel.Stop, auth.ActionWrite) {
c.ResponseStatus(http.StatusUnauthorized)
c.ResponseErrorWithStatus(http.StatusForbidden, errors.New("没有权限"))
return
}

View File

@@ -144,7 +144,7 @@ func (s *Server) slotMigrate(c *wkhttp.Context) {
}
if !s.opts.Auth.HasPermissionWithContext(c, resource.Slot.Migrate, auth.ActionWrite) {
c.ResponseStatus(http.StatusUnauthorized)
c.ResponseErrorWithStatus(http.StatusForbidden, errors.New("没有权限"))
return
}

View File

@@ -83,6 +83,13 @@ func (c *Context) ResponseError(err error) {
})
}
func (c *Context) ResponseErrorWithStatus(status int, err error) {
c.JSON(http.StatusBadRequest, gin.H{
"msg": err.Error(),
"status": status,
})
}
// ResponseOK 返回正确
func (c *Context) ResponseOK() {
c.JSON(http.StatusOK, gin.H{