| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package db
- import (
- "context"
- "yunion.io/x/jsonutils"
- "yunion.io/x/log"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/util/rbacscope"
- "yunion.io/x/sqlchemy"
- "yunion.io/x/onecloud/pkg/apis"
- "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/logclient"
- "yunion.io/x/onecloud/pkg/util/stringutils2"
- "yunion.io/x/onecloud/pkg/util/tagutils"
- )
- type SSharableBaseResourceManager struct{}
- func (manager *SSharableBaseResourceManager) ListItemFilter(
- ctx context.Context,
- q *sqlchemy.SQuery,
- userCred mcclient.TokenCredential,
- query apis.SharableResourceBaseListInput,
- ) (*sqlchemy.SQuery, error) {
- if query.IsPublic != nil {
- if *query.IsPublic == true {
- q = q.IsTrue("is_public")
- } else {
- q = q.IsFalse("is_public")
- }
- }
- if len(query.PublicScope) > 0 {
- q = q.Equals("public_scope", query.PublicScope)
- }
- return q, nil
- }
- func (manager *SSharableBaseResourceManager) FetchCustomizeColumns(
- ctx context.Context,
- userCred mcclient.TokenCredential,
- query jsonutils.JSONObject,
- objs []interface{},
- fields stringutils2.SSortedStrings,
- isList bool,
- ) []apis.SharableResourceBaseInfo {
- rows := make([]apis.SharableResourceBaseInfo, len(objs))
- var resType string
- resIds := make([]string, len(rows))
- var resScope rbacscope.TRbacScope
- for i := range rows {
- if model, ok := objs[i].(ISharableBaseModel); ok {
- if len(resType) == 0 {
- resType = model.Keyword()
- }
- if len(resScope) == 0 {
- resScope = model.GetModelManager().ResourceScope()
- }
- resIds[i] = model.GetId()
- }
- }
- q := SharedResourceManager.Query()
- q = q.Equals("resource_type", resType)
- sharedResourceMap := make(map[string][]SSharedResource)
- err := FetchQueryObjectsByIds(q, "resource_id", resIds, &sharedResourceMap)
- if err != nil {
- log.Errorf("FetchQueryObjectsByIds for shared resource fail %s", err)
- return rows
- }
- targetTenantIds := stringutils2.NewSortedStrings([]string{})
- targetDomainIds := stringutils2.NewSortedStrings([]string{})
- for _, srs := range sharedResourceMap {
- for _, sr := range srs {
- switch sr.TargetType {
- case SharedTargetProject:
- targetTenantIds = stringutils2.Append(targetTenantIds, sr.TargetProjectId)
- case SharedTargetDomain:
- targetDomainIds = stringutils2.Append(targetDomainIds, sr.TargetProjectId)
- }
- }
- }
- var tenantMap map[string]STenant
- var domainMap map[string]STenant
- if len(targetTenantIds) > 0 {
- tenantMap = DefaultProjectsFetcher(ctx, targetTenantIds, false)
- }
- if len(targetDomainIds) > 0 {
- domainMap = DefaultProjectsFetcher(ctx, targetDomainIds, true)
- }
- for i := range rows {
- resId := resIds[i]
- if srs, ok := sharedResourceMap[resId]; ok {
- projects := make([]apis.SharedProject, 0)
- domains := make([]apis.SharedDomain, 0)
- for _, sr := range srs {
- switch sr.TargetType {
- case SharedTargetProject:
- project := apis.SharedProject{}
- project.Id = sr.TargetProjectId
- if tenant, ok := tenantMap[sr.TargetProjectId]; ok {
- project.Name = tenant.Name
- project.Domain = tenant.Domain
- project.DomainId = tenant.DomainId
- }
- projects = append(projects, project)
- case SharedTargetDomain:
- domain := apis.SharedDomain{}
- domain.Id = sr.TargetProjectId
- if tenant, ok := domainMap[sr.TargetProjectId]; ok {
- domain.Name = tenant.Name
- }
- domains = append(domains, domain)
- }
- }
- rows[i].SharedProjects = projects
- rows[i].SharedDomains = domains
- }
- }
- return rows
- }
- func SharableManagerValidateCreateData(
- manager IStandaloneModelManager,
- ctx context.Context,
- userCred mcclient.TokenCredential,
- ownerId mcclient.IIdentityProvider,
- query jsonutils.JSONObject,
- input apis.SharableResourceBaseCreateInput,
- ) (apis.SharableResourceBaseCreateInput, error) {
- resScope := manager.ResourceScope()
- reqScope := resScope
- isPublic := true
- switch resScope {
- case rbacscope.ScopeProject:
- if input.PublicScope == string(rbacscope.ScopeSystem) {
- input.IsPublic = &isPublic
- reqScope = rbacscope.ScopeSystem
- } else if input.PublicScope == string(rbacscope.ScopeDomain) {
- if consts.GetNonDefaultDomainProjects() {
- // only if non_default_domain_projects turned on, allow sharing to domain
- input.IsPublic = &isPublic
- reqScope = rbacscope.ScopeDomain
- } else {
- input.IsPublic = &isPublic
- reqScope = rbacscope.ScopeSystem
- }
- } else if input.IsPublic != nil && *input.IsPublic && len(input.PublicScope) == 0 {
- // backward compatible, if only is_public is true, make it share to system
- input.IsPublic = &isPublic
- input.PublicScope = string(rbacscope.ScopeSystem)
- reqScope = rbacscope.ScopeSystem
- } else {
- input.IsPublic = nil
- input.PublicScope = "" // string(rbacscope.ScopeNone)
- }
- case rbacscope.ScopeDomain:
- if consts.GetNonDefaultDomainProjects() {
- // only if non_default_domain_projects turned on, allow sharing domain resources
- if input.PublicScope == string(rbacscope.ScopeSystem) {
- input.IsPublic = &isPublic
- reqScope = rbacscope.ScopeSystem
- } else if input.IsPublic != nil && *input.IsPublic && len(input.PublicScope) == 0 {
- // backward compatible, if only is_public is true, make it share to system
- input.IsPublic = &isPublic
- input.PublicScope = string(rbacscope.ScopeSystem)
- reqScope = rbacscope.ScopeSystem
- } else {
- input.IsPublic = nil
- input.PublicScope = "" // string(rbacscope.ScopeNone)
- }
- } else {
- // if non_default_domain_projects turned off, all domain resources shared to system
- input.IsPublic = &isPublic
- input.PublicScope = string(rbacscope.ScopeSystem)
- reqScope = rbacscope.ScopeSystem
- }
- default:
- return input, errors.Wrap(httperrors.ErrInputParameter, "the resource is not sharable")
- }
- if input.IsPublic != nil && *input.IsPublic {
- // TODO: deal with policyTags
- allowScope, _ := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionPerform, "public")
- if reqScope.HigherThan(allowScope) {
- return input, errors.Wrapf(httperrors.ErrNotSufficientPrivilege, "require %s allow %s", reqScope, allowScope)
- }
- }
- return input, nil
- }
- func SharableManagerFilterByOwner(ctx context.Context, manager IStandaloneModelManager, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, owner mcclient.IIdentityProvider, scope rbacscope.TRbacScope) *sqlchemy.SQuery {
- if owner != nil {
- resScope := manager.ResourceScope()
- if resScope == rbacscope.ScopeUser {
- targetProjectId := owner.GetProjectId()
- if len(targetProjectId) == 0 && userCred != nil {
- targetProjectId = userCred.GetProjectId()
- }
- subq := SharedResourceManager.Query("resource_id")
- subq = subq.Equals("resource_type", manager.Keyword())
- subq = subq.Equals("target_project_id", targetProjectId)
- subq = subq.Equals("target_type", SharedTargetProject)
- subq2 := SharedResourceManager.Query("resource_id")
- subq2 = subq2.Equals("resource_type", manager.Keyword())
- subq2 = subq2.Equals("target_project_id", owner.GetProjectDomainId())
- subq2 = subq2.Equals("target_type", SharedTargetDomain)
- filters := []sqlchemy.ICondition{
- sqlchemy.AND(
- sqlchemy.IsTrue(q.Field("is_public")),
- sqlchemy.Equals(q.Field("public_scope"), rbacscope.ScopeSystem),
- ),
- sqlchemy.AND(
- sqlchemy.IsTrue(q.Field("is_public")),
- sqlchemy.Equals(q.Field("public_scope"), rbacscope.ScopeDomain),
- sqlchemy.OR(
- sqlchemy.In(q.Field("id"), subq2.SubQuery()),
- ),
- ),
- sqlchemy.In(q.Field("id"), subq.SubQuery()),
- }
- ownerUserId := owner.GetUserId()
- if len(ownerUserId) > 0 {
- filters = append(filters, sqlchemy.Equals(q.Field("owner_id"), ownerUserId))
- }
- q = q.Filter(sqlchemy.OR(filters...))
- if userCred != nil {
- result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionList)
- if !result.ObjectTags.IsEmpty() {
- policyTagFilters := tagutils.STagFilters{}
- policyTagFilters.AddFilters(result.ObjectTags)
- q = ObjectIdQueryWithTagFilters(ctx, q, "id", manager.Keyword(), policyTagFilters)
- }
- }
- } else if resScope == rbacscope.ScopeProject && scope == rbacscope.ScopeProject {
- ownerProjectId := owner.GetProjectId()
- if len(ownerProjectId) > 0 {
- subq := SharedResourceManager.Query("resource_id")
- subq = subq.Equals("resource_type", manager.Keyword())
- subq = subq.Equals("target_project_id", ownerProjectId)
- subq = subq.Equals("target_type", SharedTargetProject)
- subq2 := SharedResourceManager.Query("resource_id")
- subq2 = subq2.Equals("resource_type", manager.Keyword())
- subq2 = subq2.Equals("target_project_id", owner.GetProjectDomainId())
- subq2 = subq2.Equals("target_type", SharedTargetDomain)
- q = q.Filter(sqlchemy.OR(
- sqlchemy.Equals(q.Field("tenant_id"), ownerProjectId),
- sqlchemy.AND(
- sqlchemy.IsTrue(q.Field("is_public")),
- sqlchemy.Equals(q.Field("public_scope"), rbacscope.ScopeSystem),
- ),
- sqlchemy.AND(
- sqlchemy.IsTrue(q.Field("is_public")),
- sqlchemy.Equals(q.Field("public_scope"), rbacscope.ScopeDomain),
- sqlchemy.OR(
- sqlchemy.Equals(q.Field("domain_id"), owner.GetProjectDomainId()),
- sqlchemy.In(q.Field("id"), subq2.SubQuery()),
- ),
- ),
- sqlchemy.In(q.Field("id"), subq.SubQuery()),
- ))
- if userCred != nil {
- result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionList)
- if !result.ObjectTags.IsEmpty() {
- policyTagFilters := tagutils.STagFilters{}
- policyTagFilters.AddFilters(result.ObjectTags)
- q = ObjectIdQueryWithTagFilters(ctx, q, "id", manager.Keyword(), policyTagFilters)
- }
- }
- }
- } else if (resScope == rbacscope.ScopeDomain && (scope == rbacscope.ScopeProject || scope == rbacscope.ScopeDomain)) || (resScope == rbacscope.ScopeProject && scope == rbacscope.ScopeDomain) {
- // domain view
- ownerDomainId := owner.GetProjectDomainId()
- if len(ownerDomainId) > 0 {
- subq := SharedResourceManager.Query("resource_id")
- subq = subq.Equals("resource_type", manager.Keyword())
- subq = subq.Equals("target_project_id", ownerDomainId)
- subq = subq.Equals("target_type", SharedTargetDomain)
- q = q.Filter(sqlchemy.OR(
- sqlchemy.Equals(q.Field("domain_id"), ownerDomainId),
- sqlchemy.AND(
- sqlchemy.IsTrue(q.Field("is_public")),
- sqlchemy.Equals(q.Field("public_scope"), rbacscope.ScopeSystem),
- ),
- sqlchemy.AND(
- sqlchemy.IsTrue(q.Field("is_public")),
- sqlchemy.In(q.Field("id"), subq.SubQuery()),
- ),
- ))
- if userCred != nil {
- result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionList)
- if !result.ProjectTags.IsEmpty() && resScope == rbacscope.ScopeProject {
- policyTagFilters := tagutils.STagFilters{}
- policyTagFilters.AddFilters(result.ProjectTags)
- q = ObjectIdQueryWithTagFilters(ctx, q, "tenant_id", "project", policyTagFilters)
- }
- if !result.ObjectTags.IsEmpty() {
- policyTagFilters := tagutils.STagFilters{}
- policyTagFilters.AddFilters(result.ObjectTags)
- q = ObjectIdQueryWithTagFilters(ctx, q, "id", manager.Keyword(), policyTagFilters)
- }
- }
- }
- } else {
- log.Debugf("res_scope: %s view_scope: %s", resScope, scope)
- // system view
- if userCred != nil {
- result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionList)
- log.Debugf("policy result: %s", jsonutils.Marshal(result))
- if !result.DomainTags.IsEmpty() && (resScope == rbacscope.ScopeDomain || resScope == rbacscope.ScopeProject) && scope == rbacscope.ScopeSystem {
- subq := manager.Query("id")
- policyTagFilters := tagutils.STagFilters{}
- policyTagFilters.AddFilters(result.DomainTags)
- subq = ObjectIdQueryWithTagFilters(ctx, subq, "domain_id", "domain", policyTagFilters)
- q = q.Filter(sqlchemy.OR(
- sqlchemy.In(q.Field("id"), subq.SubQuery()),
- sqlchemy.AND(
- sqlchemy.IsTrue(q.Field("is_public")),
- sqlchemy.Equals(q.Field("public_scope"), rbacscope.ScopeSystem),
- ),
- ))
- }
- if !result.ProjectTags.IsEmpty() && resScope == rbacscope.ScopeProject {
- subq := manager.Query("id")
- policyTagFilters := tagutils.STagFilters{}
- policyTagFilters.AddFilters(result.ProjectTags)
- subq = ObjectIdQueryWithTagFilters(ctx, subq, "tenant_id", "project", policyTagFilters)
- q = q.Filter(sqlchemy.OR(
- sqlchemy.In(q.Field("id"), subq.SubQuery()),
- sqlchemy.AND(
- sqlchemy.IsTrue(q.Field("is_public")),
- sqlchemy.Equals(q.Field("public_scope"), rbacscope.ScopeSystem),
- ),
- ))
- }
- if !result.ObjectTags.IsEmpty() {
- policyTagFilters := tagutils.STagFilters{}
- policyTagFilters.AddFilters(result.ObjectTags)
- q = ObjectIdQueryWithTagFilters(ctx, q, "id", manager.Keyword(), policyTagFilters)
- }
- }
- }
- }
- return q
- }
- type SSharableBaseResource struct {
- // 是否共享
- IsPublic bool `default:"false" nullable:"false" list:"user" create:"domain_optional"`
- // 默认共享范围
- PublicScope string `width:"16" charset:"ascii" nullable:"false" default:"system" list:"user" create:"domain_optional"`
- // 共享设置的来源, local: 本地设置, cloud: 从云上同步过来
- // example: local
- PublicSrc string `width:"10" charset:"ascii" nullable:"true" list:"user" json:"public_src"`
- }
- type ISharableBaseModel interface {
- IStandaloneModel
- ISharableBase
- }
- type ISharableBase interface {
- SetShare(scoe rbacscope.TRbacScope)
- GetIsPublic() bool
- GetPublicScope() rbacscope.TRbacScope
- GetSharableTargetDomainIds() []string
- GetRequiredSharedDomainIds() []string
- GetSharedDomains() []string
- }
- func ISharableChangeOwnerCandidateDomainIds(model ISharableBaseModel) []string {
- var candidates []string
- if model.GetIsPublic() {
- switch model.GetPublicScope() {
- case rbacscope.ScopeSystem:
- return candidates
- case rbacscope.ScopeDomain:
- candidates = model.GetSharedDomains()
- }
- }
- ownerId := model.GetOwnerId()
- if ownerId != nil && len(ownerId.GetProjectDomainId()) > 0 {
- candidates = append(candidates, ownerId.GetProjectDomainId())
- }
- return candidates
- }
- func ISharableMergeChangeOwnerCandidateDomainIds(model ISharableBaseModel, candidates ...[]string) []string {
- var ret stringutils2.SSortedStrings
- for i := range candidates {
- if len(candidates[i]) > 0 {
- cand := stringutils2.NewSortedStrings(candidates[i])
- ownerId := model.GetOwnerId()
- if ownerId != nil && len(ownerId.GetProjectDomainId()) > 0 && !cand.Contains(ownerId.GetProjectDomainId()) {
- cand = stringutils2.Append(cand, ownerId.GetProjectDomainId())
- }
- if len(ret) > 0 {
- ret = stringutils2.Intersect(ret, cand)
- } else {
- ret = stringutils2.NewSortedStrings(cand)
- }
- }
- }
- return ret
- }
- func ISharableMergeShareRequireDomainIds(requiredIds ...[]string) []string {
- var ret stringutils2.SSortedStrings
- for i := range requiredIds {
- if len(requiredIds[i]) > 0 {
- req := stringutils2.NewSortedStrings(requiredIds[i])
- if ret == nil {
- ret = req
- } else {
- ret = stringutils2.Merge(ret, req)
- }
- } else {
- return nil
- }
- }
- return ret
- }
- func SharableModelIsSharable(model ISharableBaseModel, reqUsrId mcclient.IIdentityProvider) bool {
- if model.GetIsPublic() && model.GetPublicScope() == rbacscope.ScopeSystem {
- return true
- }
- ownerId := model.GetOwnerId()
- if model.GetIsPublic() && model.GetPublicScope() == rbacscope.ScopeDomain {
- if ownerId != nil && ownerId.GetProjectDomainId() == reqUsrId.GetProjectDomainId() {
- return true
- }
- q := SharedResourceManager.Query().Equals("resource_id", model.GetId())
- q = q.Equals("resource_type", model.Keyword())
- q = q.Equals("target_project_id", reqUsrId.GetProjectDomainId())
- q = q.Equals("target_type", SharedTargetDomain)
- cnt, _ := q.CountWithError()
- if cnt > 0 {
- return true
- }
- }
- if model.GetPublicScope() == rbacscope.ScopeProject {
- if ownerId != nil && ownerId.GetProjectId() == reqUsrId.GetProjectId() {
- return true
- }
- q := SharedResourceManager.Query().Equals("resource_id", model.GetId())
- q = q.Equals("resource_type", model.Keyword())
- q = q.Equals("target_project_id", reqUsrId.GetProjectId())
- q = q.Equals("target_type", SharedTargetProject)
- cnt, _ := q.CountWithError()
- if cnt > 0 {
- return true
- }
- }
- return false
- }
- func (m *SSharableBaseResource) SetShare(scope rbacscope.TRbacScope) {
- pub := false
- if scope != rbacscope.ScopeNone {
- pub = true
- }
- m.IsPublic = pub
- m.PublicScope = string(scope)
- m.PublicSrc = string(apis.OWNER_SOURCE_LOCAL)
- }
- func (m SSharableBaseResource) GetIsPublic() bool {
- return m.IsPublic
- }
- func (m SSharableBaseResource) GetPublicScope() rbacscope.TRbacScope {
- return rbacscope.String2Scope(m.PublicScope)
- }
- func SharablePerformPublic(model ISharableBaseModel, ctx context.Context, userCred mcclient.TokenCredential, input apis.PerformPublicProjectInput) error {
- var err error
- resourceScope := model.GetModelManager().ResourceScope()
- targetScope := rbacscope.String2ScopeDefault(input.Scope, rbacscope.ScopeSystem)
- if resourceScope.HigherThan(targetScope) {
- return errors.Wrapf(httperrors.ErrNotSupported, "cannot share %s resource to %s", resourceScope, targetScope)
- }
- if len(input.SharedProjectIds) > 0 && len(input.SharedDomainIds) > 0 {
- return errors.Wrap(httperrors.ErrInputParameter, "cannot set shared_projects and shared_domains at the same time")
- } else if len(input.SharedProjectIds) > 0 && targetScope != rbacscope.ScopeProject {
- targetScope = rbacscope.ScopeProject
- } else if len(input.SharedDomainIds) > 0 && targetScope != rbacscope.ScopeDomain {
- targetScope = rbacscope.ScopeDomain
- }
- shareResult := apis.PerformPublicProjectInput{}
- shareResult.Scope = string(targetScope)
- candidateIds := model.GetSharableTargetDomainIds()
- requireIds := model.GetRequiredSharedDomainIds()
- switch targetScope {
- case rbacscope.ScopeProject:
- if len(requireIds) == 0 {
- return errors.Wrap(httperrors.ErrForbidden, "require to be shared to system")
- } else if len(requireIds) > 1 {
- return errors.Wrap(httperrors.ErrForbidden, "require to be shared to other domain")
- }
- // if len(input.SharedProjects) == 0 {
- // return errors.Wrap(httperrors.ErrEmptyRequest, "empty shared target project list")
- // }
- shareResult.SharedProjectIds, err = SharedResourceManager.shareToTarget(ctx, userCred, model, SharedTargetProject, input.SharedProjectIds, nil, nil)
- if err != nil {
- return errors.Wrap(err, "shareToTarget")
- }
- if len(shareResult.SharedProjectIds) == 0 {
- targetScope = rbacscope.ScopeNone
- }
- case rbacscope.ScopeDomain:
- if !consts.GetNonDefaultDomainProjects() {
- return errors.Wrap(httperrors.ErrForbidden, "not allow to share to domain when non_default_domain_projects turned off")
- }
- if len(requireIds) == 0 {
- return errors.Wrap(httperrors.ErrForbidden, "require to be shared to system")
- }
- _, err = SharedResourceManager.shareToTarget(ctx, userCred, model, SharedTargetProject, nil, nil, nil)
- if err != nil {
- return errors.Wrap(err, "shareToTarget clean projects")
- }
- shareResult.SharedDomainIds, err = SharedResourceManager.shareToTarget(ctx, userCred, model, SharedTargetDomain, input.SharedDomainIds, candidateIds, requireIds)
- if err != nil {
- return errors.Wrap(err, "shareToTarget add domains")
- }
- if len(shareResult.SharedDomainIds) == 0 && resourceScope == rbacscope.ScopeDomain {
- targetScope = rbacscope.ScopeNone
- }
- case rbacscope.ScopeSystem:
- if len(candidateIds) > 0 {
- return httperrors.NewForbiddenError("sharing is limited to domains %s", jsonutils.Marshal(candidateIds))
- }
- _, err = SharedResourceManager.shareToTarget(ctx, userCred, model, SharedTargetProject, nil, nil, nil)
- if err != nil {
- return errors.Wrap(err, "shareToTarget clean projects")
- }
- _, err = SharedResourceManager.shareToTarget(ctx, userCred, model, SharedTargetDomain, nil, nil, nil)
- if err != nil {
- return errors.Wrap(err, "shareToTarget clean domainss")
- }
- }
- allowScope, policyTags := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), model.KeywordPlural(), policy.PolicyActionPerform, "public")
- if targetScope.HigherThan(allowScope) {
- return errors.Wrapf(httperrors.ErrNotSufficientPrivilege, "require %s allow %s", targetScope, allowScope)
- }
- requireScope := model.GetPublicScope()
- if requireScope.HigherThan(allowScope) {
- return errors.Wrapf(httperrors.ErrNotSufficientPrivilege, "require %s allow %s", requireScope, allowScope)
- }
- err = objectConfirmPolicyTags(ctx, model, policyTags)
- if err != nil {
- return errors.Wrap(err, "objectConfirmPolicyTags")
- }
- _, err = Update(model, func() error {
- model.SetShare(targetScope)
- return nil
- })
- if err != nil {
- return errors.Wrap(err, "Update")
- }
- if targetScope != rbacscope.ScopeNone {
- OpsLog.LogEvent(model, ACT_PUBLIC, shareResult, userCred)
- logclient.AddActionLogWithContext(ctx, model, logclient.ACT_PUBLIC, shareResult, userCred, true)
- }
- model.GetIStandaloneModel().ClearSchedDescCache()
- return nil
- }
- func SharablePerformPrivate(model ISharableBaseModel, ctx context.Context, userCred mcclient.TokenCredential) error {
- if !model.GetIsPublic() && model.GetPublicScope() == rbacscope.ScopeNone {
- return nil
- }
- resourceScope := model.GetModelManager().ResourceScope()
- if resourceScope == rbacscope.ScopeDomain && !consts.GetNonDefaultDomainProjects() {
- return errors.Wrap(httperrors.ErrForbidden, "not allow to private domain resource")
- }
- requireIds := model.GetRequiredSharedDomainIds()
- if len(requireIds) == 0 {
- return errors.Wrap(httperrors.ErrForbidden, "require to be shared to system")
- } else if len(requireIds) > 1 {
- return errors.Wrap(httperrors.ErrForbidden, "require to be shared to other domain")
- }
- requireScope := model.GetPublicScope()
- allowScope, policyTags := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), model.GetModelManager().KeywordPlural(), policy.PolicyActionPerform, "private")
- if requireScope.HigherThan(allowScope) {
- return errors.Wrapf(httperrors.ErrNotSufficientPrivilege, "require %s allow %s", requireScope, allowScope)
- }
- err := objectConfirmPolicyTags(ctx, model, policyTags)
- if err != nil {
- return errors.Wrap(err, "objectConfirmPolicyTags")
- }
- err = SharedResourceManager.CleanModelShares(ctx, userCred, model)
- if err != nil {
- return errors.Wrap(err, "CleanModelShares")
- }
- diff, err := Update(model, func() error {
- model.SetShare(rbacscope.ScopeNone)
- return nil
- })
- if err != nil {
- return errors.Wrap(err, "Update")
- }
- OpsLog.LogEvent(model, ACT_PRIVATE, diff, userCred)
- logclient.AddActionLogWithContext(ctx, model, logclient.ACT_PRIVATE, diff, userCred, true)
- model.GetIStandaloneModel().ClearSchedDescCache()
- return nil
- }
- func SharableGetSharedProjects(model ISharableBaseModel, targetType string) []string {
- sharedResources := make([]SSharedResource, 0)
- q := SharedResourceManager.Query()
- q = q.Equals("resource_type", model.Keyword())
- q = q.Equals("resource_id", model.GetId())
- q = q.Equals("target_type", targetType)
- err := q.All(&sharedResources)
- if err != nil {
- return nil
- }
- res := make([]string, len(sharedResources))
- for i := range sharedResources {
- res[i] = sharedResources[i].TargetProjectId
- }
- return res
- }
- func SharableModelIsShared(model ISharableBaseModel) bool {
- q := SharedResourceManager.Query()
- q = q.Equals("resource_type", model.Keyword())
- q = q.Equals("resource_id", model.GetId())
- cnt, _ := q.CountWithError()
- if cnt > 0 {
- return true
- }
- switch model.GetPublicScope() {
- case rbacscope.ScopeSystem:
- if model.GetIsPublic() {
- return true
- }
- case rbacscope.ScopeDomain:
- if model.GetModelManager().ResourceScope() == rbacscope.ScopeProject {
- return true
- }
- }
- return false
- }
- func SharableModelCustomizeCreate(model ISharableBaseModel, ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
- if !data.Contains("public_scope") {
- resScope := model.GetModelManager().ResourceScope()
- if resScope == rbacscope.ScopeDomain && consts.GetNonDefaultDomainProjects() {
- // only if non_default_domain_projects turned on, do the following
- isManaged := false
- if managedModel, ok := model.(IManagedResourceBase); ok {
- isManaged = managedModel.IsManaged()
- }
- // log.Debugf("isManaged: %v IsAdminAllowPerform %v ownerId.GetProjectDomainId %s userCred.GetProjectDomainId %s", isManaged, IsAdminAllowPerform(ctx, userCred, model, "public"), ownerId.GetProjectDomainId(), userCred.GetProjectDomainId())
- if !isManaged && IsAdminAllowPerform(ctx, userCred, model, "public") && ownerId.GetProjectDomainId() == userCred.GetProjectDomainId() {
- model.SetShare(rbacscope.ScopeSystem)
- data.(*jsonutils.JSONDict).Set("public_scope", jsonutils.NewString(string(rbacscope.ScopeSystem)))
- }
- }
- }
- if !data.Contains("public_scope") {
- model.SetShare(rbacscope.ScopeNone)
- }
- return nil
- }
|