feat: 系统配置新增权限控制

This commit is contained in:
meilin.huang
2023-08-25 19:41:52 +08:00
parent 756e580469
commit 3634c902d0
17 changed files with 150 additions and 75 deletions

View File

@@ -1,11 +1,10 @@
package form
type LoginForm struct {
Username string `json:"username" binding:"required"`
Password string `binding:"required"`
Captcha string `json:"captcha"`
Cid string `json:"cid"`
LdapLogin bool `json:"ldapLogin"`
Username string `json:"username" binding:"required"`
Password string `binding:"required"`
Captcha string `json:"captcha"`
Cid string `json:"cid"`
}
type OtpVerfiy struct {

View File

@@ -3,7 +3,6 @@ package api
import (
"errors"
"fmt"
"gorm.io/gorm"
"mayfly-go/internal/auth/api/form"
msgapp "mayfly-go/internal/msg/application"
sysapp "mayfly-go/internal/sys/application"
@@ -18,6 +17,8 @@ import (
"mayfly-go/pkg/utils/cryptox"
"strconv"
"time"
"gorm.io/gorm"
)
type LdapLogin struct {
@@ -28,16 +29,18 @@ type LdapLogin struct {
// @router /auth/ldap/enabled [get]
func (a *LdapLogin) GetLdapEnabled(rc *req.Ctx) {
rc.ResData = config.Conf.Ldap.Enabled
if config.Conf.Ldap != nil {
rc.ResData = config.Conf.Ldap.Enabled
return
}
rc.ResData = false
}
// @router /auth/ldap/login [post]
func (a *LdapLogin) Login(rc *req.Ctx) {
loginForm := ginx.BindJsonAndValid(rc.GinCtx, new(form.LoginForm))
// 确认是 LDAP 登录
biz.IsTrue(loginForm.LdapLogin, "LDAP 登录参数错误")
accountLoginSecurity := a.ConfigApp.GetConfig(sysentity.ConfigKeyAccountLoginSecurity).ToAccountLoginSecurity()
// 判断是否有开启登录验证码校验
if accountLoginSecurity.UseCaptcha {

View File

@@ -10,6 +10,7 @@ import (
"mayfly-go/pkg/ginx"
"mayfly-go/pkg/model"
"mayfly-go/pkg/req"
"mayfly-go/pkg/utils/jsonx"
"regexp"
"strconv"
"strings"
@@ -71,14 +72,14 @@ func (m *Mongo) DeleteMongo(rc *req.Ctx) {
}
func (m *Mongo) Databases(rc *req.Ctx) {
cli := m.MongoApp.GetMongoCli(m.GetMongoId(rc.GinCtx))
cli := m.MongoApp.GetMongoInst(m.GetMongoId(rc.GinCtx)).Cli
res, err := cli.ListDatabases(context.TODO(), bson.D{})
biz.ErrIsNilAppendErr(err, "获取mongo所有库信息失败: %s")
rc.ResData = res
}
func (m *Mongo) Collections(rc *req.Ctx) {
cli := m.MongoApp.GetMongoCli(m.GetMongoId(rc.GinCtx))
cli := m.MongoApp.GetMongoInst(m.GetMongoId(rc.GinCtx)).Cli
db := rc.GinCtx.Query("database")
biz.NotEmpty(db, "database不能为空")
ctx := context.TODO()
@@ -90,8 +91,13 @@ func (m *Mongo) Collections(rc *req.Ctx) {
func (m *Mongo) RunCommand(rc *req.Ctx) {
commandForm := new(form.MongoRunCommand)
ginx.BindJsonAndValid(rc.GinCtx, commandForm)
cli := m.MongoApp.GetMongoCli(m.GetMongoId(rc.GinCtx))
rc.ReqParam = commandForm
inst := m.MongoApp.GetMongoInst(m.GetMongoId(rc.GinCtx))
rc.ReqParam = jsonx.ToStr(map[string]any{
"info": inst.Info.GetLogDesc(),
"req": commandForm,
})
// 顺序执行
commands := bson.D{}
@@ -106,7 +112,7 @@ func (m *Mongo) RunCommand(rc *req.Ctx) {
ctx := context.TODO()
var bm bson.M
err := cli.Database(commandForm.Database).RunCommand(
err := inst.Cli.Database(commandForm.Database).RunCommand(
ctx,
commands,
).Decode(&bm)
@@ -117,7 +123,7 @@ func (m *Mongo) RunCommand(rc *req.Ctx) {
func (m *Mongo) FindCommand(rc *req.Ctx) {
g := rc.GinCtx
cli := m.MongoApp.GetMongoCli(m.GetMongoId(g))
cli := m.MongoApp.GetMongoInst(m.GetMongoId(g)).Cli
commandForm := new(form.MongoFindCommand)
ginx.BindJsonAndValid(g, commandForm)
@@ -150,10 +156,15 @@ func (m *Mongo) FindCommand(rc *req.Ctx) {
func (m *Mongo) UpdateByIdCommand(rc *req.Ctx) {
g := rc.GinCtx
cli := m.MongoApp.GetMongoCli(m.GetMongoId(g))
commandForm := new(form.MongoUpdateByIdCommand)
ginx.BindJsonAndValid(g, commandForm)
inst := m.MongoApp.GetMongoInst(m.GetMongoId(g))
rc.ReqParam = jsonx.ToStr(map[string]any{
"info": inst.Info.GetLogDesc(),
"req": commandForm,
})
// 解析docId文档id如果为string类型则使用ObjectId解析解析失败则为普通字符串
docId := commandForm.DocId
docIdVal, ok := docId.(string)
@@ -164,19 +175,23 @@ func (m *Mongo) UpdateByIdCommand(rc *req.Ctx) {
}
}
res, err := cli.Database(commandForm.Database).Collection(commandForm.Collection).UpdateByID(context.TODO(), docId, commandForm.Update)
res, err := inst.Cli.Database(commandForm.Database).Collection(commandForm.Collection).UpdateByID(context.TODO(), docId, commandForm.Update)
biz.ErrIsNilAppendErr(err, "命令执行失败: %s")
rc.ReqParam = commandForm
rc.ResData = res
}
func (m *Mongo) DeleteByIdCommand(rc *req.Ctx) {
g := rc.GinCtx
cli := m.MongoApp.GetMongoCli(m.GetMongoId(g))
commandForm := new(form.MongoUpdateByIdCommand)
ginx.BindJsonAndValid(g, commandForm)
inst := m.MongoApp.GetMongoInst(m.GetMongoId(g))
rc.ReqParam = jsonx.ToStr(map[string]any{
"info": inst.Info.GetLogDesc(),
"req": commandForm,
})
// 解析docId文档id如果为string类型则使用ObjectId解析解析失败则为普通字符串
docId := commandForm.DocId
docIdVal, ok := docId.(string)
@@ -187,23 +202,24 @@ func (m *Mongo) DeleteByIdCommand(rc *req.Ctx) {
}
}
res, err := cli.Database(commandForm.Database).Collection(commandForm.Collection).DeleteOne(context.TODO(), bson.D{{"_id", docId}})
res, err := inst.Cli.Database(commandForm.Database).Collection(commandForm.Collection).DeleteOne(context.TODO(), bson.D{{Key: "_id", Value: docId}})
biz.ErrIsNilAppendErr(err, "命令执行失败: %s")
rc.ReqParam = commandForm
rc.ResData = res
}
func (m *Mongo) InsertOneCommand(rc *req.Ctx) {
g := rc.GinCtx
cli := m.MongoApp.GetMongoCli(m.GetMongoId(g))
commandForm := new(form.MongoInsertCommand)
ginx.BindJsonAndValid(g, commandForm)
res, err := cli.Database(commandForm.Database).Collection(commandForm.Collection).InsertOne(context.TODO(), commandForm.Doc)
biz.ErrIsNilAppendErr(err, "命令执行失败: %s")
inst := m.MongoApp.GetMongoInst(m.GetMongoId(g))
rc.ReqParam = jsonx.ToStr(map[string]any{
"info": inst.Info.GetLogDesc(),
"req": commandForm,
})
rc.ReqParam = commandForm
res, err := inst.Cli.Database(commandForm.Database).Collection(commandForm.Collection).InsertOne(context.TODO(), commandForm.Doc)
biz.ErrIsNilAppendErr(err, "命令执行失败: %s")
rc.ResData = res
}

View File

@@ -39,9 +39,9 @@ type Mongo interface {
// 删除数据库信息
Delete(id uint64)
// 获取mongo连接client
// 获取mongo连接实例
// @param id mongo id
GetMongoCli(id uint64) *mongo.Client
GetMongoInst(id uint64) *MongoInstance
}
func newMongoAppImpl(mongoRepo repository.Mongo) Mongo {
@@ -88,14 +88,14 @@ func (d *mongoAppImpl) Save(m *entity.Mongo) {
}
}
func (d *mongoAppImpl) GetMongoCli(id uint64) *mongo.Client {
func (d *mongoAppImpl) GetMongoInst(id uint64) *MongoInstance {
mongoInstance, err := GetMongoInstance(id, func(u uint64) *entity.Mongo {
mongo := d.GetById(u)
biz.NotNil(mongo, "mongo信息不存在")
return mongo
})
biz.ErrIsNilAppendErr(err, "连接mongo失败: %s")
return mongoInstance.Cli
return mongoInstance
}
// -----------------------------------------------------------
@@ -173,7 +173,7 @@ func connect(me *entity.Mongo) (*MongoInstance, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
mongoInstance := &MongoInstance{Id: me.Id, Info: toMongiInfo(me)}
mongoInstance := &MongoInstance{Id: me.Id, Info: toMongoInfo(me)}
mongoOptions := options.Client().ApplyURI(me.Uri).
SetMaxPoolSize(1)
@@ -200,7 +200,7 @@ func connect(me *entity.Mongo) (*MongoInstance, error) {
return mongoInstance, err
}
func toMongiInfo(me *entity.Mongo) *MongoInfo {
func toMongoInfo(me *entity.Mongo) *MongoInfo {
mi := new(MongoInfo)
structx.Copy(mi, me)
return mi

View File

@@ -16,28 +16,22 @@ type Config struct {
func (c *Config) Configs(rc *req.Ctx) {
g := rc.GinCtx
condition := &entity.Config{Key: g.Query("key")}
condition.Permission = rc.LoginAccount.Username
rc.ResData = c.ConfigApp.GetPageList(condition, ginx.GetPageParam(g), new([]entity.Config))
}
func (c *Config) GetConfigValueByKey(rc *req.Ctx) {
key := rc.GinCtx.Query("key")
biz.NotEmpty(key, "key不能为空")
rc.ResData = c.ConfigApp.GetConfig(key).Value
}
func (c *Config) GetConfigValueByKeyWithNoToken(keys []string) func(rc *req.Ctx) {
keyMap := make(map[string]struct{})
for _, key := range keys {
keyMap[key] = struct{}{}
}
return func(rc *req.Ctx) {
key := rc.GinCtx.Query("key")
biz.NotEmpty(key, "key不能为空")
if _, ok := keyMap[key]; !ok {
biz.ErrIsNil(nil, "无权限获取该配置信息")
}
rc.ResData = c.ConfigApp.GetConfig(key).Value
config := c.ConfigApp.GetConfig(key)
// 判断是否为公开配置
if config.Permission != "all" {
rc.ResData = ""
return
}
rc.ResData = config.Value
}
func (c *Config) SaveConfig(rc *req.Ctx) {

View File

@@ -1,10 +1,11 @@
package form
type ConfigForm struct {
Id int `json:"id"`
Name string `json:"name"`
Key string `json:"key"`
Params string `json:"params"`
Value string `json:"value"`
Remark string `json:"remark"`
Id int `json:"id"`
Name string `json:"name"`
Key string `json:"key"`
Params string `json:"params"`
Value string `json:"value"`
Remark string `json:"remark"`
Permission string `json:"permission"`
}

View File

@@ -4,10 +4,12 @@ import (
"encoding/json"
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/internal/sys/domain/repository"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/cache"
"mayfly-go/pkg/global"
"mayfly-go/pkg/model"
"mayfly-go/pkg/utils/jsonx"
"strings"
)
const SysConfigKeyPrefix = "mayfly:sys:config:"
@@ -39,6 +41,11 @@ func (a *configAppImpl) Save(config *entity.Config) {
if config.Id == 0 {
a.configRepo.Insert(config)
} else {
oldConfig := a.GetConfig(config.Key)
if oldConfig.Permission != "all" {
biz.IsTrue(strings.Contains(oldConfig.Permission, config.Modifier), "您无权修改该配置")
}
a.configRepo.Update(config)
}
cache.Del(SysConfigKeyPrefix + config.Key)
@@ -53,7 +60,7 @@ func (a *configAppImpl) GetConfig(key string) *entity.Config {
return config
}
if err := a.configRepo.GetConfig(config, "Id", "Key", "Value"); err != nil {
if err := a.configRepo.GetConfig(config, "Id", "Key", "Value", "Permission"); err != nil {
global.Log.Warnf("不存在key = [%s] 的系统配置", key)
} else {
cache.SetStr(SysConfigKeyPrefix+key, jsonx.ToStr(config), -1)

View File

@@ -16,11 +16,12 @@ const (
type Config struct {
model.Model
Name string `json:"name"` // 配置名
Key string `json:"key"` // 配置key
Params string `json:"params" gorm:"column:params;type:varchar(1500)"`
Value string `json:"value" gorm:"column:value;type:varchar(1500)"`
Remark string `json:"remark"`
Name string `json:"name"` // 配置名
Key string `json:"key"` // 配置key
Params string `json:"params" gorm:"column:params;type:varchar(1500)"`
Value string `json:"value" gorm:"column:value;type:varchar(1500)"`
Remark string `json:"remark"`
Permission string `json:"permission"` // 可操作该配置的权限
}
func (a *Config) TableName() string {

View File

@@ -15,7 +15,10 @@ func newConfigRepo() repository.Config {
}
func (m *configRepoImpl) GetPageList(condition *entity.Config, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
qd := gormx.NewQuery(condition).WithCondModel(condition).WithOrderBy(orderBy...)
qd := gormx.NewQuery(condition).
Eq("key", condition.Key).
And("permission = 'all' OR permission LIKE ?", "%"+condition.Permission+",%").
WithOrderBy(orderBy...)
return gormx.PageQuery(qd, pageParam, toEntity)
}

View File

@@ -3,7 +3,6 @@ package router
import (
"mayfly-go/internal/sys/api"
"mayfly-go/internal/sys/application"
"mayfly-go/internal/sys/domain/entity"
"mayfly-go/pkg/req"
"github.com/gin-gonic/gin"
@@ -19,12 +18,7 @@ func InitSysConfigRouter(router *gin.RouterGroup) {
req.NewGet("", r.Configs).RequiredPermission(baseP),
// 获取指定配置key对应的值
req.NewGet("/value", r.GetConfigValueByKeyWithNoToken([]string{
entity.ConfigKeyAccountLoginSecurity,
entity.ConfigKeyDbQueryMaxCount,
entity.ConfigKeyDbSaveQuerySQL,
entity.ConfigUseWartermark,
})).DontNeedToken(),
req.NewGet("/value", r.GetConfigValueByKey).DontNeedToken(),
req.NewGet("/oauth2-login", r.Oauth2Config).DontNeedToken(),