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

4
.gitignore vendored
View File

@@ -22,5 +22,5 @@ out
server/docs/docker-compose
server/config.yml
mayfly-go.log
server/ip2region.xdb
mayfly-go.log

View File

@@ -8,6 +8,20 @@
<el-form-item prop="key" label="配置key:" required>
<el-input :disabled="form.id != null" v-model="form.key"></el-input>
</el-form-item>
<el-form-item prop="permission" label="权限:">
<el-select
style="width: 100%"
remote
:remote-method="getAccount"
v-model="state.permissionAccount"
filterable
multiple
placeholder="请输入账号模糊搜索并选择"
>
<el-option v-for="item in state.accounts" :key="item.id" :label="`${item.username} [${item.name}]`" :value="item.username"> </el-option>
</el-select>
<!-- <el-input v-model="form.permission" placeholder="可,分割可操作用户名"></el-input> -->
</el-form-item>
<el-row style="margin-left: 30px; margin-bottom: 5px">
<el-button @click="onAddParam" size="small" type="success">新增配置项</el-button>
@@ -62,7 +76,7 @@
<script lang="ts" setup>
import { ref, toRefs, reactive, watch } from 'vue';
import { configApi } from '../api';
import { configApi, accountApi } from '../api';
const props = defineProps({
visible: {
@@ -84,6 +98,8 @@ const configForm: any = ref(null);
const state = reactive({
dvisible: false,
params: [] as any,
accounts: [] as any,
permissionAccount: [] as any,
form: {
id: null,
name: '',
@@ -91,6 +107,7 @@ const state = reactive({
params: '',
value: '',
remark: '',
permission: '',
},
btnLoading: false,
});
@@ -99,6 +116,10 @@ const { dvisible, params, form, btnLoading } = toRefs(state);
watch(props, (newValue: any) => {
state.dvisible = newValue.visible;
if (!state.dvisible) {
return;
}
if (newValue.data) {
state.form = { ...newValue.data };
if (state.form.params) {
@@ -107,9 +128,16 @@ watch(props, (newValue: any) => {
state.params = [];
}
} else {
state.form = {} as any;
state.form = { permission: 'all' } as any;
state.params = [];
}
if (state.form.permission != 'all') {
const accounts = state.form.permission.split(',');
state.permissionAccount = accounts.slice(0, accounts.length - 1);
} else {
state.permissionAccount = [];
}
});
const onAddParam = () => {
@@ -125,6 +153,15 @@ const cancel = () => {
emit('update:visible', false);
// 若父组件有取消事件,则调用
emit('cancel');
state.permissionAccount = [];
};
const getAccount = (username: any) => {
if (username) {
accountApi.list.request({ username }).then((res) => {
state.accounts = res.list;
});
}
};
const btnOk = async () => {
@@ -133,6 +170,11 @@ const btnOk = async () => {
if (state.params) {
state.form.params = JSON.stringify(state.params);
}
if (state.permissionAccount.length > 0) {
state.form.permission = state.permissionAccount.join(',') + ',';
} else {
state.form.permission = 'all';
}
await configApi.save.request(state.form);
emit('val-change', state.form);
cancel();

View File

@@ -38,6 +38,8 @@ log:
# file:
# path: ./
# name: mayfly-go.log
# ldap相关配置
ldap:
enabled: true
host: "ldap.example.com"

View File

@@ -6,6 +6,7 @@ require (
github.com/buger/jsonparser v1.1.1
github.com/gin-gonic/gin v1.9.1
github.com/go-gormigrate/gormigrate/v2 v2.1.0
github.com/go-ldap/ldap/v3 v3.4.5
github.com/go-playground/locales v0.14.1
github.com/go-playground/universal-translator v0.18.1
github.com/go-playground/validator/v10 v10.14.0
@@ -15,6 +16,7 @@ require (
github.com/lib/pq v1.10.9
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20230712084735-068dc2aee82d
github.com/mojocn/base64Captcha v1.3.5 //
github.com/pkg/errors v0.9.1
github.com/pkg/sftp v1.13.6
github.com/pquerna/otp v1.4.0
github.com/redis/go-redis/v9 v9.1.0
@@ -31,6 +33,7 @@ require (
)
require (
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/bytedance/sonic v1.9.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
@@ -38,6 +41,7 @@ require (
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
@@ -64,7 +68,7 @@ require (
golang.org/x/arch v0.3.0 // indirect
golang.org/x/image v0.0.0-20220302094943-723b81ca9867 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
google.golang.org/appengine v1.6.7 // indirect

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(),

View File

@@ -423,6 +423,7 @@ CREATE TABLE `t_sys_config` (
`params` varchar(1500) DEFAULT NULL,
`value` varchar(1500) DEFAULT NULL COMMENT '配置value',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`permission` varchar(255) DEFAULT 'all' COMMENT '操作权限',
`create_time` datetime NOT NULL,
`creator_id` bigint(20) NOT NULL,
`creator` varchar(36) NOT NULL,
@@ -438,7 +439,7 @@ CREATE TABLE `t_sys_config` (
-- Records of t_sys_config
-- ----------------------------
BEGIN;
INSERT INTO `t_sys_config` (name, `key`, params, value, remark, create_time, creator_id, creator, update_time, modifier_id, modifier) VALUES('账号登录安全设置', 'AccountLoginSecurity', '[{"name":"登录验证码","model":"useCaptcha","placeholder":"是否启用登录验证码","options":"true,false"},{"name":"双因素校验(OTP)","model":"useOtp","placeholder":"是否启用双因素(OTP)校验","options":"true,false"},{"name":"OTP签发人","model":"otpIssuer","placeholder":"otp签发人"},{"name":"允许失败次数","model":"loginFailCount","placeholder":"登录失败n次后禁止登录"},{"name":"禁止登录时间","model":"loginFailMin","placeholder":"登录失败指定次数后禁止m分钟内再次登录"}]', '{"useCaptcha":"true","useOtp":"false","loginFailCount":"5","loginFailMin":"10","otpIssuer":"mayfly-go"}', '系统账号登录相关安全设置', '2023-06-17 11:02:11', 1, 'admin', '2023-06-17 14:18:07', 1, 'admin');
INSERT INTO `t_sys_config` (name, `key`, params, value, remark, permission, create_time, creator_id, creator, update_time, modifier_id, modifier) VALUES('账号登录安全设置', 'AccountLoginSecurity', '[{"name":"登录验证码","model":"useCaptcha","placeholder":"是否启用登录验证码","options":"true,false"},{"name":"双因素校验(OTP)","model":"useOtp","placeholder":"是否启用双因素(OTP)校验","options":"true,false"},{"name":"OTP签发人","model":"otpIssuer","placeholder":"otp签发人"},{"name":"允许失败次数","model":"loginFailCount","placeholder":"登录失败n次后禁止登录"},{"name":"禁止登录时间","model":"loginFailMin","placeholder":"登录失败指定次数后禁止m分钟内再次登录"}]', '{"useCaptcha":"true","useOtp":"false","loginFailCount":"5","loginFailMin":"10","otpIssuer":"mayfly-go"}', '系统账号登录相关安全设置', 'admin,', '2023-06-17 11:02:11', 1, 'admin', '2023-06-17 14:18:07', 1, 'admin');
INSERT INTO `t_sys_config` (name, `key`, params, value, remark, create_time, creator_id, creator, update_time, modifier_id, modifier, is_deleted, delete_time) VALUES('oauth2登录配置', 'Oauth2Login', '[{"name":"是否启用","model":"enable","placeholder":"是否启用oauth2登录","options":"true,false"},{"name":"名称","model":"name","placeholder":"oauth2名称"},{"name":"Client ID","model":"clientId","placeholder":"Client ID"},{"name":"Client Secret","model":"clientSecret","placeholder":"Client Secret"},{"name":"Authorization URL","model":"authorizationURL","placeholder":"Authorization URL"},{"name":"AccessToken URL","model":"accessTokenURL","placeholder":"AccessToken URL"},{"name":"Redirect URL","model":"redirectURL","placeholder":"本系统地址"},{"name":"Scopes","model":"scopes","placeholder":"Scopes"},{"name":"Resource URL","model":"resourceURL","placeholder":"获取用户信息资源地址"},{"name":"UserIdentifier","model":"userIdentifier","placeholder":"用户唯一标识字段;格式为type:fieldPath(string:username)"},{"name":"是否自动注册","model":"autoRegister","placeholder":"","options":"true,false"}]', '', 'oauth2登录相关配置信息', '2023-07-22 13:58:51', 1, 'admin', '2023-07-22 19:34:37', 1, 'admin', 0, NULL);
INSERT INTO `t_sys_config` (name, `key`, params, value, remark, create_time, creator_id, creator, update_time, modifier_id, modifier)VALUES ('是否启用水印', 'UseWartermark', NULL, '1', '1: 启用、0: 不启用', '2022-08-25 23:36:35', 1, 'admin', '2022-08-26 10:02:52', 1, 'admin');
INSERT INTO `t_sys_config` (name, `key`, params, value, remark, create_time, creator_id, creator, update_time, modifier_id, modifier)VALUES ('数据库查询最大结果集', 'DbQueryMaxCount', '[]', '200', '允许sql查询的最大结果集数。注: 0=不限制', '2023-02-11 14:29:03', 1, 'admin', '2023-02-11 14:40:56', 1, 'admin');

View File

@@ -157,6 +157,13 @@ func (q *QueryCond) Le(column string, val any) *QueryCond {
return q
}
// And条件
func (q *QueryCond) And(column string, val any) *QueryCond {
q.columns = append(q.columns, column)
q.values = append(q.values, val)
return q
}
func (q *QueryCond) Cond(cond, column string, val any, skipBlank bool) *QueryCond {
// 零值跳过
if skipBlank && anyx.IsBlank(val) {

View File

@@ -3,10 +3,11 @@ package ldap
import (
"crypto/tls"
"fmt"
"github.com/go-ldap/ldap/v3"
"github.com/pkg/errors"
"mayfly-go/pkg/config"
"strings"
"github.com/go-ldap/ldap/v3"
"github.com/pkg/errors"
)
type UserInfo struct {