Merge pull request #6668 from swordqiu/hotfix/qj-get-property-support-rbac

fix: class method GetPropertyXXX should support rbac
This commit is contained in:
yunion-ci-robot
2020-06-03 10:13:06 +08:00
committed by GitHub
5 changed files with 48 additions and 32 deletions
+2
View File
@@ -35,3 +35,5 @@ GPATH
GRTAGS
GTAGS
pkg/generated
*.orig
+11 -11
View File
@@ -17,7 +17,7 @@ package apis
type DomainizedResourceInput struct {
// 指定项目归属域名称或ID
// required: false
ProjectDomain string `json:"project_domain"`
ProjectDomain string `json:"project_domain" help:"name or id of the belonging domain"`
// swagger:ignore
// Deprecated
@@ -62,11 +62,11 @@ type ProjectizedResourceCreateInput struct {
type SharableResourceBaseCreateInput struct {
// 是否共享
// required: false
IsPublic *bool `json:"is_public"`
IsPublic *bool `json:"is_public" token:"public" negative:"private" help:"Turn on/off public/private"`
// 共享范围
// required: false
PublicScope string `json:"public_scope"`
PublicScope string `json:"public_scope" help:"set public_scope, either project, domain or system" choices:"project|domain|system"`
}
type SharableVirtualResourceCreateInput struct {
@@ -87,11 +87,11 @@ type VirtualResourceCreateInput struct {
type EnabledBaseResourceCreateInput struct {
// 该资源是否被管理员*人为*启用或者禁用
// required: false
Enabled *bool `json:"enabled"`
Enabled *bool `json:"enabled" help:"turn on enabled flag"`
// 该资源是否被管理员*人为*禁用, 和enabled互斥
// required: false
Disabled *bool `json:"disabled"`
Disabled *bool `json:"disabled" help:"turn off enabled flag"`
}
func (input *EnabledBaseResourceCreateInput) AfterUnmarshal() {
@@ -104,7 +104,7 @@ func (input *EnabledBaseResourceCreateInput) AfterUnmarshal() {
type StatusBaseResourceCreateInput struct {
// 用来存储资源的状态
// required: false
Status string `json:"status"`
Status string `json:"status" help:"set initial status"`
}
type EnabledStatusDomainLevelResourceCreateInput struct {
@@ -140,28 +140,28 @@ type StandaloneResourceCreateInput struct {
// unique: true
// required: true
// example: test-network
Name string `json:"name"`
Name string `json:"name" help:"name of newly created resource" positional:"true" required:"true"`
// 生成资源名称的模板,如果name为空,则为必填项
// description: generated resource name, given a pattern to generate name, required if name is not given
// unique: false
// required: false
// example: test###
GenerateName string `json:"generate_name"`
GenerateName string `json:"generate_name" help:"pattern for generating name if no name is given"`
// 资源描述
// required: false
// example: test create network
Description string `json:"description"`
Description string `json:"description" token:"desc" help:"description"`
// 资源是否为模拟资源
// description: the resource is an emulated resource
// required: false
IsEmulated *bool `json:"is_emulated"`
IsEmulated *bool `json:"is_emulated" token:"emulated" negative:"no_emulated" help:"set is_emulated flag"`
// 标签列表,最多支持20个
// example: { "user:rd": "op" }
Metadata map[string]string `json:"__meta__"`
Metadata map[string]string `json:"__meta__" token:"tag" help:"tags in the form of key=value"`
}
type JoinResourceBaseCreateInput struct {
+4 -4
View File
@@ -67,7 +67,7 @@ type ModelBaseListInput struct {
// 查询限制量
// default: 20
Limit *int `json:"limit"`
Limit *int `json:"limit" default:"20" help:"max items per page"`
// 查询偏移量
// default: 0
Offset *int `json:"offset"`
@@ -182,12 +182,12 @@ type StandaloneResourceListInput struct {
MetadataResourceListInput
// 显示所有的资源,包括模拟的资源
ShowEmulated *bool `json:"show_emulated"`
ShowEmulated *bool `json:"show_emulated" help:"show emulated resources" negative:"do not show emulated resources"`
// 以资源名称过滤列表
Names []string `json:"name"`
Names []string `json:"name" help:"filter by names"`
// 以资源ID过滤列表
Ids []string `json:"id"`
Ids []string `json:"id" help:"filter by ids"`
}
type StatusResourceBaseListInput struct {
+30 -16
View File
@@ -853,29 +853,43 @@ func getItemDetails(manager IModelManager, item IModel, ctx context.Context, use
}
func (dispatcher *DBModelDispatcher) tryGetModelProperty(ctx context.Context, property string, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
userCred := fetchUserCredential(ctx)
funcName := fmt.Sprintf("GetProperty%s", utils.Kebab2Camel(property, "-"))
allowFuncName := "Allow" + funcName
modelValue := reflect.ValueOf(dispatcher.modelManager)
params := []interface{}{ctx, userCred, query}
funcValue := modelValue.MethodByName(allowFuncName)
if consts.IsRbacEnabled() {
ownerId, err := fetchOwnerId(ctx, dispatcher.modelManager, userCred, query)
if err != nil {
return nil, httperrors.NewGeneralError(err)
}
err = isClassRbacAllowed(dispatcher.modelManager, userCred, ownerId, policy.PolicyActionList, property)
if err != nil {
return nil, err
}
} else {
funcValue := modelValue.MethodByName(allowFuncName)
if !funcValue.IsValid() || funcValue.IsNil() {
return nil, nil
}
outs, err := callFunc(funcValue, allowFuncName, params...)
if err != nil {
return nil, httperrors.NewInternalServerError("reflect call %s fail %s", allowFuncName, err)
}
if len(outs) != 1 {
return nil, httperrors.NewInternalServerError("Invald %s return value", funcName)
}
if !outs[0].Bool() {
return nil, httperrors.NewForbiddenError("%s not allow to get property %s", dispatcher.Keyword(), property)
}
}
funcValue := modelValue.MethodByName(funcName)
if !funcValue.IsValid() || funcValue.IsNil() {
return nil, nil
}
userCred := fetchUserCredential(ctx)
params := []interface{}{ctx, userCred, query}
outs, err := callFunc(funcValue, allowFuncName, params...)
if err != nil {
return nil, httperrors.NewInternalServerError("reflect call %s fail %s", allowFuncName, err)
}
if len(outs) != 1 {
return nil, httperrors.NewInternalServerError("Invald %s return value", funcName)
}
if !outs[0].Bool() {
return nil, httperrors.NewForbiddenError("%s not allow to get property %s", dispatcher.Keyword(), property)
}
funcValue = modelValue.MethodByName(funcName)
outs, err = callFunc(funcValue, funcName, params...)
outs, err := callFunc(funcValue, funcName, params...)
if err != nil {
return nil, httperrors.NewInternalServerError("reflect call %s fail %s", funcName, err)
}
+1 -1
View File
@@ -64,7 +64,7 @@ func (manager *SModelBaseManager) IsStandaloneManager() bool {
func (manager *SModelBaseManager) GetIModelManager() IModelManager {
virt := manager.GetVirtualObject()
if virt == nil {
panic(fmt.Sprintf("Forgot to call SetVirtualObject?"))
panic(fmt.Sprintf("[%s] Forgot to call SetVirtualObject?", manager.Keyword()))
}
r, ok := virt.(IModelManager)
if !ok {