mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-19 02:37:24 +08:00
fix: bugs in scope support
This commit is contained in:
@@ -19,41 +19,18 @@ import (
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type GroupListOptions struct {
|
||||
Admin bool `help:"admin mode"`
|
||||
Name string `help:"Name of the groups to filter"`
|
||||
Domain string `help:"Domain to filter"`
|
||||
Limit int64 `help:"Items per page" default:"20"`
|
||||
Offset int64 `help:"Offset"`
|
||||
Search string `help:"search text"`
|
||||
options.BaseListOptions
|
||||
Name string `help:"Filter by name"`
|
||||
}
|
||||
R(&GroupListOptions{}, "group-list", "List groups", func(s *mcclient.ClientSession, args *GroupListOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
if len(args.Name) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Name), "name")
|
||||
}
|
||||
if len(args.Domain) > 0 {
|
||||
domainId, e := modules.Domains.GetId(s, args.Domain, nil)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
params.Add(jsonutils.NewString(domainId), "domain_id")
|
||||
params.Add(jsonutils.JSONTrue, "admin")
|
||||
}
|
||||
if args.Admin {
|
||||
params.Add(jsonutils.JSONTrue, "admin")
|
||||
}
|
||||
if args.Limit > 0 {
|
||||
params.Add(jsonutils.NewInt(args.Limit), "limit")
|
||||
}
|
||||
if args.Offset > 0 {
|
||||
params.Add(jsonutils.NewInt(args.Offset), "offset")
|
||||
}
|
||||
if len(args.Search) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Search), "name__icontains")
|
||||
params, err := options.ListStructToParams(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.Groups.List(s, params)
|
||||
if err != nil {
|
||||
|
||||
@@ -40,6 +40,7 @@ func init() {
|
||||
Type string `help:"filter by type"`
|
||||
Format string `help:"policy format, default to yaml" default:"yaml" choices:"yaml|json"`
|
||||
Admin bool `help:"admin mode"`
|
||||
Scope string `help:""`
|
||||
}
|
||||
R(&PolicyListOptions{}, "policy-list", "List all policies", func(s *mcclient.ClientSession, args *PolicyListOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
@@ -136,6 +137,27 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type PolicyPerformOptions struct {
|
||||
ID string `help:"ID of policy to update"`
|
||||
}
|
||||
R(&PolicyPerformOptions{}, "policy-public", "Mark a policy public", func(s *mcclient.ClientSession, args *PolicyPerformOptions) error {
|
||||
result, err := modules.Policies.PerformAction(s, args.ID, "public", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&PolicyPerformOptions{}, "policy-private", "Mark a policy private", func(s *mcclient.ClientSession, args *PolicyPerformOptions) error {
|
||||
result, err := modules.Policies.PerformAction(s, args.ID, "private", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type PolicyDeleteOptions struct {
|
||||
ID string `help:"ID of policy"`
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@ type GeneralUsageOptions struct {
|
||||
Provider []string `help:"Provider" choices:"VMware|Aliyun|Azure|Aws|Qcloud|Huawei|OpenStack|Ucloud|ZStack"`
|
||||
Project string `help:"show usage of specified project"`
|
||||
Domain string `help:"show usage of specified domain"`
|
||||
CloudEnv string `help:"show usage of specified cloudenv, e.g public_cloud/private_cloud/on_premise" choices:"public|private|onpremise"`
|
||||
CloudEnv string `help:"show usage of specified cloudenv, e.g. public_cloud/private_cloud/on_premise" choices:"public|private|onpremise"`
|
||||
Scope string `help:"show usage of specified privilege scope, e.g. system/domain/project" choices:"system|domain|project"`
|
||||
}
|
||||
|
||||
func fetchHostTypeOptions(args *GeneralUsageOptions) *jsonutils.JSONDict {
|
||||
@@ -51,6 +52,9 @@ func init() {
|
||||
} else if args.Domain != "" {
|
||||
params.Add(jsonutils.NewString(args.Domain), "domain")
|
||||
}
|
||||
if len(args.Scope) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Scope), "scope")
|
||||
}
|
||||
result, err := modules.Usages.GetGeneralUsage(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -19,56 +19,18 @@ import (
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type UserListOptions struct {
|
||||
System bool `help:"system mode"`
|
||||
Admin bool `help:"admin mode"`
|
||||
Domain string `help:"Filter by domain"`
|
||||
Name string `help:"Filter by name"`
|
||||
Limit int64 `help:"Limit, default 0, i.e. no limit"`
|
||||
Offset int64 `help:"Offset, default 0, i.e. no offset"`
|
||||
Search string `help:"Search by name"`
|
||||
DefaultProject string `help:"Filter by default_project_id"`
|
||||
NoDefaultProject bool `help:"Filter users without valid default_project_id"`
|
||||
options.BaseListOptions
|
||||
Name string `help:"Filter by name"`
|
||||
}
|
||||
R(&UserListOptions{}, "user-list", "List users", func(s *mcclient.ClientSession, args *UserListOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
if len(args.Domain) > 0 {
|
||||
domainId, err := modules.Domains.GetId(s, args.Domain, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params.Add(jsonutils.NewString(domainId), "domain_id")
|
||||
params.Add(jsonutils.JSONTrue, "admin")
|
||||
}
|
||||
if args.Admin {
|
||||
params.Add(jsonutils.JSONTrue, "admin")
|
||||
}
|
||||
if args.System {
|
||||
params.Add(jsonutils.JSONTrue, "system")
|
||||
}
|
||||
if len(args.Name) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Name), "name")
|
||||
}
|
||||
if len(args.Search) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Search), "name__icontains")
|
||||
}
|
||||
if args.Limit > 0 {
|
||||
params.Add(jsonutils.NewInt(args.Limit), "limit")
|
||||
}
|
||||
if args.Offset > 0 {
|
||||
params.Add(jsonutils.NewInt(args.Offset), "offset")
|
||||
}
|
||||
if len(args.DefaultProject) > 0 {
|
||||
projId, err := modules.Projects.GetId(s, args.DefaultProject, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params.Add(jsonutils.NewString(projId), "default_project_id")
|
||||
} else if args.NoDefaultProject {
|
||||
params.Add(jsonutils.NewString(""), "default_project_id__iempty")
|
||||
params, err := options.ListStructToParams(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.UsersV3.List(s, params)
|
||||
if err != nil {
|
||||
|
||||
@@ -36,8 +36,13 @@ func (manager *SDomainizedResourceBaseManager) ResourceScope() rbacutils.TRbacSc
|
||||
}
|
||||
|
||||
func (manager *SDomainizedResourceBaseManager) FilterByOwner(q *sqlchemy.SQuery, owner mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
|
||||
if owner != nil && len(owner.GetProjectDomainId()) > 0 {
|
||||
q = q.Equals("domain_id", owner.GetProjectDomainId())
|
||||
if owner != nil {
|
||||
switch scope {
|
||||
case rbacutils.ScopeDomain:
|
||||
if len(owner.GetProjectDomainId()) > 0 {
|
||||
q = q.Equals("domain_id", owner.GetProjectDomainId())
|
||||
}
|
||||
}
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
+32
-49
@@ -255,7 +255,7 @@ func FetchProjectInfo(ctx context.Context, data jsonutils.JSONObject) (mcclient.
|
||||
}
|
||||
return &ownerId, nil
|
||||
}
|
||||
return nil, nil
|
||||
return FetchDomainInfo(ctx, data)
|
||||
}
|
||||
|
||||
func FetchDomainInfo(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
|
||||
@@ -284,6 +284,10 @@ func (m *sUsageManager) ResourceScope() rbacutils.TRbacScope {
|
||||
return rbacutils.ScopeProject
|
||||
}
|
||||
|
||||
func (m *sUsageManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
|
||||
return FetchProjectInfo(ctx, data)
|
||||
}
|
||||
|
||||
func FetchUsageOwnerScope(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) (mcclient.IIdentityProvider, rbacutils.TRbacScope, error) {
|
||||
return FetchQueryOwnerScope(ctx, userCred, data, &sUsageManager{}, policy.PolicyActionGet)
|
||||
}
|
||||
@@ -291,6 +295,7 @@ func FetchUsageOwnerScope(ctx context.Context, userCred mcclient.TokenCredential
|
||||
type IScopedResourceManager interface {
|
||||
KeywordPlural() string
|
||||
ResourceScope() rbacutils.TRbacScope
|
||||
FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error)
|
||||
}
|
||||
|
||||
func FetchQueryOwnerScope(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject, manager IScopedResourceManager, action string) (mcclient.IIdentityProvider, rbacutils.TRbacScope, error) {
|
||||
@@ -315,65 +320,43 @@ func FetchQueryOwnerScope(ctx context.Context, userCred mcclient.TokenCredential
|
||||
}
|
||||
}
|
||||
|
||||
ownerId, err := FetchProjectInfo(ctx, data)
|
||||
// var ownerId mcclient.IIdentityProvider
|
||||
// var err error
|
||||
|
||||
ownerId, err := manager.FetchOwnerId(ctx, data)
|
||||
if err != nil {
|
||||
return nil, queryScope, err
|
||||
}
|
||||
if ownerId != nil {
|
||||
if resScope == rbacutils.ScopeProject {
|
||||
queryScope = rbacutils.ScopeProject
|
||||
if ownerId.GetProjectId() == userCred.GetProjectId() {
|
||||
requireScope = rbacutils.ScopeProject
|
||||
} else if ownerId.GetProjectDomainId() == userCred.GetProjectDomainId() {
|
||||
requireScope = rbacutils.ScopeDomain
|
||||
} else {
|
||||
requireScope = rbacutils.ScopeSystem
|
||||
}
|
||||
} else if resScope == rbacutils.ScopeDomain {
|
||||
queryScope = rbacutils.ScopeDomain
|
||||
if ownerId.GetProjectDomainId() == userCred.GetProjectDomainId() {
|
||||
requireScope = rbacutils.ScopeDomain
|
||||
} else {
|
||||
requireScope = rbacutils.ScopeSystem
|
||||
}
|
||||
} else {
|
||||
return nil, queryScope, httperrors.NewInputParameterError("query scope out of resource scope")
|
||||
}
|
||||
} else {
|
||||
ownerId, err = FetchUserInfo(ctx, data)
|
||||
if err != nil {
|
||||
return nil, queryScope, err
|
||||
}
|
||||
if ownerId != nil {
|
||||
if resScope == rbacutils.ScopeUser {
|
||||
queryScope = rbacutils.ScopeUser
|
||||
if ownerId.GetUserId() == userCred.GetUserId() {
|
||||
requireScope = rbacutils.ScopeUser
|
||||
switch resScope {
|
||||
case rbacutils.ScopeProject, rbacutils.ScopeDomain:
|
||||
if len(ownerId.GetProjectId()) > 0 {
|
||||
queryScope = rbacutils.ScopeProject
|
||||
if ownerId.GetProjectId() == userCred.GetProjectId() {
|
||||
requireScope = rbacutils.ScopeProject
|
||||
} else if ownerId.GetProjectDomainId() == userCred.GetProjectDomainId() {
|
||||
requireScope = rbacutils.ScopeDomain
|
||||
} else {
|
||||
requireScope = rbacutils.ScopeSystem
|
||||
}
|
||||
} else {
|
||||
return nil, queryScope, httperrors.NewInputParameterError("query scope out of resource scope")
|
||||
}
|
||||
} else {
|
||||
ownerId, err = FetchDomainInfo(ctx, data)
|
||||
if err != nil {
|
||||
return nil, queryScope, err
|
||||
}
|
||||
if ownerId != nil {
|
||||
if resScope == rbacutils.ScopeDomain {
|
||||
queryScope = rbacutils.ScopeDomain
|
||||
if ownerId.GetProjectDomainId() == userCred.GetProjectDomainId() {
|
||||
requireScope = rbacutils.ScopeDomain
|
||||
} else {
|
||||
requireScope = rbacutils.ScopeSystem
|
||||
}
|
||||
} else if len(ownerId.GetProjectDomainId()) > 0 {
|
||||
queryScope = rbacutils.ScopeDomain
|
||||
if ownerId.GetProjectDomainId() == userCred.GetProjectDomainId() {
|
||||
requireScope = rbacutils.ScopeDomain
|
||||
} else {
|
||||
return nil, queryScope, httperrors.NewInputParameterError("query scope out of resource scope")
|
||||
requireScope = rbacutils.ScopeSystem
|
||||
}
|
||||
}
|
||||
case rbacutils.ScopeUser:
|
||||
queryScope = rbacutils.ScopeUser
|
||||
if ownerId.GetUserId() == userCred.GetUserId() {
|
||||
requireScope = rbacutils.ScopeUser
|
||||
} else {
|
||||
requireScope = rbacutils.ScopeSystem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ownerId == nil {
|
||||
ownerId = userCred
|
||||
reqScopeStr, _ := data.GetString("scope")
|
||||
@@ -391,7 +374,7 @@ func FetchQueryOwnerScope(ctx context.Context, userCred mcclient.TokenCredential
|
||||
requireScope = queryScope
|
||||
}
|
||||
if requireScope.HigherThan(allowScope) {
|
||||
return nil, scope, httperrors.NewForbiddenError("not enough privilleges")
|
||||
return nil, scope, httperrors.NewForbiddenError(fmt.Sprintf("not enough privilleges(require:%s,allow:%s:query:%s)", requireScope, allowScope, queryScope))
|
||||
}
|
||||
return ownerId, queryScope, nil
|
||||
}
|
||||
|
||||
@@ -35,11 +35,11 @@ func RegisterModelManager(modelMan IModelManager) {
|
||||
|
||||
func mustCheckModelManager(modelMan IModelManager) {
|
||||
allowedTags := map[string][]string{
|
||||
"create": {"required", "optional", "admin_required", "admin_optional"},
|
||||
"search": {"user", "admin"},
|
||||
"get": {"user", "admin"},
|
||||
"list": {"user", "admin"},
|
||||
"update": {"user", "admin"},
|
||||
"create": {"required", "optional", "domain_required", "domain_optional", "admin_required", "admin_optional"},
|
||||
"search": {"user", "domain", "admin"},
|
||||
"get": {"user", "domain", "admin"},
|
||||
"list": {"user", "domain", "admin"},
|
||||
"update": {"user", "domain", "admin"},
|
||||
}
|
||||
for _, col := range modelMan.TableSpec().Columns() {
|
||||
tags := col.Tags()
|
||||
|
||||
@@ -64,9 +64,5 @@ func (manager *SProjectizedResourceBaseManager) ResourceScope() rbacutils.TRbacS
|
||||
}
|
||||
|
||||
func (manager *SProjectizedResourceBaseManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
|
||||
ownerId, err := FetchProjectInfo(ctx, data)
|
||||
if err == nil && ownerId == nil {
|
||||
ownerId, err = FetchDomainInfo(ctx, data)
|
||||
}
|
||||
return nil, nil
|
||||
return FetchProjectInfo(ctx, data)
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
@@ -56,6 +57,10 @@ func (manager *SQuotaManager) ResourceScope() rbacutils.TRbacScope {
|
||||
return rbacutils.ScopeProject
|
||||
}
|
||||
|
||||
func (manager *SQuotaManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
|
||||
return db.FetchProjectInfo(ctx, data)
|
||||
}
|
||||
|
||||
func (manager *SQuotaManager) Keyword() string {
|
||||
return manager.keyword
|
||||
}
|
||||
|
||||
@@ -21,10 +21,6 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
)
|
||||
|
||||
func getListRbacAllowedScope(manager IModelManager, userCred mcclient.TokenCredential) rbacutils.TRbacScope {
|
||||
return policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionList)
|
||||
}
|
||||
|
||||
func isObjectRbacAllowed(model IModel, userCred mcclient.TokenCredential, action string, extra ...string) bool {
|
||||
manager := model.GetModelManager()
|
||||
objOwnerId := model.GetOwnerId()
|
||||
@@ -46,6 +42,12 @@ func isObjectRbacAllowed(model IModel, userCred mcclient.TokenCredential, action
|
||||
} else {
|
||||
requireScope = rbacutils.ScopeSystem
|
||||
}
|
||||
case rbacutils.ScopeUser:
|
||||
if ownerId != nil && ownerId.GetUserId() == objOwnerId.GetUserId() {
|
||||
requireScope = rbacutils.ScopeUser
|
||||
} else {
|
||||
requireScope = rbacutils.ScopeSystem
|
||||
}
|
||||
default:
|
||||
// objOwnerId should not be nil
|
||||
if ownerId != nil && (ownerId.GetProjectId() == objOwnerId.GetProjectId() || (model.IsSharable() && action == policy.PolicyActionGet)) {
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
)
|
||||
@@ -29,8 +30,8 @@ import (
|
||||
type SSharableVirtualResourceBase struct {
|
||||
SVirtualResourceBase
|
||||
|
||||
IsPublic bool `default:"false" nullable:"false" index:"true" create:"admin_optional" list:"user" update:"admin"`
|
||||
PublicScope string `width:"16" charset:"ascii" nullable:"false" default:"system" create:"admin_optional" list:"user" update:"admin"`
|
||||
IsPublic bool `default:"false" nullable:"false" create:"domain_optional" list:"user"`
|
||||
PublicScope string `width:"16" charset:"ascii" nullable:"false" default:"system" create:"domain_optional" list:"user"`
|
||||
}
|
||||
|
||||
type SSharableVirtualResourceBaseManager struct {
|
||||
@@ -90,13 +91,12 @@ func (model *SSharableVirtualResourceBase) AllowPerformPublic(ctx context.Contex
|
||||
return IsAllowPerform(rbacutils.ScopeSystem, userCred, model, "public")
|
||||
}
|
||||
|
||||
func (model *SSharableVirtualResourceBase) AllowPerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return IsAllowPerform(rbacutils.ScopeSystem, userCred, model, "private")
|
||||
}
|
||||
|
||||
func (model *SSharableVirtualResourceBase) PerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
scope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), model.GetModelManager().KeywordPlural(), policy.PolicyActionPerform, "public")
|
||||
if !scope.HigherThan(rbacutils.ScopeProject) {
|
||||
return nil, httperrors.NewForbiddenError("not enough privilege")
|
||||
}
|
||||
if !model.IsPublic {
|
||||
scope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), model.GetModelManager().KeywordPlural(), "public")
|
||||
diff, err := Update(model, func() error {
|
||||
model.IsPublic = true
|
||||
model.PublicScope = string(scope)
|
||||
@@ -110,7 +110,15 @@ func (model *SSharableVirtualResourceBase) PerformPublic(ctx context.Context, us
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (model *SSharableVirtualResourceBase) AllowPerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return IsAllowPerform(rbacutils.ScopeSystem, userCred, model, "private")
|
||||
}
|
||||
|
||||
func (model *SSharableVirtualResourceBase) PerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
scope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), model.GetModelManager().KeywordPlural(), policy.PolicyActionPerform, "private")
|
||||
if !scope.HigherThan(rbacutils.ScopeProject) {
|
||||
return nil, httperrors.NewForbiddenError("not enough privilege")
|
||||
}
|
||||
if model.IsPublic {
|
||||
diff, err := Update(model, func() error {
|
||||
model.IsPublic = false
|
||||
|
||||
@@ -103,7 +103,10 @@ func (manager *SVirtualResourceBaseManager) FilterBySystemAttributes(q *sqlchemy
|
||||
q = q.Filter(sqlchemy.OR(sqlchemy.IsNull(q.Field("is_system")), sqlchemy.IsFalse(q.Field("is_system"))))
|
||||
}
|
||||
|
||||
pendingDelete, _ := query.GetString("pending_delete")
|
||||
var pendingDelete string
|
||||
if query != nil {
|
||||
pendingDelete, _ = query.GetString("pending_delete")
|
||||
}
|
||||
pendingDeleteLower := strings.ToLower(pendingDelete)
|
||||
if pendingDeleteLower == "all" || pendingDeleteLower == "any" || utils.ToBool(pendingDeleteLower) {
|
||||
var isAllow bool
|
||||
|
||||
@@ -88,6 +88,8 @@ func parseJsonPolicy(obj jsonutils.JSONObject) (string, *rbacutils.SRbacPolicy,
|
||||
return "", nil, errors.Wrap(err, "missing domain_id")
|
||||
}
|
||||
|
||||
isPublic := jsonutils.QueryBoolean(obj, "is_public", false)
|
||||
|
||||
blob, err := obj.Get("policy")
|
||||
if err != nil {
|
||||
log.Errorf("get blob error %s", err)
|
||||
@@ -102,6 +104,7 @@ func parseJsonPolicy(obj jsonutils.JSONObject) (string, *rbacutils.SRbacPolicy,
|
||||
}
|
||||
|
||||
policy.DomainId = domainId
|
||||
policy.IsPublic = isPublic
|
||||
|
||||
return typeStr, &policy, nil
|
||||
}
|
||||
@@ -117,6 +120,7 @@ func remotePolicyFetcher() (map[rbacutils.TRbacScope]map[string]*rbacutils.SRbac
|
||||
params.Add(jsonutils.NewInt(2048), "limit")
|
||||
params.Add(jsonutils.NewInt(int64(offset)), "offset")
|
||||
params.Add(jsonutils.JSONTrue, "admin")
|
||||
params.Add(jsonutils.JSONTrue, "enabled")
|
||||
result, err := modules.Policies.List(s, params)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "modules.Policies.List")
|
||||
|
||||
@@ -67,37 +67,37 @@ type SCloudaccount struct {
|
||||
db.SDomainizedResourceBase
|
||||
|
||||
SSyncableBaseResource
|
||||
LastAutoSync time.Time `list:"admin"`
|
||||
LastAutoSync time.Time `list:"domain"`
|
||||
|
||||
AccessUrl string `width:"64" charset:"ascii" nullable:"true" list:"admin" update:"admin" create:"admin_optional"`
|
||||
AccessUrl string `width:"64" charset:"ascii" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
|
||||
|
||||
Account string `width:"128" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(64, charset='ascii'), nullable=False)
|
||||
Secret string `width:"256" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(256, charset='ascii'), nullable=False)
|
||||
Account string `width:"128" charset:"ascii" nullable:"false" list:"domain" create:"domain_required"` // Column(VARCHAR(64, charset='ascii'), nullable=False)
|
||||
Secret string `width:"256" charset:"ascii" nullable:"false" list:"domain" create:"domain_required"` // Column(VARCHAR(256, charset='ascii'), nullable=False)
|
||||
|
||||
// BalanceKey string `width:"256" charset:"ascii" nullable:"true" list:"admin" update:"admin" create:"admin_optional"`
|
||||
// BalanceKey string `width:"256" charset:"ascii" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
|
||||
|
||||
IsPublicCloud *bool `nullable:"false" get:"user" create:"optional" list:"user" default:"true"`
|
||||
IsOnPremise bool `nullable:"false" get:"user" create:"optional" list:"user" default:"false"`
|
||||
|
||||
Provider string `width:"64" charset:"ascii" list:"admin" create:"admin_required"`
|
||||
Provider string `width:"64" charset:"ascii" list:"domain" create:"domain_required"`
|
||||
|
||||
EnableAutoSync bool `default:"false" create:"admin_optional" list:"admin"`
|
||||
SyncIntervalSeconds int `create:"admin_optional" list:"admin" update:"admin"`
|
||||
EnableAutoSync bool `default:"false" create:"domain_optional" list:"domain"`
|
||||
SyncIntervalSeconds int `create:"domain_optional" list:"domain" update:"domain"`
|
||||
|
||||
Balance float64 `list:"admin"`
|
||||
ProbeAt time.Time `list:"admin"`
|
||||
HealthStatus string `width:"16" charset:"ascii" default:"normal" nullable:"false" list:"admin"`
|
||||
Balance float64 `list:"domain"`
|
||||
ProbeAt time.Time `list:"domain"`
|
||||
HealthStatus string `width:"16" charset:"ascii" default:"normal" nullable:"false" list:"domain"`
|
||||
|
||||
ErrorCount int `list:"admin"`
|
||||
ErrorCount int `list:"domain"`
|
||||
|
||||
AutoCreateProject bool `list:"admin" create:"admin_optional"`
|
||||
AutoCreateProject bool `list:"domain" create:"domain_optional"`
|
||||
|
||||
Version string `width:"32" charset:"ascii" nullable:"true" list:"admin"` // Column(VARCHAR(32, charset='ascii'), nullable=True)
|
||||
Sysinfo jsonutils.JSONObject `get:"admin"` // Column(JSONEncodedDict, nullable=True)
|
||||
Version string `width:"32" charset:"ascii" nullable:"true" list:"domain"` // Column(VARCHAR(32, charset='ascii'), nullable=True)
|
||||
Sysinfo jsonutils.JSONObject `get:"domain"` // Column(JSONEncodedDict, nullable=True)
|
||||
|
||||
Brand string `width:"64" charset:"utf8" nullable:"true" list:"admin" create:"optional"`
|
||||
Brand string `width:"64" charset:"utf8" nullable:"true" list:"domain" create:"optional"`
|
||||
|
||||
Options *jsonutils.JSONDict `get:"admin" create:"admin_optional" update:"admin"`
|
||||
Options *jsonutils.JSONDict `get:"domain" create:"domain_optional" update:"domain"`
|
||||
}
|
||||
|
||||
func (self *SCloudaccountManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
|
||||
@@ -19,15 +19,17 @@ import (
|
||||
"database/sql"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/util/timeutils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/util/timeutils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
)
|
||||
|
||||
type SCloudproviderregionManager struct {
|
||||
@@ -57,15 +59,15 @@ type SCloudproviderregion struct {
|
||||
|
||||
SSyncableBaseResource
|
||||
|
||||
CloudproviderId string `width:"36" charset:"ascii" nullable:"false" list:"admin"` // Column(VARCHAR(36, charset='ascii'), nullable=False)
|
||||
CloudregionId string `width:"36" charset:"ascii" nullable:"false" list:"admin"`
|
||||
CloudproviderId string `width:"36" charset:"ascii" nullable:"false" list:"domain"` // Column(VARCHAR(36, charset='ascii'), nullable=False)
|
||||
CloudregionId string `width:"36" charset:"ascii" nullable:"false" list:"domain"`
|
||||
|
||||
Enabled bool `nullable:"false" list:"admin" update:"admin"`
|
||||
Enabled bool `nullable:"false" list:"domain" update:"domain"`
|
||||
|
||||
// SyncIntervalSeconds int `list:"admin"`
|
||||
SyncResults jsonutils.JSONObject `list:"admin"`
|
||||
// SyncIntervalSeconds int `list:"domain"`
|
||||
SyncResults jsonutils.JSONObject `list:"domain"`
|
||||
|
||||
LastDeepSyncAt time.Time `list:"admin"`
|
||||
LastDeepSyncAt time.Time `list:"domain"`
|
||||
}
|
||||
|
||||
func (manager *SCloudproviderregionManager) GetMasterFieldName() string {
|
||||
|
||||
@@ -69,23 +69,23 @@ type SCloudprovider struct {
|
||||
|
||||
SSyncableBaseResource
|
||||
|
||||
HealthStatus string `width:"16" charset:"ascii" default:"normal" nullable:"false" list:"admin"` // 云端服务健康状态。例如欠费、项目冻结都属于不健康状态。
|
||||
HealthStatus string `width:"16" charset:"ascii" default:"normal" nullable:"false" list:"domain"` // 云端服务健康状态。例如欠费、项目冻结都属于不健康状态。
|
||||
// Hostname string `width:"64" charset:"ascii" nullable:"true"` // Column(VARCHAR(64, charset='ascii'), nullable=False)
|
||||
// port = Column(Integer, nullable=False)
|
||||
// Version string `width:"32" charset:"ascii" nullable:"true" list:"admin"` // Column(VARCHAR(32, charset='ascii'), nullable=True)
|
||||
// Sysinfo jsonutils.JSONObject `get:"admin"` // Column(JSONEncodedDict, nullable=True)
|
||||
// Version string `width:"32" charset:"ascii" nullable:"true" list:"domain"` // Column(VARCHAR(32, charset='ascii'), nullable=True)
|
||||
// Sysinfo jsonutils.JSONObject `get:"domain"` // Column(JSONEncodedDict, nullable=True)
|
||||
|
||||
AccessUrl string `width:"64" charset:"ascii" nullable:"true" list:"admin" update:"admin" create:"admin_optional"`
|
||||
Account string `width:"128" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(64, charset='ascii'), nullable=False)
|
||||
Secret string `width:"256" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(256, charset='ascii'), nullable=False)
|
||||
AccessUrl string `width:"64" charset:"ascii" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
|
||||
Account string `width:"128" charset:"ascii" nullable:"false" list:"domain" create:"domain_required"` // Column(VARCHAR(64, charset='ascii'), nullable=False)
|
||||
Secret string `width:"256" charset:"ascii" nullable:"false" list:"domain" create:"domain_required"` // Column(VARCHAR(256, charset='ascii'), nullable=False)
|
||||
|
||||
CloudaccountId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
|
||||
// ProjectId string `name:"tenant_id" width:"128" charset:"ascii" nullable:"true" list:"admin"`
|
||||
// ProjectId string `name:"tenant_id" width:"128" charset:"ascii" nullable:"true" list:"domain"`
|
||||
|
||||
// LastSync time.Time `get:"admin" list:"admin"` // = Column(DateTime, nullable=True)
|
||||
// LastSync time.Time `get:"domain" list:"domain"` // = Column(DateTime, nullable=True)
|
||||
|
||||
Provider string `width:"64" charset:"ascii" list:"admin" create:"admin_required"`
|
||||
Provider string `width:"64" charset:"ascii" list:"domain" create:"domain_required"`
|
||||
}
|
||||
|
||||
func (self *SCloudproviderManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
|
||||
@@ -35,9 +35,9 @@ import (
|
||||
)
|
||||
|
||||
type SSyncableBaseResource struct {
|
||||
SyncStatus string `width:"10" charset:"ascii" default:"idle" list:"admin"`
|
||||
LastSync time.Time `list:"admin"` // = Column(DateTime, nullable=True)
|
||||
LastSyncEndAt time.Time `list:"admin"`
|
||||
SyncStatus string `width:"10" charset:"ascii" default:"idle" list:"domain"`
|
||||
LastSync time.Time `list:"domain"` // = Column(DateTime, nullable=True)
|
||||
LastSyncEndAt time.Time `list:"domain"`
|
||||
}
|
||||
|
||||
func (self *SSyncableBaseResource) CanSync() bool {
|
||||
|
||||
@@ -25,11 +25,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
|
||||
@@ -23,7 +23,6 @@ import (
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
@@ -66,7 +65,7 @@ func init() {
|
||||
}
|
||||
|
||||
func (manager *SSnapshotPolicyManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
input := &compute.SSnapshotPolicyCreateInput{}
|
||||
input := &api.SSnapshotPolicyCreateInput{}
|
||||
err := data.Unmarshal(input)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("Unmarshal input failed %s", err)
|
||||
@@ -114,7 +113,7 @@ func (self *SSnapshotPolicy) StartCreateSnapshotPolicy(ctx context.Context, user
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
self.SetStatus(userCred, compute.SNAPSHOT_POLICY_DELETING, "")
|
||||
self.SetStatus(userCred, api.SNAPSHOT_POLICY_DELETING, "")
|
||||
return self.StartSnapshotPolicyDeleteTask(ctx, userCred, jsonutils.NewDict(), "")
|
||||
}
|
||||
|
||||
@@ -375,7 +374,7 @@ func (self *SSnapshotPolicy) preCheck(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data jsonutils.JSONObject,
|
||||
) ([]string, error) {
|
||||
if self.Status != compute.SNAPSHOT_POLICY_READY {
|
||||
if self.Status != api.SNAPSHOT_POLICY_READY {
|
||||
return nil, httperrors.NewInvalidStatusError("Snapshot policy status %s can't do apply", self.Status)
|
||||
}
|
||||
jsonDiskIds, err := data.Get("disks")
|
||||
|
||||
@@ -245,11 +245,14 @@ func (domain *SDomain) ValidateDeleteCondition(ctx context.Context) error {
|
||||
return domain.SStandaloneResourceBase.ValidateDeleteCondition(ctx)
|
||||
}
|
||||
|
||||
func (domain *SDomain) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
func (domain *SDomain) ValidateUpdateCondition(ctx context.Context) error {
|
||||
if domain.Id == api.DEFAULT_DOMAIN_ID {
|
||||
return nil, httperrors.NewForbiddenError("default domain is protected")
|
||||
return httperrors.NewForbiddenError("default domain is protected")
|
||||
}
|
||||
return domain.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
if domain.IsReadOnly() {
|
||||
return httperrors.NewForbiddenError("readonly")
|
||||
}
|
||||
return domain.SStandaloneResourceBase.ValidateUpdateCondition(ctx)
|
||||
}
|
||||
|
||||
/*func (domain *SDomain) isReadOnly() bool {
|
||||
|
||||
@@ -66,7 +66,7 @@ func init() {
|
||||
type SGroup struct {
|
||||
SIdentityBaseResource
|
||||
|
||||
Displayname string `with:"128" charset:"utf8" nullable:"true" list:"admin" update:"admin" create:"admin_optional"`
|
||||
Displayname string `with:"128" charset:"utf8" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
|
||||
}
|
||||
|
||||
func (manager *SGroupManager) GetContextManagers() [][]db.IModelManager {
|
||||
@@ -209,8 +209,11 @@ func (manager *SGroupManager) RegisterExternalGroup(ctx context.Context, idpId s
|
||||
return &group, nil
|
||||
}
|
||||
|
||||
func (group *SGroup) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return group.SIdentityBaseResource.ValidateUpdateData(ctx, userCred, query, data)
|
||||
func (group *SGroup) ValidateUpdateCondition(ctx context.Context) error {
|
||||
if group.IsReadOnly() {
|
||||
return httperrors.NewForbiddenError("readonly")
|
||||
}
|
||||
return group.SIdentityBaseResource.ValidateUpdateCondition(ctx)
|
||||
}
|
||||
|
||||
func (manager *SGroupManager) fetchGroupById(gid string) *SGroup {
|
||||
|
||||
@@ -77,7 +77,7 @@ func NewEnabledIdentityBaseResourceManager(dt interface{}, tableName string, key
|
||||
type SEnabledIdentityBaseResource struct {
|
||||
SIdentityBaseResource
|
||||
|
||||
Enabled tristate.TriState `nullable:"false" default:"true" list:"admin" update:"admin" create:"admin_optional"`
|
||||
Enabled tristate.TriState `nullable:"false" default:"true" list:"user" update:"domain" create:"domain_optional"`
|
||||
}
|
||||
|
||||
func (model *SIdentityBaseResource) GetIIdentityModelManager() IIdentityModelManager {
|
||||
@@ -197,23 +197,15 @@ func (model *SIdentityBaseResource) CustomizeCreate(ctx context.Context, userCre
|
||||
return model.SStandaloneResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
|
||||
}
|
||||
|
||||
/*
|
||||
func (self *SIdentityBaseResource) ValidateDeleteCondition(ctx context.Context) error {
|
||||
// domain := self.GetDomain()
|
||||
// if self.GetIIdentityModelManager().IsDomainReadonly(domain) {
|
||||
// return httperrors.NewForbiddenError("readonly domain")
|
||||
// }
|
||||
return self.SStandaloneResourceBase.ValidateDeleteCondition(ctx)
|
||||
}
|
||||
|
||||
func (self *SIdentityBaseResource) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
// if data.Contains("name") {
|
||||
// domain := self.GetDomain()
|
||||
// if self.GetIIdentityModelManager().IsDomainReadonly(domain) {
|
||||
// return nil, httperrors.NewForbiddenError("cannot update name in readonly domain")
|
||||
// }
|
||||
// }
|
||||
return self.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
}
|
||||
*/
|
||||
|
||||
func (self *SEnabledIdentityBaseResource) ValidateDeleteCondition(ctx context.Context) error {
|
||||
if self.Enabled.IsTrue() {
|
||||
|
||||
@@ -19,11 +19,14 @@ import (
|
||||
"database/sql"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
policyman "yunion.io/x/onecloud/pkg/cloudcommon/policy"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
)
|
||||
|
||||
type SPolicyManager struct {
|
||||
@@ -58,8 +61,10 @@ func init() {
|
||||
type SPolicy struct {
|
||||
SEnabledIdentityBaseResource
|
||||
|
||||
Type string `width:"255" charset:"utf8" nullable:"false" list:"user" update:"admin"`
|
||||
Blob jsonutils.JSONObject `nullable:"false" list:"user" update:"admin"`
|
||||
Type string `width:"255" charset:"utf8" nullable:"false" list:"user" update:"domain"`
|
||||
Blob jsonutils.JSONObject `nullable:"false" list:"user" update:"domain"`
|
||||
|
||||
IsPublic bool `default:"false" nullable:"false" list:"user"`
|
||||
}
|
||||
|
||||
func (manager *SPolicyManager) InitializeData() error {
|
||||
@@ -100,9 +105,48 @@ func (manager *SPolicyManager) ValidateCreateData(ctx context.Context, userCred
|
||||
if !data.Contains("name") {
|
||||
data.Set("name", jsonutils.NewString(typeStr))
|
||||
}
|
||||
blobJson, err := data.Get("blob")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid policy data")
|
||||
}
|
||||
policy := rbacutils.SRbacPolicy{}
|
||||
err = policy.Decode(blobJson)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("fail to decode policy data")
|
||||
}
|
||||
if policy.IsSystemWidePolicy() && policyman.PolicyManager.Allow(rbacutils.ScopeSystem, userCred, consts.GetServiceType(), manager.KeywordPlural(), policyman.PolicyActionCreate) == rbacutils.Deny {
|
||||
return nil, httperrors.NewNotSufficientPrivilegeError("not allow to create system-wide policy")
|
||||
}
|
||||
return manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
|
||||
}
|
||||
|
||||
func (policy *SPolicy) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
if data.Contains("blob") {
|
||||
blobJson, err := data.Get("blob")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid policy data")
|
||||
}
|
||||
p := rbacutils.SRbacPolicy{}
|
||||
err = p.Decode(blobJson)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("fail to decode policy data")
|
||||
}
|
||||
if p.IsSystemWidePolicy() && policyman.PolicyManager.Allow(rbacutils.ScopeSystem, userCred, consts.GetServiceType(), policy.GetModelManager().KeywordPlural(), policyman.PolicyActionUpdate) == rbacutils.Deny {
|
||||
return nil, httperrors.NewNotSufficientPrivilegeError("not allow to update system-wide policy")
|
||||
}
|
||||
}
|
||||
if data.Contains("type") {
|
||||
typeStr, _ := data.GetString("type")
|
||||
if len(typeStr) == 0 {
|
||||
return nil, httperrors.NewInputParameterError("empty name")
|
||||
}
|
||||
if len(typeStr) > 0 {
|
||||
data.Set("name", jsonutils.NewString(typeStr))
|
||||
}
|
||||
}
|
||||
return policy.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
}
|
||||
|
||||
func (policy *SPolicy) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
policy.SStandaloneResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
|
||||
policyman.PolicyManager.SyncOnce()
|
||||
@@ -117,3 +161,75 @@ func (policy *SPolicy) PostDelete(ctx context.Context, userCred mcclient.TokenCr
|
||||
policy.SStandaloneResourceBase.PostDelete(ctx, userCred)
|
||||
policyman.PolicyManager.SyncOnce()
|
||||
}
|
||||
|
||||
func (policy *SPolicy) AllowPerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsAllowPerform(rbacutils.ScopeSystem, userCred, policy, "public")
|
||||
}
|
||||
|
||||
func (policy *SPolicy) PerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if policy.IsPublic {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
scope := policyman.PolicyManager.AllowScope(userCred, consts.GetServiceType(), policy.GetModelManager().KeywordPlural(), policyman.PolicyActionPerform, "public")
|
||||
if scope != rbacutils.ScopeSystem {
|
||||
return nil, httperrors.NewForbiddenError("not enough privilege")
|
||||
}
|
||||
|
||||
p := rbacutils.SRbacPolicy{}
|
||||
err := p.Decode(policy.Blob)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("fail to decode policy data")
|
||||
}
|
||||
if !p.IsSystemWidePolicy() {
|
||||
return nil, httperrors.NewInvalidStatusError("only system-wide policy (no roles and projects constraints) is sharable")
|
||||
}
|
||||
|
||||
diff, err := db.Update(policy, func() error {
|
||||
policy.IsPublic = true
|
||||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
db.OpsLog.LogEvent(policy, db.ACT_UPDATE, diff, userCred)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (policy *SPolicy) AllowPerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsAllowPerform(rbacutils.ScopeSystem, userCred, policy, "private")
|
||||
}
|
||||
|
||||
func (policy *SPolicy) PerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if !policy.IsPublic {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
scope := policyman.PolicyManager.AllowScope(userCred, consts.GetServiceType(), policy.GetModelManager().KeywordPlural(), policyman.PolicyActionPerform, "private")
|
||||
if scope != rbacutils.ScopeSystem {
|
||||
return nil, httperrors.NewForbiddenError("not enough privilege")
|
||||
}
|
||||
|
||||
diff, err := db.Update(policy, func() error {
|
||||
policy.IsPublic = false
|
||||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
db.OpsLog.LogEvent(policy, db.ACT_UPDATE, diff, userCred)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (manager *SPolicyManager) FilterByOwner(q *sqlchemy.SQuery, owner mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
|
||||
if owner != nil {
|
||||
switch scope {
|
||||
case rbacutils.ScopeDomain:
|
||||
if len(owner.GetProjectDomainId()) > 0 {
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.Equals(q.Field("domain_id"), owner.GetProjectDomainId()),
|
||||
sqlchemy.IsTrue(q.Field("is_public")),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
@@ -19,10 +19,9 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/tristate"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
@@ -66,16 +65,12 @@ func init() {
|
||||
+-------------+-------------+------+-----+---------+-------+
|
||||
*/
|
||||
|
||||
type SBaseProject struct {
|
||||
type SProject struct {
|
||||
SIdentityBaseResource
|
||||
|
||||
ParentId string `width:"64" charset:"ascii" list:"admin" create:"admin_optional"`
|
||||
ParentId string `width:"64" charset:"ascii" list:"domain" create:"domain_optional"`
|
||||
|
||||
IsDomain tristate.TriState `default:"false" nullable:"false" create:"admin_optional"`
|
||||
}
|
||||
|
||||
type SProject struct {
|
||||
SBaseProject
|
||||
IsDomain tristate.TriState `default:"false" nullable:"false" create:"domain_optional"`
|
||||
}
|
||||
|
||||
func (manager *SProjectManager) GetContextManagers() [][]db.IModelManager {
|
||||
@@ -244,7 +239,7 @@ func (manager *SProjectManager) ListItemFilter(ctx context.Context, q *sqlchemy.
|
||||
func (model *SProject) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
model.ParentId = ownerId.GetProjectDomainId()
|
||||
model.IsDomain = tristate.False
|
||||
return model.SBaseProject.CustomizeCreate(ctx, userCred, ownerId, query, data)
|
||||
return model.SIdentityBaseResource.CustomizeCreate(ctx, userCred, ownerId, query, data)
|
||||
}
|
||||
|
||||
func (proj *SProject) GetUserCount() (int, error) {
|
||||
|
||||
@@ -73,22 +73,22 @@ func init() {
|
||||
type SUser struct {
|
||||
SEnabledIdentityBaseResource
|
||||
|
||||
Email string `width:"64" charset:"ascii" nullable:"true" index:"true" list:"admin" update:"admin" create:"admin_optional"`
|
||||
Mobile string `width:"20" charset:"ascii" nullable:"true" index:"true" list:"admin" update:"admin" create:"admin_optional"`
|
||||
Email string `width:"64" charset:"ascii" nullable:"true" index:"true" list:"domain" update:"domain" create:"domain_optional"`
|
||||
Mobile string `width:"20" charset:"ascii" nullable:"true" index:"true" list:"domain" update:"domain" create:"domain_optional"`
|
||||
|
||||
Displayname string `with:"128" charset:"utf8" nullable:"true" list:"admin" update:"admin" create:"admin_optional"`
|
||||
Displayname string `with:"128" charset:"utf8" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
|
||||
|
||||
LastActiveAt time.Time `nullable:"true" list:"admin"`
|
||||
LastActiveAt time.Time `nullable:"true" list:"domain"`
|
||||
|
||||
LastLoginIp string `nullable:"true" list:"admin"`
|
||||
LastLoginSource string `nullable:"true" list:"admin"`
|
||||
LastLoginIp string `nullable:"true" list:"domain"`
|
||||
LastLoginSource string `nullable:"true" list:"domain"`
|
||||
|
||||
IsSystemAccount tristate.TriState `nullable:"false" default:"false" list:"admin" update:"admin" create:"admin_optional"`
|
||||
IsSystemAccount tristate.TriState `nullable:"false" default:"false" list:"domain" update:"domain" create:"domain_optional"`
|
||||
|
||||
DefaultProjectId string `width:"64" charset:"ascii" nullable:"true"`
|
||||
|
||||
AllowWebConsole tristate.TriState `nullable:"false" default:"true" list:"admin" update:"admin" create:"admin_optional"`
|
||||
EnableMfa tristate.TriState `nullable:"false" default:"true" list:"admin" update:"admin" create:"admin_optional"`
|
||||
AllowWebConsole tristate.TriState `nullable:"false" default:"true" list:"domain" update:"domain" create:"domain_optional"`
|
||||
EnableMfa tristate.TriState `nullable:"false" default:"true" list:"domain" update:"domain" create:"domain_optional"`
|
||||
}
|
||||
|
||||
func (manager *SUserManager) GetContextManagers() [][]db.IModelManager {
|
||||
@@ -327,15 +327,21 @@ func (manager *SUserManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu
|
||||
}
|
||||
|
||||
func (user *SUser) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
if user.IsAdminUser() {
|
||||
return nil, httperrors.NewForbiddenError("system admin user is protected")
|
||||
}
|
||||
if user.IsReadOnly() {
|
||||
return nil, httperrors.NewForbiddenError("readonly")
|
||||
if data.Contains("name") {
|
||||
if user.IsAdminUser() {
|
||||
return nil, httperrors.NewForbiddenError("cannot alter sysadmin user name")
|
||||
}
|
||||
}
|
||||
return user.SEnabledIdentityBaseResource.ValidateUpdateData(ctx, userCred, query, data)
|
||||
}
|
||||
|
||||
func (user *SUser) ValidateUpdateCondition(ctx context.Context) error {
|
||||
if user.IsReadOnly() {
|
||||
return httperrors.NewForbiddenError("readonly")
|
||||
}
|
||||
return user.SEnabledIdentityBaseResource.ValidateUpdateCondition(ctx)
|
||||
}
|
||||
|
||||
func (manager *SUserManager) fetchUserById(uid string) (*SUser, error) {
|
||||
obj, err := manager.FetchById(uid)
|
||||
if err != nil {
|
||||
|
||||
@@ -24,7 +24,8 @@ func init() {
|
||||
"balance", "error_count", "health_status",
|
||||
"Sync_Status", "Last_sync",
|
||||
"guest_count", "domain", "domain_id",
|
||||
"Provider", "Enable_Auto_Sync", "Sync_Interval_Seconds"},
|
||||
"Provider", "Brand",
|
||||
"Enable_Auto_Sync", "Sync_Interval_Seconds"},
|
||||
[]string{})
|
||||
|
||||
registerCompute(&Cloudaccounts)
|
||||
|
||||
@@ -29,7 +29,7 @@ var Policies SPolicyManager
|
||||
|
||||
func policyReadFilter(session *mcclient.ClientSession, s jsonutils.JSONObject, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
ss := s.(*jsonutils.JSONDict)
|
||||
ret := ss.CopyIncludes("id", "type", "enabled", "domain_id", "domain", "can_update", "can_delete")
|
||||
ret := ss.CopyIncludes("id", "type", "enabled", "domain_id", "domain", "can_update", "can_delete", "is_public")
|
||||
blobJson, _ := ss.Get("blob")
|
||||
if blobJson != nil {
|
||||
policy := rbacutils.SRbacPolicy{}
|
||||
@@ -96,7 +96,7 @@ func policyWriteFilter(session *mcclient.ClientSession, s jsonutils.JSONObject,
|
||||
|
||||
func init() {
|
||||
Policies = SPolicyManager{NewIdentityV3Manager("policy", "policies",
|
||||
[]string{"id", "type", "policy", "enabled", "domain_id", "domain"},
|
||||
[]string{"id", "type", "policy", "enabled", "domain_id", "domain", "is_public"},
|
||||
[]string{})}
|
||||
|
||||
Policies.SetReadFilter(policyReadFilter).SetWriteFilter(policyWriteFilter).SetNameField("type")
|
||||
|
||||
@@ -90,6 +90,8 @@ type SRbacPolicy struct {
|
||||
|
||||
DomainId string
|
||||
|
||||
IsPublic bool
|
||||
|
||||
Projects []string
|
||||
Roles []string
|
||||
Ips []netutils.IPV4Prefix
|
||||
@@ -550,6 +552,10 @@ type IRbacIdentity interface {
|
||||
GetLoginIp() string
|
||||
}
|
||||
|
||||
func (policy *SRbacPolicy) IsSystemWidePolicy() bool {
|
||||
return len(policy.Roles) == 0 && len(policy.Projects) == 0
|
||||
}
|
||||
|
||||
func (policy *SRbacPolicy) Match(userCred IRbacIdentity) bool {
|
||||
if !policy.Auth && len(policy.Projects) == 0 && len(policy.Roles) == 0 && len(policy.Ips) == 0 {
|
||||
return true
|
||||
@@ -557,7 +563,10 @@ func (policy *SRbacPolicy) Match(userCred IRbacIdentity) bool {
|
||||
if userCred == nil {
|
||||
return false
|
||||
}
|
||||
if (len(policy.Projects) == 0 || (policy.DomainId == userCred.GetProjectDomainId() && contains(policy.Projects, userCred.GetProjectName()))) && (len(policy.Roles) == 0 || (policy.DomainId == userCred.GetProjectDomainId() && intersect(policy.Roles, userCred.GetRoles()))) && (len(policy.Ips) == 0 || containsIp(policy.Ips, userCred.GetLoginIp())) {
|
||||
if !policy.IsPublic && policy.DomainId != userCred.GetProjectDomainId() {
|
||||
return false
|
||||
}
|
||||
if (len(policy.Projects) == 0 || contains(policy.Projects, userCred.GetProjectName())) && (len(policy.Roles) == 0 || intersect(policy.Roles, userCred.GetRoles())) && (len(policy.Ips) == 0 || containsIp(policy.Ips, userCred.GetLoginIp())) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -169,6 +169,10 @@ func (manager *SParameterManager) NamespaceScope() rbacutils.TRbacScope {
|
||||
return rbacutils.ScopeUser
|
||||
}
|
||||
|
||||
func (manager *SParameterManager) ResourceScope() rbacutils.TRbacScope {
|
||||
return rbacutils.ScopeUser
|
||||
}
|
||||
|
||||
func (manager *SParameterManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
if !isAdminQuery(query) {
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user