补充应用CRUD测试
This commit is contained in:
parent
f018f28390
commit
c1f263ab84
@ -11,7 +11,7 @@
|
||||
database = "devcloud_go18"
|
||||
username = "root"
|
||||
password = "123456"
|
||||
auto_migrate = true
|
||||
auto_migrate = false
|
||||
debug = true
|
||||
|
||||
[mongo]
|
||||
|
@ -1,18 +1,17 @@
|
||||
package policy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"122.51.31.227/go-course/go18/devcloud/mcenter/apps/namespace"
|
||||
"122.51.31.227/go-course/go18/devcloud/mcenter/apps/role"
|
||||
"122.51.31.227/go-course/go18/devcloud/mcenter/apps/user"
|
||||
"github.com/infraboard/mcube/v2/ioc/config/datasource"
|
||||
"github.com/infraboard/mcube/v2/ioc/config/validator"
|
||||
"github.com/infraboard/mcube/v2/tools/pretty"
|
||||
"github.com/infraboard/modules/iam/apps"
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
func NewPolicy() *Policy {
|
||||
@ -82,10 +81,11 @@ type ResourceScope struct {
|
||||
Scope map[string][]string `json:"scope" bson:"scope" gorm:"column:scope;serializer:json;type:json" description:"数据访问的范围" optional:"true"`
|
||||
}
|
||||
|
||||
// 辅助函数:将字符串切片转换为 JSON 数组字符串
|
||||
func toJsonArray(arr []string) string {
|
||||
b, _ := json.Marshal(arr)
|
||||
return string(b)
|
||||
func (l *ResourceScope) SetScope(key string, value []string) {
|
||||
if l.Scope == nil {
|
||||
l.Scope = map[string][]string{}
|
||||
}
|
||||
l.Scope[key] = value
|
||||
}
|
||||
|
||||
func (r ResourceScope) GormResourceFilter(query *gorm.DB) *gorm.DB {
|
||||
@ -93,23 +93,27 @@ func (r ResourceScope) GormResourceFilter(query *gorm.DB) *gorm.DB {
|
||||
query = query.Where("namespace = ?", r.NamespaceId)
|
||||
}
|
||||
|
||||
switch datasource.Get().Provider {
|
||||
case datasource.PROVIDER_POSTGRES:
|
||||
for key, values := range r.Scope {
|
||||
for k, v := range r.Scope {
|
||||
// 创建一个临时 JSON 对象 {"key": ["value1", "value2"]}
|
||||
jsonCondition := fmt.Sprintf(`{"%s": %s}`, k, toJsonArray(v))
|
||||
query = query.Where("label @> ?", jsonCondition)
|
||||
}
|
||||
query = query.Where("label -->>? IN ?", key, values)
|
||||
for key, values := range r.Scope {
|
||||
if len(values) == 0 {
|
||||
continue
|
||||
}
|
||||
case datasource.PROVIDER_MYSQL:
|
||||
// 过滤条件, Label
|
||||
for key, values := range r.Scope {
|
||||
query = query.Where("label->>? IN (?)", "$."+key, values)
|
||||
}
|
||||
}
|
||||
|
||||
// 构建"标签不存在"条件
|
||||
notHasKey := clause.Not(datatypes.JSONQuery("label").HasKey(key))
|
||||
|
||||
// 构建"标签值匹配"条件
|
||||
var valueMatches []clause.Expression
|
||||
for _, val := range values {
|
||||
valueMatches = append(valueMatches,
|
||||
datatypes.JSONQuery("label").Equals(val, key))
|
||||
}
|
||||
|
||||
// 组合条件:标签不存在 OR 标签值匹配
|
||||
query = query.Where(clause.Or(
|
||||
notHasKey,
|
||||
clause.Or(valueMatches...),
|
||||
))
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
@ -128,3 +132,10 @@ type ResourceLabel struct {
|
||||
// 访问范围, 需要提前定义scope, 比如环境, 后端开发小组,开发资源
|
||||
Label map[string]string `json:"label" bson:"label" gorm:"column:label;serializer:json;type:json" description:"数据访问的范围" optional:"true"`
|
||||
}
|
||||
|
||||
func (l *ResourceLabel) SetLabel(key, value string) {
|
||||
if l.Label == nil {
|
||||
l.Label = map[string]string{}
|
||||
}
|
||||
l.Label[key] = value
|
||||
}
|
||||
|
@ -1,3 +1,9 @@
|
||||
# 应用管理
|
||||
|
||||
应用的核心是代码, 围绕这应用的核心代码, SCM的仓库地址管理
|
||||
应用的核心是代码, 围绕这应用的核心代码, SCM的仓库地址管理
|
||||
|
||||
|
||||
## 应用CRUD
|
||||
|
||||
最麻烦的基于标签的动态匹配(核心权限)
|
||||
|
||||
|
@ -4,8 +4,10 @@ import (
|
||||
"context"
|
||||
|
||||
"122.51.31.227/go-course/go18/devcloud/mpaas/apps/application"
|
||||
"github.com/infraboard/mcube/v2/exception"
|
||||
"github.com/infraboard/mcube/v2/ioc/config/datasource"
|
||||
"github.com/infraboard/mcube/v2/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// CreateApplication implements application.Service.
|
||||
@ -27,7 +29,7 @@ func (i *ApplicationServiceImpl) CreateApplication(ctx context.Context, in *appl
|
||||
func (i *ApplicationServiceImpl) QueryApplication(ctx context.Context, in *application.QueryApplicationRequest) (*types.Set[*application.Application], error) {
|
||||
set := types.New[*application.Application]()
|
||||
|
||||
query := datasource.DBFromCtx(ctx).Model(&application.Application{})
|
||||
query := in.GormResourceFilter(datasource.DBFromCtx(ctx).Model(&application.Application{}))
|
||||
if in.Id != "" {
|
||||
query = query.Where("id = ?", in.Id)
|
||||
}
|
||||
@ -64,16 +66,40 @@ func (i *ApplicationServiceImpl) QueryApplication(ctx context.Context, in *appli
|
||||
}
|
||||
|
||||
// DescribeApplication implements application.Service.
|
||||
func (i *ApplicationServiceImpl) DescribeApplication(context.Context, *application.DescribeApplicationRequest) (*application.Application, error) {
|
||||
panic("unimplemented")
|
||||
func (i *ApplicationServiceImpl) DescribeApplication(ctx context.Context, in *application.DescribeApplicationRequest) (*application.Application, error) {
|
||||
query := in.GormResourceFilter(datasource.DBFromCtx(ctx).Model(&application.Application{}))
|
||||
|
||||
ins := &application.Application{}
|
||||
if err := query.Where("id = ?", in.Id).First(ins).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, exception.NewNotFound("app %s not found", in.Id)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ins, nil
|
||||
}
|
||||
|
||||
// UpdateApplication implements application.Service.
|
||||
func (i *ApplicationServiceImpl) UpdateApplication(context.Context, *application.UpdateApplicationRequest) (*application.Application, error) {
|
||||
panic("unimplemented")
|
||||
func (i *ApplicationServiceImpl) UpdateApplication(ctx context.Context, in *application.UpdateApplicationRequest) (*application.Application, error) {
|
||||
ins, err := i.DescribeApplication(ctx, &in.DescribeApplicationRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ins.CreateApplicationSpec = in.CreateApplicationSpec
|
||||
return ins, datasource.DBFromCtx(ctx).Where("id = ?", in.Id).Updates(ins).Error
|
||||
}
|
||||
|
||||
// DeleteApplication implements application.Service.
|
||||
func (i *ApplicationServiceImpl) DeleteApplication(context.Context, *application.DeleteApplicationRequest) (*application.Application, error) {
|
||||
panic("unimplemented")
|
||||
func (i *ApplicationServiceImpl) DeleteApplication(ctx context.Context, in *application.DeleteApplicationRequest) (*application.Application, error) {
|
||||
ins, err := i.DescribeApplication(ctx, &in.DescribeApplicationRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ins, datasource.DBFromCtx(ctx).
|
||||
Where("id = ?", in.Id).
|
||||
Delete(&application.Application{}).
|
||||
Error
|
||||
}
|
||||
|
@ -14,9 +14,22 @@ func TestCreateApplication(t *testing.T) {
|
||||
req.CodeRepository = application.CodeRepository{
|
||||
SshUrl: "git@122.51.31.227:go-course/go18.git",
|
||||
}
|
||||
req.SetLabel("team", "golang_dev_group_01")
|
||||
ins, err := svc.CreateApplication(ctx, req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(ins)
|
||||
}
|
||||
|
||||
// SELECT * FROM `applications` WHERE (NOT JSON_EXTRACT(`label`,'$.team') IS NOT NULL OR JSON_EXTRACT(`label`,'$.team') = 'golang_dev_group_01') ORDER BY created_at desc LIMIT 20
|
||||
func TestQueryApplication(t *testing.T) {
|
||||
req := application.NewQueryApplicationRequest()
|
||||
req.SetScope("team", []string{"golang_dev_group_01"})
|
||||
// req.SetScope("env", []string{"prod"})
|
||||
ins, err := svc.QueryApplication(ctx, req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(ins)
|
||||
}
|
||||
|
@ -30,6 +30,14 @@ type Service interface {
|
||||
DescribeApplication(context.Context, *DescribeApplicationRequest) (*Application, error)
|
||||
}
|
||||
|
||||
func NewQueryApplicationRequest() *QueryApplicationRequest {
|
||||
return &QueryApplicationRequest{
|
||||
QueryApplicationRequestSpec: QueryApplicationRequestSpec{
|
||||
PageRequest: request.NewDefaultPageRequest(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type QueryApplicationRequest struct {
|
||||
policy.ResourceScope
|
||||
QueryApplicationRequestSpec
|
||||
|
6
go.mod
6
go.mod
@ -17,11 +17,13 @@ require (
|
||||
go.mongodb.org/mongo-driver v1.17.3
|
||||
golang.org/x/crypto v0.38.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gorm.io/datatypes v1.2.5
|
||||
gorm.io/driver/mysql v1.5.7
|
||||
gorm.io/gorm v1.26.0
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bytedance/sonic v1.13.2 // indirect
|
||||
@ -44,13 +46,13 @@ require (
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.26.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect
|
||||
github.com/jackc/pgx/v5 v5.5.5 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
|
23
go.sum
23
go.sum
@ -1,3 +1,5 @@
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
@ -66,11 +68,16 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
|
||||
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
||||
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
@ -93,8 +100,8 @@ github.com/infraboard/modules v0.0.12 h1:vQqm+JwzmhL+hcD9SV+WVlp9ecInc7NsbGahcTm
|
||||
github.com/infraboard/modules v0.0.12/go.mod h1:NdgdH/NoeqibJmFPn9th+tisMuR862/crbXeH4FPMaU=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
|
||||
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||
@ -136,6 +143,10 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA=
|
||||
github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@ -317,10 +328,16 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/datatypes v1.2.5 h1:9UogU3jkydFVW1bIVVeoYsTpLRgwDVW3rHfJG6/Ek9I=
|
||||
gorm.io/datatypes v1.2.5/go.mod h1:I5FUdlKpLb5PMqeMQhm30CQ6jXP8Rj89xkTeCSAaAD4=
|
||||
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
|
||||
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
||||
gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314=
|
||||
gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
|
||||
gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU=
|
||||
gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
|
||||
gorm.io/driver/sqlserver v1.5.4 h1:xA+Y1KDNspv79q43bPyjDMUgHoYHLhXYmdFcYPobg8g=
|
||||
gorm.io/driver/sqlserver v1.5.4/go.mod h1:+frZ/qYmuna11zHPlh5oc2O6ZA/lS88Keb0XSH1Zh/g=
|
||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
gorm.io/gorm v1.26.0 h1:9lqQVPG5aNNS6AyHdRiwScAVnXHg/L/Srzx55G5fOgs=
|
||||
gorm.io/gorm v1.26.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
|
||||
|
Loading…
x
Reference in New Issue
Block a user