补充应用授权
This commit is contained in:
parent
1b27d97f2a
commit
c76c8b1100
2
devcloud/.vscode/launch.json
vendored
2
devcloud/.vscode/launch.json
vendored
@ -5,7 +5,7 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "mcenter api server",
|
"name": "devcloud api server",
|
||||||
"type": "go",
|
"type": "go",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"mode": "auto",
|
"mode": "auto",
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
database = "devcloud_go18"
|
database = "devcloud_go18"
|
||||||
username = "root"
|
username = "root"
|
||||||
password = "123456"
|
password = "123456"
|
||||||
auto_migrate = true
|
auto_migrate = false
|
||||||
debug = true
|
debug = false
|
||||||
|
|
||||||
[mongo]
|
[mongo]
|
||||||
endpoints = ["127.0.0.1:27017"]
|
endpoints = ["127.0.0.1:27017"]
|
||||||
|
@ -5,9 +5,12 @@ import (
|
|||||||
|
|
||||||
// mcenter 业务对象
|
// mcenter 业务对象
|
||||||
_ "122.51.31.227/go-course/go18/devcloud/mcenter/apps"
|
_ "122.51.31.227/go-course/go18/devcloud/mcenter/apps"
|
||||||
|
|
||||||
// audit 业务对象
|
// audit 业务对象
|
||||||
_ "122.51.31.227/go-course/go18/devcloud/audit/apps"
|
_ "122.51.31.227/go-course/go18/devcloud/audit/apps"
|
||||||
|
|
||||||
// mpaas 应用发布
|
// mpaas 应用发布
|
||||||
|
_ "122.51.31.227/go-course/go18/devcloud/mpaas/apps"
|
||||||
|
|
||||||
// 非功能性模块
|
// 非功能性模块
|
||||||
_ "github.com/infraboard/mcube/v2/ioc/apps/apidoc/restful"
|
_ "github.com/infraboard/mcube/v2/ioc/apps/apidoc/restful"
|
||||||
|
@ -2,8 +2,8 @@ package impl
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"122.51.31.227/go-course/go18/devcloud/mcenter/apps/endpoint"
|
|
||||||
"122.51.31.227/go-course/go18/devcloud/mcenter/apps/namespace"
|
"122.51.31.227/go-course/go18/devcloud/mcenter/apps/namespace"
|
||||||
"122.51.31.227/go-course/go18/devcloud/mcenter/apps/policy"
|
"122.51.31.227/go-course/go18/devcloud/mcenter/apps/policy"
|
||||||
"122.51.31.227/go-course/go18/devcloud/mcenter/apps/role"
|
"122.51.31.227/go-course/go18/devcloud/mcenter/apps/role"
|
||||||
@ -36,8 +36,8 @@ func (i *PolicyServiceImpl) QueryNamespace(ctx context.Context, in *policy.Query
|
|||||||
|
|
||||||
// 查询用户可以访问的Api接口
|
// 查询用户可以访问的Api接口
|
||||||
// 找到用户可以访问的角色列表,然后在找出角色对应的Api访问权限
|
// 找到用户可以访问的角色列表,然后在找出角色对应的Api访问权限
|
||||||
func (i *PolicyServiceImpl) QueryEndpoint(ctx context.Context, in *policy.QueryEndpointRequest) (*types.Set[*endpoint.Endpoint], error) {
|
func (i *PolicyServiceImpl) QueryEndpoint(ctx context.Context, in *policy.QueryEndpointRequest) (*policy.QueryEndpointResponse, error) {
|
||||||
set := types.New[*endpoint.Endpoint]()
|
resp := policy.NewQueryEndpointResponse()
|
||||||
policies, err := i.QueryPolicy(ctx,
|
policies, err := i.QueryPolicy(ctx,
|
||||||
policy.NewQueryPolicyRequest().
|
policy.NewQueryPolicyRequest().
|
||||||
SetSkipPage(true).
|
SetSkipPage(true).
|
||||||
@ -49,19 +49,25 @@ func (i *PolicyServiceImpl) QueryEndpoint(ctx context.Context, in *policy.QueryE
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
roleReq := role.NewQueryMatchedEndpointRequest()
|
if policies.Len() > 1 {
|
||||||
policies.ForEach(func(t *policy.Policy) {
|
return nil, fmt.Errorf("同一个空间下, 一个用户有多条[%d]授权", policies.Len())
|
||||||
roleReq.Add(t.RoleId...)
|
}
|
||||||
})
|
|
||||||
|
|
||||||
|
p := policies.First()
|
||||||
|
roleReq := role.NewQueryMatchedEndpointRequest()
|
||||||
|
roleReq.Add(p.RoleId...)
|
||||||
|
|
||||||
|
// p.ResourceScope
|
||||||
|
resp.ResourceScope = p.ResourceScope
|
||||||
if policies.Len() > 0 {
|
if policies.Len() > 0 {
|
||||||
set, err = role.GetService().QueryMatchedEndpoint(ctx, roleReq)
|
set, err := role.GetService().QueryMatchedEndpoint(ctx, roleReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
resp.Items = set.Items
|
||||||
}
|
}
|
||||||
|
|
||||||
return set, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 校验Api接口权限
|
// 校验Api接口权限
|
||||||
@ -69,7 +75,7 @@ func (i *PolicyServiceImpl) ValidateEndpointPermission(ctx context.Context, in *
|
|||||||
resp := policy.NewValidateEndpointPermissionResponse(*in)
|
resp := policy.NewValidateEndpointPermissionResponse(*in)
|
||||||
|
|
||||||
// 空间Owner有所有权限
|
// 空间Owner有所有权限
|
||||||
ns, err := namespace.GetService().DescribeNamespace(ctx, namespace.NewDescribeNamespaceRequest().SetNamespaceId(in.NamespaceId))
|
ns, err := namespace.GetService().DescribeNamespace(ctx, namespace.NewDescribeNamespaceRequest().SetNamespaceId(in.GetNamespaceId()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -81,15 +87,20 @@ func (i *PolicyServiceImpl) ValidateEndpointPermission(ctx context.Context, in *
|
|||||||
// 非空间管理员需要独立鉴权, 查询用户可以访问的API列表
|
// 非空间管理员需要独立鉴权, 查询用户可以访问的API列表
|
||||||
endpointReq := policy.NewQueryEndpointRequest()
|
endpointReq := policy.NewQueryEndpointRequest()
|
||||||
endpointReq.UserId = in.UserId
|
endpointReq.UserId = in.UserId
|
||||||
endpointReq.NamespaceId = in.NamespaceId
|
endpointReq.NamespaceId = in.GetNamespaceId()
|
||||||
endpointSet, err := i.QueryEndpoint(ctx, endpointReq)
|
endpointSet, err := i.QueryEndpoint(ctx, endpointReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 补充Api访问的scope
|
||||||
|
resp.ResourceScope = endpointSet.ResourceScope
|
||||||
|
|
||||||
for _, item := range endpointSet.Items {
|
for _, item := range endpointSet.Items {
|
||||||
if item.IsMatched(in.Service, in.Method, in.Path) {
|
if item.IsMatched(in.Service, in.Method, in.Path) {
|
||||||
resp.HasPermission = true
|
resp.HasPermission = true
|
||||||
resp.Endpoint = item
|
resp.Endpoint = item
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
func TestQueryNamespace(t *testing.T) {
|
func TestQueryNamespace(t *testing.T) {
|
||||||
req := policy.NewQueryNamespaceRequest()
|
req := policy.NewQueryNamespaceRequest()
|
||||||
req.UserId = 1
|
req.UserId = 2
|
||||||
set, err := impl.QueryNamespace(ctx, req)
|
set, err := impl.QueryNamespace(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -29,8 +29,8 @@ func TestQueryEndpoint(t *testing.T) {
|
|||||||
|
|
||||||
func TestValidateEndpointPermission(t *testing.T) {
|
func TestValidateEndpointPermission(t *testing.T) {
|
||||||
req := policy.NewValidateEndpointPermissionRequest()
|
req := policy.NewValidateEndpointPermissionRequest()
|
||||||
req.UserId = 1
|
req.UserId = 3
|
||||||
req.NamespaceId = 1
|
req.SetNamespaceId(1)
|
||||||
req.Service = "devcloud"
|
req.Service = "devcloud"
|
||||||
req.Method = "GET"
|
req.Method = "GET"
|
||||||
req.Path = "/api/devcloud/v1/users/"
|
req.Path = "/api/devcloud/v1/users/"
|
||||||
|
@ -20,9 +20,14 @@ func TestQueryPolicy(t *testing.T) {
|
|||||||
|
|
||||||
func TestCreatePolicy(t *testing.T) {
|
func TestCreatePolicy(t *testing.T) {
|
||||||
req := policy.NewCreatePolicyRequest()
|
req := policy.NewCreatePolicyRequest()
|
||||||
|
// guest
|
||||||
req.UserId = 2
|
req.UserId = 2
|
||||||
req.RoleId = []uint64{1}
|
// 开发
|
||||||
|
req.RoleId = []uint64{3}
|
||||||
|
// default
|
||||||
req.SetNamespaceId(1)
|
req.SetNamespaceId(1)
|
||||||
|
// 开发小组1的资源
|
||||||
|
req.SetScope("team", []string{"dev01"})
|
||||||
set, err := impl.CreatePolicy(ctx, req)
|
set, err := impl.CreatePolicy(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -132,17 +132,28 @@ type PermissionService interface {
|
|||||||
// 查询用户可以访问的菜单
|
// 查询用户可以访问的菜单
|
||||||
QueryMenu(context.Context, *QueryMenuRequest) (*types.Set[*view.Menu], error)
|
QueryMenu(context.Context, *QueryMenuRequest) (*types.Set[*view.Menu], error)
|
||||||
// 查询用户可以访问的Api接口
|
// 查询用户可以访问的Api接口
|
||||||
QueryEndpoint(context.Context, *QueryEndpointRequest) (*types.Set[*endpoint.Endpoint], error)
|
QueryEndpoint(context.Context, *QueryEndpointRequest) (*QueryEndpointResponse, error)
|
||||||
// 校验页面权限
|
// 校验页面权限
|
||||||
ValidatePagePermission(context.Context, *ValidatePagePermissionRequest) (*ValidatePagePermissionResponse, error)
|
ValidatePagePermission(context.Context, *ValidatePagePermissionRequest) (*ValidatePagePermissionResponse, error)
|
||||||
// 校验接口权限
|
// 校验接口权限
|
||||||
ValidateEndpointPermission(context.Context, *ValidateEndpointPermissionRequest) (*ValidateEndpointPermissionResponse, error)
|
ValidateEndpointPermission(context.Context, *ValidateEndpointPermissionRequest) (*ValidateEndpointPermissionResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewQueryEndpointResponse() *QueryEndpointResponse {
|
||||||
|
return &QueryEndpointResponse{
|
||||||
|
Items: []*endpoint.Endpoint{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type QueryEndpointResponse struct {
|
||||||
|
ResourceScope
|
||||||
|
Items []*endpoint.Endpoint
|
||||||
|
}
|
||||||
|
|
||||||
type ValidatePagePermissionRequest struct {
|
type ValidatePagePermissionRequest struct {
|
||||||
UserId uint64 `json:"user_id" form:"user_id"`
|
UserId uint64 `json:"user_id" form:"user_id"`
|
||||||
NamespaceId uint64 `json:"namespace_id" form:"namespace_id"`
|
|
||||||
Path string `json:"path" form:"path"`
|
Path string `json:"path" form:"path"`
|
||||||
|
ResourceScope
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewValidatePagePermissionResponse(req ValidatePagePermissionRequest) *ValidatePagePermissionResponse {
|
func NewValidatePagePermissionResponse(req ValidatePagePermissionRequest) *ValidatePagePermissionResponse {
|
||||||
@ -163,10 +174,10 @@ func NewValidateEndpointPermissionRequest() *ValidateEndpointPermissionRequest {
|
|||||||
|
|
||||||
type ValidateEndpointPermissionRequest struct {
|
type ValidateEndpointPermissionRequest struct {
|
||||||
UserId uint64 `json:"user_id" form:"user_id"`
|
UserId uint64 `json:"user_id" form:"user_id"`
|
||||||
NamespaceId uint64 `json:"namespace_id" form:"namespace_id"`
|
|
||||||
Service string `json:"service" form:"service"`
|
Service string `json:"service" form:"service"`
|
||||||
Path string `json:"path" form:"path"`
|
Path string `json:"path" form:"path"`
|
||||||
Method string `json:"method" form:"method"`
|
Method string `json:"method" form:"method"`
|
||||||
|
ResourceScope
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewValidateEndpointPermissionResponse(req ValidateEndpointPermissionRequest) *ValidateEndpointPermissionResponse {
|
func NewValidateEndpointPermissionResponse(req ValidateEndpointPermissionRequest) *ValidateEndpointPermissionResponse {
|
||||||
|
@ -82,6 +82,31 @@ type ResourceScope struct {
|
|||||||
Scope map[string][]string `json:"scope" bson:"scope" gorm:"column:scope;serializer:json;type:json" description:"数据访问的范围" optional:"true"`
|
Scope map[string][]string `json:"scope" bson:"scope" gorm:"column:scope;serializer:json;type:json" description:"数据访问的范围" optional:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r ResourceScope) String() string {
|
||||||
|
return pretty.ToJSON(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ResourceScope) BuildMySQLPrefixBlob() {
|
||||||
|
for k := range r.Scope {
|
||||||
|
for i := range r.Scope[k] {
|
||||||
|
if !strings.HasSuffix(r.Scope[k][i], "%") {
|
||||||
|
r.Scope[k][i] += "%"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ResourceScope) SetNamespaceId(v uint64) {
|
||||||
|
r.NamespaceId = &v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ResourceScope) GetNamespaceId() uint64 {
|
||||||
|
if r.NamespaceId == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return *r.NamespaceId
|
||||||
|
}
|
||||||
|
|
||||||
func (l *ResourceScope) SetScope(key string, value []string) {
|
func (l *ResourceScope) SetScope(key string, value []string) {
|
||||||
if l.Scope == nil {
|
if l.Scope == nil {
|
||||||
l.Scope = map[string][]string{}
|
l.Scope = map[string][]string{}
|
||||||
@ -91,7 +116,7 @@ func (l *ResourceScope) SetScope(key string, value []string) {
|
|||||||
|
|
||||||
func (r ResourceScope) GormResourceFilter(query *gorm.DB) *gorm.DB {
|
func (r ResourceScope) GormResourceFilter(query *gorm.DB) *gorm.DB {
|
||||||
if r.NamespaceId != nil {
|
if r.NamespaceId != nil {
|
||||||
query = query.Where("namespace = ?", r.NamespaceId)
|
query = query.Where("namespace_id = ?", r.NamespaceId)
|
||||||
}
|
}
|
||||||
|
|
||||||
for key, values := range r.Scope {
|
for key, values := range r.Scope {
|
||||||
@ -144,6 +169,10 @@ type ResourceLabel struct {
|
|||||||
Label map[string]string `json:"label" bson:"label" gorm:"column:label;serializer:json;type:json" description:"数据访问的范围" optional:"true"`
|
Label map[string]string `json:"label" bson:"label" gorm:"column:label;serializer:json;type:json" description:"数据访问的范围" optional:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *ResourceLabel) SetNamespaceId(v uint64) {
|
||||||
|
l.NamespaceId = &v
|
||||||
|
}
|
||||||
|
|
||||||
func (l *ResourceLabel) SetLabel(key, value string) {
|
func (l *ResourceLabel) SetLabel(key, value string) {
|
||||||
if l.Label == nil {
|
if l.Label == nil {
|
||||||
l.Label = map[string]string{}
|
l.Label = map[string]string{}
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
func TestQueryApiPermission(t *testing.T) {
|
func TestQueryApiPermission(t *testing.T) {
|
||||||
req := role.NewQueryApiPermissionRequest()
|
req := role.NewQueryApiPermissionRequest()
|
||||||
req.AddRoleId(2)
|
req.AddRoleId(3)
|
||||||
set, err := impl.QueryApiPermission(ctx, req)
|
set, err := impl.QueryApiPermission(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -17,8 +17,11 @@ func TestQueryApiPermission(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAddApiPermission(t *testing.T) {
|
func TestAddApiPermission(t *testing.T) {
|
||||||
req := role.NewAddApiPermissionRequest(1)
|
req := role.NewAddApiPermissionRequest(3)
|
||||||
req.Add(role.NewResourceActionApiPermissionSpec("devcloud", "user", "list"))
|
req.Add(
|
||||||
|
role.NewResourceActionApiPermissionSpec("devcloud", "user", "list"),
|
||||||
|
// role.NewResourceActionApiPermissionSpec("devcloud", "application", "list"),
|
||||||
|
)
|
||||||
set, err := impl.AddApiPermission(ctx, req)
|
set, err := impl.AddApiPermission(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -28,7 +31,7 @@ func TestAddApiPermission(t *testing.T) {
|
|||||||
|
|
||||||
func TestQueryMatchedEndpoint(t *testing.T) {
|
func TestQueryMatchedEndpoint(t *testing.T) {
|
||||||
req := role.NewQueryMatchedEndpointRequest()
|
req := role.NewQueryMatchedEndpointRequest()
|
||||||
req.Add(1)
|
req.Add(3)
|
||||||
set, err := impl.QueryMatchedEndpoint(ctx, req)
|
set, err := impl.QueryMatchedEndpoint(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -49,8 +49,8 @@ func (i *TokenServiceImpl) IssueToken(ctx context.Context, in *token.IssueTokenR
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if tk.NamespaceId == 0 {
|
if tk.NamespaceId == nil {
|
||||||
tk.NamespaceId = 1
|
tk.SetNamespaceId(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保持Token
|
// 保持Token
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"122.51.31.227/go-course/go18/devcloud/mcenter/apps/policy"
|
||||||
"github.com/infraboard/mcube/v2/exception"
|
"github.com/infraboard/mcube/v2/exception"
|
||||||
"github.com/infraboard/mcube/v2/tools/pretty"
|
"github.com/infraboard/mcube/v2/tools/pretty"
|
||||||
)
|
)
|
||||||
@ -56,7 +57,6 @@ func NewToken() *Token {
|
|||||||
IssueAt: time.Now(),
|
IssueAt: time.Now(),
|
||||||
Status: NewStatus(),
|
Status: NewStatus(),
|
||||||
Extras: map[string]string{},
|
Extras: map[string]string{},
|
||||||
Scope: map[string]string{},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return tk
|
return tk
|
||||||
@ -77,12 +77,14 @@ type Token struct {
|
|||||||
UserName string `json:"user_name" gorm:"column:user_name;type:varchar(100);not null;index" description:"持有该Token的用户名称"`
|
UserName string `json:"user_name" gorm:"column:user_name;type:varchar(100);not null;index" description:"持有该Token的用户名称"`
|
||||||
// 是不是管理员
|
// 是不是管理员
|
||||||
IsAdmin bool `json:"is_admin" gorm:"column:is_admin;type:tinyint(1)" description:"是不是管理员"`
|
IsAdmin bool `json:"is_admin" gorm:"column:is_admin;type:tinyint(1)" description:"是不是管理员"`
|
||||||
// 令牌生效空间Id
|
|
||||||
NamespaceId uint64 `json:"namespace_id" gorm:"column:namespace_id;type:uint;index" description:"令牌所属空间Id"`
|
// 令牌生效空间Ids
|
||||||
|
policy.ResourceScope
|
||||||
|
// NamespaceId uint64 `json:"namespace_id" gorm:"column:namespace_id;type:uint;index" description:"令牌所属空间Id"`
|
||||||
// 令牌生效空间名称
|
// 令牌生效空间名称
|
||||||
NamespaceName string `json:"namespace_name" gorm:"column:namespace_name;type:varchar(100);index" description:"令牌所属空间"`
|
NamespaceName string `json:"namespace_name" gorm:"column:namespace_name;type:varchar(100);index" description:"令牌所属空间"`
|
||||||
// 访问范围定义, 鉴权完成后补充
|
// // 访问范围定义, 鉴权完成后补充
|
||||||
Scope map[string]string `json:"scope" gorm:"column:scope;type:varchar(100);serializer:json" description:"令牌访问范围定义"`
|
// Scope map[string][]string `json:"scope" gorm:"column:scope;type:varchar(100);serializer:json" description:"令牌访问范围定义"`
|
||||||
// 颁发给用户的访问令牌(用户需要携带Token来访问接口)
|
// 颁发给用户的访问令牌(用户需要携带Token来访问接口)
|
||||||
AccessToken string `json:"access_token" gorm:"column:access_token;type:varchar(100);not null;uniqueIndex" description:"访问令牌"`
|
AccessToken string `json:"access_token" gorm:"column:access_token;type:varchar(100);not null;uniqueIndex" description:"访问令牌"`
|
||||||
// 访问令牌过期时间
|
// 访问令牌过期时间
|
||||||
@ -105,6 +107,10 @@ func (t *Token) TableName() string {
|
|||||||
return "tokens"
|
return "tokens"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Token) String() string {
|
||||||
|
return pretty.ToJSON(r)
|
||||||
|
}
|
||||||
|
|
||||||
// 判断访问令牌是否过期,没设置代表用不过期
|
// 判断访问令牌是否过期,没设置代表用不过期
|
||||||
func (t *Token) IsAccessTokenExpired() error {
|
func (t *Token) IsAccessTokenExpired() error {
|
||||||
if t.AccessTokenExpiredAt != nil {
|
if t.AccessTokenExpiredAt != nil {
|
||||||
@ -158,10 +164,6 @@ func (t *Token) SetRefreshTokenExpiredAt(v time.Time) {
|
|||||||
t.RefreshTokenExpiredAt = &v
|
t.RefreshTokenExpiredAt = &v
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Token) String() string {
|
|
||||||
return pretty.ToJSON(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Token) SetIssuer(issuer string) *Token {
|
func (t *Token) SetIssuer(issuer string) *Token {
|
||||||
t.Issuer = issuer
|
t.Issuer = issuer
|
||||||
return t
|
return t
|
||||||
|
@ -92,6 +92,14 @@ func (c *Checker) Check(r *restful.Request, w *restful.Response, next *restful.F
|
|||||||
response.Failed(w, err)
|
response.Failed(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果校验成功,需要把 用户的身份信息,放到请求的上下文中,方便后面的逻辑获取
|
||||||
|
// context.WithValue 来往ctx 添加 value
|
||||||
|
// key: value, value token对象
|
||||||
|
ctx := context.WithValue(r.Request.Context(), token.CTX_TOKEN_KEY, tk)
|
||||||
|
|
||||||
|
// ctx 生成一个新的,继续往下传递
|
||||||
|
r.Request = r.Request.WithContext(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 请求处理
|
// 请求处理
|
||||||
@ -111,13 +119,6 @@ func (c *Checker) CheckToken(r *restful.Request) (*token.Token, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果校验成功,需要把 用户的身份信息,放到请求的上下文中,方便后面的逻辑获取
|
|
||||||
// context.WithValue 来往ctx 添加 value
|
|
||||||
// key: value, value token对象
|
|
||||||
ctx := context.WithValue(r.Request.Context(), token.CTX_TOKEN_KEY, tk)
|
|
||||||
|
|
||||||
// ctx 生成一个新的,继续往下传递
|
|
||||||
r.Request = r.Request.WithContext(ctx)
|
|
||||||
return tk, nil
|
return tk, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +132,7 @@ func (c *Checker) CheckPolicy(r *restful.Request, tk *token.Token, route *endpoi
|
|||||||
if route.HasRequiredRole() {
|
if route.HasRequiredRole() {
|
||||||
set, err := c.policy.QueryPolicy(r.Request.Context(),
|
set, err := c.policy.QueryPolicy(r.Request.Context(),
|
||||||
policy.NewQueryPolicyRequest().
|
policy.NewQueryPolicyRequest().
|
||||||
SetNamespaceId(tk.NamespaceId).
|
SetNamespaceId(tk.GetNamespaceId()).
|
||||||
SetUserId(tk.UserId).
|
SetUserId(tk.UserId).
|
||||||
SetExpired(false).
|
SetExpired(false).
|
||||||
SetEnabled(true).
|
SetEnabled(true).
|
||||||
@ -145,6 +146,9 @@ func (c *Checker) CheckPolicy(r *restful.Request, tk *token.Token, route *endpoi
|
|||||||
p := set.Items[i]
|
p := set.Items[i]
|
||||||
if route.IsRequireRole(p.Role.Name) {
|
if route.IsRequireRole(p.Role.Name) {
|
||||||
hasPerm = true
|
hasPerm = true
|
||||||
|
|
||||||
|
// 把这个scope传递下去
|
||||||
|
tk.Scope = p.Scope
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,7 +161,7 @@ func (c *Checker) CheckPolicy(r *restful.Request, tk *token.Token, route *endpoi
|
|||||||
if route.RequiredPerm {
|
if route.RequiredPerm {
|
||||||
validateReq := policy.NewValidateEndpointPermissionRequest()
|
validateReq := policy.NewValidateEndpointPermissionRequest()
|
||||||
validateReq.UserId = tk.UserId
|
validateReq.UserId = tk.UserId
|
||||||
validateReq.NamespaceId = tk.NamespaceId
|
validateReq.ResourceScope = tk.ResourceScope
|
||||||
validateReq.Service = application.Get().GetAppName()
|
validateReq.Service = application.Get().GetAppName()
|
||||||
validateReq.Method = route.Method
|
validateReq.Method = route.Method
|
||||||
validateReq.Path = route.Path
|
validateReq.Path = route.Path
|
||||||
@ -168,6 +172,9 @@ func (c *Checker) CheckPolicy(r *restful.Request, tk *token.Token, route *endpoi
|
|||||||
if !resp.HasPermission {
|
if !resp.HasPermission {
|
||||||
return exception.NewPermissionDeny("无权限访问")
|
return exception.NewPermissionDeny("无权限访问")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tk.ResourceScope = resp.ResourceScope
|
||||||
|
tk.BuildMySQLPrefixBlob()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
58
devcloud/mpaas/apps/application/api/api.go
Normal file
58
devcloud/mpaas/apps/application/api/api.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"122.51.31.227/go-course/go18/devcloud/audit/audit"
|
||||||
|
"122.51.31.227/go-course/go18/devcloud/mcenter/permission"
|
||||||
|
"122.51.31.227/go-course/go18/devcloud/mpaas/apps/application"
|
||||||
|
"github.com/infraboard/mcube/v2/ioc"
|
||||||
|
"github.com/infraboard/mcube/v2/ioc/config/gorestful"
|
||||||
|
|
||||||
|
restfulspec "github.com/emicklei/go-restful-openapi/v2"
|
||||||
|
"github.com/emicklei/go-restful/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
ioc.Api().Registry(&UserRestfulApiHandler{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserRestfulApiHandler struct {
|
||||||
|
ioc.ObjectImpl
|
||||||
|
|
||||||
|
// 依赖控制器
|
||||||
|
svc application.Service
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *UserRestfulApiHandler) Name() string {
|
||||||
|
return "applications"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *UserRestfulApiHandler) Init() error {
|
||||||
|
h.svc = application.GetService()
|
||||||
|
|
||||||
|
tags := []string{"应用管理"}
|
||||||
|
ws := gorestful.ObjectRouter(h)
|
||||||
|
// required_auth=true/false
|
||||||
|
ws.Route(ws.GET("").To(h.QueryApplication).
|
||||||
|
Doc("应用列表查询").
|
||||||
|
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||||
|
// 这个开关怎么生效
|
||||||
|
// 中间件需求读取接口的描述信息,来决定是否需要认证
|
||||||
|
Metadata(permission.Auth(true)).
|
||||||
|
Metadata(permission.Permission(true)).
|
||||||
|
Metadata(permission.Resource("application")).
|
||||||
|
Metadata(permission.Action("list")).
|
||||||
|
Metadata(audit.Enable(true)).
|
||||||
|
Param(restful.QueryParameter("page_size", "分页大小").DataType("integer")).
|
||||||
|
Param(restful.QueryParameter("page_number", "页码").DataType("integer")).
|
||||||
|
Writes(Set{}).
|
||||||
|
Returns(200, "OK", Set{}))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// *types.Set[*User]
|
||||||
|
// 返回的泛型, API Doc这个工具 不支持泛型
|
||||||
|
type Set struct {
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
Items []application.Application `json:"items"`
|
||||||
|
}
|
31
devcloud/mpaas/apps/application/api/application.go
Normal file
31
devcloud/mpaas/apps/application/api/application.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"122.51.31.227/go-course/go18/devcloud/mcenter/apps/token"
|
||||||
|
"122.51.31.227/go-course/go18/devcloud/mpaas/apps/application"
|
||||||
|
"github.com/emicklei/go-restful/v3"
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
"github.com/infraboard/mcube/v2/http/restful/response"
|
||||||
|
"github.com/infraboard/mcube/v2/ioc/config/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *UserRestfulApiHandler) QueryApplication(r *restful.Request, w *restful.Response) {
|
||||||
|
req := application.NewQueryApplicationRequest()
|
||||||
|
if err := binding.Query.Bind(r.Request, &req.QueryApplicationRequestSpec); err != nil {
|
||||||
|
response.Failed(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 过滤条件在认证完成后的上下文中
|
||||||
|
tk := token.GetTokenFromCtx(r.Request.Context())
|
||||||
|
req.ResourceScope = tk.ResourceScope
|
||||||
|
log.L().Debug().Msgf("resource scope: %s", tk.ResourceScope)
|
||||||
|
|
||||||
|
set, err := h.svc.QueryApplication(r.Request.Context(), req)
|
||||||
|
if err != nil {
|
||||||
|
response.Failed(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(w, set)
|
||||||
|
}
|
@ -29,6 +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) {
|
func (i *ApplicationServiceImpl) QueryApplication(ctx context.Context, in *application.QueryApplicationRequest) (*types.Set[*application.Application], error) {
|
||||||
set := types.New[*application.Application]()
|
set := types.New[*application.Application]()
|
||||||
|
|
||||||
|
i.log.Debug().Msgf("scope: %s", in.ResourceScope)
|
||||||
query := in.GormResourceFilter(datasource.DBFromCtx(ctx).Model(&application.Application{}))
|
query := in.GormResourceFilter(datasource.DBFromCtx(ctx).Model(&application.Application{}))
|
||||||
if in.Id != "" {
|
if in.Id != "" {
|
||||||
query = query.Where("id = ?", in.Id)
|
query = query.Where("id = ?", in.Id)
|
||||||
|
@ -14,6 +14,7 @@ func TestCreateApplication(t *testing.T) {
|
|||||||
req.CodeRepository = application.CodeRepository{
|
req.CodeRepository = application.CodeRepository{
|
||||||
SshUrl: "git@122.51.31.227:go-course/go18.git",
|
SshUrl: "git@122.51.31.227:go-course/go18.git",
|
||||||
}
|
}
|
||||||
|
req.SetNamespaceId(1)
|
||||||
req.SetLabel("team", "dev01.web_developer")
|
req.SetLabel("team", "dev01.web_developer")
|
||||||
ins, err := svc.CreateApplication(ctx, req)
|
ins, err := svc.CreateApplication(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -26,7 +27,8 @@ func TestCreateApplication(t *testing.T) {
|
|||||||
func TestQueryApplication(t *testing.T) {
|
func TestQueryApplication(t *testing.T) {
|
||||||
req := application.NewQueryApplicationRequest()
|
req := application.NewQueryApplicationRequest()
|
||||||
// dev01.%
|
// dev01.%
|
||||||
req.SetScope("team", []string{"%"})
|
// req.SetNamespaceId(1)
|
||||||
|
req.SetScope("team", []string{"dev01%"})
|
||||||
// req.SetScope("env", []string{"prod"})
|
// req.SetScope("env", []string{"prod"})
|
||||||
ins, err := svc.QueryApplication(ctx, req)
|
ins, err := svc.QueryApplication(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -4,6 +4,8 @@ import (
|
|||||||
"122.51.31.227/go-course/go18/devcloud/mpaas/apps/application"
|
"122.51.31.227/go-course/go18/devcloud/mpaas/apps/application"
|
||||||
"github.com/infraboard/mcube/v2/ioc"
|
"github.com/infraboard/mcube/v2/ioc"
|
||||||
"github.com/infraboard/mcube/v2/ioc/config/datasource"
|
"github.com/infraboard/mcube/v2/ioc/config/datasource"
|
||||||
|
"github.com/infraboard/mcube/v2/ioc/config/log"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -14,9 +16,13 @@ var _ application.Service = (*ApplicationServiceImpl)(nil)
|
|||||||
|
|
||||||
type ApplicationServiceImpl struct {
|
type ApplicationServiceImpl struct {
|
||||||
ioc.ObjectImpl
|
ioc.ObjectImpl
|
||||||
|
|
||||||
|
log *zerolog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *ApplicationServiceImpl) Init() error {
|
func (i *ApplicationServiceImpl) Init() error {
|
||||||
|
i.log = log.Sub(i.Name())
|
||||||
|
|
||||||
if datasource.Get().AutoMigrate {
|
if datasource.Get().AutoMigrate {
|
||||||
err := datasource.DB().AutoMigrate(&application.Application{})
|
err := datasource.DB().AutoMigrate(&application.Application{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package apps
|
package apps
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "122.51.31.227/go-course/go18/devcloud/mpaas/apps/application/api"
|
||||||
_ "122.51.31.227/go-course/go18/devcloud/mpaas/apps/application/impl"
|
_ "122.51.31.227/go-course/go18/devcloud/mpaas/apps/application/impl"
|
||||||
)
|
)
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
// 要注册哪些对象, Book, Comment
|
// 要注册哪些对象, Book, Comment
|
||||||
|
|
||||||
// 加载的业务对象
|
// 加载的业务对象
|
||||||
|
_ "122.51.31.227/go-course/go18/devcloud/mcenter/apps"
|
||||||
_ "122.51.31.227/go-course/go18/devcloud/mpaas/apps"
|
_ "122.51.31.227/go-course/go18/devcloud/mpaas/apps"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user