mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-02 15:30:25 +08:00
feat: 系统配置新增权限控制
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -22,5 +22,5 @@ out
|
|||||||
|
|
||||||
server/docs/docker-compose
|
server/docs/docker-compose
|
||||||
server/config.yml
|
server/config.yml
|
||||||
|
server/ip2region.xdb
|
||||||
mayfly-go.log
|
mayfly-go.log
|
||||||
@@ -8,6 +8,20 @@
|
|||||||
<el-form-item prop="key" label="配置key:" required>
|
<el-form-item prop="key" label="配置key:" required>
|
||||||
<el-input :disabled="form.id != null" v-model="form.key"></el-input>
|
<el-input :disabled="form.id != null" v-model="form.key"></el-input>
|
||||||
</el-form-item>
|
</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-row style="margin-left: 30px; margin-bottom: 5px">
|
||||||
<el-button @click="onAddParam" size="small" type="success">新增配置项</el-button>
|
<el-button @click="onAddParam" size="small" type="success">新增配置项</el-button>
|
||||||
@@ -62,7 +76,7 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, toRefs, reactive, watch } from 'vue';
|
import { ref, toRefs, reactive, watch } from 'vue';
|
||||||
import { configApi } from '../api';
|
import { configApi, accountApi } from '../api';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
visible: {
|
visible: {
|
||||||
@@ -84,6 +98,8 @@ const configForm: any = ref(null);
|
|||||||
const state = reactive({
|
const state = reactive({
|
||||||
dvisible: false,
|
dvisible: false,
|
||||||
params: [] as any,
|
params: [] as any,
|
||||||
|
accounts: [] as any,
|
||||||
|
permissionAccount: [] as any,
|
||||||
form: {
|
form: {
|
||||||
id: null,
|
id: null,
|
||||||
name: '',
|
name: '',
|
||||||
@@ -91,6 +107,7 @@ const state = reactive({
|
|||||||
params: '',
|
params: '',
|
||||||
value: '',
|
value: '',
|
||||||
remark: '',
|
remark: '',
|
||||||
|
permission: '',
|
||||||
},
|
},
|
||||||
btnLoading: false,
|
btnLoading: false,
|
||||||
});
|
});
|
||||||
@@ -99,6 +116,10 @@ const { dvisible, params, form, btnLoading } = toRefs(state);
|
|||||||
|
|
||||||
watch(props, (newValue: any) => {
|
watch(props, (newValue: any) => {
|
||||||
state.dvisible = newValue.visible;
|
state.dvisible = newValue.visible;
|
||||||
|
if (!state.dvisible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (newValue.data) {
|
if (newValue.data) {
|
||||||
state.form = { ...newValue.data };
|
state.form = { ...newValue.data };
|
||||||
if (state.form.params) {
|
if (state.form.params) {
|
||||||
@@ -107,9 +128,16 @@ watch(props, (newValue: any) => {
|
|||||||
state.params = [];
|
state.params = [];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
state.form = {} as any;
|
state.form = { permission: 'all' } as any;
|
||||||
state.params = [];
|
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 = () => {
|
const onAddParam = () => {
|
||||||
@@ -125,6 +153,15 @@ const cancel = () => {
|
|||||||
emit('update:visible', false);
|
emit('update:visible', false);
|
||||||
// 若父组件有取消事件,则调用
|
// 若父组件有取消事件,则调用
|
||||||
emit('cancel');
|
emit('cancel');
|
||||||
|
state.permissionAccount = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAccount = (username: any) => {
|
||||||
|
if (username) {
|
||||||
|
accountApi.list.request({ username }).then((res) => {
|
||||||
|
state.accounts = res.list;
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const btnOk = async () => {
|
const btnOk = async () => {
|
||||||
@@ -133,6 +170,11 @@ const btnOk = async () => {
|
|||||||
if (state.params) {
|
if (state.params) {
|
||||||
state.form.params = JSON.stringify(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);
|
await configApi.save.request(state.form);
|
||||||
emit('val-change', state.form);
|
emit('val-change', state.form);
|
||||||
cancel();
|
cancel();
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ log:
|
|||||||
# file:
|
# file:
|
||||||
# path: ./
|
# path: ./
|
||||||
# name: mayfly-go.log
|
# name: mayfly-go.log
|
||||||
|
|
||||||
|
# ldap相关配置
|
||||||
ldap:
|
ldap:
|
||||||
enabled: true
|
enabled: true
|
||||||
host: "ldap.example.com"
|
host: "ldap.example.com"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ require (
|
|||||||
github.com/buger/jsonparser v1.1.1
|
github.com/buger/jsonparser v1.1.1
|
||||||
github.com/gin-gonic/gin v1.9.1
|
github.com/gin-gonic/gin v1.9.1
|
||||||
github.com/go-gormigrate/gormigrate/v2 v2.1.0
|
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/locales v0.14.1
|
||||||
github.com/go-playground/universal-translator v0.18.1
|
github.com/go-playground/universal-translator v0.18.1
|
||||||
github.com/go-playground/validator/v10 v10.14.0
|
github.com/go-playground/validator/v10 v10.14.0
|
||||||
@@ -15,6 +16,7 @@ require (
|
|||||||
github.com/lib/pq v1.10.9
|
github.com/lib/pq v1.10.9
|
||||||
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20230712084735-068dc2aee82d
|
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20230712084735-068dc2aee82d
|
||||||
github.com/mojocn/base64Captcha v1.3.5 // 验证码
|
github.com/mojocn/base64Captcha v1.3.5 // 验证码
|
||||||
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/pkg/sftp v1.13.6
|
github.com/pkg/sftp v1.13.6
|
||||||
github.com/pquerna/otp v1.4.0
|
github.com/pquerna/otp v1.4.0
|
||||||
github.com/redis/go-redis/v9 v9.1.0
|
github.com/redis/go-redis/v9 v9.1.0
|
||||||
@@ -31,6 +33,7 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
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/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||||
github.com/bytedance/sonic v1.9.1 // indirect
|
github.com/bytedance/sonic v1.9.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // 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/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // 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/goccy/go-json v0.10.2 // indirect
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||||
github.com/golang/protobuf v1.5.3 // 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/arch v0.3.0 // indirect
|
||||||
golang.org/x/image v0.0.0-20220302094943-723b81ca9867 // indirect
|
golang.org/x/image v0.0.0-20220302094943-723b81ca9867 // indirect
|
||||||
golang.org/x/net v0.14.0 // 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/sys v0.11.0 // indirect
|
||||||
golang.org/x/text v0.12.0 // indirect
|
golang.org/x/text v0.12.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
package form
|
package form
|
||||||
|
|
||||||
type LoginForm struct {
|
type LoginForm struct {
|
||||||
Username string `json:"username" binding:"required"`
|
Username string `json:"username" binding:"required"`
|
||||||
Password string `binding:"required"`
|
Password string `binding:"required"`
|
||||||
Captcha string `json:"captcha"`
|
Captcha string `json:"captcha"`
|
||||||
Cid string `json:"cid"`
|
Cid string `json:"cid"`
|
||||||
LdapLogin bool `json:"ldapLogin"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type OtpVerfiy struct {
|
type OtpVerfiy struct {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package api
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"gorm.io/gorm"
|
|
||||||
"mayfly-go/internal/auth/api/form"
|
"mayfly-go/internal/auth/api/form"
|
||||||
msgapp "mayfly-go/internal/msg/application"
|
msgapp "mayfly-go/internal/msg/application"
|
||||||
sysapp "mayfly-go/internal/sys/application"
|
sysapp "mayfly-go/internal/sys/application"
|
||||||
@@ -18,6 +17,8 @@ import (
|
|||||||
"mayfly-go/pkg/utils/cryptox"
|
"mayfly-go/pkg/utils/cryptox"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LdapLogin struct {
|
type LdapLogin struct {
|
||||||
@@ -28,16 +29,18 @@ type LdapLogin struct {
|
|||||||
|
|
||||||
// @router /auth/ldap/enabled [get]
|
// @router /auth/ldap/enabled [get]
|
||||||
func (a *LdapLogin) GetLdapEnabled(rc *req.Ctx) {
|
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]
|
// @router /auth/ldap/login [post]
|
||||||
func (a *LdapLogin) Login(rc *req.Ctx) {
|
func (a *LdapLogin) Login(rc *req.Ctx) {
|
||||||
loginForm := ginx.BindJsonAndValid(rc.GinCtx, new(form.LoginForm))
|
loginForm := ginx.BindJsonAndValid(rc.GinCtx, new(form.LoginForm))
|
||||||
|
|
||||||
// 确认是 LDAP 登录
|
|
||||||
biz.IsTrue(loginForm.LdapLogin, "LDAP 登录参数错误")
|
|
||||||
|
|
||||||
accountLoginSecurity := a.ConfigApp.GetConfig(sysentity.ConfigKeyAccountLoginSecurity).ToAccountLoginSecurity()
|
accountLoginSecurity := a.ConfigApp.GetConfig(sysentity.ConfigKeyAccountLoginSecurity).ToAccountLoginSecurity()
|
||||||
// 判断是否有开启登录验证码校验
|
// 判断是否有开启登录验证码校验
|
||||||
if accountLoginSecurity.UseCaptcha {
|
if accountLoginSecurity.UseCaptcha {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"mayfly-go/pkg/ginx"
|
"mayfly-go/pkg/ginx"
|
||||||
"mayfly-go/pkg/model"
|
"mayfly-go/pkg/model"
|
||||||
"mayfly-go/pkg/req"
|
"mayfly-go/pkg/req"
|
||||||
|
"mayfly-go/pkg/utils/jsonx"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -71,14 +72,14 @@ func (m *Mongo) DeleteMongo(rc *req.Ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mongo) Databases(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{})
|
res, err := cli.ListDatabases(context.TODO(), bson.D{})
|
||||||
biz.ErrIsNilAppendErr(err, "获取mongo所有库信息失败: %s")
|
biz.ErrIsNilAppendErr(err, "获取mongo所有库信息失败: %s")
|
||||||
rc.ResData = res
|
rc.ResData = res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mongo) Collections(rc *req.Ctx) {
|
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")
|
db := rc.GinCtx.Query("database")
|
||||||
biz.NotEmpty(db, "database不能为空")
|
biz.NotEmpty(db, "database不能为空")
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
@@ -90,8 +91,13 @@ func (m *Mongo) Collections(rc *req.Ctx) {
|
|||||||
func (m *Mongo) RunCommand(rc *req.Ctx) {
|
func (m *Mongo) RunCommand(rc *req.Ctx) {
|
||||||
commandForm := new(form.MongoRunCommand)
|
commandForm := new(form.MongoRunCommand)
|
||||||
ginx.BindJsonAndValid(rc.GinCtx, commandForm)
|
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{}
|
commands := bson.D{}
|
||||||
@@ -106,7 +112,7 @@ func (m *Mongo) RunCommand(rc *req.Ctx) {
|
|||||||
|
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
var bm bson.M
|
var bm bson.M
|
||||||
err := cli.Database(commandForm.Database).RunCommand(
|
err := inst.Cli.Database(commandForm.Database).RunCommand(
|
||||||
ctx,
|
ctx,
|
||||||
commands,
|
commands,
|
||||||
).Decode(&bm)
|
).Decode(&bm)
|
||||||
@@ -117,7 +123,7 @@ func (m *Mongo) RunCommand(rc *req.Ctx) {
|
|||||||
|
|
||||||
func (m *Mongo) FindCommand(rc *req.Ctx) {
|
func (m *Mongo) FindCommand(rc *req.Ctx) {
|
||||||
g := rc.GinCtx
|
g := rc.GinCtx
|
||||||
cli := m.MongoApp.GetMongoCli(m.GetMongoId(g))
|
cli := m.MongoApp.GetMongoInst(m.GetMongoId(g)).Cli
|
||||||
commandForm := new(form.MongoFindCommand)
|
commandForm := new(form.MongoFindCommand)
|
||||||
ginx.BindJsonAndValid(g, commandForm)
|
ginx.BindJsonAndValid(g, commandForm)
|
||||||
|
|
||||||
@@ -150,10 +156,15 @@ func (m *Mongo) FindCommand(rc *req.Ctx) {
|
|||||||
|
|
||||||
func (m *Mongo) UpdateByIdCommand(rc *req.Ctx) {
|
func (m *Mongo) UpdateByIdCommand(rc *req.Ctx) {
|
||||||
g := rc.GinCtx
|
g := rc.GinCtx
|
||||||
cli := m.MongoApp.GetMongoCli(m.GetMongoId(g))
|
|
||||||
commandForm := new(form.MongoUpdateByIdCommand)
|
commandForm := new(form.MongoUpdateByIdCommand)
|
||||||
ginx.BindJsonAndValid(g, commandForm)
|
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文档id,如果为string类型则使用ObjectId解析,解析失败则为普通字符串
|
||||||
docId := commandForm.DocId
|
docId := commandForm.DocId
|
||||||
docIdVal, ok := docId.(string)
|
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")
|
biz.ErrIsNilAppendErr(err, "命令执行失败: %s")
|
||||||
|
|
||||||
rc.ReqParam = commandForm
|
|
||||||
rc.ResData = res
|
rc.ResData = res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mongo) DeleteByIdCommand(rc *req.Ctx) {
|
func (m *Mongo) DeleteByIdCommand(rc *req.Ctx) {
|
||||||
g := rc.GinCtx
|
g := rc.GinCtx
|
||||||
cli := m.MongoApp.GetMongoCli(m.GetMongoId(g))
|
|
||||||
commandForm := new(form.MongoUpdateByIdCommand)
|
commandForm := new(form.MongoUpdateByIdCommand)
|
||||||
ginx.BindJsonAndValid(g, commandForm)
|
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文档id,如果为string类型则使用ObjectId解析,解析失败则为普通字符串
|
||||||
docId := commandForm.DocId
|
docId := commandForm.DocId
|
||||||
docIdVal, ok := docId.(string)
|
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")
|
biz.ErrIsNilAppendErr(err, "命令执行失败: %s")
|
||||||
|
|
||||||
rc.ReqParam = commandForm
|
|
||||||
rc.ResData = res
|
rc.ResData = res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mongo) InsertOneCommand(rc *req.Ctx) {
|
func (m *Mongo) InsertOneCommand(rc *req.Ctx) {
|
||||||
g := rc.GinCtx
|
g := rc.GinCtx
|
||||||
cli := m.MongoApp.GetMongoCli(m.GetMongoId(g))
|
|
||||||
commandForm := new(form.MongoInsertCommand)
|
commandForm := new(form.MongoInsertCommand)
|
||||||
ginx.BindJsonAndValid(g, commandForm)
|
ginx.BindJsonAndValid(g, commandForm)
|
||||||
|
|
||||||
res, err := cli.Database(commandForm.Database).Collection(commandForm.Collection).InsertOne(context.TODO(), commandForm.Doc)
|
inst := m.MongoApp.GetMongoInst(m.GetMongoId(g))
|
||||||
biz.ErrIsNilAppendErr(err, "命令执行失败: %s")
|
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
|
rc.ResData = res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ type Mongo interface {
|
|||||||
// 删除数据库信息
|
// 删除数据库信息
|
||||||
Delete(id uint64)
|
Delete(id uint64)
|
||||||
|
|
||||||
// 获取mongo连接client
|
// 获取mongo连接实例
|
||||||
// @param id mongo id
|
// @param id mongo id
|
||||||
GetMongoCli(id uint64) *mongo.Client
|
GetMongoInst(id uint64) *MongoInstance
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMongoAppImpl(mongoRepo repository.Mongo) Mongo {
|
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 {
|
mongoInstance, err := GetMongoInstance(id, func(u uint64) *entity.Mongo {
|
||||||
mongo := d.GetById(u)
|
mongo := d.GetById(u)
|
||||||
biz.NotNil(mongo, "mongo信息不存在")
|
biz.NotNil(mongo, "mongo信息不存在")
|
||||||
return mongo
|
return mongo
|
||||||
})
|
})
|
||||||
biz.ErrIsNilAppendErr(err, "连接mongo失败: %s")
|
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)
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
mongoInstance := &MongoInstance{Id: me.Id, Info: toMongiInfo(me)}
|
mongoInstance := &MongoInstance{Id: me.Id, Info: toMongoInfo(me)}
|
||||||
|
|
||||||
mongoOptions := options.Client().ApplyURI(me.Uri).
|
mongoOptions := options.Client().ApplyURI(me.Uri).
|
||||||
SetMaxPoolSize(1)
|
SetMaxPoolSize(1)
|
||||||
@@ -200,7 +200,7 @@ func connect(me *entity.Mongo) (*MongoInstance, error) {
|
|||||||
return mongoInstance, err
|
return mongoInstance, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func toMongiInfo(me *entity.Mongo) *MongoInfo {
|
func toMongoInfo(me *entity.Mongo) *MongoInfo {
|
||||||
mi := new(MongoInfo)
|
mi := new(MongoInfo)
|
||||||
structx.Copy(mi, me)
|
structx.Copy(mi, me)
|
||||||
return mi
|
return mi
|
||||||
|
|||||||
@@ -16,28 +16,22 @@ type Config struct {
|
|||||||
func (c *Config) Configs(rc *req.Ctx) {
|
func (c *Config) Configs(rc *req.Ctx) {
|
||||||
g := rc.GinCtx
|
g := rc.GinCtx
|
||||||
condition := &entity.Config{Key: g.Query("key")}
|
condition := &entity.Config{Key: g.Query("key")}
|
||||||
|
condition.Permission = rc.LoginAccount.Username
|
||||||
rc.ResData = c.ConfigApp.GetPageList(condition, ginx.GetPageParam(g), new([]entity.Config))
|
rc.ResData = c.ConfigApp.GetPageList(condition, ginx.GetPageParam(g), new([]entity.Config))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetConfigValueByKey(rc *req.Ctx) {
|
func (c *Config) GetConfigValueByKey(rc *req.Ctx) {
|
||||||
key := rc.GinCtx.Query("key")
|
key := rc.GinCtx.Query("key")
|
||||||
biz.NotEmpty(key, "key不能为空")
|
biz.NotEmpty(key, "key不能为空")
|
||||||
rc.ResData = c.ConfigApp.GetConfig(key).Value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) GetConfigValueByKeyWithNoToken(keys []string) func(rc *req.Ctx) {
|
config := c.ConfigApp.GetConfig(key)
|
||||||
keyMap := make(map[string]struct{})
|
// 判断是否为公开配置
|
||||||
for _, key := range keys {
|
if config.Permission != "all" {
|
||||||
keyMap[key] = struct{}{}
|
rc.ResData = ""
|
||||||
}
|
return
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc.ResData = config.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) SaveConfig(rc *req.Ctx) {
|
func (c *Config) SaveConfig(rc *req.Ctx) {
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package form
|
package form
|
||||||
|
|
||||||
type ConfigForm struct {
|
type ConfigForm struct {
|
||||||
Id int `json:"id"`
|
Id int `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Params string `json:"params"`
|
Params string `json:"params"`
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
|
Permission string `json:"permission"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"mayfly-go/internal/sys/domain/entity"
|
"mayfly-go/internal/sys/domain/entity"
|
||||||
"mayfly-go/internal/sys/domain/repository"
|
"mayfly-go/internal/sys/domain/repository"
|
||||||
|
"mayfly-go/pkg/biz"
|
||||||
"mayfly-go/pkg/cache"
|
"mayfly-go/pkg/cache"
|
||||||
"mayfly-go/pkg/global"
|
"mayfly-go/pkg/global"
|
||||||
"mayfly-go/pkg/model"
|
"mayfly-go/pkg/model"
|
||||||
"mayfly-go/pkg/utils/jsonx"
|
"mayfly-go/pkg/utils/jsonx"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const SysConfigKeyPrefix = "mayfly:sys:config:"
|
const SysConfigKeyPrefix = "mayfly:sys:config:"
|
||||||
@@ -39,6 +41,11 @@ func (a *configAppImpl) Save(config *entity.Config) {
|
|||||||
if config.Id == 0 {
|
if config.Id == 0 {
|
||||||
a.configRepo.Insert(config)
|
a.configRepo.Insert(config)
|
||||||
} else {
|
} else {
|
||||||
|
oldConfig := a.GetConfig(config.Key)
|
||||||
|
if oldConfig.Permission != "all" {
|
||||||
|
biz.IsTrue(strings.Contains(oldConfig.Permission, config.Modifier), "您无权修改该配置")
|
||||||
|
}
|
||||||
|
|
||||||
a.configRepo.Update(config)
|
a.configRepo.Update(config)
|
||||||
}
|
}
|
||||||
cache.Del(SysConfigKeyPrefix + config.Key)
|
cache.Del(SysConfigKeyPrefix + config.Key)
|
||||||
@@ -53,7 +60,7 @@ func (a *configAppImpl) GetConfig(key string) *entity.Config {
|
|||||||
return 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)
|
global.Log.Warnf("不存在key = [%s] 的系统配置", key)
|
||||||
} else {
|
} else {
|
||||||
cache.SetStr(SysConfigKeyPrefix+key, jsonx.ToStr(config), -1)
|
cache.SetStr(SysConfigKeyPrefix+key, jsonx.ToStr(config), -1)
|
||||||
|
|||||||
@@ -16,11 +16,12 @@ const (
|
|||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
model.Model
|
model.Model
|
||||||
Name string `json:"name"` // 配置名
|
Name string `json:"name"` // 配置名
|
||||||
Key string `json:"key"` // 配置key
|
Key string `json:"key"` // 配置key
|
||||||
Params string `json:"params" gorm:"column:params;type:varchar(1500)"`
|
Params string `json:"params" gorm:"column:params;type:varchar(1500)"`
|
||||||
Value string `json:"value" gorm:"column:value;type:varchar(1500)"`
|
Value string `json:"value" gorm:"column:value;type:varchar(1500)"`
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
|
Permission string `json:"permission"` // 可操作该配置的权限
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Config) TableName() string {
|
func (a *Config) TableName() string {
|
||||||
|
|||||||
@@ -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] {
|
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)
|
return gormx.PageQuery(qd, pageParam, toEntity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package router
|
|||||||
import (
|
import (
|
||||||
"mayfly-go/internal/sys/api"
|
"mayfly-go/internal/sys/api"
|
||||||
"mayfly-go/internal/sys/application"
|
"mayfly-go/internal/sys/application"
|
||||||
"mayfly-go/internal/sys/domain/entity"
|
|
||||||
"mayfly-go/pkg/req"
|
"mayfly-go/pkg/req"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -19,12 +18,7 @@ func InitSysConfigRouter(router *gin.RouterGroup) {
|
|||||||
req.NewGet("", r.Configs).RequiredPermission(baseP),
|
req.NewGet("", r.Configs).RequiredPermission(baseP),
|
||||||
|
|
||||||
// 获取指定配置key对应的值
|
// 获取指定配置key对应的值
|
||||||
req.NewGet("/value", r.GetConfigValueByKeyWithNoToken([]string{
|
req.NewGet("/value", r.GetConfigValueByKey).DontNeedToken(),
|
||||||
entity.ConfigKeyAccountLoginSecurity,
|
|
||||||
entity.ConfigKeyDbQueryMaxCount,
|
|
||||||
entity.ConfigKeyDbSaveQuerySQL,
|
|
||||||
entity.ConfigUseWartermark,
|
|
||||||
})).DontNeedToken(),
|
|
||||||
|
|
||||||
req.NewGet("/oauth2-login", r.Oauth2Config).DontNeedToken(),
|
req.NewGet("/oauth2-login", r.Oauth2Config).DontNeedToken(),
|
||||||
|
|
||||||
|
|||||||
@@ -423,6 +423,7 @@ CREATE TABLE `t_sys_config` (
|
|||||||
`params` varchar(1500) DEFAULT NULL,
|
`params` varchar(1500) DEFAULT NULL,
|
||||||
`value` varchar(1500) DEFAULT NULL COMMENT '配置value',
|
`value` varchar(1500) DEFAULT NULL COMMENT '配置value',
|
||||||
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
|
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
|
||||||
|
`permission` varchar(255) DEFAULT 'all' COMMENT '操作权限',
|
||||||
`create_time` datetime NOT NULL,
|
`create_time` datetime NOT NULL,
|
||||||
`creator_id` bigint(20) NOT NULL,
|
`creator_id` bigint(20) NOT NULL,
|
||||||
`creator` varchar(36) NOT NULL,
|
`creator` varchar(36) NOT NULL,
|
||||||
@@ -438,7 +439,7 @@ CREATE TABLE `t_sys_config` (
|
|||||||
-- Records of t_sys_config
|
-- Records of t_sys_config
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
BEGIN;
|
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, 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 ('是否启用水印', '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');
|
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');
|
||||||
|
|||||||
@@ -157,6 +157,13 @@ func (q *QueryCond) Le(column string, val any) *QueryCond {
|
|||||||
return q
|
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 {
|
func (q *QueryCond) Cond(cond, column string, val any, skipBlank bool) *QueryCond {
|
||||||
// 零值跳过
|
// 零值跳过
|
||||||
if skipBlank && anyx.IsBlank(val) {
|
if skipBlank && anyx.IsBlank(val) {
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ package ldap
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-ldap/ldap/v3"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"mayfly-go/pkg/config"
|
"mayfly-go/pkg/config"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-ldap/ldap/v3"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserInfo struct {
|
type UserInfo struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user